Merge from Chromium at DEPS revision r198571

This commit was generated by merge_to_master.py.

Change-Id: I3a7f89ea6b8c017335bd52739166aed708cad1e5
diff --git a/Source/core/rendering/AutoTableLayout.cpp b/Source/core/rendering/AutoTableLayout.cpp
new file mode 100644
index 0000000..52172d2
--- /dev/null
+++ b/Source/core/rendering/AutoTableLayout.cpp
@@ -0,0 +1,765 @@
+/*
+ * Copyright (C) 2002 Lars Knoll (knoll@kde.org)
+ *           (C) 2002 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2006, 2008, 2010 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 "core/rendering/AutoTableLayout.h"
+
+#include "core/rendering/RenderTable.h"
+#include "core/rendering/RenderTableCell.h"
+#include "core/rendering/RenderTableCol.h"
+#include "core/rendering/RenderTableSection.h"
+
+using namespace std;
+
+namespace WebCore {
+
+AutoTableLayout::AutoTableLayout(RenderTable* table)
+    : TableLayout(table)
+    , m_hasPercent(false)
+    , m_effectiveLogicalWidthDirty(true)
+{
+}
+
+AutoTableLayout::~AutoTableLayout()
+{
+}
+
+void AutoTableLayout::recalcColumn(unsigned effCol)
+{
+    Layout& columnLayout = m_layoutStruct[effCol];
+
+    RenderTableCell* fixedContributor = 0;
+    RenderTableCell* maxContributor = 0;
+
+    for (RenderObject* child = m_table->children()->firstChild(); child; child = child->nextSibling()) {
+        if (child->isRenderTableCol()){
+            // RenderTableCols don't have the concept of preferred logical width, but we need to clear their dirty bits
+            // so that if we call setPreferredWidthsDirty(true) on a col or one of its descendants, we'll mark it's
+            // ancestors as dirty.
+            toRenderTableCol(child)->clearPreferredLogicalWidthsDirtyBits();
+        } else if (child->isTableSection()) {
+            RenderTableSection* section = toRenderTableSection(child);
+            unsigned numRows = section->numRows();
+            for (unsigned i = 0; i < numRows; i++) {
+                RenderTableSection::CellStruct current = section->cellAt(i, effCol);
+                RenderTableCell* cell = current.primaryCell();
+                
+                if (current.inColSpan || !cell)
+                    continue;
+
+                bool cellHasContent = cell->children()->firstChild() || cell->style()->hasBorder() || cell->style()->hasPadding();
+                if (cellHasContent)
+                    columnLayout.emptyCellsOnly = false;
+
+                // A cell originates in this column. Ensure we have
+                // a min/max width of at least 1px for this column now.
+                columnLayout.minLogicalWidth = max<int>(columnLayout.minLogicalWidth, cellHasContent ? 1 : 0);
+                columnLayout.maxLogicalWidth = max<int>(columnLayout.maxLogicalWidth, 1);
+
+                if (cell->colSpan() == 1) {
+                    columnLayout.minLogicalWidth = max<int>(cell->minPreferredLogicalWidth(), columnLayout.minLogicalWidth);
+                    if (cell->maxPreferredLogicalWidth() > columnLayout.maxLogicalWidth) {
+                        columnLayout.maxLogicalWidth = cell->maxPreferredLogicalWidth();
+                        maxContributor = cell;
+                    }
+
+                    // All browsers implement a size limit on the cell's max width. 
+                    // Our limit is based on KHTML's representation that used 16 bits widths.
+                    // FIXME: Other browsers have a lower limit for the cell's max width. 
+                    const int cCellMaxWidth = 32760;
+                    Length cellLogicalWidth = cell->styleOrColLogicalWidth();
+                    if (cellLogicalWidth.value() > cCellMaxWidth)
+                        cellLogicalWidth.setValue(cCellMaxWidth);
+                    if (cellLogicalWidth.isNegative())
+                        cellLogicalWidth.setValue(0);
+                    switch (cellLogicalWidth.type()) {
+                    case Fixed:
+                        // ignore width=0
+                        if (cellLogicalWidth.isPositive() && !columnLayout.logicalWidth.isPercent()) {
+                            int logicalWidth = cell->adjustBorderBoxLogicalWidthForBoxSizing(cellLogicalWidth.value());
+                            if (columnLayout.logicalWidth.isFixed()) {
+                                // Nav/IE weirdness
+                                if ((logicalWidth > columnLayout.logicalWidth.value()) 
+                                    || ((columnLayout.logicalWidth.value() == logicalWidth) && (maxContributor == cell))) {
+                                    columnLayout.logicalWidth.setValue(Fixed, logicalWidth);
+                                    fixedContributor = cell;
+                                }
+                            } else {
+                                columnLayout.logicalWidth.setValue(Fixed, logicalWidth);
+                                fixedContributor = cell;
+                            }
+                        }
+                        break;
+                    case Percent:
+                        m_hasPercent = true;
+                        if (cellLogicalWidth.isPositive() && (!columnLayout.logicalWidth.isPercent() || cellLogicalWidth.value() > columnLayout.logicalWidth.value()))
+                            columnLayout.logicalWidth = cellLogicalWidth;
+                        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 (cellLogicalWidth.value() > columnLayout.logicalWidth.value())
+                            columnLayout.logicalWidth = cellLogicalWidth;
+                    default:
+                        break;
+                    }
+                } else if (!effCol || section->primaryCellAt(i, effCol - 1) != cell) {
+                    // This spanning cell originates in this column. Insert the cell into spanning cells list.
+                    insertSpanCell(cell);
+                }
+            }
+        }
+    }
+
+    // Nav/IE weirdness
+    if (columnLayout.logicalWidth.isFixed()) {
+        if (m_table->document()->inQuirksMode() && columnLayout.maxLogicalWidth > columnLayout.logicalWidth.value() && fixedContributor != maxContributor) {
+            columnLayout.logicalWidth = Length();
+            fixedContributor = 0;
+        }
+    }
+
+    columnLayout.maxLogicalWidth = max(columnLayout.maxLogicalWidth, columnLayout.minLogicalWidth);
+}
+
+void AutoTableLayout::fullRecalc()
+{
+    m_hasPercent = false;
+    m_effectiveLogicalWidthDirty = true;
+
+    unsigned nEffCols = m_table->numEffCols();
+    m_layoutStruct.resize(nEffCols);
+    m_layoutStruct.fill(Layout());
+    m_spanCells.fill(0);
+
+    Length groupLogicalWidth;
+    unsigned currentColumn = 0;
+    for (RenderTableCol* column = m_table->firstColumn(); column; column = column->nextColumn()) {
+        if (column->isTableColumnGroupWithColumnChildren())
+            groupLogicalWidth = column->style()->logicalWidth();
+        else {
+            Length colLogicalWidth = column->style()->logicalWidth();
+            if (colLogicalWidth.isAuto())
+                colLogicalWidth = groupLogicalWidth;
+            if ((colLogicalWidth.isFixed() || colLogicalWidth.isPercent()) && colLogicalWidth.isZero())
+                colLogicalWidth = Length();
+            unsigned effCol = m_table->colToEffCol(currentColumn);
+            unsigned span = column->span();
+            if (!colLogicalWidth.isAuto() && span == 1 && effCol < nEffCols && m_table->spanOfEffCol(effCol) == 1) {
+                m_layoutStruct[effCol].logicalWidth = colLogicalWidth;
+                if (colLogicalWidth.isFixed() && m_layoutStruct[effCol].maxLogicalWidth < colLogicalWidth.value())
+                    m_layoutStruct[effCol].maxLogicalWidth = colLogicalWidth.value();
+            }
+            currentColumn += span;
+        }
+
+        // For the last column in a column-group, we invalidate our group logical width.
+        if (column->isTableColumn() && !column->nextSibling())
+            groupLogicalWidth = Length();
+    }
+
+    for (unsigned i = 0; i < nEffCols; i++)
+        recalcColumn(i);
+}
+
+// FIXME: This needs to be adapted for vertical writing modes.
+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->isOutOfFlowPositioned()) {
+            RenderBlock* cb = table->containingBlock();
+            while (cb && !cb->isRenderView() && !cb->isTableCell() &&
+                cb->style()->width().isAuto() && !cb->isOutOfFlowPositioned())
+                cb = cb->containingBlock();
+
+            table = 0;
+            if (cb && cb->isTableCell() &&
+                (cb->style()->width().isAuto() || cb->style()->width().isPercent())) {
+                RenderTableCell* cell = toRenderTableCell(cb);
+                if (cell->colSpan() > 1 || cell->table()->style()->width().isAuto())
+                    scale = false;
+                else
+                    table = cell->table();
+            }
+        }
+        else
+            table = 0;
+    }
+    return scale;
+}
+
+void AutoTableLayout::computeIntrinsicLogicalWidths(LayoutUnit& minWidth, LayoutUnit& maxWidth)
+{
+    fullRecalc();
+
+    int spanMaxLogicalWidth = calcEffectiveLogicalWidth();
+    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 float epsilon = 1 / 128.0f;
+
+    float remainingPercent = 100;
+    for (size_t i = 0; i < m_layoutStruct.size(); ++i) {
+        minWidth += m_layoutStruct[i].effectiveMinLogicalWidth;
+        maxWidth += m_layoutStruct[i].effectiveMaxLogicalWidth;
+        if (scaleColumns) {
+            if (m_layoutStruct[i].effectiveLogicalWidth.isPercent()) {
+                float percent = min(static_cast<float>(m_layoutStruct[i].effectiveLogicalWidth.percent()), remainingPercent);
+                float logicalWidth = static_cast<float>(m_layoutStruct[i].effectiveMaxLogicalWidth) * 100 / max(percent, epsilon);
+                maxPercent = max(logicalWidth,  maxPercent);
+                remainingPercent -= percent;
+            } else
+                maxNonPercent += m_layoutStruct[i].effectiveMaxLogicalWidth;
+        }
+    }
+
+    if (scaleColumns) {
+        maxNonPercent = maxNonPercent * 100 / max(remainingPercent, epsilon);
+        maxWidth = max<int>(maxWidth, static_cast<int>(min(maxNonPercent, static_cast<float>(tableMaxWidth))));
+        maxWidth = max<int>(maxWidth, static_cast<int>(min(maxPercent, static_cast<float>(tableMaxWidth))));
+    }
+
+    maxWidth = max<int>(maxWidth, spanMaxLogicalWidth);
+}
+
+void AutoTableLayout::applyPreferredLogicalWidthQuirks(LayoutUnit& minWidth, LayoutUnit& maxWidth) const
+{
+    Length tableLogicalWidth = m_table->style()->logicalWidth();
+    if (tableLogicalWidth.isFixed() && tableLogicalWidth.isPositive())
+        minWidth = maxWidth = max<int>(minWidth, tableLogicalWidth.value());
+}
+
+/*
+  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::calcEffectiveLogicalWidth()
+{
+    int maxLogicalWidth = 0;
+
+    size_t nEffCols = m_layoutStruct.size();
+    int spacingInRowDirection = m_table->hBorderSpacing();
+
+    for (size_t i = 0; i < nEffCols; ++i) {
+        m_layoutStruct[i].effectiveLogicalWidth = m_layoutStruct[i].logicalWidth;
+        m_layoutStruct[i].effectiveMinLogicalWidth = m_layoutStruct[i].minLogicalWidth;
+        m_layoutStruct[i].effectiveMaxLogicalWidth = m_layoutStruct[i].maxLogicalWidth;
+    }
+
+    for (size_t i = 0; i < m_spanCells.size(); ++i) {
+        RenderTableCell* cell = m_spanCells[i];
+        if (!cell)
+            break;
+
+        unsigned span = cell->colSpan();
+
+        Length cellLogicalWidth = cell->styleOrColLogicalWidth();
+        if (!cellLogicalWidth.isRelative() && cellLogicalWidth.isZero())
+            cellLogicalWidth = Length(); // make it Auto
+
+        unsigned effCol = m_table->colToEffCol(cell->col());
+        size_t lastCol = effCol;
+        int cellMinLogicalWidth = cell->minPreferredLogicalWidth() + spacingInRowDirection;
+        int cellMaxLogicalWidth = cell->maxPreferredLogicalWidth() + spacingInRowDirection;
+        float totalPercent = 0;
+        int spanMinLogicalWidth = 0;
+        int spanMaxLogicalWidth = 0;
+        bool allColsArePercent = true;
+        bool allColsAreFixed = true;
+        bool haveAuto = false;
+        bool spanHasEmptyCellsOnly = true;
+        int fixedWidth = 0;
+        while (lastCol < nEffCols && span > 0) {
+            Layout& columnLayout = m_layoutStruct[lastCol];
+            switch (columnLayout.logicalWidth.type()) {
+            case Percent:
+                totalPercent += columnLayout.logicalWidth.percent();
+                allColsAreFixed = false;
+                break;
+            case Fixed:
+                if (columnLayout.logicalWidth.value() > 0) {
+                    fixedWidth += columnLayout.logicalWidth.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 (!columnLayout.effectiveLogicalWidth.isPercent()) {
+                    columnLayout.effectiveLogicalWidth = Length();
+                    allColsArePercent = false;
+                } else
+                    totalPercent += columnLayout.effectiveLogicalWidth.percent();
+                allColsAreFixed = false;
+            }
+            if (!columnLayout.emptyCellsOnly)
+                spanHasEmptyCellsOnly = false;
+            span -= m_table->spanOfEffCol(lastCol);
+            spanMinLogicalWidth += columnLayout.effectiveMinLogicalWidth;
+            spanMaxLogicalWidth += columnLayout.effectiveMaxLogicalWidth;
+            lastCol++;
+            cellMinLogicalWidth -= spacingInRowDirection;
+            cellMaxLogicalWidth -= spacingInRowDirection;
+        }
+
+        // adjust table max width if needed
+        if (cellLogicalWidth.isPercent()) {
+            if (totalPercent > cellLogicalWidth.percent() || allColsArePercent) {
+                // can't satify this condition, treat as variable
+                cellLogicalWidth = Length();
+            } else {
+                maxLogicalWidth = max(maxLogicalWidth, static_cast<int>(max(spanMaxLogicalWidth, cellMaxLogicalWidth) * 100  / cellLogicalWidth.percent()));
+
+                // all non percent columns in the span get percent values to sum up correctly.
+                float percentMissing = cellLogicalWidth.percent() - totalPercent;
+                int totalWidth = 0;
+                for (unsigned pos = effCol; pos < lastCol; ++pos) {
+                    if (!m_layoutStruct[pos].effectiveLogicalWidth.isPercent())
+                        totalWidth += m_layoutStruct[pos].effectiveMaxLogicalWidth;
+                }
+
+                for (unsigned pos = effCol; pos < lastCol && totalWidth > 0; ++pos) {
+                    if (!m_layoutStruct[pos].effectiveLogicalWidth.isPercent()) {
+                        float percent = percentMissing * static_cast<float>(m_layoutStruct[pos].effectiveMaxLogicalWidth) / totalWidth;
+                        totalWidth -= m_layoutStruct[pos].effectiveMaxLogicalWidth;
+                        percentMissing -= percent;
+                        if (percent > 0)
+                            m_layoutStruct[pos].effectiveLogicalWidth.setValue(Percent, percent);
+                        else
+                            m_layoutStruct[pos].effectiveLogicalWidth = Length();
+                    }
+                }
+            }
+        }
+
+        // make sure minWidth and maxWidth of the spanning cell are honoured
+        if (cellMinLogicalWidth > spanMinLogicalWidth) {
+            if (allColsAreFixed) {
+                for (unsigned pos = effCol; fixedWidth > 0 && pos < lastCol; ++pos) {
+                    int cellLogicalWidth = max(m_layoutStruct[pos].effectiveMinLogicalWidth, static_cast<int>(cellMinLogicalWidth * m_layoutStruct[pos].logicalWidth.value() / fixedWidth));
+                    fixedWidth -= m_layoutStruct[pos].logicalWidth.value();
+                    cellMinLogicalWidth -= cellLogicalWidth;
+                    m_layoutStruct[pos].effectiveMinLogicalWidth = cellLogicalWidth;
+                }
+            } else if (allColsArePercent) {
+                // In this case, we just split the colspan's min amd max widths following the percentage.
+                int allocatedMinLogicalWidth = 0;
+                int allocatedMaxLogicalWidth = 0;
+                for (unsigned pos = effCol; pos < lastCol; ++pos) {
+                    ASSERT(m_layoutStruct[pos].logicalWidth.isPercent() || m_layoutStruct[pos].effectiveLogicalWidth.isPercent());
+                    // |allColsArePercent| means that either the logicalWidth *or* the effectiveLogicalWidth are percents, handle both of them here.
+                    float percent = m_layoutStruct[pos].logicalWidth.isPercent() ? m_layoutStruct[pos].logicalWidth.percent() : m_layoutStruct[pos].effectiveLogicalWidth.percent();
+                    int columnMinLogicalWidth = static_cast<int>(percent * cellMinLogicalWidth / totalPercent);
+                    int columnMaxLogicalWidth = static_cast<int>(percent * cellMaxLogicalWidth / totalPercent);
+                    m_layoutStruct[pos].effectiveMinLogicalWidth = max(m_layoutStruct[pos].effectiveMinLogicalWidth, columnMinLogicalWidth);
+                    m_layoutStruct[pos].effectiveMaxLogicalWidth = columnMaxLogicalWidth;
+                    allocatedMinLogicalWidth += columnMinLogicalWidth;
+                    allocatedMaxLogicalWidth += columnMaxLogicalWidth;
+                }
+                ASSERT(allocatedMinLogicalWidth <= cellMinLogicalWidth);
+                ASSERT(allocatedMaxLogicalWidth <= cellMaxLogicalWidth);
+                cellMinLogicalWidth -= allocatedMinLogicalWidth;
+                cellMaxLogicalWidth -= allocatedMaxLogicalWidth;
+            } else {
+                int remainingMaxLogicalWidth = spanMaxLogicalWidth;
+                int remainingMinLogicalWidth = spanMinLogicalWidth;
+                
+                // Give min to variable first, to fixed second, and to others third.
+                for (unsigned pos = effCol; remainingMaxLogicalWidth >= 0 && pos < lastCol; ++pos) {
+                    if (m_layoutStruct[pos].logicalWidth.isFixed() && haveAuto && fixedWidth <= cellMinLogicalWidth) {
+                        int colMinLogicalWidth = max<int>(m_layoutStruct[pos].effectiveMinLogicalWidth, m_layoutStruct[pos].logicalWidth.value());
+                        fixedWidth -= m_layoutStruct[pos].logicalWidth.value();
+                        remainingMinLogicalWidth -= m_layoutStruct[pos].effectiveMinLogicalWidth;
+                        remainingMaxLogicalWidth -= m_layoutStruct[pos].effectiveMaxLogicalWidth;
+                        cellMinLogicalWidth -= colMinLogicalWidth;
+                        m_layoutStruct[pos].effectiveMinLogicalWidth = colMinLogicalWidth;
+                    }
+                }
+
+                for (unsigned pos = effCol; remainingMaxLogicalWidth >= 0 && pos < lastCol && remainingMinLogicalWidth < cellMinLogicalWidth; ++pos) {
+                    if (!(m_layoutStruct[pos].logicalWidth.isFixed() && haveAuto && fixedWidth <= cellMinLogicalWidth)) {
+                        int colMinLogicalWidth = max<int>(m_layoutStruct[pos].effectiveMinLogicalWidth, static_cast<int>(remainingMaxLogicalWidth ? cellMinLogicalWidth * static_cast<float>(m_layoutStruct[pos].effectiveMaxLogicalWidth) / remainingMaxLogicalWidth : cellMinLogicalWidth));
+                        colMinLogicalWidth = min<int>(m_layoutStruct[pos].effectiveMinLogicalWidth + (cellMinLogicalWidth - remainingMinLogicalWidth), colMinLogicalWidth);
+                        remainingMaxLogicalWidth -= m_layoutStruct[pos].effectiveMaxLogicalWidth;
+                        remainingMinLogicalWidth -= m_layoutStruct[pos].effectiveMinLogicalWidth;
+                        cellMinLogicalWidth -= colMinLogicalWidth;
+                        m_layoutStruct[pos].effectiveMinLogicalWidth = colMinLogicalWidth;
+                    }
+                }
+            }
+        }
+        if (!cellLogicalWidth.isPercent()) {
+            if (cellMaxLogicalWidth > spanMaxLogicalWidth) {
+                for (unsigned pos = effCol; spanMaxLogicalWidth >= 0 && pos < lastCol; ++pos) {
+                    int colMaxLogicalWidth = max(m_layoutStruct[pos].effectiveMaxLogicalWidth, static_cast<int>(spanMaxLogicalWidth ? cellMaxLogicalWidth * static_cast<float>(m_layoutStruct[pos].effectiveMaxLogicalWidth) / spanMaxLogicalWidth : cellMaxLogicalWidth));
+                    spanMaxLogicalWidth -= m_layoutStruct[pos].effectiveMaxLogicalWidth;
+                    cellMaxLogicalWidth -= colMaxLogicalWidth;
+                    m_layoutStruct[pos].effectiveMaxLogicalWidth = colMaxLogicalWidth;
+                }
+            }
+        } else {
+            for (unsigned pos = effCol; pos < lastCol; ++pos)
+                m_layoutStruct[pos].maxLogicalWidth = max(m_layoutStruct[pos].maxLogicalWidth, m_layoutStruct[pos].minLogicalWidth);
+        }
+        // treat span ranges consisting of empty cells only as if they had content
+        if (spanHasEmptyCellsOnly) {
+            for (unsigned pos = effCol; pos < lastCol; ++pos)
+                m_layoutStruct[pos].emptyCellsOnly = false;
+        }
+    }
+    m_effectiveLogicalWidthDirty = false;
+
+    return min(maxLogicalWidth, INT_MAX / 2);
+}
+
+/* gets all cells that originate in a column and have a cellspan > 1
+   Sorts them by increasing cellspan
+*/
+void AutoTableLayout::insertSpanCell(RenderTableCell *cell)
+{
+    ASSERT_ARG(cell, cell && cell->colSpan() != 1);
+    if (!cell || cell->colSpan() == 1)
+        return;
+
+    unsigned size = m_spanCells.size();
+    if (!size || m_spanCells[size-1] != 0) {
+        m_spanCells.grow(size + 10);
+        for (unsigned 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 pos = 0;
+    unsigned span = cell->colSpan();
+    while (pos < m_spanCells.size() && m_spanCells[pos] && span > m_spanCells[pos]->colSpan())
+        pos++;
+    memmove(m_spanCells.data()+pos+1, m_spanCells.data()+pos, (size-pos-1)*sizeof(RenderTableCell *));
+    m_spanCells[pos] = cell;
+}
+
+
+void AutoTableLayout::layout()
+{
+    // table layout based on the values collected in the layout structure.
+    int tableLogicalWidth = m_table->logicalWidth() - m_table->bordersPaddingAndSpacingInRowDirection();
+    int available = tableLogicalWidth;
+    size_t nEffCols = m_table->numEffCols();
+
+    // FIXME: It is possible to be called without having properly updated our internal representation.
+    // This means that our preferred logical widths were not recomputed as expected.
+    if (nEffCols != m_layoutStruct.size()) {
+        fullRecalc();
+        // FIXME: Table layout shouldn't modify our table structure (but does due to columns and column-groups).
+        nEffCols = m_table->numEffCols();
+    }
+
+    if (m_effectiveLogicalWidthDirty)
+        calcEffectiveLogicalWidth();
+
+    bool havePercent = false;
+    int totalRelative = 0;
+    int numAuto = 0;
+    int numFixed = 0;
+    float totalAuto = 0;
+    float totalFixed = 0;
+    float totalPercent = 0;
+    int allocAuto = 0;
+    unsigned numAutoEmptyCellsOnly = 0;
+
+    // fill up every cell with its minWidth
+    for (size_t i = 0; i < nEffCols; ++i) {
+        int cellLogicalWidth = m_layoutStruct[i].effectiveMinLogicalWidth;
+        m_layoutStruct[i].computedLogicalWidth = cellLogicalWidth;
+        available -= cellLogicalWidth;
+        Length& logicalWidth = m_layoutStruct[i].effectiveLogicalWidth;
+        switch (logicalWidth.type()) {
+        case Percent:
+            havePercent = true;
+            totalPercent += logicalWidth.percent();
+            break;
+        case Relative:
+            totalRelative += logicalWidth.value();
+            break;
+        case Fixed:
+            numFixed++;
+            totalFixed += m_layoutStruct[i].effectiveMaxLogicalWidth;
+            // fall through
+            break;
+        case Auto:
+            if (m_layoutStruct[i].emptyCellsOnly)
+                numAutoEmptyCellsOnly++;
+            else {
+                numAuto++;
+                totalAuto += m_layoutStruct[i].effectiveMaxLogicalWidth;
+                allocAuto += cellLogicalWidth;
+            }
+            break;
+        default:
+            break;
+        }
+    }
+
+    // allocate width to percent cols
+    if (available > 0 && havePercent) {
+        for (size_t i = 0; i < nEffCols; ++i) {
+            Length& logicalWidth = m_layoutStruct[i].effectiveLogicalWidth;
+            if (logicalWidth.isPercent()) {
+                int cellLogicalWidth = max<int>(m_layoutStruct[i].effectiveMinLogicalWidth, minimumValueForLength(logicalWidth, tableLogicalWidth));
+                available += m_layoutStruct[i].computedLogicalWidth - cellLogicalWidth;
+                m_layoutStruct[i].computedLogicalWidth = cellLogicalWidth;
+            }
+        }
+        if (totalPercent > 100) {
+            // remove overallocated space from the last columns
+            int excess = tableLogicalWidth * (totalPercent - 100) / 100;
+            for (unsigned i = nEffCols; i; ) {
+                --i;
+                if (m_layoutStruct[i].effectiveLogicalWidth.isPercent()) {
+                    int cellLogicalWidth = m_layoutStruct[i].computedLogicalWidth;
+                    int reduction = min(cellLogicalWidth,  excess);
+                    // the lines below might look inconsistent, but that's the way it's handled in mozilla
+                    excess -= reduction;
+                    int newLogicalWidth = max<int>(m_layoutStruct[i].effectiveMinLogicalWidth, cellLogicalWidth - reduction);
+                    available += cellLogicalWidth - newLogicalWidth;
+                    m_layoutStruct[i].computedLogicalWidth = newLogicalWidth;
+                }
+            }
+        }
+    }
+    
+    // then allocate width to fixed cols
+    if (available > 0) {
+        for (size_t i = 0; i < nEffCols; ++i) {
+            Length& logicalWidth = m_layoutStruct[i].effectiveLogicalWidth;
+            if (logicalWidth.isFixed() && logicalWidth.value() > m_layoutStruct[i].computedLogicalWidth) {
+                available += m_layoutStruct[i].computedLogicalWidth - logicalWidth.value();
+                m_layoutStruct[i].computedLogicalWidth = logicalWidth.value();
+            }
+        }
+    }
+
+    // now satisfy relative
+    if (available > 0) {
+        for (size_t i = 0; i < nEffCols; ++i) {
+            Length& logicalWidth = m_layoutStruct[i].effectiveLogicalWidth;
+            if (logicalWidth.isRelative() && logicalWidth.value() != 0) {
+                // width=0* gets effMinWidth.
+                int cellLogicalWidth = logicalWidth.value() * tableLogicalWidth / totalRelative;
+                available += m_layoutStruct[i].computedLogicalWidth - cellLogicalWidth;
+                m_layoutStruct[i].computedLogicalWidth = cellLogicalWidth;
+            }
+        }
+    }
+
+    // now satisfy variable
+    if (available > 0 && numAuto) {
+        available += allocAuto; // this gets redistributed
+        for (size_t i = 0; i < nEffCols; ++i) {
+            Length& logicalWidth = m_layoutStruct[i].effectiveLogicalWidth;
+            if (logicalWidth.isAuto() && totalAuto && !m_layoutStruct[i].emptyCellsOnly) {
+                int cellLogicalWidth = max<int>(m_layoutStruct[i].computedLogicalWidth, static_cast<int>(available * static_cast<float>(m_layoutStruct[i].effectiveMaxLogicalWidth) / totalAuto));
+                available -= cellLogicalWidth;
+                totalAuto -= m_layoutStruct[i].effectiveMaxLogicalWidth;
+                m_layoutStruct[i].computedLogicalWidth = cellLogicalWidth;
+            }
+        }
+    }
+
+    // spread over fixed columns
+    if (available > 0 && numFixed) {
+        for (size_t i = 0; i < nEffCols; ++i) {
+            Length& logicalWidth = m_layoutStruct[i].effectiveLogicalWidth;
+            if (logicalWidth.isFixed()) {
+                int cellLogicalWidth = static_cast<int>(available * static_cast<float>(m_layoutStruct[i].effectiveMaxLogicalWidth) / totalFixed);
+                available -= cellLogicalWidth;
+                totalFixed -= m_layoutStruct[i].effectiveMaxLogicalWidth;
+                m_layoutStruct[i].computedLogicalWidth += cellLogicalWidth;
+            }
+        }
+    }
+
+    // spread over percent colums
+    if (available > 0 && m_hasPercent && totalPercent < 100) {
+        for (size_t i = 0; i < nEffCols; ++i) {
+            Length& logicalWidth = m_layoutStruct[i].effectiveLogicalWidth;
+            if (logicalWidth.isPercent()) {
+                int cellLogicalWidth = available * logicalWidth.percent() / totalPercent;
+                available -= cellLogicalWidth;
+                totalPercent -= logicalWidth.percent();
+                m_layoutStruct[i].computedLogicalWidth += cellLogicalWidth;
+                if (!available || !totalPercent)
+                    break;
+            }
+        }
+    }
+
+    // spread over the rest
+    if (available > 0 && nEffCols > numAutoEmptyCellsOnly) {
+        unsigned total = nEffCols - numAutoEmptyCellsOnly;
+        // still have some width to spread
+        for (unsigned i = nEffCols; i; ) {
+            --i;
+            // variable columns with empty cells only don't get any width
+            if (m_layoutStruct[i].effectiveLogicalWidth.isAuto() && m_layoutStruct[i].emptyCellsOnly)
+                continue;
+            int cellLogicalWidth = available / total;
+            available -= cellLogicalWidth;
+            total--;
+            m_layoutStruct[i].computedLogicalWidth += cellLogicalWidth;
+        }
+    }
+
+    // If we have overallocated, reduce every cell according to the difference between desired width and minwidth
+    // this seems to produce to the pixel exact 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 logicalWidthBeyondMin = 0;
+            for (unsigned i = nEffCols; i; ) {
+                --i;
+                Length& logicalWidth = m_layoutStruct[i].effectiveLogicalWidth;
+                if (logicalWidth.isAuto())
+                    logicalWidthBeyondMin += m_layoutStruct[i].computedLogicalWidth - m_layoutStruct[i].effectiveMinLogicalWidth;
+            }
+            
+            for (unsigned i = nEffCols; i && logicalWidthBeyondMin > 0; ) {
+                --i;
+                Length& logicalWidth = m_layoutStruct[i].effectiveLogicalWidth;
+                if (logicalWidth.isAuto()) {
+                    int minMaxDiff = m_layoutStruct[i].computedLogicalWidth - m_layoutStruct[i].effectiveMinLogicalWidth;
+                    int reduce = available * minMaxDiff / logicalWidthBeyondMin;
+                    m_layoutStruct[i].computedLogicalWidth += reduce;
+                    available -= reduce;
+                    logicalWidthBeyondMin -= minMaxDiff;
+                    if (available >= 0)
+                        break;
+                }
+            }
+        }
+
+        if (available < 0) {
+            int logicalWidthBeyondMin = 0;
+            for (unsigned i = nEffCols; i; ) {
+                --i;
+                Length& logicalWidth = m_layoutStruct[i].effectiveLogicalWidth;
+                if (logicalWidth.isRelative())
+                    logicalWidthBeyondMin += m_layoutStruct[i].computedLogicalWidth - m_layoutStruct[i].effectiveMinLogicalWidth;
+            }
+            
+            for (unsigned i = nEffCols; i && logicalWidthBeyondMin > 0; ) {
+                --i;
+                Length& logicalWidth = m_layoutStruct[i].effectiveLogicalWidth;
+                if (logicalWidth.isRelative()) {
+                    int minMaxDiff = m_layoutStruct[i].computedLogicalWidth - m_layoutStruct[i].effectiveMinLogicalWidth;
+                    int reduce = available * minMaxDiff / logicalWidthBeyondMin;
+                    m_layoutStruct[i].computedLogicalWidth += reduce;
+                    available -= reduce;
+                    logicalWidthBeyondMin -= minMaxDiff;
+                    if (available >= 0)
+                        break;
+                }
+            }
+        }
+
+        if (available < 0) {
+            int logicalWidthBeyondMin = 0;
+            for (unsigned i = nEffCols; i; ) {
+                --i;
+                Length& logicalWidth = m_layoutStruct[i].effectiveLogicalWidth;
+                if (logicalWidth.isFixed())
+                    logicalWidthBeyondMin += m_layoutStruct[i].computedLogicalWidth - m_layoutStruct[i].effectiveMinLogicalWidth;
+            }
+            
+            for (unsigned i = nEffCols; i && logicalWidthBeyondMin > 0; ) {
+                --i;
+                Length& logicalWidth = m_layoutStruct[i].effectiveLogicalWidth;
+                if (logicalWidth.isFixed()) {
+                    int minMaxDiff = m_layoutStruct[i].computedLogicalWidth - m_layoutStruct[i].effectiveMinLogicalWidth;
+                    int reduce = available * minMaxDiff / logicalWidthBeyondMin;
+                    m_layoutStruct[i].computedLogicalWidth += reduce;
+                    available -= reduce;
+                    logicalWidthBeyondMin -= minMaxDiff;
+                    if (available >= 0)
+                        break;
+                }
+            }
+        }
+
+        if (available < 0) {
+            int logicalWidthBeyondMin = 0;
+            for (unsigned i = nEffCols; i; ) {
+                --i;
+                Length& logicalWidth = m_layoutStruct[i].effectiveLogicalWidth;
+                if (logicalWidth.isPercent())
+                    logicalWidthBeyondMin += m_layoutStruct[i].computedLogicalWidth - m_layoutStruct[i].effectiveMinLogicalWidth;
+            }
+            
+            for (unsigned i = nEffCols; i && logicalWidthBeyondMin > 0; ) {
+                --i;
+                Length& logicalWidth = m_layoutStruct[i].effectiveLogicalWidth;
+                if (logicalWidth.isPercent()) {
+                    int minMaxDiff = m_layoutStruct[i].computedLogicalWidth - m_layoutStruct[i].effectiveMinLogicalWidth;
+                    int reduce = available * minMaxDiff / logicalWidthBeyondMin;
+                    m_layoutStruct[i].computedLogicalWidth += reduce;
+                    available -= reduce;
+                    logicalWidthBeyondMin -= minMaxDiff;
+                    if (available >= 0)
+                        break;
+                }
+            }
+        }
+    }
+
+    int pos = 0;
+    for (size_t i = 0; i < nEffCols; ++i) {
+        m_table->setColumnPosition(i, pos);
+        pos += m_layoutStruct[i].computedLogicalWidth + m_table->hBorderSpacing();
+    }
+    m_table->setColumnPosition(m_table->columnPositions().size() - 1, pos);
+}
+
+}
diff --git a/Source/core/rendering/AutoTableLayout.h b/Source/core/rendering/AutoTableLayout.h
new file mode 100644
index 0000000..c87efbe
--- /dev/null
+++ b/Source/core/rendering/AutoTableLayout.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2002 Lars Knoll (knoll@kde.org)
+ *           (C) 2002 Dirk Mueller (mueller@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef AutoTableLayout_h
+#define AutoTableLayout_h
+
+#include "core/platform/LayoutUnit.h"
+#include "core/platform/Length.h"
+#include "core/rendering/TableLayout.h"
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class RenderTable;
+class RenderTableCell;
+
+class AutoTableLayout : public TableLayout {
+public:
+    AutoTableLayout(RenderTable*);
+    ~AutoTableLayout();
+
+    virtual void computeIntrinsicLogicalWidths(LayoutUnit& minWidth, LayoutUnit& maxWidth) OVERRIDE;
+    virtual void applyPreferredLogicalWidthQuirks(LayoutUnit& minWidth, LayoutUnit& maxWidth) const OVERRIDE;
+    virtual void layout();
+
+private:
+    void fullRecalc();
+    void recalcColumn(unsigned effCol);
+
+    int calcEffectiveLogicalWidth();
+
+    void insertSpanCell(RenderTableCell*);
+
+    struct Layout {
+        Layout()
+            : minLogicalWidth(0)
+            , maxLogicalWidth(0)
+            , effectiveMinLogicalWidth(0)
+            , effectiveMaxLogicalWidth(0)
+            , computedLogicalWidth(0)
+            , emptyCellsOnly(true)
+        {
+        }
+
+        Length logicalWidth;
+        Length effectiveLogicalWidth;
+        int minLogicalWidth;
+        int maxLogicalWidth;
+        int effectiveMinLogicalWidth;
+        int effectiveMaxLogicalWidth;
+        int computedLogicalWidth;
+        bool emptyCellsOnly;
+    };
+
+    Vector<Layout, 4> m_layoutStruct;
+    Vector<RenderTableCell*, 4> m_spanCells;
+    bool m_hasPercent : 1;
+    mutable bool m_effectiveLogicalWidthDirty : 1;
+};
+
+} // namespace WebCore
+
+#endif // AutoTableLayout_h
diff --git a/Source/core/rendering/BidiRun.cpp b/Source/core/rendering/BidiRun.cpp
new file mode 100644
index 0000000..4f6b82f
--- /dev/null
+++ b/Source/core/rendering/BidiRun.cpp
@@ -0,0 +1,75 @@
+/**
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Andrew Wellington (proton@wiretapped.net)
+ *
+ * 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 "core/rendering/BidiRun.h"
+#include "core/rendering/InlineBox.h"
+#include "core/rendering/RenderArena.h"
+#include <wtf/RefCountedLeakCounter.h>
+#include <wtf/StdLibExtras.h>
+
+using namespace WTF;
+
+namespace WebCore {
+
+DEFINE_DEBUG_ONLY_GLOBAL(RefCountedLeakCounter, bidiRunCounter, ("BidiRun"));
+
+#ifndef NDEBUG
+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)
+{
+#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;
+}
+
+}
diff --git a/Source/core/rendering/BidiRun.h b/Source/core/rendering/BidiRun.h
new file mode 100644
index 0000000..c4c266f
--- /dev/null
+++ b/Source/core/rendering/BidiRun.h
@@ -0,0 +1,69 @@
+/**
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Andrew Wellington (proton@wiretapped.net)
+ *
+ * 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 BidiRun_h
+#define BidiRun_h
+
+#include "core/platform/text/BidiResolver.h"
+#include "core/rendering/RenderText.h"
+#include <wtf/StdLibExtras.h>
+
+namespace WebCore {
+
+class BidiContext;
+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)
+    {
+        // Stored in base class to save space.
+        m_hasHyphen = false;
+        m_startsSegment = false;
+    }
+
+    void destroy();
+
+    // Overloaded new operator.
+    void* operator new(size_t, RenderArena*);
+
+    // Overridden to prevent the normal delete from being called.
+    void operator delete(void*, size_t);
+
+    BidiRun* next() { return static_cast<BidiRun*>(m_next); }
+    RenderObject* object() { return m_object; }
+
+private:
+    // The normal operator new is disallowed.
+    void* operator new(size_t) throw();
+
+public:
+    RenderObject* m_object;
+    InlineBox* m_box;
+};
+
+}
+
+#endif // BidiRun_h
diff --git a/Source/core/rendering/ClipPathOperation.h b/Source/core/rendering/ClipPathOperation.h
new file mode 100644
index 0000000..7b43c82
--- /dev/null
+++ b/Source/core/rendering/ClipPathOperation.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2012 Adobe Systems Incorporated. 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 THE COPYRIGHT HOLDER “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 THE COPYRIGHT HOLDER 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 ClipPathOperation_h
+#define ClipPathOperation_h
+
+#include "core/platform/graphics/Path.h"
+#include "core/rendering/style/BasicShapes.h"
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class ClipPathOperation : public RefCounted<ClipPathOperation> {
+public:
+    enum OperationType {
+        REFERENCE,
+        SHAPE
+    };
+
+    virtual ~ClipPathOperation() { }
+
+    virtual bool operator==(const ClipPathOperation&) const = 0;
+    bool operator!=(const ClipPathOperation& o) const { return !(*this == o); }
+
+    virtual OperationType getOperationType() const { return m_type; }
+    virtual bool isSameType(const ClipPathOperation& o) const { return o.getOperationType() == m_type; }
+
+protected:
+    ClipPathOperation(OperationType type)
+        : m_type(type)
+    {
+    }
+
+    OperationType m_type;
+};
+
+class ReferenceClipPathOperation : public ClipPathOperation {
+public:
+    static PassRefPtr<ReferenceClipPathOperation> create(const String& url, const String& fragment)
+    {
+        return adoptRef(new ReferenceClipPathOperation(url, fragment));
+    }
+
+    const String& url() const { return m_url; }
+    const String& fragment() const { return m_fragment; }
+
+private:
+    virtual bool operator==(const ClipPathOperation& o) const
+    {
+        if (!isSameType(o))
+            return false;
+        const ReferenceClipPathOperation* other = static_cast<const ReferenceClipPathOperation*>(&o);
+        return m_url == other->m_url;
+    }
+
+    ReferenceClipPathOperation(const String& url, const String& fragment)
+        : ClipPathOperation(REFERENCE)
+        , m_url(url)
+        , m_fragment(fragment)
+    {
+    }
+
+    String m_url;
+    String m_fragment;
+};
+
+class ShapeClipPathOperation : public ClipPathOperation {
+public:
+    static PassRefPtr<ShapeClipPathOperation> create(PassRefPtr<BasicShape> shape)
+    {
+        return adoptRef(new ShapeClipPathOperation(shape));
+    }
+
+    const BasicShape* basicShape() const { return m_shape.get(); }
+    WindRule windRule() const { return m_shape->windRule(); }
+    const Path& path(const FloatRect& boundingRect)
+    {
+        ASSERT(m_shape);
+        m_path.clear();
+        m_path = adoptPtr(new Path);
+        m_shape->path(*m_path, boundingRect);
+        return *m_path;
+    }
+
+private:
+    virtual bool operator==(const ClipPathOperation& o) const
+    {
+        if (!isSameType(o))
+            return false;
+        const ShapeClipPathOperation* other = static_cast<const ShapeClipPathOperation*>(&o);
+        return m_shape == other->m_shape;
+    }
+
+    ShapeClipPathOperation(PassRefPtr<BasicShape> shape)
+        : ClipPathOperation(SHAPE)
+        , m_shape(shape)
+    {
+    }
+
+    RefPtr<BasicShape> m_shape;
+    OwnPtr<Path> m_path;
+};
+}
+
+#endif // ClipPathOperation_h
diff --git a/Source/core/rendering/ColumnInfo.h b/Source/core/rendering/ColumnInfo.h
new file mode 100644
index 0000000..6d0d0a6
--- /dev/null
+++ b/Source/core/rendering/ColumnInfo.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2010, 2011 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 ColumnInfo_h
+#define ColumnInfo_h
+
+#include "core/platform/LayoutUnit.h"
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class ColumnInfo {
+    WTF_MAKE_NONCOPYABLE(ColumnInfo); WTF_MAKE_FAST_ALLOCATED;
+public:
+    ColumnInfo()
+        : m_desiredColumnWidth(0)
+        , m_desiredColumnCount(1)
+        , m_progressionAxis(InlineAxis)
+        , m_progressionIsReversed(false)
+        , m_columnCount(1)
+        , m_columnHeight(0)
+        , m_minimumColumnHeight(0)
+        , m_forcedBreaks(0)
+        , m_maximumDistanceBetweenForcedBreaks(0)
+        , m_forcedBreakOffset(0)
+        , m_paginationUnit(Column)
+    {
+    }
+
+    LayoutUnit desiredColumnWidth() const { return m_desiredColumnWidth; }
+    void setDesiredColumnWidth(LayoutUnit width) { m_desiredColumnWidth = width; }
+    
+    unsigned desiredColumnCount() const { return m_desiredColumnCount; }
+    void setDesiredColumnCount(unsigned count) { m_desiredColumnCount = count; }
+
+    enum Axis { InlineAxis, BlockAxis };
+
+    Axis progressionAxis() const { return m_progressionAxis; }
+    void setProgressionAxis(Axis progressionAxis) { m_progressionAxis = progressionAxis; }
+
+    bool progressionIsReversed() const { return m_progressionIsReversed; }
+    void setProgressionIsReversed(bool reversed) { m_progressionIsReversed = reversed; }
+
+    unsigned columnCount() const { return m_columnCount; }
+    LayoutUnit columnHeight() const { return m_columnHeight; }
+
+    // Set our count and height.  This is enough info for a RenderBlock to compute page rects
+    // dynamically.
+    void setColumnCountAndHeight(int count, LayoutUnit height)
+    { 
+        m_columnCount = count;
+        m_columnHeight = height;
+    }
+    void setColumnHeight(LayoutUnit height) { m_columnHeight = height; }
+
+    void updateMinimumColumnHeight(LayoutUnit height) { m_minimumColumnHeight = std::max(height, m_minimumColumnHeight); }
+    LayoutUnit minimumColumnHeight() const { return m_minimumColumnHeight; }
+
+    int forcedBreaks() const { return m_forcedBreaks; }
+    LayoutUnit forcedBreakOffset() const { return m_forcedBreakOffset; }
+    LayoutUnit maximumDistanceBetweenForcedBreaks() const { return m_maximumDistanceBetweenForcedBreaks; }
+    void clearForcedBreaks()
+    { 
+        m_forcedBreaks = 0;
+        m_maximumDistanceBetweenForcedBreaks = 0;
+        m_forcedBreakOffset = 0;
+    }
+    void addForcedBreak(LayoutUnit offsetFromFirstPage)
+    { 
+        ASSERT(!m_columnHeight);
+        LayoutUnit distanceFromLastBreak = offsetFromFirstPage - m_forcedBreakOffset;
+        if (!distanceFromLastBreak)
+            return;
+        m_forcedBreaks++;
+        m_maximumDistanceBetweenForcedBreaks = std::max(m_maximumDistanceBetweenForcedBreaks, distanceFromLastBreak);
+        m_forcedBreakOffset = offsetFromFirstPage;
+    }
+
+    enum PaginationUnit { Column, Page };
+    PaginationUnit paginationUnit() const { return m_paginationUnit; }
+    void setPaginationUnit(PaginationUnit paginationUnit) { m_paginationUnit = paginationUnit; }
+
+private:
+    LayoutUnit m_desiredColumnWidth;
+    unsigned m_desiredColumnCount;
+    Axis m_progressionAxis;
+    bool m_progressionIsReversed;
+
+    unsigned m_columnCount;
+    LayoutUnit m_columnHeight;
+    LayoutUnit m_minimumColumnHeight;
+    int m_forcedBreaks; // FIXME: We will ultimately need to cache more information to balance around forced breaks properly.
+    LayoutUnit m_maximumDistanceBetweenForcedBreaks;
+    LayoutUnit m_forcedBreakOffset;
+    PaginationUnit m_paginationUnit;
+};
+
+}
+
+#endif
diff --git a/Source/core/rendering/CounterNode.cpp b/Source/core/rendering/CounterNode.cpp
new file mode 100644
index 0000000..d941bcf
--- /dev/null
+++ b/Source/core/rendering/CounterNode.cpp
@@ -0,0 +1,385 @@
+/*
+ * Copyright (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
+ * 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 "core/rendering/CounterNode.h"
+
+#include <stdio.h>
+#include "core/rendering/RenderCounter.h"
+#include "core/rendering/RenderObject.h"
+
+namespace WebCore {
+
+CounterNode::CounterNode(RenderObject* o, bool hasResetType, int value)
+    : m_hasResetType(hasResetType)
+    , m_value(value)
+    , m_countInParent(0)
+    , m_owner(o)
+    , m_rootRenderer(0)
+    , m_parent(0)
+    , m_previousSibling(0)
+    , m_nextSibling(0)
+    , m_firstChild(0)
+    , m_lastChild(0)
+{
+}
+
+CounterNode::~CounterNode()
+{
+    // Ideally this would be an assert and this would never be reached. In reality this happens a lot
+    // so we need to handle these cases. The node is still connected to the tree so we need to detach it.
+    if (m_parent || m_previousSibling || m_nextSibling || m_firstChild || m_lastChild) {
+        CounterNode* oldParent = 0;
+        CounterNode* oldPreviousSibling = 0;
+        // Instead of calling removeChild() we do this safely as the tree is likely broken if we get here.
+        if (m_parent) {
+            if (m_parent->m_firstChild == this)
+                m_parent->m_firstChild = m_nextSibling;
+            if (m_parent->m_lastChild == this)
+                m_parent->m_lastChild = m_previousSibling;
+            oldParent = m_parent;
+            m_parent = 0;
+        }
+        if (m_previousSibling) {
+            if (m_previousSibling->m_nextSibling == this)
+                m_previousSibling->m_nextSibling = m_nextSibling;
+            oldPreviousSibling = m_previousSibling;
+            m_previousSibling = 0;
+        }
+        if (m_nextSibling) {
+            if (m_nextSibling->m_previousSibling == this)
+                m_nextSibling->m_previousSibling = oldPreviousSibling;
+            m_nextSibling = 0;
+        }
+        if (m_firstChild) {
+            // The node's children are reparented to the old parent.
+            for (CounterNode* child = m_firstChild; child; ) {
+                CounterNode* nextChild = child->m_nextSibling;
+                CounterNode* nextSibling = 0;
+                child->m_parent = oldParent;
+                if (oldPreviousSibling) {
+                    nextSibling = oldPreviousSibling->m_nextSibling;
+                    child->m_previousSibling = oldPreviousSibling;
+                    oldPreviousSibling->m_nextSibling = child;
+                    child->m_nextSibling = nextSibling;
+                    nextSibling->m_previousSibling = child;
+                    oldPreviousSibling = child;
+                }
+                child = nextChild;
+            }
+        }
+    }
+    resetRenderers();
+}
+
+PassRefPtr<CounterNode> CounterNode::create(RenderObject* owner, bool hasResetType, int value)
+{
+    return adoptRef(new CounterNode(owner, hasResetType, value));
+}
+
+CounterNode* CounterNode::nextInPreOrderAfterChildren(const CounterNode* stayWithin) const
+{
+    if (this == stayWithin)
+        return 0;
+
+    const CounterNode* current = this;
+    CounterNode* next;
+    while (!(next = current->m_nextSibling)) {
+        current = current->m_parent;
+        if (!current || current == stayWithin)
+            return 0;
+    }
+    return next;
+}
+
+CounterNode* CounterNode::nextInPreOrder(const CounterNode* stayWithin) const
+{
+    if (CounterNode* next = m_firstChild)
+        return next;
+
+    return nextInPreOrderAfterChildren(stayWithin);
+}
+
+CounterNode* CounterNode::lastDescendant() const
+{
+    CounterNode* last = m_lastChild;
+    if (!last)
+        return 0;
+
+    while (CounterNode* lastChild = last->m_lastChild)
+        last = lastChild;
+
+    return last;
+}
+
+CounterNode* CounterNode::previousInPreOrder() const
+{
+    CounterNode* previous = m_previousSibling;
+    if (!previous)
+        return m_parent;
+
+    while (CounterNode* lastChild = previous->m_lastChild)
+        previous = lastChild;
+
+    return previous;
+}
+
+int CounterNode::computeCountInParent() const
+{
+    int increment = actsAsReset() ? 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::addRenderer(RenderCounter* value)
+{
+    if (!value) {
+        ASSERT_NOT_REACHED();
+        return;
+    }
+    if (value->m_counterNode) {
+        ASSERT_NOT_REACHED();
+        value->m_counterNode->removeRenderer(value);
+    }
+    ASSERT(!value->m_nextForSameCounter);
+    for (RenderCounter* iterator = m_rootRenderer;iterator; iterator = iterator->m_nextForSameCounter) {
+        if (iterator == value) {
+            ASSERT_NOT_REACHED();
+            return;
+        }
+    }
+    value->m_nextForSameCounter = m_rootRenderer;
+    m_rootRenderer = value;
+    if (value->m_counterNode != this) {
+        if (value->m_counterNode) {
+            ASSERT_NOT_REACHED();
+            value->m_counterNode->removeRenderer(value);
+        }
+        value->m_counterNode = this;
+    }
+}
+
+void CounterNode::removeRenderer(RenderCounter* value)
+{
+    if (!value) {
+        ASSERT_NOT_REACHED();
+        return;
+    }
+    if (value->m_counterNode && value->m_counterNode != this) {
+        ASSERT_NOT_REACHED();
+        value->m_counterNode->removeRenderer(value);
+    }
+    RenderCounter* previous = 0;
+    for (RenderCounter* iterator = m_rootRenderer;iterator; iterator = iterator->m_nextForSameCounter) {
+        if (iterator == value) {
+            if (previous)
+                previous->m_nextForSameCounter = value->m_nextForSameCounter;
+            else
+                m_rootRenderer = value->m_nextForSameCounter;
+            value->m_nextForSameCounter = 0;
+            value->m_counterNode = 0;
+            return;
+        }
+        previous = iterator;
+    }
+    ASSERT_NOT_REACHED();
+}
+
+void CounterNode::resetRenderers()
+{
+    while (m_rootRenderer)
+        m_rootRenderer->invalidate(); // This makes m_rootRenderer point to the next renderer if any since it disconnects the m_rootRenderer from this.
+}
+
+void CounterNode::resetThisAndDescendantsRenderers()
+{
+    CounterNode* node = this;
+    do {
+        node->resetRenderers();
+        node = node->nextInPreOrder(this);
+    } while (node);
+}
+
+void CounterNode::recount()
+{
+    for (CounterNode* node = this; node; node = node->m_nextSibling) {
+        int oldCount = node->m_countInParent;
+        int newCount = node->computeCountInParent();
+        if (oldCount == newCount)
+            break;
+        node->m_countInParent = newCount;
+        node->resetThisAndDescendantsRenderers();
+    }
+}
+
+void CounterNode::insertAfter(CounterNode* newChild, CounterNode* refChild, const AtomicString& identifier)
+{
+    ASSERT(newChild);
+    ASSERT(!newChild->m_parent);
+    ASSERT(!newChild->m_previousSibling);
+    ASSERT(!newChild->m_nextSibling);
+    // If the refChild is not our child we can not complete the request. This hardens against bugs in RenderCounter.
+    // When renderers are reparented it may request that we insert counter nodes improperly.
+    if (refChild && refChild->m_parent != this)
+        return;
+
+    if (newChild->m_hasResetType) {
+        while (m_lastChild != refChild)
+            RenderCounter::destroyCounterNode(m_lastChild->owner(), identifier);
+    }
+
+    CounterNode* next;
+
+    if (refChild) {
+        next = refChild->m_nextSibling;
+        refChild->m_nextSibling = newChild;
+    } else {
+        next = m_firstChild;
+        m_firstChild = newChild;
+    }
+
+    newChild->m_parent = this;
+    newChild->m_previousSibling = refChild;
+
+    if (next) {
+        ASSERT(next->m_previousSibling == refChild);
+        next->m_previousSibling = newChild;
+        newChild->m_nextSibling = next;
+    } else {
+        ASSERT(m_lastChild == refChild);
+        m_lastChild = newChild;
+    }
+
+    if (!newChild->m_firstChild || newChild->m_hasResetType) {
+        newChild->m_countInParent = newChild->computeCountInParent();
+        newChild->resetThisAndDescendantsRenderers();
+        if (next)
+            next->recount();
+        return;
+    }
+
+    // The code below handles the case when a formerly root increment counter is loosing its root position
+    // and therefore its children become next siblings.
+    CounterNode* last = newChild->m_lastChild;
+    CounterNode* first = newChild->m_firstChild;
+
+    if (first) {
+        ASSERT(last);
+        newChild->m_nextSibling = first;
+        if (m_lastChild == newChild)
+            m_lastChild = last;
+
+        first->m_previousSibling = newChild;
+    
+        // The case when the original next sibling of the inserted node becomes a child of
+        // one of the former children of the inserted node is not handled as it is believed
+        // to be impossible since:
+        // 1. if the increment counter node lost it's root position as a result of another
+        //    counter node being created, it will be inserted as the last child so next is null.
+        // 2. if the increment counter node lost it's root position as a result of a renderer being
+        //    inserted into the document's render tree, all its former children counters are attached
+        //    to children of the inserted renderer and hence cannot be in scope for counter nodes
+        //    attached to renderers that were already in the document's render tree.
+        last->m_nextSibling = next;
+        if (next) {
+            ASSERT(next->m_previousSibling == newChild);
+            next->m_previousSibling = last;
+        } else
+            m_lastChild = last;
+        for (next = first; ; next = next->m_nextSibling) {
+            next->m_parent = this;
+            if (last == next)
+                break;
+        }
+    }
+    newChild->m_firstChild = 0;
+    newChild->m_lastChild = 0;
+    newChild->m_countInParent = newChild->computeCountInParent();
+    newChild->resetRenderers();
+    first->recount();
+}
+
+void CounterNode::removeChild(CounterNode* oldChild)
+{
+    ASSERT(oldChild);
+    ASSERT(!oldChild->m_firstChild);
+    ASSERT(!oldChild->m_lastChild);
+
+    CounterNode* next = oldChild->m_nextSibling;
+    CounterNode* previous = oldChild->m_previousSibling;
+
+    oldChild->m_nextSibling = 0;
+    oldChild->m_previousSibling = 0;
+    oldChild->m_parent = 0;
+
+    if (previous) 
+        previous->m_nextSibling = next;
+    else {
+        ASSERT(m_firstChild == oldChild);
+        m_firstChild = next;
+    }
+
+    if (next)
+        next->m_previousSibling = previous;
+    else {
+        ASSERT(m_lastChild == oldChild);
+        m_lastChild = previous;
+    }
+
+    if (next)
+        next->recount();
+}
+
+#ifndef NDEBUG
+
+static void showTreeAndMark(const CounterNode* node)
+{
+    const CounterNode* root = node;
+    while (root->parent())
+        root = root->parent();
+
+    for (const CounterNode* current = root; current; current = current->nextInPreOrder()) {
+        fprintf(stderr, "%c", (current == node) ? '*' : ' ');
+        for (const CounterNode* parent = current; parent && parent != root; parent = parent->parent())
+            fprintf(stderr, "    ");
+        fprintf(stderr, "%p %s: %d %d P:%p PS:%p NS:%p R:%p\n",
+            current, current->actsAsReset() ? "reset____" : "increment", current->value(),
+            current->countInParent(), current->parent(), current->previousSibling(),
+            current->nextSibling(), current->owner());
+    }
+    fflush(stderr);
+}
+
+#endif
+
+} // namespace WebCore
+
+#ifndef NDEBUG
+
+void showCounterTree(const WebCore::CounterNode* counter)
+{
+    if (counter)
+        showTreeAndMark(counter);
+}
+
+#endif
diff --git a/Source/core/rendering/CounterNode.h b/Source/core/rendering/CounterNode.h
new file mode 100644
index 0000000..7d6def8
--- /dev/null
+++ b/Source/core/rendering/CounterNode.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
+ * 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/Forward.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/RefCounted.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 RenderCounter;
+
+class CounterNode : public RefCounted<CounterNode> {
+public:
+    static PassRefPtr<CounterNode> create(RenderObject*, bool isReset, int value);
+    ~CounterNode();
+    bool actsAsReset() const { return m_hasResetType || !m_parent; }
+    bool hasResetType() const { return m_hasResetType; }
+    int value() const { return m_value; }
+    int countInParent() const { return m_countInParent; }
+    RenderObject* owner() const { return m_owner; }
+    void addRenderer(RenderCounter*);
+    void removeRenderer(RenderCounter*);
+
+    // Invalidates the text in the renderers of this counter, if any.
+    void resetRenderers();
+
+    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; }
+    CounterNode* lastDescendant() const;
+    CounterNode* previousInPreOrder() const;
+    CounterNode* nextInPreOrder(const CounterNode* stayWithin = 0) const;
+    CounterNode* nextInPreOrderAfterChildren(const CounterNode* stayWithin = 0) const;
+
+    void insertAfter(CounterNode* newChild, CounterNode* beforeChild, const AtomicString& identifier);
+
+    // identifier must match the identifier of this counter.
+    void removeChild(CounterNode*);
+
+private:
+    CounterNode(RenderObject*, bool isReset, int value);
+    int computeCountInParent() const;
+    // Invalidates the text in the renderer of this counter, if any,
+    // and in the renderers of all descendants of this counter, if any.
+    void resetThisAndDescendantsRenderers();
+    void recount();
+
+    bool m_hasResetType;
+    int m_value;
+    int m_countInParent;
+    RenderObject* m_owner;
+    RenderCounter* m_rootRenderer;
+
+    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 showCounterTree(const WebCore::CounterNode*);
+#endif
+
+#endif // CounterNode_h
diff --git a/Source/core/rendering/EllipsisBox.cpp b/Source/core/rendering/EllipsisBox.cpp
new file mode 100644
index 0000000..8d2d993
--- /dev/null
+++ b/Source/core/rendering/EllipsisBox.cpp
@@ -0,0 +1,158 @@
+/**
+ * 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 "core/rendering/EllipsisBox.h"
+
+#include "core/dom/Document.h"
+#include "core/platform/graphics/Font.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/platform/graphics/TextRun.h"
+#include "core/rendering/HitTestResult.h"
+#include "core/rendering/InlineTextBox.h"
+#include "core/rendering/PaintInfo.h"
+#include "core/rendering/RenderBlock.h"
+#include "core/rendering/RootInlineBox.h"
+
+namespace WebCore {
+
+void EllipsisBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit lineTop, LayoutUnit lineBottom)
+{
+    GraphicsContext* context = paintInfo.context;
+    RenderStyle* style = m_renderer->style(isFirstLineStyle());
+    Color textColor = style->visitedDependentColor(CSSPropertyWebkitTextFillColor);
+    if (textColor != context->fillColor())
+        context->setFillColor(textColor, style->colorSpace());
+    bool setShadow = false;
+    if (style->textShadow()) {
+        context->setShadow(LayoutSize(style->textShadow()->x(), style->textShadow()->y()),
+                           style->textShadow()->blur(), style->textShadow()->color(), style->colorSpace());
+        setShadow = true;
+    }
+
+    const Font& font = style->font();
+    if (selectionState() != RenderObject::SelectionNone) {
+        paintSelection(context, paintOffset, style, font);
+
+        // Select the correct color for painting the text.
+        Color foreground = paintInfo.forceBlackText() ? Color::black : renderer()->selectionForegroundColor();
+        if (foreground.isValid() && foreground != textColor)
+            context->setFillColor(foreground, style->colorSpace());
+    }
+
+    // FIXME: Why is this always LTR? Fix by passing correct text run flags below.
+    context->drawText(font, RenderBlock::constructTextRun(renderer(), font, m_str, style, TextRun::AllowTrailingExpansion), LayoutPoint(x() + paintOffset.x(), y() + paintOffset.y() + style->fontMetrics().ascent()));
+
+    // Restore the regular fill color.
+    if (textColor != context->fillColor())
+        context->setFillColor(textColor, style->colorSpace());
+
+    if (setShadow)
+        context->clearShadow();
+
+    paintMarkupBox(paintInfo, paintOffset, lineTop, lineBottom, style);
+}
+
+InlineBox* EllipsisBox::markupBox() const
+{
+    if (!m_shouldPaintMarkupBox || !m_renderer->isRenderBlock())
+        return 0;
+
+    RenderBlock* block = toRenderBlock(m_renderer);
+    RootInlineBox* lastLine = block->lineAtIndex(block->lineCount() - 1);
+    if (!lastLine)
+        return 0;
+
+    // If the last line-box on the last line of a block is a link, -webkit-line-clamp paints that box after the ellipsis.
+    // It does not actually move the link.
+    InlineBox* anchorBox = lastLine->lastChild();
+    if (!anchorBox || !anchorBox->renderer()->style()->isLink())
+        return 0;
+
+    return anchorBox;
+}
+
+void EllipsisBox::paintMarkupBox(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit lineTop, LayoutUnit lineBottom, RenderStyle* style)
+{
+    InlineBox* markupBox = this->markupBox();
+    if (!markupBox)
+        return;
+
+    LayoutPoint adjustedPaintOffset = paintOffset;
+    adjustedPaintOffset.move(x() + m_logicalWidth - markupBox->x(),
+        y() + style->fontMetrics().ascent() - (markupBox->y() + markupBox->renderer()->style(isFirstLineStyle())->fontMetrics().ascent()));
+    markupBox->paint(paintInfo, adjustedPaintOffset, lineTop, lineBottom);
+}
+
+IntRect EllipsisBox::selectionRect()
+{
+    RenderStyle* style = m_renderer->style(isFirstLineStyle());
+    const Font& font = style->font();
+    // FIXME: Why is this always LTR? Fix by passing correct text run flags below.
+    return enclosingIntRect(font.selectionRectForText(RenderBlock::constructTextRun(renderer(), font, m_str, style, TextRun::AllowTrailingExpansion), IntPoint(x(), y() + root()->selectionTopAdjustedForPrecedingBlock()), root()->selectionHeightAdjustedForPrecedingBlock()));
+}
+
+void EllipsisBox::paintSelection(GraphicsContext* context, const LayoutPoint& paintOffset, RenderStyle* style, const Font& font)
+{
+    Color textColor = style->visitedDependentColor(CSSPropertyColor);
+    Color c = m_renderer->selectionBackgroundColor();
+    if (!c.isValid() || !c.alpha())
+        return;
+
+    // If the text color ends up being the same as the selection background, invert the selection
+    // background.
+    if (textColor == c)
+        c = Color(0xff - c.red(), 0xff - c.green(), 0xff - c.blue());
+
+    GraphicsContextStateSaver stateSaver(*context);
+    LayoutUnit top = root()->selectionTop();
+    LayoutUnit h = root()->selectionHeight();
+    FloatRect clipRect(x() + paintOffset.x(), top + paintOffset.y(), m_logicalWidth, h);
+    alignSelectionRectToDevicePixels(clipRect);
+    context->clip(clipRect);
+    // FIXME: Why is this always LTR? Fix by passing correct text run flags below.
+    context->drawHighlightForText(font, RenderBlock::constructTextRun(renderer(), font, m_str, style, TextRun::AllowTrailingExpansion), roundedIntPoint(LayoutPoint(x() + paintOffset.x(), y() + paintOffset.y() + top)), h, c, style->colorSpace());
+}
+
+bool EllipsisBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom)
+{
+    LayoutPoint adjustedLocation = accumulatedOffset + roundedLayoutPoint(topLeft());
+
+    // Hit test the markup box.
+    if (InlineBox* markupBox = this->markupBox()) {
+        RenderStyle* style = m_renderer->style(isFirstLineStyle());
+        LayoutUnit mtx = adjustedLocation.x() + m_logicalWidth - markupBox->x();
+        LayoutUnit mty = adjustedLocation.y() + style->fontMetrics().ascent() - (markupBox->y() + markupBox->renderer()->style(isFirstLineStyle())->fontMetrics().ascent());
+        if (markupBox->nodeAtPoint(request, result, locationInContainer, LayoutPoint(mtx, mty), lineTop, lineBottom)) {
+            renderer()->updateHitTestResult(result, locationInContainer.point() - LayoutSize(mtx, mty));
+            return true;
+        }
+    }
+
+    LayoutRect boundsRect(adjustedLocation, LayoutSize(m_logicalWidth, m_height));
+    if (visibleToHitTestRequest(request) && boundsRect.intersects(HitTestLocation::rectForPoint(locationInContainer.point(), 0, 0, 0, 0))) {
+        renderer()->updateHitTestResult(result, locationInContainer.point() - toLayoutSize(adjustedLocation));
+        if (!result.addNodeToRectBasedTestResult(renderer()->node(), request, locationInContainer, boundsRect))
+            return true;
+    }
+
+    return false;
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/EllipsisBox.h b/Source/core/rendering/EllipsisBox.h
new file mode 100644
index 0000000..9382e77
--- /dev/null
+++ b/Source/core/rendering/EllipsisBox.h
@@ -0,0 +1,62 @@
+/**
+ * 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 "core/rendering/InlineBox.h"
+
+namespace WebCore {
+
+class HitTestRequest;
+class HitTestResult;
+
+class EllipsisBox FINAL : public InlineBox {
+public:
+    EllipsisBox(RenderObject* obj, const AtomicString& ellipsisStr, InlineFlowBox* parent,
+                int width, int height, int y, bool firstLine, bool isVertical, InlineBox* markupBox)
+        : InlineBox(obj, FloatPoint(0, y), width, firstLine, true, false, false, isVertical, 0, 0, parent)
+        , m_shouldPaintMarkupBox(markupBox)
+        , m_height(height)
+        , m_str(ellipsisStr)
+        , m_selectionState(RenderObject::SelectionNone)
+    {
+    }
+
+    virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom);
+    virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom) OVERRIDE;
+    void setSelectionState(RenderObject::SelectionState s) { m_selectionState = s; }
+    IntRect selectionRect();
+
+private:
+    void paintMarkupBox(PaintInfo&, const LayoutPoint& paintOffset, LayoutUnit lineTop, LayoutUnit lineBottom, RenderStyle*);
+    virtual int height() const { return m_height; }
+    virtual RenderObject::SelectionState selectionState() { return m_selectionState; }
+    void paintSelection(GraphicsContext*, const LayoutPoint&, RenderStyle*, const Font&);
+    InlineBox* markupBox() const;
+
+    bool m_shouldPaintMarkupBox;
+    int m_height;
+    AtomicString m_str;
+    RenderObject::SelectionState m_selectionState;
+};
+
+} // namespace WebCore
+
+#endif // EllipsisBox_h
diff --git a/Source/core/rendering/FilterEffectRenderer.cpp b/Source/core/rendering/FilterEffectRenderer.cpp
new file mode 100644
index 0000000..992fb55
--- /dev/null
+++ b/Source/core/rendering/FilterEffectRenderer.cpp
@@ -0,0 +1,506 @@
+/*
+ * Copyright (C) 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2013 Google 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 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 "core/rendering/FilterEffectRenderer.h"
+
+#include "core/dom/Document.h"
+#include "core/platform/FloatConversion.h"
+#include "core/platform/graphics/ColorSpace.h"
+#include "core/platform/graphics/filters/FEColorMatrix.h"
+#include "core/platform/graphics/filters/FEComponentTransfer.h"
+#include "core/platform/graphics/filters/FEDropShadow.h"
+#include "core/platform/graphics/filters/FEGaussianBlur.h"
+#include "core/platform/graphics/filters/FEMerge.h"
+#include "core/rendering/RenderLayer.h"
+
+#include <algorithm>
+#include <wtf/MathExtras.h>
+
+#include "core/platform/graphics/filters/custom/CustomFilterGlobalContext.h"
+#include "core/platform/graphics/filters/custom/CustomFilterOperation.h"
+#include "core/platform/graphics/filters/custom/CustomFilterProgram.h"
+#include "core/platform/graphics/filters/custom/CustomFilterValidatedProgram.h"
+#include "core/platform/graphics/filters/custom/FECustomFilter.h"
+#include "core/platform/graphics/filters/custom/ValidatedCustomFilterOperation.h"
+#include "core/rendering/RenderView.h"
+
+#if ENABLE(SVG)
+#include "core/loader/cache/CachedSVGDocument.h"
+#include "core/loader/cache/CachedSVGDocumentReference.h"
+#include "core/platform/graphics/filters/SourceAlpha.h"
+#include "core/svg/SVGElement.h"
+#include "core/svg/SVGFilterPrimitiveStandardAttributes.h"
+#endif
+
+namespace WebCore {
+
+static inline void endMatrixRow(Vector<float>& parameters)
+{
+    parameters.append(0);
+    parameters.append(0);
+}
+
+static inline void lastMatrixRow(Vector<float>& parameters)
+{
+    parameters.append(0);
+    parameters.append(0);
+    parameters.append(0);
+    parameters.append(1);
+    parameters.append(0);
+}
+
+inline bool isFilterSizeValid(FloatRect rect)
+{
+    if (rect.width() < 0 || rect.width() > kMaxFilterSize
+        || rect.height() < 0 || rect.height() > kMaxFilterSize)
+        return false;
+    return true;
+}
+
+static PassRefPtr<FECustomFilter> createCustomFilterEffect(Filter* filter, Document* document, ValidatedCustomFilterOperation* operation)
+{
+    if (!document)
+        return 0;
+
+    CustomFilterGlobalContext* globalContext = document->renderView()->customFilterGlobalContext();
+    globalContext->prepareContextIfNeeded(document->view()->hostWindow());
+    if (!globalContext->context())
+        return 0;
+
+    return FECustomFilter::create(filter, globalContext->context(), operation->validatedProgram(), operation->parameters(),
+        operation->meshRows(), operation->meshColumns(),  operation->meshType());
+}
+
+FilterEffectRenderer::FilterEffectRenderer()
+    : Filter(AffineTransform())
+    , m_graphicsBufferAttached(false)
+    , m_hasFilterThatMovesPixels(false)
+    , m_hasCustomShaderFilter(false)
+{
+    setFilterResolution(FloatSize(1, 1));
+    m_sourceGraphic = SourceGraphic::create(this);
+}
+
+FilterEffectRenderer::~FilterEffectRenderer()
+{
+}
+
+GraphicsContext* FilterEffectRenderer::inputContext()
+{
+    return sourceImage() ? sourceImage()->context() : 0;
+}
+
+PassRefPtr<FilterEffect> FilterEffectRenderer::buildReferenceFilter(RenderObject* renderer, PassRefPtr<FilterEffect> previousEffect, ReferenceFilterOperation* filterOperation)
+{
+#if ENABLE(SVG)
+    if (!renderer)
+        return 0;
+
+    Document* document = renderer->document();
+    ASSERT(document);
+
+    CachedSVGDocumentReference* cachedSVGDocumentReference = filterOperation->cachedSVGDocumentReference();
+    CachedSVGDocument* cachedSVGDocument = cachedSVGDocumentReference ? cachedSVGDocumentReference->document() : 0;
+
+    // If we have an SVG document, this is an external reference. Otherwise
+    // we look up the referenced node in the current document.
+    if (cachedSVGDocument)
+        document = cachedSVGDocument->document();
+
+    if (!document)
+        return 0;
+
+    Element* filter = document->getElementById(filterOperation->fragment());
+    if (!filter) {
+        // Although we did not find the referenced filter, it might exist later
+        // in the document
+        document->accessSVGExtensions()->addPendingResource(filterOperation->fragment(), toElement(renderer->node()));
+        return 0;
+    }
+
+    RefPtr<FilterEffect> effect;
+
+    // FIXME: Figure out what to do with SourceAlpha. Right now, we're
+    // using the alpha of the original input layer, which is obviously
+    // wrong. We should probably be extracting the alpha from the 
+    // previousEffect, but this requires some more processing.  
+    // This may need a spec clarification.
+    RefPtr<SVGFilterBuilder> builder = SVGFilterBuilder::create(previousEffect, SourceAlpha::create(this));
+
+    for (Node* node = filter->firstChild(); node; node = node->nextSibling()) {
+        if (!node->isSVGElement())
+            continue;
+
+        SVGElement* element = toSVGElement(node);
+        if (!element->isFilterEffect())
+            continue;
+
+        SVGFilterPrimitiveStandardAttributes* effectElement = static_cast<SVGFilterPrimitiveStandardAttributes*>(element);
+
+        effect = effectElement->build(builder.get(), this);
+        if (!effect)
+            continue;
+
+        effectElement->setStandardAttributes(effect.get());
+        builder->add(effectElement->result(), effect);
+        m_effects.append(effect);
+    }
+    return effect;
+#else
+    UNUSED_PARAM(renderer);
+    UNUSED_PARAM(previousEffect);
+    UNUSED_PARAM(filterOperation);
+    return 0;
+#endif
+}
+
+bool FilterEffectRenderer::build(RenderObject* renderer, const FilterOperations& operations)
+{
+    m_hasCustomShaderFilter = false;
+    m_hasFilterThatMovesPixels = operations.hasFilterThatMovesPixels();
+    if (m_hasFilterThatMovesPixels)
+        m_outsets = operations.outsets();
+    
+    // Keep the old effects on the stack until we've created the new effects.
+    // New FECustomFilters can reuse cached resources from old FECustomFilters.
+    FilterEffectList oldEffects;
+    m_effects.swap(oldEffects);
+
+    RefPtr<FilterEffect> previousEffect = m_sourceGraphic;
+    for (size_t i = 0; i < operations.operations().size(); ++i) {
+        RefPtr<FilterEffect> effect;
+        FilterOperation* filterOperation = operations.operations().at(i).get();
+        switch (filterOperation->getOperationType()) {
+        case FilterOperation::REFERENCE: {
+            ReferenceFilterOperation* referenceOperation = static_cast<ReferenceFilterOperation*>(filterOperation);
+            effect = buildReferenceFilter(renderer, previousEffect, referenceOperation);
+            referenceOperation->setFilterEffect(effect);
+            break;
+        }
+        case FilterOperation::GRAYSCALE: {
+            BasicColorMatrixFilterOperation* colorMatrixOperation = static_cast<BasicColorMatrixFilterOperation*>(filterOperation);
+            Vector<float> inputParameters;
+            double oneMinusAmount = clampTo(1 - colorMatrixOperation->amount(), 0.0, 1.0);
+
+            // See https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html#grayscaleEquivalent
+            // for information on parameters.
+
+            inputParameters.append(narrowPrecisionToFloat(0.2126 + 0.7874 * oneMinusAmount));
+            inputParameters.append(narrowPrecisionToFloat(0.7152 - 0.7152 * oneMinusAmount));
+            inputParameters.append(narrowPrecisionToFloat(0.0722 - 0.0722 * oneMinusAmount));
+            endMatrixRow(inputParameters);
+
+            inputParameters.append(narrowPrecisionToFloat(0.2126 - 0.2126 * oneMinusAmount));
+            inputParameters.append(narrowPrecisionToFloat(0.7152 + 0.2848 * oneMinusAmount));
+            inputParameters.append(narrowPrecisionToFloat(0.0722 - 0.0722 * oneMinusAmount));
+            endMatrixRow(inputParameters);
+
+            inputParameters.append(narrowPrecisionToFloat(0.2126 - 0.2126 * oneMinusAmount));
+            inputParameters.append(narrowPrecisionToFloat(0.7152 - 0.7152 * oneMinusAmount));
+            inputParameters.append(narrowPrecisionToFloat(0.0722 + 0.9278 * oneMinusAmount));
+            endMatrixRow(inputParameters);
+
+            lastMatrixRow(inputParameters);
+
+            effect = FEColorMatrix::create(this, FECOLORMATRIX_TYPE_MATRIX, inputParameters);
+            break;
+        }
+        case FilterOperation::SEPIA: {
+            BasicColorMatrixFilterOperation* colorMatrixOperation = static_cast<BasicColorMatrixFilterOperation*>(filterOperation);
+            Vector<float> inputParameters;
+            double oneMinusAmount = clampTo(1 - colorMatrixOperation->amount(), 0.0, 1.0);
+
+            // See https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html#sepiaEquivalent
+            // for information on parameters.
+
+            inputParameters.append(narrowPrecisionToFloat(0.393 + 0.607 * oneMinusAmount));
+            inputParameters.append(narrowPrecisionToFloat(0.769 - 0.769 * oneMinusAmount));
+            inputParameters.append(narrowPrecisionToFloat(0.189 - 0.189 * oneMinusAmount));
+            endMatrixRow(inputParameters);
+
+            inputParameters.append(narrowPrecisionToFloat(0.349 - 0.349 * oneMinusAmount));
+            inputParameters.append(narrowPrecisionToFloat(0.686 + 0.314 * oneMinusAmount));
+            inputParameters.append(narrowPrecisionToFloat(0.168 - 0.168 * oneMinusAmount));
+            endMatrixRow(inputParameters);
+
+            inputParameters.append(narrowPrecisionToFloat(0.272 - 0.272 * oneMinusAmount));
+            inputParameters.append(narrowPrecisionToFloat(0.534 - 0.534 * oneMinusAmount));
+            inputParameters.append(narrowPrecisionToFloat(0.131 + 0.869 * oneMinusAmount));
+            endMatrixRow(inputParameters);
+
+            lastMatrixRow(inputParameters);
+
+            effect = FEColorMatrix::create(this, FECOLORMATRIX_TYPE_MATRIX, inputParameters);
+            break;
+        }
+        case FilterOperation::SATURATE: {
+            BasicColorMatrixFilterOperation* colorMatrixOperation = static_cast<BasicColorMatrixFilterOperation*>(filterOperation);
+            Vector<float> inputParameters;
+            inputParameters.append(narrowPrecisionToFloat(colorMatrixOperation->amount()));
+            effect = FEColorMatrix::create(this, FECOLORMATRIX_TYPE_SATURATE, inputParameters);
+            break;
+        }
+        case FilterOperation::HUE_ROTATE: {
+            BasicColorMatrixFilterOperation* colorMatrixOperation = static_cast<BasicColorMatrixFilterOperation*>(filterOperation);
+            Vector<float> inputParameters;
+            inputParameters.append(narrowPrecisionToFloat(colorMatrixOperation->amount()));
+            effect = FEColorMatrix::create(this, FECOLORMATRIX_TYPE_HUEROTATE, inputParameters);
+            break;
+        }
+        case FilterOperation::INVERT: {
+            BasicComponentTransferFilterOperation* componentTransferOperation = static_cast<BasicComponentTransferFilterOperation*>(filterOperation);
+            ComponentTransferFunction transferFunction;
+            transferFunction.type = FECOMPONENTTRANSFER_TYPE_TABLE;
+            Vector<float> transferParameters;
+            transferParameters.append(narrowPrecisionToFloat(componentTransferOperation->amount()));
+            transferParameters.append(narrowPrecisionToFloat(1 - componentTransferOperation->amount()));
+            transferFunction.tableValues = transferParameters;
+
+            ComponentTransferFunction nullFunction;
+            effect = FEComponentTransfer::create(this, transferFunction, transferFunction, transferFunction, nullFunction);
+            break;
+        }
+        case FilterOperation::OPACITY: {
+            BasicComponentTransferFilterOperation* componentTransferOperation = static_cast<BasicComponentTransferFilterOperation*>(filterOperation);
+            ComponentTransferFunction transferFunction;
+            transferFunction.type = FECOMPONENTTRANSFER_TYPE_TABLE;
+            Vector<float> transferParameters;
+            transferParameters.append(0);
+            transferParameters.append(narrowPrecisionToFloat(componentTransferOperation->amount()));
+            transferFunction.tableValues = transferParameters;
+
+            ComponentTransferFunction nullFunction;
+            effect = FEComponentTransfer::create(this, nullFunction, nullFunction, nullFunction, transferFunction);
+            break;
+        }
+        case FilterOperation::BRIGHTNESS: {
+            BasicComponentTransferFilterOperation* componentTransferOperation = static_cast<BasicComponentTransferFilterOperation*>(filterOperation);
+            ComponentTransferFunction transferFunction;
+            transferFunction.type = FECOMPONENTTRANSFER_TYPE_LINEAR;
+            transferFunction.slope = narrowPrecisionToFloat(componentTransferOperation->amount());
+            transferFunction.intercept = 0;
+
+            ComponentTransferFunction nullFunction;
+            effect = FEComponentTransfer::create(this, transferFunction, transferFunction, transferFunction, nullFunction);
+            break;
+        }
+        case FilterOperation::CONTRAST: {
+            BasicComponentTransferFilterOperation* componentTransferOperation = static_cast<BasicComponentTransferFilterOperation*>(filterOperation);
+            ComponentTransferFunction transferFunction;
+            transferFunction.type = FECOMPONENTTRANSFER_TYPE_LINEAR;
+            float amount = narrowPrecisionToFloat(componentTransferOperation->amount());
+            transferFunction.slope = amount;
+            transferFunction.intercept = -0.5 * amount + 0.5;
+            
+            ComponentTransferFunction nullFunction;
+            effect = FEComponentTransfer::create(this, transferFunction, transferFunction, transferFunction, nullFunction);
+            break;
+        }
+        case FilterOperation::BLUR: {
+            BlurFilterOperation* blurOperation = static_cast<BlurFilterOperation*>(filterOperation);
+            float stdDeviation = floatValueForLength(blurOperation->stdDeviation(), 0);
+            effect = FEGaussianBlur::create(this, stdDeviation, stdDeviation);
+            break;
+        }
+        case FilterOperation::DROP_SHADOW: {
+            DropShadowFilterOperation* dropShadowOperation = static_cast<DropShadowFilterOperation*>(filterOperation);
+            effect = FEDropShadow::create(this, dropShadowOperation->stdDeviation(), dropShadowOperation->stdDeviation(),
+                                                dropShadowOperation->x(), dropShadowOperation->y(), dropShadowOperation->color(), 1);
+            break;
+        }
+        case FilterOperation::CUSTOM:
+            // CUSTOM operations are always converted to VALIDATED_CUSTOM before getting here.
+            // The conversion happens in RenderLayer::computeFilterOperations.
+            ASSERT_NOT_REACHED();
+            break;
+        case FilterOperation::VALIDATED_CUSTOM: {
+            ValidatedCustomFilterOperation* customFilterOperation = static_cast<ValidatedCustomFilterOperation*>(filterOperation);
+            Document* document = renderer ? renderer->document() : 0;
+            effect = createCustomFilterEffect(this, document, customFilterOperation);
+            if (effect)
+                m_hasCustomShaderFilter = true;
+            break;
+        }
+        default:
+            break;
+        }
+
+        if (effect) {
+            // Unlike SVG, filters applied here should not clip to their primitive subregions.
+            effect->setClipsToBounds(false);
+            effect->setOperatingColorSpace(ColorSpaceDeviceRGB);
+            
+            if (filterOperation->getOperationType() != FilterOperation::REFERENCE) {
+                effect->inputEffects().append(previousEffect);
+                m_effects.append(effect);
+            }
+            previousEffect = effect.release();
+        }
+    }
+
+    // If we didn't make any effects, tell our caller we are not valid
+    if (!m_effects.size())
+        return false;
+
+    setMaxEffectRects(m_sourceDrawingRegion);
+    
+    return true;
+}
+
+bool FilterEffectRenderer::updateBackingStoreRect(const FloatRect& filterRect)
+{
+    if (!filterRect.isZero() && isFilterSizeValid(filterRect)) {
+        FloatRect currentSourceRect = sourceImageRect();
+        if (filterRect != currentSourceRect) {
+            setSourceImageRect(filterRect);
+            return true;
+        }
+    }
+    return false;
+}
+
+void FilterEffectRenderer::allocateBackingStoreIfNeeded()
+{
+    // At this point the effect chain has been built, and the
+    // source image sizes set. We just need to attach the graphic
+    // buffer if we have not yet done so.
+    if (!m_graphicsBufferAttached) {
+        IntSize logicalSize(m_sourceDrawingRegion.width(), m_sourceDrawingRegion.height());
+        if (!sourceImage() || sourceImage()->logicalSize() != logicalSize)
+            setSourceImage(ImageBuffer::create(logicalSize, 1, ColorSpaceDeviceRGB, renderingMode()));
+        m_graphicsBufferAttached = true;
+    }
+}
+
+void FilterEffectRenderer::clearIntermediateResults()
+{
+    m_sourceGraphic->clearResult();
+    for (size_t i = 0; i < m_effects.size(); ++i)
+        m_effects[i]->clearResult();
+}
+
+void FilterEffectRenderer::apply()
+{
+    RefPtr<FilterEffect> effect = lastEffect();
+    effect->apply();
+    effect->transformResultColorSpace(ColorSpaceDeviceRGB);
+}
+
+LayoutRect FilterEffectRenderer::computeSourceImageRectForDirtyRect(const LayoutRect& filterBoxRect, const LayoutRect& dirtyRect)
+{
+    if (hasCustomShaderFilter()) {
+        // When we have at least a custom shader in the chain, we need to compute the whole source image, because the shader can
+        // reference any pixel and we cannot control that.
+        return filterBoxRect;
+    }
+    // The result of this function is the area in the "filterBoxRect" that needs to be repainted, so that we fully cover the "dirtyRect".
+    LayoutRect rectForRepaint = dirtyRect;
+    if (hasFilterThatMovesPixels()) {
+        // Note that the outsets are reversed here because we are going backwards -> we have the dirty rect and
+        // need to find out what is the rectangle that might influence the result inside that dirty rect.
+        rectForRepaint.move(-m_outsets.right(), -m_outsets.bottom());
+        rectForRepaint.expand(m_outsets.left() + m_outsets.right(), m_outsets.top() + m_outsets.bottom());
+    }
+    rectForRepaint.intersect(filterBoxRect);
+    return rectForRepaint;
+}
+
+bool FilterEffectRendererHelper::prepareFilterEffect(RenderLayer* renderLayer, const LayoutRect& filterBoxRect, const LayoutRect& dirtyRect, const LayoutRect& layerRepaintRect)
+{
+    ASSERT(m_haveFilterEffect && renderLayer->filterRenderer());
+    m_renderLayer = renderLayer;
+    m_repaintRect = dirtyRect;
+
+    FilterEffectRenderer* filter = renderLayer->filterRenderer();
+    LayoutRect filterSourceRect = filter->computeSourceImageRectForDirtyRect(filterBoxRect, dirtyRect);
+    m_paintOffset = filterSourceRect.location();
+
+    if (filterSourceRect.isEmpty()) {
+        // The dirty rect is not in view, just bail out.
+        m_haveFilterEffect = false;
+        return false;
+    }
+    
+    bool hasUpdatedBackingStore = filter->updateBackingStoreRect(filterSourceRect);
+    if (filter->hasFilterThatMovesPixels()) {
+        if (hasUpdatedBackingStore)
+            m_repaintRect = filterSourceRect;
+        else {
+            m_repaintRect.unite(layerRepaintRect);
+            m_repaintRect.intersect(filterSourceRect);
+        }
+    }
+    return true;
+}
+   
+GraphicsContext* FilterEffectRendererHelper::beginFilterEffect(GraphicsContext* oldContext)
+{
+    ASSERT(m_renderLayer);
+    
+    FilterEffectRenderer* filter = m_renderLayer->filterRenderer();
+    filter->allocateBackingStoreIfNeeded();
+    // Paint into the context that represents the SourceGraphic of the filter.
+    GraphicsContext* sourceGraphicsContext = filter->inputContext();
+    if (!sourceGraphicsContext || !isFilterSizeValid(filter->filterRegion())) {
+        // Disable the filters and continue.
+        m_haveFilterEffect = false;
+        return oldContext;
+    }
+    
+    m_savedGraphicsContext = oldContext;
+    
+    // Translate the context so that the contents of the layer is captuterd in the offscreen memory buffer.
+    sourceGraphicsContext->save();
+    sourceGraphicsContext->translate(-m_paintOffset.x(), -m_paintOffset.y());
+    sourceGraphicsContext->clearRect(m_repaintRect);
+    sourceGraphicsContext->clip(m_repaintRect);
+    
+    return sourceGraphicsContext;
+}
+
+GraphicsContext* FilterEffectRendererHelper::applyFilterEffect()
+{
+    ASSERT(m_haveFilterEffect && m_renderLayer->filterRenderer());
+    FilterEffectRenderer* filter = m_renderLayer->filterRenderer();
+    filter->inputContext()->restore();
+
+    filter->apply();
+    
+    // Get the filtered output and draw it in place.
+    LayoutRect destRect = filter->outputRect();
+    destRect.move(m_paintOffset.x(), m_paintOffset.y());
+    
+    m_savedGraphicsContext->drawImageBuffer(filter->output(), m_renderLayer->renderer()->style()->colorSpace(), pixelSnappedIntRect(destRect), CompositeSourceOver);
+    
+    filter->clearIntermediateResults();
+    
+    return m_savedGraphicsContext;
+}
+
+} // namespace WebCore
+
diff --git a/Source/core/rendering/FilterEffectRenderer.h b/Source/core/rendering/FilterEffectRenderer.h
new file mode 100644
index 0000000..89bfdee
--- /dev/null
+++ b/Source/core/rendering/FilterEffectRenderer.h
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2011 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 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 FilterEffectRenderer_h
+#define FilterEffectRenderer_h
+
+#include "core/platform/graphics/FloatRect.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/platform/graphics/ImageBuffer.h"
+#include "core/platform/graphics/IntRectExtent.h"
+#include "core/platform/graphics/LayoutRect.h"
+#include "core/platform/graphics/filters/Filter.h"
+#include "core/platform/graphics/filters/FilterEffect.h"
+#include "core/platform/graphics/filters/FilterOperations.h"
+#include "core/platform/graphics/filters/SourceGraphic.h"
+#include "core/svg/graphics/filters/SVGFilterBuilder.h"
+
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+typedef Vector<RefPtr<FilterEffect> > FilterEffectList;
+class CachedShader;
+class CustomFilterProgram;
+class Document;
+class GraphicsContext;
+class RenderLayer;
+class RenderObject;
+
+class FilterEffectRendererHelper {
+public:
+    FilterEffectRendererHelper(bool haveFilterEffect)
+        : m_savedGraphicsContext(0)
+        , m_renderLayer(0)
+        , m_haveFilterEffect(haveFilterEffect)
+    {
+    }
+    
+    bool haveFilterEffect() const { return m_haveFilterEffect; }
+    bool hasStartedFilterEffect() const { return m_savedGraphicsContext; }
+
+    bool prepareFilterEffect(RenderLayer*, const LayoutRect& filterBoxRect, const LayoutRect& dirtyRect, const LayoutRect& layerRepaintRect);
+    GraphicsContext* beginFilterEffect(GraphicsContext* oldContext);
+    GraphicsContext* applyFilterEffect();
+
+    const LayoutRect& repaintRect() const { return m_repaintRect; }
+private:
+    GraphicsContext* m_savedGraphicsContext;
+    RenderLayer* m_renderLayer;
+    LayoutPoint m_paintOffset;
+    LayoutRect m_repaintRect;
+    bool m_haveFilterEffect;
+};
+
+class FilterEffectRenderer : public Filter
+{
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    static PassRefPtr<FilterEffectRenderer> create()
+    {
+        return adoptRef(new FilterEffectRenderer());
+    }
+
+    virtual void setSourceImageRect(const FloatRect& sourceImageRect)
+    { 
+        m_sourceDrawingRegion = sourceImageRect;
+        setMaxEffectRects(sourceImageRect);
+        setFilterRegion(sourceImageRect);
+        m_graphicsBufferAttached = false;
+    }
+    virtual FloatRect sourceImageRect() const { return m_sourceDrawingRegion; }
+
+    virtual void setFilterRegion(const FloatRect& filterRegion) { m_filterRegion = filterRegion; }
+    virtual FloatRect filterRegion() const { return m_filterRegion; }
+
+    GraphicsContext* inputContext();
+    ImageBuffer* output() const { return lastEffect()->asImageBuffer(); }
+
+    bool build(RenderObject* renderer, const FilterOperations&);
+    PassRefPtr<FilterEffect> buildReferenceFilter(RenderObject* renderer, PassRefPtr<FilterEffect> previousEffect, ReferenceFilterOperation*);
+    bool updateBackingStoreRect(const FloatRect& filterRect);
+    void allocateBackingStoreIfNeeded();
+    void clearIntermediateResults();
+    void apply();
+    
+    IntRect outputRect() const { return lastEffect()->hasResult() ? lastEffect()->requestedRegionOfInputImageData(IntRect(m_filterRegion)) : IntRect(); }
+
+    bool hasFilterThatMovesPixels() const { return m_hasFilterThatMovesPixels; }
+    LayoutRect computeSourceImageRectForDirtyRect(const LayoutRect& filterBoxRect, const LayoutRect& dirtyRect);
+
+    bool hasCustomShaderFilter() const { return m_hasCustomShaderFilter; }
+private:
+    void setMaxEffectRects(const FloatRect& effectRect)
+    {
+        for (size_t i = 0; i < m_effects.size(); ++i) {
+            RefPtr<FilterEffect> effect = m_effects.at(i);
+            effect->setMaxEffectRect(effectRect);
+        }
+    }
+    PassRefPtr<FilterEffect> lastEffect() const
+    {
+        if (m_effects.size() > 0)
+            return m_effects.last();
+        return 0;
+    }
+
+    FilterEffectRenderer();
+    virtual ~FilterEffectRenderer();
+    
+    FloatRect m_sourceDrawingRegion;
+    FloatRect m_filterRegion;
+    
+    FilterEffectList m_effects;
+    RefPtr<SourceGraphic> m_sourceGraphic;
+    
+    IntRectExtent m_outsets;
+
+    bool m_graphicsBufferAttached;
+    bool m_hasFilterThatMovesPixels;
+    bool m_hasCustomShaderFilter;
+};
+
+} // namespace WebCore
+
+
+#endif // FilterEffectRenderer_h
diff --git a/Source/core/rendering/FixedTableLayout.cpp b/Source/core/rendering/FixedTableLayout.cpp
new file mode 100644
index 0000000..a8258da
--- /dev/null
+++ b/Source/core/rendering/FixedTableLayout.cpp
@@ -0,0 +1,321 @@
+/*
+ * Copyright (C) 2002 Lars Knoll (knoll@kde.org)
+ *           (C) 2002 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 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.
+ *
+ * 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 "core/rendering/FixedTableLayout.h"
+
+#include "core/platform/LayoutUnit.h"
+#include "core/rendering/RenderTable.h"
+#include "core/rendering/RenderTableCell.h"
+#include "core/rendering/RenderTableCol.h"
+#include "core/rendering/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()
+{
+    // FIXME: We might want to wait until we have all of the first row before computing for the first time.
+    int usedWidth = 0;
+
+    // iterate over all <col> elements
+    unsigned nEffCols = m_table->numEffCols();
+    m_width.resize(nEffCols);
+    m_width.fill(Length(Auto));
+
+    unsigned currentEffectiveColumn = 0;
+    for (RenderTableCol* col = m_table->firstColumn(); col; col = col->nextColumn()) {
+        // RenderTableCols don't have the concept of preferred logical width, but we need to clear their dirty bits
+        // so that if we call setPreferredWidthsDirty(true) on a col or one of its descendants, we'll mark it's
+        // ancestors as dirty.
+        col->clearPreferredLogicalWidthsDirtyBits();
+
+        // Width specified by column-groups that have column child does not affect column width in fixed layout tables
+        if (col->isTableColumnGroupWithColumnChildren())
+            continue;
+
+        Length colStyleLogicalWidth = col->style()->logicalWidth();
+        int effectiveColWidth = 0;
+        if (colStyleLogicalWidth.isFixed() && colStyleLogicalWidth.value() > 0)
+            effectiveColWidth = colStyleLogicalWidth.value();
+
+        unsigned span = col->span();
+        while (span) {
+            unsigned spanInCurrentEffectiveColumn;
+            if (currentEffectiveColumn >= nEffCols) {
+                m_table->appendColumn(span);
+                nEffCols++;
+                m_width.append(Length());
+                spanInCurrentEffectiveColumn = span;
+            } else {
+                if (span < m_table->spanOfEffCol(currentEffectiveColumn)) {
+                    m_table->splitColumn(currentEffectiveColumn, span);
+                    nEffCols++;
+                    m_width.append(Length());
+                }
+                spanInCurrentEffectiveColumn = m_table->spanOfEffCol(currentEffectiveColumn);
+            }
+            if ((colStyleLogicalWidth.isFixed() || colStyleLogicalWidth.isPercent()) && colStyleLogicalWidth.isPositive()) {
+                m_width[currentEffectiveColumn] = colStyleLogicalWidth;
+                m_width[currentEffectiveColumn] *= spanInCurrentEffectiveColumn;
+                usedWidth += effectiveColWidth * spanInCurrentEffectiveColumn;
+            }
+            span -= spanInCurrentEffectiveColumn;
+            currentEffectiveColumn++;
+        }
+    }
+
+    // Iterate over the first row in case some are unspecified.
+    RenderTableSection* section = m_table->topNonEmptySection();
+    if (!section)
+        return usedWidth;
+
+    unsigned currentColumn = 0;
+
+    RenderObject* firstRow = section->firstChild();
+    for (RenderObject* child = firstRow->firstChild(); child; child = child->nextSibling()) {
+        if (!child->isTableCell())
+            continue;
+
+        RenderTableCell* cell = toRenderTableCell(child);
+
+        Length logicalWidth = cell->styleOrColLogicalWidth();
+        unsigned span = cell->colSpan();
+        int fixedBorderBoxLogicalWidth = 0;
+        // FIXME: Support other length types. If the width is non-auto, it should probably just use
+        // RenderBox::computeLogicalWidthInRegionUsing to compute the width.
+        if (logicalWidth.isFixed() && logicalWidth.isPositive()) {
+            fixedBorderBoxLogicalWidth = cell->adjustBorderBoxLogicalWidthForBoxSizing(logicalWidth.value());
+            logicalWidth.setValue(fixedBorderBoxLogicalWidth);
+        }
+
+        unsigned usedSpan = 0;
+        while (usedSpan < span && currentColumn < nEffCols) {
+            float eSpan = m_table->spanOfEffCol(currentColumn);
+            // Only set if no col element has already set it.
+            if (m_width[currentColumn].isAuto() && logicalWidth.type() != Auto) {
+                m_width[currentColumn] = logicalWidth;
+                m_width[currentColumn] *= eSpan / span;
+                usedWidth += fixedBorderBoxLogicalWidth * eSpan / span;
+            }
+            usedSpan += eSpan;
+            ++currentColumn;
+        }
+
+        // FixedTableLayout doesn't use min/maxPreferredLogicalWidths, but we need to clear the
+        // dirty bit on the cell so that we'll correctly mark its ancestors dirty
+        // in case we later call setPreferredLogicalWidthsDirty(true) on it later.
+        if (cell->preferredLogicalWidthsDirty())
+            cell->setPreferredLogicalWidthsDirty(false);
+    }
+
+    return usedWidth;
+}
+
+void FixedTableLayout::computeIntrinsicLogicalWidths(LayoutUnit& minWidth, LayoutUnit& maxWidth)
+{
+    minWidth = maxWidth = calcWidthArray();
+}
+
+void FixedTableLayout::applyPreferredLogicalWidthQuirks(LayoutUnit& minWidth, LayoutUnit& maxWidth) const
+{
+    Length tableLogicalWidth = m_table->style()->logicalWidth();
+    if (tableLogicalWidth.isFixed() && tableLogicalWidth.isPositive())
+        minWidth = maxWidth = max<int>(minWidth, tableLogicalWidth.value() - m_table->bordersPaddingAndSpacingInRowDirection());
+
+    /*
+        <table style="width:100%; background-color:red"><tr><td>
+            <table style="background-color:blue"><tr><td>
+                <table style="width:100%; background-color:green; table-layout:fixed"><tr><td>
+                    Content
+                </td></tr></table>
+            </td></tr></table>
+        </td></tr></table>
+    */ 
+    // In this example, the two inner tables should be as large as the outer table. 
+    // We can achieve this effect by making the maxwidth of fixed tables with percentage
+    // widths be infinite.
+    if (m_table->style()->logicalWidth().isPercent() && maxWidth < tableMaxWidth)
+        maxWidth = tableMaxWidth;
+}
+
+void FixedTableLayout::layout()
+{
+    int tableLogicalWidth = m_table->logicalWidth() - m_table->bordersPaddingAndSpacingInRowDirection();
+    unsigned nEffCols = m_table->numEffCols();
+
+    // FIXME: It is possible to be called without having properly updated our internal representation.
+    // This means that our preferred logical widths were not recomputed as expected.
+    if (nEffCols != m_width.size()) {
+        calcWidthArray();
+        // FIXME: Table layout shouldn't modify our table structure (but does due to columns and column-groups).
+        nEffCols = m_table->numEffCols();
+    }
+
+    Vector<int> calcWidth(nEffCols, 0);
+
+    unsigned numAuto = 0;
+    unsigned autoSpan = 0;
+    int totalFixedWidth = 0;
+    int totalPercentWidth = 0;
+    float totalPercent = 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 (unsigned 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] = valueForLength(m_width[i], tableLogicalWidth);
+            totalPercentWidth += calcWidth[i];
+            totalPercent += m_width[i].percent();
+        } else if (m_width[i].isAuto()) {
+            numAuto++;
+            autoSpan += m_table->spanOfEffCol(i);
+        }
+    }
+
+    int hspacing = m_table->hBorderSpacing();
+    int totalWidth = totalFixedWidth + totalPercentWidth;
+    if (!numAuto || totalWidth > tableLogicalWidth) {
+        // 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 != tableLogicalWidth) {
+            // Fixed widths only scale up
+            if (totalFixedWidth && totalWidth < tableLogicalWidth) {
+                totalFixedWidth = 0;
+                for (unsigned i = 0; i < nEffCols; i++) {
+                    if (m_width[i].isFixed()) {
+                        calcWidth[i] = calcWidth[i] * tableLogicalWidth / totalWidth;
+                        totalFixedWidth += calcWidth[i];
+                    }
+                }
+            }
+            if (totalPercent) {
+                totalPercentWidth = 0;
+                for (unsigned i = 0; i < nEffCols; i++) {
+                    if (m_width[i].isPercent()) {
+                        calcWidth[i] = m_width[i].percent() * (tableLogicalWidth - totalFixedWidth) / totalPercent;
+                        totalPercentWidth += calcWidth[i];
+                    }
+                }
+            }
+            totalWidth = totalFixedWidth + totalPercentWidth;
+        }
+    } else {
+        // Divide the remaining width among the auto columns.
+        ASSERT(autoSpan >= numAuto);
+        int remainingWidth = tableLogicalWidth - totalFixedWidth - totalPercentWidth - hspacing * (autoSpan - numAuto);
+        int lastAuto = 0;
+        for (unsigned i = 0; i < nEffCols; i++) {
+            if (m_width[i].isAuto()) {
+                unsigned span = m_table->spanOfEffCol(i);
+                int w = remainingWidth * span / autoSpan;
+                calcWidth[i] = w + hspacing * (span - 1);
+                remainingWidth -= w;
+                if (!remainingWidth)
+                    break;
+                lastAuto = i;
+                numAuto--;
+                ASSERT(autoSpan >= span);
+                autoSpan -= span;
+            }
+        }
+        // Last one gets the remainder.
+        if (remainingWidth)
+            calcWidth[lastAuto] += remainingWidth;
+        totalWidth = tableLogicalWidth;
+    }
+
+    if (totalWidth < tableLogicalWidth) {
+        // Spread extra space over columns.
+        int remainingWidth = tableLogicalWidth - 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 (unsigned i = 0; i < nEffCols; i++) {
+        m_table->setColumnPosition(i, pos);
+        pos += calcWidth[i] + hspacing;
+    }
+    int colPositionsSize = m_table->columnPositions().size();
+    if (colPositionsSize > 0)
+        m_table->setColumnPosition(colPositionsSize - 1, pos);
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/FixedTableLayout.h b/Source/core/rendering/FixedTableLayout.h
new file mode 100644
index 0000000..886d098
--- /dev/null
+++ b/Source/core/rendering/FixedTableLayout.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2002 Lars Knoll (knoll@kde.org)
+ *           (C) 2002 Dirk Mueller (mueller@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef FixedTableLayout_h
+#define FixedTableLayout_h
+
+#include "core/platform/Length.h"
+#include "core/rendering/TableLayout.h"
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class RenderTable;
+
+class FixedTableLayout : public TableLayout {
+public:
+    FixedTableLayout(RenderTable*);
+
+    virtual void computeIntrinsicLogicalWidths(LayoutUnit& minWidth, LayoutUnit& maxWidth) OVERRIDE;
+    virtual void applyPreferredLogicalWidthQuirks(LayoutUnit& minWidth, LayoutUnit& maxWidth) const OVERRIDE;
+    virtual void layout();
+
+private:
+    int calcWidthArray();
+
+    Vector<Length> m_width;
+};
+
+} // namespace WebCore
+
+#endif // FixedTableLayout_h
diff --git a/Source/core/rendering/FlowThreadController.cpp b/Source/core/rendering/FlowThreadController.cpp
new file mode 100644
index 0000000..0970518
--- /dev/null
+++ b/Source/core/rendering/FlowThreadController.cpp
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2012 Adobe Systems Incorporated. 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 THE COPYRIGHT HOLDER "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 THE COPYRIGHT HOLDER 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 "core/rendering/FlowThreadController.h"
+
+#include "core/dom/NamedFlowCollection.h"
+#include "core/rendering/RenderFlowThread.h"
+#include "core/rendering/RenderNamedFlowThread.h"
+#include "core/rendering/style/StyleInheritedData.h"
+#include <wtf/text/AtomicString.h>
+
+namespace WebCore {
+
+PassOwnPtr<FlowThreadController> FlowThreadController::create(RenderView* view)
+{
+    return adoptPtr(new FlowThreadController(view));
+}
+
+FlowThreadController::FlowThreadController(RenderView* view)
+    : m_view(view)
+    , m_currentRenderFlowThread(0)
+    , m_isRenderNamedFlowThreadOrderDirty(false)
+    , m_flowThreadsWithAutoLogicalHeightRegions(0)
+{
+}
+
+FlowThreadController::~FlowThreadController()
+{
+}
+
+RenderNamedFlowThread* FlowThreadController::ensureRenderFlowThreadWithName(const AtomicString& name)
+{
+    if (!m_renderNamedFlowThreadList)
+        m_renderNamedFlowThreadList = adoptPtr(new RenderNamedFlowThreadList());
+    else {
+        for (RenderNamedFlowThreadList::iterator iter = m_renderNamedFlowThreadList->begin(); iter != m_renderNamedFlowThreadList->end(); ++iter) {
+            RenderNamedFlowThread* flowRenderer = *iter;
+            if (flowRenderer->flowThreadName() == name)
+                return flowRenderer;
+        }
+    }
+
+    NamedFlowCollection* namedFlows = m_view->document()->namedFlows();
+
+    // Sanity check for the absence of a named flow in the "CREATED" state with the same name.
+    ASSERT(!namedFlows->flowByName(name));
+
+    RenderNamedFlowThread* flowRenderer = RenderNamedFlowThread::createAnonymous(m_view->document(), namedFlows->ensureFlowWithName(name));
+    flowRenderer->setStyle(RenderFlowThread::createFlowThreadStyle(m_view->style()));
+    m_renderNamedFlowThreadList->add(flowRenderer);
+
+    // Keep the flow renderer as a child of RenderView.
+    m_view->addChild(flowRenderer);
+
+    setIsRenderNamedFlowThreadOrderDirty(true);
+
+    return flowRenderer;
+}
+
+void FlowThreadController::styleDidChange()
+{
+    RenderStyle* viewStyle = m_view->style();
+    for (RenderNamedFlowThreadList::iterator iter = m_renderNamedFlowThreadList->begin(); iter != m_renderNamedFlowThreadList->end(); ++iter) {
+        RenderNamedFlowThread* flowRenderer = *iter;
+        flowRenderer->setStyle(RenderFlowThread::createFlowThreadStyle(viewStyle));
+    }
+}
+
+void FlowThreadController::layoutRenderNamedFlowThreads()
+{
+    updateFlowThreadsChainIfNecessary();
+
+    for (RenderNamedFlowThreadList::iterator iter = m_renderNamedFlowThreadList->begin(); iter != m_renderNamedFlowThreadList->end(); ++iter) {
+        RenderNamedFlowThread* flowRenderer = *iter;
+        flowRenderer->layoutIfNeeded();
+    }
+}
+
+void FlowThreadController::registerNamedFlowContentNode(Node* contentNode, RenderNamedFlowThread* namedFlow)
+{
+    ASSERT(contentNode && contentNode->isElementNode());
+    ASSERT(namedFlow);
+    ASSERT(!m_mapNamedFlowContentNodes.contains(contentNode));
+    ASSERT(!namedFlow->hasContentNode(contentNode));
+    m_mapNamedFlowContentNodes.add(contentNode, namedFlow);
+    namedFlow->registerNamedFlowContentNode(contentNode);
+}
+
+void FlowThreadController::unregisterNamedFlowContentNode(Node* contentNode)
+{
+    ASSERT(contentNode && contentNode->isElementNode());
+    HashMap<Node*, RenderNamedFlowThread*>::iterator it = m_mapNamedFlowContentNodes.find(contentNode);
+    ASSERT(it != m_mapNamedFlowContentNodes.end());
+    ASSERT(it->value);
+    ASSERT(it->value->hasContentNode(contentNode));
+    it->value->unregisterNamedFlowContentNode(contentNode);
+    m_mapNamedFlowContentNodes.remove(contentNode);
+}
+
+void FlowThreadController::updateFlowThreadsChainIfNecessary()
+{
+    ASSERT(m_renderNamedFlowThreadList);
+    ASSERT(isAutoLogicalHeightRegionsCountConsistent());
+
+    // Remove the left-over flow threads.
+    RenderNamedFlowThreadList toRemoveList;
+    for (RenderNamedFlowThreadList::iterator iter = m_renderNamedFlowThreadList->begin(); iter != m_renderNamedFlowThreadList->end(); ++iter) {
+        RenderNamedFlowThread* flowRenderer = *iter;
+        if (flowRenderer->isMarkedForDestruction())
+            toRemoveList.add(flowRenderer);
+    }
+
+    if (toRemoveList.size() > 0)
+        setIsRenderNamedFlowThreadOrderDirty(true);
+
+    for (RenderNamedFlowThreadList::iterator iter = toRemoveList.begin(); iter != toRemoveList.end(); ++iter) {
+        RenderNamedFlowThread* flowRenderer = *iter;
+        m_renderNamedFlowThreadList->remove(flowRenderer);
+        flowRenderer->destroy();
+    }
+
+    if (isRenderNamedFlowThreadOrderDirty()) {
+        // Arrange the thread list according to dependencies.
+        RenderNamedFlowThreadList sortedList;
+        for (RenderNamedFlowThreadList::iterator iter = m_renderNamedFlowThreadList->begin(); iter != m_renderNamedFlowThreadList->end(); ++iter) {
+            RenderNamedFlowThread* flowRenderer = *iter;
+            if (sortedList.contains(flowRenderer))
+                continue;
+            flowRenderer->pushDependencies(sortedList);
+            sortedList.add(flowRenderer);
+        }
+        m_renderNamedFlowThreadList->swap(sortedList);
+        setIsRenderNamedFlowThreadOrderDirty(false);
+    }
+}
+
+bool FlowThreadController::updateFlowThreadsNeedingLayout()
+{
+    bool needsTwoPassLayout = false;
+
+    for (RenderNamedFlowThreadList::iterator iter = m_renderNamedFlowThreadList->begin(); iter != m_renderNamedFlowThreadList->end(); ++iter) {
+        RenderNamedFlowThread* flowRenderer = *iter;
+        ASSERT(!flowRenderer->needsTwoPhasesLayout());
+        flowRenderer->setInConstrainedLayoutPhase(false);
+        if (flowRenderer->needsLayout() && flowRenderer->hasAutoLogicalHeightRegions())
+            needsTwoPassLayout = true;
+    }
+
+    if (needsTwoPassLayout)
+        resetFlowThreadsWithAutoHeightRegions();
+
+    return needsTwoPassLayout;
+}
+
+bool FlowThreadController::updateFlowThreadsNeedingTwoStepLayout()
+{
+    bool needsTwoPassLayout = false;
+
+    for (RenderNamedFlowThreadList::iterator iter = m_renderNamedFlowThreadList->begin(); iter != m_renderNamedFlowThreadList->end(); ++iter) {
+        RenderNamedFlowThread* flowRenderer = *iter;
+        if (flowRenderer->needsTwoPhasesLayout()) {
+            needsTwoPassLayout = true;
+            break;
+        }
+    }
+
+    if (needsTwoPassLayout)
+        resetFlowThreadsWithAutoHeightRegions();
+
+    return needsTwoPassLayout;
+}
+
+void FlowThreadController::resetFlowThreadsWithAutoHeightRegions()
+{
+    for (RenderNamedFlowThreadList::iterator iter = m_renderNamedFlowThreadList->begin(); iter != m_renderNamedFlowThreadList->end(); ++iter) {
+        RenderNamedFlowThread* flowRenderer = *iter;
+        if (flowRenderer->hasAutoLogicalHeightRegions()) {
+            flowRenderer->markAutoLogicalHeightRegionsForLayout();
+            flowRenderer->invalidateRegions();
+        }
+    }
+}
+
+void FlowThreadController::updateFlowThreadsIntoConstrainedPhase()
+{
+    // Walk the flow chain in reverse order to update the auto-height regions and compute correct sizes for the containing regions. Only after this we can
+    // set the flow in the constrained layout phase.
+    for (RenderNamedFlowThreadList::reverse_iterator iter = m_renderNamedFlowThreadList->rbegin(); iter != m_renderNamedFlowThreadList->rend(); ++iter) {
+        RenderNamedFlowThread* flowRenderer = *iter;
+        ASSERT(!flowRenderer->hasRegions() || flowRenderer->hasValidRegionInfo());
+        flowRenderer->layoutIfNeeded();
+        if (flowRenderer->hasAutoLogicalHeightRegions()) {
+            ASSERT(flowRenderer->needsTwoPhasesLayout());
+            flowRenderer->markAutoLogicalHeightRegionsForLayout();
+        }
+        flowRenderer->setInConstrainedLayoutPhase(true);
+        flowRenderer->clearNeedsTwoPhasesLayout();
+    }
+}
+
+#ifndef NDEBUG
+bool FlowThreadController::isAutoLogicalHeightRegionsCountConsistent() const
+{
+    if (!hasRenderNamedFlowThreads())
+        return !hasFlowThreadsWithAutoLogicalHeightRegions();
+
+    for (RenderNamedFlowThreadList::iterator iter = m_renderNamedFlowThreadList->begin(); iter != m_renderNamedFlowThreadList->end(); ++iter) {
+        if (!(*iter)->isAutoLogicalHeightRegionsCountConsistent())
+            return false;
+    }
+
+    return true;
+}
+#endif
+
+} // namespace WebCore
diff --git a/Source/core/rendering/FlowThreadController.h b/Source/core/rendering/FlowThreadController.h
new file mode 100644
index 0000000..c0b6a1b
--- /dev/null
+++ b/Source/core/rendering/FlowThreadController.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2012 Adobe Systems Incorporated. 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 THE COPYRIGHT HOLDER "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 THE COPYRIGHT HOLDER 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 FlowThreadController_h
+#define FlowThreadController_h
+
+#include "core/rendering/RenderView.h"
+#include <wtf/ListHashSet.h>
+#include <wtf/OwnPtr.h>
+
+namespace WebCore {
+
+class RenderFlowThread;
+class RenderNamedFlowThread;
+
+typedef ListHashSet<RenderNamedFlowThread*> RenderNamedFlowThreadList;
+
+class FlowThreadController {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    static PassOwnPtr<FlowThreadController> create(RenderView*);
+    ~FlowThreadController();
+
+    RenderFlowThread* currentRenderFlowThread() const { return m_currentRenderFlowThread; }
+    void setCurrentRenderFlowThread(RenderFlowThread* flowThread) { m_currentRenderFlowThread = flowThread; }
+
+    bool isRenderNamedFlowThreadOrderDirty() const { return m_isRenderNamedFlowThreadOrderDirty; }
+    void setIsRenderNamedFlowThreadOrderDirty(bool dirty)
+    {
+        m_isRenderNamedFlowThreadOrderDirty = dirty;
+        if (dirty)
+            m_view->setNeedsLayout(true);
+    }
+
+    RenderNamedFlowThread* ensureRenderFlowThreadWithName(const AtomicString&);
+    const RenderNamedFlowThreadList* renderNamedFlowThreadList() const { return m_renderNamedFlowThreadList.get(); }
+    bool hasRenderNamedFlowThreads() const { return m_renderNamedFlowThreadList && !m_renderNamedFlowThreadList->isEmpty(); }
+    void layoutRenderNamedFlowThreads();
+    void styleDidChange();
+
+    void registerNamedFlowContentNode(Node*, RenderNamedFlowThread*);
+    void unregisterNamedFlowContentNode(Node*);
+
+    bool hasFlowThreadsWithAutoLogicalHeightRegions() const { return m_flowThreadsWithAutoLogicalHeightRegions; }
+    void incrementFlowThreadsWithAutoLogicalHeightRegions() { ++m_flowThreadsWithAutoLogicalHeightRegions; }
+    void decrementFlowThreadsWithAutoLogicalHeightRegions() { ASSERT(m_flowThreadsWithAutoLogicalHeightRegions > 0); --m_flowThreadsWithAutoLogicalHeightRegions; }
+
+    bool updateFlowThreadsNeedingLayout();
+    bool updateFlowThreadsNeedingTwoStepLayout();
+    void updateFlowThreadsIntoConstrainedPhase();
+
+#ifndef NDEBUG
+    bool isAutoLogicalHeightRegionsCountConsistent() const;
+#endif
+
+protected:
+    FlowThreadController(RenderView*);
+    void updateFlowThreadsChainIfNecessary();
+    void resetFlowThreadsWithAutoHeightRegions();
+
+private:
+    RenderView* m_view;
+    RenderFlowThread* m_currentRenderFlowThread;
+    bool m_isRenderNamedFlowThreadOrderDirty;
+    unsigned m_flowThreadsWithAutoLogicalHeightRegions;
+    OwnPtr<RenderNamedFlowThreadList> m_renderNamedFlowThreadList;
+    // maps a content node to its render flow thread.
+    HashMap<Node*, RenderNamedFlowThread*> m_mapNamedFlowContentNodes;
+};
+
+}
+
+#endif
diff --git a/Source/core/rendering/GapRects.h b/Source/core/rendering/GapRects.h
new file mode 100644
index 0000000..515d4a6
--- /dev/null
+++ b/Source/core/rendering/GapRects.h
@@ -0,0 +1,62 @@
+/*
+    Copyright (C) 2005, 2006 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.
+
+
+    Some useful definitions needed for laying out elements
+*/
+
+#ifndef GapRects_h
+#define GapRects_h
+
+#include "core/platform/graphics/LayoutRect.h"
+
+namespace WebCore {
+
+    struct GapRects {
+        const LayoutRect& left() const { return m_left; }
+        const LayoutRect& center() const { return m_center; }
+        const LayoutRect& right() const { return m_right; }
+        
+        void uniteLeft(const LayoutRect& r) { m_left.unite(r); }
+        void uniteCenter(const LayoutRect& r) { m_center.unite(r); }
+        void uniteRight(const LayoutRect& r) { m_right.unite(r); }
+        void unite(const GapRects& o) { uniteLeft(o.left()); uniteCenter(o.center()); uniteRight(o.right()); }
+
+        operator LayoutRect() const
+        {
+            LayoutRect 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:
+        LayoutRect m_left;
+        LayoutRect m_center;
+        LayoutRect m_right;
+    };
+
+} // namespace WebCore
+
+#endif // GapRects_h
diff --git a/Source/core/rendering/HitTestLocation.cpp b/Source/core/rendering/HitTestLocation.cpp
new file mode 100644
index 0000000..47f956c
--- /dev/null
+++ b/Source/core/rendering/HitTestLocation.cpp
@@ -0,0 +1,201 @@
+/*
+ * Copyright (C) 2006, 2008, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2012 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 "core/rendering/HitTestLocation.h"
+
+#include "HTMLNames.h"
+#include "core/dom/DocumentMarkerController.h"
+#include "core/editing/FrameSelection.h"
+#include "core/html/HTMLAnchorElement.h"
+#include "core/html/HTMLImageElement.h"
+#include "core/html/HTMLInputElement.h"
+#include "core/html/HTMLMediaElement.h"
+#include "core/html/HTMLPlugInImageElement.h"
+#include "core/html/HTMLVideoElement.h"
+#include "core/html/parser/HTMLParserIdioms.h"
+#include "core/loader/cache/CachedImage.h"
+#include "core/page/Frame.h"
+#include "core/page/FrameTree.h"
+#include "core/platform/Scrollbar.h"
+#include "core/rendering/RenderBlock.h"
+#include "core/rendering/RenderImage.h"
+#include "core/rendering/RenderInline.h"
+
+#if ENABLE(SVG)
+#include "SVGNames.h"
+#include "XLinkNames.h"
+#endif
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+HitTestLocation::HitTestLocation()
+    : m_region(0)
+    , m_isRectBased(false)
+    , m_isRectilinear(true)
+{
+}
+
+HitTestLocation::HitTestLocation(const LayoutPoint& point)
+    : m_point(point)
+    , m_boundingBox(rectForPoint(point, 0, 0, 0, 0))
+    , m_transformedPoint(point)
+    , m_transformedRect(m_boundingBox)
+    , m_region(0)
+    , m_isRectBased(false)
+    , m_isRectilinear(true)
+{
+}
+
+HitTestLocation::HitTestLocation(const FloatPoint& point)
+    : m_point(flooredLayoutPoint(point))
+    , m_boundingBox(rectForPoint(m_point, 0, 0, 0, 0))
+    , m_transformedPoint(point)
+    , m_transformedRect(m_boundingBox)
+    , m_region(0)
+    , m_isRectBased(false)
+    , m_isRectilinear(true)
+{
+}
+
+HitTestLocation::HitTestLocation(const FloatPoint& point, const FloatQuad& quad)
+    : m_transformedPoint(point)
+    , m_transformedRect(quad)
+    , m_region(0)
+    , m_isRectBased(true)
+{
+    m_point = flooredLayoutPoint(point);
+    m_boundingBox = enclosingIntRect(quad.boundingBox());
+    m_isRectilinear = quad.isRectilinear();
+}
+
+HitTestLocation::HitTestLocation(const LayoutPoint& centerPoint, unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding)
+    : m_point(centerPoint)
+    , m_boundingBox(rectForPoint(centerPoint, topPadding, rightPadding, bottomPadding, leftPadding))
+    , m_transformedPoint(centerPoint)
+    , m_region(0)
+    , m_isRectBased(topPadding || rightPadding || bottomPadding || leftPadding)
+    , m_isRectilinear(true)
+{
+    m_transformedRect = FloatQuad(m_boundingBox);
+}
+
+HitTestLocation::HitTestLocation(const HitTestLocation& other, const LayoutSize& offset, RenderRegion* region)
+    : m_point(other.m_point)
+    , m_boundingBox(other.m_boundingBox)
+    , m_transformedPoint(other.m_transformedPoint)
+    , m_transformedRect(other.m_transformedRect)
+    , m_region(region ? region : other.m_region)
+    , m_isRectBased(other.m_isRectBased)
+    , m_isRectilinear(other.m_isRectilinear)
+{
+    move(offset);
+}
+
+HitTestLocation::HitTestLocation(const HitTestLocation& other)
+    : m_point(other.m_point)
+    , m_boundingBox(other.m_boundingBox)
+    , m_transformedPoint(other.m_transformedPoint)
+    , m_transformedRect(other.m_transformedRect)
+    , m_region(other.m_region)
+    , m_isRectBased(other.m_isRectBased)
+    , m_isRectilinear(other.m_isRectilinear)
+{
+}
+
+HitTestLocation::~HitTestLocation()
+{
+}
+
+HitTestLocation& HitTestLocation::operator=(const HitTestLocation& other)
+{
+    m_point = other.m_point;
+    m_boundingBox = other.m_boundingBox;
+    m_transformedPoint = other.m_transformedPoint;
+    m_transformedRect = other.m_transformedRect;
+    m_region = other.m_region;
+    m_isRectBased = other.m_isRectBased;
+    m_isRectilinear = other.m_isRectilinear;
+
+    return *this;
+}
+
+void HitTestLocation::move(const LayoutSize& offset)
+{
+    m_point.move(offset);
+    m_transformedPoint.move(offset);
+    m_transformedRect.move(offset);
+    m_boundingBox = enclosingIntRect(m_transformedRect.boundingBox());
+}
+
+template<typename RectType>
+bool HitTestLocation::intersectsRect(const RectType& rect) const
+{
+    // FIXME: When the hit test is not rect based we should use rect.contains(m_point).
+    // That does change some corner case tests though.
+
+    // First check if rect even intersects our bounding box.
+    if (!rect.intersects(m_boundingBox))
+        return false;
+
+    // If the transformed rect is rectilinear the bounding box intersection was accurate.
+    if (m_isRectilinear)
+        return true;
+
+    // If rect fully contains our bounding box, we are also sure of an intersection.
+    if (rect.contains(m_boundingBox))
+        return true;
+
+    // Otherwise we need to do a slower quad based intersection test.
+    return m_transformedRect.intersectsRect(rect);
+}
+
+bool HitTestLocation::intersects(const LayoutRect& rect) const
+{
+    return intersectsRect(rect);
+}
+
+bool HitTestLocation::intersects(const FloatRect& rect) const
+{
+    return intersectsRect(rect);
+}
+
+bool HitTestLocation::intersects(const RoundedRect& rect) const
+{
+    return rect.intersectsQuad(m_transformedRect);
+}
+
+IntRect HitTestLocation::rectForPoint(const LayoutPoint& point, unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding)
+{
+    IntPoint actualPoint(flooredIntPoint(point));
+    actualPoint -= IntSize(leftPadding, topPadding);
+
+    IntSize actualPadding(leftPadding + rightPadding, topPadding + bottomPadding);
+    // As IntRect is left inclusive and right exclusive (seeing IntRect::contains(x, y)), adding "1".
+    // FIXME: Remove this once non-rect based hit-detection stops using IntRect:intersects.
+    actualPadding += IntSize(1, 1);
+
+    return IntRect(actualPoint, actualPadding);
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/HitTestLocation.h b/Source/core/rendering/HitTestLocation.h
new file mode 100644
index 0000000..1e64663
--- /dev/null
+++ b/Source/core/rendering/HitTestLocation.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2012 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 HitTestLocation_h
+#define HitTestLocation_h
+
+#include "core/platform/graphics/FloatQuad.h"
+#include "core/platform/graphics/FloatRect.h"
+#include "core/platform/graphics/LayoutRect.h"
+#include "core/platform/graphics/RoundedRect.h"
+#include "core/platform/text/TextDirection.h"
+#include "core/rendering/HitTestRequest.h"
+#include <wtf/Forward.h>
+#include <wtf/ListHashSet.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class Element;
+class Frame;
+class Image;
+class KURL;
+class Node;
+class RenderRegion;
+class Scrollbar;
+
+class HitTestLocation {
+public:
+
+    HitTestLocation();
+    HitTestLocation(const LayoutPoint&);
+    HitTestLocation(const FloatPoint&);
+    HitTestLocation(const FloatPoint&, const FloatQuad&);
+    // Pass non-zero padding values to perform a rect-based hit test.
+    HitTestLocation(const LayoutPoint& centerPoint, unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding);
+    // Make a copy the HitTestLocation in a new region by applying given offset to internal point and area.
+    HitTestLocation(const HitTestLocation&, const LayoutSize& offset, RenderRegion* = 0);
+    HitTestLocation(const HitTestLocation&);
+    ~HitTestLocation();
+    HitTestLocation& operator=(const HitTestLocation&);
+
+    const LayoutPoint& point() const { return m_point; }
+    IntPoint roundedPoint() const { return roundedIntPoint(m_point); }
+
+    RenderRegion* region() const { return m_region; }
+
+    // Rect-based hit test related methods.
+    bool isRectBasedTest() const { return m_isRectBased; }
+    bool isRectilinear() const { return m_isRectilinear; }
+    IntRect boundingBox() const { return m_boundingBox; }
+
+    static IntRect rectForPoint(const LayoutPoint&, unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding);
+    int topPadding() const { return roundedPoint().y() - m_boundingBox.y(); }
+    int rightPadding() const { return m_boundingBox.maxX() - roundedPoint().x() - 1; }
+    int bottomPadding() const { return m_boundingBox.maxY() - roundedPoint().y() - 1; }
+    int leftPadding() const { return roundedPoint().x() - m_boundingBox.x(); }
+
+    bool intersects(const LayoutRect&) const;
+    bool intersects(const FloatRect&) const;
+    bool intersects(const RoundedRect&) const;
+
+    const FloatPoint& transformedPoint() const { return m_transformedPoint; }
+    const FloatQuad& transformedRect() const { return m_transformedRect; }
+
+private:
+    template<typename RectType>
+    bool intersectsRect(const RectType&) const;
+    void move(const LayoutSize& offset);
+
+    // This is cached forms of the more accurate point and area below.
+    LayoutPoint m_point;
+    IntRect m_boundingBox;
+
+    FloatPoint m_transformedPoint;
+    FloatQuad m_transformedRect;
+
+    RenderRegion* m_region; // The region we're inside.
+
+    bool m_isRectBased;
+    bool m_isRectilinear;
+};
+
+} // namespace WebCore
+
+#endif // HitTestLocation_h
diff --git a/Source/core/rendering/HitTestRequest.h b/Source/core/rendering/HitTestRequest.h
new file mode 100644
index 0000000..1166fe3
--- /dev/null
+++ b/Source/core/rendering/HitTestRequest.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2009 Torch Mobile Inc. http://www.torchmobile.com/
+ * Copyright (C) 2012 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 HitTestRequest_h
+#define HitTestRequest_h
+
+namespace WebCore {
+
+class HitTestRequest {
+public:
+    enum RequestType {
+        ReadOnly = 1 << 1,
+        Active = 1 << 2,
+        Move = 1 << 3,
+        Release = 1 << 4,
+        IgnoreClipping = 1 << 5,
+        SVGClipContent = 1 << 6,
+        TouchEvent = 1 << 7,
+        DisallowShadowContent = 1 << 8,
+        AllowFrameScrollbars = 1 << 9,
+        AllowChildFrameContent = 1 << 10,
+        ChildFrameHitTest = 1 << 11,
+        IgnorePointerEventsNone = 1 << 12
+    };
+
+    typedef unsigned HitTestRequestType;
+
+    HitTestRequest(HitTestRequestType requestType)
+        : m_requestType(requestType)
+    {
+    }
+
+    bool readOnly() const { return m_requestType & ReadOnly; }
+    bool active() const { return m_requestType & Active; }
+    bool move() const { return m_requestType & Move; }
+    bool release() const { return m_requestType & Release; }
+    bool ignoreClipping() const { return m_requestType & IgnoreClipping; }
+    bool svgClipContent() const { return m_requestType & SVGClipContent; }
+    bool touchEvent() const { return m_requestType & TouchEvent; }
+    bool mouseEvent() const { return !touchEvent(); }
+    bool disallowsShadowContent() const { return m_requestType & DisallowShadowContent; }
+    bool allowsFrameScrollbars() const { return m_requestType & AllowFrameScrollbars; }
+    bool allowsChildFrameContent() const { return m_requestType & AllowChildFrameContent; }
+    bool isChildFrameHitTest() const { return m_requestType & ChildFrameHitTest; }
+    bool ignorePointerEventsNone() const { return m_requestType & IgnorePointerEventsNone; }
+
+    // Convenience functions
+    bool touchMove() const { return move() && touchEvent(); }
+    bool touchRelease() const { return release() && touchEvent(); }
+
+    HitTestRequestType type() const { return m_requestType; }
+
+private:
+    HitTestRequestType m_requestType;
+};
+
+} // namespace WebCore
+
+#endif // HitTestRequest_h
diff --git a/Source/core/rendering/HitTestResult.cpp b/Source/core/rendering/HitTestResult.cpp
new file mode 100644
index 0000000..62fcfa4
--- /dev/null
+++ b/Source/core/rendering/HitTestResult.cpp
@@ -0,0 +1,634 @@
+/*
+ * Copyright (C) 2006, 2008, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2012 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 "core/rendering/HitTestResult.h"
+
+#include "HTMLNames.h"
+#include "core/dom/DocumentMarkerController.h"
+#include "core/editing/Editor.h"
+#include "core/editing/FrameSelection.h"
+#include "core/html/HTMLAnchorElement.h"
+#include "core/html/HTMLImageElement.h"
+#include "core/html/HTMLInputElement.h"
+#include "core/html/HTMLMediaElement.h"
+#include "core/html/HTMLPlugInImageElement.h"
+#include "core/html/HTMLVideoElement.h"
+#include "core/html/parser/HTMLParserIdioms.h"
+#include "core/loader/cache/CachedImage.h"
+#include "core/page/Frame.h"
+#include "core/page/FrameTree.h"
+#include "core/platform/Scrollbar.h"
+#include "core/rendering/HitTestLocation.h"
+#include "core/rendering/RenderBlock.h"
+#include "core/rendering/RenderImage.h"
+#include "core/rendering/RenderInline.h"
+
+#if ENABLE(SVG)
+#include "SVGNames.h"
+#include "XLinkNames.h"
+#endif
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+HitTestResult::HitTestResult()
+    : m_isOverWidget(false)
+{
+}
+
+HitTestResult::HitTestResult(const LayoutPoint& point)
+    : m_hitTestLocation(point)
+    , m_pointInInnerNodeFrame(point)
+    , m_isOverWidget(false)
+{
+}
+
+HitTestResult::HitTestResult(const LayoutPoint& centerPoint, unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding)
+    : m_hitTestLocation(centerPoint, topPadding, rightPadding, bottomPadding, leftPadding)
+    , m_pointInInnerNodeFrame(centerPoint)
+    , m_isOverWidget(false)
+{
+}
+
+HitTestResult::HitTestResult(const HitTestLocation& other)
+    : m_hitTestLocation(other)
+    , m_pointInInnerNodeFrame(m_hitTestLocation.point())
+    , m_isOverWidget(false)
+{
+}
+
+HitTestResult::HitTestResult(const HitTestResult& other)
+    : m_hitTestLocation(other.m_hitTestLocation)
+    , m_innerNode(other.innerNode())
+    , m_innerNonSharedNode(other.innerNonSharedNode())
+    , m_pointInInnerNodeFrame(other.m_pointInInnerNodeFrame)
+    , m_localPoint(other.localPoint())
+    , m_innerURLElement(other.URLElement())
+    , m_scrollbar(other.scrollbar())
+    , m_isOverWidget(other.isOverWidget())
+{
+    // Only copy the NodeSet in case of rect hit test.
+    m_rectBasedTestResult = adoptPtr(other.m_rectBasedTestResult ? new NodeSet(*other.m_rectBasedTestResult) : 0);
+}
+
+HitTestResult::~HitTestResult()
+{
+}
+
+HitTestResult& HitTestResult::operator=(const HitTestResult& other)
+{
+    m_hitTestLocation = other.m_hitTestLocation;
+    m_innerNode = other.innerNode();
+    m_innerNonSharedNode = other.innerNonSharedNode();
+    m_pointInInnerNodeFrame = other.m_pointInInnerNodeFrame;
+    m_localPoint = other.localPoint();
+    m_innerURLElement = other.URLElement();
+    m_scrollbar = other.scrollbar();
+    m_isOverWidget = other.isOverWidget();
+
+    // Only copy the NodeSet in case of rect hit test.
+    m_rectBasedTestResult = adoptPtr(other.m_rectBasedTestResult ? new NodeSet(*other.m_rectBasedTestResult) : 0);
+
+    return *this;
+}
+
+void HitTestResult::setToNonShadowAncestor()
+{
+    Node* node = innerNode();
+    if (node)
+        node = node->document()->ancestorInThisScope(node);
+    setInnerNode(node);
+    node = innerNonSharedNode();
+    if (node)
+        node = node->document()->ancestorInThisScope(node);
+    setInnerNonSharedNode(node);
+}
+
+void HitTestResult::setInnerNode(Node* n)
+{
+    if (n && n->isPseudoElement())
+        n = n->parentOrShadowHostNode();
+    m_innerNode = n;
+}
+    
+void HitTestResult::setInnerNonSharedNode(Node* n)
+{
+    if (n && n->isPseudoElement())
+        n = n->parentOrShadowHostNode();
+    m_innerNonSharedNode = n;
+}
+
+void HitTestResult::setURLElement(Element* n) 
+{ 
+    m_innerURLElement = n; 
+}
+
+void HitTestResult::setScrollbar(Scrollbar* s)
+{
+    m_scrollbar = s;
+}
+
+Frame* HitTestResult::innerNodeFrame() const
+{
+    if (m_innerNonSharedNode)
+        return m_innerNonSharedNode->document()->frame();
+    if (m_innerNode)
+        return m_innerNode->document()->frame();
+    return 0;
+}
+
+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());
+}
+
+bool HitTestResult::isSelected() const
+{
+    if (!m_innerNonSharedNode)
+        return false;
+
+    Frame* frame = m_innerNonSharedNode->document()->frame();
+    if (!frame)
+        return false;
+
+    return frame->selection()->contains(m_hitTestLocation.point());
+}
+
+String HitTestResult::spellingToolTip(TextDirection& dir) const
+{
+    dir = LTR;
+    // 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()->markers()->markerContainingPoint(m_hitTestLocation.point(), DocumentMarker::Grammar);
+    if (!marker)
+        return String();
+
+    if (RenderObject* renderer = m_innerNonSharedNode->renderer())
+        dir = renderer->style()->direction();
+    return marker->description();
+}
+
+String HitTestResult::replacedString() const
+{
+    // Return the replaced string associated with this point, if any. This marker is created when a string is autocorrected, 
+    // and is used for generating a contextual menu item that allows it to easily be changed back if desired.
+    if (!m_innerNonSharedNode)
+        return String();
+    
+    DocumentMarker* marker = m_innerNonSharedNode->document()->markers()->markerContainingPoint(m_hitTestLocation.point(), DocumentMarker::Replacement);
+    if (!marker)
+        return String();
+    
+    return marker->description();
+}    
+    
+String HitTestResult::title(TextDirection& dir) const
+{
+    dir = LTR;
+    // 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 = toElement(titleNode)->title();
+            if (!title.isEmpty()) {
+                if (RenderObject* renderer = titleNode->renderer())
+                    dir = renderer->style()->direction();
+                return title;
+            }
+        }
+    }
+    return String();
+}
+
+String HitTestResult::innerTextIfTruncated(TextDirection& dir) const
+{
+    for (Node* truncatedNode = m_innerNode.get(); truncatedNode; truncatedNode = truncatedNode->parentNode()) {
+        if (!truncatedNode->isElementNode())
+            continue;
+
+        if (RenderObject* renderer = truncatedNode->renderer()) {
+            if (renderer->isRenderBlock()) {
+                RenderBlock* block = toRenderBlock(renderer);
+                if (block->style()->textOverflow()) {
+                    for (RootInlineBox* line = block->firstRootBox(); line; line = line->nextRootBox()) {
+                        if (line->hasEllipsisBox()) {
+                            dir = block->style()->direction();
+                            return toElement(truncatedNode)->innerText();
+                        }
+                    }
+                }
+                break;
+            }
+        }
+    }
+
+    dir = LTR;
+    return String();
+}
+
+String displayString(const String& string, const Node* node)
+{
+    if (!node)
+        return string;
+    return node->document()->displayStringModifiedByEncoding(string);
+}
+
+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->getAttribute(altAttr), 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()->imageForRenderer(image);
+    }
+
+    return 0;
+}
+
+IntRect HitTestResult::imageRect() const
+{
+    if (!image())
+        return IntRect();
+    return m_innerNonSharedNode->renderBox()->absoluteContentQuad().enclosingBoundingBox();
+}
+
+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(embedTag)
+        || m_innerNonSharedNode->hasTagName(imgTag)
+        || m_innerNonSharedNode->hasTagName(inputTag)
+        || m_innerNonSharedNode->hasTagName(objectTag)    
+#if ENABLE(SVG)
+        || m_innerNonSharedNode->hasTagName(SVGNames::imageTag)
+#endif
+       ) {
+        Element* element = toElement(m_innerNonSharedNode.get());
+        urlString = element->imageSourceURL();
+    } else
+        return KURL();
+
+    return m_innerNonSharedNode->document()->completeURL(stripLeadingAndTrailingHTMLSpaces(urlString));
+}
+
+KURL HitTestResult::absolutePDFURL() const
+{
+    if (!(m_innerNonSharedNode && m_innerNonSharedNode->document()))
+        return KURL();
+
+    if (!m_innerNonSharedNode->hasTagName(embedTag) && !m_innerNonSharedNode->hasTagName(objectTag))
+        return KURL();
+
+    HTMLPlugInImageElement* element = toHTMLPlugInImageElement(m_innerNonSharedNode.get());
+    KURL url = m_innerNonSharedNode->document()->completeURL(stripLeadingAndTrailingHTMLSpaces(element->url()));
+    if (!url.isValid())
+        return KURL();
+
+    if (element->serviceType() == "application/pdf" || (element->serviceType().isEmpty() && url.path().lower().endsWith(".pdf")))
+        return url;
+    return KURL();
+}
+
+KURL HitTestResult::absoluteMediaURL() const
+{
+    if (HTMLMediaElement* mediaElt = mediaElement())
+        return mediaElt->currentSrc();
+    return KURL();
+}
+
+bool HitTestResult::mediaSupportsFullscreen() const
+{
+    HTMLMediaElement* mediaElt(mediaElement());
+    return (mediaElt && mediaElt->hasTagName(HTMLNames::videoTag) && mediaElt->supportsFullscreen());
+}
+
+HTMLMediaElement* HitTestResult::mediaElement() const
+{
+    if (!(m_innerNonSharedNode && m_innerNonSharedNode->document()))
+        return 0;
+
+    if (!(m_innerNonSharedNode->renderer() && m_innerNonSharedNode->renderer()->isMedia()))
+        return 0;
+
+    if (m_innerNonSharedNode->hasTagName(HTMLNames::videoTag) || m_innerNonSharedNode->hasTagName(HTMLNames::audioTag))
+        return static_cast<HTMLMediaElement*>(m_innerNonSharedNode.get());
+    return 0;
+}
+
+void HitTestResult::toggleMediaControlsDisplay() const
+{
+    if (HTMLMediaElement* mediaElt = mediaElement())
+        mediaElt->setControls(!mediaElt->controls());
+}
+
+void HitTestResult::toggleMediaLoopPlayback() const
+{
+    if (HTMLMediaElement* mediaElt = mediaElement())
+        mediaElt->setLoop(!mediaElt->loop());
+}
+
+void HitTestResult::enterFullscreenForVideo() const
+{
+    HTMLMediaElement* mediaElt(mediaElement());
+    if (mediaElt && mediaElt->hasTagName(HTMLNames::videoTag)) {
+        HTMLVideoElement* videoElt = static_cast<HTMLVideoElement*>(mediaElt);
+        if (!videoElt->isFullscreen() && mediaElt->supportsFullscreen())
+            videoElt->enterFullscreen();
+    }
+}
+
+bool HitTestResult::mediaControlsEnabled() const
+{
+    if (HTMLMediaElement* mediaElt = mediaElement())
+        return mediaElt->controls();
+    return false;
+}
+
+bool HitTestResult::mediaLoopEnabled() const
+{
+    if (HTMLMediaElement* mediaElt = mediaElement())
+        return mediaElt->loop();
+    return false;
+}
+
+bool HitTestResult::mediaPlaying() const
+{
+    if (HTMLMediaElement* mediaElt = mediaElement())
+        return !mediaElt->paused();
+    return false;
+}
+
+void HitTestResult::toggleMediaPlayState() const
+{
+    if (HTMLMediaElement* mediaElt = mediaElement())
+        mediaElt->togglePlayState();
+}
+
+bool HitTestResult::mediaHasAudio() const
+{
+    if (HTMLMediaElement* mediaElt = mediaElement())
+        return mediaElt->hasAudio();
+    return false;
+}
+
+bool HitTestResult::mediaIsVideo() const
+{
+    if (HTMLMediaElement* mediaElt = mediaElement())
+        return mediaElt->hasTagName(HTMLNames::videoTag);
+    return false;
+}
+
+bool HitTestResult::mediaMuted() const
+{
+    if (HTMLMediaElement* mediaElt = mediaElement())
+        return mediaElt->muted();
+    return false;
+}
+
+void HitTestResult::toggleMediaMuteState() const
+{
+    if (HTMLMediaElement* mediaElt = mediaElement())
+        mediaElt->setMuted(!mediaElt->muted());
+}
+
+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(stripLeadingAndTrailingHTMLSpaces(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))
+        return true;
+
+    if (m_innerNonSharedNode->hasTagName(inputTag))
+        return static_cast<HTMLInputElement*>(m_innerNonSharedNode.get())->isTextField();
+
+    return m_innerNonSharedNode->rendererIsEditable();
+}
+
+bool HitTestResult::addNodeToRectBasedTestResult(Node* node, const HitTestRequest& request, const HitTestLocation& locationInContainer, const LayoutRect& rect)
+{
+    // If it is not a rect-based hit test, this method has to be no-op.
+    // Return false, so the hit test stops.
+    if (!isRectBasedTest())
+        return false;
+
+    // If node is null, return true so the hit test can continue.
+    if (!node)
+        return true;
+
+    if (request.disallowsShadowContent())
+        node = node->document()->ancestorInThisScope(node);
+
+    mutableRectBasedTestResult().add(node);
+
+    bool regionFilled = rect.contains(locationInContainer.boundingBox());
+    return !regionFilled;
+}
+
+bool HitTestResult::addNodeToRectBasedTestResult(Node* node, const HitTestRequest& request, const HitTestLocation& locationInContainer, const FloatRect& rect)
+{
+    // If it is not a rect-based hit test, this method has to be no-op.
+    // Return false, so the hit test stops.
+    if (!isRectBasedTest())
+        return false;
+
+    // If node is null, return true so the hit test can continue.
+    if (!node)
+        return true;
+
+    if (request.disallowsShadowContent())
+        node = node->document()->ancestorInThisScope(node);
+
+    mutableRectBasedTestResult().add(node);
+
+    bool regionFilled = rect.contains(locationInContainer.boundingBox());
+    return !regionFilled;
+}
+
+void HitTestResult::append(const HitTestResult& other)
+{
+    ASSERT(isRectBasedTest() && other.isRectBasedTest());
+
+    if (!m_innerNode && other.innerNode()) {
+        m_innerNode = other.innerNode();
+        m_innerNonSharedNode = other.innerNonSharedNode();
+        m_localPoint = other.localPoint();
+        m_pointInInnerNodeFrame = other.m_pointInInnerNodeFrame;
+        m_innerURLElement = other.URLElement();
+        m_scrollbar = other.scrollbar();
+        m_isOverWidget = other.isOverWidget();
+    }
+
+    if (other.m_rectBasedTestResult) {
+        NodeSet& set = mutableRectBasedTestResult();
+        for (NodeSet::const_iterator it = other.m_rectBasedTestResult->begin(), last = other.m_rectBasedTestResult->end(); it != last; ++it)
+            set.add(it->get());
+    }
+}
+
+const HitTestResult::NodeSet& HitTestResult::rectBasedTestResult() const
+{
+    if (!m_rectBasedTestResult)
+        m_rectBasedTestResult = adoptPtr(new NodeSet);
+    return *m_rectBasedTestResult;
+}
+
+HitTestResult::NodeSet& HitTestResult::mutableRectBasedTestResult()
+{
+    if (!m_rectBasedTestResult)
+        m_rectBasedTestResult = adoptPtr(new NodeSet);
+    return *m_rectBasedTestResult;
+}
+
+Vector<String> HitTestResult::dictationAlternatives() const
+{
+    // Return the dictation context handle if the text at this point has DictationAlternative marker, which means this text is
+    if (!m_innerNonSharedNode)
+        return Vector<String>();
+
+    DocumentMarker* marker = m_innerNonSharedNode->document()->markers()->markerContainingPoint(pointInInnerNodeFrame(), DocumentMarker::DictationAlternatives);
+    if (!marker)
+        return Vector<String>();
+
+    Frame* frame = innerNonSharedNode()->document()->frame();
+    if (!frame)
+        return Vector<String>();
+
+    return frame->editor()->dictationAlternativesForMarker(marker);
+}
+
+Node* HitTestResult::targetNode() const
+{
+    Node* node = innerNode();
+    if (!node)
+        return 0;
+    if (node->inDocument())
+        return node;
+
+    Element* element = node->parentElement();
+    if (element && element->inDocument())
+        return element;
+
+    return node;
+}
+
+Element* HitTestResult::innerElement() const
+{
+    for (Node* node = m_innerNode.get(); node; node = node->parentNode()) {
+        if (node->isElementNode())
+            return toElement(node);
+    }
+
+    return 0;
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/HitTestResult.h b/Source/core/rendering/HitTestResult.h
new file mode 100644
index 0000000..37fe7c6
--- /dev/null
+++ b/Source/core/rendering/HitTestResult.h
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2012 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 HitTestResult_h
+#define HitTestResult_h
+
+#include "core/platform/graphics/FloatQuad.h"
+#include "core/platform/graphics/FloatRect.h"
+#include "core/platform/graphics/LayoutRect.h"
+#include "core/platform/text/TextDirection.h"
+#include "core/rendering/HitTestLocation.h"
+#include "core/rendering/HitTestRequest.h"
+#include <wtf/Forward.h>
+#include <wtf/ListHashSet.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class Element;
+class Frame;
+class HTMLMediaElement;
+class Image;
+class KURL;
+class Node;
+class RenderRegion;
+class Scrollbar;
+
+class HitTestResult {
+public:
+    typedef ListHashSet<RefPtr<Node> > NodeSet;
+
+    HitTestResult();
+    HitTestResult(const LayoutPoint&);
+    // Pass non-negative padding values to perform a rect-based hit test.
+    HitTestResult(const LayoutPoint& centerPoint, unsigned topPadding, unsigned rightPadding, unsigned bottomPadding, unsigned leftPadding);
+    HitTestResult(const HitTestLocation&);
+    HitTestResult(const HitTestResult&);
+    ~HitTestResult();
+    HitTestResult& operator=(const HitTestResult&);
+
+    Node* innerNode() const { return m_innerNode.get(); }
+    Element* innerElement() const;
+    Node* innerNonSharedNode() const { return m_innerNonSharedNode.get(); }
+    Element* URLElement() const { return m_innerURLElement.get(); }
+    Scrollbar* scrollbar() const { return m_scrollbar.get(); }
+    bool isOverWidget() const { return m_isOverWidget; }
+
+    // Forwarded from HitTestLocation
+    bool isRectBasedTest() const { return m_hitTestLocation.isRectBasedTest(); }
+
+    // The hit-tested point in the coordinates of the main frame.
+    const LayoutPoint& pointInMainFrame() const { return m_hitTestLocation.point(); }
+    IntPoint roundedPointInMainFrame() const { return roundedIntPoint(pointInMainFrame()); }
+
+    // The hit-tested point in the coordinates of the innerNode frame, the frame containing innerNode.
+    const LayoutPoint& pointInInnerNodeFrame() const { return m_pointInInnerNodeFrame; }
+    IntPoint roundedPointInInnerNodeFrame() const { return roundedIntPoint(pointInInnerNodeFrame()); }
+    Frame* innerNodeFrame() const;
+
+    // The hit-tested point in the coordinates of the inner node.
+    const LayoutPoint& localPoint() const { return m_localPoint; }
+    void setLocalPoint(const LayoutPoint& p) { m_localPoint = p; }
+
+    void setToNonShadowAncestor();
+
+    const HitTestLocation& hitTestLocation() const { return m_hitTestLocation; }
+
+    void setInnerNode(Node*);
+    void setInnerNonSharedNode(Node*);
+    void setURLElement(Element*);
+    void setScrollbar(Scrollbar*);
+    void setIsOverWidget(bool b) { m_isOverWidget = b; }
+
+    Frame* targetFrame() const;
+    bool isSelected() const;
+    String spellingToolTip(TextDirection&) const;
+    String replacedString() const;
+    String title(TextDirection&) const;
+    String innerTextIfTruncated(TextDirection&) const;
+    String altDisplayString() const;
+    String titleDisplayString() const;
+    Image* image() const;
+    IntRect imageRect() const;
+    KURL absoluteImageURL() const;
+    KURL absolutePDFURL() const;
+    KURL absoluteMediaURL() const;
+    KURL absoluteLinkURL() const;
+    String textContent() const;
+    bool isLiveLink() const;
+    bool isContentEditable() const;
+    void toggleMediaControlsDisplay() const;
+    void toggleMediaLoopPlayback() const;
+    void enterFullscreenForVideo() const;
+    bool mediaControlsEnabled() const;
+    bool mediaLoopEnabled() const;
+    bool mediaPlaying() const;
+    bool mediaSupportsFullscreen() const;
+    void toggleMediaPlayState() const;
+    bool mediaHasAudio() const;
+    bool mediaIsVideo() const;
+    bool mediaMuted() const;
+    void toggleMediaMuteState() const;
+
+    // Returns true if it is rect-based hit test and needs to continue until the rect is fully
+    // enclosed by the boundaries of a node.
+    bool addNodeToRectBasedTestResult(Node*, const HitTestRequest&, const HitTestLocation& pointInContainer, const LayoutRect& = LayoutRect());
+    bool addNodeToRectBasedTestResult(Node*, const HitTestRequest&, const HitTestLocation& pointInContainer, const FloatRect&);
+    void append(const HitTestResult&);
+
+    // If m_rectBasedTestResult is 0 then set it to a new NodeSet. Return *m_rectBasedTestResult. Lazy allocation makes
+    // sense because the NodeSet is seldom necessary, and it's somewhat expensive to allocate and initialize. This method does
+    // the same thing as mutableRectBasedTestResult(), but here the return value is const.
+    const NodeSet& rectBasedTestResult() const;
+
+    Vector<String> dictationAlternatives() const;
+
+    Node* targetNode() const;
+
+private:
+    NodeSet& mutableRectBasedTestResult(); // See above.
+    HTMLMediaElement* mediaElement() const;
+
+    HitTestLocation m_hitTestLocation;
+
+    RefPtr<Node> m_innerNode;
+    RefPtr<Node> m_innerNonSharedNode;
+    LayoutPoint m_pointInInnerNodeFrame; // The hit-tested point in innerNode frame coordinates.
+    LayoutPoint 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).
+
+    mutable OwnPtr<NodeSet> m_rectBasedTestResult;
+};
+
+String displayString(const String&, const Node*);
+
+} // namespace WebCore
+
+#endif // HitTestResult_h
diff --git a/Source/core/rendering/HitTestingTransformState.cpp b/Source/core/rendering/HitTestingTransformState.cpp
new file mode 100644
index 0000000..7a31128
--- /dev/null
+++ b/Source/core/rendering/HitTestingTransformState.cpp
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2011 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 "core/rendering/HitTestingTransformState.h"
+
+#include "core/platform/graphics/LayoutRect.h"
+#include <wtf/PassOwnPtr.h>
+
+namespace WebCore {
+
+void HitTestingTransformState::translate(int x, int y, TransformAccumulation accumulate)
+{
+    m_accumulatedTransform.translate(x, y);    
+    if (accumulate == FlattenTransform)
+        flattenWithTransform(m_accumulatedTransform);
+
+    m_accumulatingTransform = accumulate == AccumulateTransform;
+}
+
+void HitTestingTransformState::applyTransform(const TransformationMatrix& transformFromContainer, TransformAccumulation accumulate)
+{
+    m_accumulatedTransform.multiply(transformFromContainer);
+    if (accumulate == FlattenTransform)
+        flattenWithTransform(m_accumulatedTransform);
+
+    m_accumulatingTransform = accumulate == AccumulateTransform;
+}
+
+void HitTestingTransformState::flatten()
+{
+    flattenWithTransform(m_accumulatedTransform);
+}
+
+void HitTestingTransformState::flattenWithTransform(const TransformationMatrix& t)
+{
+    TransformationMatrix inverseTransform = t.inverse();
+    m_lastPlanarPoint = inverseTransform.projectPoint(m_lastPlanarPoint);
+    m_lastPlanarQuad = inverseTransform.projectQuad(m_lastPlanarQuad);
+    m_lastPlanarArea = inverseTransform.projectQuad(m_lastPlanarArea);
+
+    m_accumulatedTransform.makeIdentity();
+    m_accumulatingTransform = false;
+}
+
+FloatPoint HitTestingTransformState::mappedPoint() const
+{
+    return m_accumulatedTransform.inverse().projectPoint(m_lastPlanarPoint);
+}
+
+FloatQuad HitTestingTransformState::mappedQuad() const
+{
+    return m_accumulatedTransform.inverse().projectQuad(m_lastPlanarQuad);
+}
+
+FloatQuad HitTestingTransformState::mappedArea() const
+{
+    return m_accumulatedTransform.inverse().projectQuad(m_lastPlanarArea);
+}
+
+LayoutRect HitTestingTransformState::boundsOfMappedArea() const
+{
+    return m_accumulatedTransform.inverse().clampedBoundsOfProjectedQuad(m_lastPlanarArea);
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/HitTestingTransformState.h b/Source/core/rendering/HitTestingTransformState.h
new file mode 100644
index 0000000..6cb7ec5
--- /dev/null
+++ b/Source/core/rendering/HitTestingTransformState.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2011 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 HitTestingTransformState_h
+#define HitTestingTransformState_h
+
+#include "core/platform/graphics/FloatPoint.h"
+#include "core/platform/graphics/FloatQuad.h"
+#include "core/platform/graphics/IntSize.h"
+#include "core/platform/graphics/transforms/AffineTransform.h"
+#include "core/platform/graphics/transforms/TransformationMatrix.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+// FIXME: Now that TransformState lazily creates its TransformationMatrix it takes up less space.
+// So there's really no need for a ref counted version. So This class should be removed and replaced
+// with TransformState. There are some minor differences (like the way translate() works slightly
+// differently than move()) so care has to be taken when this is done.
+class HitTestingTransformState : public RefCounted<HitTestingTransformState> {
+public:
+    static PassRefPtr<HitTestingTransformState> create(const FloatPoint& p, const FloatQuad& quad, const FloatQuad& area)
+    {
+        return adoptRef(new HitTestingTransformState(p, quad, area));
+    }
+
+    static PassRefPtr<HitTestingTransformState> create(const HitTestingTransformState& other)
+    {
+        return adoptRef(new HitTestingTransformState(other));
+    }
+
+    enum TransformAccumulation { FlattenTransform, AccumulateTransform };
+    void translate(int x, int y, TransformAccumulation);
+    void applyTransform(const TransformationMatrix& transformFromContainer, TransformAccumulation);
+
+    FloatPoint mappedPoint() const;
+    FloatQuad mappedQuad() const;
+    FloatQuad mappedArea() const;
+    LayoutRect boundsOfMappedArea() const;
+    void flatten();
+
+    FloatPoint m_lastPlanarPoint;
+    FloatQuad m_lastPlanarQuad;
+    FloatQuad m_lastPlanarArea;
+    TransformationMatrix m_accumulatedTransform;
+    bool m_accumulatingTransform;
+
+private:
+    HitTestingTransformState(const FloatPoint& p, const FloatQuad& quad, const FloatQuad& area)
+        : m_lastPlanarPoint(p)
+        , m_lastPlanarQuad(quad)
+        , m_lastPlanarArea(area)
+        , m_accumulatingTransform(false)
+    {
+    }
+    
+    HitTestingTransformState(const HitTestingTransformState& other)
+        : RefCounted<HitTestingTransformState>()
+        , m_lastPlanarPoint(other.m_lastPlanarPoint)
+        , m_lastPlanarQuad(other.m_lastPlanarQuad)
+        , m_lastPlanarArea(other.m_lastPlanarArea)
+        , m_accumulatedTransform(other.m_accumulatedTransform)
+        , m_accumulatingTransform(other.m_accumulatingTransform)
+    {
+    }
+    
+    void flattenWithTransform(const TransformationMatrix&);
+};
+
+} // namespace WebCore
+
+#endif // HitTestingTransformState_h
diff --git a/Source/core/rendering/ImageQualityController.cpp b/Source/core/rendering/ImageQualityController.cpp
new file mode 100644
index 0000000..af1b9ab
--- /dev/null
+++ b/Source/core/rendering/ImageQualityController.cpp
@@ -0,0 +1,214 @@
+/*
+ * Copyright (C) 2013 Google 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:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+ * OWNER 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 "core/rendering/ImageQualityController.h"
+
+#include "core/page/Frame.h"
+#include "core/page/FrameView.h"
+#include "core/page/Page.h"
+#include "core/platform/graphics/FloatRect.h"
+#include "core/platform/graphics/GraphicsContext.h"
+
+namespace WebCore {
+
+static const double cLowQualityTimeThreshold = 0.500; // 500 ms
+
+static ImageQualityController* gImageQualityController = 0;
+
+ImageQualityController* ImageQualityController::imageQualityController()
+{
+    if (!gImageQualityController)
+        gImageQualityController = new ImageQualityController;
+
+    return gImageQualityController;
+}
+
+void ImageQualityController::remove(RenderObject* renderer)
+{
+    if (gImageQualityController) {
+        gImageQualityController->objectDestroyed(renderer);
+        if (gImageQualityController->isEmpty()) {
+            delete gImageQualityController;
+            gImageQualityController = 0;
+        }
+    }
+}
+
+ImageQualityController::~ImageQualityController()
+{
+    // This will catch users of ImageQualityController that forget to call cleanUp.
+    ASSERT(!gImageQualityController || gImageQualityController->isEmpty());
+}
+
+ImageQualityController::ImageQualityController()
+    : m_timer(this, &ImageQualityController::highQualityRepaintTimerFired)
+    , m_animatedResizeIsActive(false)
+    , m_liveResizeOptimizationIsActive(false)
+{
+}
+
+void ImageQualityController::removeLayer(RenderObject* object, LayerSizeMap* innerMap, const void* layer)
+{
+    if (innerMap) {
+        innerMap->remove(layer);
+        if (innerMap->isEmpty())
+            objectDestroyed(object);
+    }
+}
+
+void ImageQualityController::set(RenderObject* object, LayerSizeMap* innerMap, const void* layer, const LayoutSize& size)
+{
+    if (innerMap)
+        innerMap->set(layer, size);
+    else {
+        LayerSizeMap newInnerMap;
+        newInnerMap.set(layer, size);
+        m_objectLayerSizeMap.set(object, newInnerMap);
+    }
+}
+
+void ImageQualityController::objectDestroyed(RenderObject* object)
+{
+    m_objectLayerSizeMap.remove(object);
+    if (m_objectLayerSizeMap.isEmpty()) {
+        m_animatedResizeIsActive = false;
+        m_timer.stop();
+    }
+}
+
+void ImageQualityController::highQualityRepaintTimerFired(Timer<ImageQualityController>*)
+{
+    if (!m_animatedResizeIsActive && !m_liveResizeOptimizationIsActive)
+        return;
+    m_animatedResizeIsActive = false;
+
+    for (ObjectLayerSizeMap::iterator it = m_objectLayerSizeMap.begin(); it != m_objectLayerSizeMap.end(); ++it) {
+        if (Frame* frame = it->key->document()->frame()) {
+            // If this renderer's containing FrameView is in live resize, punt the timer and hold back for now.
+            if (frame->view() && frame->view()->inLiveResize()) {
+                restartTimer();
+                return;
+            }
+        }
+        it->key->repaint();
+    }
+
+    m_liveResizeOptimizationIsActive = false;
+}
+
+void ImageQualityController::restartTimer()
+{
+    m_timer.startOneShot(cLowQualityTimeThreshold);
+}
+
+bool ImageQualityController::shouldPaintAtLowQuality(GraphicsContext* context, RenderObject* object, Image* image, const void *layer, const LayoutSize& layoutSize)
+{
+    // If the image is not a bitmap image, then none of this is relevant and we just paint at high
+    // quality.
+    if (!image || !image->isBitmapImage() || context->paintingDisabled())
+        return false;
+
+    if (object->style()->imageRendering() == ImageRenderingOptimizeContrast)
+        return true;
+
+    // Look ourselves up in the hashtables.
+    ObjectLayerSizeMap::iterator i = m_objectLayerSizeMap.find(object);
+    LayerSizeMap* innerMap = i != m_objectLayerSizeMap.end() ? &i->value : 0;
+    LayoutSize oldSize;
+    bool isFirstResize = true;
+    if (innerMap) {
+        LayerSizeMap::iterator j = innerMap->find(layer);
+        if (j != innerMap->end()) {
+            isFirstResize = false;
+            oldSize = j->value;
+        }
+    }
+
+    const AffineTransform& currentTransform = context->getCTM();
+    bool contextIsScaled = !currentTransform.isIdentityOrTranslationOrFlipped();
+
+    // Make sure to use the unzoomed image size, since if a full page zoom is in effect, the image
+    // is actually being scaled.
+    LayoutSize scaledImageSize = currentTransform.mapSize(image->size());
+    LayoutSize scaledLayoutSize = currentTransform.mapSize(roundedIntSize(layoutSize));
+
+    // If the containing FrameView is being resized, paint at low quality until resizing is finished.
+    if (Frame* frame = object->document()->frame()) {
+        bool frameViewIsCurrentlyInLiveResize = frame->view() && frame->view()->inLiveResize();
+        if (frameViewIsCurrentlyInLiveResize) {
+            set(object, innerMap, layer, scaledLayoutSize);
+            restartTimer();
+            m_liveResizeOptimizationIsActive = true;
+            return true;
+        }
+        if (m_liveResizeOptimizationIsActive) {
+            // Live resize has ended, paint in HQ and remove this object from the list.
+            removeLayer(object, innerMap, layer);
+            return false;
+        }
+    }
+
+    if (!contextIsScaled && scaledLayoutSize == scaledImageSize) {
+        // There is no scale in effect. If we had a scale in effect before, we can just remove this object from the list.
+        removeLayer(object, innerMap, layer);
+        return false;
+    }
+
+    // If an animated resize is active, paint in low quality and kick the timer ahead.
+    if (m_animatedResizeIsActive) {
+        set(object, innerMap, layer, scaledLayoutSize);
+        restartTimer();
+        return true;
+    }
+    // If this is the first time resizing this image, or its size is the
+    // same as the last resize, draw at high res, but record the paint
+    // size and set the timer.
+    if (isFirstResize || oldSize == scaledLayoutSize) {
+        restartTimer();
+        set(object, innerMap, layer, scaledLayoutSize);
+        return false;
+    }
+    // If the timer is no longer active, draw at high quality and don't
+    // set the timer.
+    if (!m_timer.isActive()) {
+        removeLayer(object, innerMap, layer);
+        return false;
+    }
+    // This object has been resized to two different sizes while the timer
+    // is active, so draw at low quality, set the flag for animated resizes and
+    // the object to the list for high quality redraw.
+    set(object, innerMap, layer, scaledLayoutSize);
+    m_animatedResizeIsActive = true;
+    restartTimer();
+    return true;
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/ImageQualityController.h b/Source/core/rendering/ImageQualityController.h
new file mode 100644
index 0000000..83e69df
--- /dev/null
+++ b/Source/core/rendering/ImageQualityController.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2013 Google 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:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+ * OWNER 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 ImageQualityController_h
+#define ImageQualityController_h
+
+#include "core/platform/graphics/Image.h"
+#include "core/platform/graphics/ImageOrientation.h"
+#include "core/platform/graphics/ImageSource.h"
+#include "core/platform/graphics/IntSize.h"
+#include "core/platform/graphics/LayoutSize.h"
+#include "core/rendering/RenderObject.h"
+#include <wtf/HashMap.h>
+
+namespace WebCore {
+
+typedef HashMap<const void*, LayoutSize> LayerSizeMap;
+typedef HashMap<RenderObject*, LayerSizeMap> ObjectLayerSizeMap;
+
+class ImageQualityController {
+    WTF_MAKE_NONCOPYABLE(ImageQualityController); WTF_MAKE_FAST_ALLOCATED;
+public:
+    virtual ~ImageQualityController();
+
+    static ImageQualityController* imageQualityController();
+
+    static void remove(RenderObject*);
+
+    bool shouldPaintAtLowQuality(GraphicsContext*, RenderObject*, Image*, const void* layer, const LayoutSize&);
+
+private:
+    ImageQualityController();
+
+    void removeLayer(RenderObject*, LayerSizeMap* innerMap, const void* layer);
+    void set(RenderObject*, LayerSizeMap* innerMap, const void* layer, const LayoutSize&);
+    void objectDestroyed(RenderObject*);
+    bool isEmpty() { return m_objectLayerSizeMap.isEmpty(); }
+
+    void highQualityRepaintTimerFired(Timer<ImageQualityController>*);
+    void restartTimer();
+
+    ObjectLayerSizeMap m_objectLayerSizeMap;
+    Timer<ImageQualityController> m_timer;
+    bool m_animatedResizeIsActive;
+    bool m_liveResizeOptimizationIsActive;
+};
+
+} // namespace WebCore
+
+#endif
diff --git a/Source/core/rendering/InlineBox.cpp b/Source/core/rendering/InlineBox.cpp
new file mode 100644
index 0000000..6c7da93
--- /dev/null
+++ b/Source/core/rendering/InlineBox.cpp
@@ -0,0 +1,422 @@
+/*
+ * 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 "core/rendering/InlineBox.h"
+
+#include "core/dom/WebCoreMemoryInstrumentation.h"
+#include "core/page/Frame.h"
+#include "core/page/Page.h"
+#include "core/platform/graphics/FontMetrics.h"
+#include "core/rendering/HitTestResult.h"
+#include "core/rendering/InlineFlowBox.h"
+#include "core/rendering/PaintInfo.h"
+#include "core/rendering/RenderArena.h"
+#include "core/rendering/RenderBlock.h"
+#include "core/rendering/RootInlineBox.h"
+
+#ifndef NDEBUG
+#include <stdio.h>
+#endif
+
+using namespace std;
+
+namespace WebCore {
+
+struct SameSizeAsInlineBox {
+    virtual ~SameSizeAsInlineBox() { }
+    void* a[4];
+    FloatPoint b;
+    float c;
+    uint32_t d : 32;
+#ifndef NDEBUG
+    bool f;
+#endif
+};
+
+COMPILE_ASSERT(sizeof(InlineBox) == sizeof(SameSizeAsInlineBox), InlineBox_size_guard);
+
+#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)
+{
+    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
+const char* InlineBox::boxName() const
+{
+    return "InlineBox";
+}
+
+void InlineBox::showTreeForThis() const
+{
+    if (m_renderer)
+        m_renderer->showTreeForThis();
+}
+
+void InlineBox::showLineTreeForThis() const
+{
+    if (m_renderer)
+        m_renderer->containingBlock()->showLineTreeAndMark(this, "*");
+}
+
+void InlineBox::showLineTreeAndMark(const InlineBox* markedBox1, const char* markedLabel1, const InlineBox* markedBox2, const char* markedLabel2, const RenderObject* obj, int depth) const
+{
+    int printedCharacters = 0;
+    if (this == markedBox1)
+        printedCharacters += fprintf(stderr, "%s", markedLabel1);
+    if (this == markedBox2)
+        printedCharacters += fprintf(stderr, "%s", markedLabel2);
+    if (renderer() == obj)
+        printedCharacters += fprintf(stderr, "*");
+    for (; printedCharacters < depth * 2; printedCharacters++)
+        fputc(' ', stderr);
+
+    showBox(printedCharacters);
+}
+
+void InlineBox::showBox(int printedCharacters) const
+{
+    printedCharacters += fprintf(stderr, "%s\t%p", boxName(), this);
+    for (; printedCharacters < showTreeCharacterOffset; printedCharacters++)
+        fputc(' ', stderr);
+    fprintf(stderr, "\t%s %p\n", renderer() ? renderer()->renderName() : "No Renderer", renderer());
+}
+#endif
+
+float InlineBox::logicalHeight() const
+{
+    if (hasVirtualLogicalHeight())
+        return virtualLogicalHeight();
+    
+    if (renderer()->isText())
+        return m_bitfields.isText() ? renderer()->style(isFirstLineStyle())->fontMetrics().height() : 0;
+    if (renderer()->isBox() && parent())
+        return isHorizontal() ? toRenderBox(m_renderer)->height() : toRenderBox(m_renderer)->width();
+
+    ASSERT(isInlineFlowBox());
+    RenderBoxModelObject* flowObject = boxModelObject();
+    const FontMetrics& fontMetrics = renderer()->style(isFirstLineStyle())->fontMetrics();
+    float result = fontMetrics.height();
+    if (parent())
+        result += flowObject->borderAndPaddingLogicalHeight();
+    return result;
+}
+
+int InlineBox::baselinePosition(FontBaseline baselineType) const
+{
+    return boxModelObject()->baselinePosition(baselineType, m_bitfields.firstLine(), isHorizontal() ? HorizontalLine : VerticalLine, PositionOnContainingLine);
+}
+
+LayoutUnit InlineBox::lineHeight() const
+{
+    return boxModelObject()->lineHeight(m_bitfields.firstLine(), isHorizontal() ? HorizontalLine : VerticalLine, PositionOnContainingLine);
+}
+
+int InlineBox::caretMinOffset() const 
+{ 
+    return m_renderer->caretMinOffset(); 
+}
+
+int InlineBox::caretMaxOffset() const 
+{ 
+    return m_renderer->caretMaxOffset(); 
+}
+
+void InlineBox::dirtyLineBoxes()
+{
+    markDirty();
+    for (InlineFlowBox* curr = parent(); curr && !curr->isDirty(); curr = curr->parent())
+        curr->markDirty();
+}
+
+void InlineBox::deleteLine(RenderArena* arena)
+{
+    if (!m_bitfields.extracted() && m_renderer->isBox())
+        toRenderBox(m_renderer)->setInlineBoxWrapper(0);
+    destroy(arena);
+}
+
+void InlineBox::extractLine()
+{
+    m_bitfields.setExtracted(true);
+    if (m_renderer->isBox())
+        toRenderBox(m_renderer)->setInlineBoxWrapper(0);
+}
+
+void InlineBox::attachLine()
+{
+    m_bitfields.setExtracted(false);
+    if (m_renderer->isBox())
+        toRenderBox(m_renderer)->setInlineBoxWrapper(this);
+}
+
+void InlineBox::adjustPosition(float dx, float dy)
+{
+    m_topLeft.move(dx, dy);
+
+    if (m_renderer->isReplaced()) 
+        toRenderBox(m_renderer)->move(dx, dy); 
+}
+
+void InlineBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit /* lineTop */, LayoutUnit /*lineBottom*/)
+{
+    if (!paintInfo.shouldPaintWithinRoot(renderer()) || (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseSelection))
+        return;
+
+    LayoutPoint childPoint = paintOffset;
+    if (parent()->renderer()->style()->isFlippedBlocksWritingMode()) // Faster than calling containingBlock().
+        childPoint = renderer()->containingBlock()->flipForWritingModeForChild(toRenderBox(renderer()), childPoint);
+    
+    // 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;
+    PaintInfo info(paintInfo);
+    info.phase = preservePhase ? paintInfo.phase : PaintPhaseBlockBackground;
+    renderer()->paint(info, childPoint);
+    if (!preservePhase) {
+        info.phase = PaintPhaseChildBlockBackgrounds;
+        renderer()->paint(info, childPoint);
+        info.phase = PaintPhaseFloat;
+        renderer()->paint(info, childPoint);
+        info.phase = PaintPhaseForeground;
+        renderer()->paint(info, childPoint);
+        info.phase = PaintPhaseOutline;
+        renderer()->paint(info, childPoint);
+    }
+}
+
+bool InlineBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit /* lineTop */, LayoutUnit /*lineBottom*/)
+{
+    // 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.)
+    LayoutPoint childPoint = accumulatedOffset;
+    if (parent()->renderer()->style()->isFlippedBlocksWritingMode()) // Faster than calling containingBlock().
+        childPoint = renderer()->containingBlock()->flipForWritingModeForChild(toRenderBox(renderer()), childPoint);
+    
+    return renderer()->hitTest(request, result, locationInContainer, childPoint);
+}
+
+const RootInlineBox* InlineBox::root() const
+{ 
+    if (m_parent)
+        return m_parent->root(); 
+    ASSERT(isRootInlineBox());
+    return static_cast<const RootInlineBox*>(this);
+}
+
+RootInlineBox* InlineBox::root()
+{ 
+    if (m_parent)
+        return m_parent->root(); 
+    ASSERT(isRootInlineBox());
+    return static_cast<RootInlineBox*>(this);
+}
+
+bool InlineBox::nextOnLineExists() const
+{
+    if (!m_bitfields.determinedIfNextOnLineExists()) {
+        m_bitfields.setDeterminedIfNextOnLineExists(true);
+
+        if (!parent())
+            m_bitfields.setNextOnLineExists(false);
+        else if (nextOnLine())
+            m_bitfields.setNextOnLineExists(true);
+        else
+            m_bitfields.setNextOnLineExists(parent()->nextOnLineExists());
+    }
+    return m_bitfields.nextOnLineExists();
+}
+
+InlineBox* InlineBox::nextLeafChild() const
+{
+    InlineBox* leaf = 0;
+    for (InlineBox* box = nextOnLine(); box && !leaf; box = box->nextOnLine())
+        leaf = box->isLeaf() ? box : toInlineFlowBox(box)->firstLeafChild();
+    if (!leaf && parent())
+        leaf = parent()->nextLeafChild();
+    return leaf;
+}
+    
+InlineBox* InlineBox::prevLeafChild() const
+{
+    InlineBox* leaf = 0;
+    for (InlineBox* box = prevOnLine(); box && !leaf; box = box->prevOnLine())
+        leaf = box->isLeaf() ? box : toInlineFlowBox(box)->lastLeafChild();
+    if (!leaf && parent())
+        leaf = parent()->prevLeafChild();
+    return leaf;
+}
+
+InlineBox* InlineBox::nextLeafChildIgnoringLineBreak() const
+{
+    InlineBox* leaf = nextLeafChild();
+    if (leaf && leaf->isLineBreak())
+        return 0;
+    return leaf;
+}
+
+InlineBox* InlineBox::prevLeafChildIgnoringLineBreak() const
+{
+    InlineBox* leaf = prevLeafChild();
+    if (leaf && leaf->isLineBreak())
+        return 0;
+    return leaf;
+}
+
+RenderObject::SelectionState InlineBox::selectionState()
+{
+    return renderer()->selectionState();
+}
+
+bool InlineBox::canAccommodateEllipsis(bool ltr, int blockEdge, int ellipsisWidth) const
+{
+    // Non-replaced elements can always accommodate an ellipsis.
+    if (!m_renderer || !m_renderer->isReplaced())
+        return true;
+    
+    IntRect boxRect(left(), 0, m_logicalWidth, 10);
+    IntRect ellipsisRect(ltr ? blockEdge - ellipsisWidth : blockEdge, 0, ellipsisWidth, 10);
+    return !(boxRect.intersects(ellipsisRect));
+}
+
+float InlineBox::placeEllipsisBox(bool, float, float, float, float& truncatedWidth, bool&)
+{
+    // Use -1 to mean "we didn't set the position."
+    truncatedWidth += logicalWidth();
+    return -1;
+}
+
+void InlineBox::clearKnownToHaveNoOverflow()
+{ 
+    m_bitfields.setKnownToHaveNoOverflow(false);
+    if (parent() && parent()->knownToHaveNoOverflow())
+        parent()->clearKnownToHaveNoOverflow();
+}
+
+FloatPoint InlineBox::locationIncludingFlipping()
+{
+    if (!renderer()->style()->isFlippedBlocksWritingMode())
+        return FloatPoint(x(), y());
+    RenderBlock* block = root()->block();
+    if (block->style()->isHorizontalWritingMode())
+        return FloatPoint(x(), block->height() - height() - y());
+    else
+        return FloatPoint(block->width() - width() - x(), y());
+}
+
+void InlineBox::flipForWritingMode(FloatRect& rect)
+{
+    if (!renderer()->style()->isFlippedBlocksWritingMode())
+        return;
+    root()->block()->flipForWritingMode(rect);
+}
+
+FloatPoint InlineBox::flipForWritingMode(const FloatPoint& point)
+{
+    if (!renderer()->style()->isFlippedBlocksWritingMode())
+        return point;
+    return root()->block()->flipForWritingMode(point);
+}
+
+void InlineBox::flipForWritingMode(LayoutRect& rect)
+{
+    if (!renderer()->style()->isFlippedBlocksWritingMode())
+        return;
+    root()->block()->flipForWritingMode(rect);
+}
+
+LayoutPoint InlineBox::flipForWritingMode(const LayoutPoint& point)
+{
+    if (!renderer()->style()->isFlippedBlocksWritingMode())
+        return point;
+    return root()->block()->flipForWritingMode(point);
+}
+
+void InlineBox::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::Rendering);
+    info.addMember(m_next, "next");
+    info.addMember(m_prev, "prev");
+    info.addMember(m_parent, "parent");
+    info.addMember(m_renderer, "renderer");
+
+    info.setCustomAllocation(true);
+}
+
+} // namespace WebCore
+
+#ifndef NDEBUG
+
+void showTree(const WebCore::InlineBox* b)
+{
+    if (b)
+        b->showTreeForThis();
+}
+
+void showLineTree(const WebCore::InlineBox* b)
+{
+    if (b)
+        b->showLineTreeForThis();
+}
+
+#endif
diff --git a/Source/core/rendering/InlineBox.h b/Source/core/rendering/InlineBox.h
new file mode 100644
index 0000000..9a97cd5
--- /dev/null
+++ b/Source/core/rendering/InlineBox.h
@@ -0,0 +1,447 @@
+/*
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2009, 2010, 2011 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 "core/platform/text/TextDirection.h"
+#include "core/rendering/RenderBoxModelObject.h"
+
+namespace WebCore {
+
+class HitTestRequest;
+class HitTestResult;
+class RootInlineBox;
+
+// 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_next(0)
+        , m_prev(0)
+        , m_parent(0)
+        , m_renderer(obj)
+        , m_logicalWidth(0)
+#ifndef NDEBUG
+        , m_hasBadParent(false)
+#endif
+    {
+    }
+
+    InlineBox(RenderObject* obj, FloatPoint topLeft, float logicalWidth, bool firstLine, bool constructed,
+              bool dirty, bool extracted, bool isHorizontal, InlineBox* next, InlineBox* prev, InlineFlowBox* parent)
+        : m_next(next)
+        , m_prev(prev)
+        , m_parent(parent)
+        , m_renderer(obj)
+        , m_topLeft(topLeft)
+        , m_logicalWidth(logicalWidth)
+        , m_bitfields(firstLine, constructed, dirty, extracted, isHorizontal)
+#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(float dx, float dy);
+    void adjustLogicalPosition(float deltaLogicalLeft, float deltaLogicalTop)
+    {
+        if (isHorizontal())
+            adjustPosition(deltaLogicalLeft, deltaLogicalTop);
+        else
+            adjustPosition(deltaLogicalTop, deltaLogicalLeft);
+    }
+    void adjustLineDirectionPosition(float delta)
+    {
+        if (isHorizontal())
+            adjustPosition(delta, 0);
+        else
+            adjustPosition(0, delta);
+    }
+    void adjustBlockDirectionPosition(float delta)
+    {
+        if (isHorizontal())
+            adjustPosition(0, delta);
+        else
+            adjustPosition(delta, 0);
+    }
+
+    virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom);
+    virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom);
+
+    // Overloaded new operator.
+    void* operator new(size_t, RenderArena*);
+
+    // 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;
+    void showLineTreeForThis() const;
+
+    virtual void showBox(int = 0) const;
+    virtual void showLineTreeAndMark(const InlineBox* = 0, const char* = 0, const InlineBox* = 0, const char* = 0, const RenderObject* = 0, int = 0) const;
+    virtual const char* boxName() const;
+#endif
+
+    bool isText() const { return m_bitfields.isText(); }
+    void setIsText(bool isText) { m_bitfields.setIsText(isText); }
+ 
+    virtual bool isInlineFlowBox() const { return false; }
+    virtual bool isInlineTextBox() const { return false; }
+    virtual bool isRootInlineBox() const { return false; }
+#if ENABLE(SVG)
+    virtual bool isSVGInlineTextBox() const { return false; }
+    virtual bool isSVGInlineFlowBox() const { return false; }
+    virtual bool isSVGRootInlineBox() const { return false; }
+#endif
+
+    bool hasVirtualLogicalHeight() const { return m_bitfields.hasVirtualLogicalHeight(); }
+    void setHasVirtualLogicalHeight() { m_bitfields.setHasVirtualLogicalHeight(true); }
+    virtual float virtualLogicalHeight() const
+    {
+        ASSERT_NOT_REACHED();
+        return 0;
+    }
+
+    bool isHorizontal() const { return m_bitfields.isHorizontal(); }
+    void setIsHorizontal(bool isHorizontal) { m_bitfields.setIsHorizontal(isHorizontal); }
+
+    virtual FloatRect calculateBoundaries() const
+    {
+        ASSERT_NOT_REACHED();
+        return FloatRect();
+    }
+
+    bool isConstructed() { return m_bitfields.constructed(); }
+    virtual void setConstructed() { m_bitfields.setConstructed(true); }
+
+    void setExtracted(bool extracted = true) { m_bitfields.setExtracted(extracted); }
+    
+    void setFirstLineStyleBit(bool firstLine) { m_bitfields.setFirstLine(firstLine); }
+    bool isFirstLineStyle() const { return m_bitfields.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;
+
+    virtual bool isLeaf() const { return true; }
+    
+    InlineBox* nextLeafChild() const;
+    InlineBox* prevLeafChild() const;
+
+    // Helper functions for editing and hit-testing code.
+    // FIXME: These two functions should be moved to RenderedPosition once the code to convert between
+    // Position and inline box, offset pair is moved to RenderedPosition.
+    InlineBox* nextLeafChildIgnoringLineBreak() const;
+    InlineBox* prevLeafChildIgnoringLineBreak() const;
+
+    RenderObject* renderer() const { return m_renderer; }
+
+    InlineFlowBox* parent() const
+    {
+        ASSERT(!m_hasBadParent);
+        return m_parent;
+    }
+    void setParent(InlineFlowBox* par) { m_parent = par; }
+
+    const RootInlineBox* root() const;
+    RootInlineBox* root();
+
+    // x() is the left side of the box in the containing block's coordinate system.
+    void setX(float x) { m_topLeft.setX(x); }
+    float x() const { return m_topLeft.x(); }
+    float left() const { return m_topLeft.x(); }
+
+    // y() is the top side of the box in the containing block's coordinate system.
+    void setY(float y) { m_topLeft.setY(y); }
+    float y() const { return m_topLeft.y(); }
+    float top() const { return m_topLeft.y(); }
+
+    const FloatPoint& topLeft() const { return m_topLeft; }
+
+    float width() const { return isHorizontal() ? logicalWidth() : logicalHeight(); }
+    float height() const { return isHorizontal() ? logicalHeight() : logicalWidth(); }
+    FloatSize size() const { return FloatSize(width(), height()); }
+    float right() const { return left() + width(); }
+    float bottom() const { return top() + height(); }
+
+    // The logicalLeft position is the left edge of the line box in a horizontal line and the top edge in a vertical line.
+    float logicalLeft() const { return isHorizontal() ? m_topLeft.x() : m_topLeft.y(); }
+    float logicalRight() const { return logicalLeft() + logicalWidth(); }
+    void setLogicalLeft(float left)
+    {
+        if (isHorizontal())
+            setX(left);
+        else
+            setY(left);
+    }
+    int pixelSnappedLogicalLeft() const { return logicalLeft(); }
+    int pixelSnappedLogicalRight() const { return ceilf(logicalRight()); }
+    int pixelSnappedLogicalTop() const { return logicalTop(); }
+    int pixelSnappedLogicalBottom() const { return ceilf(logicalBottom()); }
+
+    // The logicalTop[ position is the top edge of the line box in a horizontal line and the left edge in a vertical line.
+    float logicalTop() const { return isHorizontal() ? m_topLeft.y() : m_topLeft.x(); }
+    float logicalBottom() const { return logicalTop() + logicalHeight(); }
+    void setLogicalTop(float top)
+    {
+        if (isHorizontal())
+            setY(top);
+        else
+            setX(top);
+    }
+
+    // The logical width is our extent in the line's overall inline direction, i.e., width for horizontal text and height for vertical text.
+    void setLogicalWidth(float w) { m_logicalWidth = w; }
+    float logicalWidth() const { return m_logicalWidth; }
+
+    // The logical height is our extent in the block flow direction, i.e., height for horizontal text and width for vertical text.
+    float logicalHeight() const;
+
+    FloatRect logicalFrameRect() const { return isHorizontal() ? FloatRect(m_topLeft.x(), m_topLeft.y(), m_logicalWidth, logicalHeight()) : FloatRect(m_topLeft.y(), m_topLeft.x(), m_logicalWidth, logicalHeight()); }
+
+    virtual int baselinePosition(FontBaseline baselineType) const;
+    virtual LayoutUnit lineHeight() const;
+
+    virtual int caretMinOffset() const;
+    virtual int caretMaxOffset() const;
+
+    unsigned char bidiLevel() const { return m_bitfields.bidiEmbeddingLevel(); }
+    void setBidiLevel(unsigned char level) { m_bitfields.setBidiEmbeddingLevel(level); }
+    TextDirection direction() const { return bidiLevel() % 2 ? RTL : LTR; }
+    bool isLeftToRightDirection() const { return direction() == LTR; }
+    int caretLeftmostOffset() const { return isLeftToRightDirection() ? caretMinOffset() : caretMaxOffset(); }
+    int caretRightmostOffset() const { return isLeftToRightDirection() ? caretMaxOffset() : caretMinOffset(); }
+
+    virtual void clearTruncation() { }
+
+    bool isDirty() const { return m_bitfields.dirty(); }
+    virtual void markDirty(bool dirty = true) { m_bitfields.setDirty(dirty); }
+
+    virtual void dirtyLineBoxes();
+    
+    virtual RenderObject::SelectionState selectionState();
+
+    virtual bool canAccommodateEllipsis(bool ltr, int blockEdge, int ellipsisWidth) const;
+    // visibleLeftEdge, visibleRightEdge are in the parent's coordinate system.
+    virtual float placeEllipsisBox(bool ltr, float visibleLeftEdge, float visibleRightEdge, float ellipsisWidth, float &truncatedWidth, bool&);
+
+#ifndef NDEBUG
+    void setHasBadParent();
+#endif
+
+    int expansion() const { return m_bitfields.expansion(); }
+
+    bool visibleToHitTestRequest(const HitTestRequest& request) const { return renderer()->style()->visibility() == VISIBLE && (request.ignorePointerEventsNone() || renderer()->style()->pointerEvents() != PE_NONE); }
+    
+    EVerticalAlign verticalAlign() const { return renderer()->style(m_bitfields.firstLine())->verticalAlign(); }
+
+    // Use with caution! The type is not checked!
+    RenderBoxModelObject* boxModelObject() const
+    { 
+        if (!m_renderer->isText())
+            return toRenderBoxModelObject(m_renderer);
+        return 0;
+    }
+
+    FloatPoint locationIncludingFlipping();
+    void flipForWritingMode(FloatRect&);
+    FloatPoint flipForWritingMode(const FloatPoint&);
+    void flipForWritingMode(LayoutRect&);
+    LayoutPoint flipForWritingMode(const LayoutPoint&);
+
+    bool knownToHaveNoOverflow() const { return m_bitfields.knownToHaveNoOverflow(); }
+    void clearKnownToHaveNoOverflow();
+
+    bool dirOverride() const { return m_bitfields.dirOverride(); }
+    void setDirOverride(bool dirOverride) { m_bitfields.setDirOverride(dirOverride); }
+
+    virtual void reportMemoryUsage(MemoryObjectInfo*) const;
+
+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.
+
+public:
+    RenderObject* m_renderer;
+
+    FloatPoint m_topLeft;
+    float m_logicalWidth;
+
+#define ADD_BOOLEAN_BITFIELD(name, Name) \
+    private:\
+    unsigned m_##name : 1;\
+    public:\
+    bool name() const { return m_##name; }\
+    void set##Name(bool name) { m_##name = name; }\
+
+    class InlineBoxBitfields {
+    public:
+        InlineBoxBitfields(bool firstLine = false, bool constructed = false, bool dirty = false, bool extracted = false, bool isHorizontal = true)
+            : m_firstLine(firstLine)
+            , m_constructed(constructed)
+            , m_bidiEmbeddingLevel(0)
+            , m_dirty(dirty)
+            , m_extracted(extracted)
+            , m_hasVirtualLogicalHeight(false)
+            , m_isHorizontal(isHorizontal)
+            , m_endsWithBreak(false)
+            , m_hasSelectedChildrenOrCanHaveLeadingExpansion(false)
+            , m_knownToHaveNoOverflow(true)  
+            , m_hasEllipsisBoxOrHyphen(false)
+            , m_dirOverride(false)
+            , m_isText(false)
+            , m_determinedIfNextOnLineExists(false)
+            , m_nextOnLineExists(false)
+            , m_expansion(0)
+        {
+        }
+
+        // Some of these bits are actually for subclasses and moved here to compact the structures.
+        // for this class
+        ADD_BOOLEAN_BITFIELD(firstLine, FirstLine);
+        ADD_BOOLEAN_BITFIELD(constructed, Constructed);
+
+    private:
+        unsigned m_bidiEmbeddingLevel : 6; // The maximium bidi level is 62: http://unicode.org/reports/tr9/#Explicit_Levels_and_Directions
+
+    public:
+        unsigned char bidiEmbeddingLevel() const { return m_bidiEmbeddingLevel; }
+        void setBidiEmbeddingLevel(unsigned char bidiEmbeddingLevel) { m_bidiEmbeddingLevel = bidiEmbeddingLevel; }
+
+        ADD_BOOLEAN_BITFIELD(dirty, Dirty);
+        ADD_BOOLEAN_BITFIELD(extracted, Extracted);
+        ADD_BOOLEAN_BITFIELD(hasVirtualLogicalHeight, HasVirtualLogicalHeight);
+        ADD_BOOLEAN_BITFIELD(isHorizontal, IsHorizontal);
+        // for RootInlineBox
+        ADD_BOOLEAN_BITFIELD(endsWithBreak, EndsWithBreak); // Whether the line ends with a <br>.
+        // shared between RootInlineBox and InlineTextBox
+        ADD_BOOLEAN_BITFIELD(hasSelectedChildrenOrCanHaveLeadingExpansion, HasSelectedChildrenOrCanHaveLeadingExpansion);
+        ADD_BOOLEAN_BITFIELD(knownToHaveNoOverflow, KnownToHaveNoOverflow);
+        ADD_BOOLEAN_BITFIELD(hasEllipsisBoxOrHyphen, HasEllipsisBoxOrHyphen);
+        // for InlineTextBox
+        ADD_BOOLEAN_BITFIELD(dirOverride, DirOverride);
+        ADD_BOOLEAN_BITFIELD(isText, IsText); // Whether or not this object represents text with a non-zero height. Includes non-image list markers, text boxes.
+
+    private:
+        mutable unsigned m_determinedIfNextOnLineExists : 1;
+
+    public:
+        bool determinedIfNextOnLineExists() const { return m_determinedIfNextOnLineExists; }
+        void setDeterminedIfNextOnLineExists(bool determinedIfNextOnLineExists) const { m_determinedIfNextOnLineExists = determinedIfNextOnLineExists; }
+
+    private:
+        mutable unsigned m_nextOnLineExists : 1;
+        
+    public:
+        bool nextOnLineExists() const { return m_nextOnLineExists; }
+        void setNextOnLineExists(bool nextOnLineExists) const { m_nextOnLineExists = nextOnLineExists; }
+
+    private:
+        signed m_expansion : 12; // for justified text
+        
+    public:
+        signed expansion() const { return m_expansion; }
+        void setExpansion(signed expansion) { m_expansion = expansion; }
+    };
+#undef ADD_BOOLEAN_BITFIELD
+
+private:
+    InlineBoxBitfields m_bitfields;
+
+protected:
+    // For RootInlineBox
+    bool endsWithBreak() const { return m_bitfields.endsWithBreak(); }
+    void setEndsWithBreak(bool endsWithBreak) { m_bitfields.setEndsWithBreak(endsWithBreak); }
+    bool hasEllipsisBox() const { return m_bitfields.hasEllipsisBoxOrHyphen(); }
+    bool hasSelectedChildren() const { return m_bitfields.hasSelectedChildrenOrCanHaveLeadingExpansion(); }
+    void setHasSelectedChildren(bool hasSelectedChildren) { m_bitfields.setHasSelectedChildrenOrCanHaveLeadingExpansion(hasSelectedChildren); }
+    void setHasEllipsisBox(bool hasEllipsisBox) { m_bitfields.setHasEllipsisBoxOrHyphen(hasEllipsisBox); }
+
+    // For InlineTextBox
+    bool hasHyphen() const { return m_bitfields.hasEllipsisBoxOrHyphen(); }
+    void setHasHyphen(bool hasHyphen) { m_bitfields.setHasEllipsisBoxOrHyphen(hasHyphen); }    
+    bool canHaveLeadingExpansion() const { return m_bitfields.hasSelectedChildrenOrCanHaveLeadingExpansion(); }
+    void setCanHaveLeadingExpansion(bool canHaveLeadingExpansion) { m_bitfields.setHasSelectedChildrenOrCanHaveLeadingExpansion(canHaveLeadingExpansion); }
+    signed expansion() { return m_bitfields.expansion(); }
+    void setExpansion(signed expansion) { m_bitfields.setExpansion(expansion); }
+    
+    // For InlineFlowBox and InlineTextBox
+    bool extracted() const { return m_bitfields.extracted(); }
+
+#ifndef NDEBUG
+private:
+    bool m_hasBadParent;
+#endif
+};
+
+#ifdef NDEBUG
+inline InlineBox::~InlineBox()
+{
+}
+#endif
+
+#ifndef NDEBUG
+inline void InlineBox::setHasBadParent()
+{
+    m_hasBadParent = true;
+}
+#endif
+
+} // namespace WebCore
+
+#ifndef NDEBUG
+// Outside the WebCore namespace for ease of invocation from gdb.
+void showTree(const WebCore::InlineBox*);
+void showLineTree(const WebCore::InlineBox*);
+#endif
+
+#endif // InlineBox_h
diff --git a/Source/core/rendering/InlineFlowBox.cpp b/Source/core/rendering/InlineFlowBox.cpp
new file mode 100644
index 0000000..79e544c
--- /dev/null
+++ b/Source/core/rendering/InlineFlowBox.cpp
@@ -0,0 +1,1660 @@
+/*
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 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 "core/rendering/InlineFlowBox.h"
+
+#include "CSSPropertyNames.h"
+#include "core/dom/Document.h"
+#include "core/dom/Text.h"
+#include "core/dom/WebCoreMemoryInstrumentation.h"
+#include "core/loader/cache/CachedImage.h"
+#include "core/platform/graphics/Font.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/rendering/EllipsisBox.h"
+#include "core/rendering/HitTestResult.h"
+#include "core/rendering/InlineTextBox.h"
+#include "core/rendering/RenderBlock.h"
+#include "core/rendering/RenderInline.h"
+#include "core/rendering/RenderLayer.h"
+#include "core/rendering/RenderListMarker.h"
+#include "core/rendering/RenderRubyBase.h"
+#include "core/rendering/RenderRubyRun.h"
+#include "core/rendering/RenderRubyText.h"
+#include "core/rendering/RenderTableCell.h"
+#include "core/rendering/RenderView.h"
+#include "core/rendering/RootInlineBox.h"
+
+#include <math.h>
+
+using namespace std;
+
+namespace WebCore {
+
+struct SameSizeAsInlineFlowBox : public InlineBox {
+    void* pointers[5];
+    uint32_t bitfields : 23;
+};
+
+COMPILE_ASSERT(sizeof(InlineFlowBox) == sizeof(SameSizeAsInlineFlowBox), InlineFlowBox_should_stay_small);
+
+#ifndef NDEBUG
+
+InlineFlowBox::~InlineFlowBox()
+{
+    if (!m_hasBadChildList)
+        for (InlineBox* child = firstChild(); child; child = child->nextOnLine())
+            child->setHasBadParent();
+}
+
+#endif
+
+LayoutUnit InlineFlowBox::getFlowSpacingLogicalWidth()
+{
+    LayoutUnit totWidth = marginBorderPaddingLogicalLeft() + marginBorderPaddingLogicalRight();
+    for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
+        if (curr->isInlineFlowBox())
+            totWidth += toInlineFlowBox(curr)->getFlowSpacingLogicalWidth();
+    }
+    return totWidth;
+}
+
+IntRect InlineFlowBox::roundedFrameRect() const
+{
+    // Begin by snapping the x and y coordinates to the nearest pixel.
+    int snappedX = lroundf(x());
+    int snappedY = lroundf(y());
+    
+    int snappedMaxX = lroundf(x() + width());
+    int snappedMaxY = lroundf(y() + height());
+    
+    return IntRect(snappedX, snappedY, snappedMaxX - snappedX, snappedMaxY - snappedY);
+}
+
+static void setHasTextDescendantsOnAncestors(InlineFlowBox* box)
+{
+    while (box && !box->hasTextDescendants()) {
+        box->setHasTextDescendants();
+        box = box->parent();
+    }
+}
+
+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(isFirstLineStyle());
+    child->setIsHorizontal(isHorizontal());
+    if (child->isText()) {
+        if (child->renderer()->parent() == renderer())
+            m_hasTextChildren = true;
+        setHasTextDescendantsOnAncestors(this);
+    } else if (child->isInlineFlowBox()) {
+        if (toInlineFlowBox(child)->hasTextDescendants())
+            setHasTextDescendantsOnAncestors(this);
+    }
+
+    if (descendantsHaveSameLineHeightAndBaseline() && !child->renderer()->isOutOfFlowPositioned()) {
+        RenderStyle* parentStyle = renderer()->style(isFirstLineStyle());
+        RenderStyle* childStyle = child->renderer()->style(isFirstLineStyle());
+        bool shouldClearDescendantsHaveSameLineHeightAndBaseline = false;
+        if (child->renderer()->isReplaced())
+            shouldClearDescendantsHaveSameLineHeightAndBaseline = true;
+        else if (child->isText()) {
+            if (child->renderer()->isBR() || child->renderer()->parent() != renderer()) {
+                if (!parentStyle->font().fontMetrics().hasIdenticalAscentDescentAndLineGap(childStyle->font().fontMetrics())
+                    || parentStyle->lineHeight() != childStyle->lineHeight()
+                    || (parentStyle->verticalAlign() != BASELINE && !isRootInlineBox()) || childStyle->verticalAlign() != BASELINE)
+                    shouldClearDescendantsHaveSameLineHeightAndBaseline = true;
+            }
+            if (childStyle->hasTextCombine() || childStyle->textEmphasisMark() != TextEmphasisMarkNone)
+                shouldClearDescendantsHaveSameLineHeightAndBaseline = true;
+        } else {
+            if (child->renderer()->isBR()) {
+                // FIXME: This is dumb. We only turn off because current layout test results expect the <br> to be 0-height on the baseline.
+                // Other than making a zillion tests have to regenerate results, there's no reason to ditch the optimization here.
+                shouldClearDescendantsHaveSameLineHeightAndBaseline = true;
+            } else {
+                ASSERT(isInlineFlowBox());
+                InlineFlowBox* childFlowBox = toInlineFlowBox(child);
+                // Check the child's bit, and then also check for differences in font, line-height, vertical-align
+                if (!childFlowBox->descendantsHaveSameLineHeightAndBaseline()
+                    || !parentStyle->font().fontMetrics().hasIdenticalAscentDescentAndLineGap(childStyle->font().fontMetrics())
+                    || parentStyle->lineHeight() != childStyle->lineHeight()
+                    || (parentStyle->verticalAlign() != BASELINE && !isRootInlineBox()) || childStyle->verticalAlign() != BASELINE
+                    || childStyle->hasBorder() || childStyle->hasPadding() || childStyle->hasTextCombine())
+                    shouldClearDescendantsHaveSameLineHeightAndBaseline = true;
+            }
+        }
+
+        if (shouldClearDescendantsHaveSameLineHeightAndBaseline)
+            clearDescendantsHaveSameLineHeightAndBaseline();
+    }
+
+    if (!child->renderer()->isOutOfFlowPositioned()) {
+        if (child->isText()) {
+            RenderStyle* childStyle = child->renderer()->style(isFirstLineStyle());
+            if (childStyle->letterSpacing() < 0 || childStyle->textShadow() || childStyle->textEmphasisMark() != TextEmphasisMarkNone || childStyle->textStrokeWidth())
+                child->clearKnownToHaveNoOverflow();
+        } else if (child->renderer()->isReplaced()) {
+            RenderBox* box = toRenderBox(child->renderer());
+            if (box->hasRenderOverflow() || box->hasSelfPaintingLayer())
+                child->clearKnownToHaveNoOverflow();
+        } else if (!child->renderer()->isBR() && (child->renderer()->style(isFirstLineStyle())->boxShadow() || child->boxModelObject()->hasSelfPaintingLayer()
+                   || (child->renderer()->isListMarker() && !toRenderListMarker(child->renderer())->isInside())
+                   || child->renderer()->style(isFirstLineStyle())->hasBorderImageOutsets()))
+            child->clearKnownToHaveNoOverflow();
+        
+        if (knownToHaveNoOverflow() && child->isInlineFlowBox() && !toInlineFlowBox(child)->knownToHaveNoOverflow())
+            clearKnownToHaveNoOverflow();
+    }
+
+    checkConsistency();
+}
+
+void InlineFlowBox::removeChild(InlineBox* child)
+{
+    checkConsistency();
+
+    if (!isDirty())
+        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
+
+    removeLineBoxFromRenderObject();
+    destroy(arena);
+}
+
+void InlineFlowBox::removeLineBoxFromRenderObject()
+{
+    toRenderInline(renderer())->lineBoxes()->removeLineBox(this);
+}
+
+void InlineFlowBox::extractLine()
+{
+    if (!extracted())
+        extractLineBoxFromRenderObject();
+    for (InlineBox* child = firstChild(); child; child = child->nextOnLine())
+        child->extractLine();
+}
+
+void InlineFlowBox::extractLineBoxFromRenderObject()
+{
+    toRenderInline(renderer())->lineBoxes()->extractLineBox(this);
+}
+
+void InlineFlowBox::attachLine()
+{
+    if (extracted())
+        attachLineBoxToRenderObject();
+    for (InlineBox* child = firstChild(); child; child = child->nextOnLine())
+        child->attachLine();
+}
+
+void InlineFlowBox::attachLineBoxToRenderObject()
+{
+    toRenderInline(renderer())->lineBoxes()->attachLineBox(this);
+}
+
+void InlineFlowBox::adjustPosition(float dx, float dy)
+{
+    InlineBox::adjustPosition(dx, dy);
+    for (InlineBox* child = firstChild(); child; child = child->nextOnLine())
+        child->adjustPosition(dx, dy);
+    if (m_overflow)
+        m_overflow->move(dx, dy); // FIXME: Rounding error here since overflow was pixel snapped, but nobody other than list markers passes non-integral values here.
+}
+
+RenderLineBoxList* InlineFlowBox::rendererLineBoxes() const
+{
+    return toRenderInline(renderer())->lineBoxes();
+}
+
+static inline bool isLastChildForRenderer(RenderObject* ancestor, RenderObject* child)
+{
+    if (!child)
+        return false;
+    
+    if (child == ancestor)
+        return true;
+
+    RenderObject* curr = child;
+    RenderObject* parent = curr->parent();
+    while (parent && (!parent->isRenderBlock() || parent->isInline())) {
+        if (parent->lastChild() != curr)
+            return false;
+        if (parent == ancestor)
+            return true;
+            
+        curr = parent;
+        parent = curr->parent();
+    }
+
+    return true;
+}
+
+static bool isAnsectorAndWithinBlock(RenderObject* ancestor, RenderObject* child)
+{
+    RenderObject* object = child;
+    while (object && (!object->isRenderBlock() || object->isInline())) {
+        if (object == ancestor)
+            return true;
+        object = object->parent();
+    }
+    return false;
+}
+
+void InlineFlowBox::determineSpacingForFlowBoxes(bool lastLine, bool isLogicallyLastRunWrapped, RenderObject* logicallyLastRunRenderer)
+{
+    // All boxes start off open.  They will not apply any margins/border/padding on
+    // any side.
+    bool includeLeftEdge = false;
+    bool includeRightEdge = false;
+
+    // The root inline box never has borders/margins/padding.
+    if (parent()) {
+        bool ltr = renderer()->style()->isLeftToRightDirection();
+
+        // Check to see if all initial lines are unconstructed.  If so, then
+        // we know the inline began on this line (unless we are a continuation).
+        RenderLineBoxList* lineBoxList = rendererLineBoxes();
+        if (!lineBoxList->firstLineBox()->isConstructed() && !renderer()->isInlineElementContinuation()) {
+            if (renderer()->style()->boxDecorationBreak() == DCLONE)
+                includeLeftEdge = includeRightEdge = true;
+            else if (ltr && lineBoxList->firstLineBox() == this)
+                includeLeftEdge = true;
+            else if (!ltr && lineBoxList->lastLineBox() == this)
+                includeRightEdge = true;
+        }
+
+        if (!lineBoxList->lastLineBox()->isConstructed()) {
+            RenderInline* inlineFlow = toRenderInline(renderer());
+            bool isLastObjectOnLine = !isAnsectorAndWithinBlock(renderer(), logicallyLastRunRenderer) || (isLastChildForRenderer(renderer(), logicallyLastRunRenderer) && !isLogicallyLastRunWrapped);
+
+            // We include the border under these conditions:
+            // (1) The next line was not created, or it is constructed. We check the previous line for rtl.
+            // (2) The logicallyLastRun is not a descendant of this renderer.
+            // (3) The logicallyLastRun is a descendant of this renderer, but it is the last child of this renderer and it does not wrap to the next line.
+            // (4) The decoration break is set to clone therefore there will be borders on every sides.
+            if (renderer()->style()->boxDecorationBreak() == DCLONE)
+                includeLeftEdge = includeRightEdge = true;
+            else if (ltr) {
+                if (!nextLineBox()
+                    && ((lastLine || isLastObjectOnLine) && !inlineFlow->continuation()))
+                    includeRightEdge = true;
+            } else {
+                if ((!prevLineBox() || prevLineBox()->isConstructed())
+                    && ((lastLine || isLastObjectOnLine) && !inlineFlow->continuation()))
+                    includeLeftEdge = true;
+            }
+        }
+    }
+
+    setEdges(includeLeftEdge, includeRightEdge);
+
+    // Recur into our children.
+    for (InlineBox* currChild = firstChild(); currChild; currChild = currChild->nextOnLine()) {
+        if (currChild->isInlineFlowBox()) {
+            InlineFlowBox* currFlow = toInlineFlowBox(currChild);
+            currFlow->determineSpacingForFlowBoxes(lastLine, isLogicallyLastRunWrapped, logicallyLastRunRenderer);
+        }
+    }
+}
+
+float InlineFlowBox::placeBoxesInInlineDirection(float logicalLeft, bool& needsWordSpacing, GlyphOverflowAndFallbackFontsMap& textBoxDataMap)
+{
+    // Set our x position.
+    beginPlacingBoxRangesInInlineDirection(logicalLeft);
+
+    float startLogicalLeft = logicalLeft;
+    logicalLeft += borderLogicalLeft() + paddingLogicalLeft();
+
+    float minLogicalLeft = startLogicalLeft;
+    float maxLogicalRight = logicalLeft;
+
+    placeBoxRangeInInlineDirection(firstChild(), 0, logicalLeft, minLogicalLeft, maxLogicalRight, needsWordSpacing, textBoxDataMap);
+
+    logicalLeft += borderLogicalRight() + paddingLogicalRight();
+    endPlacingBoxRangesInInlineDirection(startLogicalLeft, logicalLeft, minLogicalLeft, maxLogicalRight);
+    return logicalLeft;
+}
+
+float InlineFlowBox::placeBoxRangeInInlineDirection(InlineBox* firstChild, InlineBox* lastChild, float& logicalLeft, float& minLogicalLeft, float& maxLogicalRight, bool& needsWordSpacing, GlyphOverflowAndFallbackFontsMap& textBoxDataMap)
+{
+    for (InlineBox* curr = firstChild; curr && curr != lastChild; curr = curr->nextOnLine()) {
+        if (curr->renderer()->isText()) {
+            InlineTextBox* text = toInlineTextBox(curr);
+            RenderText* rt = toRenderText(text->renderer());
+            if (rt->textLength()) {
+                if (needsWordSpacing && isSpaceOrNewline(rt->characterAt(text->start())))
+                    logicalLeft += rt->style(isFirstLineStyle())->font().wordSpacing();
+                needsWordSpacing = !isSpaceOrNewline(rt->characterAt(text->end()));
+            }
+            text->setLogicalLeft(logicalLeft);
+            if (knownToHaveNoOverflow())
+                minLogicalLeft = min(logicalLeft, minLogicalLeft);
+            logicalLeft += text->logicalWidth();
+            if (knownToHaveNoOverflow())
+                maxLogicalRight = max(logicalLeft, maxLogicalRight);
+        } else {
+            if (curr->renderer()->isOutOfFlowPositioned()) {
+                if (curr->renderer()->parent()->style()->isLeftToRightDirection())
+                    curr->setLogicalLeft(logicalLeft);
+                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->setLogicalLeft(root()->block()->logicalWidth() - logicalLeft);
+                continue; // The positioned object has no effect on the width.
+            }
+            if (curr->renderer()->isRenderInline()) {
+                InlineFlowBox* flow = toInlineFlowBox(curr);
+                logicalLeft += flow->marginLogicalLeft();
+                if (knownToHaveNoOverflow())
+                    minLogicalLeft = min(logicalLeft, minLogicalLeft);
+                logicalLeft = flow->placeBoxesInInlineDirection(logicalLeft, needsWordSpacing, textBoxDataMap);
+                if (knownToHaveNoOverflow())
+                    maxLogicalRight = max(logicalLeft, maxLogicalRight);
+                logicalLeft += flow->marginLogicalRight();
+            } else if (!curr->renderer()->isListMarker() || toRenderListMarker(curr->renderer())->isInside()) {
+                // The box can have a different writing-mode than the overall line, so this is a bit complicated.
+                // Just get all the physical margin and overflow values by hand based off |isVertical|.
+                LayoutUnit logicalLeftMargin = isHorizontal() ? curr->boxModelObject()->marginLeft() : curr->boxModelObject()->marginTop();
+                LayoutUnit logicalRightMargin = isHorizontal() ? curr->boxModelObject()->marginRight() : curr->boxModelObject()->marginBottom();
+                
+                logicalLeft += logicalLeftMargin;
+                curr->setLogicalLeft(logicalLeft);
+                if (knownToHaveNoOverflow())
+                    minLogicalLeft = min(logicalLeft, minLogicalLeft);
+                logicalLeft += curr->logicalWidth();
+                if (knownToHaveNoOverflow())
+                    maxLogicalRight = max(logicalLeft, maxLogicalRight);
+                logicalLeft += logicalRightMargin;
+                // If we encounter any space after this inline block then ensure it is treated as the space between two words.
+                needsWordSpacing = true;
+            }
+        }
+    }
+    return logicalLeft;
+}
+
+bool InlineFlowBox::requiresIdeographicBaseline(const GlyphOverflowAndFallbackFontsMap& textBoxDataMap) const
+{
+    if (isHorizontal())
+        return false;
+    
+    if (renderer()->style(isFirstLineStyle())->fontDescription().nonCJKGlyphOrientation() == NonCJKGlyphOrientationUpright
+        || renderer()->style(isFirstLineStyle())->font().primaryFont()->hasVerticalGlyphs())
+        return true;
+
+    for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
+        if (curr->renderer()->isOutOfFlowPositioned())
+            continue; // Positioned placeholders don't affect calculations.
+        
+        if (curr->isInlineFlowBox()) {
+            if (toInlineFlowBox(curr)->requiresIdeographicBaseline(textBoxDataMap))
+                return true;
+        } else {
+            if (curr->renderer()->style(isFirstLineStyle())->font().primaryFont()->hasVerticalGlyphs())
+                return true;
+            
+            const Vector<const SimpleFontData*>* usedFonts = 0;
+            if (curr->isInlineTextBox()) {
+                GlyphOverflowAndFallbackFontsMap::const_iterator it = textBoxDataMap.find(toInlineTextBox(curr));
+                usedFonts = it == textBoxDataMap.end() ? 0 : &it->value.first;
+            }
+
+            if (usedFonts) {
+                for (size_t i = 0; i < usedFonts->size(); ++i) {
+                    if (usedFonts->at(i)->hasVerticalGlyphs())
+                        return true;
+                }
+            }
+        }
+    }
+    
+    return false;
+}
+
+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->renderer()->isOutOfFlowPositioned())
+            continue; // Positioned placeholders don't affect calculations.
+        if (curr->verticalAlign() == TOP || curr->verticalAlign() == BOTTOM) {
+            int lineHeight = curr->lineHeight();
+            if (curr->verticalAlign() == TOP) {
+                if (maxAscent + maxDescent < lineHeight)
+                    maxDescent = lineHeight - maxAscent;
+            }
+            else {
+                if (maxAscent + maxDescent < lineHeight)
+                    maxAscent = lineHeight - maxDescent;
+            }
+
+            if (maxAscent + maxDescent >= max(maxPositionTop, maxPositionBottom))
+                break;
+        }
+
+        if (curr->isInlineFlowBox())
+            toInlineFlowBox(curr)->adjustMaxAscentAndDescent(maxAscent, maxDescent, maxPositionTop, maxPositionBottom);
+    }
+}
+
+void InlineFlowBox::computeLogicalBoxHeights(RootInlineBox* rootBox, LayoutUnit& maxPositionTop, LayoutUnit& maxPositionBottom,
+                                             int& maxAscent, int& maxDescent, bool& setMaxAscent, bool& setMaxDescent,
+                                             bool strictMode, GlyphOverflowAndFallbackFontsMap& textBoxDataMap,
+                                             FontBaseline baselineType, VerticalPositionCache& verticalPositionCache)
+{
+    // The primary purpose of this function is to compute the maximal ascent and descent values for
+    // a line. These values are computed based off the block's line-box-contain property, which indicates
+    // what parts of descendant boxes have to fit within the line.
+    //
+    // The maxAscent value represents the distance of the highest point of any box (typically including line-height) from
+    // the root box's baseline. The maxDescent value represents the distance of the lowest point of any box
+    // (also typically including line-height) from the root box baseline. These values can be negative.
+    //
+    // A secondary purpose of this function is to store the offset of every box's baseline from the root box's
+    // baseline. This information is cached in the logicalTop() of every box. We're effectively just using
+    // the logicalTop() as scratch space.
+    //
+    // Because a box can be positioned such that it ends up fully above or fully below the
+    // root line box, we only consider it to affect the maxAscent and maxDescent values if some
+    // part of the box (EXCLUDING leading) is above (for ascent) or below (for descent) the root box's baseline.
+    bool affectsAscent = false;
+    bool affectsDescent = false;
+    bool checkChildren = !descendantsHaveSameLineHeightAndBaseline();
+    
+    if (isRootInlineBox()) {
+        // Examine our root box.
+        int ascent = 0;
+        int descent = 0;
+        rootBox->ascentAndDescentForBox(rootBox, textBoxDataMap, ascent, descent, affectsAscent, affectsDescent);
+        if (strictMode || hasTextChildren() || (!checkChildren && hasTextDescendants())) {
+            if (maxAscent < ascent || !setMaxAscent) {
+                maxAscent = ascent;
+                setMaxAscent = true;
+            }
+            if (maxDescent < descent || !setMaxDescent) {
+                maxDescent = descent;
+                setMaxDescent = true;
+            }
+        }
+    }
+
+    if (!checkChildren)
+        return;
+
+    for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
+        if (curr->renderer()->isOutOfFlowPositioned())
+            continue; // Positioned placeholders don't affect calculations.
+        
+        InlineFlowBox* inlineFlowBox = curr->isInlineFlowBox() ? toInlineFlowBox(curr) : 0;
+        
+        bool affectsAscent = false;
+        bool affectsDescent = false;
+        
+        // The verticalPositionForBox function returns the distance between the child box's baseline
+        // and the root box's baseline.  The value is negative if the child box's baseline is above the
+        // root box's baseline, and it is positive if the child box's baseline is below the root box's baseline.
+        curr->setLogicalTop(rootBox->verticalPositionForBox(curr, verticalPositionCache));
+        
+        int ascent = 0;
+        int descent = 0;
+        rootBox->ascentAndDescentForBox(curr, textBoxDataMap, ascent, descent, affectsAscent, affectsDescent);
+
+        LayoutUnit boxHeight = ascent + descent;
+        if (curr->verticalAlign() == TOP) {
+            if (maxPositionTop < boxHeight)
+                maxPositionTop = boxHeight;
+        } else if (curr->verticalAlign() == BOTTOM) {
+            if (maxPositionBottom < boxHeight)
+                maxPositionBottom = boxHeight;
+        } else if (!inlineFlowBox || strictMode || inlineFlowBox->hasTextChildren() || (inlineFlowBox->descendantsHaveSameLineHeightAndBaseline() && inlineFlowBox->hasTextDescendants())
+                   || inlineFlowBox->boxModelObject()->hasInlineDirectionBordersOrPadding()) {
+            // Note that these values can be negative.  Even though we only affect the maxAscent and maxDescent values
+            // if our box (excluding line-height) was above (for ascent) or below (for descent) the root baseline, once you factor in line-height
+            // the final box can end up being fully above or fully below the root box's baseline!  This is ok, but what it
+            // means is that ascent and descent (including leading), can end up being negative.  The setMaxAscent and
+            // setMaxDescent booleans are used to ensure that we're willing to initially set maxAscent/Descent to negative
+            // values.
+            ascent -= curr->logicalTop();
+            descent += curr->logicalTop();
+            if (affectsAscent && (maxAscent < ascent || !setMaxAscent)) {
+                maxAscent = ascent;
+                setMaxAscent = true;
+            }
+
+            if (affectsDescent && (maxDescent < descent || !setMaxDescent)) {
+                maxDescent = descent;
+                setMaxDescent = true;
+            }
+        }
+
+        if (inlineFlowBox)
+            inlineFlowBox->computeLogicalBoxHeights(rootBox, maxPositionTop, maxPositionBottom, maxAscent, maxDescent,
+                                                    setMaxAscent, setMaxDescent, strictMode, textBoxDataMap,
+                                                    baselineType, verticalPositionCache);
+    }
+}
+
+void InlineFlowBox::placeBoxesInBlockDirection(LayoutUnit top, LayoutUnit maxHeight, int maxAscent, bool strictMode, LayoutUnit& lineTop, LayoutUnit& lineBottom, bool& setLineTop,
+                                               LayoutUnit& lineTopIncludingMargins, LayoutUnit& lineBottomIncludingMargins, bool& hasAnnotationsBefore, bool& hasAnnotationsAfter, FontBaseline baselineType)
+{
+    bool isRootBox = isRootInlineBox();
+    if (isRootBox) {
+        const FontMetrics& fontMetrics = renderer()->style(isFirstLineStyle())->fontMetrics();
+        // RootInlineBoxes are always placed on at pixel boundaries in their logical y direction. Not doing
+        // so results in incorrect rendering of text decorations, most notably underlines.
+        setLogicalTop(roundToInt(top + maxAscent - fontMetrics.ascent(baselineType)));
+    }
+
+    LayoutUnit adjustmentForChildrenWithSameLineHeightAndBaseline = 0;
+    if (descendantsHaveSameLineHeightAndBaseline()) {
+        adjustmentForChildrenWithSameLineHeightAndBaseline = logicalTop();
+        if (parent())
+            adjustmentForChildrenWithSameLineHeightAndBaseline += (boxModelObject()->borderBefore() + boxModelObject()->paddingBefore());
+    }
+
+    for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
+        if (curr->renderer()->isOutOfFlowPositioned())
+            continue; // Positioned placeholders don't affect calculations.
+
+        if (descendantsHaveSameLineHeightAndBaseline()) {
+            curr->adjustBlockDirectionPosition(adjustmentForChildrenWithSameLineHeightAndBaseline);
+            continue;
+        }
+
+        InlineFlowBox* inlineFlowBox = curr->isInlineFlowBox() ? toInlineFlowBox(curr) : 0;
+        bool childAffectsTopBottomPos = true;
+        if (curr->verticalAlign() == TOP)
+            curr->setLogicalTop(top);
+        else if (curr->verticalAlign() == BOTTOM)
+            curr->setLogicalTop(top + maxHeight - curr->lineHeight());
+        else {
+            if (!strictMode && inlineFlowBox && !inlineFlowBox->hasTextChildren() && !curr->boxModelObject()->hasInlineDirectionBordersOrPadding()
+                && !(inlineFlowBox->descendantsHaveSameLineHeightAndBaseline() && inlineFlowBox->hasTextDescendants()))
+                childAffectsTopBottomPos = false;
+            LayoutUnit posAdjust = maxAscent - curr->baselinePosition(baselineType);
+            curr->setLogicalTop(curr->logicalTop() + top + posAdjust);
+        }
+        
+        LayoutUnit newLogicalTop = curr->logicalTop();
+        LayoutUnit newLogicalTopIncludingMargins = newLogicalTop;
+        LayoutUnit boxHeight = curr->logicalHeight();
+        LayoutUnit boxHeightIncludingMargins = boxHeight;
+            
+        if (curr->isText() || curr->isInlineFlowBox()) {
+            const FontMetrics& fontMetrics = curr->renderer()->style(isFirstLineStyle())->fontMetrics();
+            newLogicalTop += curr->baselinePosition(baselineType) - fontMetrics.ascent(baselineType);
+            if (curr->isInlineFlowBox()) {
+                RenderBoxModelObject* boxObject = toRenderBoxModelObject(curr->renderer());
+                newLogicalTop -= boxObject->style(isFirstLineStyle())->isHorizontalWritingMode() ? boxObject->borderTop() + boxObject->paddingTop() : 
+                                 boxObject->borderRight() + boxObject->paddingRight();
+            }
+            newLogicalTopIncludingMargins = newLogicalTop;
+        } else if (!curr->renderer()->isBR()) {
+            RenderBox* box = toRenderBox(curr->renderer());
+            newLogicalTopIncludingMargins = newLogicalTop;
+            LayoutUnit overSideMargin = curr->isHorizontal() ? box->marginTop() : box->marginRight();
+            LayoutUnit underSideMargin = curr->isHorizontal() ? box->marginBottom() : box->marginLeft();
+            newLogicalTop += overSideMargin;
+            boxHeightIncludingMargins += overSideMargin + underSideMargin;
+        }
+
+        curr->setLogicalTop(newLogicalTop);
+
+        if (childAffectsTopBottomPos) {
+            if (curr->renderer()->isRubyRun()) {
+                // Treat the leading on the first and last lines of ruby runs as not being part of the overall lineTop/lineBottom.
+                // Really this is a workaround hack for the fact that ruby should have been done as line layout and not done using
+                // inline-block.
+                if (renderer()->style()->isFlippedLinesWritingMode() == (curr->renderer()->style()->rubyPosition() == RubyPositionAfter))
+                    hasAnnotationsBefore = true;
+                else
+                    hasAnnotationsAfter = true;
+
+                RenderRubyRun* rubyRun = toRenderRubyRun(curr->renderer());
+                if (RenderRubyBase* rubyBase = rubyRun->rubyBase()) {
+                    LayoutUnit bottomRubyBaseLeading = (curr->logicalHeight() - rubyBase->logicalBottom()) + rubyBase->logicalHeight() - (rubyBase->lastRootBox() ? rubyBase->lastRootBox()->lineBottom() : LayoutUnit());
+                    LayoutUnit topRubyBaseLeading = rubyBase->logicalTop() + (rubyBase->firstRootBox() ? rubyBase->firstRootBox()->lineTop() : LayoutUnit());
+                    newLogicalTop += !renderer()->style()->isFlippedLinesWritingMode() ? topRubyBaseLeading : bottomRubyBaseLeading;
+                    boxHeight -= (topRubyBaseLeading + bottomRubyBaseLeading);
+                }
+            }
+            if (curr->isInlineTextBox()) {
+                TextEmphasisPosition emphasisMarkPosition;
+                if (toInlineTextBox(curr)->getEmphasisMarkPosition(curr->renderer()->style(isFirstLineStyle()), emphasisMarkPosition)) {
+                    bool emphasisMarkIsOver = emphasisMarkPosition == TextEmphasisPositionOver;
+                    if (emphasisMarkIsOver != curr->renderer()->style(isFirstLineStyle())->isFlippedLinesWritingMode())
+                        hasAnnotationsBefore = true;
+                    else
+                        hasAnnotationsAfter = true;
+                }
+            }
+
+            if (!setLineTop) {
+                setLineTop = true;
+                lineTop = newLogicalTop;
+                lineTopIncludingMargins = min(lineTop, newLogicalTopIncludingMargins);
+            } else {
+                lineTop = min(lineTop, newLogicalTop);
+                lineTopIncludingMargins = min(lineTop, min(lineTopIncludingMargins, newLogicalTopIncludingMargins));
+            }
+            lineBottom = max(lineBottom, newLogicalTop + boxHeight);
+            lineBottomIncludingMargins = max(lineBottom, max(lineBottomIncludingMargins, newLogicalTopIncludingMargins + boxHeightIncludingMargins));
+        }
+
+        // Adjust boxes to use their real box y/height and not the logical height (as dictated by
+        // line-height).
+        if (inlineFlowBox)
+            inlineFlowBox->placeBoxesInBlockDirection(top, maxHeight, maxAscent, strictMode, lineTop, lineBottom, setLineTop,
+                                                      lineTopIncludingMargins, lineBottomIncludingMargins, hasAnnotationsBefore, hasAnnotationsAfter, baselineType);
+    }
+
+    if (isRootBox) {
+        if (strictMode || hasTextChildren() || (descendantsHaveSameLineHeightAndBaseline() && hasTextDescendants())) {
+            if (!setLineTop) {
+                setLineTop = true;
+                lineTop = pixelSnappedLogicalTop();
+                lineTopIncludingMargins = lineTop;
+            } else {
+                lineTop = min<LayoutUnit>(lineTop, pixelSnappedLogicalTop());
+                lineTopIncludingMargins = min(lineTop, lineTopIncludingMargins);
+            }
+            lineBottom = max<LayoutUnit>(lineBottom, pixelSnappedLogicalBottom());
+            lineBottomIncludingMargins = max(lineBottom, lineBottomIncludingMargins);
+        }
+        
+        if (renderer()->style()->isFlippedLinesWritingMode())
+            flipLinesInBlockDirection(lineTopIncludingMargins, lineBottomIncludingMargins);
+    }
+}
+
+#if ENABLE(CSS3_TEXT)
+void InlineFlowBox::computeMaxLogicalTop(float& maxLogicalTop)
+{
+    for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
+        if (curr->renderer()->isOutOfFlowPositioned())
+            continue; // Positioned placeholders don't affect calculations.
+
+        if (descendantsHaveSameLineHeightAndBaseline())
+            continue;
+
+        maxLogicalTop = max<float>(maxLogicalTop, curr->y());
+        float localMaxLogicalTop = 0;
+        if (curr->isInlineFlowBox())
+            toInlineFlowBox(curr)->computeMaxLogicalTop(localMaxLogicalTop);
+        maxLogicalTop = max<float>(maxLogicalTop, localMaxLogicalTop);
+    }
+}
+#endif // CSS3_TEXT
+
+void InlineFlowBox::flipLinesInBlockDirection(LayoutUnit lineTop, LayoutUnit lineBottom)
+{
+    // Flip the box on the line such that the top is now relative to the lineBottom instead of the lineTop.
+    setLogicalTop(lineBottom - (logicalTop() - lineTop) - logicalHeight());
+    
+    for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
+        if (curr->renderer()->isOutOfFlowPositioned())
+            continue; // Positioned placeholders aren't affected here.
+        
+        if (curr->isInlineFlowBox())
+            toInlineFlowBox(curr)->flipLinesInBlockDirection(lineTop, lineBottom);
+        else
+            curr->setLogicalTop(lineBottom - (curr->logicalTop() - lineTop) - curr->logicalHeight());
+    }
+}
+
+inline void InlineFlowBox::addBoxShadowVisualOverflow(LayoutRect& logicalVisualOverflow)
+{
+    // box-shadow on root line boxes is applying to the block and not to the lines.
+    if (!parent())
+        return;
+
+    RenderStyle* style = renderer()->style(isFirstLineStyle());
+    if (!style->boxShadow())
+        return;
+
+    LayoutUnit boxShadowLogicalTop;
+    LayoutUnit boxShadowLogicalBottom;
+    style->getBoxShadowBlockDirectionExtent(boxShadowLogicalTop, boxShadowLogicalBottom);
+    
+    // Similar to how glyph overflow works, if our lines are flipped, then it's actually the opposite shadow that applies, since
+    // the line is "upside down" in terms of block coordinates.
+    LayoutUnit shadowLogicalTop = style->isFlippedLinesWritingMode() ? -boxShadowLogicalBottom : boxShadowLogicalTop;
+    LayoutUnit shadowLogicalBottom = style->isFlippedLinesWritingMode() ? -boxShadowLogicalTop : boxShadowLogicalBottom;
+    
+    LayoutUnit logicalTopVisualOverflow = min(pixelSnappedLogicalTop() + shadowLogicalTop, logicalVisualOverflow.y());
+    LayoutUnit logicalBottomVisualOverflow = max(pixelSnappedLogicalBottom() + shadowLogicalBottom, logicalVisualOverflow.maxY());
+    
+    LayoutUnit boxShadowLogicalLeft;
+    LayoutUnit boxShadowLogicalRight;
+    style->getBoxShadowInlineDirectionExtent(boxShadowLogicalLeft, boxShadowLogicalRight);
+
+    LayoutUnit logicalLeftVisualOverflow = min(pixelSnappedLogicalLeft() + boxShadowLogicalLeft, logicalVisualOverflow.x());
+    LayoutUnit logicalRightVisualOverflow = max(pixelSnappedLogicalRight() + boxShadowLogicalRight, logicalVisualOverflow.maxX());
+    
+    logicalVisualOverflow = LayoutRect(logicalLeftVisualOverflow, logicalTopVisualOverflow,
+                                       logicalRightVisualOverflow - logicalLeftVisualOverflow, logicalBottomVisualOverflow - logicalTopVisualOverflow);
+}
+
+inline void InlineFlowBox::addBorderOutsetVisualOverflow(LayoutRect& logicalVisualOverflow)
+{
+    // border-image-outset on root line boxes is applying to the block and not to the lines.
+    if (!parent())
+        return;
+    
+    RenderStyle* style = renderer()->style(isFirstLineStyle());
+    if (!style->hasBorderImageOutsets())
+        return;
+
+    LayoutBoxExtent borderOutsets = style->borderImageOutsets();
+
+    LayoutUnit borderOutsetLogicalTop = borderOutsets.logicalTop(style->writingMode());
+    LayoutUnit borderOutsetLogicalBottom = borderOutsets.logicalBottom(style->writingMode());
+    LayoutUnit borderOutsetLogicalLeft = borderOutsets.logicalLeft(style->writingMode());
+    LayoutUnit borderOutsetLogicalRight = borderOutsets.logicalRight(style->writingMode());
+
+    // Similar to how glyph overflow works, if our lines are flipped, then it's actually the opposite border that applies, since
+    // the line is "upside down" in terms of block coordinates. vertical-rl and horizontal-bt are the flipped line modes.
+    LayoutUnit outsetLogicalTop = style->isFlippedLinesWritingMode() ? borderOutsetLogicalBottom : borderOutsetLogicalTop;
+    LayoutUnit outsetLogicalBottom = style->isFlippedLinesWritingMode() ? borderOutsetLogicalTop : borderOutsetLogicalBottom;
+
+    LayoutUnit logicalTopVisualOverflow = min(pixelSnappedLogicalTop() - outsetLogicalTop, logicalVisualOverflow.y());
+    LayoutUnit logicalBottomVisualOverflow = max(pixelSnappedLogicalBottom() + outsetLogicalBottom, logicalVisualOverflow.maxY());
+
+    LayoutUnit outsetLogicalLeft = includeLogicalLeftEdge() ? borderOutsetLogicalLeft : LayoutUnit();
+    LayoutUnit outsetLogicalRight = includeLogicalRightEdge() ? borderOutsetLogicalRight : LayoutUnit();
+
+    LayoutUnit logicalLeftVisualOverflow = min(pixelSnappedLogicalLeft() - outsetLogicalLeft, logicalVisualOverflow.x());
+    LayoutUnit logicalRightVisualOverflow = max(pixelSnappedLogicalRight() + outsetLogicalRight, logicalVisualOverflow.maxX());
+    
+    logicalVisualOverflow = LayoutRect(logicalLeftVisualOverflow, logicalTopVisualOverflow,
+                                       logicalRightVisualOverflow - logicalLeftVisualOverflow, logicalBottomVisualOverflow - logicalTopVisualOverflow);
+}
+
+inline void InlineFlowBox::addTextBoxVisualOverflow(InlineTextBox* textBox, GlyphOverflowAndFallbackFontsMap& textBoxDataMap, LayoutRect& logicalVisualOverflow)
+{
+    if (textBox->knownToHaveNoOverflow())
+        return;
+
+    RenderStyle* style = textBox->renderer()->style(isFirstLineStyle());
+    
+    GlyphOverflowAndFallbackFontsMap::iterator it = textBoxDataMap.find(textBox);
+    GlyphOverflow* glyphOverflow = it == textBoxDataMap.end() ? 0 : &it->value.second;
+    bool isFlippedLine = style->isFlippedLinesWritingMode();
+
+    int topGlyphEdge = glyphOverflow ? (isFlippedLine ? glyphOverflow->bottom : glyphOverflow->top) : 0;
+    int bottomGlyphEdge = glyphOverflow ? (isFlippedLine ? glyphOverflow->top : glyphOverflow->bottom) : 0;
+    int leftGlyphEdge = glyphOverflow ? glyphOverflow->left : 0;
+    int rightGlyphEdge = glyphOverflow ? glyphOverflow->right : 0;
+
+    int strokeOverflow = static_cast<int>(ceilf(style->textStrokeWidth() / 2.0f));
+    int topGlyphOverflow = -strokeOverflow - topGlyphEdge;
+    int bottomGlyphOverflow = strokeOverflow + bottomGlyphEdge;
+    int leftGlyphOverflow = -strokeOverflow - leftGlyphEdge;
+    int rightGlyphOverflow = strokeOverflow + rightGlyphEdge;
+
+    TextEmphasisPosition emphasisMarkPosition;
+    if (style->textEmphasisMark() != TextEmphasisMarkNone && textBox->getEmphasisMarkPosition(style, emphasisMarkPosition)) {
+        int emphasisMarkHeight = style->font().emphasisMarkHeight(style->textEmphasisMarkString());
+        if ((emphasisMarkPosition == TextEmphasisPositionOver) == (!style->isFlippedLinesWritingMode()))
+            topGlyphOverflow = min(topGlyphOverflow, -emphasisMarkHeight);
+        else
+            bottomGlyphOverflow = max(bottomGlyphOverflow, emphasisMarkHeight);
+    }
+
+    // If letter-spacing is negative, we should factor that into right layout overflow. (Even in RTL, letter-spacing is
+    // applied to the right, so this is not an issue with left overflow.
+    rightGlyphOverflow -= min(0, (int)style->font().letterSpacing());
+
+    LayoutUnit textShadowLogicalTop;
+    LayoutUnit textShadowLogicalBottom;
+    style->getTextShadowBlockDirectionExtent(textShadowLogicalTop, textShadowLogicalBottom);
+    
+    LayoutUnit childOverflowLogicalTop = min<LayoutUnit>(textShadowLogicalTop + topGlyphOverflow, topGlyphOverflow);
+    LayoutUnit childOverflowLogicalBottom = max<LayoutUnit>(textShadowLogicalBottom + bottomGlyphOverflow, bottomGlyphOverflow);
+   
+    LayoutUnit textShadowLogicalLeft;
+    LayoutUnit textShadowLogicalRight;
+    style->getTextShadowInlineDirectionExtent(textShadowLogicalLeft, textShadowLogicalRight);
+   
+    LayoutUnit childOverflowLogicalLeft = min<LayoutUnit>(textShadowLogicalLeft + leftGlyphOverflow, leftGlyphOverflow);
+    LayoutUnit childOverflowLogicalRight = max<LayoutUnit>(textShadowLogicalRight + rightGlyphOverflow, rightGlyphOverflow);
+
+    LayoutUnit logicalTopVisualOverflow = min(textBox->pixelSnappedLogicalTop() + childOverflowLogicalTop, logicalVisualOverflow.y());
+    LayoutUnit logicalBottomVisualOverflow = max(textBox->pixelSnappedLogicalBottom() + childOverflowLogicalBottom, logicalVisualOverflow.maxY());
+    LayoutUnit logicalLeftVisualOverflow = min(textBox->pixelSnappedLogicalLeft() + childOverflowLogicalLeft, logicalVisualOverflow.x());
+    LayoutUnit logicalRightVisualOverflow = max(textBox->pixelSnappedLogicalRight() + childOverflowLogicalRight, logicalVisualOverflow.maxX());
+    
+    logicalVisualOverflow = LayoutRect(logicalLeftVisualOverflow, logicalTopVisualOverflow,
+                                       logicalRightVisualOverflow - logicalLeftVisualOverflow, logicalBottomVisualOverflow - logicalTopVisualOverflow);
+                                    
+    textBox->setLogicalOverflowRect(logicalVisualOverflow);
+}
+
+inline void InlineFlowBox::addReplacedChildOverflow(const InlineBox* inlineBox, LayoutRect& logicalLayoutOverflow, LayoutRect& logicalVisualOverflow)
+{
+    RenderBox* box = toRenderBox(inlineBox->renderer());
+    
+    // Visual overflow only propagates if the box doesn't have a self-painting layer.  This rectangle does not include
+    // transforms or relative positioning (since those objects always have self-painting layers), but it does need to be adjusted
+    // for writing-mode differences.
+    if (!box->hasSelfPaintingLayer()) {
+        LayoutRect childLogicalVisualOverflow = box->logicalVisualOverflowRectForPropagation(renderer()->style());
+        childLogicalVisualOverflow.move(inlineBox->logicalLeft(), inlineBox->logicalTop());
+        logicalVisualOverflow.unite(childLogicalVisualOverflow);
+    }
+
+    // Layout overflow internal to the child box only propagates if the child box doesn't have overflow clip set.
+    // Otherwise the child border box propagates as layout overflow.  This rectangle must include transforms and relative positioning
+    // and be adjusted for writing-mode differences.
+    LayoutRect childLogicalLayoutOverflow = box->logicalLayoutOverflowRectForPropagation(renderer()->style());
+    childLogicalLayoutOverflow.move(inlineBox->logicalLeft(), inlineBox->logicalTop());
+    logicalLayoutOverflow.unite(childLogicalLayoutOverflow);
+}
+
+void InlineFlowBox::computeOverflow(LayoutUnit lineTop, LayoutUnit lineBottom, GlyphOverflowAndFallbackFontsMap& textBoxDataMap)
+{
+    // If we know we have no overflow, we can just bail.
+    if (knownToHaveNoOverflow())
+        return;
+
+    // Visual overflow just includes overflow for stuff we need to repaint ourselves.  Self-painting layers are ignored.
+    // Layout overflow is used to determine scrolling extent, so it still includes child layers and also factors in
+    // transforms, relative positioning, etc.
+    LayoutRect logicalLayoutOverflow(enclosingLayoutRect(logicalFrameRectIncludingLineHeight(lineTop, lineBottom)));
+    LayoutRect logicalVisualOverflow(logicalLayoutOverflow);
+  
+    addBoxShadowVisualOverflow(logicalVisualOverflow);
+    addBorderOutsetVisualOverflow(logicalVisualOverflow);
+
+    for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
+        if (curr->renderer()->isOutOfFlowPositioned())
+            continue; // Positioned placeholders don't affect calculations.
+        
+        if (curr->renderer()->isText()) {
+            InlineTextBox* text = toInlineTextBox(curr);
+            RenderText* rt = toRenderText(text->renderer());
+            if (rt->isBR())
+                continue;
+            LayoutRect textBoxOverflow(enclosingLayoutRect(text->logicalFrameRect()));
+            addTextBoxVisualOverflow(text, textBoxDataMap, textBoxOverflow);
+            logicalVisualOverflow.unite(textBoxOverflow);
+        } else  if (curr->renderer()->isRenderInline()) {
+            InlineFlowBox* flow = toInlineFlowBox(curr);
+            flow->computeOverflow(lineTop, lineBottom, textBoxDataMap);
+            if (!flow->boxModelObject()->hasSelfPaintingLayer())
+                logicalVisualOverflow.unite(flow->logicalVisualOverflowRect(lineTop, lineBottom));
+            LayoutRect childLayoutOverflow = flow->logicalLayoutOverflowRect(lineTop, lineBottom);
+            childLayoutOverflow.move(flow->boxModelObject()->relativePositionLogicalOffset());
+            logicalLayoutOverflow.unite(childLayoutOverflow);
+        } else
+            addReplacedChildOverflow(curr, logicalLayoutOverflow, logicalVisualOverflow);
+    }
+    
+    setOverflowFromLogicalRects(logicalLayoutOverflow, logicalVisualOverflow, lineTop, lineBottom);
+}
+
+void InlineFlowBox::setLayoutOverflow(const LayoutRect& rect, LayoutUnit lineTop, LayoutUnit lineBottom)
+{
+    LayoutRect frameBox = enclosingLayoutRect(frameRectIncludingLineHeight(lineTop, lineBottom));
+    if (frameBox.contains(rect) || rect.isEmpty())
+        return;
+
+    if (!m_overflow)
+        m_overflow = adoptPtr(new RenderOverflow(frameBox, frameBox));
+    
+    m_overflow->setLayoutOverflow(rect);
+}
+
+void InlineFlowBox::setVisualOverflow(const LayoutRect& rect, LayoutUnit lineTop, LayoutUnit lineBottom)
+{
+    LayoutRect frameBox = enclosingLayoutRect(frameRectIncludingLineHeight(lineTop, lineBottom));
+    if (frameBox.contains(rect) || rect.isEmpty())
+        return;
+        
+    if (!m_overflow)
+        m_overflow = adoptPtr(new RenderOverflow(frameBox, frameBox));
+    
+    m_overflow->setVisualOverflow(rect);
+}
+
+void InlineFlowBox::setOverflowFromLogicalRects(const LayoutRect& logicalLayoutOverflow, const LayoutRect& logicalVisualOverflow, LayoutUnit lineTop, LayoutUnit lineBottom)
+{
+    LayoutRect layoutOverflow(isHorizontal() ? logicalLayoutOverflow : logicalLayoutOverflow.transposedRect());
+    setLayoutOverflow(layoutOverflow, lineTop, lineBottom);
+    
+    LayoutRect visualOverflow(isHorizontal() ? logicalVisualOverflow : logicalVisualOverflow.transposedRect());
+    setVisualOverflow(visualOverflow, lineTop, lineBottom);
+}
+
+bool InlineFlowBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom)
+{
+    LayoutRect overflowRect(visualOverflowRect(lineTop, lineBottom));
+    flipForWritingMode(overflowRect);
+    overflowRect.moveBy(accumulatedOffset);
+    if (!locationInContainer.intersects(overflowRect))
+        return false;
+
+    // Check children first.
+    // We need to account for culled inline parents of the hit-tested nodes, so that they may also get included in area-based hit-tests.
+    RenderObject* culledParent = 0;
+    for (InlineBox* curr = lastChild(); curr; curr = curr->prevOnLine()) {
+        if (curr->renderer()->isText() || !curr->boxModelObject()->hasSelfPaintingLayer()) {
+            RenderObject* newParent = 0;
+            // Culled parents are only relevant for area-based hit-tests, so ignore it in point-based ones.
+            if (locationInContainer.isRectBasedTest()) {
+                newParent = curr->renderer()->parent();
+                if (newParent == renderer())
+                    newParent = 0;
+            }
+            // Check the culled parent after all its children have been checked, to do this we wait until
+            // we are about to test an element with a different parent.
+            if (newParent != culledParent) {
+                if (!newParent || !newParent->isDescendantOf(culledParent)) {
+                    while (culledParent && culledParent != renderer() && culledParent != newParent) {
+                        if (culledParent->isRenderInline() && toRenderInline(culledParent)->hitTestCulledInline(request, result, locationInContainer, accumulatedOffset))
+                            return true;
+                        culledParent = culledParent->parent();
+                    }
+                }
+                culledParent = newParent;
+            }
+            if (curr->nodeAtPoint(request, result, locationInContainer, accumulatedOffset, lineTop, lineBottom)) {
+                renderer()->updateHitTestResult(result, locationInContainer.point() - toLayoutSize(accumulatedOffset));
+                return true;
+            }
+        }
+    }
+    // Check any culled ancestor of the final children tested.
+    while (culledParent && culledParent != renderer()) {
+        if (culledParent->isRenderInline() && toRenderInline(culledParent)->hitTestCulledInline(request, result, locationInContainer, accumulatedOffset))
+            return true;
+        culledParent = culledParent->parent();
+    }
+
+    // Now check ourselves. Pixel snap hit testing.
+    LayoutRect frameRect = roundedFrameRect();
+    LayoutUnit minX = frameRect.x();
+    LayoutUnit minY = frameRect.y();
+    LayoutUnit width = frameRect.width();
+    LayoutUnit height = frameRect.height();
+
+    // Constrain our hit testing to the line top and bottom if necessary.
+    bool noQuirksMode = renderer()->document()->inNoQuirksMode();
+    if (!noQuirksMode && !hasTextChildren() && !(descendantsHaveSameLineHeightAndBaseline() && hasTextDescendants())) {
+        RootInlineBox* rootBox = root();
+        LayoutUnit& top = isHorizontal() ? minY : minX;
+        LayoutUnit& logicalHeight = isHorizontal() ? height : width;
+        LayoutUnit bottom = min(rootBox->lineBottom(), top + logicalHeight);
+        top = max(rootBox->lineTop(), top);
+        logicalHeight = bottom - top;
+    }
+
+    // Move x/y to our coordinates.
+    LayoutRect rect(minX, minY, width, height);
+    flipForWritingMode(rect);
+    rect.moveBy(accumulatedOffset);
+
+    if (visibleToHitTestRequest(request) && locationInContainer.intersects(rect)) {
+        renderer()->updateHitTestResult(result, flipForWritingMode(locationInContainer.point() - toLayoutSize(accumulatedOffset))); // Don't add in m_x or m_y here, we want coords in the containing block's space.
+        if (!result.addNodeToRectBasedTestResult(renderer()->node(), request, locationInContainer, rect))
+            return true;
+    }
+
+    return false;
+}
+
+void InlineFlowBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit lineTop, LayoutUnit lineBottom)
+{
+    LayoutRect overflowRect(visualOverflowRect(lineTop, lineBottom));
+    overflowRect.inflate(renderer()->maximalOutlineSize(paintInfo.phase));
+    flipForWritingMode(overflowRect);
+    overflowRect.moveBy(paintOffset);
+    
+    if (!paintInfo.rect.intersects(pixelSnappedIntRect(overflowRect)))
+        return;
+
+    if (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 (renderer()->style()->visibility() == VISIBLE && renderer()->hasOutline() && !isRootInlineBox()) {
+                RenderInline* inlineFlow = toRenderInline(renderer());
+
+                RenderBlock* cb = 0;
+                bool containingBlockPaintsContinuationOutline = inlineFlow->continuation() || inlineFlow->isInlineElementContinuation();
+                if (containingBlockPaintsContinuationOutline) {           
+                    // FIXME: See https://bugs.webkit.org/show_bug.cgi?id=54690. We currently don't reconnect inline continuations
+                    // after a child removal. As a result, those merged inlines do not get seperated and hence not get enclosed by
+                    // anonymous blocks. In this case, it is better to bail out and paint it ourself.
+                    RenderBlock* enclosingAnonymousBlock = renderer()->containingBlock();
+                    if (!enclosingAnonymousBlock->isAnonymousBlock())
+                        containingBlockPaintsContinuationOutline = false;
+                    else {
+                        cb = enclosingAnonymousBlock->containingBlock();
+                        for (RenderBoxModelObject* box = boxModelObject(); box != cb; box = box->parent()->enclosingBoxModelObject()) {
+                            if (box->hasSelfPaintingLayer()) {
+                                containingBlockPaintsContinuationOutline = false;
+                                break;
+                            }
+                        }
+                    }
+                }
+
+                if (containingBlockPaintsContinuationOutline) {
+                    // Add ourselves to the containing block of the entire continuation so that it can
+                    // paint us atomically.
+                    cb->addContinuationWithOutline(toRenderInline(renderer()->node()->renderer()));
+                } else if (!inlineFlow->isInlineElementContinuation())
+                    paintInfo.outlineObjects->add(inlineFlow);
+            }
+        } else if (paintInfo.phase == PaintPhaseMask) {
+            paintMask(paintInfo, paintOffset);
+            return;
+        } else {
+            // Paint our background, border and box-shadow.
+            paintBoxDecorations(paintInfo, paintOffset);
+        }
+    }
+
+    if (paintInfo.phase == PaintPhaseMask)
+        return;
+
+    PaintPhase paintPhase = paintInfo.phase == PaintPhaseChildOutlines ? PaintPhaseOutline : paintInfo.phase;
+    PaintInfo childInfo(paintInfo);
+    childInfo.phase = paintPhase;
+    childInfo.updatePaintingRootForChildren(renderer());
+    
+    // Paint our children.
+    if (paintPhase != PaintPhaseSelfOutline) {
+        for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
+            if (curr->renderer()->isText() || !curr->boxModelObject()->hasSelfPaintingLayer())
+                curr->paint(childInfo, paintOffset, lineTop, lineBottom);
+        }
+    }
+}
+
+void InlineFlowBox::paintFillLayers(const PaintInfo& paintInfo, const Color& c, const FillLayer* fillLayer, const LayoutRect& rect, CompositeOperator op)
+{
+    if (!fillLayer)
+        return;
+    paintFillLayers(paintInfo, c, fillLayer->next(), rect, op);
+    paintFillLayer(paintInfo, c, fillLayer, rect, op);
+}
+
+bool InlineFlowBox::boxShadowCanBeAppliedToBackground(const FillLayer& lastBackgroundLayer) const
+{
+    // The checks here match how paintFillLayer() decides whether to clip (if it does, the shadow
+    // would be clipped out, so it has to be drawn separately).
+    StyleImage* image = lastBackgroundLayer.image();
+    bool hasFillImage = image && image->canRender(renderer(), renderer()->style()->effectiveZoom());
+    return (!hasFillImage && !renderer()->style()->hasBorderRadius()) || (!prevLineBox() && !nextLineBox()) || !parent();
+}
+
+void InlineFlowBox::paintFillLayer(const PaintInfo& paintInfo, const Color& c, const FillLayer* fillLayer, const LayoutRect& rect, CompositeOperator op)
+{
+    StyleImage* img = fillLayer->image();
+    bool hasFillImage = img && img->canRender(renderer(), renderer()->style()->effectiveZoom());
+    if ((!hasFillImage && !renderer()->style()->hasBorderRadius()) || (!prevLineBox() && !nextLineBox()) || !parent())
+        boxModelObject()->paintFillLayerExtended(paintInfo, c, fillLayer, rect, BackgroundBleedNone, this, rect.size(), op);
+    else if (renderer()->style()->boxDecorationBreak() == DCLONE) {
+        GraphicsContextStateSaver stateSaver(*paintInfo.context);
+        paintInfo.context->clip(LayoutRect(rect.x(), rect.y(), width(), height()));
+        boxModelObject()->paintFillLayerExtended(paintInfo, c, fillLayer, rect, BackgroundBleedNone, this, rect.size(), 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.
+        LayoutUnit logicalOffsetOnLine = 0;
+        LayoutUnit totalLogicalWidth;
+        if (renderer()->style()->direction() == LTR) {
+            for (InlineFlowBox* curr = prevLineBox(); curr; curr = curr->prevLineBox())
+                logicalOffsetOnLine += curr->logicalWidth();
+            totalLogicalWidth = logicalOffsetOnLine;
+            for (InlineFlowBox* curr = this; curr; curr = curr->nextLineBox())
+                totalLogicalWidth += curr->logicalWidth();
+        } else {
+            for (InlineFlowBox* curr = nextLineBox(); curr; curr = curr->nextLineBox())
+                logicalOffsetOnLine += curr->logicalWidth();
+            totalLogicalWidth = logicalOffsetOnLine;
+            for (InlineFlowBox* curr = this; curr; curr = curr->prevLineBox())
+                totalLogicalWidth += curr->logicalWidth();
+        }
+        LayoutUnit stripX = rect.x() - (isHorizontal() ? logicalOffsetOnLine : LayoutUnit());
+        LayoutUnit stripY = rect.y() - (isHorizontal() ? LayoutUnit() : logicalOffsetOnLine);
+        LayoutUnit stripWidth = isHorizontal() ? totalLogicalWidth : static_cast<LayoutUnit>(width());
+        LayoutUnit stripHeight = isHorizontal() ? static_cast<LayoutUnit>(height()) : totalLogicalWidth;
+
+        GraphicsContextStateSaver stateSaver(*paintInfo.context);
+        paintInfo.context->clip(LayoutRect(rect.x(), rect.y(), width(), height()));
+        boxModelObject()->paintFillLayerExtended(paintInfo, c, fillLayer, LayoutRect(stripX, stripY, stripWidth, stripHeight), BackgroundBleedNone, this, rect.size(), op);
+    }
+}
+
+void InlineFlowBox::paintBoxShadow(const PaintInfo& info, RenderStyle* s, ShadowStyle shadowStyle, const LayoutRect& paintRect)
+{
+    if ((!prevLineBox() && !nextLineBox()) || !parent())
+        boxModelObject()->paintBoxShadow(info, paintRect, s, shadowStyle);
+    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
+        boxModelObject()->paintBoxShadow(info, paintRect, s, shadowStyle, includeLogicalLeftEdge(), includeLogicalRightEdge());
+    }
+}
+
+void InlineFlowBox::constrainToLineTopAndBottomIfNeeded(LayoutRect& rect) const
+{
+    bool noQuirksMode = renderer()->document()->inNoQuirksMode();
+    if (!noQuirksMode && !hasTextChildren() && !(descendantsHaveSameLineHeightAndBaseline() && hasTextDescendants())) {
+        const RootInlineBox* rootBox = root();
+        LayoutUnit logicalTop = isHorizontal() ? rect.y() : rect.x();
+        LayoutUnit logicalHeight = isHorizontal() ? rect.height() : rect.width();
+        LayoutUnit bottom = min(rootBox->lineBottom(), logicalTop + logicalHeight);
+        logicalTop = max(rootBox->lineTop(), logicalTop);
+        logicalHeight = bottom - logicalTop;
+        if (isHorizontal()) {
+            rect.setY(logicalTop);
+            rect.setHeight(logicalHeight);
+        } else {
+            rect.setX(logicalTop);
+            rect.setWidth(logicalHeight);
+        }
+    }
+}
+
+static LayoutRect clipRectForNinePieceImageStrip(InlineFlowBox* box, const NinePieceImage& image, const LayoutRect& paintRect)
+{
+    LayoutRect clipRect(paintRect);
+    RenderStyle* style = box->renderer()->style();
+    LayoutBoxExtent outsets = style->imageOutsets(image);
+    if (box->isHorizontal()) {
+        clipRect.setY(paintRect.y() - outsets.top());
+        clipRect.setHeight(paintRect.height() + outsets.top() + outsets.bottom());
+        if (box->includeLogicalLeftEdge()) {
+            clipRect.setX(paintRect.x() - outsets.left());
+            clipRect.setWidth(paintRect.width() + outsets.left());
+        }
+        if (box->includeLogicalRightEdge())
+            clipRect.setWidth(clipRect.width() + outsets.right());
+    } else {
+        clipRect.setX(paintRect.x() - outsets.left());
+        clipRect.setWidth(paintRect.width() + outsets.left() + outsets.right());
+        if (box->includeLogicalLeftEdge()) {
+            clipRect.setY(paintRect.y() - outsets.top());
+            clipRect.setHeight(paintRect.height() + outsets.top());
+        }
+        if (box->includeLogicalRightEdge())
+            clipRect.setHeight(clipRect.height() + outsets.bottom());
+    }
+    return clipRect;
+}
+
+void InlineFlowBox::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    if (!paintInfo.shouldPaintWithinRoot(renderer()) || renderer()->style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseForeground)
+        return;
+
+    // Pixel snap background/border painting.
+    LayoutRect frameRect = roundedFrameRect();
+
+    constrainToLineTopAndBottomIfNeeded(frameRect);
+    
+    // Move x/y to our coordinates.
+    LayoutRect localRect(frameRect);
+    flipForWritingMode(localRect);
+    LayoutPoint adjustedPaintoffset = paintOffset + localRect.location();
+    
+    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 = renderer()->style(isFirstLineStyle());
+    if ((!parent() && isFirstLineStyle() && styleToUse != renderer()->style()) || (parent() && renderer()->hasBoxDecorations())) {
+        LayoutRect paintRect = LayoutRect(adjustedPaintoffset, frameRect.size());
+        // Shadow comes first and is behind the background and border.
+        if (!boxModelObject()->boxShadowShouldBeAppliedToBackground(BackgroundBleedNone, this))
+            paintBoxShadow(paintInfo, styleToUse, Normal, paintRect);
+
+        Color c = styleToUse->visitedDependentColor(CSSPropertyBackgroundColor);
+        paintFillLayers(paintInfo, c, styleToUse->backgroundLayers(), paintRect);
+        paintBoxShadow(paintInfo, styleToUse, Inset, paintRect);
+
+        // :first-line cannot be used to put borders on a line. Always paint borders with our
+        // non-first-line style.
+        if (parent() && renderer()->style()->hasBorder()) {
+            const NinePieceImage& borderImage = renderer()->style()->borderImage();
+            StyleImage* borderImageSource = borderImage.image();
+            bool hasBorderImage = borderImageSource && borderImageSource->canRender(renderer(), styleToUse->effectiveZoom());
+            if (hasBorderImage && !borderImageSource->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()))
+                boxModelObject()->paintBorder(paintInfo, paintRect, renderer()->style(isFirstLineStyle()), BackgroundBleedNone, includeLogicalLeftEdge(), includeLogicalRightEdge());
+            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.
+                LayoutUnit logicalOffsetOnLine = 0;
+                for (InlineFlowBox* curr = prevLineBox(); curr; curr = curr->prevLineBox())
+                    logicalOffsetOnLine += curr->logicalWidth();
+                LayoutUnit totalLogicalWidth = logicalOffsetOnLine;
+                for (InlineFlowBox* curr = this; curr; curr = curr->nextLineBox())
+                    totalLogicalWidth += curr->logicalWidth();
+                LayoutUnit stripX = adjustedPaintoffset.x() - (isHorizontal() ? logicalOffsetOnLine : LayoutUnit());
+                LayoutUnit stripY = adjustedPaintoffset.y() - (isHorizontal() ? LayoutUnit() : logicalOffsetOnLine);
+                LayoutUnit stripWidth = isHorizontal() ? totalLogicalWidth : frameRect.width();
+                LayoutUnit stripHeight = isHorizontal() ? frameRect.height() : totalLogicalWidth;
+
+                LayoutRect clipRect = clipRectForNinePieceImageStrip(this, borderImage, paintRect);
+                GraphicsContextStateSaver stateSaver(*context);
+                context->clip(clipRect);
+                boxModelObject()->paintBorder(paintInfo, LayoutRect(stripX, stripY, stripWidth, stripHeight), renderer()->style(isFirstLineStyle()));
+            }
+        }
+    }
+}
+
+void InlineFlowBox::paintMask(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    if (!paintInfo.shouldPaintWithinRoot(renderer()) || renderer()->style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask)
+        return;
+
+    // Pixel snap mask painting.
+    LayoutRect frameRect = roundedFrameRect();
+
+    constrainToLineTopAndBottomIfNeeded(frameRect);
+    
+    // Move x/y to our coordinates.
+    LayoutRect localRect(frameRect);
+    flipForWritingMode(localRect);
+    LayoutPoint adjustedPaintOffset = paintOffset + localRect.location();
+
+    const NinePieceImage& maskNinePieceImage = renderer()->style()->maskBoxImage();
+    StyleImage* maskBoxImage = renderer()->style()->maskBoxImage().image();
+
+    // Figure out if we need to push a transparency layer to render our mask.
+    bool pushTransparencyLayer = false;
+    bool compositedMask = renderer()->hasLayer() && boxModelObject()->layer()->hasCompositedMask();
+    bool flattenCompositingLayers = renderer()->view()->frameView() && renderer()->view()->frameView()->paintBehavior() & PaintBehaviorFlattenCompositingLayers;
+    CompositeOperator compositeOp = CompositeSourceOver;
+    if (!compositedMask || flattenCompositingLayers) {
+        if ((maskBoxImage && renderer()->style()->maskLayers()->hasImage()) || renderer()->style()->maskLayers()->next())
+            pushTransparencyLayer = true;
+        
+        compositeOp = CompositeDestinationIn;
+        if (pushTransparencyLayer) {
+            paintInfo.context->setCompositeOperation(CompositeDestinationIn);
+            paintInfo.context->beginTransparencyLayer(1.0f);
+            compositeOp = CompositeSourceOver;
+        }
+    }
+
+    LayoutRect paintRect = LayoutRect(adjustedPaintOffset, frameRect.size());
+    paintFillLayers(paintInfo, Color(), renderer()->style()->maskLayers(), paintRect, compositeOp);
+    
+    bool hasBoxImage = maskBoxImage && maskBoxImage->canRender(renderer(), renderer()->style()->effectiveZoom());
+    if (!hasBoxImage || !maskBoxImage->isLoaded()) {
+        if (pushTransparencyLayer)
+            paintInfo.context->endTransparencyLayer();
+        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()) {
+        boxModelObject()->paintNinePieceImage(paintInfo.context, LayoutRect(adjustedPaintOffset, frameRect.size()), renderer()->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.
+        LayoutUnit logicalOffsetOnLine = 0;
+        for (InlineFlowBox* curr = prevLineBox(); curr; curr = curr->prevLineBox())
+            logicalOffsetOnLine += curr->logicalWidth();
+        LayoutUnit totalLogicalWidth = logicalOffsetOnLine;
+        for (InlineFlowBox* curr = this; curr; curr = curr->nextLineBox())
+            totalLogicalWidth += curr->logicalWidth();
+        LayoutUnit stripX = adjustedPaintOffset.x() - (isHorizontal() ? logicalOffsetOnLine : LayoutUnit());
+        LayoutUnit stripY = adjustedPaintOffset.y() - (isHorizontal() ? LayoutUnit() : logicalOffsetOnLine);
+        LayoutUnit stripWidth = isHorizontal() ? totalLogicalWidth : frameRect.width();
+        LayoutUnit stripHeight = isHorizontal() ? frameRect.height() : totalLogicalWidth;
+
+        LayoutRect clipRect = clipRectForNinePieceImageStrip(this, maskNinePieceImage, paintRect);
+        GraphicsContextStateSaver stateSaver(*paintInfo.context);
+        paintInfo.context->clip(clipRect);
+        boxModelObject()->paintNinePieceImage(paintInfo.context, LayoutRect(stripX, stripY, stripWidth, stripHeight), renderer()->style(), maskNinePieceImage, compositeOp);
+    }
+    
+    if (pushTransparencyLayer)
+        paintInfo.context->endTransparencyLayer();
+}
+
+InlineBox* InlineFlowBox::firstLeafChild() const
+{
+    InlineBox* leaf = 0;
+    for (InlineBox* child = firstChild(); child && !leaf; child = child->nextOnLine())
+        leaf = child->isLeaf() ? child : toInlineFlowBox(child)->firstLeafChild();
+    return leaf;
+}
+
+InlineBox* InlineFlowBox::lastLeafChild() const
+{
+    InlineBox* leaf = 0;
+    for (InlineBox* child = lastChild(); child && !leaf; child = child->prevOnLine())
+        leaf = child->isLeaf() ? child : toInlineFlowBox(child)->lastLeafChild();
+    return leaf;
+}
+
+RenderObject::SelectionState InlineFlowBox::selectionState()
+{
+    return RenderObject::SelectionNone;
+}
+
+bool InlineFlowBox::canAccommodateEllipsis(bool ltr, int blockEdge, int ellipsisWidth) const
+{
+    for (InlineBox *box = firstChild(); box; box = box->nextOnLine()) {
+        if (!box->canAccommodateEllipsis(ltr, blockEdge, ellipsisWidth))
+            return false;
+    }
+    return true;
+}
+
+float InlineFlowBox::placeEllipsisBox(bool ltr, float blockLeftEdge, float blockRightEdge, float ellipsisWidth, float &truncatedWidth, bool& foundBox)
+{
+    float result = -1;
+    // We iterate over all children, the foundBox variable tells us when we've found the
+    // box containing the ellipsis.  All boxes after that one in the flow are hidden.
+    // If our flow is ltr then iterate over the boxes from left to right, otherwise iterate
+    // from right to left. Varying the order allows us to correctly hide the boxes following the ellipsis.
+    InlineBox* box = ltr ? firstChild() : lastChild();
+
+    // NOTE: these will cross after foundBox = true.
+    int visibleLeftEdge = blockLeftEdge;
+    int visibleRightEdge = blockRightEdge;
+
+    while (box) {
+        int currResult = box->placeEllipsisBox(ltr, visibleLeftEdge, visibleRightEdge, ellipsisWidth, truncatedWidth, foundBox);
+        if (currResult != -1 && result == -1)
+            result = currResult;
+
+        if (ltr) {
+            visibleLeftEdge += box->logicalWidth();
+            box = box->nextOnLine();
+        }
+        else {
+            visibleRightEdge -= box->logicalWidth();
+            box = box->prevOnLine();
+        }
+    }
+    return result;
+}
+
+void InlineFlowBox::clearTruncation()
+{
+    for (InlineBox *box = firstChild(); box; box = box->nextOnLine())
+        box->clearTruncation();
+}
+
+LayoutUnit InlineFlowBox::computeOverAnnotationAdjustment(LayoutUnit allowedPosition) const
+{
+    LayoutUnit result = 0;
+    for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
+        if (curr->renderer()->isOutOfFlowPositioned())
+            continue; // Positioned placeholders don't affect calculations.
+        
+        if (curr->isInlineFlowBox())
+            result = max(result, toInlineFlowBox(curr)->computeOverAnnotationAdjustment(allowedPosition));
+        
+        if (curr->renderer()->isReplaced() && curr->renderer()->isRubyRun() && curr->renderer()->style()->rubyPosition() == RubyPositionBefore) {
+            RenderRubyRun* rubyRun = toRenderRubyRun(curr->renderer());
+            RenderRubyText* rubyText = rubyRun->rubyText();
+            if (!rubyText)
+                continue;
+            
+            if (!rubyRun->style()->isFlippedLinesWritingMode()) {
+                LayoutUnit topOfFirstRubyTextLine = rubyText->logicalTop() + (rubyText->firstRootBox() ? rubyText->firstRootBox()->lineTop() : LayoutUnit());
+                if (topOfFirstRubyTextLine >= 0)
+                    continue;
+                topOfFirstRubyTextLine += curr->logicalTop();
+                result = max(result, allowedPosition - topOfFirstRubyTextLine);
+            } else {
+                LayoutUnit bottomOfLastRubyTextLine = rubyText->logicalTop() + (rubyText->lastRootBox() ? rubyText->lastRootBox()->lineBottom() : rubyText->logicalHeight());
+                if (bottomOfLastRubyTextLine <= curr->logicalHeight())
+                    continue;
+                bottomOfLastRubyTextLine += curr->logicalTop();
+                result = max(result, bottomOfLastRubyTextLine - allowedPosition);
+            }
+        }
+
+        if (curr->isInlineTextBox()) {
+            RenderStyle* style = curr->renderer()->style(isFirstLineStyle());
+            TextEmphasisPosition emphasisMarkPosition;
+            if (style->textEmphasisMark() != TextEmphasisMarkNone && toInlineTextBox(curr)->getEmphasisMarkPosition(style, emphasisMarkPosition) && emphasisMarkPosition == TextEmphasisPositionOver) {
+                if (!style->isFlippedLinesWritingMode()) {
+                    int topOfEmphasisMark = curr->logicalTop() - style->font().emphasisMarkHeight(style->textEmphasisMarkString());
+                    result = max(result, allowedPosition - topOfEmphasisMark);
+                } else {
+                    int bottomOfEmphasisMark = curr->logicalBottom() + style->font().emphasisMarkHeight(style->textEmphasisMarkString());
+                    result = max(result, bottomOfEmphasisMark - allowedPosition);
+                }
+            }
+        }
+    }
+    return result;
+}
+
+LayoutUnit InlineFlowBox::computeUnderAnnotationAdjustment(LayoutUnit allowedPosition) const
+{
+    LayoutUnit result = 0;
+    for (InlineBox* curr = firstChild(); curr; curr = curr->nextOnLine()) {
+        if (curr->renderer()->isOutOfFlowPositioned())
+            continue; // Positioned placeholders don't affect calculations.
+
+        if (curr->isInlineFlowBox())
+            result = max(result, toInlineFlowBox(curr)->computeUnderAnnotationAdjustment(allowedPosition));
+
+        if (curr->renderer()->isReplaced() && curr->renderer()->isRubyRun() && curr->renderer()->style()->rubyPosition() == RubyPositionAfter) {
+            RenderRubyRun* rubyRun = toRenderRubyRun(curr->renderer());
+            RenderRubyText* rubyText = rubyRun->rubyText();
+            if (!rubyText)
+                continue;
+
+            if (rubyRun->style()->isFlippedLinesWritingMode()) {
+                LayoutUnit topOfFirstRubyTextLine = rubyText->logicalTop() + (rubyText->firstRootBox() ? rubyText->firstRootBox()->lineTop() : LayoutUnit());
+                if (topOfFirstRubyTextLine >= 0)
+                    continue;
+                topOfFirstRubyTextLine += curr->logicalTop();
+                result = max(result, allowedPosition - topOfFirstRubyTextLine);
+            } else {
+                LayoutUnit bottomOfLastRubyTextLine = rubyText->logicalTop() + (rubyText->lastRootBox() ? rubyText->lastRootBox()->lineBottom() : rubyText->logicalHeight());
+                if (bottomOfLastRubyTextLine <= curr->logicalHeight())
+                    continue;
+                bottomOfLastRubyTextLine += curr->logicalTop();
+                result = max(result, bottomOfLastRubyTextLine - allowedPosition);
+            }
+        }
+
+        if (curr->isInlineTextBox()) {
+            RenderStyle* style = curr->renderer()->style(isFirstLineStyle());
+            if (style->textEmphasisMark() != TextEmphasisMarkNone && style->textEmphasisPosition() == TextEmphasisPositionUnder) {
+                if (!style->isFlippedLinesWritingMode()) {
+                    LayoutUnit bottomOfEmphasisMark = curr->logicalBottom() + style->font().emphasisMarkHeight(style->textEmphasisMarkString());
+                    result = max(result, bottomOfEmphasisMark - allowedPosition);
+                } else {
+                    LayoutUnit topOfEmphasisMark = curr->logicalTop() - style->font().emphasisMarkHeight(style->textEmphasisMarkString());
+                    result = max(result, allowedPosition - topOfEmphasisMark);
+                }
+            }
+        }
+    }
+    return result;
+}
+
+void InlineFlowBox::collectLeafBoxesInLogicalOrder(Vector<InlineBox*>& leafBoxesInLogicalOrder, CustomInlineBoxRangeReverse customReverseImplementation, void* userData) const
+{
+    InlineBox* leaf = firstLeafChild();
+
+    // FIXME: The reordering code is a copy of parts from BidiResolver::createBidiRunsForLine, operating directly on InlineBoxes, instead of BidiRuns.
+    // Investigate on how this code could possibly be shared.
+    unsigned char minLevel = 128;
+    unsigned char maxLevel = 0;
+
+    // First find highest and lowest levels, and initialize leafBoxesInLogicalOrder with the leaf boxes in visual order.
+    for (; leaf; leaf = leaf->nextLeafChild()) {
+        minLevel = min(minLevel, leaf->bidiLevel());
+        maxLevel = max(maxLevel, leaf->bidiLevel());
+        leafBoxesInLogicalOrder.append(leaf);
+    }
+
+    if (renderer()->style()->rtlOrdering() == VisualOrder)
+        return;
+
+    // Reverse of reordering of the line (L2 according to Bidi spec):
+    // L2. From the highest level found in the text to the lowest odd level on each line,
+    // reverse any contiguous sequence of characters that are at that level or higher.
+
+    // Reversing the reordering of the line is only done up to the lowest odd level.
+    if (!(minLevel % 2))
+        ++minLevel;
+
+    Vector<InlineBox*>::iterator end = leafBoxesInLogicalOrder.end();
+    while (minLevel <= maxLevel) {
+        Vector<InlineBox*>::iterator it = leafBoxesInLogicalOrder.begin();
+        while (it != end) {
+            while (it != end) {
+                if ((*it)->bidiLevel() >= minLevel)
+                    break;
+                ++it;
+            }
+            Vector<InlineBox*>::iterator first = it;
+            while (it != end) {
+                if ((*it)->bidiLevel() < minLevel)
+                    break;
+                ++it;
+            }
+            Vector<InlineBox*>::iterator last = it;
+            if (customReverseImplementation) {
+                ASSERT(userData);
+                (*customReverseImplementation)(userData, first, last);
+            } else
+                std::reverse(first, last);
+        }                
+        ++minLevel;
+    }
+}
+
+#ifndef NDEBUG
+
+const char* InlineFlowBox::boxName() const
+{
+    return "InlineFlowBox";
+}
+
+void InlineFlowBox::showLineTreeAndMark(const InlineBox* markedBox1, const char* markedLabel1, const InlineBox* markedBox2, const char* markedLabel2, const RenderObject* obj, int depth) const
+{
+    InlineBox::showLineTreeAndMark(markedBox1, markedLabel1, markedBox2, markedLabel2, obj, depth);
+    for (const InlineBox* box = firstChild(); box; box = box->nextOnLine())
+        box->showLineTreeAndMark(markedBox1, markedLabel1, markedBox2, markedLabel2, obj, depth + 1);
+}
+
+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
+
+void InlineFlowBox::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::Rendering);
+    InlineBox::reportMemoryUsage(memoryObjectInfo);
+    info.addMember(m_overflow, "overflow");
+    info.addMember(m_firstChild, "firstChild");
+    info.addMember(m_lastChild, "lastChild");
+    info.addMember(m_prevLineBox, "prevLineBox");
+    info.addMember(m_nextLineBox, "nextLineBox");
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/InlineFlowBox.h b/Source/core/rendering/InlineFlowBox.h
new file mode 100644
index 0000000..7a606b6
--- /dev/null
+++ b/Source/core/rendering/InlineFlowBox.h
@@ -0,0 +1,391 @@
+/*
+ * 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 "core/rendering/InlineBox.h"
+#include "core/rendering/RenderOverflow.h"
+#include "core/rendering/style/ShadowData.h"
+
+namespace WebCore {
+
+class HitTestRequest;
+class HitTestResult;
+class InlineTextBox;
+class RenderLineBoxList;
+class SimpleFontData;
+class VerticalPositionCache;
+
+struct GlyphOverflow;
+
+typedef HashMap<const InlineTextBox*, pair<Vector<const SimpleFontData*>, GlyphOverflow> > GlyphOverflowAndFallbackFontsMap;
+
+class InlineFlowBox : public InlineBox {
+public:
+    InlineFlowBox(RenderObject* obj)
+        : InlineBox(obj)
+        , m_firstChild(0)
+        , m_lastChild(0)
+        , m_prevLineBox(0)
+        , m_nextLineBox(0)
+        , m_includeLogicalLeftEdge(false)
+        , m_includeLogicalRightEdge(false)
+        , m_descendantsHaveSameLineHeightAndBaseline(true)
+        , m_baselineType(AlphabeticBaseline)
+        , m_hasAnnotationsBefore(false)
+        , m_hasAnnotationsAfter(false)
+#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;
+        m_hasTextDescendants = m_hasTextChildren;
+    }
+
+#ifndef NDEBUG
+    virtual ~InlineFlowBox();
+    
+    virtual void showLineTreeAndMark(const InlineBox* = 0, const char* = 0, const InlineBox* = 0, const char* = 0, const RenderObject* = 0, int = 0) const;
+    virtual const char* boxName() const;
+#endif
+
+    InlineFlowBox* prevLineBox() const { return m_prevLineBox; }
+    InlineFlowBox* nextLineBox() const { return m_nextLineBox; }
+    void setNextLineBox(InlineFlowBox* n) { m_nextLineBox = n; }
+    void setPreviousLineBox(InlineFlowBox* p) { m_prevLineBox = p; }
+
+    InlineBox* firstChild() const { checkConsistency(); return m_firstChild; }
+    InlineBox* lastChild() const { checkConsistency(); return m_lastChild; }
+
+    virtual bool isLeaf() const OVERRIDE FINAL { return false; }
+    
+    InlineBox* firstLeafChild() const;
+    InlineBox* lastLeafChild() const;
+
+    typedef void (*CustomInlineBoxRangeReverse)(void* userData, Vector<InlineBox*>::iterator first, Vector<InlineBox*>::iterator last);
+    void collectLeafBoxesInLogicalOrder(Vector<InlineBox*>&, CustomInlineBoxRangeReverse customReverseImplementation = 0, void* userData = 0) const;
+
+    virtual void setConstructed() OVERRIDE FINAL
+    {
+        InlineBox::setConstructed();
+        for (InlineBox* child = firstChild(); child; child = child->nextOnLine())
+            child->setConstructed();
+    }
+
+    void addToLine(InlineBox* child);
+    virtual void deleteLine(RenderArena*) OVERRIDE FINAL;
+    virtual void extractLine() OVERRIDE FINAL;
+    virtual void attachLine() OVERRIDE FINAL;
+    virtual void adjustPosition(float dx, float dy);
+
+    virtual void extractLineBoxFromRenderObject();
+    virtual void attachLineBoxToRenderObject();
+    virtual void removeLineBoxFromRenderObject();
+
+    virtual void clearTruncation() OVERRIDE;
+
+    IntRect roundedFrameRect() const;
+    
+    void paintBoxDecorations(PaintInfo&, const LayoutPoint&);
+    void paintMask(PaintInfo&, const LayoutPoint&);
+    void paintFillLayers(const PaintInfo&, const Color&, const FillLayer*, const LayoutRect&, CompositeOperator = CompositeSourceOver);
+    void paintFillLayer(const PaintInfo&, const Color&, const FillLayer*, const LayoutRect&, CompositeOperator = CompositeSourceOver);
+    void paintBoxShadow(const PaintInfo&, RenderStyle*, ShadowStyle, const LayoutRect&);
+    virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom);
+    virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom) OVERRIDE;
+
+    bool boxShadowCanBeAppliedToBackground(const FillLayer&) const;
+
+    virtual RenderLineBoxList* rendererLineBoxes() const;
+
+    // logicalLeft = left in a horizontal line and top in a vertical line.
+    LayoutUnit marginBorderPaddingLogicalLeft() const { return marginLogicalLeft() + borderLogicalLeft() + paddingLogicalLeft(); }
+    LayoutUnit marginBorderPaddingLogicalRight() const { return marginLogicalRight() + borderLogicalRight() + paddingLogicalRight(); }
+    LayoutUnit marginLogicalLeft() const
+    {
+        if (!includeLogicalLeftEdge())
+            return 0;
+        return isHorizontal() ? boxModelObject()->marginLeft() : boxModelObject()->marginTop();
+    }
+    LayoutUnit marginLogicalRight() const
+    {
+        if (!includeLogicalRightEdge())
+            return 0;
+        return isHorizontal() ? boxModelObject()->marginRight() : boxModelObject()->marginBottom();
+    }
+    int borderLogicalLeft() const
+    {
+        if (!includeLogicalLeftEdge())
+            return 0;
+        return isHorizontal() ? renderer()->style(isFirstLineStyle())->borderLeftWidth() : renderer()->style(isFirstLineStyle())->borderTopWidth();
+    }
+    int borderLogicalRight() const
+    {
+        if (!includeLogicalRightEdge())
+            return 0;
+        return isHorizontal() ? renderer()->style(isFirstLineStyle())->borderRightWidth() : renderer()->style(isFirstLineStyle())->borderBottomWidth();
+    }
+    int paddingLogicalLeft() const
+    {
+        if (!includeLogicalLeftEdge())
+            return 0;
+        return isHorizontal() ? boxModelObject()->paddingLeft() : boxModelObject()->paddingTop();
+    }
+    int paddingLogicalRight() const
+    {
+        if (!includeLogicalRightEdge())
+            return 0;
+        return isHorizontal() ? boxModelObject()->paddingRight() : boxModelObject()->paddingBottom();
+    }
+
+    bool includeLogicalLeftEdge() const { return m_includeLogicalLeftEdge; }
+    bool includeLogicalRightEdge() const { return m_includeLogicalRightEdge; }
+    void setEdges(bool includeLeft, bool includeRight)
+    {
+        m_includeLogicalLeftEdge = includeLeft;
+        m_includeLogicalRightEdge = includeRight;
+    }
+
+    // Helper functions used during line construction and placement.
+    void determineSpacingForFlowBoxes(bool lastLine, bool isLogicallyLastRunWrapped, RenderObject* logicallyLastRunRenderer);
+    LayoutUnit getFlowSpacingLogicalWidth();
+    float placeBoxesInInlineDirection(float logicalLeft, bool& needsWordSpacing, GlyphOverflowAndFallbackFontsMap&);
+    float placeBoxRangeInInlineDirection(InlineBox* firstChild, InlineBox* lastChild, float& logicalLeft, float& minLogicalLeft, float& maxLogicalRight, bool& needsWordSpacing, GlyphOverflowAndFallbackFontsMap&);
+    void beginPlacingBoxRangesInInlineDirection(float logicalLeft) { setLogicalLeft(logicalLeft); }
+    void endPlacingBoxRangesInInlineDirection(float logicalLeft, float logicalRight, float minLogicalLeft, float maxLogicalRight)
+    {
+        setLogicalWidth(logicalRight - logicalLeft);
+        if (knownToHaveNoOverflow() && (minLogicalLeft < logicalLeft || maxLogicalRight > logicalRight))
+            clearKnownToHaveNoOverflow();
+    }
+
+    void computeLogicalBoxHeights(RootInlineBox*, LayoutUnit& maxPositionTop, LayoutUnit& maxPositionBottom,
+                                  int& maxAscent, int& maxDescent, bool& setMaxAscent, bool& setMaxDescent,
+                                  bool strictMode, GlyphOverflowAndFallbackFontsMap&, FontBaseline, VerticalPositionCache&);
+    void adjustMaxAscentAndDescent(int& maxAscent, int& maxDescent,
+                                   int maxPositionTop, int maxPositionBottom);
+    void placeBoxesInBlockDirection(LayoutUnit logicalTop, LayoutUnit maxHeight, int maxAscent, bool strictMode, LayoutUnit& lineTop, LayoutUnit& lineBottom, bool& setLineTop,
+                                    LayoutUnit& lineTopIncludingMargins, LayoutUnit& lineBottomIncludingMargins, bool& hasAnnotationsBefore, bool& hasAnnotationsAfter, FontBaseline);
+    void flipLinesInBlockDirection(LayoutUnit lineTop, LayoutUnit lineBottom);
+    bool requiresIdeographicBaseline(const GlyphOverflowAndFallbackFontsMap&) const;
+
+    LayoutUnit computeOverAnnotationAdjustment(LayoutUnit allowedPosition) const;
+    LayoutUnit computeUnderAnnotationAdjustment(LayoutUnit allowedPosition) const;
+
+    void computeOverflow(LayoutUnit lineTop, LayoutUnit lineBottom, GlyphOverflowAndFallbackFontsMap&);
+    
+    void removeChild(InlineBox* child);
+
+    virtual RenderObject::SelectionState selectionState();
+
+    virtual bool canAccommodateEllipsis(bool ltr, int blockEdge, int ellipsisWidth) const OVERRIDE FINAL;
+    virtual float placeEllipsisBox(bool ltr, float blockLeftEdge, float blockRightEdge, float ellipsisWidth, float &truncatedWidth, bool&) OVERRIDE;
+
+    bool hasTextChildren() const { return m_hasTextChildren; }
+    bool hasTextDescendants() const { return m_hasTextDescendants; }
+    void setHasTextChildren() { m_hasTextChildren = true; setHasTextDescendants(); }
+    void setHasTextDescendants() { m_hasTextDescendants = true; }
+    
+    void checkConsistency() const;
+    void setHasBadChildList();
+
+    // Line visual and layout overflow are in the coordinate space of the block.  This means that they aren't purely physical directions.
+    // For horizontal-tb and vertical-lr they will match physical directions, but for horizontal-bt and vertical-rl, the top/bottom and left/right
+    // respectively are flipped when compared to their physical counterparts.  For example minX is on the left in vertical-lr, but it is on the right in vertical-rl.
+    LayoutRect layoutOverflowRect(LayoutUnit lineTop, LayoutUnit lineBottom) const
+    { 
+        return m_overflow ? m_overflow->layoutOverflowRect() : enclosingLayoutRect(frameRectIncludingLineHeight(lineTop, lineBottom));
+    }
+    LayoutUnit logicalLeftLayoutOverflow() const
+    {
+        return m_overflow ? (isHorizontal() ? m_overflow->layoutOverflowRect().x() : m_overflow->layoutOverflowRect().y()) :
+                            static_cast<LayoutUnit>(logicalLeft());
+    }
+    LayoutUnit logicalRightLayoutOverflow() const
+    {
+        return m_overflow ? (isHorizontal() ? m_overflow->layoutOverflowRect().maxX() : m_overflow->layoutOverflowRect().maxY()) :
+                            static_cast<LayoutUnit>(ceilf(logicalRight()));
+    }
+    LayoutUnit logicalTopLayoutOverflow(LayoutUnit lineTop) const
+    {
+        if (m_overflow)
+            return isHorizontal() ? m_overflow->layoutOverflowRect().y() : m_overflow->layoutOverflowRect().x();
+        return lineTop;
+    }
+    LayoutUnit logicalBottomLayoutOverflow(LayoutUnit lineBottom) const
+    {
+        if (m_overflow)
+            return isHorizontal() ? m_overflow->layoutOverflowRect().maxY() : m_overflow->layoutOverflowRect().maxX();
+        return lineBottom;
+    }
+    LayoutRect logicalLayoutOverflowRect(LayoutUnit lineTop, LayoutUnit lineBottom) const
+    {
+        LayoutRect result = layoutOverflowRect(lineTop, lineBottom);
+        if (!renderer()->isHorizontalWritingMode())
+            result = result.transposedRect();
+        return result;
+    }
+
+    LayoutRect visualOverflowRect(LayoutUnit lineTop, LayoutUnit lineBottom) const
+    { 
+        return m_overflow ? m_overflow->visualOverflowRect() : enclosingLayoutRect(frameRectIncludingLineHeight(lineTop, lineBottom));
+    }
+    LayoutUnit logicalLeftVisualOverflow() const { return m_overflow ? (isHorizontal() ? m_overflow->visualOverflowRect().x() : m_overflow->visualOverflowRect().y()) : static_cast<LayoutUnit>(logicalLeft()); }
+    LayoutUnit logicalRightVisualOverflow() const { return m_overflow ? (isHorizontal() ? m_overflow->visualOverflowRect().maxX() : m_overflow->visualOverflowRect().maxY()) : static_cast<LayoutUnit>(ceilf(logicalRight())); }
+    LayoutUnit logicalTopVisualOverflow(LayoutUnit lineTop) const
+    {
+        if (m_overflow)
+            return isHorizontal() ? m_overflow->visualOverflowRect().y() : m_overflow->visualOverflowRect().x();
+        return lineTop;
+    }
+    LayoutUnit logicalBottomVisualOverflow(LayoutUnit lineBottom) const
+    {
+        if (m_overflow)
+            return isHorizontal() ? m_overflow->visualOverflowRect().maxY() : m_overflow->visualOverflowRect().maxX();
+        return lineBottom;
+    }
+    LayoutRect logicalVisualOverflowRect(LayoutUnit lineTop, LayoutUnit lineBottom) const
+    {
+        LayoutRect result = visualOverflowRect(lineTop, lineBottom);
+        if (!renderer()->isHorizontalWritingMode())
+            result = result.transposedRect();
+        return result;
+    }
+
+    void setOverflowFromLogicalRects(const LayoutRect& logicalLayoutOverflow, const LayoutRect& logicalVisualOverflow, LayoutUnit lineTop, LayoutUnit lineBottom);
+    void setLayoutOverflow(const LayoutRect&, LayoutUnit lineTop, LayoutUnit lineBottom);
+    void setVisualOverflow(const LayoutRect&, LayoutUnit lineTop, LayoutUnit lineBottom);
+
+    FloatRect frameRectIncludingLineHeight(LayoutUnit lineTop, LayoutUnit lineBottom) const
+    {
+        if (isHorizontal())
+            return FloatRect(m_topLeft.x(), lineTop, width(), lineBottom - lineTop);
+        return FloatRect(lineTop, m_topLeft.y(), lineBottom - lineTop, height());
+    }
+    
+    FloatRect logicalFrameRectIncludingLineHeight(LayoutUnit lineTop, LayoutUnit lineBottom) const
+    {
+        return FloatRect(logicalLeft(), lineTop, logicalWidth(), lineBottom - lineTop);
+    }
+    
+    bool descendantsHaveSameLineHeightAndBaseline() const { return m_descendantsHaveSameLineHeightAndBaseline; }
+    void clearDescendantsHaveSameLineHeightAndBaseline()
+    { 
+        m_descendantsHaveSameLineHeightAndBaseline = false;
+        if (parent() && parent()->descendantsHaveSameLineHeightAndBaseline())
+            parent()->clearDescendantsHaveSameLineHeightAndBaseline();
+    }
+
+    virtual void reportMemoryUsage(MemoryObjectInfo*) const OVERRIDE FINAL;
+
+private:
+    void addBoxShadowVisualOverflow(LayoutRect& logicalVisualOverflow);
+    void addBorderOutsetVisualOverflow(LayoutRect& logicalVisualOverflow);
+    void addTextBoxVisualOverflow(InlineTextBox*, GlyphOverflowAndFallbackFontsMap&, LayoutRect& logicalVisualOverflow);
+    void addReplacedChildOverflow(const InlineBox*, LayoutRect& logicalLayoutOverflow, LayoutRect& logicalVisualOverflow);
+    void constrainToLineTopAndBottomIfNeeded(LayoutRect&) const;
+
+protected:
+    OwnPtr<RenderOverflow> m_overflow;
+
+    virtual bool isInlineFlowBox() const OVERRIDE FINAL { return true; }
+
+    InlineBox* m_firstChild;
+    InlineBox* m_lastChild;
+    
+    InlineFlowBox* m_prevLineBox; // The previous box that also uses our RenderObject
+    InlineFlowBox* m_nextLineBox; // The next box that also uses our RenderObject
+
+#if ENABLE(CSS3_TEXT)
+    // Maximum logicalTop among all children of an InlineFlowBox. Used to
+    // calculate the offset for TextUnderlinePositionUnder.
+    void computeMaxLogicalTop(float& maxLogicalTop);
+#endif // CSS3_TEXT
+private:
+    unsigned m_includeLogicalLeftEdge : 1;
+    unsigned m_includeLogicalRightEdge : 1;
+    unsigned m_hasTextChildren : 1;
+    unsigned m_hasTextDescendants : 1;
+    unsigned m_descendantsHaveSameLineHeightAndBaseline : 1;
+
+protected:
+    // The following members are only used by RootInlineBox but moved here to keep the bits packed.
+
+    // Whether or not this line uses alphabetic or ideographic baselines by default.
+    unsigned m_baselineType : 1; // FontBaseline
+
+    // If the line contains any ruby runs, then this will be true.
+    unsigned m_hasAnnotationsBefore : 1;
+    unsigned m_hasAnnotationsAfter : 1;
+
+    unsigned m_lineBreakBidiStatusEor : 5; // WTF::Unicode::Direction
+    unsigned m_lineBreakBidiStatusLastStrong : 5; // WTF::Unicode::Direction
+    unsigned m_lineBreakBidiStatusLast : 5; // WTF::Unicode::Direction
+
+    // End of RootInlineBox-specific members.
+
+#ifndef NDEBUG
+private:
+    unsigned m_hasBadChildList : 1;
+#endif
+};
+
+inline InlineFlowBox* toInlineFlowBox(InlineBox* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isInlineFlowBox());
+    return static_cast<InlineFlowBox*>(object);
+}
+
+inline const InlineFlowBox* toInlineFlowBox(const InlineBox* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isInlineFlowBox());
+    return static_cast<const InlineFlowBox*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toInlineFlowBox(const InlineFlowBox*);
+
+#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::InlineFlowBox*);
+#endif
+
+#endif // InlineFlowBox_h
diff --git a/Source/core/rendering/InlineIterator.h b/Source/core/rendering/InlineIterator.h
new file mode 100644
index 0000000..229c4df
--- /dev/null
+++ b/Source/core/rendering/InlineIterator.h
@@ -0,0 +1,549 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009, 2010 Apple Inc. All right reserved.
+ * Copyright (C) 2010 Google 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 InlineIterator_h
+#define InlineIterator_h
+
+#include "core/rendering/BidiRun.h"
+#include "core/rendering/RenderBlock.h"
+#include "core/rendering/RenderText.h"
+#include <wtf/StdLibExtras.h>
+
+namespace WebCore {
+
+// This class is used to RenderInline subtrees, stepping by character within the
+// text children. InlineIterator will use bidiNext to find the next RenderText
+// optionally notifying a BidiResolver every time it steps into/out of a RenderInline.
+class InlineIterator {
+public:
+    InlineIterator()
+        : m_root(0)
+        , m_obj(0)
+        , m_pos(0)
+        , m_nextBreakablePosition(-1)
+    {
+    }
+
+    InlineIterator(RenderObject* root, RenderObject* o, unsigned p)
+        : m_root(root)
+        , m_obj(o)
+        , m_pos(p)
+        , m_nextBreakablePosition(-1)
+    {
+    }
+
+    void clear() { moveTo(0, 0); }
+
+    void moveToStartOf(RenderObject* object)
+    {
+        moveTo(object, 0);
+    }
+
+    void moveTo(RenderObject* object, unsigned offset, int nextBreak = -1)
+    {
+        m_obj = object;
+        m_pos = offset;
+        m_nextBreakablePosition = nextBreak;
+    }
+
+    RenderObject* object() const { return m_obj; }
+    unsigned offset() const { return m_pos; }
+    RenderObject* root() const { return m_root; }
+
+    void fastIncrementInTextNode();
+    void increment(InlineBidiResolver* = 0);
+    bool atEnd() const;
+
+    inline bool atTextParagraphSeparator()
+    {
+        return m_obj && m_obj->preservesNewline() && m_obj->isText() && toRenderText(m_obj)->textLength()
+            && !toRenderText(m_obj)->isWordBreak() && toRenderText(m_obj)->characterAt(m_pos) == '\n';
+    }
+    
+    inline bool atParagraphSeparator()
+    {
+        return (m_obj && m_obj->isBR()) || atTextParagraphSeparator();
+    }
+
+    UChar characterAt(unsigned) const;
+    UChar current() const;
+    UChar previousInSameNode() const;
+    ALWAYS_INLINE WTF::Unicode::Direction direction() const;
+
+private:
+    RenderObject* m_root;
+
+    // FIXME: These should be private.
+public:
+    RenderObject* m_obj;
+    unsigned m_pos;
+    int m_nextBreakablePosition;
+};
+
+inline bool operator==(const InlineIterator& it1, const InlineIterator& it2)
+{
+    return it1.m_pos == it2.m_pos && it1.m_obj == it2.m_obj;
+}
+
+inline bool operator!=(const InlineIterator& it1, const InlineIterator& it2)
+{
+    return it1.m_pos != it2.m_pos || it1.m_obj != it2.m_obj;
+}
+
+static inline WTF::Unicode::Direction embedCharFromDirection(TextDirection dir, EUnicodeBidi unicodeBidi)
+{
+    using namespace WTF::Unicode;
+    if (unicodeBidi == Embed)
+        return dir == RTL ? RightToLeftEmbedding : LeftToRightEmbedding;
+    return dir == RTL ? RightToLeftOverride : LeftToRightOverride;
+}
+
+template <class Observer>
+static inline void notifyObserverEnteredObject(Observer* observer, RenderObject* object)
+{
+    if (!observer || !object || !object->isRenderInline())
+        return;
+
+    RenderStyle* style = object->style();
+    EUnicodeBidi unicodeBidi = style->unicodeBidi();
+    if (unicodeBidi == UBNormal) {
+        // http://dev.w3.org/csswg/css3-writing-modes/#unicode-bidi
+        // "The element does not open an additional level of embedding with respect to the bidirectional algorithm."
+        // Thus we ignore any possible dir= attribute on the span.
+        return;
+    }
+    if (isIsolated(unicodeBidi)) {
+        // Make sure that explicit embeddings are committed before we enter the isolated content.
+        observer->commitExplicitEmbedding();
+        observer->enterIsolate();
+        // Embedding/Override characters implied by dir= will be handled when
+        // we process the isolated span, not when laying out the "parent" run.
+        return;
+    }
+
+    if (!observer->inIsolate())
+        observer->embed(embedCharFromDirection(style->direction(), unicodeBidi), FromStyleOrDOM);
+}
+
+template <class Observer>
+static inline void notifyObserverWillExitObject(Observer* observer, RenderObject* object)
+{
+    if (!observer || !object || !object->isRenderInline())
+        return;
+
+    EUnicodeBidi unicodeBidi = object->style()->unicodeBidi();
+    if (unicodeBidi == UBNormal)
+        return; // Nothing to do for unicode-bidi: normal
+    if (isIsolated(unicodeBidi)) {
+        observer->exitIsolate();
+        return;
+    }
+
+    // Otherwise we pop any embed/override character we added when we opened this tag.
+    if (!observer->inIsolate())
+        observer->embed(WTF::Unicode::PopDirectionalFormat, FromStyleOrDOM);
+}
+
+static inline bool isIteratorTarget(RenderObject* object)
+{
+    ASSERT(object); // The iterator will of course return 0, but its not an expected argument to this function.
+    return object->isText() || object->isFloating() || object->isOutOfFlowPositioned() || object->isReplaced();
+}
+
+// This enum is only used for bidiNextShared()
+enum EmptyInlineBehavior {
+    SkipEmptyInlines,
+    IncludeEmptyInlines,
+};
+
+static bool isEmptyInline(RenderObject* object)
+{
+    if (!object->isRenderInline())
+        return false;
+
+    for (RenderObject* curr = object->firstChild(); curr; curr = curr->nextSibling()) {
+        if (curr->isFloatingOrOutOfFlowPositioned())
+            continue;
+        if (curr->isText() && toRenderText(curr)->isAllCollapsibleWhitespace())
+            continue;
+
+        if (!isEmptyInline(curr))
+            return false;
+    }
+    return true;
+}
+
+// FIXME: This function is misleadingly named. It has little to do with bidi.
+// This function will iterate over inlines within a block, optionally notifying
+// a bidi resolver as it enters/exits inlines (so it can push/pop embedding levels).
+template <class Observer>
+static inline RenderObject* bidiNextShared(RenderObject* root, RenderObject* current, Observer* observer = 0, EmptyInlineBehavior emptyInlineBehavior = SkipEmptyInlines, bool* endOfInlinePtr = 0)
+{
+    RenderObject* next = 0;
+    // oldEndOfInline denotes if when we last stopped iterating if we were at the end of an inline.
+    bool oldEndOfInline = endOfInlinePtr ? *endOfInlinePtr : false;
+    bool endOfInline = false;
+
+    while (current) {
+        next = 0;
+        if (!oldEndOfInline && !isIteratorTarget(current)) {
+            next = current->firstChild();
+            notifyObserverEnteredObject(observer, next);
+        }
+
+        // We hit this when either current has no children, or when current is not a renderer we care about.
+        if (!next) {
+            // If it is a renderer we care about, and we're doing our inline-walk, return it.
+            if (emptyInlineBehavior == IncludeEmptyInlines && !oldEndOfInline && current->isRenderInline()) {
+                next = current;
+                endOfInline = true;
+                break;
+            }
+
+            while (current && current != root) {
+                notifyObserverWillExitObject(observer, current);
+
+                next = current->nextSibling();
+                if (next) {
+                    notifyObserverEnteredObject(observer, next);
+                    break;
+                }
+
+                current = current->parent();
+                if (emptyInlineBehavior == IncludeEmptyInlines && current && current != root && current->isRenderInline()) {
+                    next = current;
+                    endOfInline = true;
+                    break;
+                }
+            }
+        }
+
+        if (!next)
+            break;
+
+        if (isIteratorTarget(next)
+            || ((emptyInlineBehavior == IncludeEmptyInlines || isEmptyInline(next)) // Always return EMPTY inlines.
+                && next->isRenderInline()))
+            break;
+        current = next;
+    }
+
+    if (endOfInlinePtr)
+        *endOfInlinePtr = endOfInline;
+
+    return next;
+}
+
+template <class Observer>
+static inline RenderObject* bidiNextSkippingEmptyInlines(RenderObject* root, RenderObject* current, Observer* observer)
+{
+    // The SkipEmptyInlines callers never care about endOfInlinePtr.
+    return bidiNextShared(root, current, observer, SkipEmptyInlines);
+}
+
+// This makes callers cleaner as they don't have to specify a type for the observer when not providing one.
+static inline RenderObject* bidiNextSkippingEmptyInlines(RenderObject* root, RenderObject* current)
+{
+    InlineBidiResolver* observer = 0;
+    return bidiNextSkippingEmptyInlines(root, current, observer);
+}
+
+static inline RenderObject* bidiNextIncludingEmptyInlines(RenderObject* root, RenderObject* current, bool* endOfInlinePtr = 0)
+{
+    InlineBidiResolver* observer = 0; // Callers who include empty inlines, never use an observer.
+    return bidiNextShared(root, current, observer, IncludeEmptyInlines, endOfInlinePtr);
+}
+
+static inline RenderObject* bidiFirstSkippingEmptyInlines(RenderObject* root, InlineBidiResolver* resolver = 0)
+{
+    RenderObject* o = root->firstChild();
+    if (!o)
+        return 0;
+
+    if (o->isRenderInline()) {
+        notifyObserverEnteredObject(resolver, o);
+        if (!isEmptyInline(o))
+            o = bidiNextSkippingEmptyInlines(root, o, resolver);
+        else {
+            // Never skip empty inlines.
+            if (resolver)
+                resolver->commitExplicitEmbedding();
+            return o; 
+        }
+    }
+
+    // FIXME: Unify this with the bidiNext call above.
+    if (o && !isIteratorTarget(o))
+        o = bidiNextSkippingEmptyInlines(root, o, resolver);
+
+    if (resolver)
+        resolver->commitExplicitEmbedding();
+    return o;
+}
+
+// FIXME: This method needs to be renamed when bidiNext finds a good name.
+static inline RenderObject* bidiFirstIncludingEmptyInlines(RenderObject* root)
+{
+    RenderObject* o = root->firstChild();
+    // If either there are no children to walk, or the first one is correct
+    // then just return it.
+    if (!o || o->isRenderInline() || isIteratorTarget(o))
+        return o;
+
+    return bidiNextIncludingEmptyInlines(root, o);
+}
+
+inline void InlineIterator::fastIncrementInTextNode()
+{
+    ASSERT(m_obj);
+    ASSERT(m_obj->isText());
+    ASSERT(m_pos <= toRenderText(m_obj)->textLength());
+    m_pos++;
+}
+
+// FIXME: This is used by RenderBlock for simplified layout, and has nothing to do with bidi
+// it shouldn't use functions called bidiFirst and bidiNext.
+class InlineWalker {
+public:
+    InlineWalker(RenderObject* root)
+        : m_root(root)
+        , m_current(0)
+        , m_atEndOfInline(false)
+    {
+        // FIXME: This class should be taught how to do the SkipEmptyInlines codepath as well.
+        m_current = bidiFirstIncludingEmptyInlines(m_root);
+    }
+
+    RenderObject* root() { return m_root; }
+    RenderObject* current() { return m_current; }
+
+    bool atEndOfInline() { return m_atEndOfInline; }
+    bool atEnd() const { return !m_current; }
+
+    RenderObject* advance()
+    {
+        // FIXME: Support SkipEmptyInlines and observer parameters.
+        m_current = bidiNextIncludingEmptyInlines(m_root, m_current, &m_atEndOfInline);
+        return m_current;
+    }
+private:
+    RenderObject* m_root;
+    RenderObject* m_current;
+    bool m_atEndOfInline;
+};
+
+inline void InlineIterator::increment(InlineBidiResolver* resolver)
+{
+    if (!m_obj)
+        return;
+    if (m_obj->isText()) {
+        fastIncrementInTextNode();
+        if (m_pos < toRenderText(m_obj)->textLength())
+            return;
+    }
+    // bidiNext can return 0, so use moveTo instead of moveToStartOf
+    moveTo(bidiNextSkippingEmptyInlines(m_root, m_obj, resolver), 0);
+}
+
+inline bool InlineIterator::atEnd() const
+{
+    return !m_obj;
+}
+
+inline UChar InlineIterator::characterAt(unsigned index) const
+{
+    if (!m_obj || !m_obj->isText())
+        return 0;
+
+    RenderText* text = toRenderText(m_obj);
+    if (index >= text->textLength())
+        return 0;
+
+    return text->characterAt(index);
+}
+
+inline UChar InlineIterator::current() const
+{
+    return characterAt(m_pos);
+}
+
+inline UChar InlineIterator::previousInSameNode() const
+{
+    if (!m_pos)
+        return 0;
+
+    return characterAt(m_pos - 1);
+}
+
+ALWAYS_INLINE WTF::Unicode::Direction InlineIterator::direction() const
+{
+    if (UChar c = current())
+        return WTF::Unicode::direction(c);
+
+    if (m_obj && m_obj->isListMarker())
+        return m_obj->style()->isLeftToRightDirection() ? WTF::Unicode::LeftToRight : WTF::Unicode::RightToLeft;
+
+    return WTF::Unicode::OtherNeutral;
+}
+
+template<>
+inline void InlineBidiResolver::increment()
+{
+    m_current.increment(this);
+}
+
+static inline bool isIsolatedInline(RenderObject* object)
+{
+    ASSERT(object);
+    return object->isRenderInline() && isIsolated(object->style()->unicodeBidi());
+}
+
+static inline RenderObject* containingIsolate(RenderObject* object, RenderObject* root)
+{
+    ASSERT(object);
+    while (object && object != root) {
+        if (isIsolatedInline(object))
+            return object;
+        object = object->parent();
+    }
+    return 0;
+}
+
+static inline unsigned numberOfIsolateAncestors(const InlineIterator& iter)
+{
+    RenderObject* object = iter.object();
+    if (!object)
+        return 0;
+    unsigned count = 0;
+    while (object && object != iter.root()) {
+        if (isIsolatedInline(object))
+            count++;
+        object = object->parent();
+    }
+    return count;
+}
+
+// FIXME: This belongs on InlineBidiResolver, except it's a template specialization
+// of BidiResolver which knows nothing about RenderObjects.
+static inline void addPlaceholderRunForIsolatedInline(InlineBidiResolver& resolver, RenderObject* obj, unsigned pos)
+{
+    ASSERT(obj);
+    BidiRun* isolatedRun = new (obj->renderArena()) BidiRun(pos, 0, obj, resolver.context(), resolver.dir());
+    resolver.runs().addRun(isolatedRun);
+    // FIXME: isolatedRuns() could be a hash of object->run and then we could cheaply
+    // ASSERT here that we didn't create multiple objects for the same inline.
+    resolver.isolatedRuns().append(isolatedRun);
+}
+
+class IsolateTracker {
+public:
+    explicit IsolateTracker(unsigned nestedIsolateCount)
+        : m_nestedIsolateCount(nestedIsolateCount)
+        , m_haveAddedFakeRunForRootIsolate(false)
+    {
+    }
+
+    void enterIsolate() { m_nestedIsolateCount++; }
+    void exitIsolate()
+    {
+        ASSERT(m_nestedIsolateCount >= 1);
+        m_nestedIsolateCount--;
+        if (!inIsolate())
+            m_haveAddedFakeRunForRootIsolate = false;
+    }
+    bool inIsolate() const { return m_nestedIsolateCount; }
+
+    // We don't care if we encounter bidi directional overrides.
+    void embed(WTF::Unicode::Direction, BidiEmbeddingSource) { }
+    void commitExplicitEmbedding() { }
+
+    void addFakeRunIfNecessary(RenderObject* obj, unsigned pos, InlineBidiResolver& resolver)
+    {
+        // We only need to add a fake run for a given isolated span once during each call to createBidiRunsForLine.
+        // We'll be called for every span inside the isolated span so we just ignore subsequent calls.
+        // We also avoid creating a fake run until we hit a child that warrants one, e.g. we skip floats.
+        if (m_haveAddedFakeRunForRootIsolate || RenderBlock::shouldSkipCreatingRunsForObject(obj))
+            return;
+        m_haveAddedFakeRunForRootIsolate = true;
+        // obj and pos together denote a single position in the inline, from which the parsing of the isolate will start.
+        // We don't need to mark the end of the run because this is implicit: it is either endOfLine or the end of the
+        // isolate, when we call createBidiRunsForLine it will stop at whichever comes first.
+        addPlaceholderRunForIsolatedInline(resolver, obj, pos);
+        // FIXME: Inline isolates don't work properly with collapsing whitespace, see webkit.org/b/109624
+        // For now, if we enter an isolate between midpoints, we increment our current midpoint or else
+        // we'll leave the isolate and ignore the content that follows.
+        MidpointState<InlineIterator>& midpointState = resolver.midpointState();
+        if (midpointState.betweenMidpoints && midpointState.midpoints[midpointState.currentMidpoint].object() == obj) {
+            midpointState.betweenMidpoints = false;
+            ++midpointState.currentMidpoint;
+        }
+    }
+
+private:
+    unsigned m_nestedIsolateCount;
+    bool m_haveAddedFakeRunForRootIsolate;
+};
+
+template <>
+inline void InlineBidiResolver::appendRun()
+{
+    if (!m_emptyRun && !m_eor.atEnd() && !m_reachedEndOfLine) {
+        // Keep track of when we enter/leave "unicode-bidi: isolate" inlines.
+        // Initialize our state depending on if we're starting in the middle of such an inline.
+        // FIXME: Could this initialize from this->inIsolate() instead of walking up the render tree?
+        IsolateTracker isolateTracker(numberOfIsolateAncestors(m_sor));
+        int start = m_sor.m_pos;
+        RenderObject* obj = m_sor.m_obj;
+        while (obj && obj != m_eor.m_obj && obj != endOfLine.m_obj) {
+            if (isolateTracker.inIsolate())
+                isolateTracker.addFakeRunIfNecessary(obj, start, *this);
+            else
+                RenderBlock::appendRunsForObject(m_runs, start, obj->length(), obj, *this);
+            // FIXME: start/obj should be an InlineIterator instead of two separate variables.
+            start = 0;
+            obj = bidiNextSkippingEmptyInlines(m_sor.root(), obj, &isolateTracker);
+        }
+        if (obj) {
+            unsigned pos = obj == m_eor.m_obj ? m_eor.m_pos : UINT_MAX;
+            if (obj == endOfLine.m_obj && endOfLine.m_pos <= pos) {
+                m_reachedEndOfLine = true;
+                pos = endOfLine.m_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;
+            if (isolateTracker.inIsolate())
+                isolateTracker.addFakeRunIfNecessary(obj, start, *this);
+            else
+                RenderBlock::appendRunsForObject(m_runs, start, end, obj, *this);
+        }
+
+        m_eor.increment();
+        m_sor = m_eor;
+    }
+
+    m_direction = WTF::Unicode::OtherNeutral;
+    m_status.eor = WTF::Unicode::OtherNeutral;
+}
+
+}
+
+#endif // InlineIterator_h
diff --git a/Source/core/rendering/InlineTextBox.cpp b/Source/core/rendering/InlineTextBox.cpp
new file mode 100644
index 0000000..f90aa8e
--- /dev/null
+++ b/Source/core/rendering/InlineTextBox.cpp
@@ -0,0 +1,1638 @@
+/*
+ * (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 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 "core/rendering/InlineTextBox.h"
+
+#include "core/dom/Document.h"
+#include "core/dom/DocumentMarkerController.h"
+#include "core/dom/RenderedDocumentMarker.h"
+#include "core/dom/Text.h"
+#include "core/dom/WebCoreMemoryInstrumentation.h"
+#include "core/editing/Editor.h"
+#include "core/page/Chrome.h"
+#include "core/page/ChromeClient.h"
+#include "core/page/Frame.h"
+#include "core/page/Page.h"
+#include "core/page/Settings.h"
+#include "core/platform/graphics/FontCache.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/rendering/EllipsisBox.h"
+#include "core/rendering/HitTestResult.h"
+#include "core/rendering/PaintInfo.h"
+#include "core/rendering/RenderArena.h"
+#include "core/rendering/RenderBR.h"
+#include "core/rendering/RenderBlock.h"
+#include "core/rendering/RenderCombineText.h"
+#include "core/rendering/RenderRubyRun.h"
+#include "core/rendering/RenderRubyText.h"
+#include "core/rendering/RenderTheme.h"
+#include "core/rendering/break_lines.h"
+#include "core/rendering/svg/SVGTextRunRenderingContext.h"
+#include <wtf/text/CString.h>
+
+using namespace std;
+
+namespace WebCore {
+
+typedef WTF::HashMap<const InlineTextBox*, LayoutRect> InlineTextBoxOverflowMap;
+static InlineTextBoxOverflowMap* gTextBoxesWithOverflow;
+
+void InlineTextBox::destroy(RenderArena* arena)
+{
+    if (!knownToHaveNoOverflow() && gTextBoxesWithOverflow)
+        gTextBoxesWithOverflow->remove(this);
+    InlineBox::destroy(arena);
+}
+
+void InlineTextBox::markDirty(bool dirty)
+{
+    if (dirty) {
+        m_len = 0;
+        m_start = 0;
+    }
+    InlineBox::markDirty(dirty);
+}
+
+LayoutRect InlineTextBox::logicalOverflowRect() const
+{
+    if (knownToHaveNoOverflow() || !gTextBoxesWithOverflow)
+        return enclosingIntRect(logicalFrameRect());
+    return gTextBoxesWithOverflow->get(this);
+}
+
+void InlineTextBox::setLogicalOverflowRect(const LayoutRect& rect)
+{
+    ASSERT(!knownToHaveNoOverflow());
+    if (!gTextBoxesWithOverflow)
+        gTextBoxesWithOverflow = new InlineTextBoxOverflowMap;
+    gTextBoxesWithOverflow->add(this, rect);
+}
+
+int InlineTextBox::baselinePosition(FontBaseline baselineType) const
+{
+    if (!isText() || !parent())
+        return 0;
+    if (parent()->renderer() == renderer()->parent())
+        return parent()->baselinePosition(baselineType);
+    return toRenderBoxModelObject(renderer()->parent())->baselinePosition(baselineType, isFirstLineStyle(), isHorizontal() ? HorizontalLine : VerticalLine, PositionOnContainingLine);
+}
+
+LayoutUnit InlineTextBox::lineHeight() const
+{
+    if (!isText() || !renderer()->parent())
+        return 0;
+    if (m_renderer->isBR())
+        return toRenderBR(m_renderer)->lineHeight(isFirstLineStyle());
+    if (parent()->renderer() == renderer()->parent())
+        return parent()->lineHeight();
+    return toRenderBoxModelObject(renderer()->parent())->lineHeight(isFirstLineStyle(), isHorizontal() ? HorizontalLine : VerticalLine, PositionOnContainingLine);
+}
+
+LayoutUnit InlineTextBox::selectionTop()
+{
+    return root()->selectionTop();
+}
+
+LayoutUnit InlineTextBox::selectionBottom()
+{
+    return root()->selectionBottom();
+}
+
+LayoutUnit InlineTextBox::selectionHeight()
+{
+    return root()->selectionHeight();
+}
+
+bool InlineTextBox::isSelected(int startPos, int endPos) const
+{
+    int sPos = max(startPos - m_start, 0);
+    // The position after a hard line break is considered to be past its end.
+    // See the corresponding code in InlineTextBox::selectionState.
+    int ePos = min(endPos - m_start, int(m_len) + (isLineBreak() ? 0 : 1));
+    return (sPos < ePos);
+}
+
+RenderObject::SelectionState InlineTextBox::selectionState()
+{
+    RenderObject::SelectionState state = renderer()->selectionState();
+    if (state == RenderObject::SelectionStart || state == RenderObject::SelectionEnd || state == RenderObject::SelectionBoth) {
+        int startPos, endPos;
+        renderer()->selectionStartEnd(startPos, endPos);
+        // The position after a hard line break is considered to be past its end.
+        // See the corresponding code in InlineTextBox::isSelected.
+        int lastSelectable = start() + len() - (isLineBreak() ? 1 : 0);
+
+        // FIXME: Remove -webkit-line-break: LineBreakAfterWhiteSpace.
+        int endOfLineAdjustmentForCSSLineBreak = renderer()->style()->lineBreak() == LineBreakAfterWhiteSpace ? -1 : 0;
+        bool start = (state != RenderObject::SelectionEnd && startPos >= m_start && startPos <= m_start + m_len + endOfLineAdjustmentForCSSLineBreak);
+        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;
+    }
+
+    // If there are ellipsis following, make sure their selection is updated.
+    if (m_truncation != cNoTruncation && root()->ellipsisBox()) {
+        EllipsisBox* ellipsis = root()->ellipsisBox();
+        if (state != RenderObject::SelectionNone) {
+            int start, end;
+            selectionStartEnd(start, end);
+            // The ellipsis should be considered to be selected if the end of
+            // the selection is past the beginning of the truncation and the
+            // beginning of the selection is before or at the beginning of the
+            // truncation.
+            ellipsis->setSelectionState(end >= m_truncation && start <= m_truncation ?
+                RenderObject::SelectionInside : RenderObject::SelectionNone);
+        } else
+            ellipsis->setSelectionState(RenderObject::SelectionNone);
+    }
+
+    return state;
+}
+
+static void adjustCharactersAndLengthForHyphen(BufferForAppendingHyphen& charactersWithHyphen, RenderStyle* style, String& string, int& length)
+{
+    const AtomicString& hyphenString = style->hyphenString();
+    charactersWithHyphen.reserveCapacity(length + hyphenString.length());
+    charactersWithHyphen.append(string);
+    charactersWithHyphen.append(hyphenString);
+    string = charactersWithHyphen.toString();
+    length += hyphenString.length();
+}
+
+LayoutRect InlineTextBox::localSelectionRect(int startPos, int endPos)
+{
+    int sPos = max(startPos - m_start, 0);
+    int ePos = min(endPos - m_start, (int)m_len);
+    
+    if (sPos > ePos)
+        return LayoutRect();
+
+    FontCachePurgePreventer fontCachePurgePreventer;
+
+    RenderText* textObj = textRenderer();
+    LayoutUnit selTop = selectionTop();
+    LayoutUnit selHeight = selectionHeight();
+    RenderStyle* styleToUse = textObj->style(isFirstLineStyle());
+    const Font& font = styleToUse->font();
+
+    BufferForAppendingHyphen charactersWithHyphen;
+    bool respectHyphen = ePos == m_len && hasHyphen();
+    TextRun textRun = constructTextRun(styleToUse, font, respectHyphen ? &charactersWithHyphen : 0);
+    if (respectHyphen)
+        endPos = textRun.length();
+
+    FloatPoint startingPoint = FloatPoint(logicalLeft(), selTop);
+    LayoutRect r;
+    if (sPos || ePos != static_cast<int>(m_len))
+        r = enclosingIntRect(font.selectionRectForText(textRun, startingPoint, selHeight, sPos, ePos));
+    else // Avoid computing the font width when the entire line box is selected as an optimization.
+        r = enclosingIntRect(FloatRect(startingPoint, FloatSize(m_logicalWidth, selHeight)));
+
+    LayoutUnit logicalWidth = r.width();
+    if (r.x() > logicalRight())
+        logicalWidth  = 0;
+    else if (r.maxX() > logicalRight())
+        logicalWidth = logicalRight() - r.x();
+
+    LayoutPoint topPoint = isHorizontal() ? LayoutPoint(r.x(), selTop) : LayoutPoint(selTop, r.x());
+    LayoutUnit width = isHorizontal() ? logicalWidth : selHeight;
+    LayoutUnit height = isHorizontal() ? selHeight : logicalWidth;
+
+    return LayoutRect(topPoint, LayoutSize(width, height));
+}
+
+void InlineTextBox::deleteLine(RenderArena* arena)
+{
+    toRenderText(renderer())->removeTextBox(this);
+    destroy(arena);
+}
+
+void InlineTextBox::extractLine()
+{
+    if (extracted())
+        return;
+
+    toRenderText(renderer())->extractTextBox(this);
+}
+
+void InlineTextBox::attachLine()
+{
+    if (!extracted())
+        return;
+    
+    toRenderText(renderer())->attachTextBox(this);
+}
+
+float InlineTextBox::placeEllipsisBox(bool flowIsLTR, float visibleLeftEdge, float visibleRightEdge, float ellipsisWidth, float &truncatedWidth, bool& foundBox)
+{
+    if (foundBox) {
+        m_truncation = cFullTruncation;
+        return -1;
+    }
+
+    // For LTR this is the left edge of the box, for RTL, the right edge in parent coordinates.
+    float ellipsisX = flowIsLTR ? visibleRightEdge - ellipsisWidth : visibleLeftEdge + ellipsisWidth;
+    
+    // Criteria for full truncation:
+    // LTR: the left edge of the ellipsis is to the left of our text run.
+    // RTL: the right edge of the ellipsis is to the right of our text run.
+    bool ltrFullTruncation = flowIsLTR && ellipsisX <= left();
+    bool rtlFullTruncation = !flowIsLTR && ellipsisX >= left() + logicalWidth();
+    if (ltrFullTruncation || rtlFullTruncation) {
+        // 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;
+    }
+
+    bool ltrEllipsisWithinBox = flowIsLTR && (ellipsisX < right());
+    bool rtlEllipsisWithinBox = !flowIsLTR && (ellipsisX > left());
+    if (ltrEllipsisWithinBox || rtlEllipsisWithinBox) {
+        foundBox = true;
+
+        // The inline box may have different directionality than it's parent.  Since truncation
+        // behavior depends both on both the parent and the inline block's directionality, we
+        // must keep track of these separately.
+        bool ltr = isLeftToRightDirection();
+        if (ltr != flowIsLTR) {
+          // Width in pixels of the visible portion of the box, excluding the ellipsis.
+          int visibleBoxWidth = visibleRightEdge - visibleLeftEdge  - ellipsisWidth;
+          ellipsisX = ltr ? left() + visibleBoxWidth : right() - visibleBoxWidth;
+        }
+
+        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;
+            truncatedWidth += ellipsisWidth;
+            return min(ellipsisX, x());
+        }
+
+        // Set the truncation index on the text run.
+        m_truncation = offset;
+
+        // If we got here that means that we were only partially truncated and we need to return the pixel offset at which
+        // to place the ellipsis.
+        float widthOfVisibleText = toRenderText(renderer())->width(m_start, offset, textPos(), isFirstLineStyle());
+
+        // The ellipsis needs to be placed just after the last visible character.
+        // Where "after" is defined by the flow directionality, not the inline
+        // box directionality.
+        // e.g. In the case of an LTR inline box truncated in an RTL flow then we can
+        // have a situation such as |Hello| -> |...He|
+        truncatedWidth += widthOfVisibleText + ellipsisWidth;
+        if (flowIsLTR)
+            return left() + widthOfVisibleText;
+        else
+            return right() - widthOfVisibleText - ellipsisWidth;
+    }
+    truncatedWidth += logicalWidth();
+    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, ColorSpace colorSpace)
+{
+    TextDrawingModeFlags mode = context->textDrawingMode();
+    if (strokeThickness > 0) {
+        TextDrawingModeFlags newMode = mode | TextModeStroke;
+        if (mode != newMode) {
+            context->setTextDrawingMode(newMode);
+            mode = newMode;
+        }
+    }
+    
+    if (mode & TextModeFill && (fillColor != context->fillColor() || colorSpace != context->fillColorSpace()))
+        context->setFillColor(fillColor, colorSpace);
+
+    if (mode & TextModeStroke) {
+        if (strokeColor != context->strokeColor())
+            context->setStrokeColor(strokeColor, colorSpace);
+        if (strokeThickness != context->strokeThickness())
+            context->setStrokeThickness(strokeThickness);
+    }
+}
+
+bool InlineTextBox::isLineBreak() const
+{
+    return renderer()->isBR() || (renderer()->style()->preserveNewline() && len() == 1 && (*textRenderer()->text())[start()] == '\n');
+}
+
+bool InlineTextBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit /* lineTop */, LayoutUnit /*lineBottom*/)
+{
+    if (isLineBreak())
+        return false;
+
+    FloatPoint boxOrigin = locationIncludingFlipping();
+    boxOrigin.moveBy(accumulatedOffset);
+    FloatRect rect(boxOrigin, size());
+    if (m_truncation != cFullTruncation && visibleToHitTestRequest(request) && locationInContainer.intersects(rect)) {
+        renderer()->updateHitTestResult(result, flipForWritingMode(locationInContainer.point() - toLayoutSize(accumulatedOffset)));
+        if (!result.addNodeToRectBasedTestResult(renderer()->node(), request, locationInContainer, rect))
+            return true;
+    }
+    return false;
+}
+
+FloatSize InlineTextBox::applyShadowToGraphicsContext(GraphicsContext* context, const ShadowData* shadow, const FloatRect& textRect, bool stroked, bool opaque, bool horizontal)
+{
+    if (!shadow)
+        return FloatSize();
+
+    FloatSize extraOffset;
+    int shadowX = horizontal ? shadow->x() : shadow->y();
+    int shadowY = horizontal ? shadow->y() : -shadow->x();
+    FloatSize shadowOffset(shadowX, shadowY);
+    int shadowBlur = shadow->blur();
+    const Color& shadowColor = shadow->color();
+
+    if (shadow->next() || stroked || !opaque) {
+        FloatRect shadowRect(textRect);
+        shadowRect.inflate(shadowBlur);
+        shadowRect.move(shadowOffset);
+        context->save();
+        context->clip(shadowRect);
+
+        extraOffset = FloatSize(0, 2 * textRect.height() + max(0.0f, shadowOffset.height()) + shadowBlur);
+        shadowOffset -= extraOffset;
+    }
+
+    context->setShadow(shadowOffset, shadowBlur, shadowColor, context->fillColorSpace());
+    return extraOffset;
+}
+
+static void paintTextWithShadows(GraphicsContext* context, const Font& font, const TextRun& textRun, const AtomicString& emphasisMark, int emphasisMarkOffset, int startOffset, int endOffset, int truncationPoint, const FloatPoint& textOrigin,
+                                 const FloatRect& boxRect, const ShadowData* shadow, bool stroked, bool horizontal)
+{
+    Color fillColor = context->fillColor();
+    ColorSpace fillColorSpace = context->fillColorSpace();
+    bool opaque = fillColor.alpha() == 255;
+    if (!opaque)
+        context->setFillColor(Color::black, fillColorSpace);
+
+    do {
+        IntSize extraOffset;
+        if (shadow)
+            extraOffset = roundedIntSize(InlineTextBox::applyShadowToGraphicsContext(context, shadow, boxRect, stroked, opaque, horizontal));
+        else if (!opaque)
+            context->setFillColor(fillColor, fillColorSpace);
+
+        if (startOffset <= endOffset) {
+            if (emphasisMark.isEmpty())
+                context->drawText(font, textRun, textOrigin + extraOffset, startOffset, endOffset);
+            else
+                context->drawEmphasisMarks(font, textRun, emphasisMark, textOrigin + extraOffset + IntSize(0, emphasisMarkOffset), startOffset, endOffset);
+        } else {
+            if (endOffset > 0) {
+                if (emphasisMark.isEmpty())
+                    context->drawText(font, textRun, textOrigin + extraOffset,  0, endOffset);
+                else
+                    context->drawEmphasisMarks(font, textRun, emphasisMark, textOrigin + extraOffset + IntSize(0, emphasisMarkOffset),  0, endOffset);
+            }
+            if (startOffset < truncationPoint) {
+                if (emphasisMark.isEmpty())
+                    context->drawText(font, textRun, textOrigin + extraOffset, startOffset, truncationPoint);
+                else
+                    context->drawEmphasisMarks(font, textRun, emphasisMark, textOrigin + extraOffset + IntSize(0, emphasisMarkOffset),  startOffset, truncationPoint);
+            }
+        }
+
+        if (!shadow)
+            break;
+
+        if (shadow->next() || stroked || !opaque)
+            context->restore();
+        else
+            context->clearShadow();
+
+        shadow = shadow->next();
+    } while (shadow || stroked || !opaque);
+}
+
+bool InlineTextBox::getEmphasisMarkPosition(RenderStyle* style, TextEmphasisPosition& emphasisPosition) const
+{
+    // This function returns true if there are text emphasis marks and they are suppressed by ruby text.
+    if (style->textEmphasisMark() == TextEmphasisMarkNone)
+        return false;
+
+    emphasisPosition = style->textEmphasisPosition();
+    if (emphasisPosition == TextEmphasisPositionUnder)
+        return true; // Ruby text is always over, so it cannot suppress emphasis marks under.
+
+    RenderBlock* containingBlock = renderer()->containingBlock();
+    if (!containingBlock->isRubyBase())
+        return true; // This text is not inside a ruby base, so it does not have ruby text over it.
+
+    if (!containingBlock->parent()->isRubyRun())
+        return true; // Cannot get the ruby text.
+
+    RenderRubyText* rubyText = toRenderRubyRun(containingBlock->parent())->rubyText();
+
+    // The emphasis marks over are suppressed only if there is a ruby text box and it not empty.
+    return !rubyText || !rubyText->firstLineBox();
+}
+
+enum RotationDirection { Counterclockwise, Clockwise };
+
+static inline AffineTransform rotation(const FloatRect& boxRect, RotationDirection clockwise)
+{
+    return clockwise ? AffineTransform(0, 1, -1, 0, boxRect.x() + boxRect.maxY(), boxRect.maxY() - boxRect.x())
+        : AffineTransform(0, -1, 1, 0, boxRect.x() - boxRect.maxY(), boxRect.x() + boxRect.maxY());
+}
+
+void InlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit /*lineTop*/, LayoutUnit /*lineBottom*/)
+{
+    if (isLineBreak() || !paintInfo.shouldPaintWithinRoot(renderer()) || renderer()->style()->visibility() != VISIBLE ||
+        m_truncation == cFullTruncation || paintInfo.phase == PaintPhaseOutline || !m_len)
+        return;
+
+    ASSERT(paintInfo.phase != PaintPhaseSelfOutline && paintInfo.phase != PaintPhaseChildOutlines);
+
+    LayoutUnit logicalLeftSide = logicalLeftVisualOverflow();
+    LayoutUnit logicalRightSide = logicalRightVisualOverflow();
+    LayoutUnit logicalStart = logicalLeftSide + (isHorizontal() ? paintOffset.x() : paintOffset.y());
+    LayoutUnit logicalExtent = logicalRightSide - logicalLeftSide;
+    
+    LayoutUnit paintEnd = isHorizontal() ? paintInfo.rect.maxX() : paintInfo.rect.maxY();
+    LayoutUnit paintStart = isHorizontal() ? paintInfo.rect.x() : paintInfo.rect.y();
+    
+    LayoutPoint adjustedPaintOffset = roundedIntPoint(paintOffset);
+    
+    if (logicalStart >= paintEnd || logicalStart + logicalExtent <= paintStart)
+        return;
+
+    bool isPrinting = textRenderer()->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;
+
+    if (m_truncation != cNoTruncation) {
+        if (renderer()->containingBlock()->style()->isLeftToRightDirection() != isLeftToRightDirection()) {
+            // Make the visible fragment of text hug the edge closest to the rest of the run by moving the origin
+            // at which we start drawing text.
+            // e.g. In the case of LTR text truncated in an RTL Context, the correct behavior is:
+            // |Hello|CBA| -> |...He|CBA|
+            // In order to draw the fragment "He" aligned to the right edge of it's box, we need to start drawing
+            // farther to the right.
+            // NOTE: WebKit's behavior differs from that of IE which appears to just overlay the ellipsis on top of the
+            // truncated string i.e.  |Hello|CBA| -> |...lo|CBA|
+            LayoutUnit widthOfVisibleText = toRenderText(renderer())->width(m_start, m_truncation, textPos(), isFirstLineStyle());
+            LayoutUnit widthOfHiddenText = m_logicalWidth - widthOfVisibleText;
+            // FIXME: The hit testing logic also needs to take this translation into account.
+            LayoutSize truncationOffset(isLeftToRightDirection() ? widthOfHiddenText : -widthOfHiddenText, 0);
+            adjustedPaintOffset.move(isHorizontal() ? truncationOffset : truncationOffset.transposedSize());
+        }
+    }
+
+    GraphicsContext* context = paintInfo.context;
+
+    RenderStyle* styleToUse = renderer()->style(isFirstLineStyle());
+    
+    adjustedPaintOffset.move(0, styleToUse->isHorizontalWritingMode() ? 0 : -logicalHeight());
+
+    FloatPoint boxOrigin = locationIncludingFlipping();
+    boxOrigin.move(adjustedPaintOffset.x(), adjustedPaintOffset.y());
+    FloatRect boxRect(boxOrigin, LayoutSize(logicalWidth(), logicalHeight()));
+
+    RenderCombineText* combinedText = styleToUse->hasTextCombine() && textRenderer()->isCombineText() && toRenderCombineText(textRenderer())->isCombined() ? toRenderCombineText(textRenderer()) : 0;
+
+    bool shouldRotate = !isHorizontal() && !combinedText;
+    if (shouldRotate)
+        context->concatCTM(rotation(boxRect, Clockwise));
+
+    // Determine whether or not we have composition underlines to draw.
+    bool containsComposition = renderer()->node() && renderer()->frame()->editor()->compositionNode() == renderer()->node();
+    bool useCustomUnderlines = containsComposition && renderer()->frame()->editor()->compositionUsesCustomUnderlines();
+
+    // Determine the text colors and selection colors.
+    Color textFillColor;
+    Color textStrokeColor;
+    Color emphasisMarkColor;
+    float textStrokeWidth = styleToUse->textStrokeWidth();
+    const ShadowData* textShadow = paintInfo.forceBlackText() ? 0 : styleToUse->textShadow();
+
+    if (paintInfo.forceBlackText()) {
+        textFillColor = Color::black;
+        textStrokeColor = Color::black;
+        emphasisMarkColor = Color::black;
+    } else {
+        textFillColor = styleToUse->visitedDependentColor(CSSPropertyWebkitTextFillColor);
+        
+        bool forceBackgroundToWhite = false;
+        if (isPrinting) {
+            if (styleToUse->printColorAdjust() == PrintColorAdjustEconomy)
+                forceBackgroundToWhite = true;
+            if (textRenderer()->document()->settings() && textRenderer()->document()->settings()->shouldPrintBackgrounds())
+                forceBackgroundToWhite = false;
+        }
+
+        // Make the text fill color legible against a white background
+        if (forceBackgroundToWhite)
+            textFillColor = correctedTextColor(textFillColor, Color::white);
+
+        textStrokeColor = styleToUse->visitedDependentColor(CSSPropertyWebkitTextStrokeColor);
+        
+        // Make the text stroke color legible against a white background
+        if (forceBackgroundToWhite)
+            textStrokeColor = correctedTextColor(textStrokeColor, Color::white);
+
+        emphasisMarkColor = styleToUse->visitedDependentColor(CSSPropertyWebkitTextEmphasisColor);
+        
+        // Make the text stroke color legible against a white background
+        if (forceBackgroundToWhite)
+            emphasisMarkColor = correctedTextColor(emphasisMarkColor, Color::white);
+    }
+
+    bool paintSelectedTextOnly = (paintInfo.phase == PaintPhaseSelection);
+    bool paintSelectedTextSeparately = false;
+
+    Color selectionFillColor = textFillColor;
+    Color selectionStrokeColor = textStrokeColor;
+    Color selectionEmphasisMarkColor = emphasisMarkColor;
+    float selectionStrokeWidth = textStrokeWidth;
+    const ShadowData* selectionShadow = textShadow;
+    if (haveSelection) {
+        // Check foreground color first.
+        Color foreground = paintInfo.forceBlackText() ? Color::black : renderer()->selectionForegroundColor();
+        if (foreground.isValid() && foreground != selectionFillColor) {
+            if (!paintSelectedTextOnly)
+                paintSelectedTextSeparately = true;
+            selectionFillColor = foreground;
+        }
+
+        Color emphasisMarkForeground = paintInfo.forceBlackText() ? Color::black : renderer()->selectionEmphasisMarkColor();
+        if (emphasisMarkForeground.isValid() && emphasisMarkForeground != selectionEmphasisMarkColor) {
+            if (!paintSelectedTextOnly)
+                paintSelectedTextSeparately = true;
+            selectionEmphasisMarkColor = emphasisMarkForeground;
+        }
+
+        if (RenderStyle* pseudoStyle = renderer()->getCachedPseudoStyle(SELECTION)) {
+            const 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->visitedDependentColor(CSSPropertyWebkitTextStrokeColor);
+            if (stroke != selectionStrokeColor) {
+                if (!paintSelectedTextOnly)
+                    paintSelectedTextSeparately = true;
+                selectionStrokeColor = stroke;
+            }
+        }
+    }
+
+    // Set our font.
+    const Font& font = styleToUse->font();
+
+    FloatPoint textOrigin = FloatPoint(boxOrigin.x(), boxOrigin.y() + font.fontMetrics().ascent());
+
+    if (combinedText)
+        combinedText->adjustTextOrigin(textOrigin, boxRect);
+
+    // 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 (containsComposition && !useCustomUnderlines)
+            paintCompositionBackground(context, boxOrigin, styleToUse, font,
+                renderer()->frame()->editor()->compositionStart(),
+                renderer()->frame()->editor()->compositionEnd());
+
+        paintDocumentMarkers(context, boxOrigin, styleToUse, font, true);
+
+        if (haveSelection && !useCustomUnderlines)
+            paintSelection(context, boxOrigin, styleToUse, font, selectionFillColor);
+    }
+
+    if (Frame* frame = renderer()->frame()) {
+        if (Page* page = frame->page()) {
+            // FIXME: Right now, InlineTextBoxes never call addRelevantUnpaintedObject() even though they might
+            // legitimately be unpainted if they are waiting on a slow-loading web font. We should fix that, and
+            // when we do, we will have to account for the fact the InlineTextBoxes do not always have unique
+            // renderers and Page currently relies on each unpainted object having a unique renderer.
+            if (paintInfo.phase == PaintPhaseForeground)
+                page->addRelevantRepaintedObject(renderer(), IntRect(boxOrigin.x(), boxOrigin.y(), logicalWidth(), logicalHeight()));
+        }
+    }
+
+    // 2. Now paint the foreground, including text and decorations like underline/overline (in quirks mode only).
+    int length = m_len;
+    int maximumLength;
+    String string;
+    if (!combinedText) {
+        string = textRenderer()->text();
+        if (static_cast<unsigned>(length) != string.length() || m_start) {
+            ASSERT_WITH_SECURITY_IMPLICATION(static_cast<unsigned>(m_start + length) <= string.length());
+            string = string.substringSharingImpl(m_start, length);
+        }
+        maximumLength = textRenderer()->textLength() - m_start;
+    } else {
+        combinedText->getStringToRender(m_start, string, length);
+        maximumLength = length;
+    }
+
+    BufferForAppendingHyphen charactersWithHyphen;
+    TextRun textRun = constructTextRun(styleToUse, font, string, maximumLength, hasHyphen() ? &charactersWithHyphen : 0);
+    if (hasHyphen())
+        length = textRun.length();
+
+    int sPos = 0;
+    int ePos = 0;
+    if (paintSelectedTextOnly || paintSelectedTextSeparately)
+        selectionStartEnd(sPos, ePos);
+
+    if (m_truncation != cNoTruncation) {
+        sPos = min<int>(sPos, m_truncation);
+        ePos = min<int>(ePos, m_truncation);
+        length = m_truncation;
+    }
+
+    int emphasisMarkOffset = 0;
+    TextEmphasisPosition emphasisMarkPosition;
+    bool hasTextEmphasis = getEmphasisMarkPosition(styleToUse, emphasisMarkPosition);
+    const AtomicString& emphasisMark = hasTextEmphasis ? styleToUse->textEmphasisMarkString() : nullAtom;
+    if (!emphasisMark.isEmpty())
+        emphasisMarkOffset = emphasisMarkPosition == TextEmphasisPositionOver ? -font.fontMetrics().ascent() - font.emphasisMarkDescent(emphasisMark) : font.fontMetrics().descent() + font.emphasisMarkAscent(emphasisMark);
+
+    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.
+        GraphicsContextStateSaver stateSaver(*context, textStrokeWidth > 0);
+
+        updateGraphicsContext(context, textFillColor, textStrokeColor, textStrokeWidth, styleToUse->colorSpace());
+        if (!paintSelectedTextSeparately || ePos <= sPos) {
+            // FIXME: Truncate right-to-left text correctly.
+            paintTextWithShadows(context, font, textRun, nullAtom, 0, 0, length, length, textOrigin, boxRect, textShadow, textStrokeWidth > 0, isHorizontal());
+        } else
+            paintTextWithShadows(context, font, textRun, nullAtom, 0, ePos, sPos, length, textOrigin, boxRect, textShadow, textStrokeWidth > 0, isHorizontal());
+
+        if (!emphasisMark.isEmpty()) {
+            updateGraphicsContext(context, emphasisMarkColor, textStrokeColor, textStrokeWidth, styleToUse->colorSpace());
+
+            DEFINE_STATIC_LOCAL(TextRun, objectReplacementCharacterTextRun, (&objectReplacementCharacter, 1));
+            TextRun& emphasisMarkTextRun = combinedText ? objectReplacementCharacterTextRun : textRun;
+            FloatPoint emphasisMarkTextOrigin = combinedText ? FloatPoint(boxOrigin.x() + boxRect.width() / 2, boxOrigin.y() + font.fontMetrics().ascent()) : textOrigin;
+            if (combinedText)
+                context->concatCTM(rotation(boxRect, Clockwise));
+
+            if (!paintSelectedTextSeparately || ePos <= sPos) {
+                // FIXME: Truncate right-to-left text correctly.
+                paintTextWithShadows(context, combinedText ? combinedText->originalFont() : font, emphasisMarkTextRun, emphasisMark, emphasisMarkOffset, 0, length, length, emphasisMarkTextOrigin, boxRect, textShadow, textStrokeWidth > 0, isHorizontal());
+            } else
+                paintTextWithShadows(context, combinedText ? combinedText->originalFont() : font, emphasisMarkTextRun, emphasisMark, emphasisMarkOffset, ePos, sPos, length, emphasisMarkTextOrigin, boxRect, textShadow, textStrokeWidth > 0, isHorizontal());
+
+            if (combinedText)
+                context->concatCTM(rotation(boxRect, Counterclockwise));
+        }
+    }
+
+    if ((paintSelectedTextOnly || paintSelectedTextSeparately) && sPos < ePos) {
+        // paint only the text that is selected
+        GraphicsContextStateSaver stateSaver(*context, selectionStrokeWidth > 0);
+
+        updateGraphicsContext(context, selectionFillColor, selectionStrokeColor, selectionStrokeWidth, styleToUse->colorSpace());
+        paintTextWithShadows(context, font, textRun, nullAtom, 0, sPos, ePos, length, textOrigin, boxRect, selectionShadow, selectionStrokeWidth > 0, isHorizontal());
+        if (!emphasisMark.isEmpty()) {
+            updateGraphicsContext(context, selectionEmphasisMarkColor, textStrokeColor, textStrokeWidth, styleToUse->colorSpace());
+
+            DEFINE_STATIC_LOCAL(TextRun, objectReplacementCharacterTextRun, (&objectReplacementCharacter, 1));
+            TextRun& emphasisMarkTextRun = combinedText ? objectReplacementCharacterTextRun : textRun;
+            FloatPoint emphasisMarkTextOrigin = combinedText ? FloatPoint(boxOrigin.x() + boxRect.width() / 2, boxOrigin.y() + font.fontMetrics().ascent()) : textOrigin;
+            if (combinedText)
+                context->concatCTM(rotation(boxRect, Clockwise));
+
+            paintTextWithShadows(context, combinedText ? combinedText->originalFont() : font, emphasisMarkTextRun, emphasisMark, emphasisMarkOffset, sPos, ePos, length, emphasisMarkTextOrigin, boxRect, selectionShadow, selectionStrokeWidth > 0, isHorizontal());
+
+            if (combinedText)
+                context->concatCTM(rotation(boxRect, Counterclockwise));
+        }
+    }
+
+    // Paint decorations
+    ETextDecoration textDecorations = styleToUse->textDecorationsInEffect();
+    if (textDecorations != TDNONE && paintInfo.phase != PaintPhaseSelection) {
+        updateGraphicsContext(context, textFillColor, textStrokeColor, textStrokeWidth, styleToUse->colorSpace());
+        if (combinedText)
+            context->concatCTM(rotation(boxRect, Clockwise));
+        paintDecoration(context, boxOrigin, textDecorations, styleToUse->textDecorationStyle(), textShadow);
+        if (combinedText)
+            context->concatCTM(rotation(boxRect, Counterclockwise));
+    }
+
+    if (paintInfo.phase == PaintPhaseForeground) {
+        paintDocumentMarkers(context, boxOrigin, styleToUse, font, false);
+
+        if (useCustomUnderlines) {
+            const Vector<CompositionUnderline>& underlines = renderer()->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, boxOrigin, 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 (shouldRotate)
+        context->concatCTM(rotation(boxRect, Counterclockwise));
+}
+
+void InlineTextBox::selectionStartEnd(int& sPos, int& ePos)
+{
+    int startPos, endPos;
+    if (renderer()->selectionState() == RenderObject::SelectionInside) {
+        startPos = 0;
+        endPos = textRenderer()->textLength();
+    } else {
+        textRenderer()->selectionStartEnd(startPos, endPos);
+        if (renderer()->selectionState() == RenderObject::SelectionStart)
+            endPos = textRenderer()->textLength();
+        else if (renderer()->selectionState() == RenderObject::SelectionEnd)
+            startPos = 0;
+    }
+
+    sPos = max(startPos - m_start, 0);
+    ePos = min(endPos - m_start, (int)m_len);
+}
+
+void alignSelectionRectToDevicePixels(FloatRect& rect)
+{
+    float maxX = floorf(rect.maxX());
+    rect.setX(floorf(rect.x()));
+    rect.setWidth(roundf(maxX - rect.x()));
+}
+
+void InlineTextBox::paintSelection(GraphicsContext* context, const FloatPoint& boxOrigin, RenderStyle* style, const Font& font, Color textColor)
+{
+    if (context->paintingDisabled())
+        return;
+
+    // See if we have a selection to paint at all.
+    int sPos, ePos;
+    selectionStartEnd(sPos, ePos);
+    if (sPos >= ePos)
+        return;
+
+    Color c = renderer()->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.
+    if (textColor == c)
+        c = Color(0xff - c.red(), 0xff - c.green(), 0xff - c.blue());
+
+    GraphicsContextStateSaver stateSaver(*context);
+    updateGraphicsContext(context, c, c, 0, style->colorSpace());  // Don't draw text at all!
+    
+    // If the text is truncated, let the thing being painted in the truncation
+    // draw its own highlight.
+    int length = m_truncation != cNoTruncation ? m_truncation : m_len;
+    String string = textRenderer()->text();
+
+    if (string.length() != static_cast<unsigned>(length) || m_start) {
+        ASSERT_WITH_SECURITY_IMPLICATION(static_cast<unsigned>(m_start + length) <= string.length());
+        string = string.substringSharingImpl(m_start, length);
+    }
+
+    BufferForAppendingHyphen charactersWithHyphen;
+    bool respectHyphen = ePos == length && hasHyphen();
+    TextRun textRun = constructTextRun(style, font, string, textRenderer()->textLength() - m_start, respectHyphen ? &charactersWithHyphen : 0);
+    if (respectHyphen)
+        ePos = textRun.length();
+
+    LayoutUnit selectionBottom = root()->selectionBottom();
+    LayoutUnit selectionTop = root()->selectionTopAdjustedForPrecedingBlock();
+
+    int deltaY = roundToInt(renderer()->style()->isFlippedLinesWritingMode() ? selectionBottom - logicalBottom() : logicalTop() - selectionTop);
+    int selHeight = max(0, roundToInt(selectionBottom - selectionTop));
+
+    FloatPoint localOrigin(boxOrigin.x(), boxOrigin.y() - deltaY);
+    FloatRect clipRect(localOrigin, FloatSize(m_logicalWidth, selHeight));
+    alignSelectionRectToDevicePixels(clipRect);
+
+    context->clip(clipRect);
+
+    context->drawHighlightForText(font, textRun, localOrigin, selHeight, c, style->colorSpace(), sPos, ePos);
+}
+
+void InlineTextBox::paintCompositionBackground(GraphicsContext* context, const FloatPoint& boxOrigin, RenderStyle* style, const Font& font, 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;
+
+    GraphicsContextStateSaver stateSaver(*context);
+
+    Color c = Color(225, 221, 85);
+    
+    updateGraphicsContext(context, c, c, 0, style->colorSpace()); // Don't draw text at all!
+
+    int deltaY = renderer()->style()->isFlippedLinesWritingMode() ? selectionBottom() - logicalBottom() : logicalTop() - selectionTop();
+    int selHeight = selectionHeight();
+    FloatPoint localOrigin(boxOrigin.x(), boxOrigin.y() - deltaY);
+    context->drawHighlightForText(font, constructTextRun(style, font), localOrigin, selHeight, c, style->colorSpace(), sPos, ePos);
+}
+
+static StrokeStyle textDecorationStyleToStrokeStyle(TextDecorationStyle decorationStyle)
+{
+    StrokeStyle strokeStyle = SolidStroke;
+    switch (decorationStyle) {
+    case TextDecorationStyleSolid:
+        strokeStyle = SolidStroke;
+        break;
+#if ENABLE(CSS3_TEXT)
+    case TextDecorationStyleDouble:
+        strokeStyle = DoubleStroke;
+        break;
+    case TextDecorationStyleDotted:
+        strokeStyle = DottedStroke;
+        break;
+    case TextDecorationStyleDashed:
+        strokeStyle = DashedStroke;
+        break;
+    case TextDecorationStyleWavy:
+        strokeStyle = WavyStroke;
+        break;
+#endif // CSS3_TEXT
+    }
+
+    return strokeStyle;
+}
+
+#if ENABLE(CSS3_TEXT)
+static int computeUnderlineOffset(const TextUnderlinePosition underlinePosition, const FontMetrics& fontMetrics, const InlineTextBox* inlineTextBox, const int textDecorationThickness)
+{
+    // Compute the gap between the font and the underline. Use at least one
+    // pixel gap, if underline is thick then use a bigger gap.
+    const int gap = max<int>(1, ceilf(textDecorationThickness / 2.0));
+
+    // According to the specification TextUnderlinePositionAuto should default to 'alphabetic' for horizontal text
+    // and to 'under Left' for vertical text (e.g. japanese). We support only horizontal text for now.
+    switch (underlinePosition) {
+    case TextUnderlinePositionAlphabetic:
+    case TextUnderlinePositionAuto:
+        return fontMetrics.ascent() + gap; // Position underline near the alphabetic baseline.
+    case TextUnderlinePositionUnder: {
+        // Position underline relative to the under edge of the lowest element's content box.
+        const float offset = inlineTextBox->root()->maxLogicalTop() - inlineTextBox->logicalTop();
+        if (offset > 0)
+            return inlineTextBox->logicalHeight() + gap + offset;
+        return inlineTextBox->logicalHeight() + gap;
+    }
+    }
+
+    ASSERT_NOT_REACHED();
+    return fontMetrics.ascent() + gap;
+}
+#endif // CSS3_TEXT
+
+#if ENABLE(CSS3_TEXT)
+static void adjustStepToDecorationLength(float& step, float& controlPointDistance, float length)
+{
+    ASSERT(step > 0);
+
+    if (length <= 0)
+        return;
+
+    unsigned stepCount = static_cast<unsigned>(length / step);
+
+    // Each Bezier curve starts at the same pixel that the previous one
+    // ended. We need to subtract (stepCount - 1) pixels when calculating the
+    // length covered to account for that.
+    float uncoveredLength = length - (stepCount * step - (stepCount - 1));
+    float adjustment = uncoveredLength / stepCount;
+    step += adjustment;
+    controlPointDistance += adjustment;
+}
+
+/*
+ * Draw one cubic Bezier curve and repeat the same pattern long the the decoration's axis.
+ * The start point (p1), controlPoint1, controlPoint2 and end point (p2) of the Bezier curve
+ * form a diamond shape:
+ *
+ *                              step
+ *                         |-----------|
+ *
+ *                   controlPoint1
+ *                         +
+ *
+ *
+ *                  . .
+ *                .     .
+ *              .         .
+ * (x1, y1) p1 +           .            + p2 (x2, y2) - <--- Decoration's axis
+ *                          .         .               |
+ *                            .     .                 |
+ *                              . .                   | controlPointDistance
+ *                                                    |
+ *                                                    |
+ *                         +                          -
+ *                   controlPoint2
+ *
+ *             |-----------|
+ *                 step
+ */
+static void strokeWavyTextDecoration(GraphicsContext* context, FloatPoint& p1, FloatPoint& p2, float strokeThickness)
+{
+    context->adjustLineToPixelBoundaries(p1, p2, strokeThickness, context->strokeStyle());
+
+    Path path;
+    path.moveTo(p1);
+
+    // Distance between decoration's axis and Bezier curve's control points.
+    // The height of the curve is based on this distance. Use a minimum of 6 pixels distance since
+    // the actual curve passes approximately at half of that distance, that is 3 pixels.
+    // The minimum height of the curve is also approximately 3 pixels. Increases the curve's height
+    // as strockThickness increases to make the curve looks better.
+    float controlPointDistance = 3 * max<float>(2, strokeThickness);
+
+    // Increment used to form the diamond shape between start point (p1), control
+    // points and end point (p2) along the axis of the decoration. Makes the
+    // curve wider as strockThickness increases to make the curve looks better.
+    float step = 2 * max<float>(2, strokeThickness);
+
+    bool isVerticalLine = (p1.x() == p2.x());
+
+    if (isVerticalLine) {
+        ASSERT(p1.x() == p2.x());
+
+        float xAxis = p1.x();
+        float y1;
+        float y2;
+
+        if (p1.y() < p2.y()) {
+            y1 = p1.y();
+            y2 = p2.y();
+        } else {
+            y1 = p2.y();
+            y2 = p1.y();
+        }
+
+        adjustStepToDecorationLength(step, controlPointDistance, y2 - y1);
+        FloatPoint controlPoint1(xAxis + controlPointDistance, 0);
+        FloatPoint controlPoint2(xAxis - controlPointDistance, 0);
+
+        for (float y = y1; y + 2 * step <= y2;) {
+            controlPoint1.setY(y + step);
+            controlPoint2.setY(y + step);
+            y += 2 * step;
+            path.addBezierCurveTo(controlPoint1, controlPoint2, FloatPoint(xAxis, y));
+        }
+    } else {
+        ASSERT(p1.y() == p2.y());
+
+        float yAxis = p1.y();
+        float x1;
+        float x2;
+
+        if (p1.x() < p2.x()) {
+            x1 = p1.x();
+            x2 = p2.x();
+        } else {
+            x1 = p2.x();
+            x2 = p1.x();
+        }
+
+        adjustStepToDecorationLength(step, controlPointDistance, x2 - x1);
+        FloatPoint controlPoint1(0, yAxis + controlPointDistance);
+        FloatPoint controlPoint2(0, yAxis - controlPointDistance);
+
+        for (float x = x1; x + 2 * step <= x2;) {
+            controlPoint1.setX(x + step);
+            controlPoint2.setX(x + step);
+            x += 2 * step;
+            path.addBezierCurveTo(controlPoint1, controlPoint2, FloatPoint(x, yAxis));
+        }
+    }
+
+    context->setShouldAntialias(true);
+    context->strokePath(path);
+}
+#endif // CSS3_TEXT
+
+void InlineTextBox::paintDecoration(GraphicsContext* context, const FloatPoint& boxOrigin, ETextDecoration deco, TextDecorationStyle decorationStyle, const ShadowData* shadow)
+{
+    // FIXME: We should improve this rule and not always just assume 1.
+    const float textDecorationThickness = 1.f;
+
+    if (m_truncation == cFullTruncation)
+        return;
+
+    FloatPoint localOrigin = boxOrigin;
+
+    float width = m_logicalWidth;
+    if (m_truncation != cNoTruncation) {
+        width = toRenderText(renderer())->width(m_start, m_truncation, textPos(), isFirstLineStyle());
+        if (!isLeftToRightDirection())
+            localOrigin.move(m_logicalWidth - width, 0);
+    }
+    
+    // Get the text decoration colors.
+    Color underline, overline, linethrough;
+    renderer()->getTextDecorationColors(deco, underline, overline, linethrough, true);
+    if (isFirstLineStyle())
+        renderer()->getTextDecorationColors(deco, underline, overline, linethrough, true, true);
+    
+    // Use a special function for underlines to get the positioning exactly right.
+    bool isPrinting = textRenderer()->document()->printing();
+    context->setStrokeThickness(textDecorationThickness);
+
+    bool linesAreOpaque = !isPrinting && (!(deco & UNDERLINE) || underline.alpha() == 255) && (!(deco & OVERLINE) || overline.alpha() == 255) && (!(deco & LINE_THROUGH) || linethrough.alpha() == 255);
+
+    RenderStyle* styleToUse = renderer()->style(isFirstLineStyle());
+    int baseline = styleToUse->fontMetrics().ascent();
+
+    bool setClip = false;
+    int extraOffset = 0;
+    if (!linesAreOpaque && shadow && shadow->next()) {
+        FloatRect clipRect(localOrigin, FloatSize(width, baseline + 2));
+        for (const ShadowData* s = shadow; s; s = s->next()) {
+            FloatRect shadowRect(localOrigin, FloatSize(width, baseline + 2));
+            shadowRect.inflate(s->blur());
+            int shadowX = isHorizontal() ? s->x() : s->y();
+            int shadowY = isHorizontal() ? s->y() : -s->x();
+            shadowRect.move(shadowX, shadowY);
+            clipRect.unite(shadowRect);
+            extraOffset = max(extraOffset, max(0, shadowY) + s->blur());
+        }
+        context->save();
+        context->clip(clipRect);
+        extraOffset += baseline + 2;
+        localOrigin.move(0, extraOffset);
+        setClip = true;
+    }
+
+    ColorSpace colorSpace = renderer()->style()->colorSpace();
+    bool setShadow = false;
+
+    do {
+        if (shadow) {
+            if (!shadow->next()) {
+                // The last set of lines paints normally inside the clip.
+                localOrigin.move(0, -extraOffset);
+                extraOffset = 0;
+            }
+            int shadowX = isHorizontal() ? shadow->x() : shadow->y();
+            int shadowY = isHorizontal() ? shadow->y() : -shadow->x();
+            context->setShadow(FloatSize(shadowX, shadowY - extraOffset), shadow->blur(), shadow->color(), colorSpace);
+            setShadow = true;
+            shadow = shadow->next();
+        }
+
+#if ENABLE(CSS3_TEXT)
+        // Offset between lines - always non-zero, so lines never cross each other.
+        float doubleOffset = textDecorationThickness + 1.f;
+#endif // CSS3_TEXT
+        context->setStrokeStyle(textDecorationStyleToStrokeStyle(decorationStyle));
+        if (deco & UNDERLINE) {
+            context->setStrokeColor(underline, colorSpace);
+#if ENABLE(CSS3_TEXT)
+            TextUnderlinePosition underlinePosition = styleToUse->textUnderlinePosition();
+            const int underlineOffset = computeUnderlineOffset(underlinePosition, styleToUse->fontMetrics(), this, textDecorationThickness);
+
+            switch (decorationStyle) {
+            case TextDecorationStyleWavy: {
+                FloatPoint start(localOrigin.x(), localOrigin.y() + underlineOffset + doubleOffset);
+                FloatPoint end(localOrigin.x() + width, localOrigin.y() + underlineOffset + doubleOffset);
+                strokeWavyTextDecoration(context, start, end, textDecorationThickness);
+                break;
+            }
+            default:
+                context->drawLineForText(FloatPoint(localOrigin.x(), localOrigin.y() + underlineOffset), width, isPrinting);
+
+                if (decorationStyle == TextDecorationStyleDouble)
+                    context->drawLineForText(FloatPoint(localOrigin.x(), localOrigin.y() + underlineOffset + doubleOffset), width, isPrinting);
+            }
+#else
+            // Leave one pixel of white between the baseline and the underline.
+            context->drawLineForText(FloatPoint(localOrigin.x(), localOrigin.y() + baseline + 1), width, isPrinting);
+#endif // CSS3_TEXT
+        }
+        if (deco & OVERLINE) {
+            context->setStrokeColor(overline, colorSpace);
+#if ENABLE(CSS3_TEXT)
+            switch (decorationStyle) {
+            case TextDecorationStyleWavy: {
+                FloatPoint start(localOrigin.x(), localOrigin.y() - doubleOffset);
+                FloatPoint end(localOrigin.x() + width, localOrigin.y() - doubleOffset);
+                strokeWavyTextDecoration(context, start, end, textDecorationThickness);
+                break;
+            }
+            default:
+#endif // CSS3_TEXT
+                context->drawLineForText(localOrigin, width, isPrinting);
+#if ENABLE(CSS3_TEXT)
+                if (decorationStyle == TextDecorationStyleDouble)
+                    context->drawLineForText(FloatPoint(localOrigin.x(), localOrigin.y() - doubleOffset), width, isPrinting);
+            }
+#endif // CSS3_TEXT
+        }
+        if (deco & LINE_THROUGH) {
+            context->setStrokeColor(linethrough, colorSpace);
+#if ENABLE(CSS3_TEXT)
+            switch (decorationStyle) {
+            case TextDecorationStyleWavy: {
+                FloatPoint start(localOrigin.x(), localOrigin.y() + 2 * baseline / 3);
+                FloatPoint end(localOrigin.x() + width, localOrigin.y() + 2 * baseline / 3);
+                strokeWavyTextDecoration(context, start, end, textDecorationThickness);
+                break;
+            }
+            default:
+#endif // CSS3_TEXT
+                context->drawLineForText(FloatPoint(localOrigin.x(), localOrigin.y() + 2 * baseline / 3), width, isPrinting);
+#if ENABLE(CSS3_TEXT)
+                if (decorationStyle == TextDecorationStyleDouble)
+                    context->drawLineForText(FloatPoint(localOrigin.x(), localOrigin.y() + doubleOffset + 2 * baseline / 3), width, isPrinting);
+            }
+#endif // CSS3_TEXT
+        }
+    } while (shadow);
+
+    if (setClip)
+        context->restore();
+    else if (setShadow)
+        context->clearShadow();
+}
+
+static GraphicsContext::DocumentMarkerLineStyle lineStyleForMarkerType(DocumentMarker::MarkerType markerType)
+{
+    switch (markerType) {
+    case DocumentMarker::Spelling:
+        return GraphicsContext::DocumentMarkerSpellingLineStyle;
+    case DocumentMarker::Grammar:
+        return GraphicsContext::DocumentMarkerGrammarLineStyle;
+    case DocumentMarker::CorrectionIndicator:
+        return GraphicsContext::DocumentMarkerAutocorrectionReplacementLineStyle;
+    case DocumentMarker::DictationAlternatives:
+        return GraphicsContext::DocumentMarkerDictationAlternativesLineStyle;
+    default:
+        ASSERT_NOT_REACHED();
+        return GraphicsContext::DocumentMarkerSpellingLineStyle;
+    }
+}
+
+void InlineTextBox::paintDocumentMarker(GraphicsContext* pt, const FloatPoint& boxOrigin, DocumentMarker* marker, RenderStyle* style, const Font& font, bool grammar)
+{
+    // Never print spelling/grammar markers (5327887)
+    if (textRenderer()->document()->printing())
+        return;
+
+    if (m_truncation == cFullTruncation)
+        return;
+
+    float start = 0; // start of line to draw, relative to tx
+    float width = m_logicalWidth; // 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;
+
+    bool isDictationMarker = marker->type() == DocumentMarker::DictationAlternatives;
+    if (!markerSpansWholeBox || grammar || isDictationMarker) {
+        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
+        int deltaY = renderer()->style()->isFlippedLinesWritingMode() ? selectionBottom() - logicalBottom() : logicalTop() - selectionTop();
+        int selHeight = selectionHeight();
+        FloatPoint startPoint(boxOrigin.x(), boxOrigin.y() - deltaY);
+        TextRun run = constructTextRun(style, font);
+
+        // FIXME: Convert the document markers to float rects.
+        IntRect markerRect = enclosingIntRect(font.selectionRectForText(run, startPoint, selHeight, 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 || isDictationMarker) {
+            markerRect.move(-boxOrigin.x(), -boxOrigin.y());
+            markerRect = renderer()->localToAbsoluteQuad(FloatRect(markerRect)).enclosingBoundingBox();
+            toRenderedDocumentMarker(marker)->setRenderedRect(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 baseline = renderer()->style(isFirstLineStyle())->fontMetrics().ascent();
+    int descent = logicalHeight() - baseline;
+    int underlineOffset;
+    if (descent <= (2 + lineThickness)) {
+        // Place the underline at the very bottom of the text in small/medium fonts.
+        underlineOffset = logicalHeight() - lineThickness;
+    } else {
+        // In larger fonts, though, place the underline up near the baseline to prevent a big gap.
+        underlineOffset = baseline + 2;
+    }
+    pt->drawLineForDocumentMarker(FloatPoint(boxOrigin.x() + start, boxOrigin.y() + underlineOffset), width, lineStyleForMarkerType(marker->type()));
+}
+
+void InlineTextBox::paintTextMatchMarker(GraphicsContext* pt, const FloatPoint& boxOrigin, DocumentMarker* marker, RenderStyle* style, const Font& font)
+{
+    // 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 deltaY = renderer()->style()->isFlippedLinesWritingMode() ? selectionBottom() - logicalBottom() : logicalTop() - selectionTop();
+    int selHeight = selectionHeight();
+
+    int sPos = max(marker->startOffset() - m_start, (unsigned)0);
+    int ePos = min(marker->endOffset() - m_start, (unsigned)m_len);
+    TextRun run = constructTextRun(style, font);
+
+    // Always compute and store the rect associated with this marker. The computed rect is in absolute coordinates.
+    IntRect markerRect = enclosingIntRect(font.selectionRectForText(run, IntPoint(x(), selectionTop()), selHeight, sPos, ePos));
+    markerRect = renderer()->localToAbsoluteQuad(FloatRect(markerRect)).enclosingBoundingBox();
+    toRenderedDocumentMarker(marker)->setRenderedRect(markerRect);
+    
+    // Optionally highlight the text
+    if (renderer()->frame()->editor()->markedTextMatchesAreHighlighted()) {
+        Color color = marker->activeMatch() ?
+            renderer()->theme()->platformActiveTextSearchHighlightColor() :
+            renderer()->theme()->platformInactiveTextSearchHighlightColor();
+        GraphicsContextStateSaver stateSaver(*pt);
+        updateGraphicsContext(pt, color, color, 0, style->colorSpace());  // Don't draw text at all!
+        pt->clip(FloatRect(boxOrigin.x(), boxOrigin.y() - deltaY, m_logicalWidth, selHeight));
+        pt->drawHighlightForText(font, run, FloatPoint(boxOrigin.x(), boxOrigin.y() - deltaY), selHeight, color, style->colorSpace(), sPos, ePos);
+    }
+}
+
+void InlineTextBox::computeRectForReplacementMarker(DocumentMarker* marker, RenderStyle* style, const Font& font)
+{
+    // Replacement markers are not actually drawn, but their rects need to be computed for hit testing.
+    int top = 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 = constructTextRun(style, font);
+    IntPoint startPoint = IntPoint(x(), top);
+    
+    // Compute and store the rect associated with this marker.
+    IntRect markerRect = enclosingIntRect(font.selectionRectForText(run, startPoint, h, sPos, ePos));
+    markerRect = renderer()->localToAbsoluteQuad(FloatRect(markerRect)).enclosingBoundingBox();
+    toRenderedDocumentMarker(marker)->setRenderedRect(markerRect);
+}
+    
+void InlineTextBox::paintDocumentMarkers(GraphicsContext* pt, const FloatPoint& boxOrigin, RenderStyle* style, const Font& font, bool background)
+{
+    if (!renderer()->node())
+        return;
+
+    Vector<DocumentMarker*> markers = renderer()->document()->markers()->markersFor(renderer()->node());
+    Vector<DocumentMarker*>::const_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:
+            case DocumentMarker::CorrectionIndicator:
+            case DocumentMarker::Replacement:
+            case DocumentMarker::DictationAlternatives:
+                if (background)
+                    continue;
+                break;
+            case DocumentMarker::TextMatch:
+                if (!background)
+                    continue;
+                break;
+            default:
+                continue;
+        }
+
+        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:
+            case DocumentMarker::CorrectionIndicator:
+            case DocumentMarker::DictationAlternatives:
+                paintDocumentMarker(pt, boxOrigin, marker, style, font, false);
+                break;
+            case DocumentMarker::Grammar:
+                paintDocumentMarker(pt, boxOrigin, marker, style, font, true);
+                break;
+            case DocumentMarker::TextMatch:
+                paintTextMatchMarker(pt, boxOrigin, marker, style, font);
+                break;
+            case DocumentMarker::Replacement:
+                computeRectForReplacementMarker(marker, style, font);
+                break;
+            default:
+                ASSERT_NOT_REACHED();
+        }
+
+    }
+}
+
+void InlineTextBox::paintCompositionUnderline(GraphicsContext* ctx, const FloatPoint& boxOrigin, const CompositionUnderline& underline)
+{
+    if (m_truncation == cFullTruncation)
+        return;
+    
+    float start = 0; // start of line to draw, relative to tx
+    float width = m_logicalWidth; // 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 = toRenderText(renderer())->width(m_start, paintStart - m_start, textPos(), isFirstLineStyle());
+    }
+    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 = toRenderText(renderer())->width(paintStart, paintEnd - paintStart, textPos() + start, isFirstLineStyle());
+    }
+
+    // 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;
+    int baseline = renderer()->style(isFirstLineStyle())->fontMetrics().ascent();
+    if (underline.thick && logicalHeight() - 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, renderer()->style()->colorSpace());
+    ctx->setStrokeThickness(lineThickness);
+    ctx->drawLineForText(FloatPoint(boxOrigin.x() + start, boxOrigin.y() + logicalHeight() - lineThickness), width, textRenderer()->document()->printing());
+}
+
+int InlineTextBox::caretMinOffset() const
+{
+    return m_start;
+}
+
+int InlineTextBox::caretMaxOffset() const
+{
+    return m_start + m_len;
+}
+
+float InlineTextBox::textPos() const
+{
+    // When computing the width of a text run, RenderBlock::computeInlineDirectionPositionsForLine() doesn't include the actual offset
+    // from the containing block edge in its measurement. textPos() should be consistent so the text are rendered in the same width.
+    if (logicalLeft() == 0)
+        return 0;
+    return logicalLeft() - root()->logicalLeft();
+}
+
+int InlineTextBox::offsetForPosition(float lineOffset, bool includePartialGlyphs) const
+{
+    if (isLineBreak())
+        return 0;
+
+    if (lineOffset - logicalLeft() > logicalWidth())
+        return isLeftToRightDirection() ? len() : 0;
+    if (lineOffset - logicalLeft() < 0)
+        return isLeftToRightDirection() ? 0 : len();
+
+    FontCachePurgePreventer fontCachePurgePreventer;
+
+    RenderText* text = toRenderText(renderer());
+    RenderStyle* style = text->style(isFirstLineStyle());
+    const Font& font = style->font();
+    return font.offsetForPosition(constructTextRun(style, font), lineOffset - logicalLeft(), includePartialGlyphs);
+}
+
+float InlineTextBox::positionForOffset(int offset) const
+{
+    ASSERT(offset >= m_start);
+    ASSERT(offset <= m_start + m_len);
+
+    if (isLineBreak())
+        return logicalLeft();
+
+    FontCachePurgePreventer fontCachePurgePreventer;
+
+    RenderText* text = toRenderText(renderer());
+    RenderStyle* styleToUse = text->style(isFirstLineStyle());
+    ASSERT(styleToUse);
+    const Font& font = styleToUse->font();
+    int from = !isLeftToRightDirection() ? offset - m_start : 0;
+    int to = !isLeftToRightDirection() ? m_len : offset - m_start;
+    // FIXME: Do we need to add rightBearing here?
+    return font.selectionRectForText(constructTextRun(styleToUse, font), IntPoint(logicalLeft(), 0), 0, from, to).maxX();
+}
+
+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;
+}
+
+TextRun InlineTextBox::constructTextRun(RenderStyle* style, const Font& font, BufferForAppendingHyphen* charactersWithHyphen) const
+{
+    ASSERT(style);
+
+    RenderText* textRenderer = this->textRenderer();
+    ASSERT(textRenderer);
+    ASSERT(textRenderer->text());
+
+    String string = textRenderer->text();
+    unsigned startPos = start();
+    unsigned length = len();
+
+    if (string.length() != length || startPos)
+        string = string.substringSharingImpl(startPos, length);
+
+    return constructTextRun(style, font, string, textRenderer->textLength() - startPos, charactersWithHyphen);
+}
+
+TextRun InlineTextBox::constructTextRun(RenderStyle* style, const Font& font, String string, int maximumLength, BufferForAppendingHyphen* charactersWithHyphen) const
+{
+    ASSERT(style);
+
+    RenderText* textRenderer = this->textRenderer();
+    ASSERT(textRenderer);
+
+    int length = string.length();
+
+    if (charactersWithHyphen) {
+        adjustCharactersAndLengthForHyphen(*charactersWithHyphen, style, string, length);
+        maximumLength = length;
+    }
+
+    ASSERT(maximumLength >= length);
+
+    TextRun run(string, textPos(), expansion(), expansionBehavior(), direction(), dirOverride() || style->rtlOrdering() == VisualOrder, !textRenderer->canUseSimpleFontCodePath());
+    run.setTabSize(!style->collapseWhiteSpace(), style->tabSize());
+    if (textRunNeedsRenderingContext(font))
+        run.setRenderingContext(SVGTextRunRenderingContext::create(textRenderer));
+
+    // Propagate the maximum length of the characters buffer to the TextRun, even when we're only processing a substring.
+    run.setCharactersLength(maximumLength);
+    ASSERT(run.charactersLength() >= run.length());
+    return run;
+}
+
+#ifndef NDEBUG
+
+const char* InlineTextBox::boxName() const
+{
+    return "InlineTextBox";
+}
+
+void InlineTextBox::showBox(int printedCharacters) const
+{
+    const RenderText* obj = toRenderText(renderer());
+    String value = obj->text();
+    value = value.substring(start(), len());
+    value.replaceWithLiteral('\\', "\\\\");
+    value.replaceWithLiteral('\n', "\\n");
+    printedCharacters += fprintf(stderr, "%s\t%p", boxName(), this);
+    for (; printedCharacters < showTreeCharacterOffset; printedCharacters++)
+        fputc(' ', stderr);
+    printedCharacters = fprintf(stderr, "\t%s %p", obj->renderName(), obj);
+    const int rendererCharacterOffset = 24;
+    for (; printedCharacters < rendererCharacterOffset; printedCharacters++)
+        fputc(' ', stderr);
+    fprintf(stderr, "(%d,%d) \"%s\"\n", start(), start() + len(), value.utf8().data());
+}
+
+#endif
+
+void InlineTextBox::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::Rendering);
+    InlineBox::reportMemoryUsage(memoryObjectInfo);
+    info.addMember(m_prevTextBox, "prevTextBox");
+    info.addMember(m_nextTextBox, "nextTextBox");
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/InlineTextBox.h b/Source/core/rendering/InlineTextBox.h
new file mode 100644
index 0000000..8209610
--- /dev/null
+++ b/Source/core/rendering/InlineTextBox.h
@@ -0,0 +1,223 @@
+/*
+ * (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2009, 2010, 2011 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 InlineTextBox_h
+#define InlineTextBox_h
+
+#include "core/platform/graphics/TextRun.h"
+#include "core/rendering/InlineBox.h"
+#include "core/rendering/RenderText.h" // so textRenderer() can be inline
+#include <wtf/text/StringBuilder.h>
+
+namespace WebCore {
+
+struct CompositionUnderline;
+class DocumentMarker;
+
+const unsigned short cNoTruncation = USHRT_MAX;
+const unsigned short cFullTruncation = USHRT_MAX - 1;
+
+class BufferForAppendingHyphen : public StringBuilder {
+public:
+    BufferForAppendingHyphen() { reserveCapacity(256); }
+};
+
+// Helper functions shared by InlineTextBox / SVGRootInlineBox
+void updateGraphicsContext(GraphicsContext*, const Color& fillColor, const Color& strokeColor, float strokeThickness, ColorSpace);
+Color correctedTextColor(Color textColor, Color backgroundColor);
+
+class InlineTextBox : public InlineBox {
+public:
+    InlineTextBox(RenderObject* obj)
+        : InlineBox(obj)
+        , m_prevTextBox(0)
+        , m_nextTextBox(0)
+        , m_start(0)
+        , m_len(0)
+        , m_truncation(cNoTruncation)
+    {
+    }
+
+    virtual void destroy(RenderArena*) OVERRIDE FINAL;
+
+    InlineTextBox* prevTextBox() const { return m_prevTextBox; }
+    InlineTextBox* nextTextBox() const { return m_nextTextBox; }
+    void setNextTextBox(InlineTextBox* n) { m_nextTextBox = n; }
+    void setPreviousTextBox(InlineTextBox* p) { m_prevTextBox = p; }
+
+    // FIXME: These accessors should ASSERT(!isDirty()). See https://bugs.webkit.org/show_bug.cgi?id=97264
+    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) { ASSERT(!isDirty()); m_start += d; }
+
+    unsigned short truncation() { return m_truncation; }
+
+    virtual void markDirty(bool dirty = true) OVERRIDE FINAL;
+
+    using InlineBox::hasHyphen;
+    using InlineBox::setHasHyphen;
+    using InlineBox::canHaveLeadingExpansion;
+    using InlineBox::setCanHaveLeadingExpansion;
+
+    static inline bool compareByStart(const InlineTextBox* first, const InlineTextBox* second) { return first->start() < second->start(); }
+
+    virtual int baselinePosition(FontBaseline) const OVERRIDE FINAL;
+    virtual LayoutUnit lineHeight() const OVERRIDE FINAL;
+
+    bool getEmphasisMarkPosition(RenderStyle*, TextEmphasisPosition&) const;
+
+    LayoutRect logicalOverflowRect() const;
+    void setLogicalOverflowRect(const LayoutRect&);
+    LayoutUnit logicalTopVisualOverflow() const { return logicalOverflowRect().y(); }
+    LayoutUnit logicalBottomVisualOverflow() const { return logicalOverflowRect().maxY(); }
+    LayoutUnit logicalLeftVisualOverflow() const { return logicalOverflowRect().x(); }
+    LayoutUnit logicalRightVisualOverflow() const { return logicalOverflowRect().maxX(); }
+
+#ifndef NDEBUG
+    virtual void showBox(int = 0) const;
+    virtual const char* boxName() const;
+#endif
+
+    virtual void reportMemoryUsage(MemoryObjectInfo*) const OVERRIDE FINAL;
+
+private:
+    LayoutUnit selectionTop();
+    LayoutUnit selectionBottom();
+    LayoutUnit selectionHeight();
+
+    TextRun constructTextRun(RenderStyle*, const Font&, BufferForAppendingHyphen* = 0) const;
+    TextRun constructTextRun(RenderStyle*, const Font&, String, int maximumLength, BufferForAppendingHyphen* = 0) const;
+
+public:
+    virtual FloatRect calculateBoundaries() const { return FloatRect(x(), y(), width(), height()); }
+
+    virtual LayoutRect localSelectionRect(int startPos, int endPos);
+    bool isSelected(int startPos, int endPos) const;
+    void selectionStartEnd(int& sPos, int& ePos);
+
+protected:
+    virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom);
+    virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom) OVERRIDE;
+
+public:
+    RenderText* textRenderer() const;
+
+private:
+    virtual void deleteLine(RenderArena*) OVERRIDE FINAL;
+    virtual void extractLine() OVERRIDE FINAL;
+    virtual void attachLine() OVERRIDE FINAL;
+
+public:
+    virtual RenderObject::SelectionState selectionState() OVERRIDE FINAL;
+
+private:
+    virtual void clearTruncation() OVERRIDE FINAL { m_truncation = cNoTruncation; }
+    virtual float placeEllipsisBox(bool flowIsLTR, float visibleLeftEdge, float visibleRightEdge, float ellipsisWidth, float &truncatedWidth, bool& foundBox) OVERRIDE FINAL;
+
+public:
+    virtual bool isLineBreak() const OVERRIDE FINAL;
+
+    void setExpansion(int newExpansion)
+    {
+        m_logicalWidth -= expansion();
+        InlineBox::setExpansion(newExpansion);
+        m_logicalWidth += newExpansion;
+    }
+
+private:
+    virtual bool isInlineTextBox() const OVERRIDE FINAL { return true; }
+
+public:
+    virtual int caretMinOffset() const OVERRIDE FINAL;
+    virtual int caretMaxOffset() const OVERRIDE FINAL;
+
+private:
+    float textPos() const; // returns the x position relative to the left start of the text line.
+
+public:
+    virtual int offsetForPosition(float x, bool includePartialGlyphs = true) const;
+    virtual float positionForOffset(int offset) const;
+
+    bool containsCaretOffset(int offset) const; // false for offset after line break
+
+    // Needs to be public, so the static paintTextWithShadows() function can use it.
+    static FloatSize applyShadowToGraphicsContext(GraphicsContext*, const ShadowData*, const FloatRect& textRect, bool stroked, bool opaque, bool horizontal);
+
+private:
+    InlineTextBox* m_prevTextBox; // The previous box that also uses our RenderObject
+    InlineTextBox* m_nextTextBox; // The next box that also uses our RenderObject
+
+    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*, const FloatPoint& boxOrigin, RenderStyle*, const Font&, int startPos, int endPos);
+    void paintDocumentMarkers(GraphicsContext*, const FloatPoint& boxOrigin, RenderStyle*, const Font&, bool background);
+    void paintCompositionUnderline(GraphicsContext*, const FloatPoint& boxOrigin, const CompositionUnderline&);
+
+private:
+    void paintDecoration(GraphicsContext*, const FloatPoint& boxOrigin, ETextDecoration, TextDecorationStyle, const ShadowData*);
+    void paintSelection(GraphicsContext*, const FloatPoint& boxOrigin, RenderStyle*, const Font&, Color textColor);
+    void paintDocumentMarker(GraphicsContext*, const FloatPoint& boxOrigin, DocumentMarker*, RenderStyle*, const Font&, bool grammar);
+    void paintTextMatchMarker(GraphicsContext*, const FloatPoint& boxOrigin, DocumentMarker*, RenderStyle*, const Font&);
+    void computeRectForReplacementMarker(DocumentMarker*, RenderStyle*, const Font&);
+
+    TextRun::ExpansionBehavior expansionBehavior() const
+    {
+        return (canHaveLeadingExpansion() ? TextRun::AllowLeadingExpansion : TextRun::ForbidLeadingExpansion)
+            | (expansion() && nextLeafChild() ? TextRun::AllowTrailingExpansion : TextRun::ForbidTrailingExpansion);
+    }
+};
+
+inline InlineTextBox* toInlineTextBox(InlineBox* inlineBox)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!inlineBox || inlineBox->isInlineTextBox());
+    return static_cast<InlineTextBox*>(inlineBox);
+}
+
+inline const InlineTextBox* toInlineTextBox(const InlineBox* inlineBox)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!inlineBox || inlineBox->isInlineTextBox());
+    return static_cast<const InlineTextBox*>(inlineBox);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toInlineTextBox(const InlineTextBox*);
+
+inline RenderText* InlineTextBox::textRenderer() const
+{
+    return toRenderText(renderer());
+}
+
+void alignSelectionRectToDevicePixels(FloatRect&);
+
+} // namespace WebCore
+
+#endif // InlineTextBox_h
diff --git a/Source/core/rendering/LayoutRepainter.cpp b/Source/core/rendering/LayoutRepainter.cpp
new file mode 100644
index 0000000..112db53
--- /dev/null
+++ b/Source/core/rendering/LayoutRepainter.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ *           (C) 2000 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2000 Dirk Mueller (mueller@kde.org)
+ *           (C) 2004 Allan Sandfeld Jensen (kde@carewolf.com)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Google 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 "core/rendering/LayoutRepainter.h"
+
+#include "core/rendering/RenderObject.h"
+
+namespace WebCore {
+
+LayoutRepainter::LayoutRepainter(RenderObject& object, bool checkForRepaint)
+    : m_object(object)
+    , m_repaintContainer(0)
+    , m_checkForRepaint(checkForRepaint)
+{
+    if (m_checkForRepaint) {
+        m_repaintContainer = m_object.containerForRepaint();
+        m_oldBounds = m_object.clippedOverflowRectForRepaint(m_repaintContainer);
+        m_oldOutlineBox = m_object.outlineBoundsForRepaint(m_repaintContainer);
+    }
+}
+
+bool LayoutRepainter::repaintAfterLayout()
+{
+    return m_checkForRepaint ? m_object.repaintAfterLayoutIfNeeded(m_repaintContainer, m_oldBounds, m_oldOutlineBox) : false;
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/LayoutRepainter.h b/Source/core/rendering/LayoutRepainter.h
new file mode 100644
index 0000000..fe6129c
--- /dev/null
+++ b/Source/core/rendering/LayoutRepainter.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ *           (C) 2000 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2000 Dirk Mueller (mueller@kde.org)
+ *           (C) 2004 Allan Sandfeld Jensen (kde@carewolf.com)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Google 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 LayoutRepainter_h
+#define LayoutRepainter_h
+
+#include "core/platform/graphics/LayoutRect.h"
+
+namespace WebCore {
+
+class RenderLayerModelObject;
+class RenderObject;
+
+class LayoutRepainter {
+public:
+    LayoutRepainter(RenderObject&, bool checkForRepaint);
+
+    bool checkForRepaint() const { return m_checkForRepaint; }
+
+    // Return true if it repainted.
+    bool repaintAfterLayout();
+
+private:
+    RenderObject& m_object;
+    RenderLayerModelObject* m_repaintContainer;
+    // We store these values as LayoutRects, but the final invalidations will be pixel snapped
+    LayoutRect m_oldBounds;
+    LayoutRect m_oldOutlineBox;
+    bool m_checkForRepaint;
+};
+
+} // namespace WebCore
+
+#endif // LayoutRepainter_h
diff --git a/Source/core/rendering/LayoutState.cpp b/Source/core/rendering/LayoutState.cpp
new file mode 100644
index 0000000..346dd82
--- /dev/null
+++ b/Source/core/rendering/LayoutState.cpp
@@ -0,0 +1,293 @@
+/*
+ * 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 "core/rendering/LayoutState.h"
+
+#include "core/rendering/ColumnInfo.h"
+#include "core/rendering/RenderArena.h"
+#include "core/rendering/RenderFlowThread.h"
+#include "core/rendering/RenderInline.h"
+#include "core/rendering/RenderLayer.h"
+#include "core/rendering/RenderView.h"
+
+namespace WebCore {
+
+LayoutState::LayoutState(LayoutState* prev, RenderBox* renderer, const LayoutSize& offset, LayoutUnit pageLogicalHeight, bool pageLogicalHeightChanged, ColumnInfo* columnInfo)
+    : m_columnInfo(columnInfo)
+    , m_lineGrid(0)
+    , m_next(prev)
+    , m_exclusionShapeInsideInfo(0)
+#ifndef NDEBUG
+    , m_renderer(renderer)
+#endif
+{
+    ASSERT(m_next);
+
+    bool fixed = renderer->isOutOfFlowPositioned() && renderer->style()->position() == FixedPosition;
+    if (fixed) {
+        // FIXME: This doesn't work correctly with transforms.
+        FloatPoint fixedOffset = renderer->view()->localToAbsolute(FloatPoint(), IsFixed);
+        m_paintOffset = LayoutSize(fixedOffset.x(), fixedOffset.y()) + offset;
+    } else
+        m_paintOffset = prev->m_paintOffset + offset;
+
+    if (renderer->isOutOfFlowPositioned() && !fixed) {
+        if (RenderObject* container = renderer->container()) {
+            if (container->isInFlowPositioned() && container->isRenderInline())
+                m_paintOffset += toRenderInline(container)->offsetForInFlowPositionedInline(renderer);
+        }
+    }
+
+    m_layoutOffset = m_paintOffset;
+
+    if (renderer->hasPaintOffset() && renderer->hasLayer())
+        m_paintOffset += renderer->layer()->paintOffset();
+
+    m_clipped = !fixed && prev->m_clipped;
+    if (m_clipped)
+        m_clipRect = prev->m_clipRect;
+
+    if (renderer->hasOverflowClip()) {
+        LayoutRect clipRect(toPoint(m_paintOffset) + renderer->view()->layoutDelta(), renderer->cachedSizeForOverflowClip());
+        if (m_clipped)
+            m_clipRect.intersect(clipRect);
+        else {
+            m_clipRect = clipRect;
+            m_clipped = true;
+        }
+
+        m_paintOffset -= renderer->scrolledContentOffset();
+    }
+
+    // If we establish a new page height, then cache the offset to the top of the first page.
+    // We can compare this later on to figure out what part of the page we're actually on,
+    if (pageLogicalHeight || m_columnInfo || renderer->isRenderFlowThread()) {
+        m_pageLogicalHeight = pageLogicalHeight;
+        bool isFlipped = renderer->style()->isFlippedBlocksWritingMode();
+        m_pageOffset = LayoutSize(m_layoutOffset.width() + (!isFlipped ? renderer->borderLeft() + renderer->paddingLeft() : renderer->borderRight() + renderer->paddingRight()),
+                               m_layoutOffset.height() + (!isFlipped ? renderer->borderTop() + renderer->paddingTop() : renderer->borderBottom() + renderer->paddingBottom()));
+        m_pageLogicalHeightChanged = pageLogicalHeightChanged;
+    } else {
+        // If we don't establish a new page height, then propagate the old page height and offset down.
+        m_pageLogicalHeight = m_next->m_pageLogicalHeight;
+        m_pageLogicalHeightChanged = m_next->m_pageLogicalHeightChanged;
+        m_pageOffset = m_next->m_pageOffset;
+        
+        // Disable pagination for objects we don't support. For now this includes overflow:scroll/auto, inline blocks and
+        // writing mode roots.
+        if (renderer->isUnsplittableForPagination())
+            m_pageLogicalHeight = 0;
+    }
+    
+    // Propagate line grid information.
+    propagateLineGridInfo(renderer);
+
+    if (!m_columnInfo)
+        m_columnInfo = m_next->m_columnInfo;
+
+    if (renderer->isRenderBlock()) {
+        const RenderBlock* renderBlock = toRenderBlock(renderer);
+        m_exclusionShapeInsideInfo = renderBlock->exclusionShapeInsideInfo();
+        if (!m_exclusionShapeInsideInfo && m_next->m_exclusionShapeInsideInfo && renderBlock->allowsExclusionShapeInsideInfoSharing())
+            m_exclusionShapeInsideInfo = m_next->m_exclusionShapeInsideInfo;
+    }
+
+    m_layoutDelta = m_next->m_layoutDelta;
+#if !ASSERT_DISABLED
+    m_layoutDeltaXSaturated = m_next->m_layoutDeltaXSaturated;
+    m_layoutDeltaYSaturated = m_next->m_layoutDeltaYSaturated;
+#endif
+    
+    m_isPaginated = m_pageLogicalHeight || m_columnInfo || renderer->isRenderFlowThread();
+
+    if (lineGrid() && renderer->hasColumns() && renderer->style()->hasInlineColumnAxis())
+        computeLineGridPaginationOrigin(renderer);
+
+    // If we have a new grid to track, then add it to our set.
+    if (renderer->style()->lineGrid() != RenderStyle::initialLineGrid() && renderer->isBlockFlow())
+        establishLineGrid(toRenderBlock(renderer));
+
+    // FIXME: <http://bugs.webkit.org/show_bug.cgi?id=13443> Apply control clip if present.
+}
+
+LayoutState::LayoutState(RenderObject* root)
+    : m_clipped(false)
+    , m_isPaginated(false)
+    , m_pageLogicalHeightChanged(false)
+#if !ASSERT_DISABLED
+    , m_layoutDeltaXSaturated(false)
+    , m_layoutDeltaYSaturated(false)
+#endif    
+    , m_columnInfo(0)
+    , m_lineGrid(0)
+    , m_next(0)
+    , m_exclusionShapeInsideInfo(0)
+    , m_pageLogicalHeight(0)
+#ifndef NDEBUG
+    , m_renderer(root)
+#endif
+{
+    RenderObject* container = root->container();
+    FloatPoint absContentPoint = container->localToAbsolute(FloatPoint(), UseTransforms);
+    m_paintOffset = LayoutSize(absContentPoint.x(), absContentPoint.y());
+
+    if (container->hasOverflowClip()) {
+        m_clipped = true;
+        RenderBox* containerBox = toRenderBox(container);
+        m_clipRect = LayoutRect(toPoint(m_paintOffset), containerBox->cachedSizeForOverflowClip());
+        m_paintOffset -= containerBox->scrolledContentOffset();
+    }
+}
+
+#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)
+{
+    return renderArena->allocate(sz);
+}
+
+void LayoutState::operator delete(void* ptr, size_t sz)
+{
+    ASSERT(inLayoutStateDestroy);
+    *(size_t*)ptr = sz;
+}
+
+void LayoutState::clearPaginationInformation()
+{
+    m_pageLogicalHeight = m_next->m_pageLogicalHeight;
+    m_pageOffset = m_next->m_pageOffset;
+    m_columnInfo = m_next->m_columnInfo;
+}
+
+LayoutUnit LayoutState::pageLogicalOffset(RenderBox* child, LayoutUnit childLogicalOffset) const
+{
+    if (child->isHorizontalWritingMode())
+        return m_layoutOffset.height() + childLogicalOffset - m_pageOffset.height();
+    return m_layoutOffset.width() + childLogicalOffset - m_pageOffset.width();
+}
+
+void LayoutState::addForcedColumnBreak(RenderBox* child, LayoutUnit childLogicalOffset)
+{
+    if (!m_columnInfo || m_columnInfo->columnHeight())
+        return;
+    m_columnInfo->addForcedBreak(pageLogicalOffset(child, childLogicalOffset));
+}
+
+void LayoutState::propagateLineGridInfo(RenderBox* renderer)
+{
+    // Disable line grids for objects we don't support. For now this includes overflow:scroll/auto, inline blocks and
+    // writing mode roots.
+    if (!m_next || renderer->isUnsplittableForPagination())
+        return;
+
+    m_lineGrid = m_next->m_lineGrid;
+    m_lineGridOffset = m_next->m_lineGridOffset;
+    m_lineGridPaginationOrigin = m_next->m_lineGridPaginationOrigin;
+}
+
+void LayoutState::establishLineGrid(RenderBlock* block)
+{
+    // First check to see if this grid has been established already.
+    if (m_lineGrid) {
+        if (m_lineGrid->style()->lineGrid() == block->style()->lineGrid())
+            return;
+        RenderBlock* currentGrid = m_lineGrid;
+        for (LayoutState* currentState = m_next; currentState; currentState = currentState->m_next) {
+            if (currentState->m_lineGrid == currentGrid)
+                continue;
+            currentGrid = currentState->m_lineGrid;
+            if (!currentGrid)
+                break;
+            if (currentGrid->style()->lineGrid() == block->style()->lineGrid()) {
+                m_lineGrid = currentGrid;
+                m_lineGridOffset = currentState->m_lineGridOffset;
+                return;
+            }
+        }
+    }
+    
+    // We didn't find an already-established grid with this identifier. Our render object establishes the grid.
+    m_lineGrid = block;
+    m_lineGridOffset = m_layoutOffset; 
+}
+
+void LayoutState::computeLineGridPaginationOrigin(RenderBox* renderer)
+{
+    // We need to cache a line grid pagination origin so that we understand how to reset the line grid
+    // at the top of each column.
+    // Get the current line grid and offset.
+    if (!lineGrid() || lineGrid()->style()->writingMode() != renderer->style()->writingMode())
+        return;
+
+    // Get the hypothetical line box used to establish the grid.
+    RootInlineBox* lineGridBox = lineGrid()->lineGridBox();
+    if (!lineGridBox)
+        return;
+    
+    bool isHorizontalWritingMode = lineGrid()->isHorizontalWritingMode();
+
+    LayoutUnit lineGridBlockOffset = isHorizontalWritingMode ? lineGridOffset().height() : lineGridOffset().width();
+
+    // Now determine our position on the grid. Our baseline needs to be adjusted to the nearest baseline multiple
+    // as established by the line box.
+    // FIXME: Need to handle crazy line-box-contain values that cause the root line box to not be considered. I assume
+    // the grid should honor line-box-contain.
+    LayoutUnit gridLineHeight = lineGridBox->lineBottomWithLeading() - lineGridBox->lineTopWithLeading();
+    if (!gridLineHeight)
+        return;
+
+    LayoutUnit firstLineTopWithLeading = lineGridBlockOffset + lineGridBox->lineTopWithLeading();
+    
+    if (isPaginated() && pageLogicalHeight()) {
+        LayoutUnit pageLogicalTop = renderer->isHorizontalWritingMode() ? m_pageOffset.height() : m_pageOffset.width();
+        if (pageLogicalTop > firstLineTopWithLeading) {
+            // Shift to the next highest line grid multiple past the page logical top. Cache the delta
+            // between this new value and the page logical top as the pagination origin.
+            LayoutUnit remainder = roundToInt(pageLogicalTop - firstLineTopWithLeading) % roundToInt(gridLineHeight);
+            LayoutUnit paginationDelta = gridLineHeight - remainder;
+            if (isHorizontalWritingMode)
+                m_lineGridPaginationOrigin.setHeight(paginationDelta);
+            else
+                m_lineGridPaginationOrigin.setWidth(paginationDelta);
+        }
+    }
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/LayoutState.h b/Source/core/rendering/LayoutState.h
new file mode 100644
index 0000000..3f2fe56
--- /dev/null
+++ b/Source/core/rendering/LayoutState.h
@@ -0,0 +1,151 @@
+/*
+ * 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 "core/platform/graphics/LayoutRect.h"
+#include "core/rendering/ColumnInfo.h"
+#include <wtf/HashMap.h>
+#include <wtf/Noncopyable.h>
+
+namespace WebCore {
+
+class RenderArena;
+class RenderBlock;
+class RenderBox;
+class RenderObject;
+class RenderFlowThread;
+class ExclusionShapeInsideInfo;
+
+class LayoutState {
+    WTF_MAKE_NONCOPYABLE(LayoutState);
+public:
+    LayoutState()
+        : m_clipped(false)
+        , m_isPaginated(false)
+        , m_pageLogicalHeightChanged(false)
+#if !ASSERT_DISABLED
+        , m_layoutDeltaXSaturated(false)
+        , m_layoutDeltaYSaturated(false)
+#endif
+        , m_columnInfo(0)
+        , m_lineGrid(0)
+        , m_next(0)
+        , m_exclusionShapeInsideInfo(0)
+        , m_pageLogicalHeight(0)
+#ifndef NDEBUG
+        , m_renderer(0)
+#endif
+    {
+    }
+
+    LayoutState(LayoutState*, RenderBox*, const LayoutSize& offset, LayoutUnit pageHeight, bool pageHeightChanged, ColumnInfo*);
+    LayoutState(RenderObject*);
+
+    void destroy(RenderArena*);
+
+    // Overloaded new operator.
+    void* operator new(size_t, RenderArena*);
+
+    // Overridden to prevent the normal delete from being called.
+    void operator delete(void*, size_t);
+
+    void clearPaginationInformation();
+    bool isPaginatingColumns() const { return m_columnInfo && m_columnInfo->paginationUnit() == ColumnInfo::Column; }
+    bool isPaginated() const { return m_isPaginated; }
+    
+    // The page logical offset is the object's offset from the top of the page in the page progression
+    // direction (so an x-offset in vertical text and a y-offset for horizontal text).
+    LayoutUnit pageLogicalOffset(RenderBox*, LayoutUnit childLogicalOffset) const;
+
+    void addForcedColumnBreak(RenderBox*, LayoutUnit childLogicalOffset);
+    
+    LayoutUnit pageLogicalHeight() const { return m_pageLogicalHeight; }
+    bool pageLogicalHeightChanged() const { return m_pageLogicalHeightChanged; }
+
+    RenderBlock* lineGrid() const { return m_lineGrid; }
+    LayoutSize lineGridOffset() const { return m_lineGridOffset; }
+    LayoutSize lineGridPaginationOrigin() const { return m_lineGridPaginationOrigin; }
+
+    LayoutSize layoutOffset() const { return m_layoutOffset; }
+
+    bool needsBlockDirectionLocationSetBeforeLayout() const { return m_lineGrid || (m_isPaginated && m_pageLogicalHeight); }
+
+    ExclusionShapeInsideInfo* exclusionShapeInsideInfo() const { return m_exclusionShapeInsideInfo; }
+private:
+    // The normal operator new is disallowed.
+    void* operator new(size_t) throw();
+
+    void propagateLineGridInfo(RenderBox*);
+    void establishLineGrid(RenderBlock*);
+
+    void computeLineGridPaginationOrigin(RenderBox*);
+
+public:
+    // Do not add anything apart from bitfields until after m_columnInfo. See https://bugs.webkit.org/show_bug.cgi?id=100173
+    bool m_clipped:1;
+    bool m_isPaginated:1;
+    // If our page height has changed, this will force all blocks to relayout.
+    bool m_pageLogicalHeightChanged:1;
+#if !ASSERT_DISABLED
+    bool m_layoutDeltaXSaturated:1;
+    bool m_layoutDeltaYSaturated:1;
+#endif
+    // If the enclosing pagination model is a column model, then this will store column information for easy retrieval/manipulation.
+    ColumnInfo* m_columnInfo;
+    // The current line grid that we're snapping to and the offset of the start of the grid.
+    RenderBlock* m_lineGrid;
+    LayoutState* m_next;
+    ExclusionShapeInsideInfo* m_exclusionShapeInsideInfo;
+
+    // FIXME: Distinguish between the layout clip rect and the paint clip rect which may be larger,
+    // e.g., because of composited scrolling.
+    LayoutRect m_clipRect;
+    
+    // x/y offset from container. Includes relative positioning and scroll offsets.
+    LayoutSize m_paintOffset;
+    // x/y offset from container. Does not include relative positioning or scroll offsets.
+    LayoutSize m_layoutOffset;
+    // Transient offset from the final position of the object
+    // used to ensure that repaints happen in the correct place.
+    // This is a total delta accumulated from the root. 
+    LayoutSize m_layoutDelta;
+
+    // The current page height for the pagination model that encloses us.
+    LayoutUnit m_pageLogicalHeight;
+    // The offset of the start of the first page in the nearest enclosing pagination model.
+    LayoutSize m_pageOffset;
+    LayoutSize m_lineGridOffset;
+    LayoutSize m_lineGridPaginationOrigin;
+
+#ifndef NDEBUG
+    RenderObject* m_renderer;
+#endif
+};
+
+} // namespace WebCore
+
+#endif // LayoutState_h
diff --git a/Source/core/rendering/OverlapTestRequestClient.h b/Source/core/rendering/OverlapTestRequestClient.h
new file mode 100644
index 0000000..71400ab
--- /dev/null
+++ b/Source/core/rendering/OverlapTestRequestClient.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2009 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 OverlapTestRequestClient_h
+#define OverlapTestRequestClient_h
+
+namespace WebCore {
+    
+class OverlapTestRequestClient {
+public:
+    virtual ~OverlapTestRequestClient() { }
+    virtual void setOverlapTestResult(bool) = 0;
+};
+
+} // namespace WebCore
+
+#endif // OverlapTestRequestClient_h
diff --git a/Source/core/rendering/Pagination.h b/Source/core/rendering/Pagination.h
new file mode 100644
index 0000000..1afad69
--- /dev/null
+++ b/Source/core/rendering/Pagination.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2012 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. 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 INC. 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 Pagination_h
+#define Pagination_h
+
+namespace WebCore {
+
+struct Pagination {
+    enum Mode { Unpaginated, LeftToRightPaginated, RightToLeftPaginated, TopToBottomPaginated, BottomToTopPaginated };
+
+    Pagination()
+        : mode(Unpaginated)
+        , behavesLikeColumns(false)
+        , pageLength(0)
+        , gap(0)
+    {
+    };
+
+    bool operator==(const Pagination& other) const
+    {
+        return mode == other.mode && behavesLikeColumns == other.behavesLikeColumns && pageLength == other.pageLength && gap == other.gap;
+    }
+
+    bool operator!=(const Pagination& other) const
+    {
+        return mode != other.mode || behavesLikeColumns != other.behavesLikeColumns || pageLength != other.pageLength || gap != other.gap;
+    }
+
+    Mode mode;
+    bool behavesLikeColumns;
+    unsigned pageLength;
+    unsigned gap;
+};
+
+} // namespace WebCore
+
+#endif
diff --git a/Source/core/rendering/PaintInfo.h b/Source/core/rendering/PaintInfo.h
new file mode 100644
index 0000000..9a0cb9f
--- /dev/null
+++ b/Source/core/rendering/PaintInfo.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ *           (C) 2000 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2000 Dirk Mueller (mueller@kde.org)
+ *           (C) 2004 Allan Sandfeld Jensen (kde@carewolf.com)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Google 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 PaintInfo_h
+#define PaintInfo_h
+
+#if ENABLE(SVG)
+#include "core/platform/graphics/transforms/AffineTransform.h"
+#endif
+
+#include <limits>
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/platform/graphics/IntRect.h"
+#include "core/platform/graphics/LayoutRect.h"
+#include "core/rendering/PaintPhase.h"
+#include <wtf/HashMap.h>
+#include <wtf/ListHashSet.h>
+
+namespace WebCore {
+
+class OverlapTestRequestClient;
+class RenderInline;
+class RenderLayerModelObject;
+class RenderObject;
+class RenderRegion;
+
+typedef HashMap<OverlapTestRequestClient*, IntRect> OverlapTestRequestMap;
+
+/*
+ * 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, PaintBehavior newPaintBehavior,
+        RenderObject* newPaintingRoot = 0, RenderRegion* region = 0, ListHashSet<RenderInline*>* newOutlineObjects = 0,
+        OverlapTestRequestMap* overlapTestRequests = 0, const RenderLayerModelObject* newPaintContainer = 0)
+        : context(newContext)
+        , rect(newRect)
+        , phase(newPhase)
+        , paintBehavior(newPaintBehavior)
+        , paintingRoot(newPaintingRoot)
+        , renderRegion(region)
+        , outlineObjects(newOutlineObjects)
+        , overlapTestRequests(overlapTestRequests)
+        , paintContainer(newPaintContainer)
+    {
+    }
+
+    void updatePaintingRootForChildren(const RenderObject* renderer)
+    {
+        if (!paintingRoot)
+            return;
+
+        // If we're the painting root, kids draw normally, and see root of 0.
+        if (paintingRoot == renderer) {
+            paintingRoot = 0; 
+            return;
+        }
+    }
+
+    bool shouldPaintWithinRoot(const RenderObject* renderer) const
+    {
+        return !paintingRoot || paintingRoot == renderer;
+    }
+
+    bool forceBlackText() const { return paintBehavior & PaintBehaviorForceBlackText; }
+
+    bool skipRootBackground() const { return paintBehavior & PaintBehaviorSkipRootBackground; }
+    bool paintRootBackgroundOnly() const { return paintBehavior & PaintBehaviorRootBackgroundOnly; }
+
+#if ENABLE(SVG)
+    void applyTransform(const AffineTransform& localToAncestorTransform)
+    {
+        if (localToAncestorTransform.isIdentity())
+            return;
+
+        context->concatCTM(localToAncestorTransform);
+
+        if (rect == infiniteRect())
+            return;
+
+        rect = localToAncestorTransform.inverse().mapRect(rect);
+    }
+#endif
+
+    static IntRect infiniteRect() { return IntRect(LayoutRect::infiniteRect()); }
+
+    // FIXME: Introduce setters/getters at some point. Requires a lot of changes throughout rendering/.
+    GraphicsContext* context;
+    IntRect rect;
+    PaintPhase phase;
+    PaintBehavior paintBehavior;
+    RenderObject* paintingRoot; // used to draw just one element and its visual kids
+    RenderRegion* renderRegion;
+    ListHashSet<RenderInline*>* outlineObjects; // used to list outlines that should be painted by a block with inline children
+    OverlapTestRequestMap* overlapTestRequests;
+    const RenderLayerModelObject* paintContainer; // the layer object that originates the current painting
+};
+
+} // namespace WebCore
+
+#endif // PaintInfo_h
diff --git a/Source/core/rendering/PaintPhase.h b/Source/core/rendering/PaintPhase.h
new file mode 100644
index 0000000..af0bd59
--- /dev/null
+++ b/Source/core/rendering/PaintPhase.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ *           (C) 2000 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2000 Dirk Mueller (mueller@kde.org)
+ *           (C) 2004 Allan Sandfeld Jensen (kde@carewolf.com)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Google 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 PaintPhase_h
+#define PaintPhase_h
+
+namespace WebCore {
+
+/*
+ *  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 PaintBehaviorFlags {
+    PaintBehaviorNormal = 0,
+    PaintBehaviorSelectionOnly = 1 << 0,
+    PaintBehaviorForceBlackText = 1 << 1,
+    PaintBehaviorFlattenCompositingLayers = 1 << 2,
+    PaintBehaviorRenderingSVGMask = 1 << 3,
+    PaintBehaviorSkipRootBackground = 1 << 4,
+    PaintBehaviorRootBackgroundOnly = 1 << 5
+};
+
+typedef unsigned PaintBehavior;
+
+} // namespace WebCore
+
+#endif // PaintPhase_h
diff --git a/Source/core/rendering/PointerEventsHitRules.cpp b/Source/core/rendering/PointerEventsHitRules.cpp
new file mode 100644
index 0000000..8ae6aa7
--- /dev/null
+++ b/Source/core/rendering/PointerEventsHitRules.cpp
@@ -0,0 +1,111 @@
+/*
+    Copyright (C) 2007 Rob Buis <buis@kde.org>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, 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"
+#include "core/rendering/PointerEventsHitRules.h"
+
+namespace WebCore {
+
+PointerEventsHitRules::PointerEventsHitRules(EHitTesting hitTesting, const HitTestRequest& request, EPointerEvents pointerEvents)
+    : requireVisible(false)
+    , requireFill(false)
+    , requireStroke(false)
+    , canHitStroke(false)
+    , canHitFill(false)
+{
+    if (request.svgClipContent())
+        pointerEvents = PE_FILL;
+
+    if (hitTesting == SVG_PATH_HITTESTING) {
+        switch (pointerEvents)
+        {
+            case PE_VISIBLE_PAINTED:
+            case PE_AUTO: // "auto" is like "visiblePainted" when in SVG content
+                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:
+            case PE_AUTO: // "auto" is like "visiblePainted" when in SVG content
+                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
diff --git a/Source/core/rendering/PointerEventsHitRules.h b/Source/core/rendering/PointerEventsHitRules.h
new file mode 100644
index 0000000..73c0225
--- /dev/null
+++ b/Source/core/rendering/PointerEventsHitRules.h
@@ -0,0 +1,49 @@
+/*
+    Copyright (C) 2007 Rob Buis <buis@kde.org>
+
+    This library is free software; you can redistribute it and/or
+    modify it under the terms of the GNU Library General Public
+    License as published by the Free Software Foundation; either
+    version 2 of the License, 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
+
+#include "core/rendering/HitTestRequest.h"
+#include "core/rendering/style/RenderStyleConstants.h"
+
+namespace WebCore {
+
+class PointerEventsHitRules {
+public:
+    enum EHitTesting {
+        SVG_IMAGE_HITTESTING,
+        SVG_PATH_HITTESTING,
+        SVG_TEXT_HITTESTING
+    };
+
+    PointerEventsHitRules(EHitTesting, const HitTestRequest&, EPointerEvents);
+
+    bool requireVisible;
+    bool requireFill;
+    bool requireStroke;
+    bool canHitStroke;
+    bool canHitFill;  
+};
+
+}
+
+#endif
+
+// vim:ts=4:noet
diff --git a/Source/core/rendering/RenderApplet.cpp b/Source/core/rendering/RenderApplet.cpp
new file mode 100644
index 0000000..be4de73
--- /dev/null
+++ b/Source/core/rendering/RenderApplet.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2003, 2006, 2009, 2012 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 "core/rendering/RenderApplet.h"
+
+#include "core/html/HTMLAppletElement.h"
+
+namespace WebCore {
+
+RenderApplet::RenderApplet(HTMLAppletElement* applet)
+    : RenderEmbeddedObject(applet)
+{
+    setInline(true);
+}
+
+RenderApplet::~RenderApplet()
+{
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderApplet.h b/Source/core/rendering/RenderApplet.h
new file mode 100644
index 0000000..3a0f7af
--- /dev/null
+++ b/Source/core/rendering/RenderApplet.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2006, 2007, 2009 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 "core/rendering/RenderEmbeddedObject.h"
+
+namespace WebCore {
+
+class HTMLAppletElement;
+
+class RenderApplet FINAL : public RenderEmbeddedObject {
+public:
+    explicit RenderApplet(HTMLAppletElement*);
+    virtual ~RenderApplet();
+
+private:
+    virtual const char* renderName() const { return "RenderApplet"; }
+};
+
+} // namespace WebCore
+
+#endif // RenderApplet_h
diff --git a/Source/core/rendering/RenderArena.cpp b/Source/core/rendering/RenderArena.cpp
new file mode 100644
index 0000000..2b6a05c
--- /dev/null
+++ b/Source/core/rendering/RenderArena.cpp
@@ -0,0 +1,170 @@
+/*
+ * Copyright (C) 2003 Apple Computer, Inc.
+ * Copyright (C) Research In Motion Limited 2010. All rights reserved.
+ *
+ * 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 "core/rendering/RenderArena.h"
+
+#include <stdlib.h>
+#include <string.h>
+#include <limits>
+#include <wtf/Assertions.h>
+#include <wtf/CryptographicallyRandomNumber.h>
+
+#define ROUNDUP(x, y) ((((x)+((y)-1))/(y))*(y))
+
+#ifdef NDEBUG
+static void* MaskPtr(void* p, uintptr_t mask)
+{
+    return reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(p) ^ mask);
+}
+#endif
+
+namespace WebCore {
+
+#ifndef NDEBUG
+
+const int signature = 0xDBA00AEA;
+const int signatureDead = 0xDBA00AED;
+
+typedef struct {
+    RenderArena* arena;
+    size_t size;
+    int signature;
+} RenderArenaDebugHeader;
+
+static const size_t debugHeaderSize = ARENA_ALIGN(sizeof(RenderArenaDebugHeader));
+
+#endif
+
+RenderArena::RenderArena(unsigned arenaSize)
+    : m_totalSize(0)
+    , m_totalAllocated(0)
+{
+    ASSERT(arenaSize > sizeof(Arena) + ARENA_ALIGN_MASK);
+    // The underlying Arena class allocates some metadata on top of our
+    // requested size. Factor this in so that we can get perfect power-of-two
+    // allocation sizes passed to the underlying malloc() call.
+    arenaSize -= (sizeof(Arena) + ARENA_ALIGN_MASK);
+    // Initialize the arena pool
+    INIT_ARENA_POOL(&m_pool, "RenderArena", arenaSize);
+
+    // Zero out the recyclers array
+    memset(m_recyclers, 0, sizeof(m_recyclers));
+
+    // Mask freelist pointers to detect corruption and stop freelist spraying.
+    // We use an arbitray function and rely on ASLR to randomize it.
+    // The first value in RenderObject (or any class) is a vtable pointer, which
+    // always overlaps with the next pointer. This change guarantees that the
+    // masked vtable/next pointer will never point to valid memory. So, we
+    // should immediately crash on the first invalid vtable access for a stale
+    // RenderObject pointer.
+    // See http://download.crowdstrike.com/papers/hes-exploiting-a-coalmine.pdf.
+    WTF::cryptographicallyRandomValues(&m_mask, sizeof(m_mask));
+    m_mask |= (static_cast<uintptr_t>(3) << (std::numeric_limits<uintptr_t>::digits - 2)) | 1;
+}
+
+RenderArena::~RenderArena()
+{
+    FinishArenaPool(&m_pool);
+}
+
+void* RenderArena::allocate(size_t size)
+{
+    ASSERT(size <= gMaxRecycledSize - 32);
+    m_totalSize += size;
+
+#ifdef ADDRESS_SANITIZER
+    return ::malloc(size);
+#elif !defined(NDEBUG)
+    // Use standard malloc so that memory debugging tools work.
+    ASSERT(this);
+    void* block = ::malloc(debugHeaderSize + size);
+    RenderArenaDebugHeader* header = static_cast<RenderArenaDebugHeader*>(block);
+    header->arena = this;
+    header->size = size;
+    header->signature = signature;
+    return static_cast<char*>(block) + debugHeaderSize;
+#else
+    // Ensure we have correct alignment for pointers.  Important for Tru64
+    size = ROUNDUP(size, sizeof(void*));
+
+    const size_t index = size >> kRecyclerShift;
+
+    void* result = m_recyclers[index];
+    if (result) {
+        // Need to move to the next object
+        void* next = MaskPtr(*((void**)result), m_mask);
+        m_recyclers[index] = next;
+    }
+
+    if (!result) {
+        // Allocate a new chunk from the arena
+        unsigned bytesAllocated = 0;
+        ARENA_ALLOCATE(result, &m_pool, size, &bytesAllocated);
+        m_totalAllocated += bytesAllocated;
+    }
+
+    return result;
+#endif
+}
+
+void RenderArena::free(size_t size, void* ptr)
+{
+    ASSERT(size <= gMaxRecycledSize - 32);
+    m_totalSize -= size;
+
+#ifdef ADDRESS_SANITIZER
+    ::free(ptr);
+#elif !defined(NDEBUG)
+    // Use standard free so that memory debugging tools work.
+    void* block = static_cast<char*>(ptr) - debugHeaderSize;
+    RenderArenaDebugHeader* header = static_cast<RenderArenaDebugHeader*>(block);
+    ASSERT(header->signature == signature);
+    ASSERT_UNUSED(size, header->size == size);
+    ASSERT(header->arena == this);
+    header->signature = signatureDead;
+    ::free(block);
+#else
+    // Ensure we have correct alignment for pointers.  Important for Tru64
+    size = ROUNDUP(size, sizeof(void*));
+
+    const size_t index = size >> kRecyclerShift;
+    void* currentTop = m_recyclers[index];
+    m_recyclers[index] = ptr;
+    *((void**)ptr) = MaskPtr(currentTop, m_mask);
+#endif
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderArena.h b/Source/core/rendering/RenderArena.h
new file mode 100644
index 0000000..0dd278d
--- /dev/null
+++ b/Source/core/rendering/RenderArena.h
@@ -0,0 +1,76 @@
+/*
+ * 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 "core/platform/Arena.h"
+#include <wtf/FastAllocBase.h>
+#include <wtf/Noncopyable.h>
+
+namespace WebCore {
+
+static const size_t gMaxRecycledSize = 1024;
+
+class RenderArena {
+    WTF_MAKE_NONCOPYABLE(RenderArena); WTF_MAKE_FAST_ALLOCATED;
+public:
+    explicit RenderArena(unsigned arenaSize = 8192);
+    ~RenderArena();
+
+    // Memory management functions
+    void* allocate(size_t);
+    void free(size_t, void*);
+
+    size_t totalRenderArenaSize() const { return m_totalSize; }
+    size_t totalRenderArenaAllocatedBytes() const { return m_totalAllocated; }
+
+private:
+    // Underlying arena pool
+    ArenaPool m_pool;
+
+    // The mask used to secure the recycled freelist pointers.
+    uintptr_t m_mask;
+    // The recycler array is sparse with the indices being multiples of the
+    // rounding size, sizeof(void*), i.e., 0, 4, 8, 12, 16, 20, ... on 32-bit.
+    static const size_t kRecyclerShift = (sizeof(void*) == 8) ? 3 : 2;
+    void* m_recyclers[gMaxRecycledSize >> kRecyclerShift];
+
+    size_t m_totalSize;
+    size_t m_totalAllocated;
+};
+
+} // namespace WebCore
+
+#endif // RenderArena_h
diff --git a/Source/core/rendering/RenderBR.cpp b/Source/core/rendering/RenderBR.cpp
new file mode 100644
index 0000000..d66068f
--- /dev/null
+++ b/Source/core/rendering/RenderBR.cpp
@@ -0,0 +1,82 @@
+/**
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ * 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 "core/rendering/RenderBR.h"
+
+#include "core/dom/Document.h"
+#include "core/editing/VisiblePosition.h"
+#include "core/rendering/InlineTextBox.h"
+
+namespace WebCore {
+
+static PassRefPtr<StringImpl> newlineString()
+{
+    DEFINE_STATIC_LOCAL(const String, string, (ASCIILiteral("\n")));
+    return string.impl();
+}
+
+RenderBR::RenderBR(Node* node)
+    : RenderText(node, newlineString())
+    , m_lineHeight(-1)
+{
+}
+
+RenderBR::~RenderBR()
+{
+}
+
+int RenderBR::lineHeight(bool firstLine) const
+{
+    if (firstLine && document()->styleSheetCollection()->usesFirstLineRules()) {
+        RenderStyle* s = style(firstLine);
+        if (s != style())
+            return s->computedLineHeight(view());
+    }
+    
+    if (m_lineHeight == -1)
+        m_lineHeight = style()->computedLineHeight(view());
+    
+    return m_lineHeight;
+}
+
+void RenderBR::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
+{
+    RenderText::styleDidChange(diff, oldStyle);
+    m_lineHeight = -1;
+}
+
+int RenderBR::caretMinOffset() const 
+{ 
+    return 0;
+}
+
+int RenderBR::caretMaxOffset() const 
+{ 
+    return 1;
+}
+
+VisiblePosition RenderBR::positionForPoint(const LayoutPoint&)
+{
+    return createVisiblePosition(0, DOWNSTREAM);
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderBR.h b/Source/core/rendering/RenderBR.h
new file mode 100644
index 0000000..5a805ab
--- /dev/null
+++ b/Source/core/rendering/RenderBR.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, 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 "core/rendering/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 FINAL : public RenderText {
+public:
+    explicit RenderBR(Node*);
+    virtual ~RenderBR();
+
+    virtual const char* renderName() const { return "RenderBR"; }
+ 
+    virtual LayoutRect selectionRectForRepaint(const RenderLayerModelObject* /*repaintContainer*/, bool /*clipToVisibleContent*/) OVERRIDE { return LayoutRect(); }
+
+    virtual float width(unsigned /*from*/, unsigned /*len*/, const Font&, float /*xPos*/, HashSet<const SimpleFontData*>* = 0 /*fallbackFonts*/ , GlyphOverflow* = 0) const { return 0; }
+    virtual float width(unsigned /*from*/, unsigned /*len*/, float /*xpos*/, bool = false /*firstLine*/, HashSet<const SimpleFontData*>* = 0 /*fallbackFonts*/, GlyphOverflow* = 0) const { return 0; }
+
+    int lineHeight(bool firstLine) const;
+
+    // overrides
+    virtual bool isBR() const { return true; }
+
+    virtual int caretMinOffset() const;
+    virtual int caretMaxOffset() const;
+
+    virtual VisiblePosition positionForPoint(const LayoutPoint&);
+
+protected:
+    virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+
+private:
+    mutable int m_lineHeight;
+};
+
+
+inline RenderBR* toRenderBR(RenderObject* object)
+{ 
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isBR());
+    return static_cast<RenderBR*>(object);
+}
+
+inline const RenderBR* toRenderBR(const RenderObject* object)
+{ 
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isBR());
+    return static_cast<const RenderBR*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderBR(const RenderBR*);
+
+} // namespace WebCore
+
+#endif // RenderBR_h
diff --git a/Source/core/rendering/RenderBlock.cpp b/Source/core/rendering/RenderBlock.cpp
new file mode 100644
index 0000000..2218ef5
--- /dev/null
+++ b/Source/core/rendering/RenderBlock.cpp
@@ -0,0 +1,8094 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2007 David Smith (catfish.man@gmail.com)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) Research In Motion Limited 2010. 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 "core/rendering/RenderBlock.h"
+
+#include "HTMLNames.h"
+#include "core/accessibility/AXObjectCache.h"
+#include "core/dom/Document.h"
+#include "core/dom/Element.h"
+#include "core/dom/OverflowEvent.h"
+#include "core/dom/ShadowRoot.h"
+#include "core/dom/WebCoreMemoryInstrumentation.h"
+#include "core/editing/Editor.h"
+#include "core/editing/FrameSelection.h"
+#include "core/html/HTMLFormElement.h"
+#include "core/page/Frame.h"
+#include "core/page/FrameView.h"
+#include "core/page/Page.h"
+#include "core/page/Settings.h"
+#include "core/platform/PODFreeListArena.h"
+#include "core/platform/graphics/FloatQuad.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/platform/graphics/transforms/TransformState.h"
+#include "core/rendering/ColumnInfo.h"
+#include "core/rendering/exclusions/ExclusionShapeInsideInfo.h"
+#include "core/rendering/exclusions/ExclusionShapeOutsideInfo.h"
+#include "core/rendering/HitTestLocation.h"
+#include "core/rendering/HitTestResult.h"
+#include "core/rendering/InlineIterator.h"
+#include "core/rendering/InlineTextBox.h"
+#include "core/rendering/LayoutRepainter.h"
+#include "core/rendering/PaintInfo.h"
+#include "core/rendering/RenderBoxRegionInfo.h"
+#include "core/rendering/RenderCombineText.h"
+#include "core/rendering/RenderDeprecatedFlexibleBox.h"
+#include "core/rendering/RenderFlexibleBox.h"
+#include "core/rendering/RenderImage.h"
+#include "core/rendering/RenderInline.h"
+#include "core/rendering/RenderLayer.h"
+#include "core/rendering/RenderMarquee.h"
+#include "core/rendering/RenderNamedFlowThread.h"
+#include "core/rendering/RenderRegion.h"
+#include "core/rendering/RenderReplica.h"
+#include "core/rendering/RenderTableCell.h"
+#include "core/rendering/RenderTextFragment.h"
+#include "core/rendering/RenderTheme.h"
+#include "core/rendering/RenderView.h"
+#include "core/rendering/svg/SVGTextRunRenderingContext.h"
+#include <wtf/StdLibExtras.h>
+#include <wtf/MemoryInstrumentationHashMap.h>
+#include <wtf/MemoryInstrumentationHashSet.h>
+#include <wtf/MemoryInstrumentationListHashSet.h>
+#include <wtf/TemporaryChange.h>
+
+using namespace std;
+using namespace WTF;
+using namespace Unicode;
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+struct SameSizeAsRenderBlock : public RenderBox {
+    void* pointers[2];
+    RenderObjectChildList children;
+    RenderLineBoxList lineBoxes;
+    uint32_t bitfields;
+};
+
+COMPILE_ASSERT(sizeof(RenderBlock) == sizeof(SameSizeAsRenderBlock), RenderBlock_should_stay_small);
+
+struct SameSizeAsFloatingObject {
+    void* pointers[2];
+    LayoutRect rect;
+    int paginationStrut;
+    uint32_t bitfields : 8;
+};
+
+COMPILE_ASSERT(sizeof(RenderBlock::MarginValues) == sizeof(LayoutUnit[4]), MarginValues_should_stay_small);
+
+struct SameSizeAsMarginInfo {
+    uint32_t bitfields : 16;
+    LayoutUnit margins[2];
+};
+
+typedef WTF::HashMap<const RenderBox*, OwnPtr<ColumnInfo> > ColumnInfoMap;
+static ColumnInfoMap* gColumnInfoMap = 0;
+
+static TrackedDescendantsMap* gPositionedDescendantsMap = 0;
+static TrackedDescendantsMap* gPercentHeightDescendantsMap = 0;
+
+static TrackedContainerMap* gPositionedContainerMap = 0;
+static TrackedContainerMap* gPercentHeightContainerMap = 0;
+    
+typedef WTF::HashMap<RenderBlock*, OwnPtr<ListHashSet<RenderInline*> > > ContinuationOutlineTableMap;
+
+typedef WTF::HashSet<RenderBlock*> DelayedUpdateScrollInfoSet;
+static int gDelayUpdateScrollInfo = 0;
+static DelayedUpdateScrollInfoSet* gDelayedUpdateScrollInfoSet = 0;
+
+static bool gColumnFlowSplitEnabled = true;
+
+bool RenderBlock::s_canPropagateFloatIntoSibling = false;
+
+// This class helps dispatching the 'overflow' event on layout change. overflow can be set on RenderBoxes, yet the existing code
+// only works on RenderBlocks. If this change, this class should be shared with other RenderBoxes.
+class OverflowEventDispatcher {
+    WTF_MAKE_NONCOPYABLE(OverflowEventDispatcher);
+public:
+    OverflowEventDispatcher(const RenderBlock* block)
+        : m_block(block)
+        , m_hadHorizontalLayoutOverflow(false)
+        , m_hadVerticalLayoutOverflow(false)
+    {
+        m_shouldDispatchEvent = !m_block->isAnonymous() && m_block->hasOverflowClip() && m_block->document()->hasListenerType(Document::OVERFLOWCHANGED_LISTENER);
+        if (m_shouldDispatchEvent) {
+            m_hadHorizontalLayoutOverflow = m_block->hasHorizontalLayoutOverflow();
+            m_hadVerticalLayoutOverflow = m_block->hasVerticalLayoutOverflow();
+        }
+    }
+
+    ~OverflowEventDispatcher()
+    {
+        if (!m_shouldDispatchEvent)
+            return;
+
+        bool hasHorizontalLayoutOverflow = m_block->hasHorizontalLayoutOverflow();
+        bool hasVerticalLayoutOverflow = m_block->hasVerticalLayoutOverflow();
+
+        bool horizontalLayoutOverflowChanged = hasHorizontalLayoutOverflow != m_hadHorizontalLayoutOverflow;
+        bool verticalLayoutOverflowChanged = hasVerticalLayoutOverflow != m_hadVerticalLayoutOverflow;
+        if (horizontalLayoutOverflowChanged || verticalLayoutOverflowChanged) {
+            if (FrameView* frameView = m_block->document()->view())
+                frameView->scheduleEvent(OverflowEvent::create(horizontalLayoutOverflowChanged, hasHorizontalLayoutOverflow, verticalLayoutOverflowChanged, hasVerticalLayoutOverflow), m_block->node());
+        }
+    }
+
+private:
+    const RenderBlock* m_block;
+    bool m_shouldDispatchEvent;
+    bool m_hadHorizontalLayoutOverflow;
+    bool m_hadVerticalLayoutOverflow;
+};
+
+// Our MarginInfo state used when laying out block children.
+RenderBlock::MarginInfo::MarginInfo(RenderBlock* block, LayoutUnit beforeBorderPadding, LayoutUnit afterBorderPadding)
+    : m_atBeforeSideOfBlock(true)
+    , m_atAfterSideOfBlock(false)
+    , m_hasMarginBeforeQuirk(false)
+    , m_hasMarginAfterQuirk(false)
+    , m_determinedMarginBeforeQuirk(false)
+    , m_discardMargin(false)
+{
+    RenderStyle* blockStyle = block->style();
+    ASSERT(block->isRenderView() || block->parent());
+    m_canCollapseWithChildren = !block->isRenderView() && !block->isRoot() && !block->isOutOfFlowPositioned()
+        && !block->isFloating() && !block->isTableCell() && !block->hasOverflowClip() && !block->isInlineBlockOrInlineTable()
+        && !block->isRenderFlowThread() && !block->isWritingModeRoot() && !block->parent()->isFlexibleBox()
+        && blockStyle->hasAutoColumnCount() && blockStyle->hasAutoColumnWidth() && !blockStyle->columnSpan();
+
+    m_canCollapseMarginBeforeWithChildren = m_canCollapseWithChildren && !beforeBorderPadding && blockStyle->marginBeforeCollapse() != 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_canCollapseMarginAfterWithChildren = m_canCollapseWithChildren && (afterBorderPadding == 0) &&
+        (blockStyle->logicalHeight().isAuto() && !blockStyle->logicalHeight().value()) && blockStyle->marginAfterCollapse() != MSEPARATE;
+    
+    m_quirkContainer = block->isTableCell() || block->isBody();
+
+    m_discardMargin = m_canCollapseMarginBeforeWithChildren && block->mustDiscardMarginBefore();
+
+    m_positiveMargin = (m_canCollapseMarginBeforeWithChildren && !block->mustDiscardMarginBefore()) ? block->maxPositiveMarginBefore() : LayoutUnit();
+    m_negativeMargin = (m_canCollapseMarginBeforeWithChildren && !block->mustDiscardMarginBefore()) ? block->maxNegativeMarginBefore() : LayoutUnit();
+}
+
+// -------------------------------------------------------------------------------------------------------
+
+RenderBlock::RenderBlock(ContainerNode* node)
+    : RenderBox(node)
+    , m_lineHeight(-1)
+    , m_hasMarginBeforeQuirk(false)
+    , m_hasMarginAfterQuirk(false)
+    , m_beingDestroyed(false)
+    , m_hasMarkupTruncation(false)
+    , m_hasBorderOrPaddingLogicalWidthChanged(false)
+{
+    setChildrenInline(true);
+    COMPILE_ASSERT(sizeof(RenderBlock::FloatingObject) == sizeof(SameSizeAsFloatingObject), FloatingObject_should_stay_small);
+    COMPILE_ASSERT(sizeof(RenderBlock::MarginInfo) == sizeof(SameSizeAsMarginInfo), MarginInfo_should_stay_small);
+}
+
+static void removeBlockFromDescendantAndContainerMaps(RenderBlock* block, TrackedDescendantsMap*& descendantMap, TrackedContainerMap*& containerMap)
+{
+    if (OwnPtr<TrackedRendererListHashSet> descendantSet = descendantMap->take(block)) {
+        TrackedRendererListHashSet::iterator end = descendantSet->end();
+        for (TrackedRendererListHashSet::iterator descendant = descendantSet->begin(); descendant != end; ++descendant) {
+            TrackedContainerMap::iterator it = containerMap->find(*descendant);
+            ASSERT(it != containerMap->end());
+            if (it == containerMap->end())
+                continue;
+            HashSet<RenderBlock*>* containerSet = it->value.get();
+            ASSERT(containerSet->contains(block));
+            containerSet->remove(block);
+            if (containerSet->isEmpty())
+                containerMap->remove(it);
+        }
+    }
+}
+
+RenderBlock::~RenderBlock()
+{
+    if (m_floatingObjects)
+        deleteAllValues(m_floatingObjects->set());
+    
+    if (hasColumns())
+        gColumnInfoMap->take(this);
+
+    if (gPercentHeightDescendantsMap)
+        removeBlockFromDescendantAndContainerMaps(this, gPercentHeightDescendantsMap, gPercentHeightContainerMap);
+    if (gPositionedDescendantsMap)
+        removeBlockFromDescendantAndContainerMaps(this, gPositionedDescendantsMap, gPositionedContainerMap);
+}
+
+RenderBlock* RenderBlock::createAnonymous(Document* document)
+{
+    RenderBlock* renderer = new (document->renderArena()) RenderBlock(0);
+    renderer->setDocumentForAnonymous(document);
+    return renderer;
+}
+
+void RenderBlock::willBeDestroyed()
+{
+    // Mark as being destroyed to avoid trouble with merges in removeChild().
+    m_beingDestroyed = true;
+
+    // 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.
+    children()->destroyLeftoverChildren();
+
+    // Destroy our continuation before anything other than anonymous children.
+    // The reason we don't destroy it before anonymous children is that they may
+    // have continuations of their own that are anonymous children of our continuation.
+    RenderBoxModelObject* continuation = this->continuation();
+    if (continuation) {
+        continuation->destroy();
+        setContinuation(0);
+    }
+    
+    if (!documentBeingDestroyed()) {
+        if (firstLineBox()) {
+            // We can't wait for RenderBox::destroy to clear the selection,
+            // because by then we will have nuked the line boxes.
+            // FIXME: The FrameSelection should be responsible for this when it
+            // is notified of DOM mutations.
+            if (isSelectionBorder())
+                view()->clearSelection();
+
+            // 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 = firstLineBox(); box; box = box->nextLineBox()) {
+                    while (InlineBox* childBox = box->firstChild())
+                        childBox->remove();
+                }
+            }
+        } else if (parent())
+            parent()->dirtyLinesFromChangedChild(this);
+    }
+
+    m_lineBoxes.deleteLineBoxes(renderArena());
+
+    if (lineGridBox())
+        lineGridBox()->destroy(renderArena());
+
+    if (UNLIKELY(gDelayedUpdateScrollInfoSet != 0))
+        gDelayedUpdateScrollInfoSet->remove(this);
+
+    RenderBox::willBeDestroyed();
+}
+
+void RenderBlock::styleWillChange(StyleDifference diff, const RenderStyle* newStyle)
+{
+    RenderStyle* oldStyle = style();
+    s_canPropagateFloatIntoSibling = oldStyle ? !isFloatingOrOutOfFlowPositioned() && !avoidsFloats() : false;
+
+    setReplaced(newStyle->isDisplayInlineType());
+    
+    if (oldStyle && parent() && diff == StyleDifferenceLayout && oldStyle->position() != newStyle->position()) {
+        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, NewContainingBlock);
+        else if (oldStyle->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();
+            }
+            
+            if (cb->isRenderBlock())
+                toRenderBlock(cb)->removePositionedObjects(this, NewContainingBlock);
+        }
+
+        if (containsFloats() && !isFloating() && !isOutOfFlowPositioned() && newStyle->hasOutOfFlowPosition())
+            markAllDescendantsWithFloatsForLayout();
+    }
+
+    RenderBox::styleWillChange(diff, newStyle);
+}
+
+static bool borderOrPaddingLogicalWidthChanged(const RenderStyle* oldStyle, const RenderStyle* newStyle)
+{
+    if (newStyle->isHorizontalWritingMode())
+        return oldStyle->borderLeftWidth() != newStyle->borderLeftWidth()
+            || oldStyle->borderRightWidth() != newStyle->borderRightWidth()
+            || oldStyle->paddingLeft() != newStyle->paddingLeft()
+            || oldStyle->paddingRight() != newStyle->paddingRight();
+
+    return oldStyle->borderTopWidth() != newStyle->borderTopWidth()
+        || oldStyle->borderBottomWidth() != newStyle->borderBottomWidth()
+        || oldStyle->paddingTop() != newStyle->paddingTop()
+        || oldStyle->paddingBottom() != newStyle->paddingBottom();
+}
+
+void RenderBlock::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
+{
+    RenderBox::styleDidChange(diff, oldStyle);
+    
+    RenderStyle* newStyle = style();
+
+    // FIXME: Bug 89993: Style changes should affect the ExclusionShapeInsideInfos for other render blocks that
+    // share the same ExclusionShapeInsideInfo
+    updateExclusionShapeInsideInfoAfterStyleChange(newStyle->resolvedShapeInside(), oldStyle ? oldStyle->resolvedShapeInside() : 0);
+
+    if (!isAnonymousBlock()) {
+        // Ensure that all of our continuation blocks pick up the new style.
+        for (RenderBlock* currCont = blockElementContinuation(); currCont; currCont = currCont->blockElementContinuation()) {
+            RenderBoxModelObject* nextCont = currCont->continuation();
+            currCont->setContinuation(0);
+            currCont->setStyle(newStyle);
+            currCont->setContinuation(nextCont);
+        }
+    }
+
+    propagateStyleToAnonymousChildren(true);    
+    m_lineHeight = -1;
+
+    // After our style changed, if we lose our ability to propagate floats into next sibling
+    // blocks, then we need to find the top most parent containing that overhanging float and
+    // then mark its descendants with floats for layout and clear all floats from its next
+    // sibling blocks that exist in our floating objects list. See bug 56299 and 62875.
+    bool canPropagateFloatIntoSibling = !isFloatingOrOutOfFlowPositioned() && !avoidsFloats();
+    if (diff == StyleDifferenceLayout && s_canPropagateFloatIntoSibling && !canPropagateFloatIntoSibling && hasOverhangingFloats()) {
+        RenderBlock* parentBlock = this;
+        const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
+        FloatingObjectSetIterator end = floatingObjectSet.end();
+
+        for (RenderObject* curr = parent(); curr && !curr->isRenderView(); curr = curr->parent()) {
+            if (curr->isRenderBlock()) {
+                RenderBlock* currBlock = toRenderBlock(curr);
+
+                if (currBlock->hasOverhangingFloats()) {
+                    for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
+                        RenderBox* renderer = (*it)->renderer();
+                        if (currBlock->hasOverhangingFloat(renderer)) {
+                            parentBlock = currBlock;
+                            break;
+                        }
+                    }
+                }
+            }
+        }
+              
+        parentBlock->markAllDescendantsWithFloatsForLayout();
+        parentBlock->markSiblingsWithFloatsForLayout();
+    }
+    
+    // It's possible for our border/padding to change, but for the overall logical width of the block to
+    // end up being the same. We keep track of this change so in layoutBlock, we can know to set relayoutChildren=true.
+    m_hasBorderOrPaddingLogicalWidthChanged = oldStyle && diff == StyleDifferenceLayout && needsLayout() && borderOrPaddingLogicalWidthChanged(oldStyle, newStyle);
+}
+
+RenderBlock* RenderBlock::continuationBefore(RenderObject* beforeChild)
+{
+    if (beforeChild && beforeChild->parent() == this)
+        return this;
+
+    RenderBlock* curr = toRenderBlock(continuation());
+    RenderBlock* nextToLast = this;
+    RenderBlock* last = this;
+    while (curr) {
+        if (beforeChild && beforeChild->parent() == curr) {
+            if (curr->firstChild() == beforeChild)
+                return last;
+            return curr;
+        }
+
+        nextToLast = last;
+        last = curr;
+        curr = toRenderBlock(curr->continuation());
+    }
+
+    if (!beforeChild && !last->firstChild())
+        return nextToLast;
+    return last;
+}
+
+void RenderBlock::addChildToContinuation(RenderObject* newChild, RenderObject* beforeChild)
+{
+    RenderBlock* flow = continuationBefore(beforeChild);
+    ASSERT(!beforeChild || beforeChild->parent()->isAnonymousColumnSpanBlock() || beforeChild->parent()->isRenderBlock());
+    RenderBoxModelObject* beforeChildParent = 0;
+    if (beforeChild)
+        beforeChildParent = toRenderBoxModelObject(beforeChild->parent());
+    else {
+        RenderBoxModelObject* cont = flow->continuation();
+        if (cont)
+            beforeChildParent = cont;
+        else
+            beforeChildParent = flow;
+    }
+
+    if (newChild->isFloatingOrOutOfFlowPositioned()) {
+        beforeChildParent->addChildIgnoringContinuation(newChild, beforeChild);
+        return;
+    }
+
+    // A continuation always consists of two potential candidates: a block or an anonymous
+    // column span box holding column span children.
+    bool childIsNormal = newChild->isInline() || !newChild->style()->columnSpan();
+    bool bcpIsNormal = beforeChildParent->isInline() || !beforeChildParent->style()->columnSpan();
+    bool flowIsNormal = flow->isInline() || !flow->style()->columnSpan();
+
+    if (flow == beforeChildParent) {
+        flow->addChildIgnoringContinuation(newChild, beforeChild);
+        return;
+    }
+    
+    // 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 (childIsNormal == bcpIsNormal) {
+        beforeChildParent->addChildIgnoringContinuation(newChild, beforeChild);
+        return;
+    }
+    if (flowIsNormal == childIsNormal) {
+        flow->addChildIgnoringContinuation(newChild, 0); // Just treat like an append.
+        return;
+    }
+    beforeChildParent->addChildIgnoringContinuation(newChild, beforeChild);
+}
+
+
+void RenderBlock::addChildToAnonymousColumnBlocks(RenderObject* newChild, RenderObject* beforeChild)
+{
+    ASSERT(!continuation()); // We don't yet support column spans that aren't immediate children of the multi-column block.
+        
+    // The goal is to locate a suitable box in which to place our child.
+    RenderBlock* beforeChildParent = 0;
+    if (beforeChild) {
+        RenderObject* curr = beforeChild;
+        while (curr && curr->parent() != this)
+            curr = curr->parent();
+        beforeChildParent = toRenderBlock(curr);
+        ASSERT(beforeChildParent);
+        ASSERT(beforeChildParent->isAnonymousColumnsBlock() || beforeChildParent->isAnonymousColumnSpanBlock());
+    } else
+        beforeChildParent = toRenderBlock(lastChild());
+
+    // If the new child is floating or positioned it can just go in that block.
+    if (newChild->isFloatingOrOutOfFlowPositioned()) {
+        beforeChildParent->addChildIgnoringAnonymousColumnBlocks(newChild, beforeChild);
+        return;
+    }
+
+    // See if the child can be placed in the box.
+    bool newChildHasColumnSpan = newChild->style()->columnSpan() && !newChild->isInline();
+    bool beforeChildParentHoldsColumnSpans = beforeChildParent->isAnonymousColumnSpanBlock();
+
+    if (newChildHasColumnSpan == beforeChildParentHoldsColumnSpans) {
+        beforeChildParent->addChildIgnoringAnonymousColumnBlocks(newChild, beforeChild);
+        return;
+    }
+
+    if (!beforeChild) {
+        // Create a new block of the correct type.
+        RenderBlock* newBox = newChildHasColumnSpan ? createAnonymousColumnSpanBlock() : createAnonymousColumnsBlock();
+        children()->appendChildNode(this, newBox);
+        newBox->addChildIgnoringAnonymousColumnBlocks(newChild, 0);
+        return;
+    }
+
+    RenderObject* immediateChild = beforeChild;
+    bool isPreviousBlockViable = true;
+    while (immediateChild->parent() != this) {
+        if (isPreviousBlockViable)
+            isPreviousBlockViable = !immediateChild->previousSibling();
+        immediateChild = immediateChild->parent();
+    }
+    if (isPreviousBlockViable && immediateChild->previousSibling()) {
+        toRenderBlock(immediateChild->previousSibling())->addChildIgnoringAnonymousColumnBlocks(newChild, 0); // Treat like an append.
+        return;
+    }
+        
+    // Split our anonymous blocks.
+    RenderObject* newBeforeChild = splitAnonymousBoxesAroundChild(beforeChild);
+
+    
+    // Create a new anonymous box of the appropriate type.
+    RenderBlock* newBox = newChildHasColumnSpan ? createAnonymousColumnSpanBlock() : createAnonymousColumnsBlock();
+    children()->insertChildNode(this, newBox, newBeforeChild);
+    newBox->addChildIgnoringAnonymousColumnBlocks(newChild, 0);
+    return;
+}
+
+RenderBlock* RenderBlock::containingColumnsBlock(bool allowAnonymousColumnBlock)
+{
+    RenderBlock* firstChildIgnoringAnonymousWrappers = 0;
+    for (RenderObject* curr = this; curr; curr = curr->parent()) {
+        if (!curr->isRenderBlock() || curr->isFloatingOrOutOfFlowPositioned() || curr->isTableCell() || curr->isRoot() || curr->isRenderView() || curr->hasOverflowClip()
+            || curr->isInlineBlockOrInlineTable())
+            return 0;
+
+        // FIXME: Tables, RenderButtons, and RenderListItems all do special management
+        // of their children that breaks when the flow is split through them. Disabling
+        // multi-column for them to avoid this problem.
+        if (curr->isTable() || curr->isRenderButton() || curr->isListItem())
+            return 0;
+        
+        RenderBlock* currBlock = toRenderBlock(curr);
+        if (!currBlock->createsAnonymousWrapper())
+            firstChildIgnoringAnonymousWrappers = currBlock;
+
+        if (currBlock->style()->specifiesColumns() && (allowAnonymousColumnBlock || !currBlock->isAnonymousColumnsBlock()))
+            return firstChildIgnoringAnonymousWrappers;
+            
+        if (currBlock->isAnonymousColumnSpanBlock())
+            return 0;
+    }
+    return 0;
+}
+
+RenderBlock* RenderBlock::clone() const
+{
+    RenderBlock* cloneBlock;
+    if (isAnonymousBlock()) {
+        cloneBlock = createAnonymousBlock();
+        cloneBlock->setChildrenInline(childrenInline());
+    }
+    else {
+        RenderObject* cloneRenderer = toElement(node())->createRenderer(renderArena(), style());
+        cloneBlock = toRenderBlock(cloneRenderer);
+        cloneBlock->setStyle(style());
+
+        // This takes care of setting the right value of childrenInline in case
+        // generated content is added to cloneBlock and 'this' does not have
+        // generated content added yet.
+        cloneBlock->setChildrenInline(cloneBlock->firstChild() ? cloneBlock->firstChild()->isInline() : childrenInline());
+    }
+    cloneBlock->setFlowThreadState(flowThreadState());
+    return cloneBlock;
+}
+
+void RenderBlock::splitBlocks(RenderBlock* fromBlock, RenderBlock* toBlock,
+                              RenderBlock* middleBlock,
+                              RenderObject* beforeChild, RenderBoxModelObject* oldCont)
+{
+    // Create a clone of this inline.
+    RenderBlock* cloneBlock = clone();
+    if (!isAnonymousBlock())
+        cloneBlock->setContinuation(oldCont);
+
+    if (!beforeChild && isAfterContent(lastChild()))
+        beforeChild = lastChild();
+
+    // If we are moving inline children from |this| to cloneBlock, then we need
+    // to clear our line box tree.
+    if (beforeChild && childrenInline())
+        deleteLineBoxTree();
+
+    // Now take all of the children from beforeChild to the end and remove
+    // them from |this| and place them in the clone.
+    moveChildrenTo(cloneBlock, beforeChild, 0, true);
+    
+    // Hook |clone| up as the continuation of the middle block.
+    if (!cloneBlock->isAnonymousBlock())
+        middleBlock->setContinuation(cloneBlock);
+
+    // We have been reparented and are now under the fromBlock.  We need
+    // to walk up our block parent chain until we hit the containing anonymous columns block.
+    // Once we hit the anonymous columns block we're done.
+    RenderBoxModelObject* curr = toRenderBoxModelObject(parent());
+    RenderBoxModelObject* currChild = this;
+    RenderObject* currChildNextSibling = currChild->nextSibling();
+
+    while (curr && curr->isDescendantOf(fromBlock) && curr != fromBlock) {
+        ASSERT_WITH_SECURITY_IMPLICATION(curr->isRenderBlock());
+        
+        RenderBlock* blockCurr = toRenderBlock(curr);
+        
+        // Create a new clone.
+        RenderBlock* cloneChild = cloneBlock;
+        cloneBlock = blockCurr->clone();
+
+        // Insert our child clone as the first child.
+        cloneBlock->addChildIgnoringContinuation(cloneChild, 0);
+
+        // Hook the clone up as a continuation of |curr|.  Note we do encounter
+        // anonymous blocks possibly as we walk up the block chain.  When we split an
+        // anonymous block, there's no need to do any continuation hookup, since we haven't
+        // actually split a real element.
+        if (!blockCurr->isAnonymousBlock()) {
+            oldCont = blockCurr->continuation();
+            blockCurr->setContinuation(cloneBlock);
+            cloneBlock->setContinuation(oldCont);
+        }
+
+        // Now we need to take all of the children starting from the first child
+        // *after* currChild and append them all to the clone.
+        blockCurr->moveChildrenTo(cloneBlock, currChildNextSibling, 0, true);
+
+        // Keep walking up the chain.
+        currChild = curr;
+        currChildNextSibling = currChild->nextSibling();
+        curr = toRenderBoxModelObject(curr->parent());
+    }
+
+    // Now we are at the columns block level. We need to put the clone into the toBlock.
+    toBlock->children()->appendChildNode(toBlock, cloneBlock);
+
+    // Now take all the children after currChild and remove them from the fromBlock
+    // and put them in the toBlock.
+    fromBlock->moveChildrenTo(toBlock, currChildNextSibling, 0, true);
+}
+
+void RenderBlock::splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox,
+                            RenderObject* newChild, RenderBoxModelObject* oldCont)
+{
+    RenderBlock* pre = 0;
+    RenderBlock* block = containingColumnsBlock();
+    
+    // Delete our line boxes before we do the inline split into continuations.
+    block->deleteLineBoxTree();
+    
+    bool madeNewBeforeBlock = false;
+    if (block->isAnonymousColumnsBlock()) {
+        // We can reuse this block and make it the preBlock of the next continuation.
+        pre = block;
+        pre->removePositionedObjects(0);
+        pre->removeFloatingObjects();
+        block = toRenderBlock(block->parent());
+    } else {
+        // No anonymous block available for use.  Make one.
+        pre = block->createAnonymousColumnsBlock();
+        pre->setChildrenInline(false);
+        madeNewBeforeBlock = true;
+    }
+
+    RenderBlock* post = block->createAnonymousColumnsBlock();
+    post->setChildrenInline(false);
+
+    RenderObject* boxFirst = madeNewBeforeBlock ? block->firstChild() : pre->nextSibling();
+    if (madeNewBeforeBlock)
+        block->children()->insertChildNode(block, pre, boxFirst);
+    block->children()->insertChildNode(block, newBlockBox, boxFirst);
+    block->children()->insertChildNode(block, post, boxFirst);
+    block->setChildrenInline(false);
+    
+    if (madeNewBeforeBlock)
+        block->moveChildrenTo(pre, boxFirst, 0, true);
+
+    splitBlocks(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 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->addChild(newChild);
+
+    // 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 RenderBlock::makeChildrenAnonymousColumnBlocks(RenderObject* beforeChild, RenderBlock* newBlockBox, RenderObject* newChild)
+{
+    RenderBlock* pre = 0;
+    RenderBlock* post = 0;
+    RenderBlock* block = this; // Eventually block will not just be |this|, but will also be a block nested inside |this|.  Assign to a variable
+                               // so that we don't have to patch all of the rest of the code later on.
+    
+    // Delete the block's line boxes before we do the split.
+    block->deleteLineBoxTree();
+
+    if (beforeChild && beforeChild->parent() != this)
+        beforeChild = splitAnonymousBoxesAroundChild(beforeChild);
+
+    if (beforeChild != firstChild()) {
+        pre = block->createAnonymousColumnsBlock();
+        pre->setChildrenInline(block->childrenInline());
+    }
+
+    if (beforeChild) {
+        post = block->createAnonymousColumnsBlock();
+        post->setChildrenInline(block->childrenInline());
+    }
+
+    RenderObject* boxFirst = block->firstChild();
+    if (pre)
+        block->children()->insertChildNode(block, pre, boxFirst);
+    block->children()->insertChildNode(block, newBlockBox, boxFirst);
+    if (post)
+        block->children()->insertChildNode(block, post, boxFirst);
+    block->setChildrenInline(false);
+    
+    // The pre/post blocks always have layers, so we know to always do a full insert/remove (so we pass true as the last argument).
+    block->moveChildrenTo(pre, boxFirst, beforeChild, true);
+    block->moveChildrenTo(post, beforeChild, 0, true);
+
+    // 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 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->addChild(newChild);
+
+    // Always just do a full layout in order to ensure that line boxes (especially wrappers for images)
+    // get deleted properly.  Because objects moved from the pre block into the post block, we want to
+    // make new line boxes instead of leaving the old line boxes around.
+    if (pre)
+        pre->setNeedsLayoutAndPrefWidthsRecalc();
+    block->setNeedsLayoutAndPrefWidthsRecalc();
+    if (post)
+        post->setNeedsLayoutAndPrefWidthsRecalc();
+}
+
+RenderBlock* RenderBlock::columnsBlockForSpanningElement(RenderObject* newChild)
+{
+    // FIXME: This function is the gateway for the addition of column-span support.  It will
+    // be added to in three stages:
+    // (1) Immediate children of a multi-column block can span.
+    // (2) Nested block-level children with only block-level ancestors between them and the multi-column block can span.
+    // (3) Nested children with block or inline ancestors between them and the multi-column block can span (this is when we
+    // cross the streams and have to cope with both types of continuations mixed together).
+    // This function currently supports (1) and (2).
+    RenderBlock* columnsBlockAncestor = 0;
+    if (!newChild->isText() && newChild->style()->columnSpan() && !newChild->isBeforeOrAfterContent()
+        && !newChild->isFloatingOrOutOfFlowPositioned() && !newChild->isInline() && !isAnonymousColumnSpanBlock()) {
+        columnsBlockAncestor = containingColumnsBlock(false);
+        if (columnsBlockAncestor) {
+            // Make sure that none of the parent ancestors have a continuation.
+            // If yes, we do not want split the block into continuations.
+            RenderObject* curr = this;
+            while (curr && curr != columnsBlockAncestor) {
+                if (curr->isRenderBlock() && toRenderBlock(curr)->continuation()) {
+                    columnsBlockAncestor = 0;
+                    break;
+                }
+                curr = curr->parent();
+            }
+        }
+    }
+    return columnsBlockAncestor;
+}
+
+void RenderBlock::addChildIgnoringAnonymousColumnBlocks(RenderObject* newChild, RenderObject* beforeChild)
+{
+    if (beforeChild && beforeChild->parent() != this) {
+        RenderObject* beforeChildContainer = beforeChild->parent();
+        while (beforeChildContainer->parent() != this)
+            beforeChildContainer = beforeChildContainer->parent();
+        ASSERT(beforeChildContainer);
+
+        if (beforeChildContainer->isAnonymous()) {
+            // 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.
+            RenderObject* beforeChildAnonymousContainer = beforeChildContainer;
+            if (beforeChildAnonymousContainer->isAnonymousBlock()
+                // Full screen renderers and full screen placeholders act as anonymous blocks, not tables:
+                || beforeChildAnonymousContainer->isRenderFullScreen()
+                || beforeChildAnonymousContainer->isRenderFullScreenPlaceholder()
+                ) {
+                // Insert the child into the anonymous block box instead of here.
+                if (newChild->isInline() || beforeChild->parent()->firstChild() != beforeChild)
+                    beforeChild->parent()->addChild(newChild, beforeChild);
+                else
+                    addChild(newChild, beforeChild->parent());
+                return;
+            }
+
+            ASSERT(beforeChildAnonymousContainer->isTable());
+            if (newChild->isTablePart()) {
+                // Insert into the anonymous table.
+                beforeChildAnonymousContainer->addChild(newChild, beforeChild);
+                return;
+            }
+
+            beforeChild = splitAnonymousBoxesAroundChild(beforeChild);
+
+            ASSERT(beforeChild->parent() == this);
+            if (beforeChild->parent() != this) {
+                // We should never reach here. If we do, we need to use the
+                // safe fallback to use the topmost beforeChild container.
+                beforeChild = beforeChildContainer;
+            }
+        } else {
+            // We will reach here when beforeChild is a run-in element.
+            // If run-in element precedes a block-level element, it becomes the
+            // the first inline child of that block level element. The insertion
+            // point will be before that block-level element.
+            ASSERT(beforeChild->isRunIn());
+            beforeChild = beforeChildContainer;
+        }
+    }
+
+    // Nothing goes before the intruded run-in.
+    if (beforeChild && beforeChild->isRunIn() && runInIsPlacedIntoSiblingBlock(beforeChild))
+        beforeChild = beforeChild->nextSibling();
+
+    // Check for a spanning element in columns.
+    if (gColumnFlowSplitEnabled) {
+        RenderBlock* columnsBlockAncestor = columnsBlockForSpanningElement(newChild);
+        if (columnsBlockAncestor) {
+            TemporaryChange<bool> columnFlowSplitEnabled(gColumnFlowSplitEnabled, false);
+            // We are placing a column-span element inside a block.
+            RenderBlock* newBox = createAnonymousColumnSpanBlock();
+        
+            if (columnsBlockAncestor != this) {
+                // We are nested inside a multi-column element and are being split by the span. We have to break up
+                // our block into continuations.
+                RenderBoxModelObject* oldContinuation = continuation();
+
+                // When we split an anonymous block, there's no need to do any continuation hookup,
+                // since we haven't actually split a real element.
+                if (!isAnonymousBlock())
+                    setContinuation(newBox);
+
+                splitFlow(beforeChild, newBox, newChild, oldContinuation);
+                return;
+            }
+
+            // We have to perform a split of this block's children. This involves creating an anonymous block box to hold
+            // the column-spanning |newChild|. We take all of the children from before |newChild| and put them into
+            // one anonymous columns block, and all of the children after |newChild| go into another anonymous block.
+            makeChildrenAnonymousColumnBlocks(beforeChild, newBox, newChild);
+            return;
+        }
+    }
+
+    bool madeBoxesNonInline = false;
+
+    // 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 (childrenInline() && !newChild->isInline() && !newChild->isFloatingOrOutOfFlowPositioned()) {
+        // 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 (!childrenInline() && (newChild->isFloatingOrOutOfFlowPositioned() || 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();
+            RenderBox::addChild(newBox, beforeChild);
+            newBox->addChild(newChild);
+            return;
+        }
+    }
+
+    RenderBox::addChild(newChild, beforeChild);
+ 
+    // Handle placement of run-ins.
+    placeRunInIfNeeded(newChild);
+
+    if (madeBoxesNonInline && parent() && isAnonymousBlock() && parent()->isRenderBlock())
+        toRenderBlock(parent())->removeLeftoverAnonymousBlock(this);
+    // this object may be dead here
+}
+
+void RenderBlock::addChild(RenderObject* newChild, RenderObject* beforeChild)
+{
+    if (continuation() && !isAnonymousBlock())
+        addChildToContinuation(newChild, beforeChild);
+    else
+        addChildIgnoringContinuation(newChild, beforeChild);
+}
+
+void RenderBlock::addChildIgnoringContinuation(RenderObject* newChild, RenderObject* beforeChild)
+{
+    if (!isAnonymousBlock() && firstChild() && (firstChild()->isAnonymousColumnsBlock() || firstChild()->isAnonymousColumnSpanBlock()))
+        addChildToAnonymousColumnBlocks(newChild, beforeChild);
+    else
+        addChildIgnoringAnonymousColumnBlocks(newChild, beforeChild);
+}
+
+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->isFloatingOrOutOfFlowPositioned()))
+            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->isFloatingOrOutOfFlowPositioned()) && (curr != boundary)) {
+            inlineRunEnd = curr;
+            if (curr->isInline())
+                sawInline = true;
+            curr = curr->nextSibling();
+        }
+    } while (!sawInline);
+}
+
+void RenderBlock::deleteLineBoxTree()
+{
+    if (containsFloats()) {
+        // Clear references to originating lines, since the lines are being deleted
+        const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
+        FloatingObjectSetIterator end = floatingObjectSet.end();
+        for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
+            ASSERT(!((*it)->m_originatingLine) || (*it)->m_originatingLine->renderer() == this);
+            (*it)->m_originatingLine = 0;
+        }
+    }
+    m_lineBoxes.deleteLineBoxTree(renderArena());
+
+    if (AXObjectCache* cache = document()->existingAXObjectCache())
+        cache->recomputeIsIgnored(this);
+}
+
+RootInlineBox* RenderBlock::createRootInlineBox()
+{
+    return new (renderArena()) RootInlineBox(this);
+}
+
+RootInlineBox* RenderBlock::createAndAppendRootInlineBox()
+{
+    RootInlineBox* rootBox = createRootInlineBox();
+    m_lineBoxes.appendLineBox(rootBox);
+
+    if (UNLIKELY(AXObjectCache::accessibilityEnabled()) && m_lineBoxes.firstLineBox() == rootBox) {
+        if (AXObjectCache* cache = document()->existingAXObjectCache())
+            cache->recomputeIsIgnored(this);
+    }
+
+    return rootBox;
+}
+
+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);
+
+    setChildrenInline(false);
+
+    RenderObject *child = firstChild();
+    if (!child)
+        return;
+
+    deleteLineBoxTree();
+
+    // Since we are going to have block children, we have to move
+    // back the run-in to its original place.
+    if (child->isRunIn()) {
+        moveRunInToOriginalPosition(child);
+        child = firstChild();
+    }
+
+    while (child) {
+        RenderObject *inlineRunStart, *inlineRunEnd;
+        getInlineRun(child, insertionPoint, inlineRunStart, inlineRunEnd);
+
+        if (!inlineRunStart)
+            break;
+
+        child = inlineRunEnd->nextSibling();
+
+        RenderBlock* block = createAnonymousBlock();
+        children()->insertChildNode(this, block, inlineRunStart);
+        moveChildrenTo(block, inlineRunStart, child);
+    }
+
+#ifndef NDEBUG
+    for (RenderObject *c = firstChild(); c; c = c->nextSibling())
+        ASSERT(!c->isInline());
+#endif
+
+    repaint();
+}
+
+void RenderBlock::removeLeftoverAnonymousBlock(RenderBlock* child)
+{
+    ASSERT(child->isAnonymousBlock());
+    ASSERT(!child->childrenInline());
+    
+    if (child->continuation() || (child->firstChild() && (child->isAnonymousColumnSpanBlock() || child->isAnonymousColumnsBlock())))
+        return;
+    
+    RenderObject* firstAnChild = child->m_children.firstChild();
+    RenderObject* lastAnChild = child->m_children.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);
+            
+        if (child == m_children.firstChild())
+            m_children.setFirstChild(firstAnChild);
+        if (child == m_children.lastChild())
+            m_children.setLastChild(lastAnChild);
+    } else {
+        if (child == m_children.firstChild())
+            m_children.setFirstChild(child->nextSibling());
+        if (child == m_children.lastChild())
+            m_children.setLastChild(child->previousSibling());
+
+        if (child->previousSibling())
+            child->previousSibling()->setNextSibling(child->nextSibling());
+        if (child->nextSibling())
+            child->nextSibling()->setPreviousSibling(child->previousSibling());
+    }
+
+    child->children()->setFirstChild(0);
+    child->m_next = 0;
+
+    // Remove all the information in the flow thread associated with the leftover anonymous block.
+    child->removeFromRenderFlowThread();
+
+    child->setParent(0);
+    child->setPreviousSibling(0);
+    child->setNextSibling(0);
+
+    child->destroy();
+}
+
+static bool canMergeContiguousAnonymousBlocks(RenderObject* oldChild, RenderObject* prev, RenderObject* next)
+{
+    if (oldChild->documentBeingDestroyed() || oldChild->isInline() || oldChild->virtualContinuation())
+        return false;
+
+    if ((prev && (!prev->isAnonymousBlock() || toRenderBlock(prev)->continuation() || toRenderBlock(prev)->beingDestroyed()))
+        || (next && (!next->isAnonymousBlock() || toRenderBlock(next)->continuation() || toRenderBlock(next)->beingDestroyed())))
+        return false;
+
+    // FIXME: This check isn't required when inline run-ins can't be split into continuations.
+    if (prev && prev->firstChild() && prev->firstChild()->isInline() && prev->firstChild()->isRunIn())
+        return false;
+
+    if ((prev && (prev->isRubyRun() || prev->isRubyBase()))
+        || (next && (next->isRubyRun() || next->isRubyBase())))
+        return false;
+
+    if (!prev || !next)
+        return true;
+
+    // Make sure the types of the anonymous blocks match up.
+    return prev->isAnonymousColumnsBlock() == next->isAnonymousColumnsBlock()
+           && prev->isAnonymousColumnSpanBlock() == next->isAnonymousColumnSpanBlock();
+}
+
+void RenderBlock::collapseAnonymousBoxChild(RenderBlock* parent, RenderObject* child)
+{
+    parent->setNeedsLayoutAndPrefWidthsRecalc();
+    parent->setChildrenInline(child->childrenInline());
+    RenderObject* nextSibling = child->nextSibling();
+
+    RenderFlowThread* childFlowThread = child->flowThreadContainingBlock();
+    CurrentRenderFlowThreadMaintainer flowThreadMaintainer(childFlowThread);
+    
+    RenderBlock* anonBlock = toRenderBlock(parent->children()->removeChildNode(parent, child, child->hasLayer()));
+    anonBlock->moveAllChildrenTo(parent, nextSibling, child->hasLayer());
+    // Delete the now-empty block's lines and nuke it.
+    anonBlock->deleteLineBoxTree();
+    if (childFlowThread && childFlowThread->isRenderNamedFlowThread())
+        toRenderNamedFlowThread(childFlowThread)->removeFlowChildInfo(anonBlock);
+    anonBlock->destroy();
+}
+
+void RenderBlock::removeChild(RenderObject* oldChild)
+{
+    // No need to waste time in merging or removing empty anonymous blocks.
+    // We can just bail out if our document is getting destroyed.
+    if (documentBeingDestroyed()) {
+        RenderBox::removeChild(oldChild);
+        return;
+    }
+
+    // This protects against column split flows when anonymous blocks are getting merged.
+    TemporaryChange<bool> columnFlowSplitEnabled(gColumnFlowSplitEnabled, false);
+
+    // 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 canMergeAnonymousBlocks = canMergeContiguousAnonymousBlocks(oldChild, prev, next);
+    if (canMergeAnonymousBlocks && prev && next) {
+        prev->setNeedsLayoutAndPrefWidthsRecalc();
+        RenderBlock* nextBlock = toRenderBlock(next);
+        RenderBlock* prevBlock = toRenderBlock(prev);
+       
+        if (prev->childrenInline() != next->childrenInline()) {
+            RenderBlock* inlineChildrenBlock = prev->childrenInline() ? prevBlock : nextBlock;
+            RenderBlock* blockChildrenBlock = prev->childrenInline() ? nextBlock : prevBlock;
+            
+            // Place the inline children block inside of the block children block instead of deleting it.
+            // In order to reuse it, we have to reset it to just be a generic anonymous block.  Make sure
+            // to clear out inherited column properties by just making a new style, and to also clear the
+            // column span flag if it is set.
+            ASSERT(!inlineChildrenBlock->continuation());
+            RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(style(), BLOCK);
+            // Cache this value as it might get changed in setStyle() call.
+            bool inlineChildrenBlockHasLayer = inlineChildrenBlock->hasLayer();
+            inlineChildrenBlock->setStyle(newStyle);
+            children()->removeChildNode(this, inlineChildrenBlock, inlineChildrenBlockHasLayer);
+            
+            // Now just put the inlineChildrenBlock inside the blockChildrenBlock.
+            blockChildrenBlock->children()->insertChildNode(blockChildrenBlock, inlineChildrenBlock, prev == inlineChildrenBlock ? blockChildrenBlock->firstChild() : 0,
+                                                            inlineChildrenBlockHasLayer || blockChildrenBlock->hasLayer());
+            next->setNeedsLayoutAndPrefWidthsRecalc();
+            
+            // inlineChildrenBlock got reparented to blockChildrenBlock, so it is no longer a child
+            // of "this". we null out prev or next so that is not used later in the function.
+            if (inlineChildrenBlock == prevBlock)
+                prev = 0;
+            else
+                next = 0;
+        } else {
+            // Take all the children out of the |next| block and put them in
+            // the |prev| block.
+            nextBlock->moveAllChildrenTo(prevBlock, nextBlock->hasLayer() || prevBlock->hasLayer());        
+            
+            // Delete the now-empty block's lines and nuke it.
+            nextBlock->deleteLineBoxTree();
+            nextBlock->destroy();
+            next = 0;
+        }
+    }
+
+    RenderBox::removeChild(oldChild);
+
+    RenderObject* child = prev ? prev : next;
+    if (canMergeAnonymousBlocks && child && !child->previousSibling() && !child->nextSibling() && canCollapseAnonymousBlockChild()) {
+        // 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.
+        collapseAnonymousBoxChild(this, child);
+    } else if (((prev && prev->isAnonymousBlock()) || (next && next->isAnonymousBlock())) && canCollapseAnonymousBlockChild()) {
+        // It's possible that the removal has knocked us down to a single anonymous
+        // block with pseudo-style element siblings (e.g. first-letter). If these
+        // are floating, then we need to pull the content up also.
+        RenderBlock* anonBlock = toRenderBlock((prev && prev->isAnonymousBlock()) ? prev : next);
+        if ((anonBlock->previousSibling() || anonBlock->nextSibling())
+            && (!anonBlock->previousSibling() || (anonBlock->previousSibling()->style()->styleType() != NOPSEUDO && anonBlock->previousSibling()->isFloating() && !anonBlock->previousSibling()->previousSibling()))
+            && (!anonBlock->nextSibling() || (anonBlock->nextSibling()->style()->styleType() != NOPSEUDO && anonBlock->nextSibling()->isFloating() && !anonBlock->nextSibling()->nextSibling()))) {
+            collapseAnonymousBoxChild(this, anonBlock);
+        }
+    }
+
+    if (!firstChild()) {
+        // If this was our last child be sure to clear out our line boxes.
+        if (childrenInline())
+            deleteLineBoxTree();
+
+        // If we are an empty anonymous block in the continuation chain,
+        // we need to remove ourself and fix the continuation chain.
+        if (!beingDestroyed() && isAnonymousBlockContinuation() && !oldChild->isListMarker()) {
+            RenderObject* containingBlockIgnoringAnonymous = containingBlock();
+            while (containingBlockIgnoringAnonymous && containingBlockIgnoringAnonymous->isAnonymousBlock())
+                containingBlockIgnoringAnonymous = containingBlockIgnoringAnonymous->containingBlock();
+            for (RenderObject* curr = this; curr; curr = curr->previousInPreOrder(containingBlockIgnoringAnonymous)) {
+                if (curr->virtualContinuation() != this)
+                    continue;
+
+                // Found our previous continuation. We just need to point it to
+                // |this|'s next continuation.
+                RenderBoxModelObject* nextContinuation = continuation();
+                if (curr->isRenderInline())
+                    toRenderInline(curr)->setContinuation(nextContinuation);
+                else if (curr->isRenderBlock())
+                    toRenderBlock(curr)->setContinuation(nextContinuation);
+                else
+                    ASSERT_NOT_REACHED();
+
+                break;
+            }
+            setContinuation(0);
+            destroy();
+        }
+    }
+}
+
+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 (logicalHeight() > 0
+        || isTable() || borderAndPaddingLogicalHeight()
+        || style()->logicalMinHeight().isPositive()
+        || style()->marginBeforeCollapse() == MSEPARATE || style()->marginAfterCollapse() == MSEPARATE)
+        return false;
+
+    Length logicalHeightLength = style()->logicalHeight();
+    bool hasAutoHeight = logicalHeightLength.isAuto();
+    if (logicalHeightLength.isPercent() && !document()->inQuirksMode()) {
+        hasAutoHeight = true;
+        for (RenderBlock* cb = containingBlock(); !cb->isRenderView(); cb = cb->containingBlock()) {
+            if (cb->style()->logicalHeight().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 || ((logicalHeightLength.isFixed() || logicalHeightLength.isPercent()) && logicalHeightLength.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 (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
+            if (child->isFloatingOrOutOfFlowPositioned())
+                continue;
+            if (!child->isSelfCollapsingBlock())
+                return false;
+        }
+        return true;
+    }
+    return false;
+}
+
+void RenderBlock::startDelayUpdateScrollInfo()
+{
+    if (gDelayUpdateScrollInfo == 0) {
+        ASSERT(!gDelayedUpdateScrollInfoSet);
+        gDelayedUpdateScrollInfoSet = new DelayedUpdateScrollInfoSet;
+    }
+    ASSERT(gDelayedUpdateScrollInfoSet);
+    ++gDelayUpdateScrollInfo;
+}
+
+void RenderBlock::finishDelayUpdateScrollInfo()
+{
+    --gDelayUpdateScrollInfo;
+    ASSERT(gDelayUpdateScrollInfo >= 0);
+    if (gDelayUpdateScrollInfo == 0) {
+        ASSERT(gDelayedUpdateScrollInfoSet);
+
+        OwnPtr<DelayedUpdateScrollInfoSet> infoSet(adoptPtr(gDelayedUpdateScrollInfoSet));
+        gDelayedUpdateScrollInfoSet = 0;
+
+        for (DelayedUpdateScrollInfoSet::iterator it = infoSet->begin(); it != infoSet->end(); ++it) {
+            RenderBlock* block = *it;
+            if (block->hasOverflowClip()) {
+                block->layer()->updateScrollInfoAfterLayout();
+            }
+        }
+    }
+}
+
+void RenderBlock::updateScrollInfoAfterLayout()
+{
+    if (hasOverflowClip()) {
+        if (style()->isFlippedBlocksWritingMode()) {
+            // FIXME: https://bugs.webkit.org/show_bug.cgi?id=97937
+            // Workaround for now. We cannot delay the scroll info for overflow
+            // for items with opposite writing directions, as the contents needs
+            // to overflow in that direction
+            layer()->updateScrollInfoAfterLayout();
+            return;
+        }
+
+        if (gDelayUpdateScrollInfo)
+            gDelayedUpdateScrollInfoSet->add(this);
+        else
+            layer()->updateScrollInfoAfterLayout();
+    }
+}
+
+void RenderBlock::layout()
+{
+    StackStats::LayoutCheckPoint layoutCheckPoint;
+    OverflowEventDispatcher dispatcher(this);
+
+    // 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 we have a lightweight clip, there can never be any overflow from children.
+    if (hasControlClip() && m_overflow)
+        clearLayoutOverflow();
+
+    invalidateBackgroundObscurationStatus();
+}
+
+void RenderBlock::updateExclusionShapeInsideInfoAfterStyleChange(const ExclusionShapeValue* shapeInside, const ExclusionShapeValue* oldShapeInside)
+{
+    // FIXME: A future optimization would do a deep comparison for equality.
+    if (shapeInside == oldShapeInside)
+        return;
+
+    if (shapeInside) {
+        ExclusionShapeInsideInfo* exclusionShapeInsideInfo = ensureExclusionShapeInsideInfo();
+        exclusionShapeInsideInfo->dirtyShapeSize();
+    } else
+        setExclusionShapeInsideInfo(nullptr);
+}
+
+static inline bool exclusionInfoRequiresRelayout(const RenderBlock* block)
+{
+    ExclusionShapeInsideInfo* info = block->exclusionShapeInsideInfo();
+    if (info)
+        info->setNeedsLayout(info->shapeSizeDirty());
+    else
+        info = block->layoutExclusionShapeInsideInfo();
+    return info && info->needsLayout();
+}
+
+bool RenderBlock::updateRegionsAndExclusionsLogicalSize(RenderFlowThread* flowThread)
+{
+    if (!flowThread && !exclusionShapeInsideInfo())
+        return exclusionInfoRequiresRelayout(this);
+
+    LayoutUnit oldHeight = logicalHeight();
+    LayoutUnit oldTop = logicalTop();
+
+    // Compute the maximum logical height content may cause this block to expand to
+    // FIXME: These should eventually use the const computeLogicalHeight rather than updateLogicalHeight
+    setLogicalHeight(LayoutUnit::max() / 2);
+    updateLogicalHeight();
+
+    computeExclusionShapeSize();
+
+    // Set our start and end regions. No regions above or below us will be considered by our children. They are
+    // effectively clamped to our region range.
+    computeRegionRangeForBlock(flowThread);
+
+    setLogicalHeight(oldHeight);
+    setLogicalTop(oldTop);
+    
+    return exclusionInfoRequiresRelayout(this);
+}
+
+void RenderBlock::computeExclusionShapeSize()
+{
+    ExclusionShapeInsideInfo* exclusionShapeInsideInfo = this->exclusionShapeInsideInfo();
+    if (exclusionShapeInsideInfo) {
+        bool percentageLogicalHeightResolvable = percentageLogicalHeightIsResolvableFromBlock(this, false);
+        exclusionShapeInsideInfo->setShapeSize(logicalWidth(), percentageLogicalHeightResolvable ? logicalHeight() : LayoutUnit());
+    }
+}
+
+void RenderBlock::computeRegionRangeForBlock(RenderFlowThread* flowThread)
+{
+    if (flowThread)
+        flowThread->setRegionRangeForBox(this, offsetFromLogicalTopOfFirstPage());
+}
+
+bool RenderBlock::updateLogicalWidthAndColumnWidth()
+{
+    LayoutUnit oldWidth = logicalWidth();
+    LayoutUnit oldColumnWidth = desiredColumnWidth();
+
+    updateLogicalWidth();
+    calcColumnWidth();
+
+    bool hasBorderOrPaddingLogicalWidthChanged = m_hasBorderOrPaddingLogicalWidthChanged;
+    m_hasBorderOrPaddingLogicalWidthChanged = false;
+
+    return oldWidth != logicalWidth() || oldColumnWidth != desiredColumnWidth() || hasBorderOrPaddingLogicalWidthChanged;
+}
+
+void RenderBlock::checkForPaginationLogicalHeightChange(LayoutUnit& pageLogicalHeight, bool& pageLogicalHeightChanged, bool& hasSpecifiedPageLogicalHeight)
+{
+    ColumnInfo* colInfo = columnInfo();
+    if (hasColumns()) {
+        if (!pageLogicalHeight) {
+            // We need to go ahead and set our explicit page height if one exists, so that we can
+            // avoid doing two layout passes.
+            updateLogicalHeight();
+            LayoutUnit columnHeight = contentLogicalHeight();
+            if (columnHeight > 0) {
+                pageLogicalHeight = columnHeight;
+                hasSpecifiedPageLogicalHeight = true;
+            }
+            setLogicalHeight(0);
+        }
+        if (colInfo->columnHeight() != pageLogicalHeight && everHadLayout()) {
+            colInfo->setColumnHeight(pageLogicalHeight);
+            pageLogicalHeightChanged = true;
+        }
+        
+        if (!hasSpecifiedPageLogicalHeight && !pageLogicalHeight)
+            colInfo->clearForcedBreaks();
+
+        colInfo->setPaginationUnit(paginationUnit());
+    } else if (isRenderFlowThread()) {
+        pageLogicalHeight = 1; // This is just a hack to always make sure we have a page logical height.
+        pageLogicalHeightChanged = toRenderFlowThread(this)->pageLogicalSizeChanged();
+    }
+}
+
+void RenderBlock::layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeight)
+{
+    ASSERT(needsLayout());
+
+    if (isInline() && !isInlineBlockOrInlineTable()) // Inline <form>s inside various table elements can
+        return;                                      // cause us to come in here.  Just bail.
+
+    if (!relayoutChildren && simplifiedLayout())
+        return;
+
+    LayoutRepainter repainter(*this, checkForRepaintDuringLayout());
+
+    if (updateLogicalWidthAndColumnWidth())
+        relayoutChildren = true;
+
+    clearFloats();
+
+    LayoutUnit previousHeight = logicalHeight();
+    // FIXME: should this start out as borderAndPaddingLogicalHeight() + scrollbarLogicalHeight(),
+    // for consistency with other render classes?
+    setLogicalHeight(0);
+
+    bool pageLogicalHeightChanged = false;
+    bool hasSpecifiedPageLogicalHeight = false;
+    checkForPaginationLogicalHeightChange(pageLogicalHeight, pageLogicalHeightChanged, hasSpecifiedPageLogicalHeight);
+
+    RenderView* renderView = view();
+    RenderStyle* styleToUse = style();
+    LayoutStateMaintainer statePusher(renderView, this, locationOffset(), hasColumns() || hasTransform() || hasReflection() || styleToUse->isFlippedBlocksWritingMode(), pageLogicalHeight, pageLogicalHeightChanged, columnInfo());
+
+    // Regions changing widths can force us to relayout our children.
+    RenderFlowThread* flowThread = flowThreadContainingBlock();
+    if (logicalWidthChangedInRegions(flowThread))
+        relayoutChildren = true;
+    if (updateRegionsAndExclusionsLogicalSize(flowThread))
+        relayoutChildren = true;
+
+    // We use four values, maxTopPos, maxTopNeg, 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();
+        
+        setHasMarginBeforeQuirk(styleToUse->hasMarginBeforeQuirk());
+        setHasMarginAfterQuirk(styleToUse->hasMarginAfterQuirk());
+        setPaginationStrut(0);
+    }
+
+    LayoutUnit repaintLogicalTop = 0;
+    LayoutUnit repaintLogicalBottom = 0;
+    LayoutUnit maxFloatLogicalBottom = 0;
+    if (!firstChild() && !isAnonymousBlock())
+        setChildrenInline(true);
+    if (childrenInline())
+        layoutInlineChildren(relayoutChildren, repaintLogicalTop, repaintLogicalBottom);
+    else
+        layoutBlockChildren(relayoutChildren, maxFloatLogicalBottom);
+
+    // Expand our intrinsic height to encompass floats.
+    LayoutUnit toAdd = borderAfter() + paddingAfter() + scrollbarLogicalHeight();
+    if (lowestFloatLogicalBottom() > (logicalHeight() - toAdd) && expandsToEncloseOverhangingFloats())
+        setLogicalHeight(lowestFloatLogicalBottom() + toAdd);
+    
+    if (relayoutForPagination(hasSpecifiedPageLogicalHeight, pageLogicalHeight, statePusher))
+        return;
+
+    // Calculate our new height.
+    LayoutUnit oldHeight = logicalHeight();
+    LayoutUnit oldClientAfterEdge = clientLogicalBottom();
+
+    // Before updating the final size of the flow thread make sure a forced break is applied after the content.
+    // This ensures the size information is correctly computed for the last auto-height region receiving content.
+    if (isRenderFlowThread())
+        toRenderFlowThread(this)->applyBreakAfterContent(oldClientAfterEdge);
+
+    updateLogicalHeight();
+    LayoutUnit newHeight = logicalHeight();
+    if (oldHeight != newHeight) {
+        if (oldHeight > newHeight && maxFloatLogicalBottom > newHeight && !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->isFloatingOrOutOfFlowPositioned()) {
+                    RenderBlock* block = toRenderBlock(child);
+                    if (block->lowestFloatLogicalBottom() + block->logicalTop() > newHeight)
+                        addOverhangingFloats(block, false);
+                }
+            }
+        }
+    }
+
+    if (previousHeight != newHeight)
+        relayoutChildren = true;
+
+    layoutPositionedObjects(relayoutChildren || isRoot());
+
+    computeRegionRangeForBlock(flowThread);
+
+    // Add overflow from children (unless we're multi-column, since in that case all our child overflow is clipped anyway).
+    computeOverflow(oldClientAfterEdge);
+    
+    statePusher.pop();
+
+    fitBorderToLinesIfNeeded();
+
+    if (renderView->layoutState()->m_pageLogicalHeight)
+        setPageLogicalOffset(renderView->layoutState()->pageLogicalOffset(this, logicalTop()));
+
+    updateLayerTransform();
+
+    // Update our scroll information if we're overflow:auto/scroll/hidden now that we know if
+    // we overflow or not.
+    updateScrollInfoAfterLayout();
+
+    // FIXME: This repaint logic should be moved into a separate helper function!
+    // Repaint with our new bounds if they are different from our old bounds.
+    bool didFullRepaint = repainter.repaintAfterLayout();
+    if (!didFullRepaint && repaintLogicalTop != repaintLogicalBottom && (styleToUse->visibility() == VISIBLE || enclosingLayer()->hasVisibleContent())) {
+        // FIXME: We could tighten up the left and right invalidation points if we let layoutInlineChildren fill them in based off the particular lines
+        // it had to lay out.  We wouldn't need the hasOverflowClip() hack in that case either.
+        LayoutUnit repaintLogicalLeft = logicalLeftVisualOverflow();
+        LayoutUnit repaintLogicalRight = logicalRightVisualOverflow();
+        if (hasOverflowClip()) {
+            // If we have clipped overflow, we should use layout overflow as well, since visual overflow from lines didn't propagate to our block's overflow.
+            // Note the old code did this as well but even for overflow:visible.  The addition of hasOverflowClip() at least tightens up the hack a bit.
+            // layoutInlineChildren should be patched to compute the entire repaint rect.
+            repaintLogicalLeft = min(repaintLogicalLeft, logicalLeftLayoutOverflow());
+            repaintLogicalRight = max(repaintLogicalRight, logicalRightLayoutOverflow());
+        }
+        
+        LayoutRect repaintRect;
+        if (isHorizontalWritingMode())
+            repaintRect = LayoutRect(repaintLogicalLeft, repaintLogicalTop, repaintLogicalRight - repaintLogicalLeft, repaintLogicalBottom - repaintLogicalTop);
+        else
+            repaintRect = LayoutRect(repaintLogicalTop, repaintLogicalLeft, repaintLogicalBottom - repaintLogicalTop, repaintLogicalRight - repaintLogicalLeft);
+
+        // The repaint rect may be split across columns, in which case adjustRectForColumns() will return the union.
+        adjustRectForColumns(repaintRect);
+
+        repaintRect.inflate(maximalOutlineSize(PaintPhaseOutline));
+        
+        if (hasOverflowClip()) {
+            // Adjust repaint rect for scroll offset
+            repaintRect.move(-scrolledContentOffset());
+
+            // Don't allow this rect to spill out of our overflow box.
+            repaintRect.intersect(LayoutRect(LayoutPoint(), size()));
+        }
+
+        // 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())
+                repaintRectangle(reflectedRect(repaintRect));
+        }
+    }
+
+    setNeedsLayout(false);
+}
+
+void RenderBlock::addOverflowFromChildren()
+{
+    if (!hasColumns()) {
+        if (childrenInline())
+            addOverflowFromInlineChildren();
+        else
+            addOverflowFromBlockChildren();
+    } else {
+        ColumnInfo* colInfo = columnInfo();
+        if (columnCount(colInfo)) {
+            LayoutRect lastRect = columnRectAt(colInfo, columnCount(colInfo) - 1);
+            addLayoutOverflow(lastRect);
+            if (!hasOverflowClip())
+                addVisualOverflow(lastRect);
+        }
+    }
+}
+
+void RenderBlock::computeOverflow(LayoutUnit oldClientAfterEdge, bool recomputeFloats)
+{
+    m_overflow.clear();
+
+    // Add overflow from children.
+    addOverflowFromChildren();
+
+    if (!hasColumns() && (recomputeFloats || isRoot() || expandsToEncloseOverhangingFloats() || hasSelfPaintingLayer()))
+        addOverflowFromFloats();
+
+    // Add in the overflow from positioned objects.
+    addOverflowFromPositionedObjects();
+
+    if (hasOverflowClip()) {
+        // When we have overflow clip, propagate the original spillout since it will include collapsed bottom margins
+        // and bottom padding.  Set the axis we don't care about to be 1, since we want this overflow to always
+        // be considered reachable.
+        LayoutRect clientRect(clientBoxRect());
+        LayoutRect rectToApply;
+        if (isHorizontalWritingMode())
+            rectToApply = LayoutRect(clientRect.x(), clientRect.y(), 1, max<LayoutUnit>(0, oldClientAfterEdge - clientRect.y()));
+        else
+            rectToApply = LayoutRect(clientRect.x(), clientRect.y(), max<LayoutUnit>(0, oldClientAfterEdge - clientRect.x()), 1);
+        addLayoutOverflow(rectToApply);
+        if (hasRenderOverflow())
+            m_overflow->setLayoutClientAfterEdge(oldClientAfterEdge);
+    }
+        
+    // Allow our overflow to catch cases where the caret in an empty editable element with negative text indent needs to get painted.
+    LayoutUnit textIndent = textIndentOffset();
+    if (textIndent < 0) {
+        LayoutRect clientRect(clientBoxRect());
+        LayoutRect rectToApply = LayoutRect(clientRect.x() + min<LayoutUnit>(0, textIndent), clientRect.y(), clientRect.width() - min<LayoutUnit>(0, textIndent), clientRect.height());
+        addVisualOverflow(rectToApply);
+    }
+
+    // Add visual overflow from box-shadow and border-image-outset.
+    addVisualEffectOverflow();
+
+    // Add visual overflow from theme.
+    addVisualOverflowFromTheme();
+
+    if (isRenderFlowThread())
+        toRenderFlowThread(this)->computeOverflowStateForRegions(oldClientAfterEdge);
+}
+
+void RenderBlock::addOverflowFromBlockChildren()
+{
+    for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
+        if (!child->isFloatingOrOutOfFlowPositioned())
+            addOverflowFromChild(child);
+    }
+}
+
+void RenderBlock::addOverflowFromFloats()
+{
+    if (!m_floatingObjects)
+        return;
+
+    const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
+    FloatingObjectSetIterator end = floatingObjectSet.end();
+    for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
+        FloatingObject* r = *it;
+        if (r->isDescendant())
+            addOverflowFromChild(r->m_renderer, IntSize(xPositionForFloatIncludingMargin(r), yPositionForFloatIncludingMargin(r)));
+    }
+}
+
+void RenderBlock::addOverflowFromPositionedObjects()
+{
+    TrackedRendererListHashSet* positionedDescendants = positionedObjects();
+    if (!positionedDescendants)
+        return;
+
+    RenderBox* positionedObject;
+    TrackedRendererListHashSet::iterator end = positionedDescendants->end();
+    for (TrackedRendererListHashSet::iterator it = positionedDescendants->begin(); it != end; ++it) {
+        positionedObject = *it;
+        
+        // Fixed positioned elements don't contribute to layout overflow, since they don't scroll with the content.
+        if (positionedObject->style()->position() != FixedPosition) {
+            LayoutUnit x = positionedObject->x();
+            if (style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft())
+                x -= verticalScrollbarWidth();
+            addOverflowFromChild(positionedObject, LayoutSize(x, positionedObject->y()));
+        }
+    }
+}
+
+void RenderBlock::addVisualOverflowFromTheme()
+{
+    if (!style()->hasAppearance())
+        return;
+
+    IntRect inflatedRect = pixelSnappedBorderBoxRect();
+    theme()->adjustRepaintRect(this, inflatedRect);
+    addVisualOverflow(inflatedRect);
+}
+
+bool RenderBlock::expandsToEncloseOverhangingFloats() const
+{
+    return isInlineBlockOrInlineTable() || isFloatingOrOutOfFlowPositioned() || hasOverflowClip() || (parent() && parent()->isFlexibleBoxIncludingDeprecated())
+           || hasColumns() || isTableCell() || isTableCaption() || isFieldset() || isWritingModeRoot() || isRoot();
+}
+
+void RenderBlock::adjustPositionedBlock(RenderBox* child, const MarginInfo& marginInfo)
+{
+    bool isHorizontal = isHorizontalWritingMode();
+    bool hasStaticBlockPosition = child->style()->hasStaticBlockPosition(isHorizontal);
+    
+    LayoutUnit logicalTop = logicalHeight();
+    updateStaticInlinePositionForChild(child, logicalTop);
+
+    if (!marginInfo.canCollapseWithMarginBefore()) {
+        // Positioned blocks don't collapse margins, so add the margin provided by
+        // the container now. The child's own margin is added later when calculating its logical top.
+        LayoutUnit collapsedBeforePos = marginInfo.positiveMargin();
+        LayoutUnit collapsedBeforeNeg = marginInfo.negativeMargin();
+        logicalTop += collapsedBeforePos - collapsedBeforeNeg;
+    }
+    
+    RenderLayer* childLayer = child->layer();
+    if (childLayer->staticBlockPosition() != logicalTop) {
+        childLayer->setStaticBlockPosition(logicalTop);
+        if (hasStaticBlockPosition)
+            child->setChildNeedsLayout(true, MarkOnlyThis);
+    }
+}
+
+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 canCollapseWithMarginBefore.  See
+    // http://www.hixie.ch/tests/adhoc/css/box/block/margin-collapse/046.html for
+    // an example of this scenario.
+    LayoutUnit marginOffset = marginInfo.canCollapseWithMarginBefore() ? LayoutUnit() : marginInfo.margin();
+    setLogicalHeight(logicalHeight() + marginOffset);
+    positionNewFloats();
+    setLogicalHeight(logicalHeight() - marginOffset);
+}
+
+static void destroyRunIn(RenderBoxModelObject* runIn)
+{
+    ASSERT(runIn->isRunIn());
+    ASSERT(!runIn->firstChild());
+
+    // Delete our line box tree. This is needed as our children got moved
+    // and our line box tree is no longer valid.
+    if (runIn->isRenderBlock())
+        toRenderBlock(runIn)->deleteLineBoxTree();
+    else if (runIn->isRenderInline())
+        toRenderInline(runIn)->deleteLineBoxTree();
+    else
+        ASSERT_NOT_REACHED();
+
+    runIn->destroy();
+}
+
+void RenderBlock::placeRunInIfNeeded(RenderObject* newChild)
+{
+    if (newChild->isRunIn())
+        moveRunInUnderSiblingBlockIfNeeded(newChild);
+    else if (RenderObject* prevSibling = newChild->previousSibling()) {
+        if (prevSibling->isRunIn())
+            moveRunInUnderSiblingBlockIfNeeded(prevSibling);
+    }
+}
+
+RenderBoxModelObject* RenderBlock::createReplacementRunIn(RenderBoxModelObject* runIn)
+{
+    ASSERT(runIn->isRunIn());
+    ASSERT(runIn->node());
+
+    RenderBoxModelObject* newRunIn = 0;
+    if (!runIn->isRenderBlock())
+        newRunIn = new (renderArena()) RenderBlock(runIn->node());
+    else
+        newRunIn = new (renderArena()) RenderInline(toElement(runIn->node()));
+
+    runIn->node()->setRenderer(newRunIn);
+    newRunIn->setStyle(runIn->style());
+
+    runIn->moveAllChildrenTo(newRunIn, true);
+
+    return newRunIn;
+}
+
+void RenderBlock::moveRunInUnderSiblingBlockIfNeeded(RenderObject* runIn)
+{
+    ASSERT(runIn->isRunIn());
+
+    // See if we have inline children. If the children aren't inline,
+    // then just treat the run-in as a normal block.
+    if (!runIn->childrenInline())
+        return;
+
+    // FIXME: We don't handle non-block elements with run-in for now.
+    if (!runIn->isRenderBlock())
+        return;
+
+    // FIXME: We don't support run-ins with or as part of a continuation
+    // as it makes the back-and-forth placing complex.
+    if (runIn->isElementContinuation() || runIn->virtualContinuation())
+        return;
+
+    // Check if this node is allowed to run-in. E.g. <select> expects its renderer to
+    // be a RenderListBox or RenderMenuList, and hence cannot be a RenderInline run-in.
+    if (!runIn->canBeReplacedWithInlineRunIn())
+        return;
+
+    RenderObject* curr = runIn->nextSibling();
+    if (!curr || !curr->isRenderBlock() || !curr->childrenInline())
+        return;
+
+    // Per CSS3, "A run-in cannot run in to a block that already starts with a
+    // run-in or that itself is a run-in".
+    if (curr->isRunIn() || (curr->firstChild() && curr->firstChild()->isRunIn()))
+        return;
+
+    if (curr->isAnonymous() || curr->isFloatingOrOutOfFlowPositioned())
+        return;
+
+    // FIXME: We don't support run-ins with or as part of a continuation
+    // as it makes the back-and-forth placing complex.
+    if (curr->isElementContinuation() || curr->virtualContinuation())
+        return;
+
+    RenderBoxModelObject* oldRunIn = toRenderBoxModelObject(runIn);
+    RenderBoxModelObject* newRunIn = createReplacementRunIn(oldRunIn);
+    destroyRunIn(oldRunIn);
+
+    // Now insert the new child under |curr| block. Use addChild instead of insertChildNode
+    // since it handles correct placement of the children, especially where we cannot insert
+    // anything before the first child. e.g. details tag. See https://bugs.webkit.org/show_bug.cgi?id=58228.
+    curr->addChild(newRunIn, curr->firstChild());
+
+    // Make sure that |this| get a layout since its run-in child moved.
+    curr->setNeedsLayoutAndPrefWidthsRecalc();
+}
+
+bool RenderBlock::runInIsPlacedIntoSiblingBlock(RenderObject* runIn)
+{
+    ASSERT(runIn->isRunIn());
+
+    // If we don't have a parent, we can't be moved into our sibling block.
+    if (!parent())
+        return false;
+
+    // An intruded run-in needs to be an inline.
+    if (!runIn->isRenderInline())
+        return false;
+
+    return true;
+}
+
+void RenderBlock::moveRunInToOriginalPosition(RenderObject* runIn)
+{
+    ASSERT(runIn->isRunIn());
+
+    if (!runInIsPlacedIntoSiblingBlock(runIn))
+        return;
+
+    // FIXME: Run-in that are now placed in sibling block can break up into continuation
+    // chains when new children are added to it. We cannot easily send them back to their
+    // original place since that requires writing integration logic with RenderInline::addChild
+    // and all other places that might cause continuations to be created (without blowing away
+    // |this|). Disabling this feature for now to prevent crashes.
+    if (runIn->isElementContinuation() || runIn->virtualContinuation())
+        return;
+
+    RenderBoxModelObject* oldRunIn = toRenderBoxModelObject(runIn);
+    RenderBoxModelObject* newRunIn = createReplacementRunIn(oldRunIn);
+    destroyRunIn(oldRunIn);
+
+    // Add the run-in block as our previous sibling.
+    parent()->addChild(newRunIn, this);
+
+    // Make sure that the parent holding the new run-in gets layout.
+    parent()->setNeedsLayoutAndPrefWidthsRecalc();
+}
+
+LayoutUnit RenderBlock::collapseMargins(RenderBox* child, MarginInfo& marginInfo)
+{
+    bool childDiscardMarginBefore = mustDiscardMarginBeforeForChild(child);
+    bool childDiscardMarginAfter = mustDiscardMarginAfterForChild(child);
+    bool childIsSelfCollapsing = child->isSelfCollapsingBlock();
+
+    // The child discards the before margin when the the after margin has discard in the case of a self collapsing block.
+    childDiscardMarginBefore = childDiscardMarginBefore || (childDiscardMarginAfter && childIsSelfCollapsing);
+
+    // Get the four margin values for the child and cache them.
+    const MarginValues childMargins = marginValuesForChild(child);
+
+    // Get our max pos and neg top margins.
+    LayoutUnit posTop = childMargins.positiveMarginBefore();
+    LayoutUnit negTop = childMargins.negativeMarginBefore();
+
+    // For self-collapsing blocks, collapse our bottom margins into our
+    // top to get new posTop and negTop values.
+    if (childIsSelfCollapsing) {
+        posTop = max(posTop, childMargins.positiveMarginAfter());
+        negTop = max(negTop, childMargins.negativeMarginAfter());
+    }
+    
+    // See if the top margin is quirky. We only care if this child has
+    // margins that will collapse with us.
+    bool topQuirk = hasMarginBeforeQuirk(child);
+
+    if (marginInfo.canCollapseWithMarginBefore()) {
+        if (!childDiscardMarginBefore && !marginInfo.discardMargin()) {
+            // 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 (!document()->inQuirksMode() || !marginInfo.quirkContainer() || !topQuirk)
+                setMaxMarginBeforeValues(max(posTop, maxPositiveMarginBefore()), max(negTop, maxNegativeMarginBefore()));
+
+            // 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.determinedMarginBeforeQuirk() && !topQuirk && (posTop - negTop)) {
+                setHasMarginBeforeQuirk(false);
+                marginInfo.setDeterminedMarginBeforeQuirk(true);
+            }
+
+            if (!marginInfo.determinedMarginBeforeQuirk() && topQuirk && !marginBefore())
+                // 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.
+                setHasMarginBeforeQuirk(true);
+        } else
+            // The before margin of the container will also discard all the margins it is collapsing with.
+            setMustDiscardMarginBefore();
+    }
+
+    // Once we find a child with discardMarginBefore all the margins collapsing with us must also discard. 
+    if (childDiscardMarginBefore) {
+        marginInfo.setDiscardMargin(true);
+        marginInfo.clearMargin();
+    }
+
+    if (marginInfo.quirkContainer() && marginInfo.atBeforeSideOfBlock() && (posTop - negTop))
+        marginInfo.setHasMarginBeforeQuirk(topQuirk);
+
+    LayoutUnit beforeCollapseLogicalTop = logicalHeight();
+    LayoutUnit logicalTop = beforeCollapseLogicalTop;
+    if (childIsSelfCollapsing) {
+        // For a self collapsing block both the before and after margins get discarded. The block doesn't contribute anything to the height of the block.
+        // Also, the child's top position equals the logical height of the container.
+        if (!childDiscardMarginBefore && !marginInfo.discardMargin()) {
+            // 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.
+            LayoutUnit collapsedBeforePos = max(marginInfo.positiveMargin(), childMargins.positiveMarginBefore());
+            LayoutUnit collapsedBeforeNeg = max(marginInfo.negativeMargin(), childMargins.negativeMarginBefore());
+            marginInfo.setMargin(collapsedBeforePos, collapsedBeforeNeg);
+            
+            // Now collapse the child's margins together, which means examining our
+            // bottom margin values as well. 
+            marginInfo.setPositiveMarginIfLarger(childMargins.positiveMarginAfter());
+            marginInfo.setNegativeMarginIfLarger(childMargins.negativeMarginAfter());
+
+            if (!marginInfo.canCollapseWithMarginBefore())
+                // 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).
+                logicalTop = logicalHeight() + collapsedBeforePos - collapsedBeforeNeg;
+        }
+    } else {
+        if (mustSeparateMarginBeforeForChild(child)) {
+            ASSERT(!marginInfo.discardMargin() || (marginInfo.discardMargin() && !marginInfo.margin()));
+            // If we are at the before side of the block and we collapse, ignore the computed margin
+            // and just add the child margin to the container height. This will correctly position
+            // the child inside the container.
+            LayoutUnit separateMargin = !marginInfo.canCollapseWithMarginBefore() ? marginInfo.margin() : LayoutUnit(0);
+            setLogicalHeight(logicalHeight() + separateMargin + marginBeforeForChild(child));
+            logicalTop = logicalHeight();
+        } else if (!marginInfo.discardMargin() && (!marginInfo.atBeforeSideOfBlock()
+            || (!marginInfo.canCollapseMarginBeforeWithChildren()
+            && (!document()->inQuirksMode() || !marginInfo.quirkContainer() || !marginInfo.hasMarginBeforeQuirk())))) {
+            // We're collapsing with a previous sibling's margins and not
+            // with the top of the block.
+            setLogicalHeight(logicalHeight() + max(marginInfo.positiveMargin(), posTop) - max(marginInfo.negativeMargin(), negTop));
+            logicalTop = logicalHeight();
+        }
+
+        marginInfo.setDiscardMargin(childDiscardMarginAfter);
+        
+        if (!marginInfo.discardMargin()) {
+            marginInfo.setPositiveMargin(childMargins.positiveMarginAfter());
+            marginInfo.setNegativeMargin(childMargins.negativeMarginAfter());
+        } else
+            marginInfo.clearMargin();
+
+        if (marginInfo.margin())
+            marginInfo.setHasMarginAfterQuirk(hasMarginAfterQuirk(child));
+    }
+    
+    // If margins would pull us past the top of the next page, then we need to pull back and pretend like the margins
+    // collapsed into the page edge.
+    LayoutState* layoutState = view()->layoutState();
+    if (layoutState->isPaginated() && layoutState->pageLogicalHeight() && logicalTop > beforeCollapseLogicalTop
+        && hasNextPage(beforeCollapseLogicalTop)) {
+        LayoutUnit oldLogicalTop = logicalTop;
+        logicalTop = min(logicalTop, nextPageLogicalTop(beforeCollapseLogicalTop));
+        setLogicalHeight(logicalHeight() + (logicalTop - oldLogicalTop));
+    }
+
+    // If we have collapsed into a previous sibling and so reduced the height of the parent, ensure any floats that now
+    // overhang from the previous sibling are added to our parent. If the child's previous sibling itself is a float the child will avoid
+    // or clear it anyway, so don't worry about any floating children it may contain.
+    LayoutUnit oldLogicalHeight = logicalHeight();
+    setLogicalHeight(logicalTop);
+    RenderObject* prev = child->previousSibling();
+    if (prev && prev->isBlockFlow() && !prev->isFloatingOrOutOfFlowPositioned()) {
+        RenderBlock* block = toRenderBlock(prev);
+        if (block->containsFloats() && !block->avoidsFloats() && (block->logicalTop() + block->lowestFloatLogicalBottom()) > logicalTop) 
+            addOverhangingFloats(block, false);
+    }
+    setLogicalHeight(oldLogicalHeight);
+
+    return logicalTop;
+}
+
+LayoutUnit RenderBlock::clearFloatsIfNeeded(RenderBox* child, MarginInfo& marginInfo, LayoutUnit oldTopPosMargin, LayoutUnit oldTopNegMargin, LayoutUnit yPos)
+{
+    LayoutUnit heightIncrease = getClearDelta(child, yPos);
+    if (!heightIncrease)
+        return yPos;
+
+    if (child->isSelfCollapsingBlock()) {
+        bool childDiscardMargin = mustDiscardMarginBeforeForChild(child) || mustDiscardMarginAfterForChild(child);
+
+        // 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.
+        // If DISCARD is specified for -webkit-margin-collapse, reset the margin values.
+        if (!childDiscardMargin) {
+            MarginValues childMargins = marginValuesForChild(child);
+            marginInfo.setPositiveMargin(max(childMargins.positiveMarginBefore(), childMargins.positiveMarginAfter()));
+            marginInfo.setNegativeMargin(max(childMargins.negativeMarginBefore(), childMargins.negativeMarginAfter()));
+        } else
+            marginInfo.clearMargin();
+        marginInfo.setDiscardMargin(childDiscardMargin);
+
+        // CSS2.1 states:
+        // "If the top and bottom margins of an element with clearance are adjoining, its margins collapse with 
+        // the adjoining margins of following siblings but that resulting margin does not collapse with the bottom margin of the parent block."
+        // So the parent's bottom margin cannot collapse through this block or any subsequent self-collapsing blocks. Check subsequent siblings
+        // for a block with height - if none is found then don't allow the margins to collapse with the parent.
+        bool wouldCollapseMarginsWithParent = marginInfo.canCollapseMarginAfterWithChildren();
+        for (RenderBox* curr = child->nextSiblingBox(); curr && wouldCollapseMarginsWithParent; curr = curr->nextSiblingBox()) {
+            if (!curr->isFloatingOrOutOfFlowPositioned() && !curr->isSelfCollapsingBlock())
+                wouldCollapseMarginsWithParent = false;
+        }
+        if (wouldCollapseMarginsWithParent)
+            marginInfo.setCanCollapseMarginAfterWithChildren(false);
+
+        // CSS2.1: "the amount of clearance is set so that clearance + margin-top = [height of float], i.e., clearance = [height of float] - margin-top"
+        // Move the top of the child box to the bottom of the float ignoring the child's top margin.
+        LayoutUnit collapsedMargin = collapsedMarginBeforeForChild(child);
+        setLogicalHeight(child->logicalTop() - collapsedMargin);
+        // A negative collapsed margin-top value cancels itself out as it has already been factored into |yPos| above.
+        heightIncrease -= max(LayoutUnit(), collapsedMargin);
+    } else
+        // Increase our height by the amount we had to clear.
+        setLogicalHeight(logicalHeight() + heightIncrease);
+    
+    if (marginInfo.canCollapseWithMarginBefore()) {
+        // 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.
+        setMaxMarginBeforeValues(oldTopPosMargin, oldTopNegMargin);
+        marginInfo.setAtBeforeSideOfBlock(false);
+
+        // In case the child discarded the before margin of the block we need to reset the mustDiscardMarginBefore flag to the initial value.
+        setMustDiscardMarginBefore(style()->marginBeforeCollapse() == MDISCARD);
+    }
+
+    LayoutUnit logicalTop = yPos + heightIncrease;
+    // After margin collapsing, one of our floats may now intrude into the child. If the child doesn't contain floats of its own it
+    // won't get picked up for relayout even though the logical top estimate was wrong - so add the newly intruding float now.
+    if (containsFloats() && child->isRenderBlock() && !toRenderBlock(child)->containsFloats() && !child->avoidsFloats() && lowestFloatLogicalBottom() > logicalTop)
+        toRenderBlock(child)->addIntrudingFloats(this, logicalLeftOffsetForContent(), logicalTop);
+
+    return logicalTop;
+}
+
+void RenderBlock::marginBeforeEstimateForChild(RenderBox* child, LayoutUnit& positiveMarginBefore, LayoutUnit& negativeMarginBefore, bool& discardMarginBefore) const
+{
+    // Give up if in quirks mode and we're a body/table cell and the top margin of the child box is quirky.
+    // Give up if the child specified -webkit-margin-collapse: separate that prevents collapsing.
+    // FIXME: Use writing mode independent accessor for marginBeforeCollapse.
+    if ((document()->inQuirksMode() && hasMarginAfterQuirk(child) && (isTableCell() || isBody())) || child->style()->marginBeforeCollapse() == MSEPARATE)
+        return;
+
+    // The margins are discarded by a child that specified -webkit-margin-collapse: discard.
+    // FIXME: Use writing mode independent accessor for marginBeforeCollapse.
+    if (child->style()->marginBeforeCollapse() == MDISCARD) {
+        positiveMarginBefore = 0;
+        negativeMarginBefore = 0;
+        discardMarginBefore = true;
+        return;
+    }
+
+    LayoutUnit beforeChildMargin = marginBeforeForChild(child);
+    positiveMarginBefore = max(positiveMarginBefore, beforeChildMargin);
+    negativeMarginBefore = max(negativeMarginBefore, -beforeChildMargin);
+
+    if (!child->isRenderBlock())
+        return;
+    
+    RenderBlock* childBlock = toRenderBlock(child);
+    if (childBlock->childrenInline() || childBlock->isWritingModeRoot())
+        return;
+
+    MarginInfo childMarginInfo(childBlock, childBlock->borderBefore() + childBlock->paddingBefore(), childBlock->borderAfter() + childBlock->paddingAfter());
+    if (!childMarginInfo.canCollapseMarginBeforeWithChildren())
+        return;
+
+    RenderBox* grandchildBox = childBlock->firstChildBox();
+    for ( ; grandchildBox; grandchildBox = grandchildBox->nextSiblingBox()) {
+        if (!grandchildBox->isFloatingOrOutOfFlowPositioned())
+            break;
+    }
+    
+    // Give up if there is clearance on the box, since it probably won't collapse into us.
+    if (!grandchildBox || grandchildBox->style()->clear() != CNONE)
+        return;
+
+    // Make sure to update the block margins now for the grandchild box so that we're looking at current values.
+    if (grandchildBox->needsLayout()) {
+        grandchildBox->computeAndSetBlockDirectionMargins(this);
+        if (grandchildBox->isRenderBlock()) {
+            RenderBlock* grandchildBlock = toRenderBlock(grandchildBox);
+            grandchildBlock->setHasMarginBeforeQuirk(grandchildBox->style()->hasMarginBeforeQuirk());
+            grandchildBlock->setHasMarginAfterQuirk(grandchildBox->style()->hasMarginAfterQuirk());
+        }
+    }
+
+    // Collapse the margin of the grandchild box with our own to produce an estimate.
+    childBlock->marginBeforeEstimateForChild(grandchildBox, positiveMarginBefore, negativeMarginBefore, discardMarginBefore);
+}
+
+LayoutUnit RenderBlock::estimateLogicalTopPosition(RenderBox* child, const MarginInfo& marginInfo, LayoutUnit& estimateWithoutPagination)
+{
+    // 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.
+    LayoutUnit logicalTopEstimate = logicalHeight();
+    if (!marginInfo.canCollapseWithMarginBefore()) {
+        LayoutUnit positiveMarginBefore = 0;
+        LayoutUnit negativeMarginBefore = 0;
+        bool discardMarginBefore = false;
+        if (child->selfNeedsLayout()) {
+            // Try to do a basic estimation of how the collapse is going to go.
+            marginBeforeEstimateForChild(child, positiveMarginBefore, negativeMarginBefore, discardMarginBefore);
+        } else {
+            // Use the cached collapsed margin values from a previous layout. Most of the time they
+            // will be right.
+            MarginValues marginValues = marginValuesForChild(child);
+            positiveMarginBefore = max(positiveMarginBefore, marginValues.positiveMarginBefore());
+            negativeMarginBefore = max(negativeMarginBefore, marginValues.negativeMarginBefore());
+            discardMarginBefore = mustDiscardMarginBeforeForChild(child);
+        }
+
+        // Collapse the result with our current margins.
+        if (!discardMarginBefore)
+            logicalTopEstimate += max(marginInfo.positiveMargin(), positiveMarginBefore) - max(marginInfo.negativeMargin(), negativeMarginBefore);
+    }
+
+    // Adjust logicalTopEstimate down to the next page if the margins are so large that we don't fit on the current
+    // page.
+    LayoutState* layoutState = view()->layoutState();
+    if (layoutState->isPaginated() && layoutState->pageLogicalHeight() && logicalTopEstimate > logicalHeight()
+        && hasNextPage(logicalHeight()))
+        logicalTopEstimate = min(logicalTopEstimate, nextPageLogicalTop(logicalHeight()));
+
+    logicalTopEstimate += getClearDelta(child, logicalTopEstimate);
+    
+    estimateWithoutPagination = logicalTopEstimate;
+
+    if (layoutState->isPaginated()) {
+        // If the object has a page or column break value of "before", then we should shift to the top of the next page.
+        logicalTopEstimate = applyBeforeBreak(child, logicalTopEstimate);
+    
+        // For replaced elements and scrolled elements, we want to shift them to the next page if they don't fit on the current one.
+        logicalTopEstimate = adjustForUnsplittableChild(child, logicalTopEstimate);
+        
+        if (!child->selfNeedsLayout() && child->isRenderBlock())
+            logicalTopEstimate += toRenderBlock(child)->paginationStrut();
+    }
+
+    return logicalTopEstimate;
+}
+
+LayoutUnit RenderBlock::computeStartPositionDeltaForChildAvoidingFloats(const RenderBox* child, LayoutUnit childMarginStart,
+    RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage)
+{
+    LayoutUnit startPosition = startOffsetForContent(region, offsetFromLogicalTopOfFirstPage);
+
+    // Add in our start margin.
+    LayoutUnit oldPosition = startPosition + childMarginStart;
+    LayoutUnit newPosition = oldPosition;
+
+    LayoutUnit blockOffset = logicalTopForChild(child);
+    if (region)
+        blockOffset = max(blockOffset, blockOffset + (region->logicalTopForFlowThreadContent() - offsetFromLogicalTopOfFirstPage));
+
+    LayoutUnit startOff = startOffsetForLine(blockOffset, false, region, offsetFromLogicalTopOfFirstPage, logicalHeightForChild(child));
+
+    if (style()->textAlign() != WEBKIT_CENTER && !child->style()->marginStartUsing(style()).isAuto()) {
+        if (childMarginStart < 0)
+            startOff += childMarginStart;
+        newPosition = max(newPosition, startOff); // Let the float sit in the child's margin if it can fit.
+    } else if (startOff != startPosition)
+        newPosition = startOff + childMarginStart;
+
+    return newPosition - oldPosition;
+}
+
+void RenderBlock::determineLogicalLeftPositionForChild(RenderBox* child, ApplyLayoutDeltaMode applyDelta)
+{
+    LayoutUnit startPosition = borderStart() + paddingStart();
+    if (style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft())
+        startPosition -= verticalScrollbarWidth();
+    LayoutUnit totalAvailableLogicalWidth = borderAndPaddingLogicalWidth() + availableLogicalWidth();
+
+    // Add in our start margin.
+    LayoutUnit childMarginStart = marginStartForChild(child);
+    LayoutUnit newPosition = startPosition + childMarginStart;
+        
+    // 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() && containsFloats() && !flowThreadContainingBlock())
+        newPosition += computeStartPositionDeltaForChildAvoidingFloats(child, marginStartForChild(child));
+
+    setLogicalLeftForChild(child, style()->isLeftToRightDirection() ? newPosition : totalAvailableLogicalWidth - newPosition - logicalWidthForChild(child), applyDelta);
+}
+
+void RenderBlock::setCollapsedBottomMargin(const MarginInfo& marginInfo)
+{
+    if (marginInfo.canCollapseWithMarginAfter() && !marginInfo.canCollapseWithMarginBefore()) {
+        // Update the after side margin of the container to discard if the after margin of the last child also discards and we collapse with it.
+        // Don't update the max margin values because we won't need them anyway.
+        if (marginInfo.discardMargin()) {
+            setMustDiscardMarginAfter();
+            return;
+        }
+
+        // Update our max pos/neg bottom margins, since we collapsed our bottom margins
+        // with our children.
+        setMaxMarginAfterValues(max(maxPositiveMarginAfter(), marginInfo.positiveMargin()), max(maxNegativeMarginAfter(), marginInfo.negativeMargin()));
+
+        if (!marginInfo.hasMarginAfterQuirk())
+            setHasMarginAfterQuirk(false);
+
+        if (marginInfo.hasMarginAfterQuirk() && !marginAfter())
+            // 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.
+            setHasMarginAfterQuirk(true);
+    }
+}
+
+void RenderBlock::handleAfterSideOfBlock(LayoutUnit beforeSide, LayoutUnit afterSide, MarginInfo& marginInfo)
+{
+    marginInfo.setAtAfterSideOfBlock(true);
+
+    // If we can't collapse with children then go ahead and add in the bottom margin.
+    if (!marginInfo.discardMargin() && (!marginInfo.canCollapseWithMarginAfter() && !marginInfo.canCollapseWithMarginBefore()
+        && (!document()->inQuirksMode() || !marginInfo.quirkContainer() || !marginInfo.hasMarginAfterQuirk())))
+        setLogicalHeight(logicalHeight() + marginInfo.margin());
+        
+    // Now add in our bottom border/padding.
+    setLogicalHeight(logicalHeight() + afterSide);
+
+    // 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.
+    setLogicalHeight(max(logicalHeight(), beforeSide + afterSide));
+
+    // Update our bottom collapsed margin info.
+    setCollapsedBottomMargin(marginInfo);
+}
+
+void RenderBlock::setLogicalLeftForChild(RenderBox* child, LayoutUnit logicalLeft, ApplyLayoutDeltaMode applyDelta)
+{
+    if (isHorizontalWritingMode()) {
+        if (applyDelta == ApplyLayoutDelta)
+            view()->addLayoutDelta(LayoutSize(child->x() - logicalLeft, 0));
+        child->setX(logicalLeft);
+    } else {
+        if (applyDelta == ApplyLayoutDelta)
+            view()->addLayoutDelta(LayoutSize(0, child->y() - logicalLeft));
+        child->setY(logicalLeft);
+    }
+}
+
+void RenderBlock::setLogicalTopForChild(RenderBox* child, LayoutUnit logicalTop, ApplyLayoutDeltaMode applyDelta)
+{
+    if (isHorizontalWritingMode()) {
+        if (applyDelta == ApplyLayoutDelta)
+            view()->addLayoutDelta(LayoutSize(0, child->y() - logicalTop));
+        child->setY(logicalTop);
+    } else {
+        if (applyDelta == ApplyLayoutDelta)
+            view()->addLayoutDelta(LayoutSize(child->x() - logicalTop, 0));
+        child->setX(logicalTop);
+    }
+}
+
+void RenderBlock::updateBlockChildDirtyBitsBeforeLayout(bool relayoutChildren, RenderBox* child)
+{
+    // 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->hasRelativeLogicalHeight() && !isRenderView()) || child->hasViewportPercentageLogicalHeight())
+        child->setChildNeedsLayout(true, MarkOnlyThis);
+
+    // If relayoutChildren is set and the child has percentage padding or an embedded content box, we also need to invalidate the childs pref widths.
+    if (relayoutChildren && child->needsPreferredWidthsRecalculation())
+        child->setPreferredLogicalWidthsDirty(true, MarkOnlyThis);
+}
+
+void RenderBlock::layoutBlockChildren(bool relayoutChildren, LayoutUnit& maxFloatLogicalBottom)
+{
+    if (gPercentHeightDescendantsMap) {
+        if (TrackedRendererListHashSet* descendants = gPercentHeightDescendantsMap->get(this)) {
+            TrackedRendererListHashSet::iterator end = descendants->end();
+            for (TrackedRendererListHashSet::iterator it = descendants->begin(); it != end; ++it) {
+                RenderBox* box = *it;
+                while (box != this) {
+                    if (box->normalChildNeedsLayout())
+                        break;
+                    box->setChildNeedsLayout(true, MarkOnlyThis);
+                    box = box->containingBlock();
+                    ASSERT(box);
+                    if (!box)
+                        break;
+                }
+            }
+        }
+    }
+
+    LayoutUnit beforeEdge = borderBefore() + paddingBefore();
+    LayoutUnit afterEdge = borderAfter() + paddingAfter() + scrollbarLogicalHeight();
+
+    setLogicalHeight(beforeEdge);
+    
+    // Lay out our hypothetical grid line as though it occurs at the top of the block.
+    if (view()->layoutState()->lineGrid() == this)
+        layoutLineGridBox();
+
+    // The margin struct caches all our current margin collapsing state.  The compact struct caches state when we encounter compacts,
+    MarginInfo marginInfo(this, beforeEdge, afterEdge);
+
+    // Fieldsets need to find their legend and position it inside the border of the object.
+    // The legend then gets skipped during normal layout.  The same is true for ruby text.
+    // It doesn't get included in the normal layout process but is instead skipped.
+    RenderObject* childToExclude = layoutSpecialExcludedChild(relayoutChildren);
+
+    LayoutUnit previousFloatLogicalBottom = 0;
+    maxFloatLogicalBottom = 0;
+
+    RenderBox* next = firstChildBox();
+
+    while (next) {
+        RenderBox* child = next;
+        next = child->nextSiblingBox();
+
+        if (childToExclude == child)
+            continue; // Skip this child, since it will be positioned by the specialized subclass (fieldsets and ruby runs).
+
+        updateBlockChildDirtyBitsBeforeLayout(relayoutChildren, child);
+
+        if (child->isOutOfFlowPositioned()) {
+            child->containingBlock()->insertPositionedObject(child);
+            adjustPositionedBlock(child, marginInfo);
+            continue;
+        }
+        if (child->isFloating()) {
+            insertFloatingObject(child);
+            adjustFloatingBlock(marginInfo);
+            continue;
+        }
+
+        // Lay out the child.
+        layoutBlockChild(child, marginInfo, previousFloatLogicalBottom, maxFloatLogicalBottom);
+    }
+    
+    // Now do the handling of the bottom of the block, adding in our bottom border/padding and
+    // determining the correct collapsed bottom margin information.
+    handleAfterSideOfBlock(beforeEdge, afterEdge, marginInfo);
+}
+
+void RenderBlock::layoutBlockChild(RenderBox* child, MarginInfo& marginInfo, LayoutUnit& previousFloatLogicalBottom, LayoutUnit& maxFloatLogicalBottom)
+{
+    LayoutUnit oldPosMarginBefore = maxPositiveMarginBefore();
+    LayoutUnit oldNegMarginBefore = maxNegativeMarginBefore();
+
+    // The child is a normal flow object.  Compute the margins we will use for collapsing now.
+    child->computeAndSetBlockDirectionMargins(this);
+
+    // Try to guess our correct logical top position.  In most cases this guess will
+    // be correct.  Only if we're wrong (when we compute the real logical top position)
+    // will we have to potentially relayout.
+    LayoutUnit estimateWithoutPagination;
+    LayoutUnit logicalTopEstimate = estimateLogicalTopPosition(child, marginInfo, estimateWithoutPagination);
+
+    // Cache our old rect so that we can dirty the proper repaint rects if the child moves.
+    LayoutRect oldRect = child->frameRect();
+    LayoutUnit oldLogicalTop = logicalTopForChild(child);
+
+#if !ASSERT_DISABLED
+    LayoutSize oldLayoutDelta = view()->layoutDelta();
+#endif
+    // Go ahead and position the child as though it didn't collapse with the top.
+    setLogicalTopForChild(child, logicalTopEstimate, ApplyLayoutDelta);
+
+    RenderBlock* childRenderBlock = child->isRenderBlock() ? toRenderBlock(child) : 0;
+    bool markDescendantsWithFloats = false;
+    if (logicalTopEstimate != oldLogicalTop && !child->avoidsFloats() && childRenderBlock && childRenderBlock->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.
+        LayoutUnit fb = max(previousFloatLogicalBottom, lowestFloatLogicalBottom());
+        if (fb > logicalTopEstimate)
+            markDescendantsWithFloats = true;
+    }
+
+    if (childRenderBlock) {
+        if (markDescendantsWithFloats)
+            childRenderBlock->markAllDescendantsWithFloatsForLayout();
+        if (!child->isWritingModeRoot())
+            previousFloatLogicalBottom = max(previousFloatLogicalBottom, oldLogicalTop + childRenderBlock->lowestFloatLogicalBottom());
+    }
+
+    if (!child->needsLayout())
+        child->markForPaginationRelayoutIfNeeded();
+
+    bool childHadLayout = child->everHadLayout();
+    bool childNeededLayout = child->needsLayout();
+    if (childNeededLayout)
+        child->layout();
+
+    // Cache if we are at the top of the block right now.
+    bool atBeforeSideOfBlock = marginInfo.atBeforeSideOfBlock();
+
+    // Now determine the correct ypos based off examination of collapsing margin
+    // values.
+    LayoutUnit logicalTopBeforeClear = collapseMargins(child, marginInfo);
+
+    // Now check for clear.
+    LayoutUnit logicalTopAfterClear = clearFloatsIfNeeded(child, marginInfo, oldPosMarginBefore, oldNegMarginBefore, logicalTopBeforeClear);
+    
+    bool paginated = view()->layoutState()->isPaginated();
+    if (paginated)
+        logicalTopAfterClear = adjustBlockChildForPagination(logicalTopAfterClear, estimateWithoutPagination, child,
+            atBeforeSideOfBlock && logicalTopBeforeClear == logicalTopAfterClear);
+
+    setLogicalTopForChild(child, logicalTopAfterClear, ApplyLayoutDelta);
+
+    // Now we have a final top position.  See if it really does end up being different from our estimate.
+    // clearFloatsIfNeeded can also mark the child as needing a layout even though we didn't move. This happens
+    // when collapseMargins dynamically adds overhanging floats because of a child with negative margins.
+    if (logicalTopAfterClear != logicalTopEstimate || child->needsLayout() || (paginated && childRenderBlock && childRenderBlock->shouldBreakAtLineToAvoidWidow())) {
+        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, MarkOnlyThis);
+        }
+        
+        if (childRenderBlock) {
+            if (!child->avoidsFloats() && childRenderBlock->containsFloats())
+                childRenderBlock->markAllDescendantsWithFloatsForLayout();
+            if (!child->needsLayout())
+                child->markForPaginationRelayoutIfNeeded();
+        }
+
+        // Our guess was wrong. Make the child lay itself out again.
+        child->layoutIfNeeded();
+    }
+
+    // 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.atBeforeSideOfBlock() && !child->isSelfCollapsingBlock())
+        marginInfo.setAtBeforeSideOfBlock(false);
+
+    // Now place the child in the correct left position
+    determineLogicalLeftPositionForChild(child, ApplyLayoutDelta);
+
+    // Update our height now that the child has been placed in the correct position.
+    setLogicalHeight(logicalHeight() + logicalHeightForChild(child));
+    if (mustSeparateMarginAfterForChild(child)) {
+        setLogicalHeight(logicalHeight() + marginAfterForChild(child));
+        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.
+    if (childRenderBlock && childRenderBlock->containsFloats())
+        maxFloatLogicalBottom = max(maxFloatLogicalBottom, addOverhangingFloats(toRenderBlock(child), !childNeededLayout));
+
+    LayoutSize childOffset = child->location() - oldRect.location();
+    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->repaintOverhangingFloats(true);
+    }
+
+    if (paginated) {
+        // Check for an after page/column break.
+        LayoutUnit newHeight = applyAfterBreak(child, logicalHeight(), marginInfo);
+        if (newHeight != height())
+            setLogicalHeight(newHeight);
+    }
+
+    ASSERT(view()->layoutDeltaMatches(oldLayoutDelta));
+}
+
+void RenderBlock::simplifiedNormalFlowLayout()
+{
+    if (childrenInline()) {
+        ListHashSet<RootInlineBox*> lineBoxes;
+        for (InlineWalker walker(this); !walker.atEnd(); walker.advance()) {
+            RenderObject* o = walker.current();
+            if (!o->isOutOfFlowPositioned() && (o->isReplaced() || o->isFloating())) {
+                o->layoutIfNeeded();
+                if (toRenderBox(o)->inlineBoxWrapper()) {
+                    RootInlineBox* box = toRenderBox(o)->inlineBoxWrapper()->root();
+                    lineBoxes.add(box);
+                }
+            } else if (o->isText() || (o->isRenderInline() && !walker.atEndOfInline()))
+                o->setNeedsLayout(false);
+        }
+
+        // FIXME: Glyph overflow will get lost in this case, but not really a big deal.
+        GlyphOverflowAndFallbackFontsMap textBoxDataMap;                  
+        for (ListHashSet<RootInlineBox*>::const_iterator it = lineBoxes.begin(); it != lineBoxes.end(); ++it) {
+            RootInlineBox* box = *it;
+            box->computeOverflow(box->lineTop(), box->lineBottom(), textBoxDataMap);
+        }
+    } else {
+        for (RenderBox* box = firstChildBox(); box; box = box->nextSiblingBox()) {
+            if (!box->isOutOfFlowPositioned())
+                box->layoutIfNeeded();
+        }
+    }
+}
+
+bool RenderBlock::simplifiedLayout()
+{
+    if ((!posChildNeedsLayout() && !needsSimplifiedNormalFlowLayout()) || normalChildNeedsLayout() || selfNeedsLayout())
+        return false;
+
+    LayoutStateMaintainer statePusher(view(), this, locationOffset(), hasColumns() || hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode());
+    
+    if (needsPositionedMovementLayout() && !tryLayoutDoingPositionedMovementOnly())
+        return false;
+
+    // Lay out positioned descendants or objects that just need to recompute overflow.
+    if (needsSimplifiedNormalFlowLayout())
+        simplifiedNormalFlowLayout();
+
+    // Lay out our positioned objects if our positioned child bit is set.
+    // Also, if an absolute position element inside a relative positioned container moves, and the absolute element has a fixed position
+    // child, neither the fixed element nor its container learn of the movement since posChildNeedsLayout() is only marked as far as the 
+    // relative positioned container. So if we can have fixed pos objects in our positioned objects list check if any of them
+    // are statically positioned and thus need to move with their absolute ancestors.
+    bool canContainFixedPosObjects = canContainFixedPositionObjects();
+    if (posChildNeedsLayout() || canContainFixedPosObjects)
+        layoutPositionedObjects(false, !posChildNeedsLayout() && canContainFixedPosObjects);
+
+    // Recompute our overflow information.
+    // FIXME: We could do better here by computing a temporary overflow object from layoutPositionedObjects and only
+    // updating our overflow if we either used to have overflow or if the new temporary object has overflow.
+    // For now just always recompute overflow.  This is no worse performance-wise than the old code that called rightmostPosition and
+    // lowestPosition on every relayout so it's not a regression.
+    // computeOverflow expects the bottom edge before we clamp our height. Since this information isn't available during
+    // simplifiedLayout, we cache the value in m_overflow.
+    LayoutUnit oldClientAfterEdge = hasRenderOverflow() ? m_overflow->layoutClientAfterEdge() : clientLogicalBottom();
+    computeOverflow(oldClientAfterEdge, true);
+
+    statePusher.pop();
+    
+    updateLayerTransform();
+
+    updateScrollInfoAfterLayout();
+
+    setNeedsLayout(false);
+    return true;
+}
+
+void RenderBlock::markFixedPositionObjectForLayoutIfNeeded(RenderObject* child)
+{
+    if (child->style()->position() != FixedPosition)
+        return;
+
+    bool hasStaticBlockPosition = child->style()->hasStaticBlockPosition(isHorizontalWritingMode());
+    bool hasStaticInlinePosition = child->style()->hasStaticInlinePosition(isHorizontalWritingMode());
+    if (!hasStaticBlockPosition && !hasStaticInlinePosition)
+        return;
+
+    RenderObject* o = child->parent();
+    while (o && !o->isRenderView() && o->style()->position() != AbsolutePosition)
+        o = o->parent();
+    if (o->style()->position() != AbsolutePosition)
+        return;
+
+    RenderBox* box = toRenderBox(child);
+    if (hasStaticInlinePosition) {
+        LayoutUnit oldLeft = box->logicalLeft();
+        box->updateLogicalWidth();
+        if (box->logicalLeft() != oldLeft)
+            child->setChildNeedsLayout(true, MarkOnlyThis);
+    } else if (hasStaticBlockPosition) {
+        LayoutUnit oldTop = box->logicalTop();
+        box->updateLogicalHeight();
+        if (box->logicalTop() != oldTop)
+            child->setChildNeedsLayout(true, MarkOnlyThis);
+    }
+}
+
+void RenderBlock::layoutPositionedObjects(bool relayoutChildren, bool fixedPositionObjectsOnly)
+{
+    TrackedRendererListHashSet* positionedDescendants = positionedObjects();
+    if (!positionedDescendants)
+        return;
+        
+    if (hasColumns())
+        view()->layoutState()->clearPaginationInformation(); // Positioned objects are not part of the column flow, so they don't paginate with the columns.
+
+    RenderBox* r;
+    TrackedRendererListHashSet::iterator end = positionedDescendants->end();
+    for (TrackedRendererListHashSet::iterator it = positionedDescendants->begin(); it != end; ++it) {
+        r = *it;
+
+        // A fixed position element with an absolute positioned ancestor has no way of knowing if the latter has changed position. So
+        // if this is a fixed position element, mark it for layout if it has an abspos ancestor and needs to move with that ancestor, i.e. 
+        // it has static position.
+        markFixedPositionObjectForLayoutIfNeeded(r);
+        if (fixedPositionObjectsOnly) {
+            r->layoutIfNeeded();
+            continue;
+        }
+
+        // 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->style()->hasStaticBlockPosition(isHorizontalWritingMode()) && r->parent() != this))
+            r->setChildNeedsLayout(true, MarkOnlyThis);
+            
+        // If relayoutChildren is set and the child has percentage padding or an embedded content box, we also need to invalidate the childs pref widths.
+        if (relayoutChildren && r->needsPreferredWidthsRecalculation())
+            r->setPreferredLogicalWidthsDirty(true, MarkOnlyThis);
+        
+        if (!r->needsLayout())
+            r->markForPaginationRelayoutIfNeeded();
+        
+        // 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->setNeedsLayout(false);
+            
+        // If we are paginated or in a line grid, go ahead and compute a vertical position for our object now.
+        // If it's wrong we'll lay out again.
+        LayoutUnit oldLogicalTop = 0;
+        bool needsBlockDirectionLocationSetBeforeLayout = r->needsLayout() && view()->layoutState()->needsBlockDirectionLocationSetBeforeLayout(); 
+        if (needsBlockDirectionLocationSetBeforeLayout) {
+            if (isHorizontalWritingMode() == r->isHorizontalWritingMode())
+                r->updateLogicalHeight();
+            else
+                r->updateLogicalWidth();
+            oldLogicalTop = logicalTopForChild(r);
+        }
+        
+        r->layoutIfNeeded();
+
+        // Lay out again if our estimate was wrong.
+        if (needsBlockDirectionLocationSetBeforeLayout && logicalTopForChild(r) != oldLogicalTop) {
+            r->setChildNeedsLayout(true, MarkOnlyThis);
+            r->layoutIfNeeded();
+        }
+    }
+    
+    if (hasColumns())
+        view()->layoutState()->m_columnInfo = columnInfo(); // FIXME: Kind of gross. We just put this back into the layout state so that pop() will work.
+}
+
+void RenderBlock::markPositionedObjectsForLayout()
+{
+    TrackedRendererListHashSet* positionedDescendants = positionedObjects();
+    if (positionedDescendants) {
+        RenderBox* r;
+        TrackedRendererListHashSet::iterator end = positionedDescendants->end();
+        for (TrackedRendererListHashSet::iterator it = positionedDescendants->begin(); it != end; ++it) {
+            r = *it;
+            r->setChildNeedsLayout(true);
+        }
+    }
+}
+
+void RenderBlock::markForPaginationRelayoutIfNeeded()
+{
+    ASSERT(!needsLayout());
+    if (needsLayout())
+        return;
+
+    if (view()->layoutState()->pageLogicalHeightChanged() || (view()->layoutState()->pageLogicalHeight() && view()->layoutState()->pageLogicalOffset(this, logicalTop()) != pageLogicalOffset()) || shouldBreakAtLineToAvoidWidow())
+        setChildNeedsLayout(true, MarkOnlyThis);
+}
+
+void RenderBlock::repaintOverhangingFloats(bool paintAllDescendants)
+{
+    // Repaint any overhanging floats (if we know we're the one to paint them).
+    // Otherwise, bail out.
+    if (!hasOverhangingFloats())
+        return;
+
+    // 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.
+    LayoutStateDisabler layoutStateDisabler(view());
+    const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
+    FloatingObjectSetIterator end = floatingObjectSet.end();
+    for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
+        FloatingObject* r = *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 (logicalBottomForFloat(r) > logicalHeight() && ((paintAllDescendants && r->m_renderer->isDescendantOf(this)) || r->shouldPaint()) && !r->m_renderer->hasSelfPaintingLayer()) {
+            r->m_renderer->repaint();
+            r->m_renderer->repaintOverhangingFloats(false);
+        }
+    }
+}
+ 
+void RenderBlock::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    LayoutPoint adjustedPaintOffset = paintOffset + location();
+    
+    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 (!isRoot()) {
+        LayoutRect overflowBox = overflowRectForPaintRejection();
+        flipForWritingMode(overflowBox);
+        overflowBox.inflate(maximalOutlineSize(paintInfo.phase));
+        overflowBox.moveBy(adjustedPaintOffset);
+        if (!overflowBox.intersects(paintInfo.rect))
+            return;
+    }
+
+    bool pushedClip = pushContentsClip(paintInfo, adjustedPaintOffset);
+    paintObject(paintInfo, adjustedPaintOffset);
+    if (pushedClip)
+        popContentsClip(paintInfo, phase, adjustedPaintOffset);
+
+    // 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.
+    if (hasOverflowClip() && style()->visibility() == VISIBLE && (phase == PaintPhaseBlockBackground || phase == PaintPhaseChildBlockBackground) && paintInfo.shouldPaintWithinRoot(this) && !paintInfo.paintRootBackgroundOnly())
+        layer()->paintOverflowControls(paintInfo.context, roundedIntPoint(adjustedPaintOffset), paintInfo.rect);
+}
+
+void RenderBlock::paintColumnRules(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    if (paintInfo.context->paintingDisabled())
+        return;
+
+    const Color& ruleColor = style()->visitedDependentColor(CSSPropertyWebkitColumnRuleColor);
+    bool ruleTransparent = style()->columnRuleIsTransparent();
+    EBorderStyle ruleStyle = style()->columnRuleStyle();
+    LayoutUnit ruleThickness = style()->columnRuleWidth();
+    LayoutUnit colGap = columnGap();
+    bool renderRule = ruleStyle > BHIDDEN && !ruleTransparent;
+    if (!renderRule)
+        return;
+
+    ColumnInfo* colInfo = columnInfo();
+    unsigned colCount = columnCount(colInfo);
+
+    bool antialias = shouldAntialiasLines(paintInfo.context);
+
+    if (colInfo->progressionAxis() == ColumnInfo::InlineAxis) {
+        bool leftToRight = style()->isLeftToRightDirection() ^ colInfo->progressionIsReversed();
+        LayoutUnit currLogicalLeftOffset = leftToRight ? LayoutUnit() : contentLogicalWidth();
+        LayoutUnit ruleAdd = logicalLeftOffsetForContent();
+        LayoutUnit ruleLogicalLeft = leftToRight ? LayoutUnit() : contentLogicalWidth();
+        LayoutUnit inlineDirectionSize = colInfo->desiredColumnWidth();
+        BoxSide boxSide = isHorizontalWritingMode()
+            ? leftToRight ? BSLeft : BSRight
+            : leftToRight ? BSTop : BSBottom;
+
+        for (unsigned i = 0; i < colCount; i++) {
+            // Move to the next position.
+            if (leftToRight) {
+                ruleLogicalLeft += inlineDirectionSize + colGap / 2;
+                currLogicalLeftOffset += inlineDirectionSize + colGap;
+            } else {
+                ruleLogicalLeft -= (inlineDirectionSize + colGap / 2);
+                currLogicalLeftOffset -= (inlineDirectionSize + colGap);
+            }
+           
+            // Now paint the column rule.
+            if (i < colCount - 1) {
+                LayoutUnit ruleLeft = isHorizontalWritingMode() ? paintOffset.x() + ruleLogicalLeft - ruleThickness / 2 + ruleAdd : paintOffset.x() + borderLeft() + paddingLeft();
+                LayoutUnit ruleRight = isHorizontalWritingMode() ? ruleLeft + ruleThickness : ruleLeft + contentWidth();
+                LayoutUnit ruleTop = isHorizontalWritingMode() ? paintOffset.y() + borderTop() + paddingTop() : paintOffset.y() + ruleLogicalLeft - ruleThickness / 2 + ruleAdd;
+                LayoutUnit ruleBottom = isHorizontalWritingMode() ? ruleTop + contentHeight() : ruleTop + ruleThickness;
+                IntRect pixelSnappedRuleRect = pixelSnappedIntRectFromEdges(ruleLeft, ruleTop, ruleRight, ruleBottom);
+                drawLineForBoxSide(paintInfo.context, pixelSnappedRuleRect.x(), pixelSnappedRuleRect.y(), pixelSnappedRuleRect.maxX(), pixelSnappedRuleRect.maxY(), boxSide, ruleColor, ruleStyle, 0, 0, antialias);
+            }
+            
+            ruleLogicalLeft = currLogicalLeftOffset;
+        }
+    } else {
+        bool topToBottom = !style()->isFlippedBlocksWritingMode() ^ colInfo->progressionIsReversed();
+        LayoutUnit ruleLeft = isHorizontalWritingMode()
+            ? borderLeft() + paddingLeft()
+            : colGap / 2 - colGap - ruleThickness / 2 + (!colInfo->progressionIsReversed() ? borderBefore() + paddingBefore() : borderAfter() + paddingAfter());
+        LayoutUnit ruleWidth = isHorizontalWritingMode() ? contentWidth() : ruleThickness;
+        LayoutUnit ruleTop = isHorizontalWritingMode()
+            ? colGap / 2 - colGap - ruleThickness / 2 + (!colInfo->progressionIsReversed() ? borderBefore() + paddingBefore() : borderAfter() + paddingAfter())
+            : borderStart() + paddingStart();
+        LayoutUnit ruleHeight = isHorizontalWritingMode() ? ruleThickness : contentHeight();
+        LayoutRect ruleRect(ruleLeft, ruleTop, ruleWidth, ruleHeight);
+
+        if (!topToBottom) {
+            if (isHorizontalWritingMode())
+                ruleRect.setY(height() - ruleRect.maxY());
+            else
+                ruleRect.setX(width() - ruleRect.maxX());
+        }
+
+        ruleRect.moveBy(paintOffset);
+
+        BoxSide boxSide = isHorizontalWritingMode()
+            ? topToBottom ? BSTop : BSBottom
+            : topToBottom ? BSLeft : BSRight;
+
+        LayoutSize step(0, topToBottom ? colInfo->columnHeight() + colGap : -(colInfo->columnHeight() + colGap));
+        if (!isHorizontalWritingMode())
+            step = step.transposedSize();
+
+        for (unsigned i = 1; i < colCount; i++) {
+            ruleRect.move(step);
+            IntRect pixelSnappedRuleRect = pixelSnappedIntRect(ruleRect);
+            drawLineForBoxSide(paintInfo.context, pixelSnappedRuleRect.x(), pixelSnappedRuleRect.y(), pixelSnappedRuleRect.maxX(), pixelSnappedRuleRect.maxY(), boxSide, ruleColor, ruleStyle, 0, 0, antialias);
+        }
+    }
+}
+
+void RenderBlock::paintColumnContents(PaintInfo& paintInfo, const LayoutPoint& paintOffset, bool paintingFloats)
+{
+    // We need to do multiple passes, breaking up our child painting into strips.
+    GraphicsContext* context = paintInfo.context;
+    ColumnInfo* colInfo = columnInfo();
+    unsigned colCount = columnCount(colInfo);
+    if (!colCount)
+        return;
+    LayoutUnit currLogicalTopOffset = 0;
+    LayoutUnit colGap = columnGap();
+    for (unsigned i = 0; i < colCount; i++) {
+        // For each rect, we clip to the rect, and then we adjust our coords.
+        LayoutRect colRect = columnRectAt(colInfo, i);
+        flipForWritingMode(colRect);
+        LayoutUnit logicalLeftOffset = (isHorizontalWritingMode() ? colRect.x() : colRect.y()) - logicalLeftOffsetForContent();
+        LayoutSize offset = isHorizontalWritingMode() ? LayoutSize(logicalLeftOffset, currLogicalTopOffset) : LayoutSize(currLogicalTopOffset, logicalLeftOffset);
+        if (colInfo->progressionAxis() == ColumnInfo::BlockAxis) {
+            if (isHorizontalWritingMode())
+                offset.expand(0, colRect.y() - borderTop() - paddingTop());
+            else
+                offset.expand(colRect.x() - borderLeft() - paddingLeft(), 0);
+        }
+        colRect.moveBy(paintOffset);
+        PaintInfo info(paintInfo);
+        info.rect.intersect(pixelSnappedIntRect(colRect));
+        
+        if (!info.rect.isEmpty()) {
+            GraphicsContextStateSaver stateSaver(*context);
+            LayoutRect clipRect(colRect);
+            
+            if (i < colCount - 1) {
+                if (isHorizontalWritingMode())
+                    clipRect.expand(colGap / 2, 0);
+                else
+                    clipRect.expand(0, colGap / 2);
+            }
+            // Each strip pushes a clip, since column boxes are specified as being
+            // like overflow:hidden.
+            // FIXME: Content and column rules that extend outside column boxes at the edges of the multi-column element
+            // are clipped according to the 'overflow' property.
+            context->clip(pixelSnappedIntRect(clipRect));
+
+            // Adjust our x and y when painting.
+            LayoutPoint adjustedPaintOffset = paintOffset + offset;
+            if (paintingFloats)
+                paintFloats(info, adjustedPaintOffset, paintInfo.phase == PaintPhaseSelection || paintInfo.phase == PaintPhaseTextClip);
+            else
+                paintContents(info, adjustedPaintOffset);
+        }
+
+        LayoutUnit blockDelta = (isHorizontalWritingMode() ? colRect.height() : colRect.width());
+        if (style()->isFlippedBlocksWritingMode())
+            currLogicalTopOffset += blockDelta;
+        else
+            currLogicalTopOffset -= blockDelta;
+    }
+}
+
+void RenderBlock::paintContents(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    // 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, styleResolverChanged() on the Document
+    // will do a full repaint.
+    if (document()->didLayoutWithPendingStylesheets() && !isRenderView())
+        return;
+
+    if (childrenInline())
+        m_lineBoxes.paint(this, paintInfo, paintOffset);
+    else {
+        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 paintInfoForChild(paintInfo);
+        paintInfoForChild.phase = newPhase;
+        paintInfoForChild.updatePaintingRootForChildren(this);
+
+        // FIXME: Paint-time pagination is obsolete and is now only used by embedded WebViews inside AppKit
+        // NSViews. Do not add any more code for this.
+        bool usePrintRect = !view()->printRect().isEmpty();
+        paintChildren(paintInfo, paintOffset, paintInfoForChild, usePrintRect);
+    }
+}
+
+void RenderBlock::paintChildren(PaintInfo& paintInfo, const LayoutPoint& paintOffset, PaintInfo& paintInfoForChild, bool usePrintRect)
+{
+    for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
+        if (!paintChild(child, paintInfo, paintOffset, paintInfoForChild, usePrintRect))
+            return;
+    }
+}
+
+bool RenderBlock::paintChild(RenderBox* child, PaintInfo& paintInfo, const LayoutPoint& paintOffset, PaintInfo& paintInfoForChild, bool usePrintRect)
+{
+    // Check for page-break-before: always, and if it's set, break and bail.
+    bool checkBeforeAlways = !childrenInline() && (usePrintRect && child->style()->pageBreakBefore() == PBALWAYS);
+    LayoutUnit absoluteChildY = paintOffset.y() + child->y();
+    if (checkBeforeAlways
+        && absoluteChildY > paintInfo.rect.y()
+        && absoluteChildY < paintInfo.rect.maxY()) {
+        view()->setBestTruncatedAt(absoluteChildY, this, true);
+        return false;
+    }
+
+    RenderView* renderView = view();
+    if (!child->isFloating() && child->isReplaced() && usePrintRect && child->height() <= renderView->printRect().height()) {
+        // Paginate block-level replaced elements.
+        if (absoluteChildY + child->height() > renderView->printRect().maxY()) {
+            if (absoluteChildY < renderView->truncatedAt())
+                renderView->setBestTruncatedAt(absoluteChildY, child);
+            // If we were able to truncate, don't paint.
+            if (absoluteChildY >= renderView->truncatedAt())
+                return false;
+        }
+    }
+
+    LayoutPoint childPoint = flipForWritingModeForChild(child, paintOffset);
+    if (!child->hasSelfPaintingLayer() && !child->isFloating())
+        child->paint(paintInfoForChild, childPoint);
+
+    // Check for page-break-after: always, and if it's set, break and bail.
+    bool checkAfterAlways = !childrenInline() && (usePrintRect && child->style()->pageBreakAfter() == PBALWAYS);
+    if (checkAfterAlways
+        && (absoluteChildY + child->height()) > paintInfo.rect.y()
+        && (absoluteChildY + child->height()) < paintInfo.rect.maxY()) {
+        view()->setBestTruncatedAt(absoluteChildY + child->height() + max<LayoutUnit>(0, child->collapsedMarginAfter()), this, true);
+        return false;
+    }
+    return true;
+}
+
+
+void RenderBlock::paintCaret(PaintInfo& paintInfo, const LayoutPoint& paintOffset, CaretType type)
+{
+    // Paint the caret if the FrameSelection says so or if caret browsing is enabled
+    bool caretBrowsing = frame()->settings() && frame()->settings()->caretBrowsingEnabled();
+    RenderObject* caretPainter;
+    bool isContentEditable;
+    if (type == CursorCaret) {
+        caretPainter = frame()->selection()->caretRenderer();
+        isContentEditable = frame()->selection()->rendererIsEditable();
+    } else {
+        caretPainter = frame()->page()->dragCaretController()->caretRenderer();
+        isContentEditable = frame()->page()->dragCaretController()->isContentEditable();
+    }
+
+    if (caretPainter == this && (isContentEditable || caretBrowsing)) {
+        if (type == CursorCaret)
+            frame()->selection()->paintCaret(paintInfo.context, paintOffset, paintInfo.rect);
+        else
+            frame()->page()->dragCaretController()->paintDragCaret(frame(), paintInfo.context, paintOffset, paintInfo.rect);
+    }
+}
+
+void RenderBlock::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    PaintPhase paintPhase = paintInfo.phase;
+
+    // 1. paint background, borders etc
+    if ((paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChildBlockBackground) && style()->visibility() == VISIBLE) {
+        if (hasBoxDecorations())
+            paintBoxDecorations(paintInfo, paintOffset);
+        if (hasColumns() && !paintInfo.paintRootBackgroundOnly())
+            paintColumnRules(paintInfo, paintOffset);
+    }
+
+    if (paintPhase == PaintPhaseMask && style()->visibility() == VISIBLE) {
+        paintMask(paintInfo, paintOffset);
+        return;
+    }
+
+    // We're done.  We don't bother painting any children.
+    if (paintPhase == PaintPhaseBlockBackground || paintInfo.paintRootBackgroundOnly())
+        return;
+
+    // Adjust our painting position if we're inside a scrolled layer (e.g., an overflow:auto div).
+    LayoutPoint scrolledOffset = paintOffset;
+    if (hasOverflowClip())
+        scrolledOffset.move(-scrolledContentOffset());
+
+    // 2. paint contents
+    if (paintPhase != PaintPhaseSelfOutline) {
+        if (hasColumns())
+            paintColumnContents(paintInfo, scrolledOffset);
+        else
+            paintContents(paintInfo, scrolledOffset);
+    }
+
+    // 3. paint selection
+    // FIXME: Make this work with multi column layouts.  For now don't fill gaps.
+    bool isPrinting = document()->printing();
+    if (!isPrinting && !hasColumns())
+        paintSelection(paintInfo, scrolledOffset); // Fill in gaps in selection on lines and between blocks.
+
+    // 4. paint floats.
+    if (paintPhase == PaintPhaseFloat || paintPhase == PaintPhaseSelection || paintPhase == PaintPhaseTextClip) {
+        if (hasColumns())
+            paintColumnContents(paintInfo, scrolledOffset, true);
+        else
+            paintFloats(paintInfo, scrolledOffset, paintPhase == PaintPhaseSelection || paintPhase == PaintPhaseTextClip);
+    }
+
+    // 5. paint outline.
+    if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseSelfOutline) && hasOutline() && style()->visibility() == VISIBLE)
+        paintOutline(paintInfo, LayoutRect(paintOffset, size()));
+
+    // 6. paint continuation outlines.
+    if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseChildOutlines)) {
+        RenderInline* inlineCont = inlineElementContinuation();
+        if (inlineCont && inlineCont->hasOutline() && inlineCont->style()->visibility() == VISIBLE) {
+            RenderInline* inlineRenderer = toRenderInline(inlineCont->node()->renderer());
+            RenderBlock* cb = containingBlock();
+
+            bool inlineEnclosedInSelfPaintingLayer = false;
+            for (RenderBoxModelObject* box = inlineRenderer; box != cb; box = box->parent()->enclosingBoxModelObject()) {
+                if (box->hasSelfPaintingLayer()) {
+                    inlineEnclosedInSelfPaintingLayer = true;
+                    break;
+                }
+            }
+
+            // Do not add continuations for outline painting by our containing block if we are a relative positioned
+            // anonymous block (i.e. have our own layer), paint them straightaway instead. This is because a block depends on renderers in its continuation table being
+            // in the same layer. 
+            if (!inlineEnclosedInSelfPaintingLayer && !hasLayer())
+                cb->addContinuationWithOutline(inlineRenderer);
+            else if (!inlineRenderer->firstLineBox() || (!inlineEnclosedInSelfPaintingLayer && hasLayer()))
+                inlineRenderer->paintOutline(paintInfo, paintOffset - locationOffset() + inlineRenderer->containingBlock()->location());
+        }
+        paintContinuationOutlines(paintInfo, paintOffset);
+    }
+
+    // 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 (paintPhase == PaintPhaseForeground) {        
+        paintCaret(paintInfo, paintOffset, CursorCaret);
+        paintCaret(paintInfo, paintOffset, DragCaret);
+    }
+}
+
+LayoutPoint RenderBlock::flipFloatForWritingModeForChild(const FloatingObject* child, const LayoutPoint& point) const
+{
+    if (!style()->isFlippedBlocksWritingMode())
+        return point;
+    
+    // This is similar to RenderBox::flipForWritingModeForChild. We have to subtract out our left/top offsets twice, since
+    // it's going to get added back in. We hide this complication here so that the calling code looks normal for the unflipped
+    // case.
+    if (isHorizontalWritingMode())
+        return LayoutPoint(point.x(), point.y() + height() - child->renderer()->height() - 2 * yPositionForFloatIncludingMargin(child));
+    return LayoutPoint(point.x() + width() - child->renderer()->width() - 2 * xPositionForFloatIncludingMargin(child), point.y());
+}
+
+void RenderBlock::paintFloats(PaintInfo& paintInfo, const LayoutPoint& paintOffset, bool preservePhase)
+{
+    if (!m_floatingObjects)
+        return;
+
+    const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
+    FloatingObjectSetIterator end = floatingObjectSet.end();
+    for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
+        FloatingObject* r = *it;
+        // Only paint the object if our m_shouldPaint flag is set.
+        if (r->shouldPaint() && !r->m_renderer->hasSelfPaintingLayer()) {
+            PaintInfo currentPaintInfo(paintInfo);
+            currentPaintInfo.phase = preservePhase ? paintInfo.phase : PaintPhaseBlockBackground;
+            LayoutPoint childPoint = flipFloatForWritingModeForChild(r, LayoutPoint(paintOffset.x() + xPositionForFloatIncludingMargin(r) - r->m_renderer->x(), paintOffset.y() + yPositionForFloatIncludingMargin(r) - r->m_renderer->y()));
+            r->m_renderer->paint(currentPaintInfo, childPoint);
+            if (!preservePhase) {
+                currentPaintInfo.phase = PaintPhaseChildBlockBackgrounds;
+                r->m_renderer->paint(currentPaintInfo, childPoint);
+                currentPaintInfo.phase = PaintPhaseFloat;
+                r->m_renderer->paint(currentPaintInfo, childPoint);
+                currentPaintInfo.phase = PaintPhaseForeground;
+                r->m_renderer->paint(currentPaintInfo, childPoint);
+                currentPaintInfo.phase = PaintPhaseOutline;
+                r->m_renderer->paint(currentPaintInfo, childPoint);
+            }
+        }
+    }
+}
+
+RenderInline* RenderBlock::inlineElementContinuation() const
+{ 
+    RenderBoxModelObject* continuation = this->continuation();
+    return continuation && continuation->isInline() ? toRenderInline(continuation) : 0;
+}
+
+RenderBlock* RenderBlock::blockElementContinuation() const
+{
+    RenderBoxModelObject* currentContinuation = continuation();
+    if (!currentContinuation || currentContinuation->isInline())
+        return 0;
+    RenderBlock* nextContinuation = toRenderBlock(currentContinuation);
+    if (nextContinuation->isAnonymousBlock())
+        return nextContinuation->blockElementContinuation();
+    return nextContinuation;
+}
+    
+static ContinuationOutlineTableMap* continuationOutlineTable()
+{
+    DEFINE_STATIC_LOCAL(ContinuationOutlineTableMap, table, ());
+    return &table;
+}
+
+void RenderBlock::addContinuationWithOutline(RenderInline* 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() && !flow->isInlineElementContinuation());
+    
+    ContinuationOutlineTableMap* table = continuationOutlineTable();
+    ListHashSet<RenderInline*>* continuations = table->get(this);
+    if (!continuations) {
+        continuations = new ListHashSet<RenderInline*>;
+        table->set(this, adoptPtr(continuations));
+    }
+    
+    continuations->add(flow);
+}
+
+bool RenderBlock::paintsContinuationOutline(RenderInline* flow)
+{
+    ContinuationOutlineTableMap* table = continuationOutlineTable();
+    if (table->isEmpty())
+        return false;
+        
+    ListHashSet<RenderInline*>* continuations = table->get(this);
+    if (!continuations)
+        return false;
+
+    return continuations->contains(flow);
+}
+
+void RenderBlock::paintContinuationOutlines(PaintInfo& info, const LayoutPoint& paintOffset)
+{
+    ContinuationOutlineTableMap* table = continuationOutlineTable();
+    if (table->isEmpty())
+        return;
+        
+    OwnPtr<ListHashSet<RenderInline*> > continuations = table->take(this);
+    if (!continuations)
+        return;
+
+    LayoutPoint accumulatedPaintOffset = paintOffset;
+    // Paint each continuation outline.
+    ListHashSet<RenderInline*>::iterator end = continuations->end();
+    for (ListHashSet<RenderInline*>::iterator it = continuations->begin(); it != end; ++it) {
+        // Need to add in the coordinates of the intervening blocks.
+        RenderInline* flow = *it;
+        RenderBlock* block = flow->containingBlock();
+        for ( ; block && block != this; block = block->containingBlock())
+            accumulatedPaintOffset.moveBy(block->location());
+        ASSERT(block);   
+        flow->paintOutline(info, accumulatedPaintOffset);
+    }
+}
+
+bool RenderBlock::shouldPaintSelectionGaps() const
+{
+    return selectionState() != SelectionNone && style()->visibility() == VISIBLE && isSelectionRoot();
+}
+
+bool RenderBlock::isSelectionRoot() const
+{
+    if (isPseudoElement())
+        return false;
+    ASSERT(node() || isAnonymous());
+        
+    // 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()
+        || isPositioned() || isFloating()
+        || isTableCell() || isInlineBlockOrInlineTable()
+        || hasTransform() || hasReflection() || hasMask() || isWritingModeRoot()
+        || isRenderFlowThread())
+        return true;
+    
+    if (view() && view()->selectionStart()) {
+        Node* startElement = view()->selectionStart()->node();
+        if (startElement && startElement->rootEditableElement() == node())
+            return true;
+    }
+    
+    return false;
+}
+
+GapRects RenderBlock::selectionGapRectsForRepaint(const RenderLayerModelObject* repaintContainer)
+{
+    ASSERT(!needsLayout());
+
+    if (!shouldPaintSelectionGaps())
+        return GapRects();
+
+    TransformState transformState(TransformState::ApplyTransformDirection, FloatPoint());
+    mapLocalToContainer(repaintContainer, transformState, ApplyContainerFlip | UseTransforms);
+    LayoutPoint offsetFromRepaintContainer = roundedLayoutPoint(transformState.mappedPoint());
+
+    if (hasOverflowClip())
+        offsetFromRepaintContainer -= scrolledContentOffset();
+
+    LayoutUnit lastTop = 0;
+    LayoutUnit lastLeft = logicalLeftSelectionOffset(this, lastTop);
+    LayoutUnit lastRight = logicalRightSelectionOffset(this, lastTop);
+    
+    return selectionGaps(this, offsetFromRepaintContainer, IntSize(), lastTop, lastLeft, lastRight);
+}
+
+void RenderBlock::paintSelection(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    if (shouldPaintSelectionGaps() && paintInfo.phase == PaintPhaseForeground) {
+        LayoutUnit lastTop = 0;
+        LayoutUnit lastLeft = logicalLeftSelectionOffset(this, lastTop);
+        LayoutUnit lastRight = logicalRightSelectionOffset(this, lastTop);
+        GraphicsContextStateSaver stateSaver(*paintInfo.context);
+
+        LayoutRect gapRectsBounds = selectionGaps(this, paintOffset, LayoutSize(), lastTop, lastLeft, lastRight, &paintInfo);
+        if (!gapRectsBounds.isEmpty()) {
+            if (RenderLayer* layer = enclosingLayer()) {
+                gapRectsBounds.moveBy(-paintOffset);
+                if (!hasLayer()) {
+                    LayoutRect localBounds(gapRectsBounds);
+                    flipForWritingMode(localBounds);
+                    gapRectsBounds = localToContainerQuad(FloatRect(localBounds), layer->renderer()).enclosingBoundingBox();
+                    if (layer->renderer()->hasOverflowClip())
+                        gapRectsBounds.move(layer->renderBox()->scrolledContentOffset());
+                }
+                layer->addBlockSelectionGapsBounds(gapRectsBounds);
+            }
+        }
+    }
+}
+
+static void clipOutPositionedObjects(const PaintInfo* paintInfo, const LayoutPoint& offset, TrackedRendererListHashSet* positionedObjects)
+{
+    if (!positionedObjects)
+        return;
+    
+    TrackedRendererListHashSet::const_iterator end = positionedObjects->end();
+    for (TrackedRendererListHashSet::const_iterator it = positionedObjects->begin(); it != end; ++it) {
+        RenderBox* r = *it;
+        paintInfo->context->clipOut(IntRect(offset.x() + r->x(), offset.y() + r->y(), r->width(), r->height()));
+    }
+}
+
+static LayoutUnit blockDirectionOffset(RenderBlock* rootBlock, const LayoutSize& offsetFromRootBlock)
+{
+    return rootBlock->isHorizontalWritingMode() ? offsetFromRootBlock.height() : offsetFromRootBlock.width();
+}
+
+static LayoutUnit inlineDirectionOffset(RenderBlock* rootBlock, const LayoutSize& offsetFromRootBlock)
+{
+    return rootBlock->isHorizontalWritingMode() ? offsetFromRootBlock.width() : offsetFromRootBlock.height();
+}
+
+LayoutRect RenderBlock::logicalRectToPhysicalRect(const LayoutPoint& rootBlockPhysicalPosition, const LayoutRect& logicalRect)
+{
+    LayoutRect result;
+    if (isHorizontalWritingMode())
+        result = logicalRect;
+    else
+        result = LayoutRect(logicalRect.y(), logicalRect.x(), logicalRect.height(), logicalRect.width());
+    flipForWritingMode(result);
+    result.moveBy(rootBlockPhysicalPosition);
+    return result;
+}
+
+GapRects RenderBlock::selectionGaps(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
+                                    LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, 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.
+        LayoutRect flippedBlockRect(offsetFromRootBlock.width(), offsetFromRootBlock.height(), width(), height());
+        rootBlock->flipForWritingMode(flippedBlockRect);
+        flippedBlockRect.moveBy(rootBlockPhysicalPosition);
+        clipOutPositionedObjects(paintInfo, flippedBlockRect.location(), 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, LayoutPoint(cb->x(), cb->y()), cb->positionedObjects()); // FIXME: Not right for flipped writing modes.
+        if (m_floatingObjects) {
+            const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
+            FloatingObjectSetIterator end = floatingObjectSet.end();
+            for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
+                FloatingObject* r = *it;
+                LayoutRect floatBox(offsetFromRootBlock.width() + xPositionForFloatIncludingMargin(r),
+                                    offsetFromRootBlock.height() + yPositionForFloatIncludingMargin(r),
+                                    r->m_renderer->width(), r->m_renderer->height());
+                rootBlock->flipForWritingMode(floatBox);
+                floatBox.move(rootBlockPhysicalPosition.x(), rootBlockPhysicalPosition.y());
+                paintInfo->context->clipOut(pixelSnappedIntRect(floatBox));
+            }
+        }
+    }
+
+    // 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;
+    if (!isBlockFlow()) // FIXME: Make multi-column selection gap filling work someday.
+        return result;
+
+    if (hasColumns() || hasTransform() || style()->columnSpan()) {
+        // FIXME: We should learn how to gap fill multiple columns and transforms eventually.
+        lastLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + logicalHeight();
+        lastLogicalLeft = logicalLeftSelectionOffset(rootBlock, logicalHeight());
+        lastLogicalRight = logicalRightSelectionOffset(rootBlock, logicalHeight());
+        return result;
+    }
+
+    if (childrenInline())
+        result = inlineSelectionGaps(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, lastLogicalTop, lastLogicalLeft, lastLogicalRight, paintInfo);
+    else
+        result = blockSelectionGaps(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, lastLogicalTop, lastLogicalLeft, lastLogicalRight, 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 && (selectionState() != SelectionBoth && selectionState() != SelectionEnd))
+        result.uniteCenter(blockSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, lastLogicalTop, lastLogicalLeft, lastLogicalRight, 
+                                             logicalHeight(), paintInfo));
+    return result;
+}
+
+GapRects RenderBlock::inlineSelectionGaps(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
+                                          LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const PaintInfo* paintInfo)
+{
+    GapRects result;
+
+    bool containsStart = selectionState() == SelectionStart || selectionState() == SelectionBoth;
+
+    if (!firstLineBox()) {
+        if (containsStart) {
+            // Go ahead and update our lastLogicalTop to be the bottom of the block.  <hr>s or empty blocks with height can trip this
+            // case.
+            lastLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + logicalHeight();
+            lastLogicalLeft = logicalLeftSelectionOffset(rootBlock, logicalHeight());
+            lastLogicalRight = logicalRightSelectionOffset(rootBlock, logicalHeight());
+        }
+        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()) {
+        LayoutUnit selTop =  curr->selectionTopAdjustedForPrecedingBlock();
+        LayoutUnit selHeight = curr->selectionHeightAdjustedForPrecedingBlock();
+
+        if (!containsStart && !lastSelectedLine &&
+            selectionState() != SelectionStart && selectionState() != SelectionBoth)
+            result.uniteCenter(blockSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, lastLogicalTop, lastLogicalLeft, lastLogicalRight, 
+                                                 selTop, paintInfo));
+        
+        LayoutRect logicalRect(curr->logicalLeft(), selTop, curr->logicalWidth(), selTop + selHeight);
+        logicalRect.move(isHorizontalWritingMode() ? offsetFromRootBlock : offsetFromRootBlock.transposedSize());
+        LayoutRect physicalRect = rootBlock->logicalRectToPhysicalRect(rootBlockPhysicalPosition, logicalRect);
+        if (!paintInfo || (isHorizontalWritingMode() && physicalRect.y() < paintInfo->rect.maxY() && physicalRect.maxY() > paintInfo->rect.y())
+            || (!isHorizontalWritingMode() && physicalRect.x() < paintInfo->rect.maxX() && physicalRect.maxX() > paintInfo->rect.x()))
+            result.unite(curr->lineSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, selTop, selHeight, paintInfo));
+
+        lastSelectedLine = curr;
+    }
+
+    if (containsStart && !lastSelectedLine)
+        // VisibleSelection 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.
+        lastLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + lastSelectedLine->selectionBottom();
+        lastLogicalLeft = logicalLeftSelectionOffset(rootBlock, lastSelectedLine->selectionBottom());
+        lastLogicalRight = logicalRightSelectionOffset(rootBlock, lastSelectedLine->selectionBottom());
+    }
+    return result;
+}
+
+GapRects RenderBlock::blockSelectionGaps(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
+                                         LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const PaintInfo* paintInfo)
+{
+    GapRects result;
+
+    // Go ahead and jump right to the first block child that contains some selected objects.
+    RenderBox* curr;
+    for (curr = firstChildBox(); curr && curr->selectionState() == SelectionNone; curr = curr->nextSiblingBox()) { }
+
+    for (bool sawSelectionEnd = false; curr && !sawSelectionEnd; curr = curr->nextSiblingBox()) {
+        SelectionState childState = curr->selectionState();
+        if (childState == SelectionBoth || childState == SelectionEnd)
+            sawSelectionEnd = true;
+
+        if (curr->isFloatingOrOutOfFlowPositioned())
+            continue; // We must be a normal flow object in order to even be considered.
+
+        if (curr->hasPaintOffset() && curr->hasLayer()) {
+            // If the relposition offset is anything other than 0, then treat this just like an absolute positioned element.
+            // Just disregard it completely.
+            LayoutSize relOffset = curr->layer()->paintOffset();
+            if (relOffset.width() || relOffset.height())
+                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(blockSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, lastLogicalTop, lastLogicalLeft, lastLogicalRight, 
+                                                     curr->logicalTop(), 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;
+            getSelectionGapInfo(childState, leftGap, rightGap);
+
+            if (leftGap)
+                result.uniteLeft(logicalLeftSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, this, curr->logicalLeft(), curr->logicalTop(), curr->logicalHeight(), paintInfo));
+            if (rightGap)
+                result.uniteRight(logicalRightSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock, this, curr->logicalRight(), curr->logicalTop(), curr->logicalHeight(), paintInfo));
+
+            // Update lastLogicalTop to be just underneath the object.  lastLogicalLeft and lastLogicalRight 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.
+            lastLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + curr->logicalBottom();
+            lastLogicalLeft = logicalLeftSelectionOffset(rootBlock, curr->logicalBottom());
+            lastLogicalRight = logicalRightSelectionOffset(rootBlock, curr->logicalBottom());
+        } else if (childState != SelectionNone)
+            // We must be a block that has some selected object inside it.  Go ahead and recur.
+            result.unite(toRenderBlock(curr)->selectionGaps(rootBlock, rootBlockPhysicalPosition, LayoutSize(offsetFromRootBlock.width() + curr->x(), offsetFromRootBlock.height() + curr->y()), 
+                                                            lastLogicalTop, lastLogicalLeft, lastLogicalRight, paintInfo));
+    }
+    return result;
+}
+
+LayoutRect RenderBlock::blockSelectionGap(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
+                                          LayoutUnit lastLogicalTop, LayoutUnit lastLogicalLeft, LayoutUnit lastLogicalRight, LayoutUnit logicalBottom, const PaintInfo* paintInfo)
+{
+    LayoutUnit logicalTop = lastLogicalTop;
+    LayoutUnit logicalHeight = blockDirectionOffset(rootBlock, offsetFromRootBlock) + logicalBottom - logicalTop;
+    if (logicalHeight <= 0)
+        return LayoutRect();
+
+    // Get the selection offsets for the bottom of the gap
+    LayoutUnit logicalLeft = max(lastLogicalLeft, logicalLeftSelectionOffset(rootBlock, logicalBottom));
+    LayoutUnit logicalRight = min(lastLogicalRight, logicalRightSelectionOffset(rootBlock, logicalBottom));
+    LayoutUnit logicalWidth = logicalRight - logicalLeft;
+    if (logicalWidth <= 0)
+        return LayoutRect();
+
+    LayoutRect gapRect = rootBlock->logicalRectToPhysicalRect(rootBlockPhysicalPosition, LayoutRect(logicalLeft, logicalTop, logicalWidth, logicalHeight));
+    if (paintInfo)
+        paintInfo->context->fillRect(pixelSnappedIntRect(gapRect), selectionBackgroundColor(), style()->colorSpace());
+    return gapRect;
+}
+
+LayoutRect RenderBlock::logicalLeftSelectionGap(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
+                                                RenderObject* selObj, LayoutUnit logicalLeft, LayoutUnit logicalTop, LayoutUnit logicalHeight, const PaintInfo* paintInfo)
+{
+    LayoutUnit rootBlockLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + logicalTop;
+    LayoutUnit rootBlockLogicalLeft = max(logicalLeftSelectionOffset(rootBlock, logicalTop), logicalLeftSelectionOffset(rootBlock, logicalTop + logicalHeight));
+    LayoutUnit rootBlockLogicalRight = min(inlineDirectionOffset(rootBlock, offsetFromRootBlock) + floorToInt(logicalLeft), min(logicalRightSelectionOffset(rootBlock, logicalTop), logicalRightSelectionOffset(rootBlock, logicalTop + logicalHeight)));
+    LayoutUnit rootBlockLogicalWidth = rootBlockLogicalRight - rootBlockLogicalLeft;
+    if (rootBlockLogicalWidth <= 0)
+        return LayoutRect();
+
+    LayoutRect gapRect = rootBlock->logicalRectToPhysicalRect(rootBlockPhysicalPosition, LayoutRect(rootBlockLogicalLeft, rootBlockLogicalTop, rootBlockLogicalWidth, logicalHeight));
+    if (paintInfo)
+        paintInfo->context->fillRect(pixelSnappedIntRect(gapRect), selObj->selectionBackgroundColor(), selObj->style()->colorSpace());
+    return gapRect;
+}
+
+LayoutRect RenderBlock::logicalRightSelectionGap(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
+                                                 RenderObject* selObj, LayoutUnit logicalRight, LayoutUnit logicalTop, LayoutUnit logicalHeight, const PaintInfo* paintInfo)
+{
+    LayoutUnit rootBlockLogicalTop = blockDirectionOffset(rootBlock, offsetFromRootBlock) + logicalTop;
+    LayoutUnit rootBlockLogicalLeft = max(inlineDirectionOffset(rootBlock, offsetFromRootBlock) + floorToInt(logicalRight), max(logicalLeftSelectionOffset(rootBlock, logicalTop), logicalLeftSelectionOffset(rootBlock, logicalTop + logicalHeight)));
+    LayoutUnit rootBlockLogicalRight = min(logicalRightSelectionOffset(rootBlock, logicalTop), logicalRightSelectionOffset(rootBlock, logicalTop + logicalHeight));
+    LayoutUnit rootBlockLogicalWidth = rootBlockLogicalRight - rootBlockLogicalLeft;
+    if (rootBlockLogicalWidth <= 0)
+        return LayoutRect();
+
+    LayoutRect gapRect = rootBlock->logicalRectToPhysicalRect(rootBlockPhysicalPosition, LayoutRect(rootBlockLogicalLeft, rootBlockLogicalTop, rootBlockLogicalWidth, logicalHeight));
+    if (paintInfo)
+        paintInfo->context->fillRect(pixelSnappedIntRect(gapRect), selObj->selectionBackgroundColor(), selObj->style()->colorSpace());
+    return gapRect;
+}
+
+void RenderBlock::getSelectionGapInfo(SelectionState state, bool& leftGap, bool& rightGap)
+{
+    bool ltr = style()->isLeftToRightDirection();
+    leftGap = (state == RenderObject::SelectionInside) ||
+              (state == RenderObject::SelectionEnd && ltr) ||
+              (state == RenderObject::SelectionStart && !ltr);
+    rightGap = (state == RenderObject::SelectionInside) ||
+               (state == RenderObject::SelectionStart && ltr) ||
+               (state == RenderObject::SelectionEnd && !ltr);
+}
+
+LayoutUnit RenderBlock::logicalLeftSelectionOffset(RenderBlock* rootBlock, LayoutUnit position)
+{
+    LayoutUnit logicalLeft = logicalLeftOffsetForLine(position, false);
+    if (logicalLeft == logicalLeftOffsetForContent()) {
+        if (rootBlock != this)
+            // The border can potentially be further extended by our containingBlock().
+            return containingBlock()->logicalLeftSelectionOffset(rootBlock, position + logicalTop());
+        return logicalLeft;
+    } else {
+        RenderBlock* cb = this;
+        while (cb != rootBlock) {
+            logicalLeft += cb->logicalLeft();
+            cb = cb->containingBlock();
+        }
+    }
+    return logicalLeft;
+}
+
+LayoutUnit RenderBlock::logicalRightSelectionOffset(RenderBlock* rootBlock, LayoutUnit position)
+{
+    LayoutUnit logicalRight = logicalRightOffsetForLine(position, false);
+    if (logicalRight == logicalRightOffsetForContent()) {
+        if (rootBlock != this)
+            // The border can potentially be further extended by our containingBlock().
+            return containingBlock()->logicalRightSelectionOffset(rootBlock, position + logicalTop());
+        return logicalRight;
+    } else {
+        RenderBlock* cb = this;
+        while (cb != rootBlock) {
+            logicalRight += cb->logicalLeft();
+            cb = cb->containingBlock();
+        }
+    }
+    return logicalRight;
+}
+
+RenderBlock* RenderBlock::blockBeforeWithinSelectionRoot(LayoutSize& offset) const
+{
+    if (isSelectionRoot())
+        return 0;
+
+    const RenderObject* object = this;
+    RenderObject* sibling;
+    do {
+        sibling = object->previousSibling();
+        while (sibling && (!sibling->isRenderBlock() || toRenderBlock(sibling)->isSelectionRoot()))
+            sibling = sibling->previousSibling();
+
+        offset -= LayoutSize(toRenderBlock(object)->logicalLeft(), toRenderBlock(object)->logicalTop());
+        object = object->parent();
+    } while (!sibling && object && object->isRenderBlock() && !toRenderBlock(object)->isSelectionRoot());
+
+    if (!sibling)
+        return 0;
+
+    RenderBlock* beforeBlock = toRenderBlock(sibling);
+
+    offset += LayoutSize(beforeBlock->logicalLeft(), beforeBlock->logicalTop());
+
+    RenderObject* child = beforeBlock->lastChild();
+    while (child && child->isRenderBlock()) {
+        beforeBlock = toRenderBlock(child);
+        offset += LayoutSize(beforeBlock->logicalLeft(), beforeBlock->logicalTop());
+        child = beforeBlock->lastChild();
+    }
+    return beforeBlock;
+}
+
+void RenderBlock::insertIntoTrackedRendererMaps(RenderBox* descendant, TrackedDescendantsMap*& descendantsMap, TrackedContainerMap*& containerMap)
+{
+    if (!descendantsMap) {
+        descendantsMap = new TrackedDescendantsMap;
+        containerMap = new TrackedContainerMap;
+    }
+    
+    TrackedRendererListHashSet* descendantSet = descendantsMap->get(this);
+    if (!descendantSet) {
+        descendantSet = new TrackedRendererListHashSet;
+        descendantsMap->set(this, adoptPtr(descendantSet));
+    }
+    bool added = descendantSet->add(descendant).isNewEntry;
+    if (!added) {
+        ASSERT(containerMap->get(descendant));
+        ASSERT(containerMap->get(descendant)->contains(this));
+        return;
+    }
+    
+    HashSet<RenderBlock*>* containerSet = containerMap->get(descendant);
+    if (!containerSet) {
+        containerSet = new HashSet<RenderBlock*>;
+        containerMap->set(descendant, adoptPtr(containerSet));
+    }
+    ASSERT(!containerSet->contains(this));
+    containerSet->add(this);
+}
+
+void RenderBlock::removeFromTrackedRendererMaps(RenderBox* descendant, TrackedDescendantsMap*& descendantsMap, TrackedContainerMap*& containerMap)
+{
+    if (!descendantsMap)
+        return;
+    
+    OwnPtr<HashSet<RenderBlock*> > containerSet = containerMap->take(descendant);
+    if (!containerSet)
+        return;
+    
+    HashSet<RenderBlock*>::iterator end = containerSet->end();
+    for (HashSet<RenderBlock*>::iterator it = containerSet->begin(); it != end; ++it) {
+        RenderBlock* container = *it;
+
+        // FIXME: Disabling this assert temporarily until we fix the layout
+        // bugs associated with positioned objects not properly cleared from
+        // their ancestor chain before being moved. See webkit bug 93766.
+        // ASSERT(descendant->isDescendantOf(container));
+
+        TrackedDescendantsMap::iterator descendantsMapIterator = descendantsMap->find(container);
+        ASSERT(descendantsMapIterator != descendantsMap->end());
+        if (descendantsMapIterator == descendantsMap->end())
+            continue;
+        TrackedRendererListHashSet* descendantSet = descendantsMapIterator->value.get();
+        ASSERT(descendantSet->contains(descendant));
+        descendantSet->remove(descendant);
+        if (descendantSet->isEmpty())
+            descendantsMap->remove(descendantsMapIterator);
+    }
+}
+
+TrackedRendererListHashSet* RenderBlock::positionedObjects() const
+{
+    if (gPositionedDescendantsMap)
+        return gPositionedDescendantsMap->get(this);
+    return 0;
+}
+
+void RenderBlock::insertPositionedObject(RenderBox* o)
+{
+    ASSERT(!isAnonymousBlock());
+
+    if (o->isRenderFlowThread())
+        return;
+    
+    insertIntoTrackedRendererMaps(o, gPositionedDescendantsMap, gPositionedContainerMap);
+}
+
+void RenderBlock::removePositionedObject(RenderBox* o)
+{
+    removeFromTrackedRendererMaps(o, gPositionedDescendantsMap, gPositionedContainerMap);
+}
+
+void RenderBlock::removePositionedObjects(RenderBlock* o, ContainingBlockState containingBlockState)
+{
+    TrackedRendererListHashSet* positionedDescendants = positionedObjects();
+    if (!positionedDescendants)
+        return;
+    
+    RenderBox* r;
+    
+    TrackedRendererListHashSet::iterator end = positionedDescendants->end();
+    
+    Vector<RenderBox*, 16> deadObjects;
+
+    for (TrackedRendererListHashSet::iterator it = positionedDescendants->begin(); it != end; ++it) {
+        r = *it;
+        if (!o || r->isDescendantOf(o)) {
+            if (containingBlockState == NewContainingBlock)
+                r->setChildNeedsLayout(true, MarkOnlyThis);
+            
+            // 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++)
+        removePositionedObject(deadObjects.at(i));
+}
+
+void RenderBlock::removeFloatingObjects()
+{
+    if (!m_floatingObjects)
+        return;
+
+    deleteAllValues(m_floatingObjects->set());
+    m_floatingObjects->clear();
+}
+
+RenderBlock::FloatingObject* RenderBlock::insertFloatingObject(RenderBox* o)
+{
+    ASSERT(o->isFloating());
+
+    // Create the list of special objects if we don't aleady have one
+    if (!m_floatingObjects)
+        createFloatingObjects();
+    else {
+        // Don't insert the object again if it's already in the list
+        const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
+        FloatingObjectSetIterator it = floatingObjectSet.find<RenderBox*, FloatingObjectHashTranslator>(o);
+        if (it != floatingObjectSet.end())
+            return *it;
+    }
+
+    // Create the special object entry & append it to the list
+
+    FloatingObject* newObj = new FloatingObject(o->style()->floating());
+    
+    // Our location is irrelevant if we're unsplittable or no pagination is in effect.
+    // Just go ahead and lay out the float.
+    bool isChildRenderBlock = o->isRenderBlock();
+    if (isChildRenderBlock && !o->needsLayout() && view()->layoutState()->pageLogicalHeightChanged())
+        o->setChildNeedsLayout(true, MarkOnlyThis);
+            
+    bool needsBlockDirectionLocationSetBeforeLayout = isChildRenderBlock && view()->layoutState()->needsBlockDirectionLocationSetBeforeLayout();
+    if (!needsBlockDirectionLocationSetBeforeLayout || isWritingModeRoot()) // We are unsplittable if we're a block flow root.
+        o->layoutIfNeeded();
+    else {
+        o->updateLogicalWidth();
+        o->computeAndSetBlockDirectionMargins(this);
+    }
+
+    ExclusionShapeOutsideInfo* shapeOutside = o->exclusionShapeOutsideInfo();
+    if (shapeOutside) {
+        shapeOutside->setShapeSize(o->logicalWidth(), o->logicalHeight());
+        // The CSS Exclusions specification says that the margins are ignored
+        // when a float has a shape outside.
+        setLogicalWidthForFloat(newObj, shapeOutside->shapeLogicalWidth());
+    } else
+        setLogicalWidthForFloat(newObj, logicalWidthForChild(o) + marginStartForChild(o) + marginEndForChild(o));
+
+    newObj->setShouldPaint(!o->hasSelfPaintingLayer()); // If a layer exists, the float will paint itself. Otherwise someone else will.
+    newObj->setIsDescendant(true);
+    newObj->m_renderer = o;
+
+    m_floatingObjects->add(newObj);
+    
+    return newObj;
+}
+
+void RenderBlock::removeFloatingObject(RenderBox* o)
+{
+    if (m_floatingObjects) {
+        const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
+        FloatingObjectSetIterator it = floatingObjectSet.find<RenderBox*, FloatingObjectHashTranslator>(o);
+        if (it != floatingObjectSet.end()) {
+            FloatingObject* r = *it;
+            if (childrenInline()) {
+                LayoutUnit logicalTop = logicalTopForFloat(r);
+                LayoutUnit logicalBottom = logicalBottomForFloat(r);
+
+                // Fix for https://bugs.webkit.org/show_bug.cgi?id=54995.
+                if (logicalBottom < 0 || logicalBottom < logicalTop || logicalTop == LayoutUnit::max())
+                    logicalBottom = LayoutUnit::max();
+                else {
+                    // Special-case zero- and less-than-zero-height floats: those don't touch
+                    // the line that they're on, but it still needs to be dirtied. This is
+                    // accomplished by pretending they have a height of 1.
+                    logicalBottom = max(logicalBottom, logicalTop + 1);
+                }
+                if (r->m_originatingLine) {
+                    if (!selfNeedsLayout()) {
+                        ASSERT(r->m_originatingLine->renderer() == this);
+                        r->m_originatingLine->markDirty();
+                    }
+#if !ASSERT_DISABLED
+                    r->m_originatingLine = 0;
+#endif
+                }
+                markLinesDirtyInBlockRange(0, logicalBottom);
+            }
+            m_floatingObjects->remove(r);
+            ASSERT(!r->m_originatingLine);
+            delete r;
+        }
+    }
+}
+
+void RenderBlock::removeFloatingObjectsBelow(FloatingObject* lastFloat, int logicalOffset)
+{
+    if (!containsFloats())
+        return;
+    
+    const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
+    FloatingObject* curr = floatingObjectSet.last();
+    while (curr != lastFloat && (!curr->isPlaced() || logicalTopForFloat(curr) >= logicalOffset)) {
+        m_floatingObjects->remove(curr);
+        ASSERT(!curr->m_originatingLine);
+        delete curr;
+        if (floatingObjectSet.isEmpty())
+            break;
+        curr = floatingObjectSet.last();
+    }
+}
+
+LayoutPoint RenderBlock::computeLogicalLocationForFloat(const FloatingObject* floatingObject, LayoutUnit logicalTopOffset) const
+{
+    RenderBox* childBox = floatingObject->renderer();
+    LayoutUnit logicalLeftOffset = logicalLeftOffsetForContent(logicalTopOffset); // Constant part of left offset.
+    LayoutUnit logicalRightOffset; // Constant part of right offset.
+    // FIXME Bug 102948: This only works for shape outside directly set on this block.
+    ExclusionShapeInsideInfo* shapeInsideInfo = exclusionShapeInsideInfo();
+    // FIXME Bug 102846: Take into account the height of the content. The offset should be
+    // equal to the maximum segment length.
+    if (shapeInsideInfo && shapeInsideInfo->hasSegments() && shapeInsideInfo->segments().size() == 1) {
+        // FIXME Bug 102949: Add support for shapes with multipe segments.
+
+        // The segment offsets are relative to the content box.
+        logicalRightOffset = logicalLeftOffset + shapeInsideInfo->segments()[0].logicalRight;
+        logicalLeftOffset += shapeInsideInfo->segments()[0].logicalLeft;
+    } else
+        logicalRightOffset = logicalRightOffsetForContent(logicalTopOffset);
+
+    LayoutUnit floatLogicalWidth = min(logicalWidthForFloat(floatingObject), logicalRightOffset - logicalLeftOffset); // The width we look for.
+
+    LayoutUnit floatLogicalLeft;
+
+    bool insideFlowThread = flowThreadContainingBlock();
+
+    if (childBox->style()->floating() == LeftFloat) {
+        LayoutUnit heightRemainingLeft = 1;
+        LayoutUnit heightRemainingRight = 1;
+        floatLogicalLeft = logicalLeftOffsetForLine(logicalTopOffset, logicalLeftOffset, false, &heightRemainingLeft);
+        while (logicalRightOffsetForLine(logicalTopOffset, logicalRightOffset, false, &heightRemainingRight) - floatLogicalLeft < floatLogicalWidth) {
+            logicalTopOffset += min(heightRemainingLeft, heightRemainingRight);
+            floatLogicalLeft = logicalLeftOffsetForLine(logicalTopOffset, logicalLeftOffset, false, &heightRemainingLeft);
+            if (insideFlowThread) {
+                // Have to re-evaluate all of our offsets, since they may have changed.
+                logicalRightOffset = logicalRightOffsetForContent(logicalTopOffset); // Constant part of right offset.
+                logicalLeftOffset = logicalLeftOffsetForContent(logicalTopOffset); // Constant part of left offset.
+                floatLogicalWidth = min(logicalWidthForFloat(floatingObject), logicalRightOffset - logicalLeftOffset);
+            }
+        }
+        floatLogicalLeft = max(logicalLeftOffset - borderAndPaddingLogicalLeft(), floatLogicalLeft);
+    } else {
+        LayoutUnit heightRemainingLeft = 1;
+        LayoutUnit heightRemainingRight = 1;
+        floatLogicalLeft = logicalRightOffsetForLine(logicalTopOffset, logicalRightOffset, false, &heightRemainingRight);
+        while (floatLogicalLeft - logicalLeftOffsetForLine(logicalTopOffset, logicalLeftOffset, false, &heightRemainingLeft) < floatLogicalWidth) {
+            logicalTopOffset += min(heightRemainingLeft, heightRemainingRight);
+            floatLogicalLeft = logicalRightOffsetForLine(logicalTopOffset, logicalRightOffset, false, &heightRemainingRight);
+            if (insideFlowThread) {
+                // Have to re-evaluate all of our offsets, since they may have changed.
+                logicalRightOffset = logicalRightOffsetForContent(logicalTopOffset); // Constant part of right offset.
+                logicalLeftOffset = logicalLeftOffsetForContent(logicalTopOffset); // Constant part of left offset.
+                floatLogicalWidth = min(logicalWidthForFloat(floatingObject), logicalRightOffset - logicalLeftOffset);
+            }
+        }
+        floatLogicalLeft -= logicalWidthForFloat(floatingObject); // Use the original width of the float here, since the local variable
+                                                                  // |floatLogicalWidth| was capped to the available line width.
+                                                                  // See fast/block/float/clamped-right-float.html.
+    }
+    
+    return LayoutPoint(floatLogicalLeft, logicalTopOffset);
+}
+
+bool RenderBlock::positionNewFloats()
+{
+    if (!m_floatingObjects)
+        return false;
+
+    const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
+    if (floatingObjectSet.isEmpty())
+        return false;
+
+    // If all floats have already been positioned, then we have no work to do.
+    if (floatingObjectSet.last()->isPlaced())
+        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.
+    FloatingObjectSetIterator it = floatingObjectSet.end();
+    --it; // Go to last item.
+    FloatingObjectSetIterator begin = floatingObjectSet.begin();
+    FloatingObject* lastPlacedFloatingObject = 0;
+    while (it != begin) {
+        --it;
+        if ((*it)->isPlaced()) {
+            lastPlacedFloatingObject = *it;
+            ++it;
+            break;
+        }
+    }
+
+    LayoutUnit logicalTop = logicalHeight();
+    
+    // The float cannot start above the top position of the last positioned float.
+    if (lastPlacedFloatingObject)
+        logicalTop = max(logicalTopForFloat(lastPlacedFloatingObject), logicalTop);
+
+    FloatingObjectSetIterator end = floatingObjectSet.end();
+    // Now walk through the set of unpositioned floats and place them.
+    for (; it != end; ++it) {
+        FloatingObject* floatingObject = *it;
+        // 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 (floatingObject->renderer()->containingBlock() != this)
+            continue;
+
+        RenderBox* childBox = floatingObject->renderer();
+        LayoutUnit childLogicalLeftMargin = style()->isLeftToRightDirection() ? marginStartForChild(childBox) : marginEndForChild(childBox);
+
+        LayoutRect oldRect = childBox->frameRect();
+
+        if (childBox->style()->clear() & CLEFT)
+            logicalTop = max(lowestFloatLogicalBottom(FloatingObject::FloatLeft), logicalTop);
+        if (childBox->style()->clear() & CRIGHT)
+            logicalTop = max(lowestFloatLogicalBottom(FloatingObject::FloatRight), logicalTop);
+
+        LayoutPoint floatLogicalLocation = computeLogicalLocationForFloat(floatingObject, logicalTop);
+
+        setLogicalLeftForFloat(floatingObject, floatLogicalLocation.x());
+
+        setLogicalLeftForChild(childBox, floatLogicalLocation.x() + childLogicalLeftMargin);
+        setLogicalTopForChild(childBox, floatLogicalLocation.y() + marginBeforeForChild(childBox));
+
+        LayoutState* layoutState = view()->layoutState();
+        bool isPaginated = layoutState->isPaginated();
+        if (isPaginated && !childBox->needsLayout())
+            childBox->markForPaginationRelayoutIfNeeded();
+        
+        childBox->layoutIfNeeded();
+
+        if (isPaginated) {
+            // If we are unsplittable and don't fit, then we need to move down.
+            // We include our margins as part of the unsplittable area.
+            LayoutUnit newLogicalTop = adjustForUnsplittableChild(childBox, floatLogicalLocation.y(), true);
+            
+            // See if we have a pagination strut that is making us move down further.
+            // Note that an unsplittable child can't also have a pagination strut, so this is
+            // exclusive with the case above.
+            RenderBlock* childBlock = childBox->isRenderBlock() ? toRenderBlock(childBox) : 0;
+            if (childBlock && childBlock->paginationStrut()) {
+                newLogicalTop += childBlock->paginationStrut();
+                childBlock->setPaginationStrut(0);
+            }
+            
+            if (newLogicalTop != floatLogicalLocation.y()) {
+                floatingObject->m_paginationStrut = newLogicalTop - floatLogicalLocation.y();
+
+                floatLogicalLocation = computeLogicalLocationForFloat(floatingObject, newLogicalTop);
+                setLogicalLeftForFloat(floatingObject, floatLogicalLocation.x());
+
+                setLogicalLeftForChild(childBox, floatLogicalLocation.x() + childLogicalLeftMargin);
+                setLogicalTopForChild(childBox, floatLogicalLocation.y() + marginBeforeForChild(childBox));
+        
+                if (childBlock)
+                    childBlock->setChildNeedsLayout(true, MarkOnlyThis);
+                childBox->layoutIfNeeded();
+            }
+        }
+
+        setLogicalTopForFloat(floatingObject, floatLogicalLocation.y());
+        if (childBox->exclusionShapeOutsideInfo())
+            setLogicalHeightForFloat(floatingObject, childBox->exclusionShapeOutsideInfo()->shapeLogicalHeight());
+        else
+            setLogicalHeightForFloat(floatingObject, logicalHeightForChild(childBox) + marginBeforeForChild(childBox) + marginAfterForChild(childBox));
+
+        m_floatingObjects->addPlacedObject(floatingObject);
+
+        // If the child moved, we have to repaint it.
+        if (childBox->checkForRepaintDuringLayout())
+            childBox->repaintDuringLayoutIfMoved(oldRect);
+    }
+    return true;
+}
+
+void RenderBlock::newLine(EClear clear)
+{
+    positionNewFloats();
+    // set y position
+    LayoutUnit newY = 0;
+    switch (clear)
+    {
+        case CLEFT:
+            newY = lowestFloatLogicalBottom(FloatingObject::FloatLeft);
+            break;
+        case CRIGHT:
+            newY = lowestFloatLogicalBottom(FloatingObject::FloatRight);
+            break;
+        case CBOTH:
+            newY = lowestFloatLogicalBottom();
+        default:
+            break;
+    }
+    if (height() < newY)
+        setLogicalHeight(newY);
+}
+
+void RenderBlock::addPercentHeightDescendant(RenderBox* descendant)
+{
+    insertIntoTrackedRendererMaps(descendant, gPercentHeightDescendantsMap, gPercentHeightContainerMap);
+}
+
+void RenderBlock::removePercentHeightDescendant(RenderBox* descendant)
+{
+    removeFromTrackedRendererMaps(descendant, gPercentHeightDescendantsMap, gPercentHeightContainerMap);
+}
+
+TrackedRendererListHashSet* RenderBlock::percentHeightDescendants() const
+{
+    return gPercentHeightDescendantsMap ? gPercentHeightDescendantsMap->get(this) : 0;
+}
+
+bool RenderBlock::hasPercentHeightContainerMap()
+{
+    return gPercentHeightContainerMap;
+}
+
+bool RenderBlock::hasPercentHeightDescendant(RenderBox* descendant)
+{
+    // We don't null check gPercentHeightContainerMap since the caller
+    // already ensures this and we need to call this function on every
+    // descendant in clearPercentHeightDescendantsFrom().
+    ASSERT(gPercentHeightContainerMap);
+    return gPercentHeightContainerMap->contains(descendant);
+}
+
+void RenderBlock::removePercentHeightDescendantIfNeeded(RenderBox* descendant)
+{
+    // We query the map directly, rather than looking at style's
+    // logicalHeight()/logicalMinHeight()/logicalMaxHeight() since those
+    // can change with writing mode/directional changes.
+    if (!hasPercentHeightContainerMap())
+        return;
+
+    if (!hasPercentHeightDescendant(descendant))
+        return;
+
+    removePercentHeightDescendant(descendant);
+}
+
+void RenderBlock::clearPercentHeightDescendantsFrom(RenderBox* parent)
+{
+    ASSERT(gPercentHeightContainerMap);
+    for (RenderObject* curr = parent->firstChild(); curr; curr = curr->nextInPreOrder(parent)) {
+        if (!curr->isBox())
+            continue;
+ 
+        RenderBox* box = toRenderBox(curr);
+        if (!hasPercentHeightDescendant(box))
+            continue;
+
+        removePercentHeightDescendant(box);
+    }
+}
+
+static bool rangesIntersect(int floatTop, int floatBottom, int objectTop, int objectBottom)
+{
+    if (objectTop >= floatBottom || objectBottom < floatTop)
+        return false;
+
+    // The top of the object overlaps the float
+    if (objectTop >= floatTop)
+        return true;
+
+    // The object encloses the float
+    if (objectTop < floatTop && objectBottom > floatBottom)
+        return true;
+
+    // The bottom of the object overlaps the float
+    if (objectBottom > objectTop && objectBottom > floatTop && objectBottom <= floatBottom)
+        return true;
+
+    return false;
+}
+
+template <RenderBlock::FloatingObject::Type FloatTypeValue>
+inline void RenderBlock::FloatIntervalSearchAdapter<FloatTypeValue>::collectIfNeeded(const IntervalType& interval) const
+{
+    const FloatingObject* r = interval.data();
+    if (r->type() != FloatTypeValue || !rangesIntersect(interval.low(), interval.high(), m_lowValue, m_highValue))
+        return;
+
+    // All the objects returned from the tree should be already placed.
+    ASSERT(r->isPlaced() && rangesIntersect(m_renderer->pixelSnappedLogicalTopForFloat(r), m_renderer->pixelSnappedLogicalBottomForFloat(r), m_lowValue, m_highValue));
+
+    if (FloatTypeValue == FloatingObject::FloatLeft 
+        && m_renderer->logicalRightForFloat(r) > m_offset) {
+        m_offset = m_renderer->logicalRightForFloat(r);
+        if (m_heightRemaining)
+            *m_heightRemaining = m_renderer->logicalBottomForFloat(r) - m_lowValue;
+    }
+
+    if (FloatTypeValue == FloatingObject::FloatRight
+        && m_renderer->logicalLeftForFloat(r) < m_offset) {
+        m_offset = m_renderer->logicalLeftForFloat(r);
+        if (m_heightRemaining)
+            *m_heightRemaining = m_renderer->logicalBottomForFloat(r) - m_lowValue;
+    }
+
+    m_last = r;
+}
+
+LayoutUnit RenderBlock::textIndentOffset() const
+{
+    LayoutUnit cw = 0;
+    RenderView* renderView = 0;
+    if (style()->textIndent().isPercent())
+        cw = containingBlock()->availableLogicalWidth();
+    else if (style()->textIndent().isViewportPercentage())
+        renderView = view();
+    return minimumValueForLength(style()->textIndent(), cw, renderView);
+}
+
+LayoutUnit RenderBlock::logicalLeftOffsetForContent(RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage) const
+{
+    LayoutUnit logicalLeftOffset = style()->isHorizontalWritingMode() ? borderLeft() + paddingLeft() : borderTop() + paddingTop();
+    if (!region)
+        return logicalLeftOffset;
+    LayoutRect boxRect = borderBoxRectInRegion(region, offsetFromLogicalTopOfFirstPage);
+    return logicalLeftOffset + (isHorizontalWritingMode() ? boxRect.x() : boxRect.y());
+}
+
+LayoutUnit RenderBlock::logicalRightOffsetForContent(RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage) const
+{
+    LayoutUnit logicalRightOffset = style()->isHorizontalWritingMode() ? borderLeft() + paddingLeft() : borderTop() + paddingTop();
+    logicalRightOffset += availableLogicalWidth();
+    if (!region)
+        return logicalRightOffset;
+    LayoutRect boxRect = borderBoxRectInRegion(region, offsetFromLogicalTopOfFirstPage);
+    return logicalRightOffset - (logicalWidth() - (isHorizontalWritingMode() ? boxRect.maxX() : boxRect.maxY()));
+}
+
+LayoutUnit RenderBlock::logicalLeftOffsetForLine(LayoutUnit logicalTop, LayoutUnit fixedOffset, bool applyTextIndent, LayoutUnit* heightRemaining, LayoutUnit logicalHeight) const
+{
+    LayoutUnit left = fixedOffset;
+    if (m_floatingObjects && m_floatingObjects->hasLeftObjects()) {
+        if (heightRemaining)
+            *heightRemaining = 1;
+
+        FloatIntervalSearchAdapter<FloatingObject::FloatLeft> adapter(this, roundToInt(logicalTop), roundToInt(logicalTop + logicalHeight), left, heightRemaining);
+        m_floatingObjects->placedFloatsTree().allOverlapsWithAdapter(adapter);
+
+        if (const FloatingObject* lastFloat = adapter.lastFloat()) {
+            if (ExclusionShapeOutsideInfo* shapeOutside = lastFloat->renderer()->exclusionShapeOutsideInfo()) {
+                shapeOutside->computeSegmentsForLine(logicalTop - logicalTopForFloat(lastFloat) + shapeOutside->shapeLogicalTop(), logicalHeight);
+                left += shapeOutside->rightSegmentShapeBoundingBoxDelta();
+            }
+        }
+    }
+
+    if (applyTextIndent && style()->isLeftToRightDirection())
+        left += textIndentOffset();
+
+    if (style()->lineAlign() == LineAlignNone)
+        return left;
+    
+    // Push in our left offset so that it is aligned with the character grid.
+    LayoutState* layoutState = view()->layoutState();
+    if (!layoutState)
+        return left;
+
+    RenderBlock* lineGrid = layoutState->lineGrid();
+    if (!lineGrid || lineGrid->style()->writingMode() != style()->writingMode())
+        return left;
+
+    // FIXME: Should letter-spacing apply? This is complicated since it doesn't apply at the edge?
+    float maxCharWidth = lineGrid->style()->font().primaryFont()->maxCharWidth();
+    if (!maxCharWidth)
+        return left;
+
+    LayoutUnit lineGridOffset = lineGrid->isHorizontalWritingMode() ? layoutState->lineGridOffset().width(): layoutState->lineGridOffset().height();
+    LayoutUnit layoutOffset = lineGrid->isHorizontalWritingMode() ? layoutState->layoutOffset().width() : layoutState->layoutOffset().height();
+    
+    // Push in to the nearest character width.
+    // FIXME: This is wrong for RTL (https://bugs.webkit.org/show_bug.cgi?id=79945).
+    // FIXME: This doesn't work with columns or regions (https://bugs.webkit.org/show_bug.cgi?id=79942).
+    // FIXME: This doesn't work when the inline position of the object isn't set ahead of time.
+    // FIXME: Dynamic changes to the font or to the inline position need to result in a deep relayout.
+    // (https://bugs.webkit.org/show_bug.cgi?id=79944)
+    float remainder = fmodf(maxCharWidth - fmodf(left + layoutOffset - lineGridOffset, maxCharWidth), maxCharWidth);
+    left += remainder;
+    return left;
+}
+
+LayoutUnit RenderBlock::logicalRightOffsetForLine(LayoutUnit logicalTop, LayoutUnit fixedOffset, bool applyTextIndent, LayoutUnit* heightRemaining, LayoutUnit logicalHeight) const
+{
+    LayoutUnit right = fixedOffset;
+    if (m_floatingObjects && m_floatingObjects->hasRightObjects()) {
+        if (heightRemaining)
+            *heightRemaining = 1;
+
+        LayoutUnit rightFloatOffset = fixedOffset;
+        FloatIntervalSearchAdapter<FloatingObject::FloatRight> adapter(this, roundToInt(logicalTop), roundToInt(logicalTop + logicalHeight), rightFloatOffset, heightRemaining);
+        m_floatingObjects->placedFloatsTree().allOverlapsWithAdapter(adapter);
+
+        if (const FloatingObject* lastFloat = adapter.lastFloat()) {
+            if (ExclusionShapeOutsideInfo* shapeOutside = lastFloat->renderer()->exclusionShapeOutsideInfo()) {
+                shapeOutside->computeSegmentsForLine(logicalTop - logicalTopForFloat(lastFloat) + shapeOutside->shapeLogicalTop(), logicalHeight);
+                rightFloatOffset += shapeOutside->leftSegmentShapeBoundingBoxDelta();
+            }
+        }
+
+        right = min(right, rightFloatOffset);
+    }
+    
+    if (applyTextIndent && !style()->isLeftToRightDirection())
+        right -= textIndentOffset();
+    
+    if (style()->lineAlign() == LineAlignNone)
+        return right;
+    
+    // Push in our right offset so that it is aligned with the character grid.
+    LayoutState* layoutState = view()->layoutState();
+    if (!layoutState)
+        return right;
+
+    RenderBlock* lineGrid = layoutState->lineGrid();
+    if (!lineGrid || lineGrid->style()->writingMode() != style()->writingMode())
+        return right;
+
+    // FIXME: Should letter-spacing apply? This is complicated since it doesn't apply at the edge?
+    float maxCharWidth = lineGrid->style()->font().primaryFont()->maxCharWidth();
+    if (!maxCharWidth)
+        return right;
+
+    LayoutUnit lineGridOffset = lineGrid->isHorizontalWritingMode() ? layoutState->lineGridOffset().width(): layoutState->lineGridOffset().height();
+    LayoutUnit layoutOffset = lineGrid->isHorizontalWritingMode() ? layoutState->layoutOffset().width() : layoutState->layoutOffset().height();
+    
+    // Push in to the nearest character width.
+    // FIXME: This is wrong for RTL (https://bugs.webkit.org/show_bug.cgi?id=79945).
+    // FIXME: This doesn't work with columns or regions (https://bugs.webkit.org/show_bug.cgi?id=79942).
+    // FIXME: This doesn't work when the inline position of the object isn't set ahead of time.
+    // FIXME: Dynamic changes to the font or to the inline position need to result in a deep relayout.
+    // (https://bugs.webkit.org/show_bug.cgi?id=79944)
+    float remainder = fmodf(fmodf(right + layoutOffset - lineGridOffset, maxCharWidth), maxCharWidth);
+    right -= LayoutUnit::fromFloatCeil(remainder);
+    return right;
+}
+
+LayoutUnit RenderBlock::nextFloatLogicalBottomBelow(LayoutUnit logicalHeight) const
+{
+    if (!m_floatingObjects)
+        return logicalHeight;
+
+    LayoutUnit bottom = LayoutUnit::max();
+    const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
+    FloatingObjectSetIterator end = floatingObjectSet.end();
+    for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
+        FloatingObject* r = *it;
+        LayoutUnit floatBottom = logicalBottomForFloat(r);
+        if (floatBottom > logicalHeight)
+            bottom = min(floatBottom, bottom);
+    }
+
+    return bottom == LayoutUnit::max() ? LayoutUnit() : bottom;
+}
+
+LayoutUnit RenderBlock::lowestFloatLogicalBottom(FloatingObject::Type floatType) const
+{
+    if (!m_floatingObjects)
+        return 0;
+    LayoutUnit lowestFloatBottom = 0;
+    const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
+    FloatingObjectSetIterator end = floatingObjectSet.end();
+    for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
+        FloatingObject* r = *it;
+        if (r->isPlaced() && r->type() & floatType)
+            lowestFloatBottom = max(lowestFloatBottom, logicalBottomForFloat(r));
+    }
+    return lowestFloatBottom;
+}
+
+void RenderBlock::markLinesDirtyInBlockRange(LayoutUnit logicalTop, LayoutUnit logicalBottom, RootInlineBox* highest)
+{
+    if (logicalTop >= logicalBottom)
+        return;
+
+    RootInlineBox* lowestDirtyLine = lastRootBox();
+    RootInlineBox* afterLowest = lowestDirtyLine;
+    while (lowestDirtyLine && lowestDirtyLine->lineBottomWithLeading() >= logicalBottom && logicalBottom < LayoutUnit::max()) {
+        afterLowest = lowestDirtyLine;
+        lowestDirtyLine = lowestDirtyLine->prevRootBox();
+    }
+
+    while (afterLowest && afterLowest != highest && (afterLowest->lineBottomWithLeading() >= logicalTop || afterLowest->lineBottomWithLeading() < 0)) {
+        afterLowest->markDirty();
+        afterLowest = afterLowest->prevRootBox();
+    }
+}
+
+void RenderBlock::clearFloats()
+{
+    if (m_floatingObjects)
+        m_floatingObjects->setHorizontalWritingMode(isHorizontalWritingMode());
+
+    HashSet<RenderBox*> oldIntrudingFloatSet;
+    if (!childrenInline() && m_floatingObjects) {
+        const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
+        FloatingObjectSetIterator end = floatingObjectSet.end();
+        for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
+            FloatingObject* floatingObject = *it;
+            if (!floatingObject->isDescendant())
+                oldIntrudingFloatSet.add(floatingObject->m_renderer);
+        }
+    }
+
+    // Inline blocks are covered by the isReplaced() check in the avoidFloats method.
+    if (avoidsFloats() || isRoot() || isRenderView() || isFloatingOrOutOfFlowPositioned() || isTableCell()) {
+        if (m_floatingObjects) {
+            deleteAllValues(m_floatingObjects->set());
+            m_floatingObjects->clear();
+        }
+        if (!oldIntrudingFloatSet.isEmpty())
+            markAllDescendantsWithFloatsForLayout();
+        return;
+    }
+
+    typedef HashMap<RenderObject*, FloatingObject*> RendererToFloatInfoMap;
+    RendererToFloatInfoMap floatMap;
+
+    if (m_floatingObjects) {
+        const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
+        if (childrenInline()) {
+            FloatingObjectSetIterator end = floatingObjectSet.end();
+            for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
+                FloatingObject* f = *it;
+                floatMap.add(f->m_renderer, f);
+            }
+        } else
+            deleteAllValues(floatingObjectSet);
+        m_floatingObjects->clear();
+    }
+
+    // We should not process floats if the parent node is not a RenderBlock. Otherwise, we will add 
+    // floats in an invalid context. This will cause a crash arising from a bad cast on the parent.
+    // See <rdar://problem/8049753>, where float property is applied on a text node in a SVG.
+    if (!parent() || !parent()->isRenderBlock())
+        return;
+
+    // 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.
+    RenderBlock* parentBlock = toRenderBlock(parent());
+    bool parentHasFloats = false;
+    RenderObject* prev = previousSibling();
+    while (prev && (prev->isFloatingOrOutOfFlowPositioned() || !prev->isBox() || !prev->isRenderBlock() || toRenderBlock(prev)->avoidsFloats())) {
+        if (prev->isFloating())
+            parentHasFloats = true;
+        prev = prev->previousSibling();
+    }
+
+    // First add in floats from the parent.
+    LayoutUnit logicalTopOffset = logicalTop();
+    if (parentHasFloats)
+        addIntrudingFloats(parentBlock, parentBlock->logicalLeftOffsetForContent(), logicalTopOffset);
+    
+    LayoutUnit logicalLeftOffset = 0;
+    if (prev)
+        logicalTopOffset -= toRenderBox(prev)->logicalTop();
+    else {
+        prev = parentBlock;
+        logicalLeftOffset += parentBlock->logicalLeftOffsetForContent();
+    }
+
+    // Add overhanging floats from the previous RenderBlock, but only if it has a float that intrudes into our space.    
+    RenderBlock* block = toRenderBlock(prev);
+    if (block->m_floatingObjects && block->lowestFloatLogicalBottom() > logicalTopOffset)
+        addIntrudingFloats(block, logicalLeftOffset, logicalTopOffset);
+
+    if (childrenInline()) {
+        LayoutUnit changeLogicalTop = LayoutUnit::max();
+        LayoutUnit changeLogicalBottom = LayoutUnit::min();
+        if (m_floatingObjects) {
+            const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
+            FloatingObjectSetIterator end = floatingObjectSet.end();
+            for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
+                FloatingObject* f = *it;
+                FloatingObject* oldFloatingObject = floatMap.get(f->m_renderer);
+                LayoutUnit logicalBottom = logicalBottomForFloat(f);
+                if (oldFloatingObject) {
+                    LayoutUnit oldLogicalBottom = logicalBottomForFloat(oldFloatingObject);
+                    if (logicalWidthForFloat(f) != logicalWidthForFloat(oldFloatingObject) || logicalLeftForFloat(f) != logicalLeftForFloat(oldFloatingObject)) {
+                        changeLogicalTop = 0;
+                        changeLogicalBottom = max(changeLogicalBottom, max(logicalBottom, oldLogicalBottom));
+                    } else {
+                        if (logicalBottom != oldLogicalBottom) {
+                            changeLogicalTop = min(changeLogicalTop, min(logicalBottom, oldLogicalBottom));
+                            changeLogicalBottom = max(changeLogicalBottom, max(logicalBottom, oldLogicalBottom));
+                        }
+                        LayoutUnit logicalTop = logicalTopForFloat(f);
+                        LayoutUnit oldLogicalTop = logicalTopForFloat(oldFloatingObject);
+                        if (logicalTop != oldLogicalTop) {
+                            changeLogicalTop = min(changeLogicalTop, min(logicalTop, oldLogicalTop));
+                            changeLogicalBottom = max(changeLogicalBottom, max(logicalTop, oldLogicalTop));
+                        }
+                    }
+
+                    floatMap.remove(f->m_renderer);
+                    if (oldFloatingObject->m_originatingLine && !selfNeedsLayout()) {
+                        ASSERT(oldFloatingObject->m_originatingLine->renderer() == this);
+                        oldFloatingObject->m_originatingLine->markDirty();
+                    }
+                    delete oldFloatingObject;
+                } else {
+                    changeLogicalTop = 0;
+                    changeLogicalBottom = max(changeLogicalBottom, logicalBottom);
+                }
+            }
+        }
+
+        RendererToFloatInfoMap::iterator end = floatMap.end();
+        for (RendererToFloatInfoMap::iterator it = floatMap.begin(); it != end; ++it) {
+            FloatingObject* floatingObject = (*it).value;
+            if (!floatingObject->isDescendant()) {
+                changeLogicalTop = 0;
+                changeLogicalBottom = max(changeLogicalBottom, logicalBottomForFloat(floatingObject));
+            }
+        }
+        deleteAllValues(floatMap);
+
+        markLinesDirtyInBlockRange(changeLogicalTop, changeLogicalBottom);
+    } else if (!oldIntrudingFloatSet.isEmpty()) {
+        // If there are previously intruding floats that no longer intrude, then children with floats
+        // should also get layout because they might need their floating object lists cleared.
+        if (m_floatingObjects->set().size() < oldIntrudingFloatSet.size())
+            markAllDescendantsWithFloatsForLayout();
+        else {
+            const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
+            FloatingObjectSetIterator end = floatingObjectSet.end();
+            for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end && !oldIntrudingFloatSet.isEmpty(); ++it)
+                oldIntrudingFloatSet.remove((*it)->m_renderer);
+            if (!oldIntrudingFloatSet.isEmpty())
+                markAllDescendantsWithFloatsForLayout();
+        }
+    }
+}
+
+LayoutUnit RenderBlock::addOverhangingFloats(RenderBlock* child, bool makeChildPaintOtherFloats)
+{
+    // Prevent floats from being added to the canvas by the root element, e.g., <html>.
+    if (child->hasOverflowClip() || !child->containsFloats() || child->isRoot() || child->hasColumns() || child->isWritingModeRoot())
+        return 0;
+
+    LayoutUnit childLogicalTop = child->logicalTop();
+    LayoutUnit childLogicalLeft = child->logicalLeft();
+    LayoutUnit lowestFloatLogicalBottom = 0;
+
+    // Floats that will remain the child's responsibility to paint should factor into its
+    // overflow.
+    FloatingObjectSetIterator childEnd = child->m_floatingObjects->set().end();
+    for (FloatingObjectSetIterator childIt = child->m_floatingObjects->set().begin(); childIt != childEnd; ++childIt) {
+        FloatingObject* r = *childIt;
+        LayoutUnit logicalBottomForFloat = min(this->logicalBottomForFloat(r), LayoutUnit::max() - childLogicalTop);
+        LayoutUnit logicalBottom = childLogicalTop + logicalBottomForFloat;
+        lowestFloatLogicalBottom = max(lowestFloatLogicalBottom, logicalBottom);
+
+        if (logicalBottom > logicalHeight()) {
+            // If the object is not in the list, we add it now.
+            if (!containsFloat(r->m_renderer)) {
+                LayoutSize offset = isHorizontalWritingMode() ? LayoutSize(-childLogicalLeft, -childLogicalTop) : LayoutSize(-childLogicalTop, -childLogicalLeft);
+                FloatingObject* floatingObj = new FloatingObject(r->type(), LayoutRect(r->frameRect().location() - offset, r->frameRect().size()));
+                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 self-painting layer boundary.
+                if (r->m_renderer->enclosingFloatPaintingLayer() == enclosingFloatPaintingLayer())
+                    r->setShouldPaint(false);
+                else
+                    floatingObj->setShouldPaint(false);
+
+                floatingObj->setIsDescendant(true);
+
+                // We create the floating object list lazily.
+                if (!m_floatingObjects)
+                    createFloatingObjects();
+                m_floatingObjects->add(floatingObj);
+            }
+        } else {
+            if (makeChildPaintOtherFloats && !r->shouldPaint() && !r->m_renderer->hasSelfPaintingLayer()
+                && r->m_renderer->isDescendantOf(child) && r->m_renderer->enclosingFloatPaintingLayer() == child->enclosingFloatPaintingLayer()) {
+                // 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->setShouldPaint(true);
+            }
+            
+            // Since the float doesn't overhang, it didn't get put into our list.  We need to go ahead and add its overflow in to the
+            // child now.
+            if (r->isDescendant())
+                child->addOverflowFromChild(r->m_renderer, LayoutSize(xPositionForFloatIncludingMargin(r), yPositionForFloatIncludingMargin(r)));
+        }
+    }
+    return lowestFloatLogicalBottom;
+}
+
+bool RenderBlock::hasOverhangingFloat(RenderBox* renderer)
+{
+    if (!m_floatingObjects || hasColumns() || !parent())
+        return false;
+
+    const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
+    FloatingObjectSetIterator it = floatingObjectSet.find<RenderBox*, FloatingObjectHashTranslator>(renderer);
+    if (it == floatingObjectSet.end())
+        return false;
+
+    return logicalBottomForFloat(*it) > logicalHeight();
+}
+
+void RenderBlock::addIntrudingFloats(RenderBlock* prev, LayoutUnit logicalLeftOffset, LayoutUnit logicalTopOffset)
+{
+    ASSERT(!avoidsFloats());
+
+    // If the parent or previous sibling doesn't have any floats to add, don't bother.
+    if (!prev->m_floatingObjects)
+        return;
+
+    logicalLeftOffset += marginLogicalLeft();
+
+    const FloatingObjectSet& prevSet = prev->m_floatingObjects->set();
+    FloatingObjectSetIterator prevEnd = prevSet.end();
+    for (FloatingObjectSetIterator prevIt = prevSet.begin(); prevIt != prevEnd; ++prevIt) {
+        FloatingObject* r = *prevIt;
+        if (logicalBottomForFloat(r) > logicalTopOffset) {
+            if (!m_floatingObjects || !m_floatingObjects->set().contains(r)) {
+                LayoutSize offset = isHorizontalWritingMode() ? LayoutSize(logicalLeftOffset, logicalTopOffset) : LayoutSize(logicalTopOffset, logicalLeftOffset);
+                FloatingObject* floatingObj = new FloatingObject(r->type(), LayoutRect(r->frameRect().location() - offset, r->frameRect().size()));
+
+                // Applying the child's margin makes no sense in the case where the child was passed in.
+                // since this margin was added already through the modification of the |logicalLeftOffset| variable
+                // above.  |logicalLeftOffset| will equal the margin in this case, so it's already been taken
+                // into account.  Only apply this code if prev is the parent, since otherwise the left margin
+                // will get applied twice.
+                if (prev != parent()) {
+                    if (isHorizontalWritingMode())
+                        floatingObj->setX(floatingObj->x() + prev->marginLeft());
+                    else
+                        floatingObj->setY(floatingObj->y() + prev->marginTop());
+                }
+               
+                floatingObj->setShouldPaint(false); // We are not in the direct inheritance chain for this float. We will never paint it.
+                floatingObj->m_renderer = r->m_renderer;
+                
+                // We create the floating object list lazily.
+                if (!m_floatingObjects)
+                    createFloatingObjects();
+                m_floatingObjects->add(floatingObj);
+            }
+        }
+    }
+}
+
+bool RenderBlock::avoidsFloats() const
+{
+    // Floats can't intrude into our box if we have a non-auto column count or width.
+    return RenderBox::avoidsFloats() || !style()->hasAutoColumnCount() || !style()->hasAutoColumnWidth();
+}
+
+bool RenderBlock::containsFloat(RenderBox* renderer) const
+{
+    return m_floatingObjects && m_floatingObjects->set().contains<RenderBox*, FloatingObjectHashTranslator>(renderer);
+}
+
+void RenderBlock::markAllDescendantsWithFloatsForLayout(RenderBox* floatToRemove, bool inLayout)
+{
+    if (!everHadLayout())
+        return;
+
+    MarkingBehavior markParents = inLayout ? MarkOnlyThis : MarkContainingBlockChain;
+    setChildNeedsLayout(true, markParents);
+ 
+    if (floatToRemove)
+        removeFloatingObject(floatToRemove);
+
+    // Iterate over our children and mark them as needed.
+    if (!childrenInline()) {
+        for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+            if ((!floatToRemove && child->isFloatingOrOutOfFlowPositioned()) || !child->isRenderBlock())
+                continue;
+            RenderBlock* childBlock = toRenderBlock(child);
+            if ((floatToRemove ? childBlock->containsFloat(floatToRemove) : childBlock->containsFloats()) || childBlock->shrinkToAvoidFloats())
+                childBlock->markAllDescendantsWithFloatsForLayout(floatToRemove, inLayout);
+        }
+    }
+}
+
+void RenderBlock::markSiblingsWithFloatsForLayout(RenderBox* floatToRemove)
+{
+    if (!m_floatingObjects)
+        return;
+
+    const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
+    FloatingObjectSetIterator end = floatingObjectSet.end();
+
+    for (RenderObject* next = nextSibling(); next; next = next->nextSibling()) {
+        if (!next->isRenderBlock() || next->isFloatingOrOutOfFlowPositioned() || toRenderBlock(next)->avoidsFloats())
+            continue;
+
+        RenderBlock* nextBlock = toRenderBlock(next);
+        for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
+            RenderBox* floatingBox = (*it)->renderer();
+            if (floatToRemove && floatingBox != floatToRemove)
+                continue;
+            if (nextBlock->containsFloat(floatingBox))
+                nextBlock->markAllDescendantsWithFloatsForLayout(floatingBox);
+        }
+    }
+}
+
+LayoutUnit RenderBlock::getClearDelta(RenderBox* child, LayoutUnit logicalTop)
+{
+    // 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;
+    LayoutUnit logicalBottom = 0;
+    switch (child->style()->clear()) {
+        case CNONE:
+            break;
+        case CLEFT:
+            logicalBottom = lowestFloatLogicalBottom(FloatingObject::FloatLeft);
+            break;
+        case CRIGHT:
+            logicalBottom = lowestFloatLogicalBottom(FloatingObject::FloatRight);
+            break;
+        case CBOTH:
+            logicalBottom = lowestFloatLogicalBottom();
+            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).
+    LayoutUnit result = clearSet ? max<LayoutUnit>(0, logicalBottom - logicalTop) : LayoutUnit();
+    if (!result && child->avoidsFloats()) {
+        LayoutUnit newLogicalTop = logicalTop;
+        while (true) {
+            LayoutUnit availableLogicalWidthAtNewLogicalTopOffset = availableLogicalWidthForLine(newLogicalTop, false, logicalHeightForChild(child));
+            if (availableLogicalWidthAtNewLogicalTopOffset == availableLogicalWidthForContent(newLogicalTop))
+                return newLogicalTop - logicalTop;
+
+            RenderRegion* region = regionAtBlockOffset(logicalTopForChild(child));
+            LayoutRect borderBox = child->borderBoxRectInRegion(region, offsetFromLogicalTopOfFirstPage() + logicalTopForChild(child), DoNotCacheRenderBoxRegionInfo);
+            LayoutUnit childLogicalWidthAtOldLogicalTopOffset = isHorizontalWritingMode() ? borderBox.width() : borderBox.height();
+
+            // FIXME: None of this is right for perpendicular writing-mode children.
+            LayoutUnit childOldLogicalWidth = child->logicalWidth();
+            LayoutUnit childOldMarginLeft = child->marginLeft();
+            LayoutUnit childOldMarginRight = child->marginRight();
+            LayoutUnit childOldLogicalTop = child->logicalTop();
+
+            child->setLogicalTop(newLogicalTop);
+            child->updateLogicalWidth();
+            region = regionAtBlockOffset(logicalTopForChild(child));
+            borderBox = child->borderBoxRectInRegion(region, offsetFromLogicalTopOfFirstPage() + logicalTopForChild(child), DoNotCacheRenderBoxRegionInfo);
+            LayoutUnit childLogicalWidthAtNewLogicalTopOffset = isHorizontalWritingMode() ? borderBox.width() : borderBox.height();
+
+            child->setLogicalTop(childOldLogicalTop);
+            child->setLogicalWidth(childOldLogicalWidth);
+            child->setMarginLeft(childOldMarginLeft);
+            child->setMarginRight(childOldMarginRight);
+            
+            if (childLogicalWidthAtNewLogicalTopOffset <= availableLogicalWidthAtNewLogicalTopOffset) {
+                // Even though we may not be moving, if the logical width did shrink because of the presence of new floats, then
+                // we need to force a relayout as though we shifted. This happens because of the dynamic addition of overhanging floats
+                // from previous siblings when negative margins exist on a child (see the addOverhangingFloats call at the end of collapseMargins).
+                if (childLogicalWidthAtOldLogicalTopOffset != childLogicalWidthAtNewLogicalTopOffset)
+                    child->setChildNeedsLayout(true, MarkOnlyThis);
+                return newLogicalTop - logicalTop;
+            }
+
+            newLogicalTop = nextFloatLogicalBottomBelow(newLogicalTop);
+            ASSERT(newLogicalTop >= logicalTop);
+            if (newLogicalTop < logicalTop)
+                break;
+        }
+        ASSERT_NOT_REACHED();
+    }
+    return result;
+}
+
+bool RenderBlock::isPointInOverflowControl(HitTestResult& result, const LayoutPoint& locationInContainer, const LayoutPoint& accumulatedOffset)
+{
+    if (!scrollsOverflow())
+        return false;
+
+    return layer()->hitTestOverflowControls(result, roundedIntPoint(locationInContainer - toLayoutSize(accumulatedOffset)));
+}
+
+Node* RenderBlock::nodeForHitTest() const
+{
+    // If we are in the margins of block elements that are part of a
+    // continuation we're actually still inside the enclosing element
+    // that was split. Use the appropriate inner node.
+    return isAnonymousBlockContinuation() ? continuation()->node() : node();
+}
+
+bool RenderBlock::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
+{
+    LayoutPoint adjustedLocation(accumulatedOffset + location());
+    LayoutSize localOffset = toLayoutSize(adjustedLocation);
+
+    if (!isRenderView()) {
+        // Check if we need to do anything at all.
+        LayoutRect overflowBox = visualOverflowRect();
+        flipForWritingMode(overflowBox);
+        overflowBox.moveBy(adjustedLocation);
+        if (!locationInContainer.intersects(overflowBox))
+            return false;
+    }
+
+    if ((hitTestAction == HitTestBlockBackground || hitTestAction == HitTestChildBlockBackground) && isPointInOverflowControl(result, locationInContainer.point(), adjustedLocation)) {
+        updateHitTestResult(result, locationInContainer.point() - localOffset);
+        // FIXME: isPointInOverflowControl() doesn't handle rect-based tests yet.
+        if (!result.addNodeToRectBasedTestResult(nodeForHitTest(), request, locationInContainer))
+           return true;
+    }
+
+    // If we have clipping, then we can't have any spillout.
+    bool useOverflowClip = hasOverflowClip() && !hasSelfPaintingLayer();
+    bool useClip = (hasControlClip() || useOverflowClip);
+    bool checkChildren = !useClip || (hasControlClip() ? locationInContainer.intersects(controlClipRect(adjustedLocation)) : locationInContainer.intersects(overflowClipRect(adjustedLocation, locationInContainer.region(), IncludeOverlayScrollbarSize)));
+    if (checkChildren) {
+        // Hit test descendants first.
+        LayoutSize scrolledOffset(localOffset);
+        if (hasOverflowClip())
+            scrolledOffset -= scrolledContentOffset();
+
+        // Hit test contents if we don't have columns.
+        if (!hasColumns()) {
+            if (hitTestContents(request, result, locationInContainer, toLayoutPoint(scrolledOffset), hitTestAction)) {
+                updateHitTestResult(result, flipForWritingMode(locationInContainer.point() - localOffset));
+                return true;
+            }
+            if (hitTestAction == HitTestFloat && hitTestFloats(request, result, locationInContainer, toLayoutPoint(scrolledOffset)))
+                return true;
+        } else if (hitTestColumns(request, result, locationInContainer, toLayoutPoint(scrolledOffset), hitTestAction)) {
+            updateHitTestResult(result, flipForWritingMode(locationInContainer.point() - localOffset));
+            return true;
+        }
+    }
+
+    // Check if the point is outside radii.
+    if (!isRenderView() && style()->hasBorderRadius()) {
+        LayoutRect borderRect = borderBoxRect();
+        borderRect.moveBy(adjustedLocation);
+        RoundedRect border = style()->getRoundedBorderFor(borderRect, view());
+        if (!locationInContainer.intersects(border))
+            return false;
+    }
+
+    // Now hit test our background
+    if (hitTestAction == HitTestBlockBackground || hitTestAction == HitTestChildBlockBackground) {
+        LayoutRect boundsRect(adjustedLocation, size());
+        if (visibleToHitTestRequest(request) && locationInContainer.intersects(boundsRect)) {
+            updateHitTestResult(result, flipForWritingMode(locationInContainer.point() - localOffset));
+            if (!result.addNodeToRectBasedTestResult(nodeForHitTest(), request, locationInContainer, boundsRect))
+                return true;
+        }
+    }
+
+    return false;
+}
+
+bool RenderBlock::hitTestFloats(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset)
+{
+    if (!m_floatingObjects)
+        return false;
+
+    LayoutPoint adjustedLocation = accumulatedOffset;
+    if (isRenderView()) {
+        adjustedLocation += toLayoutSize(toRenderView(this)->frameView()->scrollPosition());
+    }
+
+    const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
+    FloatingObjectSetIterator begin = floatingObjectSet.begin();
+    for (FloatingObjectSetIterator it = floatingObjectSet.end(); it != begin;) {
+        --it;
+        FloatingObject* floatingObject = *it;
+        if (floatingObject->shouldPaint() && !floatingObject->m_renderer->hasSelfPaintingLayer()) {
+            LayoutUnit xOffset = xPositionForFloatIncludingMargin(floatingObject) - floatingObject->m_renderer->x();
+            LayoutUnit yOffset = yPositionForFloatIncludingMargin(floatingObject) - floatingObject->m_renderer->y();
+            LayoutPoint childPoint = flipFloatForWritingModeForChild(floatingObject, adjustedLocation + LayoutSize(xOffset, yOffset));
+            if (floatingObject->m_renderer->hitTest(request, result, locationInContainer, childPoint)) {
+                updateHitTestResult(result, locationInContainer.point() - toLayoutSize(childPoint));
+                return true;
+            }
+        }
+    }
+
+    return false;
+}
+
+class ColumnRectIterator {
+    WTF_MAKE_NONCOPYABLE(ColumnRectIterator);
+public:
+    ColumnRectIterator(const RenderBlock& block)
+        : m_block(block)
+        , m_colInfo(block.columnInfo())
+        , m_direction(m_block.style()->isFlippedBlocksWritingMode() ? 1 : -1)
+        , m_isHorizontal(block.isHorizontalWritingMode())
+        , m_logicalLeft(block.logicalLeftOffsetForContent())
+    {
+        int colCount = m_colInfo->columnCount();
+        m_colIndex = colCount - 1;
+        m_currLogicalTopOffset = colCount * m_colInfo->columnHeight() * m_direction;
+        update();
+    }
+
+    void advance()
+    {
+        ASSERT(hasMore());
+        m_colIndex--;
+        update();
+    }
+
+    LayoutRect columnRect() const { return m_colRect; }
+    bool hasMore() const { return m_colIndex >= 0; }
+
+    void adjust(LayoutSize& offset) const
+    {
+        LayoutUnit currLogicalLeftOffset = (m_isHorizontal ? m_colRect.x() : m_colRect.y()) - m_logicalLeft;
+        offset += m_isHorizontal ? LayoutSize(currLogicalLeftOffset, m_currLogicalTopOffset) : LayoutSize(m_currLogicalTopOffset, currLogicalLeftOffset);
+        if (m_colInfo->progressionAxis() == ColumnInfo::BlockAxis) {
+            if (m_isHorizontal)
+                offset.expand(0, m_colRect.y() - m_block.borderTop() - m_block.paddingTop());
+            else
+                offset.expand(m_colRect.x() - m_block.borderLeft() - m_block.paddingLeft(), 0);
+        }
+    }
+
+private:
+    void update()
+    {
+        if (m_colIndex < 0)
+            return;
+
+        m_colRect = m_block.columnRectAt(const_cast<ColumnInfo*>(m_colInfo), m_colIndex);
+        m_block.flipForWritingMode(m_colRect);
+        m_currLogicalTopOffset -= (m_isHorizontal ? m_colRect.height() : m_colRect.width()) * m_direction;
+    }
+
+    const RenderBlock& m_block;
+    const ColumnInfo* const m_colInfo;
+    const int m_direction;
+    const bool m_isHorizontal;
+    const LayoutUnit m_logicalLeft;
+    int m_colIndex;
+    LayoutUnit m_currLogicalTopOffset;
+    LayoutRect m_colRect;
+};
+
+bool RenderBlock::hitTestColumns(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
+{
+    // We need to do multiple passes, breaking up our hit testing into strips.
+    if (!hasColumns())
+        return false;
+
+    for (ColumnRectIterator it(*this); it.hasMore(); it.advance()) {
+        LayoutRect hitRect = locationInContainer.boundingBox();
+        LayoutRect colRect = it.columnRect();
+        colRect.moveBy(accumulatedOffset);
+        if (locationInContainer.intersects(colRect)) {
+            // The point is inside this column.
+            // Adjust accumulatedOffset to change where we hit test.
+            LayoutSize offset;
+            it.adjust(offset);
+            LayoutPoint finalLocation = accumulatedOffset + offset;
+            if (!result.isRectBasedTest() || colRect.contains(hitRect))
+                return hitTestContents(request, result, locationInContainer, finalLocation, hitTestAction) || (hitTestAction == HitTestFloat && hitTestFloats(request, result, locationInContainer, finalLocation));
+
+            hitTestContents(request, result, locationInContainer, finalLocation, hitTestAction);
+        }
+    }
+
+    return false;
+}
+
+void RenderBlock::adjustForColumnRect(LayoutSize& offset, const LayoutPoint& locationInContainer) const
+{
+    for (ColumnRectIterator it(*this); it.hasMore(); it.advance()) {
+        LayoutRect colRect = it.columnRect();
+        if (colRect.contains(locationInContainer)) {
+            it.adjust(offset);
+            return;
+        }
+    }
+}
+
+bool RenderBlock::hitTestContents(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
+{
+    if (childrenInline() && !isTable()) {
+        // We have to hit-test our line boxes.
+        if (m_lineBoxes.hitTest(this, request, result, locationInContainer, accumulatedOffset, hitTestAction))
+            return true;
+    } else {
+        // Hit test our children.
+        HitTestAction childHitTest = hitTestAction;
+        if (hitTestAction == HitTestChildBlockBackgrounds)
+            childHitTest = HitTestChildBlockBackground;
+        for (RenderBox* child = lastChildBox(); child; child = child->previousSiblingBox()) {
+            LayoutPoint childPoint = flipForWritingModeForChild(child, accumulatedOffset);
+            if (!child->hasSelfPaintingLayer() && !child->isFloating() && child->nodeAtPoint(request, result, locationInContainer, childPoint, childHitTest))
+                return true;
+        }
+    }
+
+    return false;
+}
+
+Position RenderBlock::positionForBox(InlineBox *box, bool start) const
+{
+    if (!box)
+        return Position();
+
+    if (!box->renderer()->nonPseudoNode())
+        return createLegacyEditingPosition(nonPseudoNode(), start ? caretMinOffset() : caretMaxOffset());
+
+    if (!box->isInlineTextBox())
+        return createLegacyEditingPosition(box->renderer()->nonPseudoNode(), start ? box->renderer()->caretMinOffset() : box->renderer()->caretMaxOffset());
+
+    InlineTextBox* textBox = toInlineTextBox(box);
+    return createLegacyEditingPosition(box->renderer()->nonPseudoNode(), start ? textBox->start() : textBox->start() + textBox->len());
+}
+
+static inline bool isEditingBoundary(RenderObject* ancestor, RenderObject* child)
+{
+    ASSERT(!ancestor || ancestor->nonPseudoNode());
+    ASSERT(child && child->nonPseudoNode());
+    return !ancestor || !ancestor->parent() || (ancestor->hasLayer() && ancestor->parent()->isRenderView())
+        || ancestor->nonPseudoNode()->rendererIsEditable() == child->nonPseudoNode()->rendererIsEditable();
+}
+
+// FIXME: This function should go on RenderObject as an instance method. Then
+// all cases in which positionForPoint recurs could call this instead to
+// prevent crossing editable boundaries. This would require many tests.
+static VisiblePosition positionForPointRespectingEditingBoundaries(RenderBlock* parent, RenderBox* child, const LayoutPoint& pointInParentCoordinates)
+{
+    LayoutPoint childLocation = child->location();
+    if (child->hasPaintOffset())
+        childLocation += child->paintOffset();
+
+    // FIXME: This is wrong if the child's writing-mode is different from the parent's.
+    LayoutPoint pointInChildCoordinates(toLayoutPoint(pointInParentCoordinates - childLocation));
+
+    // If this is an anonymous renderer, we just recur normally
+    Node* childNode = child->nonPseudoNode();
+    if (!childNode)
+        return child->positionForPoint(pointInChildCoordinates);
+
+    // Otherwise, first make sure that the editability of the parent and child agree.
+    // If they don't agree, then we return a visible position just before or after the child
+    RenderObject* ancestor = parent;
+    while (ancestor && !ancestor->nonPseudoNode())
+        ancestor = ancestor->parent();
+
+    // If we can't find an ancestor to check editability on, or editability is unchanged, we recur like normal
+    if (isEditingBoundary(ancestor, child))
+        return child->positionForPoint(pointInChildCoordinates);
+
+    // Otherwise return before or after the child, depending on if the click was to the logical left or logical right of the child
+    LayoutUnit childMiddle = parent->logicalWidthForChild(child) / 2;
+    LayoutUnit logicalLeft = parent->isHorizontalWritingMode() ? pointInChildCoordinates.x() : pointInChildCoordinates.y();
+    if (logicalLeft < childMiddle)
+        return ancestor->createVisiblePosition(childNode->nodeIndex(), DOWNSTREAM);
+    return ancestor->createVisiblePosition(childNode->nodeIndex() + 1, UPSTREAM);
+}
+
+VisiblePosition RenderBlock::positionForPointWithInlineChildren(const LayoutPoint& pointInLogicalContents)
+{
+    ASSERT(childrenInline());
+
+    if (!firstRootBox())
+        return createVisiblePosition(0, DOWNSTREAM);
+
+    bool linesAreFlipped = style()->isFlippedLinesWritingMode();
+    bool blocksAreFlipped = style()->isFlippedBlocksWritingMode();
+
+    // look for the closest line box in the root box which is at the passed-in y coordinate
+    InlineBox* closestBox = 0;
+    RootInlineBox* firstRootBoxWithChildren = 0;
+    RootInlineBox* lastRootBoxWithChildren = 0;
+    for (RootInlineBox* root = firstRootBox(); root; root = root->nextRootBox()) {
+        if (!root->firstLeafChild())
+            continue;
+        if (!firstRootBoxWithChildren)
+            firstRootBoxWithChildren = root;
+
+        if (!linesAreFlipped && root->isFirstAfterPageBreak() && (pointInLogicalContents.y() < root->lineTopWithLeading()
+            || (blocksAreFlipped && pointInLogicalContents.y() == root->lineTopWithLeading())))
+            break;
+
+        lastRootBoxWithChildren = root;
+
+        // check if this root line box is located at this y coordinate
+        if (pointInLogicalContents.y() < root->selectionBottom() || (blocksAreFlipped && pointInLogicalContents.y() == root->selectionBottom())) {
+            if (linesAreFlipped) {
+                RootInlineBox* nextRootBoxWithChildren = root->nextRootBox();
+                while (nextRootBoxWithChildren && !nextRootBoxWithChildren->firstLeafChild())
+                    nextRootBoxWithChildren = nextRootBoxWithChildren->nextRootBox();
+
+                if (nextRootBoxWithChildren && nextRootBoxWithChildren->isFirstAfterPageBreak() && (pointInLogicalContents.y() > nextRootBoxWithChildren->lineTopWithLeading()
+                    || (!blocksAreFlipped && pointInLogicalContents.y() == nextRootBoxWithChildren->lineTopWithLeading())))
+                    continue;
+            }
+            closestBox = root->closestLeafChildForLogicalLeftPosition(pointInLogicalContents.x());
+            if (closestBox)
+                break;
+        }
+    }
+
+    bool moveCaretToBoundary = document()->frame()->editor()->behavior().shouldMoveCaretToHorizontalBoundaryWhenPastTopOrBottom();
+
+    if (!moveCaretToBoundary && !closestBox && lastRootBoxWithChildren) {
+        // y coordinate is below last root line box, pretend we hit it
+        closestBox = lastRootBoxWithChildren->closestLeafChildForLogicalLeftPosition(pointInLogicalContents.x());
+    }
+
+    if (closestBox) {
+        if (moveCaretToBoundary) {
+            LayoutUnit firstRootBoxWithChildrenTop = min<LayoutUnit>(firstRootBoxWithChildren->selectionTop(), firstRootBoxWithChildren->logicalTop());
+            if (pointInLogicalContents.y() < firstRootBoxWithChildrenTop
+                || (blocksAreFlipped && pointInLogicalContents.y() == firstRootBoxWithChildrenTop)) {
+                InlineBox* box = firstRootBoxWithChildren->firstLeafChild();
+                if (box->isLineBreak()) {
+                    if (InlineBox* newBox = box->nextLeafChildIgnoringLineBreak())
+                        box = newBox;
+                }
+                // y coordinate is above first root line box, so return the start of the first
+                return VisiblePosition(positionForBox(box, true), DOWNSTREAM);
+            }
+        }
+
+        // pass the box a top position that is inside it
+        LayoutPoint point(pointInLogicalContents.x(), closestBox->root()->blockDirectionPointInLine());
+        if (!isHorizontalWritingMode())
+            point = point.transposedPoint();
+        if (closestBox->renderer()->isReplaced())
+            return positionForPointRespectingEditingBoundaries(this, toRenderBox(closestBox->renderer()), point);
+        return closestBox->renderer()->positionForPoint(point);
+    }
+
+    if (lastRootBoxWithChildren) {
+        // We hit this case for Mac behavior when the Y coordinate is below the last box.
+        ASSERT(moveCaretToBoundary);
+        InlineBox* logicallyLastBox;
+        if (lastRootBoxWithChildren->getLogicalEndBoxWithNode(logicallyLastBox))
+            return VisiblePosition(positionForBox(logicallyLastBox, false), DOWNSTREAM);
+    }
+
+    // Can't reach this. We have a root line box, but it has no kids.
+    // FIXME: This should ASSERT_NOT_REACHED(), but clicking on placeholder text
+    // seems to hit this code path.
+    return createVisiblePosition(0, DOWNSTREAM);
+}
+
+static inline bool isChildHitTestCandidate(RenderBox* box)
+{
+    return box->height() && box->style()->visibility() == VISIBLE && !box->isFloatingOrOutOfFlowPositioned();
+}
+
+VisiblePosition RenderBlock::positionForPoint(const LayoutPoint& point)
+{
+    if (isTable())
+        return RenderBox::positionForPoint(point);
+
+    if (isReplaced()) {
+        // FIXME: This seems wrong when the object's writing-mode doesn't match the line's writing-mode.
+        LayoutUnit pointLogicalLeft = isHorizontalWritingMode() ? point.x() : point.y();
+        LayoutUnit pointLogicalTop = isHorizontalWritingMode() ? point.y() : point.x();
+
+        if (pointLogicalTop < 0 || (pointLogicalTop < logicalHeight() && pointLogicalLeft < 0))
+            return createVisiblePosition(caretMinOffset(), DOWNSTREAM);
+        if (pointLogicalTop >= logicalHeight() || (pointLogicalTop >= 0 && pointLogicalLeft >= logicalWidth()))
+            return createVisiblePosition(caretMaxOffset(), DOWNSTREAM);
+    } 
+
+    LayoutPoint pointInContents = point;
+    offsetForContents(pointInContents);
+    LayoutPoint pointInLogicalContents(pointInContents);
+    if (!isHorizontalWritingMode())
+        pointInLogicalContents = pointInLogicalContents.transposedPoint();
+
+    if (childrenInline())
+        return positionForPointWithInlineChildren(pointInLogicalContents);
+
+    RenderBox* lastCandidateBox = lastChildBox();
+    while (lastCandidateBox && !isChildHitTestCandidate(lastCandidateBox))
+        lastCandidateBox = lastCandidateBox->previousSiblingBox();
+
+    bool blocksAreFlipped = style()->isFlippedBlocksWritingMode();
+    if (lastCandidateBox) {
+        if (pointInLogicalContents.y() > logicalTopForChild(lastCandidateBox)
+            || (!blocksAreFlipped && pointInLogicalContents.y() == logicalTopForChild(lastCandidateBox)))
+            return positionForPointRespectingEditingBoundaries(this, lastCandidateBox, pointInContents);
+
+        for (RenderBox* childBox = firstChildBox(); childBox; childBox = childBox->nextSiblingBox()) {
+            if (!isChildHitTestCandidate(childBox))
+                continue;
+            LayoutUnit childLogicalBottom = logicalTopForChild(childBox) + logicalHeightForChild(childBox);
+            // We hit child if our click is above the bottom of its padding box (like IE6/7 and FF3).
+            if (isChildHitTestCandidate(childBox) && (pointInLogicalContents.y() < childLogicalBottom
+                || (blocksAreFlipped && pointInLogicalContents.y() == childLogicalBottom)))
+                return positionForPointRespectingEditingBoundaries(this, childBox, pointInContents);
+        }
+    }
+
+    // We only get here if there are no hit test candidate children below the click.
+    return RenderBox::positionForPoint(point);
+}
+
+void RenderBlock::offsetForContents(LayoutPoint& offset) const
+{
+    offset = flipForWritingMode(offset);
+
+    if (hasOverflowClip())
+        offset += scrolledContentOffset();
+
+    if (hasColumns())
+        adjustPointToColumnContents(offset);
+
+    offset = flipForWritingMode(offset);
+}
+
+LayoutUnit RenderBlock::availableLogicalWidth() const
+{
+    // If we have multiple columns, then the available logical width is reduced to our column width.
+    if (hasColumns())
+        return desiredColumnWidth();
+    return RenderBox::availableLogicalWidth();
+}
+
+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()
+{   
+    if (document()->regionBasedColumnsEnabled())
+        return;
+
+    // Calculate our column width and column count.
+    // FIXME: Can overflow on fast/block/float/float-not-removed-from-next-sibling4.html, see https://bugs.webkit.org/show_bug.cgi?id=68744
+    unsigned desiredColumnCount = 1;
+    LayoutUnit desiredColumnWidth = contentLogicalWidth();
+    
+    // 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()->paginated() || (style()->hasAutoColumnCount() && style()->hasAutoColumnWidth()) || !style()->hasInlineColumnAxis()) {
+        setDesiredColumnCountAndWidth(desiredColumnCount, desiredColumnWidth);
+        return;
+    }
+        
+    LayoutUnit availWidth = desiredColumnWidth;
+    LayoutUnit colGap = columnGap();
+    LayoutUnit colWidth = max<LayoutUnit>(1, LayoutUnit(style()->columnWidth()));
+    int colCount = max<int>(1, style()->columnCount());
+
+    if (style()->hasAutoColumnWidth() && !style()->hasAutoColumnCount()) {
+        desiredColumnCount = colCount;
+        desiredColumnWidth = max<LayoutUnit>(0, (availWidth - ((desiredColumnCount - 1) * colGap)) / desiredColumnCount);
+    } else if (!style()->hasAutoColumnWidth() && style()->hasAutoColumnCount()) {
+        desiredColumnCount = max<LayoutUnit>(1, (availWidth + colGap) / (colWidth + colGap));
+        desiredColumnWidth = ((availWidth + colGap) / desiredColumnCount) - colGap;
+    } else {
+        desiredColumnCount = max<LayoutUnit>(min<LayoutUnit>(colCount, (availWidth + colGap) / (colWidth + colGap)), 1);
+        desiredColumnWidth = ((availWidth + colGap) / desiredColumnCount) - colGap;
+    }
+    setDesiredColumnCountAndWidth(desiredColumnCount, desiredColumnWidth);
+}
+
+bool RenderBlock::requiresColumns(int desiredColumnCount) const
+{
+    // If overflow-y is set to paged-x or paged-y on the body or html element, we'll handle the paginating
+    // in the RenderView instead.
+    bool isPaginated = (style()->overflowY() == OPAGEDX || style()->overflowY() == OPAGEDY) && !(isRoot() || isBody());
+
+    return firstChild()
+        && (desiredColumnCount != 1 || !style()->hasAutoColumnWidth() || !style()->hasInlineColumnAxis() || isPaginated)
+        && !firstChild()->isAnonymousColumnsBlock()
+        && !firstChild()->isAnonymousColumnSpanBlock();
+}
+
+void RenderBlock::setDesiredColumnCountAndWidth(int count, LayoutUnit width)
+{
+    bool destroyColumns = !requiresColumns(count);
+    if (destroyColumns) {
+        if (hasColumns()) {
+            gColumnInfoMap->take(this);
+            setHasColumns(false);
+        }
+    } else {
+        ColumnInfo* info;
+        if (hasColumns())
+            info = gColumnInfoMap->get(this);
+        else {
+            if (!gColumnInfoMap)
+                gColumnInfoMap = new ColumnInfoMap;
+            info = new ColumnInfo;
+            gColumnInfoMap->add(this, adoptPtr(info));
+            setHasColumns(true);
+        }
+        info->setDesiredColumnCount(count);
+        info->setDesiredColumnWidth(width);
+        info->setProgressionAxis(style()->hasInlineColumnAxis() ? ColumnInfo::InlineAxis : ColumnInfo::BlockAxis);
+        info->setProgressionIsReversed(style()->columnProgression() == ReverseColumnProgression);
+    }
+}
+
+void RenderBlock::updateColumnInfoFromStyle(RenderStyle* style)
+{
+    if (!hasColumns())
+        return;
+
+    ColumnInfo* info = gColumnInfoMap->get(this);
+
+    bool needsLayout = false;
+    ColumnInfo::Axis oldAxis = info->progressionAxis();
+    ColumnInfo::Axis newAxis = style->hasInlineColumnAxis() ? ColumnInfo::InlineAxis : ColumnInfo::BlockAxis;
+    if (oldAxis != newAxis) {
+        info->setProgressionAxis(newAxis);
+        needsLayout = true;
+    }
+
+    bool oldProgressionIsReversed = info->progressionIsReversed();
+    bool newProgressionIsReversed = style->columnProgression() == ReverseColumnProgression;
+    if (oldProgressionIsReversed != newProgressionIsReversed) {
+        info->setProgressionIsReversed(newProgressionIsReversed);
+        needsLayout = true;
+    }
+
+    if (needsLayout)
+        setNeedsLayoutAndPrefWidthsRecalc();
+}
+
+LayoutUnit RenderBlock::desiredColumnWidth() const
+{
+    if (!hasColumns())
+        return contentLogicalWidth();
+    return gColumnInfoMap->get(this)->desiredColumnWidth();
+}
+
+unsigned RenderBlock::desiredColumnCount() const
+{
+    if (!hasColumns())
+        return 1;
+    return gColumnInfoMap->get(this)->desiredColumnCount();
+}
+
+ColumnInfo* RenderBlock::columnInfo() const
+{
+    if (!hasColumns())
+        return 0;
+    return gColumnInfoMap->get(this);    
+}
+
+unsigned RenderBlock::columnCount(ColumnInfo* colInfo) const
+{
+    ASSERT(hasColumns());
+    ASSERT(gColumnInfoMap->get(this) == colInfo);
+    return colInfo->columnCount();
+}
+
+LayoutRect RenderBlock::columnRectAt(ColumnInfo* colInfo, unsigned index) const
+{
+    ASSERT(hasColumns() && gColumnInfoMap->get(this) == colInfo);
+
+    // Compute the appropriate rect based off our information.
+    LayoutUnit colLogicalWidth = colInfo->desiredColumnWidth();
+    LayoutUnit colLogicalHeight = colInfo->columnHeight();
+    LayoutUnit colLogicalTop = borderBefore() + paddingBefore();
+    LayoutUnit colLogicalLeft = logicalLeftOffsetForContent();
+    LayoutUnit colGap = columnGap();
+    if (colInfo->progressionAxis() == ColumnInfo::InlineAxis) {
+        if (style()->isLeftToRightDirection() ^ colInfo->progressionIsReversed())
+            colLogicalLeft += index * (colLogicalWidth + colGap);
+        else
+            colLogicalLeft += contentLogicalWidth() - colLogicalWidth - index * (colLogicalWidth + colGap);
+    } else {
+        if (!colInfo->progressionIsReversed())
+            colLogicalTop += index * (colLogicalHeight + colGap);
+        else
+            colLogicalTop += contentLogicalHeight() - colLogicalHeight - index * (colLogicalHeight + colGap);
+    }
+
+    if (isHorizontalWritingMode())
+        return LayoutRect(colLogicalLeft, colLogicalTop, colLogicalWidth, colLogicalHeight);
+    return LayoutRect(colLogicalTop, colLogicalLeft, colLogicalHeight, colLogicalWidth);
+}
+
+bool RenderBlock::relayoutForPagination(bool hasSpecifiedPageLogicalHeight, LayoutUnit pageLogicalHeight, LayoutStateMaintainer& statePusher)
+{
+    if (!hasColumns())
+        return false;
+
+    OwnPtr<RenderOverflow> savedOverflow = m_overflow.release();
+    if (childrenInline())
+        addOverflowFromInlineChildren();
+    else
+        addOverflowFromBlockChildren();
+    LayoutUnit layoutOverflowLogicalBottom = (isHorizontalWritingMode() ? layoutOverflowRect().maxY() : layoutOverflowRect().maxX()) - borderBefore() - paddingBefore();
+
+    // FIXME: We don't balance properly at all in the presence of forced page breaks.  We need to understand what
+    // the distance between forced page breaks is so that we can avoid making the minimum column height too tall.
+    ColumnInfo* colInfo = columnInfo();
+    if (!hasSpecifiedPageLogicalHeight) {
+        LayoutUnit columnHeight = pageLogicalHeight;
+        int minColumnCount = colInfo->forcedBreaks() + 1;
+        int desiredColumnCount = colInfo->desiredColumnCount();
+        if (minColumnCount >= desiredColumnCount) {
+            // The forced page breaks are in control of the balancing.  Just set the column height to the
+            // maximum page break distance.
+            if (!pageLogicalHeight) {
+                LayoutUnit distanceBetweenBreaks = max<LayoutUnit>(colInfo->maximumDistanceBetweenForcedBreaks(),
+                                                                   view()->layoutState()->pageLogicalOffset(this, borderBefore() + paddingBefore() + layoutOverflowLogicalBottom) - colInfo->forcedBreakOffset());
+                columnHeight = max(colInfo->minimumColumnHeight(), distanceBetweenBreaks);
+            }
+        } else if (layoutOverflowLogicalBottom > boundedMultiply(pageLogicalHeight, desiredColumnCount)) {
+            // Now that we know the intrinsic height of the columns, we have to rebalance them.
+            columnHeight = max<LayoutUnit>(colInfo->minimumColumnHeight(), ceilf((float)layoutOverflowLogicalBottom / desiredColumnCount));
+        }
+        
+        if (columnHeight && columnHeight != pageLogicalHeight) {
+            statePusher.pop();
+            setEverHadLayout(true);
+            layoutBlock(false, columnHeight);
+            return true;
+        }
+    } 
+
+    if (pageLogicalHeight)
+        colInfo->setColumnCountAndHeight(ceilf((float)layoutOverflowLogicalBottom / pageLogicalHeight), pageLogicalHeight);
+
+    if (columnCount(colInfo)) {
+        setLogicalHeight(borderBefore() + paddingBefore() + colInfo->columnHeight() + borderAfter() + paddingAfter() + scrollbarLogicalHeight());
+        m_overflow.clear();
+    } else
+        m_overflow = savedOverflow.release();
+    
+    return false;
+}
+
+void RenderBlock::adjustPointToColumnContents(LayoutPoint& point) const
+{
+    // Just bail if we have no columns.
+    if (!hasColumns())
+        return;
+    
+    ColumnInfo* colInfo = columnInfo();
+    if (!columnCount(colInfo))
+        return;
+
+    // Determine which columns we intersect.
+    LayoutUnit colGap = columnGap();
+    LayoutUnit halfColGap = colGap / 2;
+    LayoutPoint columnPoint(columnRectAt(colInfo, 0).location());
+    LayoutUnit logicalOffset = 0;
+    for (unsigned i = 0; i < colInfo->columnCount(); i++) {
+        // Add in half the column gap to the left and right of the rect.
+        LayoutRect colRect = columnRectAt(colInfo, i);
+        flipForWritingMode(colRect);
+        if (isHorizontalWritingMode() == (colInfo->progressionAxis() == ColumnInfo::InlineAxis)) {
+            LayoutRect gapAndColumnRect(colRect.x() - halfColGap, colRect.y(), colRect.width() + colGap, colRect.height());
+            if (point.x() >= gapAndColumnRect.x() && point.x() < gapAndColumnRect.maxX()) {
+                if (colInfo->progressionAxis() == ColumnInfo::InlineAxis) {
+                    // FIXME: The clamping that follows is not completely right for right-to-left
+                    // content.
+                    // Clamp everything above the column to its top left.
+                    if (point.y() < gapAndColumnRect.y())
+                        point = gapAndColumnRect.location();
+                    // Clamp everything below the column to the next column's top left. If there is
+                    // no next column, this still maps to just after this column.
+                    else if (point.y() >= gapAndColumnRect.maxY()) {
+                        point = gapAndColumnRect.location();
+                        point.move(0, gapAndColumnRect.height());
+                    }
+                } else {
+                    if (point.x() < colRect.x())
+                        point.setX(colRect.x());
+                    else if (point.x() >= colRect.maxX())
+                        point.setX(colRect.maxX() - 1);
+                }
+
+                // We're inside the column.  Translate the x and y into our column coordinate space.
+                if (colInfo->progressionAxis() == ColumnInfo::InlineAxis)
+                    point.move(columnPoint.x() - colRect.x(), (!style()->isFlippedBlocksWritingMode() ? logicalOffset : -logicalOffset));
+                else
+                    point.move((!style()->isFlippedBlocksWritingMode() ? logicalOffset : -logicalOffset) - colRect.x() + borderLeft() + paddingLeft(), 0);
+                return;
+            }
+
+            // Move to the next position.
+            logicalOffset += colInfo->progressionAxis() == ColumnInfo::InlineAxis ? colRect.height() : colRect.width();
+        } else {
+            LayoutRect gapAndColumnRect(colRect.x(), colRect.y() - halfColGap, colRect.width(), colRect.height() + colGap);
+            if (point.y() >= gapAndColumnRect.y() && point.y() < gapAndColumnRect.maxY()) {
+                if (colInfo->progressionAxis() == ColumnInfo::InlineAxis) {
+                    // FIXME: The clamping that follows is not completely right for right-to-left
+                    // content.
+                    // Clamp everything above the column to its top left.
+                    if (point.x() < gapAndColumnRect.x())
+                        point = gapAndColumnRect.location();
+                    // Clamp everything below the column to the next column's top left. If there is
+                    // no next column, this still maps to just after this column.
+                    else if (point.x() >= gapAndColumnRect.maxX()) {
+                        point = gapAndColumnRect.location();
+                        point.move(gapAndColumnRect.width(), 0);
+                    }
+                } else {
+                    if (point.y() < colRect.y())
+                        point.setY(colRect.y());
+                    else if (point.y() >= colRect.maxY())
+                        point.setY(colRect.maxY() - 1);
+                }
+
+                // We're inside the column.  Translate the x and y into our column coordinate space.
+                if (colInfo->progressionAxis() == ColumnInfo::InlineAxis)
+                    point.move((!style()->isFlippedBlocksWritingMode() ? logicalOffset : -logicalOffset), columnPoint.y() - colRect.y());
+                else
+                    point.move(0, (!style()->isFlippedBlocksWritingMode() ? logicalOffset : -logicalOffset) - colRect.y() + borderTop() + paddingTop());
+                return;
+            }
+
+            // Move to the next position.
+            logicalOffset += colInfo->progressionAxis() == ColumnInfo::InlineAxis ? colRect.width() : colRect.height();
+        }
+    }
+}
+
+void RenderBlock::adjustRectForColumns(LayoutRect& r) const
+{
+    // Just bail if we have no columns.
+    if (!hasColumns())
+        return;
+    
+    ColumnInfo* colInfo = columnInfo();
+    
+    // Determine which columns we intersect.
+    unsigned colCount = columnCount(colInfo);
+    if (!colCount)
+        return;
+
+    // Begin with a result rect that is empty.
+    LayoutRect result;
+
+    bool isHorizontal = isHorizontalWritingMode();
+    LayoutUnit beforeBorderPadding = borderBefore() + paddingBefore();
+    LayoutUnit colHeight = colInfo->columnHeight();
+    if (!colHeight)
+        return;
+
+    LayoutUnit startOffset = max(isHorizontal ? r.y() : r.x(), beforeBorderPadding);
+    LayoutUnit endOffset = max(min<LayoutUnit>(isHorizontal ? r.maxY() : r.maxX(), beforeBorderPadding + colCount * colHeight), beforeBorderPadding);
+
+    // FIXME: Can overflow on fast/block/float/float-not-removed-from-next-sibling4.html, see https://bugs.webkit.org/show_bug.cgi?id=68744
+    unsigned startColumn = (startOffset - beforeBorderPadding) / colHeight;
+    unsigned endColumn = (endOffset - beforeBorderPadding) / colHeight;
+
+    if (startColumn == endColumn) {
+        // The rect is fully contained within one column. Adjust for our offsets
+        // and repaint only that portion.
+        LayoutUnit logicalLeftOffset = logicalLeftOffsetForContent();
+        LayoutRect colRect = columnRectAt(colInfo, startColumn);
+        LayoutRect repaintRect = r;
+
+        if (colInfo->progressionAxis() == ColumnInfo::InlineAxis) {
+            if (isHorizontal)
+                repaintRect.move(colRect.x() - logicalLeftOffset, - static_cast<int>(startColumn) * colHeight);
+            else
+                repaintRect.move(- static_cast<int>(startColumn) * colHeight, colRect.y() - logicalLeftOffset);
+        } else {
+            if (isHorizontal)
+                repaintRect.move(0, colRect.y() - startColumn * colHeight - beforeBorderPadding);
+            else
+                repaintRect.move(colRect.x() - startColumn * colHeight - beforeBorderPadding, 0);
+        }
+        repaintRect.intersect(colRect);
+        result.unite(repaintRect);
+    } else {
+        // We span multiple columns. We can just unite the start and end column to get the final
+        // repaint rect.
+        result.unite(columnRectAt(colInfo, startColumn));
+        result.unite(columnRectAt(colInfo, endColumn));
+    }
+
+    r = result;
+}
+
+LayoutPoint RenderBlock::flipForWritingModeIncludingColumns(const LayoutPoint& point) const
+{
+    ASSERT(hasColumns());
+    if (!hasColumns() || !style()->isFlippedBlocksWritingMode())
+        return point;
+    ColumnInfo* colInfo = columnInfo();
+    LayoutUnit columnLogicalHeight = colInfo->columnHeight();
+    LayoutUnit expandedLogicalHeight = borderBefore() + paddingBefore() + columnCount(colInfo) * columnLogicalHeight + borderAfter() + paddingAfter() + scrollbarLogicalHeight();
+    if (isHorizontalWritingMode())
+        return LayoutPoint(point.x(), expandedLogicalHeight - point.y());
+    return LayoutPoint(expandedLogicalHeight - point.x(), point.y());
+}
+
+void RenderBlock::adjustStartEdgeForWritingModeIncludingColumns(LayoutRect& rect) const
+{
+    ASSERT(hasColumns());
+    if (!hasColumns() || !style()->isFlippedBlocksWritingMode())
+        return;
+    
+    ColumnInfo* colInfo = columnInfo();
+    LayoutUnit columnLogicalHeight = colInfo->columnHeight();
+    LayoutUnit expandedLogicalHeight = borderBefore() + paddingBefore() + columnCount(colInfo) * columnLogicalHeight + borderAfter() + paddingAfter() + scrollbarLogicalHeight();
+    
+    if (isHorizontalWritingMode())
+        rect.setY(expandedLogicalHeight - rect.maxY());
+    else
+        rect.setX(expandedLogicalHeight - rect.maxX());
+}
+
+void RenderBlock::adjustForColumns(LayoutSize& offset, const LayoutPoint& point) const
+{
+    if (!hasColumns())
+        return;
+
+    ColumnInfo* colInfo = columnInfo();
+
+    LayoutUnit logicalLeft = logicalLeftOffsetForContent();
+    unsigned colCount = columnCount(colInfo);
+    LayoutUnit colLogicalWidth = colInfo->desiredColumnWidth();
+    LayoutUnit colLogicalHeight = colInfo->columnHeight();
+
+    for (unsigned i = 0; i < colCount; ++i) {
+        // Compute the edges for a given column in the block progression direction.
+        LayoutRect sliceRect = LayoutRect(logicalLeft, borderBefore() + paddingBefore() + i * colLogicalHeight, colLogicalWidth, colLogicalHeight);
+        if (!isHorizontalWritingMode())
+            sliceRect = sliceRect.transposedRect();
+        
+        LayoutUnit logicalOffset = i * colLogicalHeight;
+
+        // Now we're in the same coordinate space as the point.  See if it is inside the rectangle.
+        if (isHorizontalWritingMode()) {
+            if (point.y() >= sliceRect.y() && point.y() < sliceRect.maxY()) {
+                if (colInfo->progressionAxis() == ColumnInfo::InlineAxis)
+                    offset.expand(columnRectAt(colInfo, i).x() - logicalLeft, -logicalOffset);
+                else
+                    offset.expand(0, columnRectAt(colInfo, i).y() - logicalOffset - borderBefore() - paddingBefore());
+                return;
+            }
+        } else {
+            if (point.x() >= sliceRect.x() && point.x() < sliceRect.maxX()) {
+                if (colInfo->progressionAxis() == ColumnInfo::InlineAxis)
+                    offset.expand(-logicalOffset, columnRectAt(colInfo, i).y() - logicalLeft);
+                else
+                    offset.expand(columnRectAt(colInfo, i).x() - logicalOffset - borderBefore() - paddingBefore(), 0);
+                return;
+            }
+        }
+    }
+}
+
+void RenderBlock::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const
+{
+    if (childrenInline()) {
+        // FIXME: Remove this const_cast.
+        const_cast<RenderBlock*>(this)->computeInlinePreferredLogicalWidths(minLogicalWidth, maxLogicalWidth);
+    } else
+        computeBlockPreferredLogicalWidths(minLogicalWidth, maxLogicalWidth);
+
+    maxLogicalWidth = max(minLogicalWidth, maxLogicalWidth);
+
+    if (!style()->autoWrap() && childrenInline()) {
+        minLogicalWidth = maxLogicalWidth;
+        // A horizontal marquee with inline children has no minimum width.
+        if (layer() && layer()->marquee() && layer()->marquee()->isHorizontal())
+            minLogicalWidth = 0;
+    }
+
+    if (isTableCell()) {
+        Length tableCellWidth = toRenderTableCell(this)->styleOrColLogicalWidth();
+        if (tableCellWidth.isFixed() && tableCellWidth.value() > 0)
+            maxLogicalWidth = max(minLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(tableCellWidth.value()));
+    }
+
+    int scrollbarWidth = instrinsicScrollbarLogicalWidth();
+    maxLogicalWidth += scrollbarWidth;
+    minLogicalWidth += scrollbarWidth;
+}
+
+void RenderBlock::computePreferredLogicalWidths()
+{
+    ASSERT(preferredLogicalWidthsDirty());
+
+    updateFirstLetter();
+
+    m_minPreferredLogicalWidth = 0;
+    m_maxPreferredLogicalWidth = 0;
+
+    RenderStyle* styleToUse = style();
+    if (!isTableCell() && styleToUse->logicalWidth().isFixed() && styleToUse->logicalWidth().value() >= 0 
+        && !(isDeprecatedFlexItem() && !styleToUse->logicalWidth().intValue()))
+        m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = adjustContentBoxLogicalWidthForBoxSizing(styleToUse->logicalWidth().value());
+    else
+        computeIntrinsicLogicalWidths(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);
+    
+    if (styleToUse->logicalMinWidth().isFixed() && styleToUse->logicalMinWidth().value() > 0) {
+        m_maxPreferredLogicalWidth = max(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->logicalMinWidth().value()));
+        m_minPreferredLogicalWidth = max(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->logicalMinWidth().value()));
+    }
+    
+    if (styleToUse->logicalMaxWidth().isFixed()) {
+        m_maxPreferredLogicalWidth = min(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->logicalMaxWidth().value()));
+        m_minPreferredLogicalWidth = min(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->logicalMaxWidth().value()));
+    }
+    
+    // Table layout uses integers, ceil the preferred widths to ensure that they can contain the contents.
+    if (isTableCell()) {
+        m_minPreferredLogicalWidth = m_minPreferredLogicalWidth.ceil();
+        m_maxPreferredLogicalWidth = m_maxPreferredLogicalWidth.ceil();
+    }
+
+    LayoutUnit borderAndPadding = borderAndPaddingLogicalWidth();
+    m_minPreferredLogicalWidth += borderAndPadding;
+    m_maxPreferredLogicalWidth += borderAndPadding;
+
+    setPreferredLogicalWidthsDirty(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->isOutOfFlowPositioned())))
+            result = current->firstChild();
+        if (!result) {
+            // We hit the end of our inline. (It was empty, e.g., <span></span>.)
+            if (!oldEndOfInline && current->isRenderInline()) {
+                result = current;
+                endOfInline = true;
+                break;
+            }
+
+            while (current && current != parent) {
+                result = current->nextSibling();
+                if (result) break;
+                current = current->parent();
+                if (current && current != parent && current->isRenderInline()) {
+                    result = current;
+                    endOfInline = true;
+                    break;
+                }
+            }
+        }
+
+        if (!result)
+            break;
+
+        if (!result->isOutOfFlowPositioned() && (result->isText() || result->isFloating() || result->isReplaced() || result->isRenderInline()))
+             break;
+        
+        current = result;
+        result = 0;
+    }
+
+    // Update our position.
+    current = result;
+    return current;
+}
+
+static LayoutUnit getBPMWidth(LayoutUnit childValue, Length cssUnit)
+{
+    if (cssUnit.type() != Auto)
+        return (cssUnit.isFixed() ? static_cast<LayoutUnit>(cssUnit.value()) : childValue);
+    return 0;
+}
+
+static LayoutUnit getBorderPaddingMargin(const RenderBoxModelObject* child, bool endOfInline)
+{
+    RenderStyle* childStyle = child->style();
+    if (endOfInline)
+        return getBPMWidth(child->marginEnd(), childStyle->marginEnd()) +
+               getBPMWidth(child->paddingEnd(), childStyle->paddingEnd()) +
+               child->borderEnd();
+    return getBPMWidth(child->marginStart(), childStyle->marginStart()) +
+               getBPMWidth(child->paddingStart(), childStyle->paddingStart()) +
+               child->borderStart();
+}
+
+static inline void stripTrailingSpace(float& inlineMax, float& inlineMin,
+                                      RenderObject* trailingSpaceChild)
+{
+    if (trailingSpaceChild && trailingSpaceChild->isText()) {
+        // Collapse away the trailing space at the end of a block.
+        RenderText* t = toRenderText(trailingSpaceChild);
+        const UChar space = ' ';
+        const Font& font = t->style()->font(); // FIXME: This ignores first-line.
+        float spaceWidth = font.width(RenderBlock::constructTextRun(t, font, &space, 1, t->style()));
+        inlineMax -= spaceWidth + font.wordSpacing();
+        if (inlineMin > inlineMax)
+            inlineMin = inlineMax;
+    }
+}
+
+static inline void updatePreferredWidth(LayoutUnit& preferredWidth, float& result)
+{
+    LayoutUnit snappedResult = ceiledLayoutUnit(result);
+    preferredWidth = max(snappedResult, preferredWidth);
+}
+
+// When converting between floating point and LayoutUnits we risk losing precision
+// with each conversion. When this occurs while accumulating our preferred widths,
+// we can wind up with a line width that's larger than our maxPreferredWidth due to
+// pure float accumulation.
+static inline LayoutUnit adjustFloatForSubPixelLayout(float value)
+{
+    return ceiledLayoutUnit(value);
+}
+
+
+void RenderBlock::computeInlinePreferredLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth)
+{
+    float inlineMax = 0;
+    float inlineMin = 0;
+
+    RenderStyle* styleToUse = style();
+    RenderBlock* containingBlock = this->containingBlock();
+    LayoutUnit cw = containingBlock ? containingBlock->contentLogicalWidth() : LayoutUnit();
+
+    // 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 = !document()->inQuirksMode() || !isTableCell() || !styleToUse->logicalWidth().isIntrinsicOrAuto();
+
+    bool autoWrap, oldAutoWrap;
+    autoWrap = oldAutoWrap = styleToUse->autoWrap();
+
+    InlineMinMaxIterator childIterator(this);
+
+    // Only gets added to the max preffered width once.
+    bool addedTextIndent = false;
+    // Signals the text indent was more negative than the min preferred width
+    bool hasRemainingNegativeTextIndent = false;
+
+    LayoutUnit textIndent = minimumValueForLength(styleToUse->textIndent(), cw, view());
+    RenderObject* prevFloat = 0;
+    bool isPrevChildInlineFlow = false;
+    bool shouldBreakLineAfterText = false;
+    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* childStyle = child->style();
+            float childMin = 0;
+            float childMax = 0;
+
+            if (!child->isText()) {
+                // Case (1) and (2).  Inline replaced and inline flow elements.
+                if (child->isRenderInline()) {
+                    // Add in padding/border/margin from the appropriate side of
+                    // the element.
+                    float bpm = getBorderPaddingMargin(toRenderInline(child), childIterator.endOfInline);
+                    childMin += bpm;
+                    childMax += bpm;
+
+                    inlineMin += childMin;
+                    inlineMax += childMax;
+                    
+                    child->setPreferredLogicalWidthsDirty(false);
+                } else {
+                    // Inline replaced elts add in their margins to their min/max values.
+                    LayoutUnit margins = 0;
+                    Length startMargin = childStyle->marginStart();
+                    Length endMargin = childStyle->marginEnd();
+                    if (startMargin.isFixed())
+                        margins += adjustFloatForSubPixelLayout(startMargin.value());
+                    if (endMargin.isFixed())
+                        margins += adjustFloatForSubPixelLayout(endMargin.value());
+                    childMin += margins.ceilToFloat();
+                    childMax += margins.ceilToFloat();
+                }
+            }
+
+            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->minPreferredLogicalWidth().ceilToFloat();
+                childMax += child->maxPreferredLogicalWidth().ceilToFloat();
+
+                bool clearPreviousFloat;
+                if (child->isFloating()) {
+                    clearPreviousFloat = (prevFloat
+                        && ((prevFloat->style()->floating() == LeftFloat && (childStyle->clear() & CLEFT))
+                            || (prevFloat->style()->floating() == RightFloat && (childStyle->clear() & CRIGHT))));
+                    prevFloat = child;
+                } else
+                    clearPreviousFloat = false;
+
+                bool canBreakReplacedElement = !child->isImage() || allowImagesToBreak;
+                if ((canBreakReplacedElement && (autoWrap || oldAutoWrap) && (!isPrevChildInlineFlow || shouldBreakLineAfterText)) || clearPreviousFloat) {
+                    updatePreferredWidth(minLogicalWidth, inlineMin);
+                    inlineMin = 0;
+                }
+
+                // If we're supposed to clear the previous float, then terminate maxwidth as well.
+                if (clearPreviousFloat) {
+                    updatePreferredWidth(maxLogicalWidth, inlineMax);
+                    inlineMax = 0;
+                }
+
+                // Add in text-indent.  This is added in only once.
+                LayoutUnit ti = 0;
+                if (!addedTextIndent && !child->isFloating()) {
+                    ti = textIndent;
+                    childMin += ti.ceilToFloat();
+                    childMax += ti.ceilToFloat();
+
+                    if (childMin < 0)
+                        textIndent = adjustFloatForSubPixelLayout(childMin);
+                    else
+                        addedTextIndent = true;
+                }
+
+                // Add our width to the max.
+                inlineMax += max<float>(0, childMax);
+
+                if (!autoWrap || !canBreakReplacedElement || (isPrevChildInlineFlow && !shouldBreakLineAfterText)) {
+                    if (child->isFloating())
+                        updatePreferredWidth(minLogicalWidth, childMin);
+                    else
+                        inlineMin += childMin;
+                } else {
+                    // Now check our line.
+                    updatePreferredWidth(minLogicalWidth, childMin);
+
+                    // Now start a new line.
+                    inlineMin = 0;
+                }
+
+                if (autoWrap && canBreakReplacedElement && isPrevChildInlineFlow) {
+                    updatePreferredWidth(minLogicalWidth, inlineMin);
+                    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 = toRenderText(child);
+
+                if (t->isWordBreak()) {
+                    updatePreferredWidth(minLogicalWidth, inlineMin);
+                    inlineMin = 0;
+                    continue;
+                }
+
+                if (t->style()->hasTextCombine() && t->isCombineText())
+                    toRenderCombineText(t)->combineText();
+
+                // 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;
+                float beginMin, endMin;
+                bool beginWS, endWS;
+                float 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)) {
+                        updatePreferredWidth(minLogicalWidth, inlineMin);
+                        inlineMin = 0;
+                    }
+                    continue;
+                }
+                
+                if (stripFrontSpaces)
+                    trailingSpaceChild = child;
+                else
+                    trailingSpaceChild = 0;
+
+                // Add in text-indent.  This is added in only once.
+                float ti = 0;
+                if (!addedTextIndent || hasRemainingNegativeTextIndent) {
+                    ti = textIndent.ceilToFloat();
+                    childMin += ti;
+                    beginMin += ti;
+                    
+                    // It the text indent negative and larger than the child minimum, we re-use the remainder
+                    // in future minimum calculations, but using the negative value again on the maximum
+                    // will lead to under-counting the max pref width.
+                    if (!addedTextIndent) {
+                        childMax += ti;
+                        beginMax += ti;
+                        addedTextIndent = true;
+                    }
+                    
+                    if (childMin < 0) {
+                        textIndent = childMin;
+                        hasRemainingNegativeTextIndent = true;
+                    }
+                }
+                
+                // 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.
+                        updatePreferredWidth(minLogicalWidth, inlineMin);
+                    else {
+                        inlineMin += beginMin;
+                        updatePreferredWidth(minLogicalWidth, inlineMin);
+                        childMin -= ti;
+                    }
+
+                    inlineMin = childMin;
+
+                    if (endWS) {
+                        // We end in whitespace, which means we can go ahead
+                        // and end our current line.
+                        updatePreferredWidth(minLogicalWidth, inlineMin);
+                        inlineMin = 0;
+                        shouldBreakLineAfterText = false;
+                    } else {
+                        updatePreferredWidth(minLogicalWidth, inlineMin);
+                        inlineMin = endMin;
+                        shouldBreakLineAfterText = true;
+                    }
+                }
+
+                if (hasBreak) {
+                    inlineMax += beginMax;
+                    updatePreferredWidth(maxLogicalWidth, inlineMax);
+                    updatePreferredWidth(maxLogicalWidth, childMax);
+                    inlineMax = endMax;
+                    addedTextIndent = true;
+                } else
+                    inlineMax += max<float>(0, childMax);
+            }
+
+            // Ignore spaces after a list marker.
+            if (child->isListMarker())
+                stripFrontSpaces = true;
+        } else {
+            updatePreferredWidth(minLogicalWidth, inlineMin);
+            updatePreferredWidth(maxLogicalWidth, inlineMax);
+            inlineMin = inlineMax = 0;
+            stripFrontSpaces = true;
+            trailingSpaceChild = 0;
+            addedTextIndent = true;
+        }
+
+        if (!child->isText() && child->isRenderInline())
+            isPrevChildInlineFlow = true;
+        else
+            isPrevChildInlineFlow = false;
+
+        oldAutoWrap = autoWrap;
+    }
+
+    if (styleToUse->collapseWhiteSpace())
+        stripTrailingSpace(inlineMax, inlineMin, trailingSpaceChild);
+
+    updatePreferredWidth(minLogicalWidth, inlineMin);
+    updatePreferredWidth(maxLogicalWidth, inlineMax);
+}
+
+void RenderBlock::computeBlockPreferredLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const
+{
+    RenderStyle* styleToUse = style();
+    bool nowrap = styleToUse->whiteSpace() == NOWRAP;
+
+    RenderObject* child = firstChild();
+    RenderBlock* containingBlock = this->containingBlock();
+    LayoutUnit floatLeftWidth = 0, floatRightWidth = 0;
+    while (child) {
+        // Positioned children don't affect the min/max width
+        if (child->isOutOfFlowPositioned()) {
+            child = child->nextSibling();
+            continue;
+        }
+
+        RenderStyle* childStyle = child->style();
+        if (child->isFloating() || (child->isBox() && toRenderBox(child)->avoidsFloats())) {
+            LayoutUnit floatTotalWidth = floatLeftWidth + floatRightWidth;
+            if (childStyle->clear() & CLEFT) {
+                maxLogicalWidth = max(floatTotalWidth, maxLogicalWidth);
+                floatLeftWidth = 0;
+            }
+            if (childStyle->clear() & CRIGHT) {
+                maxLogicalWidth = max(floatTotalWidth, maxLogicalWidth);
+                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 startMarginLength = childStyle->marginStartUsing(styleToUse);
+        Length endMarginLength = childStyle->marginEndUsing(styleToUse);
+        LayoutUnit margin = 0;
+        LayoutUnit marginStart = 0;
+        LayoutUnit marginEnd = 0;
+        if (startMarginLength.isFixed())
+            marginStart += startMarginLength.value();
+        if (endMarginLength.isFixed())
+            marginEnd += endMarginLength.value();
+        margin = marginStart + marginEnd;
+
+        LayoutUnit childMinPreferredLogicalWidth, childMaxPreferredLogicalWidth;
+        if (child->isBox() && child->isHorizontalWritingMode() != isHorizontalWritingMode()) {
+            RenderBox* childBox = toRenderBox(child);
+            LogicalExtentComputedValues computedValues;
+            childBox->computeLogicalHeight(childBox->borderAndPaddingLogicalHeight(), 0, computedValues);
+            childMinPreferredLogicalWidth = childMaxPreferredLogicalWidth = computedValues.m_extent;
+        } else {
+            childMinPreferredLogicalWidth = child->minPreferredLogicalWidth();
+            childMaxPreferredLogicalWidth = child->maxPreferredLogicalWidth();
+        }
+
+        LayoutUnit w = childMinPreferredLogicalWidth + margin;
+        minLogicalWidth = max(w, minLogicalWidth);
+        
+        // IE ignores tables for calculation of nowrap. Makes some sense.
+        if (nowrap && !child->isTable())
+            maxLogicalWidth = max(w, maxLogicalWidth);
+
+        w = childMaxPreferredLogicalWidth + margin;
+
+        if (!child->isFloating()) {
+            if (child->isBox() && toRenderBox(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.
+                bool ltr = containingBlock ? containingBlock->style()->isLeftToRightDirection() : styleToUse->isLeftToRightDirection();
+                LayoutUnit marginLogicalLeft = ltr ? marginStart : marginEnd;
+                LayoutUnit marginLogicalRight = ltr ? marginEnd : marginStart;
+                LayoutUnit maxLeft = marginLogicalLeft > 0 ? max(floatLeftWidth, marginLogicalLeft) : floatLeftWidth + marginLogicalLeft;
+                LayoutUnit maxRight = marginLogicalRight > 0 ? max(floatRightWidth, marginLogicalRight) : floatRightWidth + marginLogicalRight;
+                w = childMaxPreferredLogicalWidth + maxLeft + maxRight;
+                w = max(w, floatLeftWidth + floatRightWidth);
+            }
+            else
+                maxLogicalWidth = max(floatLeftWidth + floatRightWidth, maxLogicalWidth);
+            floatLeftWidth = floatRightWidth = 0;
+        }
+        
+        if (child->isFloating()) {
+            if (childStyle->floating() == LeftFloat)
+                floatLeftWidth += w;
+            else
+                floatRightWidth += w;
+        } else
+            maxLogicalWidth = max(w, maxLogicalWidth);
+        
+        child = child->nextSibling();
+    }
+
+    // Always make sure these values are non-negative.
+    minLogicalWidth = max<LayoutUnit>(0, minLogicalWidth);
+    maxLogicalWidth = max<LayoutUnit>(0, maxLogicalWidth);
+
+    maxLogicalWidth = max(floatLeftWidth + floatRightWidth, maxLogicalWidth);
+}
+
+bool RenderBlock::hasLineIfEmpty() const
+{
+    if (!node())
+        return false;
+    
+    if (node()->isRootEditableElement())
+        return true;
+    
+    if (node()->isShadowRoot() && toShadowRoot(node())->host()->hasTagName(inputTag))
+        return true;
+    
+    return false;
+}
+
+LayoutUnit RenderBlock::lineHeight(bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) 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() && linePositionMode == PositionOnContainingLine)
+        return RenderBox::lineHeight(firstLine, direction, linePositionMode);
+
+    if (firstLine && document()->styleSheetCollection()->usesFirstLineRules()) {
+        RenderStyle* s = style(firstLine);
+        if (s != style())
+            return s->computedLineHeight(view());
+    }
+    
+    if (m_lineHeight == -1)
+        m_lineHeight = style()->computedLineHeight(view());
+
+    return m_lineHeight;
+}
+
+int RenderBlock::baselinePosition(FontBaseline baselineType, bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) 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() && linePositionMode == PositionOnContainingLine) {
+        // 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.
+        // FIXME: Need to patch form controls to deal with vertical lines.
+        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.
+        bool ignoreBaseline = (layer() && (layer()->marquee() || (direction == HorizontalLine ? (layer()->verticalScrollbar() || layer()->scrollYOffset() != 0)
+            : (layer()->horizontalScrollbar() || layer()->scrollXOffset() != 0)))) || (isWritingModeRoot() && !isRubyRun());
+        
+        int baselinePos = ignoreBaseline ? -1 : inlineBlockBaseline(direction);
+        
+        LayoutUnit bottomOfContent = direction == HorizontalLine ? borderTop() + paddingTop() + contentHeight() : borderRight() + paddingRight() + contentWidth();
+        if (baselinePos != -1 && baselinePos <= bottomOfContent)
+            return direction == HorizontalLine ? marginTop() + baselinePos : marginRight() + baselinePos;
+            
+        return RenderBox::baselinePosition(baselineType, firstLine, direction, linePositionMode);
+    }
+
+    // If we're not replaced, we'll only get called with PositionOfInteriorLineBoxes.
+    // Note that inline-block counts as replaced here.
+    ASSERT(linePositionMode == PositionOfInteriorLineBoxes);
+
+    const FontMetrics& fontMetrics = style(firstLine)->fontMetrics();
+    return fontMetrics.ascent(baselineType) + (lineHeight(firstLine, direction, linePositionMode) - fontMetrics.height()) / 2;
+}
+
+int RenderBlock::firstLineBoxBaseline() const
+{
+    if (!isBlockFlow() || (isWritingModeRoot() && !isRubyRun()))
+        return -1;
+
+    if (childrenInline()) {
+        if (firstLineBox())
+            return firstLineBox()->logicalTop() + style(true)->fontMetrics().ascent(firstRootBox()->baselineType());
+        else
+            return -1;
+    }
+    else {
+        for (RenderBox* curr = firstChildBox(); curr; curr = curr->nextSiblingBox()) {
+            if (!curr->isFloatingOrOutOfFlowPositioned()) {
+                int result = curr->firstLineBoxBaseline();
+                if (result != -1)
+                    return curr->logicalTop() + result; // Translate to our coordinate space.
+            }
+        }
+    }
+
+    return -1;
+}
+
+int RenderBlock::inlineBlockBaseline(LineDirectionMode direction) const
+{
+    return lastLineBoxBaseline(direction);
+}
+
+int RenderBlock::lastLineBoxBaseline(LineDirectionMode lineDirection) const
+{
+    if (!isBlockFlow() || (isWritingModeRoot() && !isRubyRun()))
+        return -1;
+
+    if (childrenInline()) {
+        if (!firstLineBox() && hasLineIfEmpty()) {
+            const FontMetrics& fontMetrics = firstLineStyle()->fontMetrics();
+            return fontMetrics.ascent()
+                 + (lineHeight(true, lineDirection, PositionOfInteriorLineBoxes) - fontMetrics.height()) / 2
+                 + (lineDirection == HorizontalLine ? borderTop() + paddingTop() : borderRight() + paddingRight());
+        }
+        if (lastLineBox())
+            return lastLineBox()->logicalTop() + style(lastLineBox() == firstLineBox())->fontMetrics().ascent(lastRootBox()->baselineType());
+        return -1;
+    } else {
+        bool haveNormalFlowChild = false;
+        for (RenderBox* curr = lastChildBox(); curr; curr = curr->previousSiblingBox()) {
+            if (!curr->isFloatingOrOutOfFlowPositioned()) {
+                haveNormalFlowChild = true;
+                int result = curr->inlineBlockBaseline(lineDirection);
+                if (result != -1)
+                    return curr->logicalTop() + result; // Translate to our coordinate space.
+            }
+        }
+        if (!haveNormalFlowChild && hasLineIfEmpty()) {
+            const FontMetrics& fontMetrics = firstLineStyle()->fontMetrics();
+            return fontMetrics.ascent()
+                 + (lineHeight(true, lineDirection, PositionOfInteriorLineBoxes) - fontMetrics.height()) / 2
+                 + (lineDirection == HorizontalLine ? borderTop() + paddingTop() : borderRight() + paddingRight());
+        }
+    }
+
+    return -1;
+}
+
+bool RenderBlock::containsNonZeroBidiLevel() const
+{
+    for (RootInlineBox* root = firstRootBox(); root; root = root->nextRootBox()) {
+        for (InlineBox* box = root->firstLeafChild(); box; box = box->nextLeafChild()) {
+            if (box->bidiLevel())
+                return true;
+        }
+    }
+    return false;
+}
+
+RenderBlock* RenderBlock::firstLineBlock() const
+{
+    RenderBlock* firstLineBlock = const_cast<RenderBlock*>(this);
+    bool hasPseudo = false;
+    while (true) {
+        hasPseudo = firstLineBlock->style()->hasPseudoStyle(FIRST_LINE);
+        if (hasPseudo)
+            break;
+        RenderObject* parentBlock = firstLineBlock->parent();
+        // We include isRenderButton in this check because buttons are
+        // implemented using flex box but should still support first-line. The
+        // flex box spec requires that flex box does not support first-line,
+        // though.
+        // FIXME: Remove when buttons are implemented with align-items instead
+        // of flexbox.
+        if (firstLineBlock->isReplaced() || firstLineBlock->isFloating()
+            || !parentBlock || parentBlock->firstChild() != firstLineBlock || !parentBlock->isBlockFlow()
+            || (parentBlock->isFlexibleBox() && !parentBlock->isRenderButton()))
+            break;
+        ASSERT_WITH_SECURITY_IMPLICATION(parentBlock->isRenderBlock());
+        firstLineBlock = toRenderBlock(parentBlock);
+    } 
+    
+    if (!hasPseudo)
+        return 0;
+    
+    return firstLineBlock;
+}
+
+static RenderStyle* styleForFirstLetter(RenderObject* firstLetterBlock, RenderObject* firstLetterContainer)
+{
+    RenderStyle* pseudoStyle = firstLetterBlock->getCachedPseudoStyle(FIRST_LETTER, firstLetterContainer->firstLineStyle());
+    // Force inline display (except for floating first-letters).
+    pseudoStyle->setDisplay(pseudoStyle->isFloating() ? BLOCK : INLINE);
+    // CSS2 says first-letter can't be positioned.
+    pseudoStyle->setPosition(StaticPosition);
+    return pseudoStyle;
+}
+
+// CSS 2.1 http://www.w3.org/TR/CSS21/selector.html#first-letter
+// "Punctuation (i.e, characters defined in Unicode [UNICODE] in the "open" (Ps), "close" (Pe),
+// "initial" (Pi). "final" (Pf) and "other" (Po) punctuation classes), that precedes or follows the first letter should be included"
+static inline bool isPunctuationForFirstLetter(UChar c)
+{
+    CharCategory charCategory = category(c);
+    return charCategory == Punctuation_Open
+        || charCategory == Punctuation_Close
+        || charCategory == Punctuation_InitialQuote
+        || charCategory == Punctuation_FinalQuote
+        || charCategory == Punctuation_Other;
+}
+
+static inline bool shouldSkipForFirstLetter(UChar c)
+{
+    return isSpaceOrNewline(c) || c == noBreakSpace || isPunctuationForFirstLetter(c);
+}
+
+static inline RenderObject* findFirstLetterBlock(RenderBlock* start)
+{
+    RenderObject* firstLetterBlock = start;
+    while (true) {
+        // We include isRenderButton in these two checks because buttons are
+        // implemented using flex box but should still support first-letter.
+        // The flex box spec requires that flex box does not support
+        // first-letter, though.
+        // FIXME: Remove when buttons are implemented with align-items instead
+        // of flexbox.
+        bool canHaveFirstLetterRenderer = firstLetterBlock->style()->hasPseudoStyle(FIRST_LETTER)
+            && firstLetterBlock->canHaveGeneratedChildren()
+            && (!firstLetterBlock->isFlexibleBox() || firstLetterBlock->isRenderButton());
+        if (canHaveFirstLetterRenderer)
+            return firstLetterBlock;
+
+        RenderObject* parentBlock = firstLetterBlock->parent();
+        if (firstLetterBlock->isReplaced() || !parentBlock || parentBlock->firstChild() != firstLetterBlock || 
+            !parentBlock->isBlockFlow() || (parentBlock->isFlexibleBox() && !parentBlock->isRenderButton()))
+            return 0;
+        firstLetterBlock = parentBlock;
+    } 
+
+    return 0;
+}
+
+void RenderBlock::updateFirstLetterStyle(RenderObject* firstLetterBlock, RenderObject* currentChild)
+{
+    RenderObject* firstLetter = currentChild->parent();
+    RenderObject* firstLetterContainer = firstLetter->parent();
+    RenderStyle* pseudoStyle = styleForFirstLetter(firstLetterBlock, firstLetterContainer);
+    ASSERT(firstLetter->isFloating() || firstLetter->isInline());
+
+    if (Node::diff(firstLetter->style(), pseudoStyle, document()) == Node::Detach) {
+        // The first-letter renderer needs to be replaced. Create a new renderer of the right type.
+        RenderObject* newFirstLetter;
+        if (pseudoStyle->display() == INLINE)
+            newFirstLetter = RenderInline::createAnonymous(document());
+        else
+            newFirstLetter = RenderBlock::createAnonymous(document());
+        newFirstLetter->setStyle(pseudoStyle);
+
+        // Move the first letter into the new renderer.
+        LayoutStateDisabler layoutStateDisabler(view());
+        while (RenderObject* child = firstLetter->firstChild()) {
+            if (child->isText())
+                toRenderText(child)->removeAndDestroyTextBoxes();
+            firstLetter->removeChild(child);
+            newFirstLetter->addChild(child, 0);
+        }
+
+        RenderTextFragment* remainingText = 0;
+        RenderObject* nextSibling = firstLetter->nextSibling();
+        RenderObject* remainingTextObject = toRenderBoxModelObject(firstLetter)->firstLetterRemainingText();
+        if (remainingTextObject && remainingTextObject->isText() && toRenderText(remainingTextObject)->isTextFragment())
+            remainingText = toRenderTextFragment(remainingTextObject);
+        if (remainingText) {
+            ASSERT(remainingText->isAnonymous() || remainingText->node()->renderer() == remainingText);
+            // Replace the old renderer with the new one.
+            remainingText->setFirstLetter(newFirstLetter);
+            toRenderBoxModelObject(newFirstLetter)->setFirstLetterRemainingText(remainingText);
+        }
+        // To prevent removal of single anonymous block in RenderBlock::removeChild and causing
+        // |nextSibling| to go stale, we remove the old first letter using removeChildNode first.
+        firstLetterContainer->virtualChildren()->removeChildNode(firstLetterContainer, firstLetter);
+        firstLetter->destroy();
+        firstLetter = newFirstLetter;
+        firstLetterContainer->addChild(firstLetter, nextSibling);
+    } else
+        firstLetter->setStyle(pseudoStyle);
+
+    for (RenderObject* genChild = firstLetter->firstChild(); genChild; genChild = genChild->nextSibling()) {
+        if (genChild->isText())
+            genChild->setStyle(pseudoStyle);
+    }
+}
+
+void RenderBlock::createFirstLetterRenderer(RenderObject* firstLetterBlock, RenderObject* currentChild)
+{
+    RenderObject* firstLetterContainer = currentChild->parent();
+    RenderStyle* pseudoStyle = styleForFirstLetter(firstLetterBlock, firstLetterContainer);
+    RenderObject* firstLetter = 0;
+    if (pseudoStyle->display() == INLINE)
+        firstLetter = RenderInline::createAnonymous(document());
+    else
+        firstLetter = RenderBlock::createAnonymous(document());
+    firstLetter->setStyle(pseudoStyle);
+    firstLetterContainer->addChild(firstLetter, currentChild);
+
+    RenderText* textObj = toRenderText(currentChild);
+
+    // 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 length = 0;
+
+        // Account for leading spaces and punctuation.
+        while (length < oldText->length() && shouldSkipForFirstLetter((*oldText)[length]))
+            length++;
+
+        // Account for first letter.
+        length++;
+        
+        // Keep looking for whitespace and allowed punctuation, but avoid
+        // accumulating just whitespace into the :first-letter.
+        for (unsigned scanLength = length; scanLength < oldText->length(); ++scanLength) {
+            UChar c = (*oldText)[scanLength]; 
+            
+            if (!shouldSkipForFirstLetter(c))
+                break;
+
+            if (isPunctuationForFirstLetter(c))
+                length = scanLength + 1;
+         }
+         
+        // Construct a text fragment for the text after the first letter.
+        // This text fragment might be empty.
+        RenderTextFragment* remainingText = 
+            new (renderArena()) RenderTextFragment(textObj->node() ? textObj->node() : textObj->document(), oldText.get(), length, oldText->length() - length);
+        remainingText->setStyle(textObj->style());
+        if (remainingText->node())
+            remainingText->node()->setRenderer(remainingText);
+
+        firstLetterContainer->addChild(remainingText, textObj);
+        firstLetterContainer->removeChild(textObj);
+        remainingText->setFirstLetter(firstLetter);
+        toRenderBoxModelObject(firstLetter)->setFirstLetterRemainingText(remainingText);
+        
+        // construct text fragment for the first letter
+        RenderTextFragment* letter = 
+            new (renderArena()) RenderTextFragment(remainingText->node() ? remainingText->node() : remainingText->document(), oldText.get(), 0, length);
+        letter->setStyle(pseudoStyle);
+        firstLetter->addChild(letter);
+
+        textObj->destroy();
+    }
+}
+
+void RenderBlock::updateFirstLetter()
+{
+    if (!document()->styleSheetCollection()->usesFirstLetterRules())
+        return;
+    // Don't recur
+    if (style()->styleType() == 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 = findFirstLetterBlock(this);
+    if (!firstLetterBlock)
+        return;
+
+    // Drill into inlines looking for our first text child.
+    RenderObject* currChild = firstLetterBlock->firstChild();
+    while (currChild) {
+        if (currChild->isText())
+            break;
+        if (currChild->isListMarker())
+            currChild = currChild->nextSibling();
+        else if (currChild->isFloatingOrOutOfFlowPositioned()) {
+            if (currChild->style()->styleType() == FIRST_LETTER) {
+                currChild = currChild->firstChild();
+                break;
+            }
+            currChild = currChild->nextSibling();
+        } else if (currChild->isReplaced() || currChild->isRenderButton() || currChild->isMenuList())
+            break;
+        else if (currChild->style()->hasPseudoStyle(FIRST_LETTER) && currChild->canHaveGeneratedChildren())  {
+            // We found a lower-level node with first-letter, which supersedes the higher-level style
+            firstLetterBlock = currChild;
+            currChild = currChild->firstChild();
+        } else
+            currChild = currChild->firstChild();
+    }
+
+    if (!currChild)
+        return;
+
+    // If the child already has style, then it has already been created, so we just want
+    // to update it.
+    if (currChild->parent()->style()->styleType() == FIRST_LETTER) {
+        updateFirstLetterStyle(firstLetterBlock, currChild);
+        return;
+    }
+
+    if (!currChild->isText() || currChild->isBR())
+        return;
+
+    // Our layout state is not valid for the repaints we are going to trigger by
+    // adding and removing children of firstLetterContainer.
+    LayoutStateDisabler layoutStateDisabler(view());
+
+    createFirstLetterRenderer(firstLetterBlock, currChild);
+}
+
+// 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->isFloatingOrOutOfFlowPositioned() && !obj->isRunIn()
+            && obj->isBlockFlow() && obj->style()->height().isAuto()
+            && (!obj->isDeprecatedFlexibleBox() || obj->style()->boxOrient() == VERTICAL);
+}
+
+static 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->lineBottom() + (includeBottom ? (block->borderBottom() + block->paddingBottom()) : LayoutUnit());
+            }
+        }
+        else {
+            RenderBox* normalFlowChildWithoutLines = 0;
+            for (RenderBox* obj = block->firstChildBox(); obj; obj = obj->nextSiblingBox()) {
+                if (shouldCheckLines(obj)) {
+                    int result = getHeightForLineCount(toRenderBlock(obj), l, false, count);
+                    if (result != -1)
+                        return result + obj->y() + (includeBottom ? (block->borderBottom() + block->paddingBottom()) : LayoutUnit());
+                } else if (!obj->isFloatingOrOutOfFlowPositioned() && !obj->isRunIn())
+                    normalFlowChildWithoutLines = obj;
+            }
+            if (normalFlowChildWithoutLines && l == 0)
+                return normalFlowChildWithoutLines->y() + normalFlowChildWithoutLines->height();
+        }
+    }
+    
+    return -1;
+}
+
+RootInlineBox* RenderBlock::lineAtIndex(int i) const
+{
+    ASSERT(i >= 0);
+
+    if (style()->visibility() != VISIBLE)
+        return 0;
+
+    if (childrenInline()) {
+        for (RootInlineBox* box = firstRootBox(); box; box = box->nextRootBox())
+            if (!i--)
+                return box;
+    } else {
+        for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+            if (!shouldCheckLines(child))
+                continue;
+            if (RootInlineBox* box = toRenderBlock(child)->lineAtIndex(i))
+                return box;
+        }
+    }
+
+    return 0;
+}
+
+int RenderBlock::lineCount(const RootInlineBox* stopRootInlineBox, bool* found) const
+{
+    int count = 0;
+
+    if (style()->visibility() == VISIBLE) {
+        if (childrenInline())
+            for (RootInlineBox* box = firstRootBox(); box; box = box->nextRootBox()) {
+                count++;
+                if (box == stopRootInlineBox) {
+                    if (found)
+                        *found = true;
+                    break;
+                }
+            }
+        else
+            for (RenderObject* obj = firstChild(); obj; obj = obj->nextSibling())
+                if (shouldCheckLines(obj)) {
+                    bool recursiveFound = false;
+                    count += toRenderBlock(obj)->lineCount(stopRootInlineBox, &recursiveFound);
+                    if (recursiveFound) {
+                        if (found)
+                            *found = true;
+                        break;
+                    }
+                }
+    }
+    return count;
+}
+
+int RenderBlock::heightForLineCount(int l)
+{
+    int count = 0;
+    return getHeightForLineCount(this, l, true, count);
+}
+
+void RenderBlock::adjustForBorderFit(LayoutUnit x, LayoutUnit& left, LayoutUnit& 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 + static_cast<LayoutUnit>(box->firstChild()->x()));
+                if (box->lastChild())
+                    right = max(right, x + static_cast<LayoutUnit>(ceilf(box->lastChild()->logicalRight())));
+            }
+        }
+        else {
+            for (RenderBox* obj = firstChildBox(); obj; obj = obj->nextSiblingBox()) {
+                if (!obj->isFloatingOrOutOfFlowPositioned()) {
+                    if (obj->isBlockFlow() && !obj->hasOverflowClip())
+                        toRenderBlock(obj)->adjustForBorderFit(x + obj->x(), 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->x());
+                        right = max(right, x + obj->x() + obj->width());
+                    }
+                }
+            }
+        }
+        
+        if (m_floatingObjects) {
+            const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
+            FloatingObjectSetIterator end = floatingObjectSet.end();
+            for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
+                FloatingObject* r = *it;
+                // Only examine the object if our m_shouldPaint flag is set.
+                if (r->shouldPaint()) {
+                    LayoutUnit floatLeft = xPositionForFloatIncludingMargin(r) - r->m_renderer->x();
+                    LayoutUnit floatRight = floatLeft + r->m_renderer->width();
+                    left = min(left, floatLeft);
+                    right = max(right, floatRight);
+                }
+            }
+        }
+    }
+}
+
+void RenderBlock::fitBorderToLinesIfNeeded()
+{
+    if (style()->borderFit() == BorderFitBorder || hasOverrideWidth())
+        return;
+
+    // Walk any normal flow lines to snugly fit.
+    LayoutUnit left = LayoutUnit::max();
+    LayoutUnit right = LayoutUnit::min();
+    LayoutUnit oldWidth = contentWidth();
+    adjustForBorderFit(0, left, right);
+    
+    // Clamp to our existing edges. We can never grow. We only shrink.
+    LayoutUnit leftEdge = borderLeft() + paddingLeft();
+    LayoutUnit rightEdge = leftEdge + oldWidth;
+    left = min(rightEdge, max(leftEdge, left));
+    right = max(leftEdge, min(rightEdge, right));
+    
+    LayoutUnit newContentWidth = right - left;
+    if (newContentWidth == oldWidth)
+        return;
+    
+    setOverrideLogicalContentWidth(newContentWidth);
+    layoutBlock(false);
+    clearOverrideLogicalContentWidth();
+}
+
+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))
+                    toRenderBlock(obj)->clearTruncation();
+            }
+        }
+    }
+}
+
+void RenderBlock::setMaxMarginBeforeValues(LayoutUnit pos, LayoutUnit neg)
+{
+    if (!m_rareData) {
+        if (pos == RenderBlockRareData::positiveMarginBeforeDefault(this) && neg == RenderBlockRareData::negativeMarginBeforeDefault(this))
+            return;
+        m_rareData = adoptPtr(new RenderBlockRareData(this));
+    }
+    m_rareData->m_margins.setPositiveMarginBefore(pos);
+    m_rareData->m_margins.setNegativeMarginBefore(neg);
+}
+
+void RenderBlock::setMaxMarginAfterValues(LayoutUnit pos, LayoutUnit neg)
+{
+    if (!m_rareData) {
+        if (pos == RenderBlockRareData::positiveMarginAfterDefault(this) && neg == RenderBlockRareData::negativeMarginAfterDefault(this))
+            return;
+        m_rareData = adoptPtr(new RenderBlockRareData(this));
+    }
+    m_rareData->m_margins.setPositiveMarginAfter(pos);
+    m_rareData->m_margins.setNegativeMarginAfter(neg);
+}
+
+void RenderBlock::setMustDiscardMarginBefore(bool value)
+{
+    if (style()->marginBeforeCollapse() == MDISCARD) {
+        ASSERT(value);
+        return;
+    }
+    
+    if (!m_rareData && !value)
+        return;
+
+    if (!m_rareData)
+        m_rareData = adoptPtr(new RenderBlockRareData(this));
+
+    m_rareData->m_discardMarginBefore = value;
+}
+
+void RenderBlock::setMustDiscardMarginAfter(bool value)
+{
+    if (style()->marginAfterCollapse() == MDISCARD) {
+        ASSERT(value);
+        return;
+    }
+
+    if (!m_rareData && !value)
+        return;
+
+    if (!m_rareData)
+        m_rareData = adoptPtr(new RenderBlockRareData(this));
+
+    m_rareData->m_discardMarginAfter = value;
+}
+
+bool RenderBlock::mustDiscardMarginBefore() const
+{
+    return style()->marginBeforeCollapse() == MDISCARD || (m_rareData && m_rareData->m_discardMarginBefore);
+}
+
+bool RenderBlock::mustDiscardMarginAfter() const
+{
+    return style()->marginAfterCollapse() == MDISCARD || (m_rareData && m_rareData->m_discardMarginAfter);
+}
+
+bool RenderBlock::mustDiscardMarginBeforeForChild(const RenderBox* child) const
+{
+    ASSERT(!child->selfNeedsLayout());
+    if (!child->isWritingModeRoot())
+        return child->isRenderBlock() ? toRenderBlock(child)->mustDiscardMarginBefore() : (child->style()->marginBeforeCollapse() == MDISCARD);
+    if (child->isHorizontalWritingMode() == isHorizontalWritingMode())
+        return child->isRenderBlock() ? toRenderBlock(child)->mustDiscardMarginAfter() : (child->style()->marginAfterCollapse() == MDISCARD);
+
+    // FIXME: We return false here because the implementation is not geometrically complete. We have values only for before/after, not start/end.
+    // In case the boxes are perpendicular we assume the property is not specified.
+    return false;
+}
+
+bool RenderBlock::mustDiscardMarginAfterForChild(const RenderBox* child) const
+{
+    ASSERT(!child->selfNeedsLayout());
+    if (!child->isWritingModeRoot())
+        return child->isRenderBlock() ? toRenderBlock(child)->mustDiscardMarginAfter() : (child->style()->marginAfterCollapse() == MDISCARD);
+    if (child->isHorizontalWritingMode() == isHorizontalWritingMode())
+        return child->isRenderBlock() ? toRenderBlock(child)->mustDiscardMarginBefore() : (child->style()->marginBeforeCollapse() == MDISCARD);
+
+    // FIXME: See |mustDiscardMarginBeforeForChild| above.
+    return false;
+}
+
+bool RenderBlock::mustSeparateMarginBeforeForChild(const RenderBox* child) const
+{
+    ASSERT(!child->selfNeedsLayout());
+    const RenderStyle* childStyle = child->style();
+    if (!child->isWritingModeRoot())
+        return childStyle->marginBeforeCollapse() == MSEPARATE;
+    if (child->isHorizontalWritingMode() == isHorizontalWritingMode())
+        return childStyle->marginAfterCollapse() == MSEPARATE;
+
+    // FIXME: See |mustDiscardMarginBeforeForChild| above.
+    return false;
+}
+
+bool RenderBlock::mustSeparateMarginAfterForChild(const RenderBox* child) const
+{
+    ASSERT(!child->selfNeedsLayout());
+    const RenderStyle* childStyle = child->style();
+    if (!child->isWritingModeRoot())
+        return childStyle->marginAfterCollapse() == MSEPARATE;
+    if (child->isHorizontalWritingMode() == isHorizontalWritingMode())
+        return childStyle->marginBeforeCollapse() == MSEPARATE;
+
+    // FIXME: See |mustDiscardMarginBeforeForChild| above.
+    return false;
+}
+
+void RenderBlock::setPaginationStrut(LayoutUnit strut)
+{
+    if (!m_rareData) {
+        if (!strut)
+            return;
+        m_rareData = adoptPtr(new RenderBlockRareData(this));
+    }
+    m_rareData->m_paginationStrut = strut;
+}
+
+void RenderBlock::setPageLogicalOffset(LayoutUnit logicalOffset)
+{
+    if (!m_rareData) {
+        if (!logicalOffset)
+            return;
+        m_rareData = adoptPtr(new RenderBlockRareData(this));
+    }
+    m_rareData->m_pageLogicalOffset = logicalOffset;
+}
+
+void RenderBlock::setBreakAtLineToAvoidWidow(RootInlineBox* lineToBreak)
+{
+    ASSERT(lineToBreak);
+    if (!m_rareData)
+        m_rareData = adoptPtr(new RenderBlockRareData(this));
+    m_rareData->m_shouldBreakAtLineToAvoidWidow = true;
+    m_rareData->m_lineBreakToAvoidWidow = lineToBreak;
+}
+
+void RenderBlock::clearShouldBreakAtLineToAvoidWidow() const
+{
+    if (!m_rareData)
+        return;
+    m_rareData->m_shouldBreakAtLineToAvoidWidow = false;
+    m_rareData->m_lineBreakToAvoidWidow = 0;
+}
+
+void RenderBlock::absoluteRects(Vector<IntRect>& rects, const LayoutPoint& accumulatedOffset) const
+{
+    // 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 (isAnonymousBlockContinuation()) {
+        // FIXME: This is wrong for block-flows that are horizontal.
+        // https://bugs.webkit.org/show_bug.cgi?id=46781
+        rects.append(pixelSnappedIntRect(accumulatedOffset.x(), accumulatedOffset.y() - collapsedMarginBefore(),
+                                width(), height() + collapsedMarginBefore() + collapsedMarginAfter()));
+        continuation()->absoluteRects(rects, accumulatedOffset - toLayoutSize(location() +
+                inlineElementContinuation()->containingBlock()->location()));
+    } else
+        rects.append(pixelSnappedIntRect(accumulatedOffset, size()));
+}
+
+void RenderBlock::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed) const
+{
+    // 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 (isAnonymousBlockContinuation()) {
+        // FIXME: This is wrong for block-flows that are horizontal.
+        // https://bugs.webkit.org/show_bug.cgi?id=46781
+        FloatRect localRect(0, -collapsedMarginBefore(),
+                            width(), height() + collapsedMarginBefore() + collapsedMarginAfter());
+        quads.append(localToAbsoluteQuad(localRect, 0 /* mode */, wasFixed));
+        continuation()->absoluteQuads(quads, wasFixed);
+    } else
+        quads.append(RenderBox::localToAbsoluteQuad(FloatRect(0, 0, width(), height()), 0 /* mode */, wasFixed));
+}
+
+LayoutRect RenderBlock::rectWithOutlineForRepaint(const RenderLayerModelObject* repaintContainer, LayoutUnit outlineWidth) const
+{
+    LayoutRect r(RenderBox::rectWithOutlineForRepaint(repaintContainer, outlineWidth));
+    if (isAnonymousBlockContinuation())
+        r.inflateY(collapsedMarginBefore()); // FIXME: This is wrong for block-flows that are horizontal.
+    return r;
+}
+
+RenderObject* RenderBlock::hoverAncestor() const
+{
+    return isAnonymousBlockContinuation() ? continuation() : RenderBox::hoverAncestor();
+}
+
+void RenderBlock::updateDragState(bool dragOn)
+{
+    RenderBox::updateDragState(dragOn);
+    if (continuation())
+        continuation()->updateDragState(dragOn);
+}
+
+RenderStyle* RenderBlock::outlineStyleForRepaint() const
+{
+    return isAnonymousBlockContinuation() ? continuation()->style() : style();
+}
+
+void RenderBlock::childBecameNonInline(RenderObject*)
+{
+    makeChildrenNonInline();
+    if (isAnonymousBlock() && parent() && parent()->isRenderBlock())
+        toRenderBlock(parent())->removeLeftoverAnonymousBlock(this);
+    // |this| may be dead here
+}
+
+void RenderBlock::updateHitTestResult(HitTestResult& result, const LayoutPoint& point)
+{
+    if (result.innerNode())
+        return;
+
+    if (Node* n = nodeForHitTest()) {
+        result.setInnerNode(n);
+        if (!result.innerNonSharedNode())
+            result.setInnerNonSharedNode(n);
+        result.setLocalPoint(point);
+    }
+}
+
+LayoutRect RenderBlock::localCaretRect(InlineBox* inlineBox, int caretOffset, LayoutUnit* extraWidthToEndOfLine)
+{
+    // Do the normal calculation in most cases.
+    if (firstChild())
+        return RenderBox::localCaretRect(inlineBox, caretOffset, extraWidthToEndOfLine);
+
+    LayoutRect caretRect = localCaretRectForEmptyElement(width(), textIndentOffset());
+
+    if (extraWidthToEndOfLine) {
+        if (isRenderBlock()) {
+            *extraWidthToEndOfLine = width() - caretRect.maxX();
+        } else {
+            // FIXME: This code looks wrong.
+            // myRight and containerRight are set up, but then clobbered.
+            // So *extraWidthToEndOfLine will always be 0 here.
+
+            LayoutUnit myRight = caretRect.maxX();
+            // FIXME: why call localToAbsoluteForContent() twice here, too?
+            FloatPoint absRightPoint = localToAbsolute(FloatPoint(myRight, 0));
+
+            LayoutUnit containerRight = containingBlock()->x() + containingBlockLogicalWidthForContent();
+            FloatPoint absContainerPoint = localToAbsolute(FloatPoint(containerRight, 0));
+
+            *extraWidthToEndOfLine = absContainerPoint.x() - absRightPoint.x();
+        }
+    }
+
+    return caretRect;
+}
+
+void RenderBlock::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint& additionalOffset, const RenderLayerModelObject* paintContainer)
+{
+    // 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 (inlineElementContinuation()) {
+        // FIXME: This check really isn't accurate. 
+        bool nextInlineHasLineBox = inlineElementContinuation()->firstLineBox();
+        // FIXME: This is wrong. The principal renderer may not be the continuation preceding this block.
+        // FIXME: This is wrong for block-flows that are horizontal.
+        // https://bugs.webkit.org/show_bug.cgi?id=46781
+        bool prevInlineHasLineBox = toRenderInline(inlineElementContinuation()->node()->renderer())->firstLineBox(); 
+        float topMargin = prevInlineHasLineBox ? collapsedMarginBefore() : LayoutUnit();
+        float bottomMargin = nextInlineHasLineBox ? collapsedMarginAfter() : LayoutUnit();
+        LayoutRect rect(additionalOffset.x(), additionalOffset.y() - topMargin, width(), height() + topMargin + bottomMargin);
+        if (!rect.isEmpty())
+            rects.append(pixelSnappedIntRect(rect));
+    } else if (width() && height())
+        rects.append(pixelSnappedIntRect(additionalOffset, size()));
+
+    if (!hasOverflowClip() && !hasControlClip()) {
+        for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) {
+            LayoutUnit top = max<LayoutUnit>(curr->lineTop(), curr->top());
+            LayoutUnit bottom = min<LayoutUnit>(curr->lineBottom(), curr->top() + curr->height());
+            LayoutRect rect(additionalOffset.x() + curr->x(), additionalOffset.y() + top, curr->width(), bottom - top);
+            if (!rect.isEmpty())
+                rects.append(pixelSnappedIntRect(rect));
+        }
+
+        for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
+            if (!curr->isText() && !curr->isListMarker() && curr->isBox()) {
+                RenderBox* box = toRenderBox(curr);
+                FloatPoint pos;
+                // FIXME: This doesn't work correctly with transforms.
+                if (box->layer()) 
+                    pos = curr->localToContainerPoint(FloatPoint(), paintContainer);
+                else
+                    pos = FloatPoint(additionalOffset.x() + box->x(), additionalOffset.y() + box->y());
+                box->addFocusRingRects(rects, flooredLayoutPoint(pos), paintContainer);
+            }
+        }
+    }
+
+    if (inlineElementContinuation())
+        inlineElementContinuation()->addFocusRingRects(rects, flooredLayoutPoint(additionalOffset + inlineElementContinuation()->containingBlock()->location() - location()), paintContainer);
+}
+
+RenderBox* RenderBlock::createAnonymousBoxWithSameTypeAs(const RenderObject* parent) const
+{
+    if (isAnonymousColumnsBlock())
+        return createAnonymousColumnsWithParentRenderer(parent);
+    if (isAnonymousColumnSpanBlock())
+        return createAnonymousColumnSpanWithParentRenderer(parent);
+    return createAnonymousWithParentRendererAndDisplay(parent, style()->display());
+}
+
+bool RenderBlock::hasNextPage(LayoutUnit logicalOffset, PageBoundaryRule pageBoundaryRule) const
+{
+    ASSERT(view()->layoutState() && view()->layoutState()->isPaginated());
+
+    RenderFlowThread* flowThread = flowThreadContainingBlock();
+    if (!flowThread)
+        return true; // Printing and multi-column both make new pages to accommodate content.
+
+    // See if we're in the last region.
+    LayoutUnit pageOffset = offsetFromLogicalTopOfFirstPage() + logicalOffset;
+    RenderRegion* region = flowThread->regionAtBlockOffset(pageOffset, this);
+    if (!region)
+        return false;
+    if (region->isLastRegion())
+        return region->isRenderRegionSet() || region->style()->regionOverflow() == BreakRegionOverflow
+            || (pageBoundaryRule == IncludePageBoundary && pageOffset == region->logicalTopForFlowThreadContent());
+    return true;
+}
+
+LayoutUnit RenderBlock::nextPageLogicalTop(LayoutUnit logicalOffset, PageBoundaryRule pageBoundaryRule) const
+{
+    LayoutUnit pageLogicalHeight = pageLogicalHeightForOffset(logicalOffset);
+    if (!pageLogicalHeight)
+        return logicalOffset;
+    
+    // The logicalOffset is in our coordinate space.  We can add in our pushed offset.
+    LayoutUnit remainingLogicalHeight = pageRemainingLogicalHeightForOffset(logicalOffset);
+    if (pageBoundaryRule == ExcludePageBoundary)
+        return logicalOffset + (remainingLogicalHeight ? remainingLogicalHeight : pageLogicalHeight);
+    return logicalOffset + remainingLogicalHeight;
+}
+
+static bool inNormalFlow(RenderBox* child)
+{
+    RenderBlock* curr = child->containingBlock();
+    RenderView* renderView = child->view();
+    while (curr && curr != renderView) {
+        if (curr->hasColumns() || curr->isRenderFlowThread())
+            return true;
+        if (curr->isFloatingOrOutOfFlowPositioned())
+            return false;
+        curr = curr->containingBlock();
+    }
+    return true;
+}
+
+ColumnInfo::PaginationUnit RenderBlock::paginationUnit() const
+{
+    return ColumnInfo::Column;
+}
+
+LayoutUnit RenderBlock::applyBeforeBreak(RenderBox* child, LayoutUnit logicalOffset)
+{
+    // FIXME: Add page break checking here when we support printing.
+    bool checkColumnBreaks = view()->layoutState()->isPaginatingColumns();
+    bool checkPageBreaks = !checkColumnBreaks && view()->layoutState()->m_pageLogicalHeight; // FIXME: Once columns can print we have to check this.
+    RenderFlowThread* flowThread = flowThreadContainingBlock();
+    bool checkRegionBreaks = flowThread && flowThread->isRenderNamedFlowThread();
+    bool checkBeforeAlways = (checkColumnBreaks && child->style()->columnBreakBefore() == PBALWAYS) || (checkPageBreaks && child->style()->pageBreakBefore() == PBALWAYS)
+                             || (checkRegionBreaks && child->style()->regionBreakBefore() == PBALWAYS);
+    if (checkBeforeAlways && inNormalFlow(child) && hasNextPage(logicalOffset, IncludePageBoundary)) {
+        if (checkColumnBreaks)
+            view()->layoutState()->addForcedColumnBreak(child, logicalOffset);
+        if (checkRegionBreaks) {
+            LayoutUnit offsetBreakAdjustment = 0;
+            if (flowThread->addForcedRegionBreak(offsetFromLogicalTopOfFirstPage() + logicalOffset, child, true, &offsetBreakAdjustment))
+                return logicalOffset + offsetBreakAdjustment;
+        }
+        return nextPageLogicalTop(logicalOffset, IncludePageBoundary);
+    }
+    return logicalOffset;
+}
+
+LayoutUnit RenderBlock::applyAfterBreak(RenderBox* child, LayoutUnit logicalOffset, MarginInfo& marginInfo)
+{
+    // FIXME: Add page break checking here when we support printing.
+    bool checkColumnBreaks = view()->layoutState()->isPaginatingColumns();
+    bool checkPageBreaks = !checkColumnBreaks && view()->layoutState()->m_pageLogicalHeight; // FIXME: Once columns can print we have to check this.
+    RenderFlowThread* flowThread = flowThreadContainingBlock();
+    bool checkRegionBreaks = flowThread && flowThread->isRenderNamedFlowThread();
+    bool checkAfterAlways = (checkColumnBreaks && child->style()->columnBreakAfter() == PBALWAYS) || (checkPageBreaks && child->style()->pageBreakAfter() == PBALWAYS)
+                            || (checkRegionBreaks && child->style()->regionBreakAfter() == PBALWAYS);
+    if (checkAfterAlways && inNormalFlow(child) && hasNextPage(logicalOffset, IncludePageBoundary)) {
+        LayoutUnit marginOffset = marginInfo.canCollapseWithMarginBefore() ? LayoutUnit() : marginInfo.margin();
+
+        // So our margin doesn't participate in the next collapsing steps.
+        marginInfo.clearMargin();
+
+        if (checkColumnBreaks)
+            view()->layoutState()->addForcedColumnBreak(child, logicalOffset);
+        if (checkRegionBreaks) {
+            LayoutUnit offsetBreakAdjustment = 0;
+            if (flowThread->addForcedRegionBreak(offsetFromLogicalTopOfFirstPage() + logicalOffset + marginOffset, child, false, &offsetBreakAdjustment))
+                return logicalOffset + marginOffset + offsetBreakAdjustment;
+        }
+        return nextPageLogicalTop(logicalOffset, IncludePageBoundary);
+    }
+    return logicalOffset;
+}
+
+LayoutUnit RenderBlock::pageLogicalTopForOffset(LayoutUnit offset) const
+{
+    RenderView* renderView = view();
+    LayoutUnit firstPageLogicalTop = isHorizontalWritingMode() ? renderView->layoutState()->m_pageOffset.height() : renderView->layoutState()->m_pageOffset.width();
+    LayoutUnit blockLogicalTop = isHorizontalWritingMode() ? renderView->layoutState()->m_layoutOffset.height() : renderView->layoutState()->m_layoutOffset.width();
+
+    LayoutUnit cumulativeOffset = offset + blockLogicalTop;
+    RenderFlowThread* flowThread = flowThreadContainingBlock();
+    if (!flowThread) {
+        LayoutUnit pageLogicalHeight = renderView->layoutState()->pageLogicalHeight();
+        if (!pageLogicalHeight)
+            return 0;
+        return cumulativeOffset - roundToInt(cumulativeOffset - firstPageLogicalTop) % roundToInt(pageLogicalHeight);
+    }
+    return flowThread->pageLogicalTopForOffset(cumulativeOffset);
+}
+
+LayoutUnit RenderBlock::pageLogicalHeightForOffset(LayoutUnit offset) const
+{
+    RenderView* renderView = view();
+    RenderFlowThread* flowThread = flowThreadContainingBlock();
+    if (!flowThread)
+        return renderView->layoutState()->m_pageLogicalHeight;
+    return flowThread->pageLogicalHeightForOffset(offset + offsetFromLogicalTopOfFirstPage());
+}
+
+LayoutUnit RenderBlock::pageRemainingLogicalHeightForOffset(LayoutUnit offset, PageBoundaryRule pageBoundaryRule) const
+{
+    RenderView* renderView = view();
+    offset += offsetFromLogicalTopOfFirstPage();
+    
+    RenderFlowThread* flowThread = flowThreadContainingBlock();
+    if (!flowThread) {
+        LayoutUnit pageLogicalHeight = renderView->layoutState()->m_pageLogicalHeight;
+        LayoutUnit remainingHeight = pageLogicalHeight - intMod(offset, pageLogicalHeight);
+        if (pageBoundaryRule == IncludePageBoundary) {
+            // If includeBoundaryPoint is true the line exactly on the top edge of a
+            // column will act as being part of the previous column.
+            remainingHeight = intMod(remainingHeight, pageLogicalHeight);
+        }
+        return remainingHeight;
+    }
+    
+    return flowThread->pageRemainingLogicalHeightForOffset(offset, pageBoundaryRule);
+}
+
+LayoutUnit RenderBlock::adjustForUnsplittableChild(RenderBox* child, LayoutUnit logicalOffset, bool includeMargins)
+{
+    bool checkColumnBreaks = view()->layoutState()->isPaginatingColumns();
+    bool checkPageBreaks = !checkColumnBreaks && view()->layoutState()->m_pageLogicalHeight;
+    RenderFlowThread* flowThread = flowThreadContainingBlock();
+    bool checkRegionBreaks = flowThread && flowThread->isRenderNamedFlowThread();
+    bool isUnsplittable = child->isUnsplittableForPagination() || (checkColumnBreaks && child->style()->columnBreakInside() == PBAVOID)
+        || (checkPageBreaks && child->style()->pageBreakInside() == PBAVOID)
+        || (checkRegionBreaks && child->style()->regionBreakInside() == PBAVOID);
+    if (!isUnsplittable)
+        return logicalOffset;
+    LayoutUnit childLogicalHeight = logicalHeightForChild(child) + (includeMargins ? marginBeforeForChild(child) + marginAfterForChild(child) : LayoutUnit());
+    LayoutState* layoutState = view()->layoutState();
+    if (layoutState->m_columnInfo)
+        layoutState->m_columnInfo->updateMinimumColumnHeight(childLogicalHeight);
+    LayoutUnit pageLogicalHeight = pageLogicalHeightForOffset(logicalOffset);
+    bool hasUniformPageLogicalHeight = !flowThread || flowThread->regionsHaveUniformLogicalHeight();
+    if (!pageLogicalHeight || (hasUniformPageLogicalHeight && childLogicalHeight > pageLogicalHeight)
+        || !hasNextPage(logicalOffset))
+        return logicalOffset;
+    LayoutUnit remainingLogicalHeight = pageRemainingLogicalHeightForOffset(logicalOffset, ExcludePageBoundary);
+    if (remainingLogicalHeight < childLogicalHeight) {
+        if (!hasUniformPageLogicalHeight && !pushToNextPageWithMinimumLogicalHeight(remainingLogicalHeight, logicalOffset, childLogicalHeight))
+            return logicalOffset;
+        return logicalOffset + remainingLogicalHeight;
+    }
+    return logicalOffset;
+}
+
+bool RenderBlock::pushToNextPageWithMinimumLogicalHeight(LayoutUnit& adjustment, LayoutUnit logicalOffset, LayoutUnit minimumLogicalHeight) const
+{
+    bool checkRegion = false;
+    for (LayoutUnit pageLogicalHeight = pageLogicalHeightForOffset(logicalOffset + adjustment); pageLogicalHeight;
+        pageLogicalHeight = pageLogicalHeightForOffset(logicalOffset + adjustment)) {
+        if (minimumLogicalHeight <= pageLogicalHeight)
+            return true;
+        if (!hasNextPage(logicalOffset + adjustment))
+            return false;
+        adjustment += pageLogicalHeight;
+        checkRegion = true;
+    }
+    return !checkRegion;
+}
+
+void RenderBlock::adjustLinePositionForPagination(RootInlineBox* lineBox, LayoutUnit& delta, RenderFlowThread* flowThread)
+{
+    // FIXME: For now we paginate using line overflow.  This ensures that lines don't overlap at all when we
+    // put a strut between them for pagination purposes.  However, this really isn't the desired rendering, since
+    // the line on the top of the next page will appear too far down relative to the same kind of line at the top
+    // of the first column.
+    //
+    // The rendering we would like to see is one where the lineTopWithLeading is at the top of the column, and any line overflow
+    // simply spills out above the top of the column.  This effect would match what happens at the top of the first column.
+    // We can't achieve this rendering, however, until we stop columns from clipping to the column bounds (thus allowing
+    // for overflow to occur), and then cache visible overflow for each column rect.
+    //
+    // Furthermore, the paint we have to do when a column has overflow has to be special.  We need to exclude
+    // content that paints in a previous column (and content that paints in the following column).
+    //
+    // For now we'll at least honor the lineTopWithLeading when paginating if it is above the logical top overflow. This will
+    // at least make positive leading work in typical cases.
+    //
+    // FIXME: Another problem with simply moving lines is that the available line width may change (because of floats).
+    // Technically if the location we move the line to has a different line width than our old position, then we need to dirty the
+    // line and all following lines.
+    LayoutRect logicalVisualOverflow = lineBox->logicalVisualOverflowRect(lineBox->lineTop(), lineBox->lineBottom());
+    LayoutUnit logicalOffset = min(lineBox->lineTopWithLeading(), logicalVisualOverflow.y());
+    LayoutUnit lineHeight = max(lineBox->lineBottomWithLeading(), logicalVisualOverflow.maxY()) - logicalOffset;
+    RenderView* renderView = view();
+    LayoutState* layoutState = renderView->layoutState();
+    if (layoutState->m_columnInfo)
+        layoutState->m_columnInfo->updateMinimumColumnHeight(lineHeight);
+    logicalOffset += delta;
+    lineBox->setPaginationStrut(0);
+    lineBox->setIsFirstAfterPageBreak(false);
+    LayoutUnit pageLogicalHeight = pageLogicalHeightForOffset(logicalOffset);
+    bool hasUniformPageLogicalHeight = !flowThread || flowThread->regionsHaveUniformLogicalHeight();
+    // If lineHeight is greater than pageLogicalHeight, but logicalVisualOverflow.height() still fits, we are
+    // still going to add a strut, so that the visible overflow fits on a single page.
+    if (!pageLogicalHeight || (hasUniformPageLogicalHeight && logicalVisualOverflow.height() > pageLogicalHeight)
+        || !hasNextPage(logicalOffset))
+        return;
+    LayoutUnit remainingLogicalHeight = pageRemainingLogicalHeightForOffset(logicalOffset, ExcludePageBoundary);
+
+    if (remainingLogicalHeight < lineHeight || (shouldBreakAtLineToAvoidWidow() && lineBreakToAvoidWidow() == lineBox)) {
+        if (shouldBreakAtLineToAvoidWidow() && lineBreakToAvoidWidow() == lineBox)
+            clearShouldBreakAtLineToAvoidWidow();
+        // If we have a non-uniform page height, then we have to shift further possibly.
+        if (!hasUniformPageLogicalHeight && !pushToNextPageWithMinimumLogicalHeight(remainingLogicalHeight, logicalOffset, lineHeight))
+            return;
+        if (lineHeight > pageLogicalHeight) {
+            // Split the top margin in order to avoid splitting the visible part of the line.
+            remainingLogicalHeight -= min(lineHeight - pageLogicalHeight, max<LayoutUnit>(0, logicalVisualOverflow.y() - lineBox->lineTopWithLeading()));
+        }
+        LayoutUnit totalLogicalHeight = lineHeight + max<LayoutUnit>(0, logicalOffset);
+        LayoutUnit pageLogicalHeightAtNewOffset = hasUniformPageLogicalHeight ? pageLogicalHeight : pageLogicalHeightForOffset(logicalOffset + remainingLogicalHeight);
+        if (((lineBox == firstRootBox() && totalLogicalHeight < pageLogicalHeightAtNewOffset) || (!style()->hasAutoOrphans() && style()->orphans() >= lineCount(lineBox)))
+            && !isOutOfFlowPositioned() && !isTableCell())
+            setPaginationStrut(remainingLogicalHeight + max<LayoutUnit>(0, logicalOffset));
+        else {
+            delta += remainingLogicalHeight;
+            lineBox->setPaginationStrut(remainingLogicalHeight);
+            lineBox->setIsFirstAfterPageBreak(true);
+        }
+    } else if (remainingLogicalHeight == pageLogicalHeight && lineBox != firstRootBox())
+        lineBox->setIsFirstAfterPageBreak(true);
+}
+
+LayoutUnit RenderBlock::adjustBlockChildForPagination(LayoutUnit logicalTopAfterClear, LayoutUnit estimateWithoutPagination, RenderBox* child, bool atBeforeSideOfBlock)
+{
+    RenderBlock* childRenderBlock = child->isRenderBlock() ? toRenderBlock(child) : 0;
+
+    if (estimateWithoutPagination != logicalTopAfterClear) {
+        // Our guess prior to pagination movement was wrong. Before we attempt to paginate, let's try again at the new
+        // position.
+        setLogicalHeight(logicalTopAfterClear);
+        setLogicalTopForChild(child, logicalTopAfterClear, ApplyLayoutDelta);
+
+        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, MarkOnlyThis);
+        }
+        
+        if (childRenderBlock) {
+            if (!child->avoidsFloats() && childRenderBlock->containsFloats())
+                childRenderBlock->markAllDescendantsWithFloatsForLayout();
+            if (!child->needsLayout())
+                child->markForPaginationRelayoutIfNeeded();
+        }
+
+        // Our guess was wrong. Make the child lay itself out again.
+        child->layoutIfNeeded();
+    }
+
+    LayoutUnit oldTop = logicalTopAfterClear;
+
+    // If the object has a page or column break value of "before", then we should shift to the top of the next page.
+    LayoutUnit result = applyBeforeBreak(child, logicalTopAfterClear);
+
+    // For replaced elements and scrolled elements, we want to shift them to the next page if they don't fit on the current one.
+    LayoutUnit logicalTopBeforeUnsplittableAdjustment = result;
+    LayoutUnit logicalTopAfterUnsplittableAdjustment = adjustForUnsplittableChild(child, result);
+    
+    LayoutUnit paginationStrut = 0;
+    LayoutUnit unsplittableAdjustmentDelta = logicalTopAfterUnsplittableAdjustment - logicalTopBeforeUnsplittableAdjustment;
+    if (unsplittableAdjustmentDelta)
+        paginationStrut = unsplittableAdjustmentDelta;
+    else if (childRenderBlock && childRenderBlock->paginationStrut())
+        paginationStrut = childRenderBlock->paginationStrut();
+
+    if (paginationStrut) {
+        // We are willing to propagate out to our parent block as long as we were at the top of the block prior
+        // to collapsing our margins, and as long as we didn't clear or move as a result of other pagination.
+        if (atBeforeSideOfBlock && oldTop == result && !isOutOfFlowPositioned() && !isTableCell()) {
+            // FIXME: Should really check if we're exceeding the page height before propagating the strut, but we don't
+            // have all the information to do so (the strut only has the remaining amount to push). Gecko gets this wrong too
+            // and pushes to the next page anyway, so not too concerned about it.
+            setPaginationStrut(result + paginationStrut);
+            if (childRenderBlock)
+                childRenderBlock->setPaginationStrut(0);
+        } else
+            result += paginationStrut;
+    }
+
+    // Similar to how we apply clearance. Go ahead and boost height() to be the place where we're going to position the child.
+    setLogicalHeight(logicalHeight() + (result - oldTop));
+    
+    // Return the final adjusted logical top.
+    return result;
+}
+
+bool RenderBlock::lineWidthForPaginatedLineChanged(RootInlineBox* rootBox, LayoutUnit lineDelta, RenderFlowThread* flowThread) const
+{
+    if (!flowThread)
+        return false;
+
+    RenderRegion* currentRegion = regionAtBlockOffset(rootBox->lineTopWithLeading() + lineDelta);
+    // Just bail if the region didn't change.
+    if (rootBox->containingRegion() == currentRegion)
+        return false;
+    return rootBox->paginatedLineWidth() != availableLogicalWidthForContent(currentRegion, offsetFromLogicalTopOfFirstPage());
+}
+
+LayoutUnit RenderBlock::offsetFromLogicalTopOfFirstPage() const
+{
+    LayoutState* layoutState = view()->layoutState();
+    if (layoutState && !layoutState->isPaginated())
+        return 0;
+    if (layoutState) {
+        // FIXME: Sanity check that the renderer in the layout state is ours, since otherwise the computation will be off.
+        // Right now this assert gets hit inside computeLogicalHeight for percentage margins, since they're computed using
+        // widths which can vary in each region. Until we patch that, we can't have this assert.
+        // ASSERT(layoutState->m_renderer == this);
+
+        LayoutSize offsetDelta = layoutState->m_layoutOffset - layoutState->m_pageOffset;
+        return isHorizontalWritingMode() ? offsetDelta.height() : offsetDelta.width();
+    }
+    // FIXME: Right now, this assert is hit outside layout, from logicalLeftSelectionOffset in selectionGapRectsForRepaint (called from FrameSelection::selectAll).
+    // ASSERT(inRenderFlowThread());
+
+    // FIXME: This is a slower path that doesn't use layout state and relies on getting your logical top inside the enclosing flow thread. It doesn't
+    // work with columns or pages currently, but it should once they have been switched over to using flow threads.
+    RenderFlowThread* flowThread = flowThreadContainingBlock();
+    if (!flowThread)
+        return 0;
+
+    const RenderBlock* currentBlock = this;
+    LayoutRect blockRect(0, 0, width(), height());
+
+    while (currentBlock && !currentBlock->isRenderFlowThread()) {
+        RenderBlock* containerBlock = currentBlock->containingBlock();
+        ASSERT(containerBlock);
+        if (!containerBlock)
+            return 0;
+        LayoutPoint currentBlockLocation = currentBlock->location();
+
+        if (containerBlock->style()->writingMode() != currentBlock->style()->writingMode()) {
+            // We have to put the block rect in container coordinates
+            // and we have to take into account both the container and current block flipping modes
+            if (containerBlock->style()->isFlippedBlocksWritingMode()) {
+                if (containerBlock->isHorizontalWritingMode())
+                    blockRect.setY(currentBlock->height() - blockRect.maxY());
+                else
+                    blockRect.setX(currentBlock->width() - blockRect.maxX());
+            }
+            currentBlock->flipForWritingMode(blockRect);
+        }
+        blockRect.moveBy(currentBlockLocation);
+        currentBlock = containerBlock;
+    };
+    return currentBlock->isHorizontalWritingMode() ? blockRect.y() : blockRect.x();
+}
+
+RenderRegion* RenderBlock::regionAtBlockOffset(LayoutUnit blockOffset) const
+{
+    RenderFlowThread* flowThread = flowThreadContainingBlock();
+    if (!flowThread || !flowThread->hasValidRegionInfo())
+        return 0;
+
+    return flowThread->regionAtBlockOffset(offsetFromLogicalTopOfFirstPage() + blockOffset, true);
+}
+
+void RenderBlock::updateStaticInlinePositionForChild(RenderBox* child, LayoutUnit logicalTop)
+{
+    if (child->style()->isOriginalDisplayInlineType())
+        setStaticInlinePositionForChild(child, logicalTop, startAlignedOffsetForLine(logicalTop, false));
+    else
+        setStaticInlinePositionForChild(child, logicalTop, startOffsetForContent(logicalTop));
+}
+
+void RenderBlock::setStaticInlinePositionForChild(RenderBox* child, LayoutUnit blockOffset, LayoutUnit inlinePosition)
+{
+    if (flowThreadContainingBlock()) {
+        // Shift the inline position to exclude the region offset.
+        inlinePosition += startOffsetForContent() - startOffsetForContent(blockOffset);
+    }
+    child->layer()->setStaticInlinePosition(inlinePosition);
+}
+
+bool RenderBlock::logicalWidthChangedInRegions(RenderFlowThread* flowThread) const
+{
+    if (!flowThread || !flowThread->hasValidRegionInfo())
+        return false;
+    
+    return flowThread->logicalWidthChangedInRegions(this, offsetFromLogicalTopOfFirstPage());
+}
+
+RenderRegion* RenderBlock::clampToStartAndEndRegions(RenderRegion* region) const
+{
+    RenderFlowThread* flowThread = flowThreadContainingBlock();
+
+    ASSERT(isRenderView() || (region && flowThread));
+    if (isRenderView())
+        return region;
+
+    // We need to clamp to the block, since we want any lines or blocks that overflow out of the
+    // logical top or logical bottom of the block to size as though the border box in the first and
+    // last regions extended infinitely. Otherwise the lines are going to size according to the regions
+    // they overflow into, which makes no sense when this block doesn't exist in |region| at all.
+    RenderRegion* startRegion;
+    RenderRegion* endRegion;
+    flowThread->getRegionRangeForBox(this, startRegion, endRegion);
+    
+    if (startRegion && region->logicalTopForFlowThreadContent() < startRegion->logicalTopForFlowThreadContent())
+        return startRegion;
+    if (endRegion && region->logicalTopForFlowThreadContent() > endRegion->logicalTopForFlowThreadContent())
+        return endRegion;
+    
+    return region;
+}
+
+LayoutUnit RenderBlock::collapsedMarginBeforeForChild(const RenderBox* child) const
+{
+    // If the child has the same directionality as we do, then we can just return its
+    // collapsed margin.
+    if (!child->isWritingModeRoot())
+        return child->collapsedMarginBefore();
+    
+    // The child has a different directionality.  If the child is parallel, then it's just
+    // flipped relative to us.  We can use the collapsed margin for the opposite edge.
+    if (child->isHorizontalWritingMode() == isHorizontalWritingMode())
+        return child->collapsedMarginAfter();
+    
+    // The child is perpendicular to us, which means its margins don't collapse but are on the
+    // "logical left/right" sides of the child box.  We can just return the raw margin in this case.  
+    return marginBeforeForChild(child);
+}
+
+LayoutUnit RenderBlock::collapsedMarginAfterForChild(const  RenderBox* child) const
+{
+    // If the child has the same directionality as we do, then we can just return its
+    // collapsed margin.
+    if (!child->isWritingModeRoot())
+        return child->collapsedMarginAfter();
+    
+    // The child has a different directionality.  If the child is parallel, then it's just
+    // flipped relative to us.  We can use the collapsed margin for the opposite edge.
+    if (child->isHorizontalWritingMode() == isHorizontalWritingMode())
+        return child->collapsedMarginBefore();
+    
+    // The child is perpendicular to us, which means its margins don't collapse but are on the
+    // "logical left/right" side of the child box.  We can just return the raw margin in this case.  
+    return marginAfterForChild(child);
+}
+
+bool RenderBlock::hasMarginBeforeQuirk(const RenderBox* child) const
+{
+    // If the child has the same directionality as we do, then we can just return its
+    // margin quirk.
+    if (!child->isWritingModeRoot())
+        return child->isRenderBlock() ? toRenderBlock(child)->hasMarginBeforeQuirk() : child->style()->hasMarginBeforeQuirk();
+    
+    // The child has a different directionality. If the child is parallel, then it's just
+    // flipped relative to us. We can use the opposite edge.
+    if (child->isHorizontalWritingMode() == isHorizontalWritingMode())
+        return child->isRenderBlock() ? toRenderBlock(child)->hasMarginAfterQuirk() : child->style()->hasMarginAfterQuirk();
+    
+    // The child is perpendicular to us and box sides are never quirky in html.css, and we don't really care about
+    // whether or not authors specified quirky ems, since they're an implementation detail.
+    return false;
+}
+
+bool RenderBlock::hasMarginAfterQuirk(const RenderBox* child) const
+{
+    // If the child has the same directionality as we do, then we can just return its
+    // margin quirk.
+    if (!child->isWritingModeRoot())
+        return child->isRenderBlock() ? toRenderBlock(child)->hasMarginAfterQuirk() : child->style()->hasMarginAfterQuirk();
+    
+    // The child has a different directionality. If the child is parallel, then it's just
+    // flipped relative to us. We can use the opposite edge.
+    if (child->isHorizontalWritingMode() == isHorizontalWritingMode())
+        return child->isRenderBlock() ? toRenderBlock(child)->hasMarginBeforeQuirk() : child->style()->hasMarginBeforeQuirk();
+    
+    // The child is perpendicular to us and box sides are never quirky in html.css, and we don't really care about
+    // whether or not authors specified quirky ems, since they're an implementation detail.
+    return false;
+}
+
+RenderBlock::MarginValues RenderBlock::marginValuesForChild(RenderBox* child) const
+{
+    LayoutUnit childBeforePositive = 0;
+    LayoutUnit childBeforeNegative = 0;
+    LayoutUnit childAfterPositive = 0;
+    LayoutUnit childAfterNegative = 0;
+
+    LayoutUnit beforeMargin = 0;
+    LayoutUnit afterMargin = 0;
+
+    RenderBlock* childRenderBlock = child->isRenderBlock() ? toRenderBlock(child) : 0;
+    
+    // If the child has the same directionality as we do, then we can just return its
+    // margins in the same direction.
+    if (!child->isWritingModeRoot()) {
+        if (childRenderBlock) {
+            childBeforePositive = childRenderBlock->maxPositiveMarginBefore();
+            childBeforeNegative = childRenderBlock->maxNegativeMarginBefore();
+            childAfterPositive = childRenderBlock->maxPositiveMarginAfter();
+            childAfterNegative = childRenderBlock->maxNegativeMarginAfter();
+        } else {
+            beforeMargin = child->marginBefore();
+            afterMargin = child->marginAfter();
+        }
+    } else if (child->isHorizontalWritingMode() == isHorizontalWritingMode()) {
+        // The child has a different directionality.  If the child is parallel, then it's just
+        // flipped relative to us.  We can use the margins for the opposite edges.
+        if (childRenderBlock) {
+            childBeforePositive = childRenderBlock->maxPositiveMarginAfter();
+            childBeforeNegative = childRenderBlock->maxNegativeMarginAfter();
+            childAfterPositive = childRenderBlock->maxPositiveMarginBefore();
+            childAfterNegative = childRenderBlock->maxNegativeMarginBefore();
+        } else {
+            beforeMargin = child->marginAfter();
+            afterMargin = child->marginBefore();
+        }
+    } else {
+        // The child is perpendicular to us, which means its margins don't collapse but are on the
+        // "logical left/right" sides of the child box.  We can just return the raw margin in this case.
+        beforeMargin = marginBeforeForChild(child);
+        afterMargin = marginAfterForChild(child);
+    }
+
+    // Resolve uncollapsing margins into their positive/negative buckets.
+    if (beforeMargin) {
+        if (beforeMargin > 0)
+            childBeforePositive = beforeMargin;
+        else
+            childBeforeNegative = -beforeMargin;
+    }
+    if (afterMargin) {
+        if (afterMargin > 0)
+            childAfterPositive = afterMargin;
+        else
+            childAfterNegative = -afterMargin;
+    }
+
+    return MarginValues(childBeforePositive, childBeforeNegative, childAfterPositive, childAfterNegative);
+}
+
+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 (isOutOfFlowPositioned())
+        return "RenderBlock (positioned)";
+    if (isAnonymousColumnsBlock())
+        return "RenderBlock (anonymous multi-column)";
+    if (isAnonymousColumnSpanBlock())
+        return "RenderBlock (anonymous multi-column span)";
+    if (isAnonymousBlock())
+        return "RenderBlock (anonymous)";
+    // FIXME: Temporary hack while the new generated content system is being implemented.
+    if (isPseudoElement())
+        return "RenderBlock (generated)";
+    if (isAnonymous())
+        return "RenderBlock (generated)";
+    if (isRelPositioned())
+        return "RenderBlock (relative positioned)";
+    if (isStickyPositioned())
+        return "RenderBlock (sticky positioned)";
+    if (isRunIn())
+        return "RenderBlock (run-in)";
+    return "RenderBlock";
+}
+
+inline RenderBlock::FloatingObjects::FloatingObjects(const RenderBlock* renderer, bool horizontalWritingMode)
+    : m_placedFloatsTree(UninitializedTree)
+    , m_leftObjectsCount(0)
+    , m_rightObjectsCount(0)
+    , m_horizontalWritingMode(horizontalWritingMode)
+    , m_renderer(renderer)
+{
+}
+
+void RenderBlock::createFloatingObjects()
+{
+    m_floatingObjects = adoptPtr(new FloatingObjects(this, isHorizontalWritingMode()));
+}
+
+inline void RenderBlock::FloatingObjects::clear()
+{
+    m_set.clear();
+    m_placedFloatsTree.clear();
+    m_leftObjectsCount = 0;
+    m_rightObjectsCount = 0;
+}
+
+inline void RenderBlock::FloatingObjects::increaseObjectsCount(FloatingObject::Type type)
+{    
+    if (type == FloatingObject::FloatLeft)
+        m_leftObjectsCount++;
+    else 
+        m_rightObjectsCount++;
+}
+
+inline void RenderBlock::FloatingObjects::decreaseObjectsCount(FloatingObject::Type type)
+{
+    if (type == FloatingObject::FloatLeft)
+        m_leftObjectsCount--;
+    else
+        m_rightObjectsCount--;
+}
+
+inline RenderBlock::FloatingObjectInterval RenderBlock::FloatingObjects::intervalForFloatingObject(FloatingObject* floatingObject)
+{
+    if (m_horizontalWritingMode)
+        return RenderBlock::FloatingObjectInterval(floatingObject->frameRect().pixelSnappedY(), floatingObject->frameRect().pixelSnappedMaxY(), floatingObject);
+    return RenderBlock::FloatingObjectInterval(floatingObject->frameRect().pixelSnappedX(), floatingObject->frameRect().pixelSnappedMaxX(), floatingObject);
+}
+
+void RenderBlock::FloatingObjects::addPlacedObject(FloatingObject* floatingObject)
+{
+    ASSERT(!floatingObject->isInPlacedTree());
+
+    floatingObject->setIsPlaced(true);
+    if (m_placedFloatsTree.isInitialized())
+        m_placedFloatsTree.add(intervalForFloatingObject(floatingObject));
+
+#ifndef NDEBUG
+    floatingObject->setIsInPlacedTree(true);      
+#endif
+}
+
+void RenderBlock::FloatingObjects::removePlacedObject(FloatingObject* floatingObject)
+{
+    ASSERT(floatingObject->isPlaced() && floatingObject->isInPlacedTree());
+
+    if (m_placedFloatsTree.isInitialized()) {
+        bool removed = m_placedFloatsTree.remove(intervalForFloatingObject(floatingObject));
+        ASSERT_UNUSED(removed, removed);
+    }
+    
+    floatingObject->setIsPlaced(false);
+#ifndef NDEBUG
+    floatingObject->setIsInPlacedTree(false);
+#endif
+}
+
+inline void RenderBlock::FloatingObjects::add(FloatingObject* floatingObject)
+{
+    increaseObjectsCount(floatingObject->type());
+    m_set.add(floatingObject);
+    if (floatingObject->isPlaced())
+        addPlacedObject(floatingObject);
+}
+
+inline void RenderBlock::FloatingObjects::remove(FloatingObject* floatingObject)
+{
+    decreaseObjectsCount(floatingObject->type());
+    m_set.remove(floatingObject);
+    ASSERT(floatingObject->isPlaced() || !floatingObject->isInPlacedTree());
+    if (floatingObject->isPlaced())
+        removePlacedObject(floatingObject);
+}
+
+void RenderBlock::FloatingObjects::computePlacedFloatsTree()
+{
+    ASSERT(!m_placedFloatsTree.isInitialized());
+    if (m_set.isEmpty())
+        return;
+    m_placedFloatsTree.initIfNeeded(m_renderer->view()->intervalArena());
+    FloatingObjectSetIterator it = m_set.begin();
+    FloatingObjectSetIterator end = m_set.end();
+    for (; it != end; ++it) {
+        FloatingObject* floatingObject = *it;
+        if (floatingObject->isPlaced())
+            m_placedFloatsTree.add(intervalForFloatingObject(floatingObject));
+    }
+}
+
+template <typename CharacterType>
+static inline TextRun constructTextRunInternal(RenderObject* context, const Font& font, const CharacterType* characters, int length, RenderStyle* style, TextRun::ExpansionBehavior expansion)
+{
+    ASSERT(style);
+
+    TextDirection textDirection = LTR;
+    bool directionalOverride = style->rtlOrdering() == VisualOrder;
+
+    TextRun run(characters, length, 0, 0, expansion, textDirection, directionalOverride);
+    if (textRunNeedsRenderingContext(font))
+        run.setRenderingContext(SVGTextRunRenderingContext::create(context));
+
+    return run;
+}
+
+template <typename CharacterType>
+static inline TextRun constructTextRunInternal(RenderObject* context, const Font& font, const CharacterType* characters, int length, RenderStyle* style, TextRun::ExpansionBehavior expansion, TextRunFlags flags)
+{
+    ASSERT(style);
+
+    TextDirection textDirection = LTR;
+    bool directionalOverride = style->rtlOrdering() == VisualOrder;
+    if (flags != DefaultTextRunFlags) {
+        if (flags & RespectDirection)
+            textDirection = style->direction();
+        if (flags & RespectDirectionOverride)
+            directionalOverride |= isOverride(style->unicodeBidi());
+    }
+    TextRun run(characters, length, 0, 0, expansion, textDirection, directionalOverride);
+    if (textRunNeedsRenderingContext(font))
+        run.setRenderingContext(SVGTextRunRenderingContext::create(context));
+
+    return run;
+}
+
+#if ENABLE(8BIT_TEXTRUN)
+TextRun RenderBlock::constructTextRun(RenderObject* context, const Font& font, const LChar* characters, int length, RenderStyle* style, TextRun::ExpansionBehavior expansion)
+{
+    return constructTextRunInternal(context, font, characters, length, style, expansion);
+}
+#endif
+
+TextRun RenderBlock::constructTextRun(RenderObject* context, const Font& font, const UChar* characters, int length, RenderStyle* style, TextRun::ExpansionBehavior expansion)
+{
+    return constructTextRunInternal(context, font, characters, length, style, expansion);
+}
+
+TextRun RenderBlock::constructTextRun(RenderObject* context, const Font& font, const RenderText* text, RenderStyle* style, TextRun::ExpansionBehavior expansion)
+{
+#if ENABLE(8BIT_TEXTRUN)
+    if (text->is8Bit())
+        return constructTextRunInternal(context, font, text->characters8(), text->textLength(), style, expansion);
+    return constructTextRunInternal(context, font, text->characters16(), text->textLength(), style, expansion);
+#else
+    return constructTextRunInternal(context, font, text->characters(), text->textLength(), style, expansion);
+#endif
+}
+
+TextRun RenderBlock::constructTextRun(RenderObject* context, const Font& font, const RenderText* text, unsigned offset, unsigned length, RenderStyle* style, TextRun::ExpansionBehavior expansion)
+{
+    ASSERT(offset + length <= text->textLength());
+#if ENABLE(8BIT_TEXTRUN)
+    if (text->is8Bit())
+        return constructTextRunInternal(context, font, text->characters8() + offset, length, style, expansion);
+    return constructTextRunInternal(context, font, text->characters16() + offset, length, style, expansion);
+#else
+    return constructTextRunInternal(context, font, text->characters() + offset, length, style, expansion);
+#endif
+}
+
+TextRun RenderBlock::constructTextRun(RenderObject* context, const Font& font, const String& string, RenderStyle* style, TextRun::ExpansionBehavior expansion, TextRunFlags flags)
+{
+    unsigned length = string.length();
+
+#if ENABLE(8BIT_TEXTRUN)
+    if (length && string.is8Bit())
+        return constructTextRunInternal(context, font, string.characters8(), length, style, expansion, flags);
+    return constructTextRunInternal(context, font, string.characters(), length, style, expansion, flags);
+#else
+    return constructTextRunInternal(context, font, string.characters(), length, style, expansion, flags);
+#endif
+}
+
+RenderBlock* RenderBlock::createAnonymousWithParentRendererAndDisplay(const RenderObject* parent, EDisplay display)
+{
+    // FIXME: Do we need to convert all our inline displays to block-type in the anonymous logic ?
+    EDisplay newDisplay;
+    RenderBlock* newBox = 0;
+    if (display == BOX || display == INLINE_BOX) {
+        // FIXME: Remove this case once we have eliminated all internal users of old flexbox
+        newBox = RenderDeprecatedFlexibleBox::createAnonymous(parent->document());
+        newDisplay = BOX;
+    } else if (display == FLEX || display == INLINE_FLEX) {
+        newBox = RenderFlexibleBox::createAnonymous(parent->document());
+        newDisplay = FLEX;
+    } else {
+        newBox = RenderBlock::createAnonymous(parent->document());
+        newDisplay = BLOCK;
+    }
+
+    RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(parent->style(), newDisplay);
+    newBox->setStyle(newStyle.release());
+    return newBox;
+}
+
+RenderBlock* RenderBlock::createAnonymousColumnsWithParentRenderer(const RenderObject* parent)
+{
+    RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(parent->style(), BLOCK);
+    newStyle->inheritColumnPropertiesFrom(parent->style());
+
+    RenderBlock* newBox = RenderBlock::createAnonymous(parent->document());
+    newBox->setStyle(newStyle.release());
+    return newBox;
+}
+
+RenderBlock* RenderBlock::createAnonymousColumnSpanWithParentRenderer(const RenderObject* parent)
+{
+    RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(parent->style(), BLOCK);
+    newStyle->setColumnSpan(ColumnSpanAll);
+
+    RenderBlock* newBox = RenderBlock::createAnonymous(parent->document());
+    newBox->setStyle(newStyle.release());
+    return newBox;
+}
+
+#ifndef NDEBUG
+void RenderBlock::checkPositionedObjectsNeedLayout()
+{
+    if (!gPositionedDescendantsMap)
+        return;
+
+    if (TrackedRendererListHashSet* positionedDescendantSet = positionedObjects()) {
+        TrackedRendererListHashSet::const_iterator end = positionedDescendantSet->end();
+        for (TrackedRendererListHashSet::const_iterator it = positionedDescendantSet->begin(); it != end; ++it) {
+            RenderBox* currBox = *it;
+            ASSERT(!currBox->needsLayout());
+        }
+    }
+}
+
+void RenderBlock::showLineTreeAndMark(const InlineBox* markedBox1, const char* markedLabel1, const InlineBox* markedBox2, const char* markedLabel2, const RenderObject* obj) const
+{
+    showRenderObject();
+    for (const RootInlineBox* root = firstRootBox(); root; root = root->nextRootBox())
+        root->showLineTreeAndMark(markedBox1, markedLabel1, markedBox2, markedLabel2, obj, 1);
+}
+
+// These helpers are only used by the PODIntervalTree for debugging purposes.
+String ValueToString<int>::string(const int value)
+{
+    return String::number(value);
+}
+
+String ValueToString<RenderBlock::FloatingObject*>::string(const RenderBlock::FloatingObject* floatingObject)
+{
+    return String::format("%p (%dx%d %dx%d)", floatingObject, floatingObject->frameRect().pixelSnappedX(), floatingObject->frameRect().pixelSnappedY(), floatingObject->frameRect().pixelSnappedMaxX(), floatingObject->frameRect().pixelSnappedMaxY());
+}
+
+#endif
+
+void RenderBlock::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, PlatformMemoryTypes::Rendering);
+    RenderBox::reportMemoryUsage(memoryObjectInfo);
+    info.addMember(m_floatingObjects, "floatingObjects");
+    info.addMember(m_rareData, "rareData");
+    info.addMember(m_children, "children");
+    info.addMember(m_lineBoxes, "lineBoxes");
+}
+
+void RenderBlock::reportStaticMembersMemoryUsage(MemoryInstrumentation* memoryInstrumentation)
+{
+    memoryInstrumentation->addRootObject(gColumnInfoMap, WebCoreMemoryTypes::RenderingStructures);
+    memoryInstrumentation->addRootObject(gPositionedDescendantsMap, WebCoreMemoryTypes::RenderingStructures);
+    memoryInstrumentation->addRootObject(gPercentHeightDescendantsMap, WebCoreMemoryTypes::RenderingStructures);
+    memoryInstrumentation->addRootObject(gPositionedContainerMap, WebCoreMemoryTypes::RenderingStructures);
+    memoryInstrumentation->addRootObject(gPercentHeightContainerMap, WebCoreMemoryTypes::RenderingStructures);
+    memoryInstrumentation->addRootObject(gDelayedUpdateScrollInfoSet, WebCoreMemoryTypes::RenderingStructures);
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderBlock.h b/Source/core/rendering/RenderBlock.h
new file mode 100644
index 0000000..17030db
--- /dev/null
+++ b/Source/core/rendering/RenderBlock.h
@@ -0,0 +1,1314 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2007 David Smith (catfish.man@gmail.com)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 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 "core/platform/PODIntervalTree.h"
+#include "core/platform/graphics/TextRun.h"
+#include "core/platform/text/TextBreakIterator.h"
+#include "core/rendering/ColumnInfo.h"
+#include "core/rendering/exclusions/ExclusionShapeInsideInfo.h"
+#include "core/rendering/GapRects.h"
+#include "core/rendering/RenderBox.h"
+#include "core/rendering/RenderLineBoxList.h"
+#include "core/rendering/RootInlineBox.h"
+#include "core/rendering/style/ExclusionShapeValue.h"
+#include <wtf/ListHashSet.h>
+#include <wtf/OwnPtr.h>
+
+namespace WebCore {
+
+class BasicShape;
+class BidiContext;
+class InlineIterator;
+class LayoutStateMaintainer;
+class LineLayoutState;
+class LineWidth;
+class RenderInline;
+class RenderText;
+
+struct BidiRun;
+struct PaintInfo;
+class LineInfo;
+class RenderRubyRun;
+class TextLayout;
+class WordMeasurement;
+
+template <class Iterator, class Run> class BidiResolver;
+template <class Run> class BidiRunList;
+template <class Iterator> struct MidpointState;
+typedef BidiResolver<InlineIterator, BidiRun> InlineBidiResolver;
+typedef MidpointState<InlineIterator> LineMidpointState;
+typedef WTF::ListHashSet<RenderBox*, 16> TrackedRendererListHashSet;
+typedef WTF::HashMap<const RenderBlock*, OwnPtr<TrackedRendererListHashSet> > TrackedDescendantsMap;
+typedef WTF::HashMap<const RenderBox*, OwnPtr<HashSet<RenderBlock*> > > TrackedContainerMap;
+typedef Vector<WordMeasurement, 64> WordMeasurements;
+
+enum CaretType { CursorCaret, DragCaret };
+enum ContainingBlockState { NewContainingBlock, SameContainingBlock };
+
+enum TextRunFlag {
+    DefaultTextRunFlags = 0,
+    RespectDirection = 1 << 0,
+    RespectDirectionOverride = 1 << 1
+};
+
+typedef unsigned TextRunFlags;
+
+class RenderBlock : public RenderBox {
+public:
+    friend class LineLayoutState;
+#ifndef NDEBUG
+    // Used by the PODIntervalTree for debugging the FloatingObject.
+    template <class> friend struct ValueToString;
+#endif
+
+    explicit RenderBlock(ContainerNode*);
+    virtual ~RenderBlock();
+
+    static RenderBlock* createAnonymous(Document*);
+
+    RenderObject* firstChild() const { ASSERT(children() == virtualChildren()); return children()->firstChild(); }
+    RenderObject* lastChild() const { ASSERT(children() == virtualChildren()); return children()->lastChild(); }
+
+    const RenderObjectChildList* children() const { return &m_children; }
+    RenderObjectChildList* children() { return &m_children; }
+
+    bool beingDestroyed() const { return m_beingDestroyed; }
+
+    // These two functions are overridden for inline-block.
+    virtual LayoutUnit lineHeight(bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const OVERRIDE FINAL;
+    virtual int baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const;
+
+    RenderLineBoxList* lineBoxes() { return &m_lineBoxes; }
+    const RenderLineBoxList* lineBoxes() const { return &m_lineBoxes; }
+
+    InlineFlowBox* firstLineBox() const { return m_lineBoxes.firstLineBox(); }
+    InlineFlowBox* lastLineBox() const { return m_lineBoxes.lastLineBox(); }
+
+    void deleteLineBoxTree();
+
+    virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0);
+    virtual void removeChild(RenderObject*);
+
+    virtual void layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeight = 0);
+
+    void insertPositionedObject(RenderBox*);
+    static void removePositionedObject(RenderBox*);
+    void removePositionedObjects(RenderBlock*, ContainingBlockState = SameContainingBlock);
+
+    void removeFloatingObjects();
+
+    TrackedRendererListHashSet* positionedObjects() const;
+    bool hasPositionedObjects() const
+    {
+        TrackedRendererListHashSet* objects = positionedObjects();
+        return objects && !objects->isEmpty();
+    }
+
+    void addPercentHeightDescendant(RenderBox*);
+    static void removePercentHeightDescendant(RenderBox*);
+    TrackedRendererListHashSet* percentHeightDescendants() const;
+    static bool hasPercentHeightContainerMap();
+    static bool hasPercentHeightDescendant(RenderBox*);
+    static void clearPercentHeightDescendantsFrom(RenderBox*);
+    static void removePercentHeightDescendantIfNeeded(RenderBox*);
+
+    void setHasMarkupTruncation(bool b) { m_hasMarkupTruncation = b; }
+    bool hasMarkupTruncation() const { return m_hasMarkupTruncation; }
+
+    void setHasMarginBeforeQuirk(bool b) { m_hasMarginBeforeQuirk = b; }
+    void setHasMarginAfterQuirk(bool b) { m_hasMarginAfterQuirk = b; }
+
+    bool hasMarginBeforeQuirk() const { return m_hasMarginBeforeQuirk; }
+    bool hasMarginAfterQuirk() const { return m_hasMarginAfterQuirk; }
+
+    bool hasMarginBeforeQuirk(const RenderBox* child) const;
+    bool hasMarginAfterQuirk(const RenderBox* child) const;
+
+    RootInlineBox* createAndAppendRootInlineBox();
+
+    bool generatesLineBoxesForInlineChild(RenderObject*);
+
+    void markAllDescendantsWithFloatsForLayout(RenderBox* floatToRemove = 0, bool inLayout = true);
+    void markSiblingsWithFloatsForLayout(RenderBox* floatToRemove = 0);
+    void markPositionedObjectsForLayout();
+    virtual void markForPaginationRelayoutIfNeeded() OVERRIDE FINAL;
+
+    bool containsFloats() const { return m_floatingObjects && !m_floatingObjects->set().isEmpty(); }
+    bool containsFloat(RenderBox*) const;
+
+    // Versions that can compute line offsets with the region and page offset passed in. Used for speed to avoid having to
+    // compute the region all over again when you already know it.
+    LayoutUnit availableLogicalWidthForLine(LayoutUnit position, bool shouldIndentText, RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage, LayoutUnit logicalHeight = 0) const
+    {
+        return max<LayoutUnit>(0, logicalRightOffsetForLine(position, shouldIndentText, region, offsetFromLogicalTopOfFirstPage, logicalHeight)
+            - logicalLeftOffsetForLine(position, shouldIndentText, region, offsetFromLogicalTopOfFirstPage, logicalHeight));
+    }
+    LayoutUnit logicalRightOffsetForLine(LayoutUnit position, bool shouldIndentText, RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage, LayoutUnit logicalHeight = 0) const
+    {
+        return logicalRightOffsetForLine(position, logicalRightOffsetForContent(region, offsetFromLogicalTopOfFirstPage), shouldIndentText, 0, logicalHeight);
+    }
+    LayoutUnit logicalLeftOffsetForLine(LayoutUnit position, bool shouldIndentText, RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage, LayoutUnit logicalHeight = 0) const
+    {
+        return logicalLeftOffsetForLine(position, logicalLeftOffsetForContent(region, offsetFromLogicalTopOfFirstPage), shouldIndentText, 0, logicalHeight);
+    }
+    LayoutUnit startOffsetForLine(LayoutUnit position, bool shouldIndentText, RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage, LayoutUnit logicalHeight = 0) const
+    {
+        return style()->isLeftToRightDirection() ? logicalLeftOffsetForLine(position, shouldIndentText, region, offsetFromLogicalTopOfFirstPage, logicalHeight)
+            : logicalWidth() - logicalRightOffsetForLine(position, shouldIndentText, region, offsetFromLogicalTopOfFirstPage, logicalHeight);
+    }
+    LayoutUnit endOffsetForLine(LayoutUnit position, bool shouldIndentText, RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage, LayoutUnit logicalHeight = 0) const
+    {
+        return !style()->isLeftToRightDirection() ? logicalLeftOffsetForLine(position, shouldIndentText, region, offsetFromLogicalTopOfFirstPage, logicalHeight)
+            : logicalWidth() - logicalRightOffsetForLine(position, shouldIndentText, region, offsetFromLogicalTopOfFirstPage, logicalHeight);
+    }
+
+    LayoutUnit availableLogicalWidthForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0) const
+    {
+        return availableLogicalWidthForLine(position, shouldIndentText, regionAtBlockOffset(position), offsetFromLogicalTopOfFirstPage(), logicalHeight);
+    }
+    LayoutUnit logicalRightOffsetForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0) const
+    {
+        return logicalRightOffsetForLine(position, logicalRightOffsetForContent(position), shouldIndentText, 0, logicalHeight);
+    }
+    LayoutUnit logicalLeftOffsetForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0) const
+    {
+        return logicalLeftOffsetForLine(position, logicalLeftOffsetForContent(position), shouldIndentText, 0, logicalHeight);
+    }
+    LayoutUnit pixelSnappedLogicalLeftOffsetForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0) const
+    {
+        return roundToInt(logicalLeftOffsetForLine(position, shouldIndentText, logicalHeight));
+    }
+    LayoutUnit pixelSnappedLogicalRightOffsetForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0) const
+    {
+        // FIXME: Multicolumn layouts break carrying over subpixel values to the logical right offset because the lines may be shifted
+        // by a subpixel value for all but the first column. This can lead to the actual pixel snapped width of the column being off
+        // by one pixel when rendered versus layed out, which can result in the line being clipped. For now, we have to floor.
+        // https://bugs.webkit.org/show_bug.cgi?id=105461
+        return floorToInt(logicalRightOffsetForLine(position, shouldIndentText, logicalHeight));
+    }
+    LayoutUnit startOffsetForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0) const
+    {
+        return style()->isLeftToRightDirection() ? logicalLeftOffsetForLine(position, shouldIndentText, logicalHeight)
+            : logicalWidth() - logicalRightOffsetForLine(position, shouldIndentText, logicalHeight);
+    }
+    LayoutUnit endOffsetForLine(LayoutUnit position, bool shouldIndentText, LayoutUnit logicalHeight = 0) const
+    {
+        return !style()->isLeftToRightDirection() ? logicalLeftOffsetForLine(position, shouldIndentText, logicalHeight)
+            : logicalWidth() - logicalRightOffsetForLine(position, shouldIndentText, logicalHeight);
+    }
+
+    LayoutUnit startAlignedOffsetForLine(LayoutUnit position, bool shouldIndentText);
+    LayoutUnit textIndentOffset() const;
+
+    virtual VisiblePosition positionForPoint(const LayoutPoint&);
+    
+    // Block flows subclass availableWidth to handle multi column layout (shrinking the width available to children when laying out.)
+    virtual LayoutUnit availableLogicalWidth() const OVERRIDE FINAL;
+
+    LayoutPoint flipForWritingModeIncludingColumns(const LayoutPoint&) const;
+    void adjustStartEdgeForWritingModeIncludingColumns(LayoutRect&) const;
+
+    RootInlineBox* firstRootBox() const { return static_cast<RootInlineBox*>(firstLineBox()); }
+    RootInlineBox* lastRootBox() const { return static_cast<RootInlineBox*>(lastLineBox()); }
+
+    bool containsNonZeroBidiLevel() const;
+
+    GapRects selectionGapRectsForRepaint(const RenderLayerModelObject* repaintContainer);
+    LayoutRect logicalLeftSelectionGap(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
+                                       RenderObject* selObj, LayoutUnit logicalLeft, LayoutUnit logicalTop, LayoutUnit logicalHeight, const PaintInfo*);
+    LayoutRect logicalRightSelectionGap(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
+                                        RenderObject* selObj, LayoutUnit logicalRight, LayoutUnit logicalTop, LayoutUnit logicalHeight, const PaintInfo*);
+    void getSelectionGapInfo(SelectionState, bool& leftGap, bool& rightGap);
+    RenderBlock* blockBeforeWithinSelectionRoot(LayoutSize& offset) const;
+
+    LayoutRect logicalRectToPhysicalRect(const LayoutPoint& physicalPosition, const LayoutRect& logicalRect);
+
+    // Helper methods for computing line counts and heights for line counts.
+    RootInlineBox* lineAtIndex(int) const;
+    int lineCount(const RootInlineBox* = 0, bool* = 0) const;
+    int heightForLineCount(int);
+    void clearTruncation();
+
+    void adjustRectForColumns(LayoutRect&) const;
+    virtual void adjustForColumns(LayoutSize&, const LayoutPoint&) const OVERRIDE FINAL;
+    void adjustForColumnRect(LayoutSize& offset, const LayoutPoint& locationInContainer) const;
+
+    void addContinuationWithOutline(RenderInline*);
+    bool paintsContinuationOutline(RenderInline*);
+
+    virtual RenderBoxModelObject* virtualContinuation() const OVERRIDE FINAL { return continuation(); }
+    bool isAnonymousBlockContinuation() const { return continuation() && isAnonymousBlock(); }
+    RenderInline* inlineElementContinuation() const;
+    RenderBlock* blockElementContinuation() const;
+
+    using RenderBoxModelObject::continuation;
+    using RenderBoxModelObject::setContinuation;
+
+    static RenderBlock* createAnonymousWithParentRendererAndDisplay(const RenderObject*, EDisplay = BLOCK);
+    static RenderBlock* createAnonymousColumnsWithParentRenderer(const RenderObject*);
+    static RenderBlock* createAnonymousColumnSpanWithParentRenderer(const RenderObject*);
+    RenderBlock* createAnonymousBlock(EDisplay display = BLOCK) const { return createAnonymousWithParentRendererAndDisplay(this, display); }
+    RenderBlock* createAnonymousColumnsBlock() const { return createAnonymousColumnsWithParentRenderer(this); }
+    RenderBlock* createAnonymousColumnSpanBlock() const { return createAnonymousColumnSpanWithParentRenderer(this); }
+
+    virtual RenderBox* createAnonymousBoxWithSameTypeAs(const RenderObject* parent) const OVERRIDE;
+
+    static bool shouldSkipCreatingRunsForObject(RenderObject* obj)
+    {
+        return obj->isFloating() || (obj->isOutOfFlowPositioned() && !obj->style()->isOriginalDisplayInlineType() && !obj->container()->isRenderInline());
+    }
+    
+    static void appendRunsForObject(BidiRunList<BidiRun>&, int start, int end, RenderObject*, InlineBidiResolver&);
+
+    static TextRun constructTextRun(RenderObject* context, const Font& font, const String& string, RenderStyle* style,
+        TextRun::ExpansionBehavior = TextRun::AllowTrailingExpansion | TextRun::ForbidLeadingExpansion, TextRunFlags = DefaultTextRunFlags);
+
+    static TextRun constructTextRun(RenderObject* context, const Font& font, const RenderText* text, RenderStyle* style,
+        TextRun::ExpansionBehavior = TextRun::AllowTrailingExpansion | TextRun::ForbidLeadingExpansion);
+
+    static TextRun constructTextRun(RenderObject* context, const Font& font, const RenderText* text, unsigned offset, unsigned length, RenderStyle* style,
+        TextRun::ExpansionBehavior = TextRun::AllowTrailingExpansion | TextRun::ForbidLeadingExpansion);
+
+    static TextRun constructTextRun(RenderObject* context, const Font& font, const RenderText* text, unsigned offset, RenderStyle* style,
+        TextRun::ExpansionBehavior = TextRun::AllowTrailingExpansion | TextRun::ForbidLeadingExpansion);
+
+#if ENABLE(8BIT_TEXTRUN)
+    static TextRun constructTextRun(RenderObject* context, const Font& font, const LChar* characters, int length, RenderStyle* style,
+        TextRun::ExpansionBehavior = TextRun::AllowTrailingExpansion | TextRun::ForbidLeadingExpansion);
+#endif
+
+    static TextRun constructTextRun(RenderObject* context, const Font& font, const UChar* characters, int length, RenderStyle* style,
+        TextRun::ExpansionBehavior = TextRun::AllowTrailingExpansion | TextRun::ForbidLeadingExpansion);
+
+    ColumnInfo* columnInfo() const;
+    int columnGap() const;
+
+    void updateColumnInfoFromStyle(RenderStyle*);
+    
+    // These two functions take the ColumnInfo* to avoid repeated lookups of the info in the global HashMap.
+    unsigned columnCount(ColumnInfo*) const;
+    LayoutRect columnRectAt(ColumnInfo*, unsigned) const;
+
+    LayoutUnit paginationStrut() const { return m_rareData ? m_rareData->m_paginationStrut : LayoutUnit(); }
+    void setPaginationStrut(LayoutUnit);
+
+    bool shouldBreakAtLineToAvoidWidow() const { return m_rareData && m_rareData->m_shouldBreakAtLineToAvoidWidow; }
+    void clearShouldBreakAtLineToAvoidWidow() const;
+    RootInlineBox* lineBreakToAvoidWidow() const { return m_rareData ? m_rareData->m_lineBreakToAvoidWidow : 0; }
+    void setBreakAtLineToAvoidWidow(RootInlineBox*);
+
+    // The page logical offset is the object's offset from the top of the page in the page progression
+    // direction (so an x-offset in vertical text and a y-offset for horizontal text).
+    LayoutUnit pageLogicalOffset() const { return m_rareData ? m_rareData->m_pageLogicalOffset : LayoutUnit(); }
+    void setPageLogicalOffset(LayoutUnit);
+
+    RootInlineBox* lineGridBox() const { return m_rareData ? m_rareData->m_lineGridBox : 0; }
+    void setLineGridBox(RootInlineBox* box)
+    {
+        if (!m_rareData)
+            m_rareData = adoptPtr(new RenderBlockRareData(this));
+        if (m_rareData->m_lineGridBox)
+            m_rareData->m_lineGridBox->destroy(renderArena());
+        m_rareData->m_lineGridBox = box;
+    }
+    void layoutLineGridBox();
+
+    // Accessors for logical width/height and margins in the containing block's block-flow direction.
+    enum ApplyLayoutDeltaMode { ApplyLayoutDelta, DoNotApplyLayoutDelta };
+    LayoutUnit logicalWidthForChild(const RenderBox* child) { return isHorizontalWritingMode() ? child->width() : child->height(); }
+    LayoutUnit logicalHeightForChild(const RenderBox* child) { return isHorizontalWritingMode() ? child->height() : child->width(); }
+    LayoutUnit logicalTopForChild(const RenderBox* child) { return isHorizontalWritingMode() ? child->y() : child->x(); }
+    void setLogicalLeftForChild(RenderBox* child, LayoutUnit logicalLeft, ApplyLayoutDeltaMode = DoNotApplyLayoutDelta);
+    void setLogicalTopForChild(RenderBox* child, LayoutUnit logicalTop, ApplyLayoutDeltaMode = DoNotApplyLayoutDelta);
+    LayoutUnit marginBeforeForChild(const RenderBoxModelObject* child) const { return child->marginBefore(style()); }
+    LayoutUnit marginAfterForChild(const RenderBoxModelObject* child) const { return child->marginAfter(style()); }
+    LayoutUnit marginStartForChild(const RenderBoxModelObject* child) const { return child->marginStart(style()); }
+    LayoutUnit marginEndForChild(const RenderBoxModelObject* child) const { return child->marginEnd(style()); }
+    void setMarginStartForChild(RenderBox* child, LayoutUnit value) const { child->setMarginStart(value, style()); }
+    void setMarginEndForChild(RenderBox* child, LayoutUnit value) const { child->setMarginEnd(value, style()); }
+    void setMarginBeforeForChild(RenderBox* child, LayoutUnit value) const { child->setMarginBefore(value, style()); }
+    void setMarginAfterForChild(RenderBox* child, LayoutUnit value) const { child->setMarginAfter(value, style()); }
+    LayoutUnit collapsedMarginBeforeForChild(const RenderBox* child) const;
+    LayoutUnit collapsedMarginAfterForChild(const RenderBox* child) const;
+
+    void updateLogicalWidthForAlignment(const ETextAlign&, BidiRun* trailingSpaceRun, float& logicalLeft, float& totalLogicalWidth, float& availableLogicalWidth, int expansionOpportunityCount);
+
+    virtual void updateFirstLetter();
+
+    class MarginValues {
+    public:
+        MarginValues(LayoutUnit beforePos, LayoutUnit beforeNeg, LayoutUnit afterPos, LayoutUnit afterNeg)
+            : m_positiveMarginBefore(beforePos)
+            , m_negativeMarginBefore(beforeNeg)
+            , m_positiveMarginAfter(afterPos)
+            , m_negativeMarginAfter(afterNeg)
+        { }
+        
+        LayoutUnit positiveMarginBefore() const { return m_positiveMarginBefore; }
+        LayoutUnit negativeMarginBefore() const { return m_negativeMarginBefore; }
+        LayoutUnit positiveMarginAfter() const { return m_positiveMarginAfter; }
+        LayoutUnit negativeMarginAfter() const { return m_negativeMarginAfter; }
+        
+        void setPositiveMarginBefore(LayoutUnit pos) { m_positiveMarginBefore = pos; }
+        void setNegativeMarginBefore(LayoutUnit neg) { m_negativeMarginBefore = neg; }
+        void setPositiveMarginAfter(LayoutUnit pos) { m_positiveMarginAfter = pos; }
+        void setNegativeMarginAfter(LayoutUnit neg) { m_negativeMarginAfter = neg; }
+    
+    private:
+        LayoutUnit m_positiveMarginBefore;
+        LayoutUnit m_negativeMarginBefore;
+        LayoutUnit m_positiveMarginAfter;
+        LayoutUnit m_negativeMarginAfter;
+    };
+    MarginValues marginValuesForChild(RenderBox* child) const;
+
+    virtual void scrollbarsChanged(bool /*horizontalScrollbarChanged*/, bool /*verticalScrollbarChanged*/) { };
+
+    LayoutUnit logicalLeftOffsetForContent(RenderRegion*, LayoutUnit offsetFromLogicalTopOfFirstPage) const;
+    LayoutUnit logicalRightOffsetForContent(RenderRegion*, LayoutUnit offsetFromLogicalTopOfFirstPage) const;
+    LayoutUnit availableLogicalWidthForContent(RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage) const
+    { 
+        return max<LayoutUnit>(0, logicalRightOffsetForContent(region, offsetFromLogicalTopOfFirstPage) -
+            logicalLeftOffsetForContent(region, offsetFromLogicalTopOfFirstPage)); }
+    LayoutUnit startOffsetForContent(RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage) const
+    {
+        return style()->isLeftToRightDirection() ? logicalLeftOffsetForContent(region, offsetFromLogicalTopOfFirstPage)
+            : logicalWidth() - logicalRightOffsetForContent(region, offsetFromLogicalTopOfFirstPage);
+    }
+    LayoutUnit endOffsetForContent(RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage) const
+    {
+        return !style()->isLeftToRightDirection() ? logicalLeftOffsetForContent(region, offsetFromLogicalTopOfFirstPage)
+            : logicalWidth() - logicalRightOffsetForContent(region, offsetFromLogicalTopOfFirstPage);
+    }
+    LayoutUnit logicalLeftOffsetForContent(LayoutUnit blockOffset) const
+    {
+        return logicalLeftOffsetForContent(regionAtBlockOffset(blockOffset), offsetFromLogicalTopOfFirstPage());
+    }
+    LayoutUnit logicalRightOffsetForContent(LayoutUnit blockOffset) const
+    {
+        return logicalRightOffsetForContent(regionAtBlockOffset(blockOffset), offsetFromLogicalTopOfFirstPage());
+    }
+    LayoutUnit availableLogicalWidthForContent(LayoutUnit blockOffset) const
+    {
+        return availableLogicalWidthForContent(regionAtBlockOffset(blockOffset), offsetFromLogicalTopOfFirstPage());
+    }
+    LayoutUnit startOffsetForContent(LayoutUnit blockOffset) const
+    {
+        return startOffsetForContent(regionAtBlockOffset(blockOffset), offsetFromLogicalTopOfFirstPage());
+    }
+    LayoutUnit endOffsetForContent(LayoutUnit blockOffset) const
+    {
+        return endOffsetForContent(regionAtBlockOffset(blockOffset), offsetFromLogicalTopOfFirstPage());
+    }
+    LayoutUnit logicalLeftOffsetForContent() const { return isHorizontalWritingMode() ? borderLeft() + paddingLeft() : borderTop() + paddingTop(); }
+    LayoutUnit logicalRightOffsetForContent() const { return logicalLeftOffsetForContent() + availableLogicalWidth(); }
+    LayoutUnit startOffsetForContent() const { return style()->isLeftToRightDirection() ? logicalLeftOffsetForContent() : logicalWidth() - logicalRightOffsetForContent(); }
+    LayoutUnit endOffsetForContent() const { return !style()->isLeftToRightDirection() ? logicalLeftOffsetForContent() : logicalWidth() - logicalRightOffsetForContent(); }
+    
+    void setStaticInlinePositionForChild(RenderBox*, LayoutUnit blockOffset, LayoutUnit inlinePosition);
+    void updateStaticInlinePositionForChild(RenderBox*, LayoutUnit logicalTop);
+
+    LayoutUnit computeStartPositionDeltaForChildAvoidingFloats(const RenderBox* child, LayoutUnit childMarginStart, RenderRegion* = 0, LayoutUnit offsetFromLogicalTopOfFirstPage = 0);
+
+    void placeRunInIfNeeded(RenderObject* newChild);
+    bool runInIsPlacedIntoSiblingBlock(RenderObject* runIn);
+
+#ifndef NDEBUG
+    void checkPositionedObjectsNeedLayout();
+    void showLineTreeAndMark(const InlineBox* = 0, const char* = 0, const InlineBox* = 0, const char* = 0, const RenderObject* = 0) const;
+#endif
+
+    ExclusionShapeInsideInfo* ensureExclusionShapeInsideInfo()
+    {
+        if (!m_rareData || !m_rareData->m_shapeInsideInfo)
+            setExclusionShapeInsideInfo(ExclusionShapeInsideInfo::createInfo(this));
+        return m_rareData->m_shapeInsideInfo.get();
+    }
+    ExclusionShapeInsideInfo* exclusionShapeInsideInfo() const
+    {
+        return m_rareData && m_rareData->m_shapeInsideInfo && ExclusionShapeInsideInfo::isEnabledFor(this) ? m_rareData->m_shapeInsideInfo.get() : 0;
+    }
+    void setExclusionShapeInsideInfo(PassOwnPtr<ExclusionShapeInsideInfo> value)
+    {
+        if (!m_rareData)
+            m_rareData = adoptPtr(new RenderBlockRareData(this));
+        m_rareData->m_shapeInsideInfo = value;
+    }
+    ExclusionShapeInsideInfo* layoutExclusionShapeInsideInfo() const;
+    bool allowsExclusionShapeInsideInfoSharing() const { return !isInline() && !isFloating(); }
+
+    virtual void reportMemoryUsage(MemoryObjectInfo*) const OVERRIDE;
+    static void reportStaticMembersMemoryUsage(MemoryInstrumentation*);
+
+protected:
+    virtual void willBeDestroyed();
+
+    LayoutUnit maxPositiveMarginBefore() const { return m_rareData ? m_rareData->m_margins.positiveMarginBefore() : RenderBlockRareData::positiveMarginBeforeDefault(this); }
+    LayoutUnit maxNegativeMarginBefore() const { return m_rareData ? m_rareData->m_margins.negativeMarginBefore() : RenderBlockRareData::negativeMarginBeforeDefault(this); }
+    LayoutUnit maxPositiveMarginAfter() const { return m_rareData ? m_rareData->m_margins.positiveMarginAfter() : RenderBlockRareData::positiveMarginAfterDefault(this); }
+    LayoutUnit maxNegativeMarginAfter() const { return m_rareData ? m_rareData->m_margins.negativeMarginAfter() : RenderBlockRareData::negativeMarginAfterDefault(this); }
+    
+    void setMaxMarginBeforeValues(LayoutUnit pos, LayoutUnit neg);
+    void setMaxMarginAfterValues(LayoutUnit pos, LayoutUnit neg);
+
+    void setMustDiscardMarginBefore(bool = true);
+    void setMustDiscardMarginAfter(bool = true);
+
+    bool mustDiscardMarginBefore() const;
+    bool mustDiscardMarginAfter() const;
+
+    bool mustDiscardMarginBeforeForChild(const RenderBox*) const;
+    bool mustDiscardMarginAfterForChild(const RenderBox*) const;
+
+    bool mustSeparateMarginBeforeForChild(const RenderBox*) const;
+    bool mustSeparateMarginAfterForChild(const RenderBox*) const;
+
+    void initMaxMarginValues()
+    {
+        if (m_rareData) {
+            m_rareData->m_margins = MarginValues(RenderBlockRareData::positiveMarginBeforeDefault(this) , RenderBlockRareData::negativeMarginBeforeDefault(this),
+                                                 RenderBlockRareData::positiveMarginAfterDefault(this), RenderBlockRareData::negativeMarginAfterDefault(this));
+            m_rareData->m_paginationStrut = 0;
+
+            m_rareData->m_discardMarginBefore = false;
+            m_rareData->m_discardMarginAfter = false;
+        }
+    }
+
+    virtual void layout();
+
+    void layoutPositionedObjects(bool relayoutChildren, bool fixedPositionObjectsOnly = false);
+    void markFixedPositionObjectForLayoutIfNeeded(RenderObject* child);
+
+    virtual void paint(PaintInfo&, const LayoutPoint&);
+    virtual void paintObject(PaintInfo&, const LayoutPoint&);
+    virtual void paintChildren(PaintInfo& forSelf, const LayoutPoint&, PaintInfo& forChild, bool usePrintRect);
+    bool paintChild(RenderBox*, PaintInfo& forSelf, const LayoutPoint&, PaintInfo& forChild, bool usePrintRect);
+   
+    LayoutUnit logicalRightOffsetForLine(LayoutUnit position, LayoutUnit fixedOffset, bool applyTextIndent, LayoutUnit* logicalHeightRemaining = 0, LayoutUnit logicalHeight = 0) const;
+    LayoutUnit logicalLeftOffsetForLine(LayoutUnit position, LayoutUnit fixedOffset, bool applyTextIndent, LayoutUnit* logicalHeightRemaining = 0, LayoutUnit logicalHeight = 0) const;
+
+    virtual ETextAlign textAlignmentForLine(bool endsWithSoftBreak) const;
+    virtual void adjustInlineDirectionLineBounds(int /* expansionOpportunityCount */, float& /* logicalLeft */, float& /* logicalWidth */) const { }
+
+    virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
+
+    virtual void computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const OVERRIDE;
+    virtual void computePreferredLogicalWidths() OVERRIDE;
+
+    virtual int firstLineBoxBaseline() const;
+    virtual int inlineBlockBaseline(LineDirectionMode) const OVERRIDE;
+    int lastLineBoxBaseline(LineDirectionMode) const;
+
+    virtual void updateHitTestResult(HitTestResult&, const LayoutPoint&);
+
+    // Delay update scrollbar until finishDelayRepaint() will be
+    // called. This function is used when a flexbox is laying out its
+    // descendant. If multiple calls are made to startDelayRepaint(),
+    // finishDelayRepaint() will do nothing until finishDelayRepaint()
+    // is called the same number of times.
+    static void startDelayUpdateScrollInfo();
+    static void finishDelayUpdateScrollInfo();
+
+    void updateScrollInfoAfterLayout();
+
+    virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle);
+    virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+
+    virtual bool hasLineIfEmpty() const;
+    
+    bool simplifiedLayout();
+    virtual void simplifiedNormalFlowLayout();
+
+    void setDesiredColumnCountAndWidth(int, LayoutUnit);
+
+public:
+    void computeOverflow(LayoutUnit oldClientAfterEdge, bool recomputeFloats = false);
+protected:
+    virtual void addOverflowFromChildren();
+    void addOverflowFromFloats();
+    void addOverflowFromPositionedObjects();
+    void addOverflowFromBlockChildren();
+    void addOverflowFromInlineChildren();
+    void addVisualOverflowFromTheme();
+
+    virtual void addFocusRingRects(Vector<IntRect>&, const LayoutPoint& additionalOffset, const RenderLayerModelObject* paintContainer = 0) OVERRIDE;
+
+#if ENABLE(SVG)
+    // Only used by RenderSVGText, which explicitely overrides RenderBlock::layoutBlock(), do NOT use for anything else.
+    void forceLayoutInlineChildren()
+    {
+        LayoutUnit repaintLogicalTop = 0;
+        LayoutUnit repaintLogicalBottom = 0;
+        clearFloats();
+        layoutInlineChildren(true, repaintLogicalTop, repaintLogicalBottom);
+    }
+#endif
+
+    bool updateRegionsAndExclusionsLogicalSize(RenderFlowThread*);
+    void computeRegionRangeForBlock(RenderFlowThread*);
+
+    void updateBlockChildDirtyBitsBeforeLayout(bool relayoutChildren, RenderBox*);
+
+    virtual void checkForPaginationLogicalHeightChange(LayoutUnit& pageLogicalHeight, bool& pageLogicalHeightChanged, bool& hasSpecifiedPageLogicalHeight);
+
+private:
+    void computeExclusionShapeSize();
+    void updateExclusionShapeInsideInfoAfterStyleChange(const ExclusionShapeValue*, const ExclusionShapeValue* oldExclusionShape);
+
+    virtual RenderObjectChildList* virtualChildren() OVERRIDE FINAL { return children(); }
+    virtual const RenderObjectChildList* virtualChildren() const OVERRIDE FINAL { return children(); }
+
+    virtual const char* renderName() const;
+
+    virtual bool isRenderBlock() const OVERRIDE FINAL { return true; }
+    virtual bool isBlockFlow() const OVERRIDE FINAL { return (!isInline() || isReplaced()) && !isTable(); }
+    virtual bool isInlineBlockOrInlineTable() const OVERRIDE FINAL { return isInline() && isReplaced(); }
+
+    void makeChildrenNonInline(RenderObject* insertionPoint = 0);
+    virtual void removeLeftoverAnonymousBlock(RenderBlock* child);
+
+    static void collapseAnonymousBoxChild(RenderBlock* parent, RenderObject* child);
+
+    virtual void dirtyLinesFromChangedChild(RenderObject* child) OVERRIDE FINAL { m_lineBoxes.dirtyLinesFromChangedChild(this, child); }
+
+    void addChildToContinuation(RenderObject* newChild, RenderObject* beforeChild);
+    void addChildIgnoringContinuation(RenderObject* newChild, RenderObject* beforeChild);
+    void addChildToAnonymousColumnBlocks(RenderObject* newChild, RenderObject* beforeChild);
+
+    void addChildIgnoringAnonymousColumnBlocks(RenderObject* newChild, RenderObject* beforeChild = 0);
+    
+    virtual bool isSelfCollapsingBlock() const OVERRIDE FINAL;
+
+    virtual LayoutUnit collapsedMarginBefore() const OVERRIDE FINAL { return maxPositiveMarginBefore() - maxNegativeMarginBefore(); }
+    virtual LayoutUnit collapsedMarginAfter() const OVERRIDE FINAL { return maxPositiveMarginAfter() - maxNegativeMarginAfter(); }
+
+    virtual void repaintOverhangingFloats(bool paintAllDescendants) OVERRIDE FINAL;
+
+    void layoutBlockChildren(bool relayoutChildren, LayoutUnit& maxFloatLogicalBottom);
+    void layoutInlineChildren(bool relayoutChildren, LayoutUnit& repaintLogicalTop, LayoutUnit& repaintLogicalBottom);
+    BidiRun* handleTrailingSpaces(BidiRunList<BidiRun>&, BidiContext*);
+
+    void insertIntoTrackedRendererMaps(RenderBox* descendant, TrackedDescendantsMap*&, TrackedContainerMap*&);
+    static void removeFromTrackedRendererMaps(RenderBox* descendant, TrackedDescendantsMap*&, TrackedContainerMap*&);
+
+    virtual RootInlineBox* createRootInlineBox(); // Subclassed by SVG and Ruby.
+
+    // Called to lay out the legend for a fieldset or the ruby text of a ruby run.
+    virtual RenderObject* layoutSpecialExcludedChild(bool /*relayoutChildren*/) { return 0; }
+
+    void createFirstLetterRenderer(RenderObject* firstLetterBlock, RenderObject* currentChild);
+    void updateFirstLetterStyle(RenderObject* firstLetterBlock, RenderObject* firstLetterContainer);
+
+    Node* nodeForHitTest() const;
+
+    struct FloatWithRect {
+        FloatWithRect(RenderBox* f)
+            : object(f)
+            , rect(LayoutRect(f->x() - f->marginLeft(), f->y() - f->marginTop(), f->width() + f->marginWidth(), f->height() + f->marginHeight()))
+            , everHadLayout(f->everHadLayout())
+        {
+        }
+
+        RenderBox* object;
+        LayoutRect rect;
+        bool everHadLayout;
+    };
+
+    struct FloatingObject {
+        WTF_MAKE_NONCOPYABLE(FloatingObject); WTF_MAKE_FAST_ALLOCATED;
+    public:
+        // Note that Type uses bits so you can use FloatLeftRight as a mask to query for both left and right.
+        enum Type { FloatLeft = 1, FloatRight = 2, FloatLeftRight = 3 };
+
+        FloatingObject(EFloat type)
+            : m_renderer(0)
+            , m_originatingLine(0)
+            , m_paginationStrut(0)
+            , m_shouldPaint(true)
+            , m_isDescendant(false)
+            , m_isPlaced(false)
+#ifndef NDEBUG
+            , m_isInPlacedTree(false)
+#endif
+        {
+            ASSERT(type != NoFloat);
+            if (type == LeftFloat)
+                m_type = FloatLeft;
+            else if (type == RightFloat)
+                m_type = FloatRight;  
+        }
+
+        FloatingObject(Type type, const LayoutRect& frameRect)
+            : m_renderer(0)
+            , m_originatingLine(0)
+            , m_frameRect(frameRect)
+            , m_paginationStrut(0)
+            , m_type(type)
+            , m_shouldPaint(true)
+            , m_isDescendant(false)
+            , m_isPlaced(true)
+#ifndef NDEBUG
+            , m_isInPlacedTree(false)
+#endif
+        {
+        }
+
+        Type type() const { return static_cast<Type>(m_type); }
+        RenderBox* renderer() const { return m_renderer; }
+        
+        bool isPlaced() const { return m_isPlaced; }
+        void setIsPlaced(bool placed = true) { m_isPlaced = placed; }
+
+        inline LayoutUnit x() const { ASSERT(isPlaced()); return m_frameRect.x(); }
+        inline LayoutUnit maxX() const { ASSERT(isPlaced()); return m_frameRect.maxX(); }
+        inline LayoutUnit y() const { ASSERT(isPlaced()); return m_frameRect.y(); }
+        inline LayoutUnit maxY() const { ASSERT(isPlaced()); return m_frameRect.maxY(); }
+        inline LayoutUnit width() const { return m_frameRect.width(); }
+        inline LayoutUnit height() const { return m_frameRect.height(); }
+
+        void setX(LayoutUnit x) { ASSERT(!isInPlacedTree()); m_frameRect.setX(x); }
+        void setY(LayoutUnit y) { ASSERT(!isInPlacedTree()); m_frameRect.setY(y); }
+        void setWidth(LayoutUnit width) { ASSERT(!isInPlacedTree()); m_frameRect.setWidth(width); }
+        void setHeight(LayoutUnit height) { ASSERT(!isInPlacedTree()); m_frameRect.setHeight(height); }
+
+        const LayoutRect& frameRect() const { ASSERT(isPlaced()); return m_frameRect; }
+        void setFrameRect(const LayoutRect& frameRect) { ASSERT(!isInPlacedTree()); m_frameRect = frameRect; }
+
+#ifndef NDEBUG
+        bool isInPlacedTree() const { return m_isInPlacedTree; }
+        void setIsInPlacedTree(bool value) { m_isInPlacedTree = value; }
+#endif
+
+        bool shouldPaint() const { return m_shouldPaint; }
+        void setShouldPaint(bool shouldPaint) { m_shouldPaint = shouldPaint; }
+        bool isDescendant() const { return m_isDescendant; }
+        void setIsDescendant(bool isDescendant) { m_isDescendant = isDescendant; }
+
+        RenderBox* m_renderer;
+        RootInlineBox* m_originatingLine;
+        LayoutRect m_frameRect;
+        int m_paginationStrut;
+
+    private:
+        unsigned m_type : 2; // Type (left or right aligned)
+        unsigned m_shouldPaint : 1;
+        unsigned m_isDescendant : 1;
+        unsigned m_isPlaced : 1;
+#ifndef NDEBUG
+        unsigned m_isInPlacedTree : 1;
+#endif
+    };
+
+    LayoutPoint flipFloatForWritingModeForChild(const FloatingObject*, const LayoutPoint&) const;
+
+    LayoutUnit logicalTopForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->y() : child->x(); }
+    LayoutUnit logicalBottomForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->maxY() : child->maxX(); }
+    LayoutUnit logicalLeftForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->x() : child->y(); }
+    LayoutUnit logicalRightForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->maxX() : child->maxY(); }
+    LayoutUnit logicalWidthForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->width() : child->height(); }
+
+    int pixelSnappedLogicalTopForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->frameRect().pixelSnappedY() : child->frameRect().pixelSnappedX(); }
+    int pixelSnappedLogicalBottomForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->frameRect().pixelSnappedMaxY() : child->frameRect().pixelSnappedMaxX(); }
+    int pixelSnappedLogicalLeftForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->frameRect().pixelSnappedX() : child->frameRect().pixelSnappedY(); }
+    int pixelSnappedLogicalRightForFloat(const FloatingObject* child) const { return isHorizontalWritingMode() ? child->frameRect().pixelSnappedMaxX() : child->frameRect().pixelSnappedMaxY(); }
+
+    void setLogicalTopForFloat(FloatingObject* child, LayoutUnit logicalTop)
+    {
+        if (isHorizontalWritingMode())
+            child->setY(logicalTop);
+        else
+            child->setX(logicalTop);
+    }
+    void setLogicalLeftForFloat(FloatingObject* child, LayoutUnit logicalLeft)
+    {
+        if (isHorizontalWritingMode())
+            child->setX(logicalLeft);
+        else
+            child->setY(logicalLeft);
+    }
+    void setLogicalHeightForFloat(FloatingObject* child, LayoutUnit logicalHeight)
+    {
+        if (isHorizontalWritingMode())
+            child->setHeight(logicalHeight);
+        else
+            child->setWidth(logicalHeight);
+    }
+    void setLogicalWidthForFloat(FloatingObject* child, LayoutUnit logicalWidth)
+    {
+        if (isHorizontalWritingMode())
+            child->setWidth(logicalWidth);
+        else
+            child->setHeight(logicalWidth);
+    }
+
+    LayoutUnit xPositionForFloatIncludingMargin(const FloatingObject* child) const
+    {
+        ExclusionShapeOutsideInfo *shapeOutside = child->renderer()->exclusionShapeOutsideInfo();
+        if (shapeOutside)
+            return child->x();
+
+        if (isHorizontalWritingMode())
+            return child->x() + child->renderer()->marginLeft();
+        else
+            return child->x() + marginBeforeForChild(child->renderer());
+    }
+        
+    LayoutUnit yPositionForFloatIncludingMargin(const FloatingObject* child) const
+    {
+        ExclusionShapeOutsideInfo *shapeOutside = child->renderer()->exclusionShapeOutsideInfo();
+        if (shapeOutside)
+            return child->y();
+
+        if (isHorizontalWritingMode())
+            return child->y() + marginBeforeForChild(child->renderer());
+        else
+            return child->y() + child->renderer()->marginTop();
+    }
+
+    LayoutPoint computeLogicalLocationForFloat(const FloatingObject*, LayoutUnit logicalTopOffset) const;
+
+    // The following functions' implementations are in RenderBlockLineLayout.cpp.
+    struct RenderTextInfo {
+        // Destruction of m_layout requires TextLayout to be a complete type, so the constructor and destructor are made non-inline to avoid compilation errors.
+        RenderTextInfo();
+        ~RenderTextInfo();
+
+        RenderText* m_text;
+        OwnPtr<TextLayout> m_layout;
+        LazyLineBreakIterator m_lineBreakIterator;
+        const Font* m_font;
+    };
+
+    class LineBreaker {
+    public:
+        LineBreaker(RenderBlock* block)
+            : m_block(block)
+        {
+            reset();
+        }
+
+        InlineIterator nextLineBreak(InlineBidiResolver&, LineInfo&, RenderTextInfo&, FloatingObject* lastFloatFromPreviousLine, unsigned consecutiveHyphenatedLines, WordMeasurements&);
+
+        bool lineWasHyphenated() { return m_hyphenated; }
+        const Vector<RenderBox*>& positionedObjects() { return m_positionedObjects; }
+        EClear clear() { return m_clear; }
+    private:
+        void reset();
+        
+        InlineIterator nextSegmentBreak(InlineBidiResolver&, LineInfo&, RenderTextInfo&, FloatingObject* lastFloatFromPreviousLine, unsigned consecutiveHyphenatedLines, WordMeasurements&);
+        void skipTrailingWhitespace(InlineIterator&, const LineInfo&);
+        void skipLeadingWhitespace(InlineBidiResolver&, LineInfo&, FloatingObject* lastFloatFromPreviousLine, LineWidth&);
+        
+        RenderBlock* m_block;
+        bool m_hyphenated;
+        EClear m_clear;
+        Vector<RenderBox*> m_positionedObjects;
+    };
+
+    void checkFloatsInCleanLine(RootInlineBox*, Vector<FloatWithRect>&, size_t& floatIndex, bool& encounteredNewFloat, bool& dirtiedByFloat);
+    RootInlineBox* determineStartPosition(LineLayoutState&, InlineBidiResolver&);
+    void determineEndPosition(LineLayoutState&, RootInlineBox* startBox, InlineIterator& cleanLineStart, BidiStatus& cleanLineBidiStatus);
+    bool matchedEndLine(LineLayoutState&, const InlineBidiResolver&, const InlineIterator& endLineStart, const BidiStatus& endLineStatus);
+    bool checkPaginationAndFloatsAtEndLine(LineLayoutState&);
+    
+    RootInlineBox* constructLine(BidiRunList<BidiRun>&, const LineInfo&);
+    InlineFlowBox* createLineBoxes(RenderObject*, const LineInfo&, InlineBox* childBox, bool startsNewSegment);
+
+    void setMarginsForRubyRun(BidiRun*, RenderRubyRun*, RenderObject*, const LineInfo&);
+
+    BidiRun* computeInlineDirectionPositionsForSegment(RootInlineBox*, const LineInfo&, ETextAlign, float& logicalLeft,
+        float& availableLogicalWidth, BidiRun* firstRun, BidiRun* trailingSpaceRun, GlyphOverflowAndFallbackFontsMap& textBoxDataMap, VerticalPositionCache&, WordMeasurements&);
+    void computeInlineDirectionPositionsForLine(RootInlineBox*, const LineInfo&, BidiRun* firstRun, BidiRun* trailingSpaceRun, bool reachedEnd, GlyphOverflowAndFallbackFontsMap&, VerticalPositionCache&, WordMeasurements&);
+    void computeBlockDirectionPositionsForLine(RootInlineBox*, BidiRun*, GlyphOverflowAndFallbackFontsMap&, VerticalPositionCache&);
+    void deleteEllipsisLineBoxes();
+    void checkLinesForTextOverflow();
+
+    // Positions new floats and also adjust all floats encountered on the line if any of them
+    // have to move to the next page/column.
+    bool positionNewFloatOnLine(FloatingObject* newFloat, FloatingObject* lastFloatFromPreviousLine, LineInfo&, LineWidth&);
+    void appendFloatingObjectToLastLine(FloatingObject*);
+
+    // End of functions defined in RenderBlockLineLayout.cpp.
+
+    void paintFloats(PaintInfo&, const LayoutPoint&, bool preservePhase = false);
+    void paintContents(PaintInfo&, const LayoutPoint&);
+    void paintColumnContents(PaintInfo&, const LayoutPoint&, bool paintFloats = false);
+    void paintColumnRules(PaintInfo&, const LayoutPoint&);
+    void paintSelection(PaintInfo&, const LayoutPoint&);
+    void paintCaret(PaintInfo&, const LayoutPoint&, CaretType);
+
+    FloatingObject* insertFloatingObject(RenderBox*);
+    void removeFloatingObject(RenderBox*);
+    void removeFloatingObjectsBelow(FloatingObject*, int logicalOffset);
+    
+    // Called from lineWidth, to position the floats added in the last line.
+    // Returns true if and only if it has positioned any floats.
+    bool positionNewFloats();
+
+    void clearFloats();
+
+    LayoutUnit getClearDelta(RenderBox* child, LayoutUnit yPos);
+
+    virtual bool avoidsFloats() const;
+
+    bool hasOverhangingFloats() { return parent() && !hasColumns() && containsFloats() && lowestFloatLogicalBottom() > logicalHeight(); }
+    bool hasOverhangingFloat(RenderBox*);
+    void addIntrudingFloats(RenderBlock* prev, LayoutUnit xoffset, LayoutUnit yoffset);
+    LayoutUnit addOverhangingFloats(RenderBlock* child, bool makeChildPaintOtherFloats);
+
+    LayoutUnit lowestFloatLogicalBottom(FloatingObject::Type = FloatingObject::FloatLeftRight) const; 
+    LayoutUnit nextFloatLogicalBottomBelow(LayoutUnit) const;
+    
+    bool hitTestColumns(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction);
+    bool hitTestContents(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction);
+    bool hitTestFloats(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset);
+
+    virtual bool isPointInOverflowControl(HitTestResult&, const LayoutPoint& locationInContainer, const LayoutPoint& accumulatedOffset);
+
+    // FIXME: Make this method const so we can remove the const_cast in computeIntrinsicLogicalWidths.
+    void computeInlinePreferredLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth);
+    void computeBlockPreferredLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const;
+
+    // Obtains the nearest enclosing block (including this block) that contributes a first-line style to our inline
+    // children.
+    virtual RenderBlock* firstLineBlock() const;
+
+    virtual LayoutRect rectWithOutlineForRepaint(const RenderLayerModelObject* repaintContainer, LayoutUnit outlineWidth) const OVERRIDE FINAL;
+    virtual RenderStyle* outlineStyleForRepaint() const OVERRIDE FINAL;
+    
+    virtual RenderObject* hoverAncestor() const OVERRIDE FINAL;
+    virtual void updateDragState(bool dragOn) OVERRIDE FINAL;
+    virtual void childBecameNonInline(RenderObject* child) OVERRIDE FINAL;
+
+    virtual LayoutRect selectionRectForRepaint(const RenderLayerModelObject* repaintContainer, bool /*clipToVisibleContent*/) OVERRIDE FINAL
+    {
+        return selectionGapRectsForRepaint(repaintContainer);
+    }
+    virtual bool shouldPaintSelectionGaps() const OVERRIDE FINAL;
+    bool isSelectionRoot() const;
+    GapRects selectionGaps(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
+                           LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const PaintInfo* = 0);
+    GapRects inlineSelectionGaps(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
+                                 LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const PaintInfo*);
+    GapRects blockSelectionGaps(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
+                                LayoutUnit& lastLogicalTop, LayoutUnit& lastLogicalLeft, LayoutUnit& lastLogicalRight, const PaintInfo*);
+    LayoutRect blockSelectionGap(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock,
+                                 LayoutUnit lastLogicalTop, LayoutUnit lastLogicalLeft, LayoutUnit lastLogicalRight, LayoutUnit logicalBottom, const PaintInfo*);
+    LayoutUnit logicalLeftSelectionOffset(RenderBlock* rootBlock, LayoutUnit position);
+    LayoutUnit logicalRightSelectionOffset(RenderBlock* rootBlock, LayoutUnit position);
+
+    virtual void absoluteRects(Vector<IntRect>&, const LayoutPoint& accumulatedOffset) const;
+    virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const;
+
+    LayoutUnit desiredColumnWidth() const;
+    unsigned desiredColumnCount() const;
+
+    void paintContinuationOutlines(PaintInfo&, const LayoutPoint&);
+
+    virtual LayoutRect localCaretRect(InlineBox*, int caretOffset, LayoutUnit* extraWidthToEndOfLine = 0) OVERRIDE FINAL;
+
+    void adjustPointToColumnContents(LayoutPoint&) const;
+    
+    void fitBorderToLinesIfNeeded(); // Shrink the box in which the border paints if border-fit is set.
+    void adjustForBorderFit(LayoutUnit x, LayoutUnit& left, LayoutUnit& right) const; // Helper function for borderFitAdjust
+
+    void markLinesDirtyInBlockRange(LayoutUnit logicalTop, LayoutUnit logicalBottom, RootInlineBox* highest = 0);
+
+    void newLine(EClear);
+
+    Position positionForBox(InlineBox*, bool start = true) const;
+    VisiblePosition positionForPointWithInlineChildren(const LayoutPoint&);
+
+    virtual void calcColumnWidth();
+    void makeChildrenAnonymousColumnBlocks(RenderObject* beforeChild, RenderBlock* newBlockBox, RenderObject* newChild);
+
+    bool expandsToEncloseOverhangingFloats() const;
+
+    void splitBlocks(RenderBlock* fromBlock, RenderBlock* toBlock, RenderBlock* middleBlock,
+                     RenderObject* beforeChild, RenderBoxModelObject* oldCont);
+    void splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox,
+                   RenderObject* newChild, RenderBoxModelObject* oldCont);
+    RenderBlock* clone() const;
+    RenderBlock* continuationBefore(RenderObject* beforeChild);
+    RenderBlock* containingColumnsBlock(bool allowAnonymousColumnBlock = true);
+    RenderBlock* columnsBlockForSpanningElement(RenderObject* newChild);
+
+    class MarginInfo {
+        // Collapsing flags for whether we can collapse our margins with our children's margins.
+        bool m_canCollapseWithChildren : 1;
+        bool m_canCollapseMarginBeforeWithChildren : 1;
+        bool m_canCollapseMarginAfterWithChildren : 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_atBeforeSideOfBlock : 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_atAfterSideOfBlock : 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_hasMarginBeforeQuirk : 1;
+        bool m_hasMarginAfterQuirk : 1;
+        bool m_determinedMarginBeforeQuirk : 1;
+
+        bool m_discardMargin : 1;
+
+        // These flags track the previous maximal positive and negative margins.
+        LayoutUnit m_positiveMargin;
+        LayoutUnit m_negativeMargin;
+
+    public:
+        MarginInfo(RenderBlock*, LayoutUnit beforeBorderPadding, LayoutUnit afterBorderPadding);
+
+        void setAtBeforeSideOfBlock(bool b) { m_atBeforeSideOfBlock = b; }
+        void setAtAfterSideOfBlock(bool b) { m_atAfterSideOfBlock = b; }
+        void clearMargin()
+        {
+            m_positiveMargin = 0;
+            m_negativeMargin = 0;
+        }
+        void setHasMarginBeforeQuirk(bool b) { m_hasMarginBeforeQuirk = b; }
+        void setHasMarginAfterQuirk(bool b) { m_hasMarginAfterQuirk = b; }
+        void setDeterminedMarginBeforeQuirk(bool b) { m_determinedMarginBeforeQuirk = b; }
+        void setPositiveMargin(LayoutUnit p) { ASSERT(!m_discardMargin); m_positiveMargin = p; }
+        void setNegativeMargin(LayoutUnit n) { ASSERT(!m_discardMargin); m_negativeMargin = n; }
+        void setPositiveMarginIfLarger(LayoutUnit p)
+        {
+            ASSERT(!m_discardMargin);
+            if (p > m_positiveMargin)
+                m_positiveMargin = p;
+        }
+        void setNegativeMarginIfLarger(LayoutUnit n)
+        {
+            ASSERT(!m_discardMargin);
+            if (n > m_negativeMargin)
+                m_negativeMargin = n;
+        }
+
+        void setMargin(LayoutUnit p, LayoutUnit n) { ASSERT(!m_discardMargin); m_positiveMargin = p; m_negativeMargin = n; }
+        void setCanCollapseMarginAfterWithChildren(bool collapse) { m_canCollapseMarginAfterWithChildren = collapse; }
+        void setDiscardMargin(bool value) { m_discardMargin = value; }
+
+        bool atBeforeSideOfBlock() const { return m_atBeforeSideOfBlock; }
+        bool canCollapseWithMarginBefore() const { return m_atBeforeSideOfBlock && m_canCollapseMarginBeforeWithChildren; }
+        bool canCollapseWithMarginAfter() const { return m_atAfterSideOfBlock && m_canCollapseMarginAfterWithChildren; }
+        bool canCollapseMarginBeforeWithChildren() const { return m_canCollapseMarginBeforeWithChildren; }
+        bool canCollapseMarginAfterWithChildren() const { return m_canCollapseMarginAfterWithChildren; }
+        bool quirkContainer() const { return m_quirkContainer; }
+        bool determinedMarginBeforeQuirk() const { return m_determinedMarginBeforeQuirk; }
+        bool hasMarginBeforeQuirk() const { return m_hasMarginBeforeQuirk; }
+        bool hasMarginAfterQuirk() const { return m_hasMarginAfterQuirk; }
+        LayoutUnit positiveMargin() const { return m_positiveMargin; }
+        LayoutUnit negativeMargin() const { return m_negativeMargin; }
+        bool discardMargin() const { return m_discardMargin; }
+        LayoutUnit margin() const { return m_positiveMargin - m_negativeMargin; }
+    };
+
+    void layoutBlockChild(RenderBox* child, MarginInfo&, LayoutUnit& previousFloatLogicalBottom, LayoutUnit& maxFloatLogicalBottom);
+    void adjustPositionedBlock(RenderBox* child, const MarginInfo&);
+    void adjustFloatingBlock(const MarginInfo&);
+
+    RenderBoxModelObject* createReplacementRunIn(RenderBoxModelObject* runIn);
+    void moveRunInUnderSiblingBlockIfNeeded(RenderObject* runIn);
+    void moveRunInToOriginalPosition(RenderObject* runIn);
+
+    LayoutUnit collapseMargins(RenderBox* child, MarginInfo&);
+    LayoutUnit clearFloatsIfNeeded(RenderBox* child, MarginInfo&, LayoutUnit oldTopPosMargin, LayoutUnit oldTopNegMargin, LayoutUnit yPos);
+    LayoutUnit estimateLogicalTopPosition(RenderBox* child, const MarginInfo&, LayoutUnit& estimateWithoutPagination);
+    void marginBeforeEstimateForChild(RenderBox*, LayoutUnit&, LayoutUnit&, bool&) const;
+    void handleAfterSideOfBlock(LayoutUnit top, LayoutUnit bottom, MarginInfo&);
+    void setCollapsedBottomMargin(const MarginInfo&);
+    // End helper functions and structs used by layoutBlockChildren.
+
+    // Helper function for layoutInlineChildren()
+    RootInlineBox* createLineBoxesFromBidiRuns(BidiRunList<BidiRun>&, const InlineIterator& end, LineInfo&, VerticalPositionCache&, BidiRun* trailingSpaceRun, WordMeasurements&);
+    void layoutRunsAndFloats(LineLayoutState&, bool hasInlineChild);
+    void layoutRunsAndFloatsInRange(LineLayoutState&, InlineBidiResolver&, const InlineIterator& cleanLineStart, const BidiStatus& cleanLineBidiStatus, unsigned consecutiveHyphenatedLines);
+    const InlineIterator& restartLayoutRunsAndFloatsInRange(LayoutUnit oldLogicalHeight, LayoutUnit newLogicalHeight,  FloatingObject* lastFloatFromPreviousLine, InlineBidiResolver&,  const InlineIterator&);
+    void linkToEndLineIfNeeded(LineLayoutState&);
+    static void repaintDirtyFloats(Vector<FloatWithRect>& floats);
+
+protected:
+    void determineLogicalLeftPositionForChild(RenderBox* child, ApplyLayoutDeltaMode = DoNotApplyLayoutDelta);
+
+    // Pagination routines.
+    virtual bool relayoutForPagination(bool hasSpecifiedPageLogicalHeight, LayoutUnit pageLogicalHeight, LayoutStateMaintainer&);
+    
+    // Returns the logicalOffset at the top of the next page. If the offset passed in is already at the top of the current page,
+    // then nextPageLogicalTop with ExcludePageBoundary will still move to the top of the next page. nextPageLogicalTop with
+    // IncludePageBoundary set will not.
+    //
+    // For a page height of 800px, the first rule will return 800 if the value passed in is 0. The second rule will simply return 0.
+    enum PageBoundaryRule { ExcludePageBoundary, IncludePageBoundary };
+    LayoutUnit nextPageLogicalTop(LayoutUnit logicalOffset, PageBoundaryRule = ExcludePageBoundary) const;
+    bool hasNextPage(LayoutUnit logicalOffset, PageBoundaryRule = ExcludePageBoundary) const;
+
+    virtual ColumnInfo::PaginationUnit paginationUnit() const;
+
+    LayoutUnit applyBeforeBreak(RenderBox* child, LayoutUnit logicalOffset); // If the child has a before break, then return a new yPos that shifts to the top of the next page/column.
+    LayoutUnit applyAfterBreak(RenderBox* child, LayoutUnit logicalOffset, MarginInfo&); // If the child has an after break, then return a new offset that shifts to the top of the next page/column.
+
+public:
+    LayoutUnit pageLogicalTopForOffset(LayoutUnit offset) const;
+    LayoutUnit pageLogicalHeightForOffset(LayoutUnit offset) const;
+    LayoutUnit pageRemainingLogicalHeightForOffset(LayoutUnit offset, PageBoundaryRule = IncludePageBoundary) const;
+    
+protected:
+    bool pushToNextPageWithMinimumLogicalHeight(LayoutUnit& adjustment, LayoutUnit logicalOffset, LayoutUnit minimumLogicalHeight) const;
+
+    LayoutUnit adjustForUnsplittableChild(RenderBox* child, LayoutUnit logicalOffset, bool includeMargins = false); // If the child is unsplittable and can't fit on the current page, return the top of the next page/column.
+    void adjustLinePositionForPagination(RootInlineBox*, LayoutUnit& deltaOffset, RenderFlowThread*); // Computes a deltaOffset value that put a line at the top of the next page if it doesn't fit on the current page.
+    LayoutUnit adjustBlockChildForPagination(LayoutUnit logicalTopAfterClear, LayoutUnit estimateWithoutPagination, RenderBox* child, bool atBeforeSideOfBlock);
+
+    // Adjust from painting offsets to the local coords of this renderer
+    void offsetForContents(LayoutPoint&) const;
+
+    // This function is called to test a line box that has moved in the block direction to see if it has ended up in a new
+    // region/page/column that has a different available line width than the old one. Used to know when you have to dirty a
+    // line, i.e., that it can't be re-used.
+    bool lineWidthForPaginatedLineChanged(RootInlineBox*, LayoutUnit lineDelta, RenderFlowThread*) const;
+
+    bool logicalWidthChangedInRegions(RenderFlowThread*) const;
+
+    virtual bool requiresColumns(int desiredColumnCount) const;
+
+    virtual bool updateLogicalWidthAndColumnWidth();
+
+    virtual bool canCollapseAnonymousBlockChild() const { return true; }
+
+public:
+    LayoutUnit offsetFromLogicalTopOfFirstPage() const;
+    RenderRegion* regionAtBlockOffset(LayoutUnit) const;
+    RenderRegion* clampToStartAndEndRegions(RenderRegion*) const;
+
+protected:
+    struct FloatingObjectHashFunctions {
+        static unsigned hash(FloatingObject* key) { return DefaultHash<RenderBox*>::Hash::hash(key->m_renderer); }
+        static bool equal(FloatingObject* a, FloatingObject* b) { return a->m_renderer == b->m_renderer; }
+        static const bool safeToCompareToEmptyOrDeleted = true;
+    };
+    struct FloatingObjectHashTranslator {
+        static unsigned hash(RenderBox* key) { return DefaultHash<RenderBox*>::Hash::hash(key); }
+        static bool equal(FloatingObject* a, RenderBox* b) { return a->m_renderer == b; }
+    };
+    typedef ListHashSet<FloatingObject*, 4, FloatingObjectHashFunctions> FloatingObjectSet;
+    typedef FloatingObjectSet::const_iterator FloatingObjectSetIterator;
+    typedef PODInterval<int, FloatingObject*> FloatingObjectInterval;
+    typedef PODIntervalTree<int, FloatingObject*> FloatingObjectTree;
+    typedef PODFreeListArena<PODRedBlackTree<FloatingObjectInterval>::Node> IntervalArena;
+    
+    template <FloatingObject::Type FloatTypeValue>
+    class FloatIntervalSearchAdapter {
+    public:
+        typedef FloatingObjectInterval IntervalType;
+        
+        FloatIntervalSearchAdapter(const RenderBlock* renderer, int lowValue, int highValue, LayoutUnit& offset, LayoutUnit* heightRemaining)
+            : m_renderer(renderer)
+            , m_lowValue(lowValue)
+            , m_highValue(highValue)
+            , m_offset(offset)
+            , m_heightRemaining(heightRemaining)
+            , m_last(0)
+        {
+        }
+        
+        inline int lowValue() const { return m_lowValue; }
+        inline int highValue() const { return m_highValue; }
+        void collectIfNeeded(const IntervalType&) const;
+
+        // When computing the offset caused by the floats on a given line, if
+        // the outermost float on that line has a shape-outside, the inline
+        // content that butts up against that float must be positioned using
+        // the contours of the shape, not the shape's bounding box. We save the
+        // last float encountered so that the offset can be computed correctly
+        // by the code using this adapter.
+        const FloatingObject* lastFloat() const { return m_last; }
+
+    private:
+        const RenderBlock* m_renderer;
+        int m_lowValue;
+        int m_highValue;
+        LayoutUnit& m_offset;
+        LayoutUnit* m_heightRemaining;
+        // This member variable is mutable because the collectIfNeeded method
+        // is declared as const, even though it doesn't actually respect that
+        // contract. It modifies other member variables via loopholes in the
+        // const behavior. Instead of using loopholes, I decided it was better
+        // to make the fact that this is modified in a const method explicit.
+        mutable const FloatingObject* m_last;
+    };
+
+    void createFloatingObjects();
+
+public:
+
+    class FloatingObjects {
+        WTF_MAKE_NONCOPYABLE(FloatingObjects); WTF_MAKE_FAST_ALLOCATED;
+    public:
+        void clear();
+        void add(FloatingObject*);
+        void remove(FloatingObject*);
+        void addPlacedObject(FloatingObject*);
+        void removePlacedObject(FloatingObject*);
+        void setHorizontalWritingMode(bool b = true) { m_horizontalWritingMode = b; }
+
+        bool hasLeftObjects() const { return m_leftObjectsCount > 0; }
+        bool hasRightObjects() const { return m_rightObjectsCount > 0; }
+        const FloatingObjectSet& set() const { return m_set; }
+        const FloatingObjectTree& placedFloatsTree()
+        {
+            computePlacedFloatsTreeIfNeeded();
+            return m_placedFloatsTree; 
+        }
+    private:
+        FloatingObjects(const RenderBlock*, bool horizontalWritingMode);
+        void computePlacedFloatsTree();
+        inline void computePlacedFloatsTreeIfNeeded()
+        {
+            if (!m_placedFloatsTree.isInitialized())
+                computePlacedFloatsTree();
+        }
+        void increaseObjectsCount(FloatingObject::Type);
+        void decreaseObjectsCount(FloatingObject::Type);
+        FloatingObjectInterval intervalForFloatingObject(FloatingObject*);
+
+        FloatingObjectSet m_set;
+        FloatingObjectTree m_placedFloatsTree;
+        unsigned m_leftObjectsCount;
+        unsigned m_rightObjectsCount;
+        bool m_horizontalWritingMode;
+        const RenderBlock* m_renderer;
+
+        friend void RenderBlock::createFloatingObjects();
+    };
+
+    // Allocated only when some of these fields have non-default values
+    struct RenderBlockRareData {
+        WTF_MAKE_NONCOPYABLE(RenderBlockRareData); WTF_MAKE_FAST_ALLOCATED;
+    public:
+        RenderBlockRareData(const RenderBlock* block) 
+            : m_margins(positiveMarginBeforeDefault(block), negativeMarginBeforeDefault(block), positiveMarginAfterDefault(block), negativeMarginAfterDefault(block))
+            , m_paginationStrut(0)
+            , m_pageLogicalOffset(0)
+            , m_lineGridBox(0)
+            , m_lineBreakToAvoidWidow(0)
+            , m_shouldBreakAtLineToAvoidWidow(false)
+            , m_discardMarginBefore(false)
+            , m_discardMarginAfter(false)
+        { 
+        }
+
+        static LayoutUnit positiveMarginBeforeDefault(const RenderBlock* block)
+        { 
+            return std::max<LayoutUnit>(block->marginBefore(), 0);
+        }
+        static LayoutUnit negativeMarginBeforeDefault(const RenderBlock* block)
+        { 
+            return std::max<LayoutUnit>(-block->marginBefore(), 0);
+        }
+        static LayoutUnit positiveMarginAfterDefault(const RenderBlock* block)
+        {
+            return std::max<LayoutUnit>(block->marginAfter(), 0);
+        }
+        static LayoutUnit negativeMarginAfterDefault(const RenderBlock* block)
+        {
+            return std::max<LayoutUnit>(-block->marginAfter(), 0);
+        }
+        
+        MarginValues m_margins;
+        LayoutUnit m_paginationStrut;
+        LayoutUnit m_pageLogicalOffset;
+        
+        RootInlineBox* m_lineGridBox;
+
+        RootInlineBox* m_lineBreakToAvoidWidow;
+        OwnPtr<ExclusionShapeInsideInfo> m_shapeInsideInfo;
+        bool m_shouldBreakAtLineToAvoidWidow : 1;
+        bool m_discardMarginBefore : 1;
+        bool m_discardMarginAfter : 1;
+     };
+
+protected:
+
+    OwnPtr<FloatingObjects> m_floatingObjects;
+    OwnPtr<RenderBlockRareData> m_rareData;
+
+    RenderObjectChildList m_children;
+    RenderLineBoxList m_lineBoxes;   // All of the root line boxes created for this block flow.  For example, <div>Hello<br>world.</div> will have two total lines for the <div>.
+
+    mutable signed m_lineHeight : 27;
+    unsigned m_hasMarginBeforeQuirk : 1; // Note these quirk values can't be put in RenderBlockRareData since they are set too frequently.
+    unsigned m_hasMarginAfterQuirk : 1;
+    unsigned m_beingDestroyed : 1;
+    unsigned m_hasMarkupTruncation : 1;
+    unsigned m_hasBorderOrPaddingLogicalWidthChanged : 1;
+
+    // RenderRubyBase objects need to be able to split and merge, moving their children around
+    // (calling moveChildTo, moveAllChildrenTo, and makeChildrenNonInline).
+    friend class RenderRubyBase;
+    friend class LineWidth; // Needs to know FloatingObject
+
+private:
+    // Used to store state between styleWillChange and styleDidChange
+    static bool s_canPropagateFloatIntoSibling;
+};
+
+inline RenderBlock* toRenderBlock(RenderObject* object)
+{ 
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isRenderBlock());
+    return static_cast<RenderBlock*>(object);
+}
+
+inline const RenderBlock* toRenderBlock(const RenderObject* object)
+{ 
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isRenderBlock());
+    return static_cast<const RenderBlock*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderBlock(const RenderBlock*);
+
+#ifndef NDEBUG
+// These structures are used by PODIntervalTree for debugging purposes.
+template <> struct ValueToString<int> {
+    static String string(const int value);
+};
+template<> struct ValueToString<RenderBlock::FloatingObject*> {
+    static String string(const RenderBlock::FloatingObject*);
+};
+#endif
+
+} // namespace WebCore
+
+#endif // RenderBlock_h
diff --git a/Source/core/rendering/RenderBlockLineLayout.cpp b/Source/core/rendering/RenderBlockLineLayout.cpp
new file mode 100644
index 0000000..3a56083
--- /dev/null
+++ b/Source/core/rendering/RenderBlockLineLayout.cpp
@@ -0,0 +1,3380 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All right reserved.
+ * Copyright (C) 2010 Google 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 "core/page/Settings.h"
+#include "core/platform/Logging.h"
+#include "core/platform/text/BidiResolver.h"
+#include "core/platform/text/Hyphenation.h"
+#include "core/rendering/exclusions/ExclusionShapeInsideInfo.h"
+#include "core/rendering/InlineIterator.h"
+#include "core/rendering/InlineTextBox.h"
+#include "core/rendering/RenderArena.h"
+#include "core/rendering/RenderCombineText.h"
+#include "core/rendering/RenderCounter.h"
+#include "core/rendering/RenderFlowThread.h"
+#include "core/rendering/RenderInline.h"
+#include "core/rendering/RenderLayer.h"
+#include "core/rendering/RenderListMarker.h"
+#include "core/rendering/RenderRegion.h"
+#include "core/rendering/RenderRubyRun.h"
+#include "core/rendering/RenderView.h"
+#include "core/rendering/TrailingFloatsRootInlineBox.h"
+#include "core/rendering/VerticalPositionCache.h"
+#include "core/rendering/break_lines.h"
+#include <wtf/RefCountedLeakCounter.h>
+#include <wtf/StdLibExtras.h>
+#include <wtf/unicode/CharacterNames.h>
+#include <wtf/Vector.h>
+
+#if ENABLE(SVG)
+#include "core/rendering/svg/RenderSVGInlineText.h"
+#include "core/rendering/svg/SVGRootInlineBox.h"
+#endif
+
+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;
+
+static LayoutUnit logicalHeightForLine(const RenderBlock* block, bool isFirstLine, LayoutUnit replacedHeight = 0)
+{
+    if (!block->document()->inNoQuirksMode() && replacedHeight)
+        return replacedHeight;
+
+    if (!(block->style(isFirstLine)->lineBoxContain() & LineBoxContainBlock))
+        return 0;
+
+    return max<LayoutUnit>(replacedHeight, block->lineHeight(isFirstLine, block->isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes));
+}
+
+ExclusionShapeInsideInfo* RenderBlock::layoutExclusionShapeInsideInfo() const
+{
+    ExclusionShapeInsideInfo* shapeInsideInfo = view()->layoutState()->exclusionShapeInsideInfo();
+    if (!shapeInsideInfo && flowThreadContainingBlock() && allowsExclusionShapeInsideInfoSharing()) {
+        LayoutUnit offset = logicalHeight() + logicalHeightForLine(this, false);
+        RenderRegion* region = regionAtBlockOffset(offset);
+        return region ? region->exclusionShapeInsideInfo() : 0;
+    }
+    return shapeInsideInfo;
+}
+
+enum IndentTextOrNot { DoNotIndentText, IndentText };
+
+class LineWidth {
+public:
+    LineWidth(RenderBlock* block, bool isFirstLine, IndentTextOrNot shouldIndentText)
+        : m_block(block)
+        , m_uncommittedWidth(0)
+        , m_committedWidth(0)
+        , m_overhangWidth(0)
+        , m_left(0)
+        , m_right(0)
+        , m_availableWidth(0)
+        , m_segment(0)
+        , m_isFirstLine(isFirstLine)
+        , m_shouldIndentText(shouldIndentText)
+    {
+        ASSERT(block);
+        ExclusionShapeInsideInfo* exclusionShapeInsideInfo = m_block->layoutExclusionShapeInsideInfo();
+        if (exclusionShapeInsideInfo)
+            m_segment = exclusionShapeInsideInfo->currentSegment();
+        updateAvailableWidth();
+    }
+    bool fitsOnLine() const { return currentWidth() <= m_availableWidth; }
+    bool fitsOnLine(float extra) const { return currentWidth() + extra <= m_availableWidth; }
+    float currentWidth() const { return m_committedWidth + m_uncommittedWidth; }
+
+    // FIXME: We should eventually replace these three functions by ones that work on a higher abstraction.
+    float uncommittedWidth() const { return m_uncommittedWidth; }
+    float committedWidth() const { return m_committedWidth; }
+    float availableWidth() const { return m_availableWidth; }
+
+    void updateAvailableWidth(LayoutUnit minimumHeight = 0);
+    void shrinkAvailableWidthForNewFloatIfNeeded(RenderBlock::FloatingObject*);
+    void addUncommittedWidth(float delta) { m_uncommittedWidth += delta; }
+    void commit()
+    {
+        m_committedWidth += m_uncommittedWidth;
+        m_uncommittedWidth = 0;
+    }
+    void applyOverhang(RenderRubyRun*, RenderObject* startRenderer, RenderObject* endRenderer);
+    void fitBelowFloats();
+
+    bool shouldIndentText() { return m_shouldIndentText == IndentText; }
+
+private:
+    void computeAvailableWidthFromLeftAndRight()
+    {
+        m_availableWidth = max(0.0f, m_right - m_left) + m_overhangWidth;
+    }
+
+private:
+    RenderBlock* m_block;
+    float m_uncommittedWidth;
+    float m_committedWidth;
+    float m_overhangWidth; // The amount by which |m_availableWidth| has been inflated to account for possible contraction due to ruby overhang.
+    float m_left;
+    float m_right;
+    float m_availableWidth;
+    const LineSegment* m_segment;
+    bool m_isFirstLine;
+    IndentTextOrNot m_shouldIndentText;
+};
+
+inline void LineWidth::updateAvailableWidth(LayoutUnit replacedHeight)
+{
+    LayoutUnit height = m_block->logicalHeight();
+    LayoutUnit logicalHeight = logicalHeightForLine(m_block, m_isFirstLine, replacedHeight);
+    m_left = m_block->logicalLeftOffsetForLine(height, shouldIndentText(), logicalHeight);
+    m_right = m_block->logicalRightOffsetForLine(height, shouldIndentText(), logicalHeight);
+
+    if (m_segment) {
+        m_left = max<float>(m_segment->logicalLeft, m_left);
+        m_right = min<float>(m_segment->logicalRight, m_right);
+    }
+
+    computeAvailableWidthFromLeftAndRight();
+}
+
+inline void LineWidth::shrinkAvailableWidthForNewFloatIfNeeded(RenderBlock::FloatingObject* newFloat)
+{
+    LayoutUnit height = m_block->logicalHeight();
+    if (height < m_block->logicalTopForFloat(newFloat) || height >= m_block->logicalBottomForFloat(newFloat))
+        return;
+
+    ExclusionShapeOutsideInfo* shapeOutsideInfo = newFloat->renderer()->exclusionShapeOutsideInfo();
+    if (shapeOutsideInfo)
+        shapeOutsideInfo->computeSegmentsForLine(m_block->logicalHeight() - m_block->logicalTopForFloat(newFloat) + shapeOutsideInfo->shapeLogicalTop(), logicalHeightForLine(m_block, m_isFirstLine));
+
+    if (newFloat->type() == RenderBlock::FloatingObject::FloatLeft) {
+        float newLeft = m_block->logicalRightForFloat(newFloat);
+        if (shapeOutsideInfo)
+            newLeft += shapeOutsideInfo->rightSegmentShapeBoundingBoxDelta();
+
+        if (shouldIndentText() && m_block->style()->isLeftToRightDirection())
+            newLeft += floorToInt(m_block->textIndentOffset());
+        m_left = max<float>(m_left, newLeft);
+    } else {
+        float newRight = m_block->logicalLeftForFloat(newFloat);
+        if (shapeOutsideInfo)
+            newRight += shapeOutsideInfo->leftSegmentShapeBoundingBoxDelta();
+
+        if (shouldIndentText() && !m_block->style()->isLeftToRightDirection())
+            newRight -= floorToInt(m_block->textIndentOffset());
+        m_right = min<float>(m_right, newRight);
+    }
+
+    computeAvailableWidthFromLeftAndRight();
+}
+
+void LineWidth::applyOverhang(RenderRubyRun* rubyRun, RenderObject* startRenderer, RenderObject* endRenderer)
+{
+    int startOverhang;
+    int endOverhang;
+    rubyRun->getOverhang(m_isFirstLine, startRenderer, endRenderer, startOverhang, endOverhang);
+
+    startOverhang = min<int>(startOverhang, m_committedWidth);
+    m_availableWidth += startOverhang;
+
+    endOverhang = max(min<int>(endOverhang, m_availableWidth - currentWidth()), 0);
+    m_availableWidth += endOverhang;
+    m_overhangWidth += startOverhang + endOverhang;
+}
+
+void LineWidth::fitBelowFloats()
+{
+    ASSERT(!m_committedWidth);
+    ASSERT(!fitsOnLine());
+
+    LayoutUnit floatLogicalBottom;
+    LayoutUnit lastFloatLogicalBottom = m_block->logicalHeight();
+    float newLineWidth = m_availableWidth;
+    float newLineLeft = m_left;
+    float newLineRight = m_right;
+    while (true) {
+        floatLogicalBottom = m_block->nextFloatLogicalBottomBelow(lastFloatLogicalBottom);
+        if (floatLogicalBottom <= lastFloatLogicalBottom)
+            break;
+
+        newLineLeft = m_block->logicalLeftOffsetForLine(floatLogicalBottom, shouldIndentText());
+        newLineRight = m_block->logicalRightOffsetForLine(floatLogicalBottom, shouldIndentText());
+        newLineWidth = max(0.0f, newLineRight - newLineLeft);
+        lastFloatLogicalBottom = floatLogicalBottom;
+        if (newLineWidth >= m_uncommittedWidth)
+            break;
+    }
+
+    if (newLineWidth > m_availableWidth) {
+        m_block->setLogicalHeight(lastFloatLogicalBottom);
+        m_availableWidth = newLineWidth + m_overhangWidth;
+        m_left = newLineLeft;
+        m_right = newLineRight;
+    }
+}
+
+class LineInfo {
+public:
+    LineInfo()
+        : m_isFirstLine(true)
+        , m_isLastLine(false)
+        , m_isEmpty(true)
+        , m_previousLineBrokeCleanly(true)
+        , m_floatPaginationStrut(0)
+        , m_runsFromLeadingWhitespace(0)
+    { }
+
+    bool isFirstLine() const { return m_isFirstLine; }
+    bool isLastLine() const { return m_isLastLine; }
+    bool isEmpty() const { return m_isEmpty; }
+    bool previousLineBrokeCleanly() const { return m_previousLineBrokeCleanly; }
+    LayoutUnit floatPaginationStrut() const { return m_floatPaginationStrut; }
+    unsigned runsFromLeadingWhitespace() const { return m_runsFromLeadingWhitespace; }
+    void resetRunsFromLeadingWhitespace() { m_runsFromLeadingWhitespace = 0; }
+    void incrementRunsFromLeadingWhitespace() { m_runsFromLeadingWhitespace++; }
+
+    void setFirstLine(bool firstLine) { m_isFirstLine = firstLine; }
+    void setLastLine(bool lastLine) { m_isLastLine = lastLine; }
+    void setEmpty(bool empty, RenderBlock* block = 0, LineWidth* lineWidth = 0)
+    {
+        if (m_isEmpty == empty)
+            return;
+        m_isEmpty = empty;
+        if (!empty && block && floatPaginationStrut()) {
+            block->setLogicalHeight(block->logicalHeight() + floatPaginationStrut());
+            setFloatPaginationStrut(0);
+            lineWidth->updateAvailableWidth();
+        }
+    }
+
+    void setPreviousLineBrokeCleanly(bool previousLineBrokeCleanly) { m_previousLineBrokeCleanly = previousLineBrokeCleanly; }
+    void setFloatPaginationStrut(LayoutUnit strut) { m_floatPaginationStrut = strut; }
+
+private:
+    bool m_isFirstLine;
+    bool m_isLastLine;
+    bool m_isEmpty;
+    bool m_previousLineBrokeCleanly;
+    LayoutUnit m_floatPaginationStrut;
+    unsigned m_runsFromLeadingWhitespace;
+};
+
+static inline LayoutUnit borderPaddingMarginStart(RenderInline* child)
+{
+    return child->marginStart() + child->paddingStart() + child->borderStart();
+}
+
+static inline LayoutUnit borderPaddingMarginEnd(RenderInline* child)
+{
+    return child->marginEnd() + child->paddingEnd() + child->borderEnd();
+}
+
+static bool shouldAddBorderPaddingMargin(RenderObject* child, bool &checkSide)
+{
+    if (!child || (child->isText() && !toRenderText(child)->textLength()))
+        return true;
+    checkSide = false;
+    return checkSide;
+}
+
+static LayoutUnit inlineLogicalWidth(RenderObject* child, bool start = true, bool end = true)
+{
+    unsigned lineDepth = 1;
+    LayoutUnit extraWidth = 0;
+    RenderObject* parent = child->parent();
+    while (parent->isRenderInline() && lineDepth++ < cMaxLineDepth) {
+        RenderInline* parentAsRenderInline = toRenderInline(parent);
+        if (!isEmptyInline(parentAsRenderInline)) {
+            if (start && shouldAddBorderPaddingMargin(child->previousSibling(), start))
+                extraWidth += borderPaddingMarginStart(parentAsRenderInline);
+            if (end && shouldAddBorderPaddingMargin(child->nextSibling(), end))
+                extraWidth += borderPaddingMarginEnd(parentAsRenderInline);
+            if (!start && !end)
+                return extraWidth;
+        }
+        child = parent;
+        parent = child->parent();
+    }
+    return extraWidth;
+}
+
+static void determineDirectionality(TextDirection& dir, InlineIterator iter)
+{
+    while (!iter.atEnd()) {
+        if (iter.atParagraphSeparator())
+            return;
+        if (UChar current = iter.current()) {
+            Direction charDirection = direction(current);
+            if (charDirection == LeftToRight) {
+                dir = LTR;
+                return;
+            }
+            if (charDirection == RightToLeft || charDirection == RightToLeftArabic) {
+                dir = RTL;
+                return;
+            }
+        }
+        iter.increment();
+    }
+}
+
+static void checkMidpoints(LineMidpointState& lineMidpointState, 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.m_obj && lineMidpointState.numMidpoints && !(lineMidpointState.numMidpoints % 2)) {
+        InlineIterator* midpoints = lineMidpointState.midpoints.data();
+        InlineIterator& endpoint = midpoints[lineMidpointState.numMidpoints - 2];
+        const InlineIterator& startpoint = midpoints[lineMidpointState.numMidpoints - 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.
+            lineMidpointState.numMidpoints--;
+            if (endpoint.m_obj->style()->collapseWhiteSpace())
+                endpoint.m_pos--;
+        }
+    }
+}
+
+// Don't call this directly. Use one of the descriptive helper functions below.
+static void deprecatedAddMidpoint(LineMidpointState& lineMidpointState, const InlineIterator& midpoint)
+{
+    if (lineMidpointState.midpoints.size() <= lineMidpointState.numMidpoints)
+        lineMidpointState.midpoints.grow(lineMidpointState.numMidpoints + 10);
+
+    InlineIterator* midpoints = lineMidpointState.midpoints.data();
+    midpoints[lineMidpointState.numMidpoints++] = midpoint;
+}
+
+static inline void startIgnoringSpaces(LineMidpointState& lineMidpointState, const InlineIterator& midpoint)
+{
+    ASSERT(!(lineMidpointState.numMidpoints % 2));
+    deprecatedAddMidpoint(lineMidpointState, midpoint);
+}
+
+static inline void stopIgnoringSpaces(LineMidpointState& lineMidpointState, const InlineIterator& midpoint)
+{
+    ASSERT(lineMidpointState.numMidpoints % 2);
+    deprecatedAddMidpoint(lineMidpointState, midpoint);
+}
+
+// When ignoring spaces, this needs to be called for objects that need line boxes such as RenderInlines or
+// hard line breaks to ensure that they're not ignored.
+static inline void ensureLineBoxInsideIgnoredSpaces(LineMidpointState& lineMidpointState, RenderObject* renderer)
+{
+    InlineIterator midpoint(0, renderer, 0);
+    stopIgnoringSpaces(lineMidpointState, midpoint);
+    startIgnoringSpaces(lineMidpointState, midpoint);
+}
+
+// Adding a pair of midpoints before a character will split it out into a new line box.
+static inline void ensureCharacterGetsLineBox(LineMidpointState& lineMidpointState, InlineIterator& textParagraphSeparator)
+{
+    InlineIterator midpoint(0, textParagraphSeparator.m_obj, textParagraphSeparator.m_pos);
+    startIgnoringSpaces(lineMidpointState, InlineIterator(0, textParagraphSeparator.m_obj, textParagraphSeparator.m_pos - 1));
+    stopIgnoringSpaces(lineMidpointState, InlineIterator(0, textParagraphSeparator.m_obj, textParagraphSeparator.m_pos));
+}
+
+static inline BidiRun* createRun(int start, int end, RenderObject* obj, InlineBidiResolver& resolver)
+{
+    return new (obj->renderArena()) BidiRun(start, end, obj, resolver.context(), resolver.dir());
+}
+
+void RenderBlock::appendRunsForObject(BidiRunList<BidiRun>& runs, int start, int end, RenderObject* obj, InlineBidiResolver& resolver)
+{
+    if (start > end || shouldSkipCreatingRunsForObject(obj))
+        return;
+
+    LineMidpointState& lineMidpointState = resolver.midpointState();
+    bool haveNextMidpoint = (lineMidpointState.currentMidpoint < lineMidpointState.numMidpoints);
+    InlineIterator nextMidpoint;
+    if (haveNextMidpoint)
+        nextMidpoint = lineMidpointState.midpoints[lineMidpointState.currentMidpoint];
+    if (lineMidpointState.betweenMidpoints) {
+        if (!(haveNextMidpoint && nextMidpoint.m_obj == obj))
+            return;
+        // This is a new start point. Stop ignoring objects and
+        // adjust our start.
+        lineMidpointState.betweenMidpoints = false;
+        start = nextMidpoint.m_pos;
+        lineMidpointState.currentMidpoint++;
+        if (start < end)
+            return appendRunsForObject(runs, start, end, obj, resolver);
+    } else {
+        if (!haveNextMidpoint || (obj != nextMidpoint.m_obj)) {
+            runs.addRun(createRun(start, end, obj, resolver));
+            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.m_pos + 1) <= end) {
+            lineMidpointState.betweenMidpoints = true;
+            lineMidpointState.currentMidpoint++;
+            if (nextMidpoint.m_pos != UINT_MAX) { // UINT_MAX means stop at the object and don't include any of it.
+                if (static_cast<int>(nextMidpoint.m_pos + 1) > start)
+                    runs.addRun(createRun(start, nextMidpoint.m_pos + 1, obj, resolver));
+                return appendRunsForObject(runs, nextMidpoint.m_pos + 1, end, obj, resolver);
+            }
+        } else
+           runs.addRun(createRun(start, end, obj, resolver));
+    }
+}
+
+static inline InlineBox* createInlineBoxForRenderer(RenderObject* obj, bool isRootLineBox, bool isOnlyRun = false)
+{
+    if (isRootLineBox)
+        return toRenderBlock(obj)->createAndAppendRootInlineBox();
+
+    if (obj->isText()) {
+        InlineTextBox* textBox = toRenderText(obj)->createInlineTextBox();
+        // 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.)
+        if (obj->isBR())
+            textBox->setIsText(isOnlyRun || obj->document()->inNoQuirksMode());
+        return textBox;
+    }
+
+    if (obj->isBox())
+        return toRenderBox(obj)->createInlineBox();
+
+    return toRenderInline(obj)->createAndAppendInlineFlowBox();
+}
+
+// FIXME: Don't let counters mark themselves as needing pref width recalcs during layout
+// so we don't need this hack.
+static inline void updateCounterIfNeeded(RenderText* o)
+{
+    if (!o->preferredLogicalWidthsDirty() || !o->isCounter())
+        return;
+    toRenderCounter(o)->updateCounter();
+}
+
+static inline void dirtyLineBoxesForRenderer(RenderObject* o, bool fullLayout)
+{
+    if (o->isText()) {
+        RenderText* renderText = toRenderText(o);
+        updateCounterIfNeeded(renderText);
+        renderText->dirtyLineBoxes(fullLayout);
+    } else
+        toRenderInline(o)->dirtyLineBoxes(fullLayout);
+}
+
+static bool parentIsConstructedOrHaveNext(InlineFlowBox* parentBox)
+{
+    do {
+        if (parentBox->isConstructed() || parentBox->nextOnLine())
+            return true;
+        parentBox = parentBox->parent();
+    } while (parentBox);
+    return false;
+}
+
+InlineFlowBox* RenderBlock::createLineBoxes(RenderObject* obj, const LineInfo& lineInfo, InlineBox* childBox, bool startNewSegment)
+{
+    // See if we have an unconstructed line box for this object that is also
+    // the last item on the line.
+    unsigned lineDepth = 1;
+    InlineFlowBox* parentBox = 0;
+    InlineFlowBox* result = 0;
+    bool hasDefaultLineBoxContain = style()->lineBoxContain() == RenderStyle::initialLineBoxContain();
+    do {
+        ASSERT_WITH_SECURITY_IMPLICATION(obj->isRenderInline() || obj == this);
+
+        RenderInline* inlineFlow = (obj != this) ? toRenderInline(obj) : 0;
+
+        // Get the last box we made for this render object.
+        parentBox = inlineFlow ? inlineFlow->lastLineBox() : toRenderBlock(obj)->lastLineBox();
+
+        // If this box or its ancestor is constructed then it is from a previous line, and we need
+        // to make a new box for our line.  If this box or its ancestor 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;
+        bool allowedToConstructNewBox = !hasDefaultLineBoxContain || !inlineFlow || inlineFlow->alwaysCreateLineBoxes();
+        bool mustCreateBoxesToRoot = startNewSegment && !(parentBox && parentBox->isRootInlineBox());
+        bool canUseExistingParentBox = parentBox && !parentIsConstructedOrHaveNext(parentBox) && !mustCreateBoxesToRoot;
+        if (allowedToConstructNewBox && !canUseExistingParentBox) {
+            // 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 = createInlineBoxForRenderer(obj, obj == this);
+            ASSERT_WITH_SECURITY_IMPLICATION(newBox->isInlineFlowBox());
+            parentBox = toInlineFlowBox(newBox);
+            parentBox->setFirstLineStyleBit(lineInfo.isFirstLine());
+            parentBox->setIsHorizontal(isHorizontalWritingMode());
+            if (!hasDefaultLineBoxContain)
+                parentBox->clearDescendantsHaveSameLineHeightAndBaseline();
+            constructedNewBox = true;
+        }
+
+        if (constructedNewBox || canUseExistingParentBox) {
+            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;
+}
+
+template <typename CharacterType>
+static inline bool endsWithASCIISpaces(const CharacterType* characters, unsigned pos, unsigned end)
+{
+    while (isASCIISpace(characters[pos])) {
+        pos++;
+        if (pos >= end)
+            return true;
+    }
+    return false;
+}
+
+static bool reachedEndOfTextRenderer(const BidiRunList<BidiRun>& bidiRuns)
+{
+    BidiRun* run = bidiRuns.logicallyLastRun();
+    if (!run)
+        return true;
+    unsigned pos = run->stop();
+    RenderObject* r = run->m_object;
+    if (!r->isText() || r->isBR())
+        return false;
+    RenderText* renderText = toRenderText(r);
+    unsigned length = renderText->textLength();
+    if (pos >= length)
+        return true;
+
+    if (renderText->is8Bit())
+        return endsWithASCIISpaces(renderText->characters8(), pos, length);
+    return endsWithASCIISpaces(renderText->characters16(), pos, length);
+}
+
+RootInlineBox* RenderBlock::constructLine(BidiRunList<BidiRun>& bidiRuns, const LineInfo& lineInfo)
+{
+    ASSERT(bidiRuns.firstRun());
+
+    bool rootHasSelectedChildren = false;
+    InlineFlowBox* parentBox = 0;
+    int runCount = bidiRuns.runCount() - lineInfo.runsFromLeadingWhitespace();
+    for (BidiRun* r = bidiRuns.firstRun(); r; r = r->next()) {
+        // Create a box for our object.
+        bool isOnlyRun = (runCount == 1);
+        if (runCount == 2 && !r->m_object->isListMarker())
+            isOnlyRun = (!style()->isLeftToRightDirection() ? bidiRuns.lastRun() : bidiRuns.firstRun())->m_object->isListMarker();
+
+        if (lineInfo.isEmpty())
+            continue;
+
+        InlineBox* box = createInlineBoxForRenderer(r->m_object, false, isOnlyRun);
+        r->m_box = box;
+
+        ASSERT(box);
+        if (!box)
+            continue;
+
+        if (!rootHasSelectedChildren && box->renderer()->selectionState() != RenderObject::SelectionNone)
+            rootHasSelectedChildren = true;
+
+        // 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. Segments can only be siblings at the root level, as
+        // they are positioned separately.
+        bool runStartsSegment = r->m_startsSegment;
+
+        if (!parentBox || parentBox->renderer() != r->m_object->parent() || runStartsSegment)
+            // Create new inline boxes all the way back to the appropriate insertion point.
+            parentBox = createLineBoxes(r->m_object->parent(), lineInfo, box, runStartsSegment);
+        else {
+            // Append the inline box to this line.
+            parentBox->addToLine(box);
+        }
+
+        bool visuallyOrdered = r->m_object->style()->rtlOrdering() == VisualOrder;
+        box->setBidiLevel(r->level());
+
+        if (box->isInlineTextBox()) {
+            InlineTextBox* text = toInlineTextBox(box);
+            text->setStart(r->m_start);
+            text->setLen(r->m_stop - r->m_start);
+            text->setDirOverride(r->dirOverride(visuallyOrdered));
+            if (r->m_hasHyphen)
+                text->setHasHyphen(true);
+        }
+    }
+
+    // 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 the m_selectedChildren flag on the root inline box if one of the leaf inline box
+    // from the bidi runs walk above has a selection state.
+    if (rootHasSelectedChildren)
+        lastLineBox()->root()->setHasSelectedChildren(true);
+
+    // 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.
+    bool isLogicallyLastRunWrapped = bidiRuns.logicallyLastRun()->m_object && bidiRuns.logicallyLastRun()->m_object->isText() ? !reachedEndOfTextRenderer(bidiRuns) : true;
+    lastLineBox()->determineSpacingForFlowBoxes(lineInfo.isLastLine(), isLogicallyLastRunWrapped, bidiRuns.logicallyLastRun()->m_object);
+
+    // Now mark the line boxes as being constructed.
+    lastLineBox()->setConstructed();
+
+    // Return the last line.
+    return lastRootBox();
+}
+
+ETextAlign RenderBlock::textAlignmentForLine(bool endsWithSoftBreak) const
+{
+    ETextAlign alignment = style()->textAlign();
+    if (!endsWithSoftBreak && alignment == JUSTIFY)
+        alignment = TASTART;
+
+    return alignment;
+}
+
+static void updateLogicalWidthForLeftAlignedBlock(bool isLeftToRightDirection, BidiRun* trailingSpaceRun, float& logicalLeft, float& totalLogicalWidth, float availableLogicalWidth)
+{
+    // 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 (isLeftToRightDirection) {
+        if (totalLogicalWidth > availableLogicalWidth && trailingSpaceRun)
+            trailingSpaceRun->m_box->setLogicalWidth(max<float>(0, trailingSpaceRun->m_box->logicalWidth() - totalLogicalWidth + availableLogicalWidth));
+        return;
+    }
+
+    if (trailingSpaceRun)
+        trailingSpaceRun->m_box->setLogicalWidth(0);
+    else if (totalLogicalWidth > availableLogicalWidth)
+        logicalLeft -= (totalLogicalWidth - availableLogicalWidth);
+}
+
+static void updateLogicalWidthForRightAlignedBlock(bool isLeftToRightDirection, BidiRun* trailingSpaceRun, float& logicalLeft, float& totalLogicalWidth, float availableLogicalWidth)
+{
+    // 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 (isLeftToRightDirection) {
+        if (trailingSpaceRun) {
+            totalLogicalWidth -= trailingSpaceRun->m_box->logicalWidth();
+            trailingSpaceRun->m_box->setLogicalWidth(0);
+        }
+        if (totalLogicalWidth < availableLogicalWidth)
+            logicalLeft += availableLogicalWidth - totalLogicalWidth;
+        return;
+    }
+
+    if (totalLogicalWidth > availableLogicalWidth && trailingSpaceRun) {
+        trailingSpaceRun->m_box->setLogicalWidth(max<float>(0, trailingSpaceRun->m_box->logicalWidth() - totalLogicalWidth + availableLogicalWidth));
+        totalLogicalWidth -= trailingSpaceRun->m_box->logicalWidth();
+    } else
+        logicalLeft += availableLogicalWidth - totalLogicalWidth;
+}
+
+static void updateLogicalWidthForCenterAlignedBlock(bool isLeftToRightDirection, BidiRun* trailingSpaceRun, float& logicalLeft, float& totalLogicalWidth, float availableLogicalWidth)
+{
+    float trailingSpaceWidth = 0;
+    if (trailingSpaceRun) {
+        totalLogicalWidth -= trailingSpaceRun->m_box->logicalWidth();
+        trailingSpaceWidth = min(trailingSpaceRun->m_box->logicalWidth(), (availableLogicalWidth - totalLogicalWidth + 1) / 2);
+        trailingSpaceRun->m_box->setLogicalWidth(max<float>(0, trailingSpaceWidth));
+    }
+    if (isLeftToRightDirection)
+        logicalLeft += max<float>((availableLogicalWidth - totalLogicalWidth) / 2, 0);
+    else
+        logicalLeft += totalLogicalWidth > availableLogicalWidth ? (availableLogicalWidth - totalLogicalWidth) : (availableLogicalWidth - totalLogicalWidth) / 2 - trailingSpaceWidth;
+}
+
+void RenderBlock::setMarginsForRubyRun(BidiRun* run, RenderRubyRun* renderer, RenderObject* previousObject, const LineInfo& lineInfo)
+{
+    int startOverhang;
+    int endOverhang;
+    RenderObject* nextObject = 0;
+    for (BidiRun* runWithNextObject = run->next(); runWithNextObject; runWithNextObject = runWithNextObject->next()) {
+        if (!runWithNextObject->m_object->isOutOfFlowPositioned() && !runWithNextObject->m_box->isLineBreak()) {
+            nextObject = runWithNextObject->m_object;
+            break;
+        }
+    }
+    renderer->getOverhang(lineInfo.isFirstLine(), renderer->style()->isLeftToRightDirection() ? previousObject : nextObject, renderer->style()->isLeftToRightDirection() ? nextObject : previousObject, startOverhang, endOverhang);
+    setMarginStartForChild(renderer, -startOverhang);
+    setMarginEndForChild(renderer, -endOverhang);
+}
+
+static inline float measureHyphenWidth(RenderText* renderer, const Font& font)
+{
+    RenderStyle* style = renderer->style();
+    return font.width(RenderBlock::constructTextRun(renderer, font, style->hyphenString().string(), style));
+}
+
+class WordMeasurement {
+public:
+    WordMeasurement()
+        : renderer(0)
+        , width(0)
+        , startOffset(0)
+        , endOffset(0)
+    {
+    }
+    
+    RenderText* renderer;
+    float width;
+    int startOffset;
+    int endOffset;
+    HashSet<const SimpleFontData*> fallbackFonts;
+};
+
+static inline void setLogicalWidthForTextRun(RootInlineBox* lineBox, BidiRun* run, RenderText* renderer, float xPos, const LineInfo& lineInfo,
+                                             GlyphOverflowAndFallbackFontsMap& textBoxDataMap, VerticalPositionCache& verticalPositionCache, WordMeasurements& wordMeasurements)
+{
+    HashSet<const SimpleFontData*> fallbackFonts;
+    GlyphOverflow glyphOverflow;
+    
+    const Font& font = renderer->style(lineInfo.isFirstLine())->font();
+    // Always compute glyph overflow if the block's line-box-contain value is "glyphs".
+    if (lineBox->fitsToGlyphs()) {
+        // If we don't stick out of the root line's font box, then don't bother computing our glyph overflow. This optimization
+        // will keep us from computing glyph bounds in nearly all cases.
+        bool includeRootLine = lineBox->includesRootLineBoxFontOrLeading();
+        int baselineShift = lineBox->verticalPositionForBox(run->m_box, verticalPositionCache);
+        int rootDescent = includeRootLine ? font.fontMetrics().descent() : 0;
+        int rootAscent = includeRootLine ? font.fontMetrics().ascent() : 0;
+        int boxAscent = font.fontMetrics().ascent() - baselineShift;
+        int boxDescent = font.fontMetrics().descent() + baselineShift;
+        if (boxAscent > rootDescent ||  boxDescent > rootAscent)
+            glyphOverflow.computeBounds = true; 
+    }
+    
+    LayoutUnit hyphenWidth = 0;
+    if (toInlineTextBox(run->m_box)->hasHyphen()) {
+        const Font& font = renderer->style(lineInfo.isFirstLine())->font();
+        hyphenWidth = measureHyphenWidth(renderer, font);
+    }
+    float measuredWidth = 0;
+
+    bool kerningIsEnabled = font.typesettingFeatures() & Kerning;
+
+#if OS(DARWIN)
+    // FIXME: Having any font feature settings enabled can lead to selection gaps on
+    // Chromium-mac. https://bugs.webkit.org/show_bug.cgi?id=113418
+    bool canUseSimpleFontCodePath = renderer->canUseSimpleFontCodePath() && !font.fontDescription().featureSettings();
+#else
+    bool canUseSimpleFontCodePath = renderer->canUseSimpleFontCodePath();
+#endif
+    
+    // Since we don't cache glyph overflows, we need to re-measure the run if
+    // the style is linebox-contain: glyph.
+    
+    if (!lineBox->fitsToGlyphs() && canUseSimpleFontCodePath) {
+        int lastEndOffset = run->m_start;
+        for (size_t i = 0, size = wordMeasurements.size(); i < size && lastEndOffset < run->m_stop; ++i) {
+            const WordMeasurement& wordMeasurement = wordMeasurements[i];
+            if (wordMeasurement.width <=0 || wordMeasurement.startOffset == wordMeasurement.endOffset)
+                continue;
+            if (wordMeasurement.renderer != renderer || wordMeasurement.startOffset != lastEndOffset || wordMeasurement.endOffset > run->m_stop)
+                continue;
+
+            lastEndOffset = wordMeasurement.endOffset;
+            if (kerningIsEnabled && lastEndOffset == run->m_stop) {
+                int wordLength = lastEndOffset - wordMeasurement.startOffset;
+                measuredWidth += renderer->width(wordMeasurement.startOffset, wordLength, xPos, lineInfo.isFirstLine());
+                if (i > 0 && wordLength == 1 && renderer->characterAt(wordMeasurement.startOffset) == ' ')
+                    measuredWidth += renderer->style()->wordSpacing();
+            } else
+                measuredWidth += wordMeasurement.width;
+            if (!wordMeasurement.fallbackFonts.isEmpty()) {
+                HashSet<const SimpleFontData*>::const_iterator end = wordMeasurement.fallbackFonts.end();
+                for (HashSet<const SimpleFontData*>::const_iterator it = wordMeasurement.fallbackFonts.begin(); it != end; ++it)
+                    fallbackFonts.add(*it);
+            }
+        }
+        if (measuredWidth && lastEndOffset != run->m_stop) {
+            // If we don't have enough cached data, we'll measure the run again.
+            measuredWidth = 0;
+            fallbackFonts.clear();
+        }
+    }
+
+    if (!measuredWidth)
+        measuredWidth = renderer->width(run->m_start, run->m_stop - run->m_start, xPos, lineInfo.isFirstLine(), &fallbackFonts, &glyphOverflow);
+
+    run->m_box->setLogicalWidth(measuredWidth + hyphenWidth);
+    if (!fallbackFonts.isEmpty()) {
+        ASSERT(run->m_box->isText());
+        GlyphOverflowAndFallbackFontsMap::iterator it = textBoxDataMap.add(toInlineTextBox(run->m_box), make_pair(Vector<const SimpleFontData*>(), GlyphOverflow())).iterator;
+        ASSERT(it->value.first.isEmpty());
+        copyToVector(fallbackFonts, it->value.first);
+        run->m_box->parent()->clearDescendantsHaveSameLineHeightAndBaseline();
+    }
+    if ((glyphOverflow.top || glyphOverflow.bottom || glyphOverflow.left || glyphOverflow.right)) {
+        ASSERT(run->m_box->isText());
+        GlyphOverflowAndFallbackFontsMap::iterator it = textBoxDataMap.add(toInlineTextBox(run->m_box), make_pair(Vector<const SimpleFontData*>(), GlyphOverflow())).iterator;
+        it->value.second = glyphOverflow;
+        run->m_box->clearKnownToHaveNoOverflow();
+    }
+}
+
+static inline void computeExpansionForJustifiedText(BidiRun* firstRun, BidiRun* trailingSpaceRun, Vector<unsigned, 16>& expansionOpportunities, unsigned expansionOpportunityCount, float& totalLogicalWidth, float availableLogicalWidth)
+{
+    if (!expansionOpportunityCount || availableLogicalWidth <= totalLogicalWidth)
+        return;
+
+    size_t i = 0;
+    for (BidiRun* r = firstRun; r; r = r->next()) {
+        // This method is called once per segment, do not move past the current segment.
+        if (r->m_startsSegment)
+            break;
+        if (!r->m_box || r == trailingSpaceRun)
+            continue;
+        
+        if (r->m_object->isText()) {
+            unsigned opportunitiesInRun = expansionOpportunities[i++];
+            
+            ASSERT(opportunitiesInRun <= expansionOpportunityCount);
+            
+            // Only justify text if whitespace is collapsed.
+            if (r->m_object->style()->collapseWhiteSpace()) {
+                InlineTextBox* textBox = toInlineTextBox(r->m_box);
+                int expansion = (availableLogicalWidth - totalLogicalWidth) * opportunitiesInRun / expansionOpportunityCount;
+                textBox->setExpansion(expansion);
+                totalLogicalWidth += expansion;
+            }
+            expansionOpportunityCount -= opportunitiesInRun;
+            if (!expansionOpportunityCount)
+                break;
+        }
+    }
+}
+
+void RenderBlock::updateLogicalWidthForAlignment(const ETextAlign& textAlign, BidiRun* trailingSpaceRun, float& logicalLeft, float& totalLogicalWidth, float& availableLogicalWidth, int expansionOpportunityCount)
+{
+    // 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.
+    switch (textAlign) {
+    case LEFT:
+    case WEBKIT_LEFT:
+        updateLogicalWidthForLeftAlignedBlock(style()->isLeftToRightDirection(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
+        break;
+    case RIGHT:
+    case WEBKIT_RIGHT:
+        updateLogicalWidthForRightAlignedBlock(style()->isLeftToRightDirection(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
+        break;
+    case CENTER:
+    case WEBKIT_CENTER:
+        updateLogicalWidthForCenterAlignedBlock(style()->isLeftToRightDirection(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
+        break;
+    case JUSTIFY:
+        adjustInlineDirectionLineBounds(expansionOpportunityCount, logicalLeft, availableLogicalWidth);
+        if (expansionOpportunityCount) {
+            if (trailingSpaceRun) {
+                totalLogicalWidth -= trailingSpaceRun->m_box->logicalWidth();
+                trailingSpaceRun->m_box->setLogicalWidth(0);
+            }
+            break;
+        }
+        // Fall through
+    case TASTART:
+        if (style()->isLeftToRightDirection())
+            updateLogicalWidthForLeftAlignedBlock(style()->isLeftToRightDirection(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
+        else
+            updateLogicalWidthForRightAlignedBlock(style()->isLeftToRightDirection(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
+        break;
+    case TAEND:
+        if (style()->isLeftToRightDirection())
+            updateLogicalWidthForRightAlignedBlock(style()->isLeftToRightDirection(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
+        else
+            updateLogicalWidthForLeftAlignedBlock(style()->isLeftToRightDirection(), trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth);
+        break;
+    }
+}
+
+static IndentTextOrNot requiresIndent(bool isFirstLine, bool isAfterHardLineBreak, RenderStyle* style)
+{
+    if (isFirstLine)
+        return IndentText;
+#if ENABLE(CSS3_TEXT)
+    if (isAfterHardLineBreak && style->textIndentLine() == TextIndentEachLine)
+        return IndentText;
+#else
+    UNUSED_PARAM(isAfterHardLineBreak);
+    UNUSED_PARAM(style);
+#endif
+    return DoNotIndentText;
+}
+
+static void updateLogicalInlinePositions(RenderBlock* block, float& lineLogicalLeft, float& lineLogicalRight, float& availableLogicalWidth, bool firstLine, IndentTextOrNot shouldIndentText, LayoutUnit boxLogicalHeight)
+{
+    LayoutUnit lineLogicalHeight = logicalHeightForLine(block, firstLine, boxLogicalHeight);
+    lineLogicalLeft = block->pixelSnappedLogicalLeftOffsetForLine(block->logicalHeight(), shouldIndentText == IndentText, lineLogicalHeight);
+    lineLogicalRight = block->pixelSnappedLogicalRightOffsetForLine(block->logicalHeight(), shouldIndentText == IndentText, lineLogicalHeight);
+    availableLogicalWidth = lineLogicalRight - lineLogicalLeft;
+}
+
+void RenderBlock::computeInlineDirectionPositionsForLine(RootInlineBox* lineBox, const LineInfo& lineInfo, BidiRun* firstRun, BidiRun* trailingSpaceRun, bool reachedEnd,
+                                                         GlyphOverflowAndFallbackFontsMap& textBoxDataMap, VerticalPositionCache& verticalPositionCache, WordMeasurements& wordMeasurements)
+{
+    ETextAlign textAlign = textAlignmentForLine(!reachedEnd && !lineBox->endsWithBreak());
+
+    // CSS 2.1: "'Text-indent' only affects a line if it is the first formatted line of an element. For example, the first line of an anonymous block
+    // box is only affected if it is the first child of its parent element."
+    // CSS3 "text-indent", "-webkit-each-line" affects the first line of the block container as well as each line after a forced line break,
+    // but does not affect lines after a soft wrap break.
+    bool isFirstLine = lineInfo.isFirstLine() && !(isAnonymousBlock() && parent()->firstChild() != this);
+    bool isAfterHardLineBreak = lineBox->prevRootBox() && lineBox->prevRootBox()->endsWithBreak();
+    IndentTextOrNot shouldIndentText = requiresIndent(isFirstLine, isAfterHardLineBreak, style());
+    float lineLogicalLeft;
+    float lineLogicalRight;
+    float availableLogicalWidth;
+    updateLogicalInlinePositions(this, lineLogicalLeft, lineLogicalRight, availableLogicalWidth, isFirstLine, shouldIndentText, 0);
+    bool needsWordSpacing;
+    ExclusionShapeInsideInfo* exclusionShapeInsideInfo = layoutExclusionShapeInsideInfo();
+    if (exclusionShapeInsideInfo && exclusionShapeInsideInfo->hasSegments()) {
+        BidiRun* segmentStart = firstRun;
+        const SegmentList& segments = exclusionShapeInsideInfo->segments();
+        float logicalLeft = max<float>(roundToInt(segments[0].logicalLeft), lineLogicalLeft);
+        float logicalRight = min<float>(floorToInt(segments[0].logicalRight), lineLogicalRight);
+        float startLogicalLeft = logicalLeft;
+        float endLogicalRight = logicalLeft;
+        float minLogicalLeft = logicalLeft;
+        float maxLogicalRight = logicalLeft;
+        lineBox->beginPlacingBoxRangesInInlineDirection(logicalLeft);
+        for (size_t i = 0; i < segments.size(); i++) {
+            if (i) {
+                logicalLeft = max<float>(roundToInt(segments[i].logicalLeft), lineLogicalLeft);
+                logicalRight = min<float>(floorToInt(segments[i].logicalRight), lineLogicalRight);
+            }
+            availableLogicalWidth = logicalRight - logicalLeft;
+            BidiRun* newSegmentStart = computeInlineDirectionPositionsForSegment(lineBox, lineInfo, textAlign, logicalLeft, availableLogicalWidth, segmentStart, trailingSpaceRun, textBoxDataMap, verticalPositionCache, wordMeasurements);
+            needsWordSpacing = false;
+            endLogicalRight = lineBox->placeBoxRangeInInlineDirection(segmentStart->m_box, newSegmentStart ? newSegmentStart->m_box : 0, logicalLeft, minLogicalLeft, maxLogicalRight, needsWordSpacing, textBoxDataMap);
+            if (!newSegmentStart || !newSegmentStart->next())
+                break;
+            ASSERT(newSegmentStart->m_startsSegment);
+            // Discard the empty segment start marker bidi runs
+            segmentStart = newSegmentStart->next();
+        }
+        lineBox->endPlacingBoxRangesInInlineDirection(startLogicalLeft, endLogicalRight, minLogicalLeft, maxLogicalRight);
+        return;
+    }
+
+    if (firstRun && firstRun->m_object->isReplaced()) {
+        RenderBox* renderBox = toRenderBox(firstRun->m_object);
+        updateLogicalInlinePositions(this, lineLogicalLeft, lineLogicalRight, availableLogicalWidth, isFirstLine, shouldIndentText, renderBox->logicalHeight());
+    }
+
+    computeInlineDirectionPositionsForSegment(lineBox, lineInfo, textAlign, lineLogicalLeft, availableLogicalWidth, firstRun, trailingSpaceRun, textBoxDataMap, verticalPositionCache, wordMeasurements);
+    // The widths of all runs are now known. We can now place every inline box (and
+    // compute accurate widths for the inline flow boxes).
+    needsWordSpacing = false;
+    lineBox->placeBoxesInInlineDirection(lineLogicalLeft, needsWordSpacing, textBoxDataMap);
+}
+
+BidiRun* RenderBlock::computeInlineDirectionPositionsForSegment(RootInlineBox* lineBox, const LineInfo& lineInfo, ETextAlign textAlign, float& logicalLeft, 
+    float& availableLogicalWidth, BidiRun* firstRun, BidiRun* trailingSpaceRun, GlyphOverflowAndFallbackFontsMap& textBoxDataMap, VerticalPositionCache& verticalPositionCache,
+    WordMeasurements& wordMeasurements)
+{
+    bool needsWordSpacing = false;
+    float totalLogicalWidth = lineBox->getFlowSpacingLogicalWidth();
+    unsigned expansionOpportunityCount = 0;
+    bool isAfterExpansion = true;
+    Vector<unsigned, 16> expansionOpportunities;
+    RenderObject* previousObject = 0;
+
+    BidiRun* r = firstRun;
+    for (; r; r = r->next()) {
+        // Once we have reached the start of the next segment, we have finished
+        // computing the positions for this segment's contents.
+        if (r->m_startsSegment)
+            break;
+        if (!r->m_box || r->m_object->isOutOfFlowPositioned() || 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 = toRenderText(r->m_object);
+            if (textAlign == JUSTIFY && r != trailingSpaceRun) {
+                if (!isAfterExpansion)
+                    toInlineTextBox(r->m_box)->setCanHaveLeadingExpansion(true);
+                unsigned opportunitiesInRun;
+                if (rt->is8Bit())
+                    opportunitiesInRun = Font::expansionOpportunityCount(rt->characters8() + r->m_start, r->m_stop - r->m_start, r->m_box->direction(), isAfterExpansion);
+                else
+                    opportunitiesInRun = Font::expansionOpportunityCount(rt->characters16() + r->m_start, r->m_stop - r->m_start, r->m_box->direction(), isAfterExpansion);
+                expansionOpportunities.append(opportunitiesInRun);
+                expansionOpportunityCount += opportunitiesInRun;
+            }
+
+            if (int length = rt->textLength()) {
+                if (!r->m_start && needsWordSpacing && isSpaceOrNewline(rt->characterAt(r->m_start)))
+                    totalLogicalWidth += rt->style(lineInfo.isFirstLine())->font().wordSpacing();
+                needsWordSpacing = !isSpaceOrNewline(rt->characterAt(r->m_stop - 1)) && r->m_stop == length;
+            }
+
+            setLogicalWidthForTextRun(lineBox, r, rt, totalLogicalWidth, lineInfo, textBoxDataMap, verticalPositionCache, wordMeasurements);
+        } else {
+            isAfterExpansion = false;
+            if (!r->m_object->isRenderInline()) {
+                RenderBox* renderBox = toRenderBox(r->m_object);
+                if (renderBox->isRubyRun())
+                    setMarginsForRubyRun(r, toRenderRubyRun(renderBox), previousObject, lineInfo);
+                r->m_box->setLogicalWidth(logicalWidthForChild(renderBox));
+                totalLogicalWidth += marginStartForChild(renderBox) + marginEndForChild(renderBox);
+            }
+        }
+
+        totalLogicalWidth += r->m_box->logicalWidth();
+        previousObject = r->m_object;
+    }
+
+    if (isAfterExpansion && !expansionOpportunities.isEmpty()) {
+        expansionOpportunities.last()--;
+        expansionOpportunityCount--;
+    }
+
+    updateLogicalWidthForAlignment(textAlign, trailingSpaceRun, logicalLeft, totalLogicalWidth, availableLogicalWidth, expansionOpportunityCount);
+
+    computeExpansionForJustifiedText(firstRun, trailingSpaceRun, expansionOpportunities, expansionOpportunityCount, totalLogicalWidth, availableLogicalWidth);
+
+    return r;
+}
+
+void RenderBlock::computeBlockDirectionPositionsForLine(RootInlineBox* lineBox, BidiRun* firstRun, GlyphOverflowAndFallbackFontsMap& textBoxDataMap,
+                                                        VerticalPositionCache& verticalPositionCache)
+{
+    setLogicalHeight(lineBox->alignBoxesInBlockDirection(logicalHeight(), textBoxDataMap, verticalPositionCache));
+
+    // Now make sure we place replaced render objects correctly.
+    for (BidiRun* r = firstRun; r; r = r->next()) {
+        ASSERT(r->m_box);
+        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->isOutOfFlowPositioned())
+            r->m_box->setLogicalTop(logicalHeight());
+
+        // Position is used to properly position both replaced elements and
+        // to update the static normal flow x/y of positioned elements.
+        if (r->m_object->isText())
+            toRenderText(r->m_object)->positionLineBox(r->m_box);
+        else if (r->m_object->isBox())
+            toRenderBox(r->m_object)->positionLineBox(r->m_box);
+    }
+    // Positioned objects and zero-length text nodes destroy their boxes in
+    // position(), which unnecessarily dirties the line.
+    lineBox->markDirty(false);
+}
+
+static inline bool isCollapsibleSpace(UChar character, RenderText* renderer)
+{
+    if (character == ' ' || character == '\t' || character == softHyphen)
+        return true;
+    if (character == '\n')
+        return !renderer->style()->preserveNewline();
+    return false;
+}
+
+
+static void setStaticPositions(RenderBlock* block, RenderBox* child)
+{
+    // FIXME: The math here is actually not really right. It's a best-guess approximation that
+    // will work for the common cases
+    RenderObject* containerBlock = child->container();
+    LayoutUnit blockHeight = block->logicalHeight();
+    if (containerBlock->isRenderInline()) {
+        // A relative positioned inline encloses us. In this case, we also have to determine our
+        // position as though we were an inline. Set |staticInlinePosition| and |staticBlockPosition| on the relative positioned
+        // inline so that we can obtain the value later.
+        toRenderInline(containerBlock)->layer()->setStaticInlinePosition(block->startAlignedOffsetForLine(blockHeight, false));
+        toRenderInline(containerBlock)->layer()->setStaticBlockPosition(blockHeight);
+    }
+    block->updateStaticInlinePositionForChild(child, blockHeight);
+    child->layer()->setStaticBlockPosition(blockHeight);
+}
+
+template <typename CharacterType>
+static inline int findFirstTrailingSpace(RenderText* lastText, const CharacterType* characters, int start, int stop)
+{
+    int firstSpace = stop;
+    while (firstSpace > start) {
+        UChar current = characters[firstSpace - 1];
+        if (!isCollapsibleSpace(current, lastText))
+            break;
+        firstSpace--;
+    }
+
+    return firstSpace;
+}
+
+inline BidiRun* RenderBlock::handleTrailingSpaces(BidiRunList<BidiRun>& bidiRuns, BidiContext* currentContext)
+{
+    if (!bidiRuns.runCount()
+        || !bidiRuns.logicallyLastRun()->m_object->style()->breakOnlyAfterWhiteSpace()
+        || !bidiRuns.logicallyLastRun()->m_object->style()->autoWrap())
+        return 0;
+
+    BidiRun* trailingSpaceRun = bidiRuns.logicallyLastRun();
+    RenderObject* lastObject = trailingSpaceRun->m_object;
+    if (!lastObject->isText())
+        return 0;
+
+    RenderText* lastText = toRenderText(lastObject);
+    int firstSpace;
+    if (lastText->is8Bit())
+        firstSpace = findFirstTrailingSpace(lastText, lastText->characters8(), trailingSpaceRun->start(), trailingSpaceRun->stop());
+    else
+        firstSpace = findFirstTrailingSpace(lastText, lastText->characters16(), trailingSpaceRun->start(), trailingSpaceRun->stop());
+
+    if (firstSpace == trailingSpaceRun->stop())
+        return 0;
+
+    TextDirection direction = style()->direction();
+    bool shouldReorder = trailingSpaceRun != (direction == LTR ? bidiRuns.lastRun() : bidiRuns.firstRun());
+    if (firstSpace != trailingSpaceRun->start()) {
+        BidiContext* baseContext = currentContext;
+        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)
+            bidiRuns.addRun(newTrailingRun);
+        else
+            bidiRuns.prependRun(newTrailingRun);
+        trailingSpaceRun = newTrailingRun;
+        return trailingSpaceRun;
+    }
+    if (!shouldReorder)
+        return trailingSpaceRun;
+
+    if (direction == LTR) {
+        bidiRuns.moveRunToEnd(trailingSpaceRun);
+        trailingSpaceRun->m_level = 0;
+    } else {
+        bidiRuns.moveRunToBeginning(trailingSpaceRun);
+        trailingSpaceRun->m_level = 1;
+    }
+    return trailingSpaceRun;
+}
+
+void RenderBlock::appendFloatingObjectToLastLine(FloatingObject* floatingObject)
+{
+    ASSERT(!floatingObject->m_originatingLine);
+    floatingObject->m_originatingLine = lastRootBox();
+    lastRootBox()->appendFloat(floatingObject->renderer());
+}
+
+// FIXME: This should be a BidiStatus constructor or create method.
+static inline BidiStatus statusWithDirection(TextDirection textDirection, bool isOverride)
+{
+    WTF::Unicode::Direction direction = textDirection == LTR ? LeftToRight : RightToLeft;
+    RefPtr<BidiContext> context = BidiContext::create(textDirection == LTR ? 0 : 1, direction, isOverride, FromStyleOrDOM);
+
+    // This copies BidiStatus and may churn the ref on BidiContext. I doubt it matters.
+    return BidiStatus(direction, direction, direction, context.release());
+}
+
+// FIXME: BidiResolver should have this logic.
+static inline void constructBidiRunsForSegment(InlineBidiResolver& topResolver, BidiRunList<BidiRun>& bidiRuns, const InlineIterator& endOfRuns, VisualDirectionOverride override, bool previousLineBrokeCleanly)
+{
+    // FIXME: We should pass a BidiRunList into createBidiRunsForLine instead
+    // of the resolver owning the runs.
+    ASSERT(&topResolver.runs() == &bidiRuns);
+    RenderObject* currentRoot = topResolver.position().root();
+    topResolver.createBidiRunsForLine(endOfRuns, override, previousLineBrokeCleanly);
+
+    while (!topResolver.isolatedRuns().isEmpty()) {
+        // It does not matter which order we resolve the runs as long as we resolve them all.
+        BidiRun* isolatedRun = topResolver.isolatedRuns().last();
+        topResolver.isolatedRuns().removeLast();
+
+        RenderObject* startObj = isolatedRun->object();
+
+        // Only inlines make sense with unicode-bidi: isolate (blocks are already isolated).
+        // FIXME: Because enterIsolate is not passed a RenderObject, we have to crawl up the
+        // tree to see which parent inline is the isolate. We could change enterIsolate
+        // to take a RenderObject and do this logic there, but that would be a layering
+        // violation for BidiResolver (which knows nothing about RenderObject).
+        RenderInline* isolatedInline = toRenderInline(containingIsolate(startObj, currentRoot));
+        InlineBidiResolver isolatedResolver;
+        EUnicodeBidi unicodeBidi = isolatedInline->style()->unicodeBidi();
+        TextDirection direction;
+        if (unicodeBidi == Plaintext)
+            determineDirectionality(direction, InlineIterator(isolatedInline, isolatedRun->object(), 0));
+        else {
+            ASSERT(unicodeBidi == Isolate || unicodeBidi == IsolateOverride);
+            direction = isolatedInline->style()->direction();
+        }
+        isolatedResolver.setStatus(statusWithDirection(direction, isOverride(unicodeBidi)));
+
+        // FIXME: The fact that we have to construct an Iterator here
+        // currently prevents this code from moving into BidiResolver.
+        if (!bidiFirstSkippingEmptyInlines(isolatedInline, &isolatedResolver))
+            continue;
+
+        // The starting position is the beginning of the first run within the isolate that was identified
+        // during the earlier call to createBidiRunsForLine. This can be but is not necessarily the
+        // first run within the isolate.
+        InlineIterator iter = InlineIterator(isolatedInline, startObj, isolatedRun->m_start);
+        isolatedResolver.setPositionIgnoringNestedIsolates(iter);
+
+        // We stop at the next end of line; we may re-enter this isolate in the next call to constructBidiRuns().
+        // FIXME: What should end and previousLineBrokeCleanly be?
+        // rniwa says previousLineBrokeCleanly is just a WinIE hack and could always be false here?
+        isolatedResolver.createBidiRunsForLine(endOfRuns, NoVisualOverride, previousLineBrokeCleanly);
+        // Note that we do not delete the runs from the resolver.
+        // We're not guaranteed to get any BidiRuns in the previous step. If we don't, we allow the placeholder
+        // itself to be turned into an InlineBox. We can't remove it here without potentially losing track of
+        // the logically last run.
+        if (isolatedResolver.runs().runCount())
+            bidiRuns.replaceRunWithRuns(isolatedRun, isolatedResolver.runs());
+
+        // If we encountered any nested isolate runs, just move them
+        // to the top resolver's list for later processing.
+        if (!isolatedResolver.isolatedRuns().isEmpty()) {
+            topResolver.isolatedRuns().append(isolatedResolver.isolatedRuns());
+            isolatedResolver.isolatedRuns().clear();
+        }
+    }
+}
+
+static inline void constructBidiRunsForLine(const RenderBlock* block, InlineBidiResolver& topResolver, BidiRunList<BidiRun>& bidiRuns, const InlineIterator& endOfLine, VisualDirectionOverride override, bool previousLineBrokeCleanly)
+{
+    ExclusionShapeInsideInfo* exclusionShapeInsideInfo = block->layoutExclusionShapeInsideInfo();
+    if (!exclusionShapeInsideInfo || !exclusionShapeInsideInfo->hasSegments()) {
+        constructBidiRunsForSegment(topResolver, bidiRuns, endOfLine, override, previousLineBrokeCleanly);
+        return;
+    }
+
+    const SegmentRangeList& segmentRanges = exclusionShapeInsideInfo->segmentRanges();
+    ASSERT(segmentRanges.size());
+
+    for (size_t i = 0; i < segmentRanges.size(); i++) {
+        LineSegmentIterator iterator = segmentRanges[i].start;
+        InlineIterator segmentStart(iterator.root, iterator.object, iterator.offset);
+        iterator = segmentRanges[i].end;
+        InlineIterator segmentEnd(iterator.root, iterator.object, iterator.offset);
+        if (i) {
+            ASSERT(segmentStart.m_obj);
+            BidiRun* segmentMarker = createRun(segmentStart.m_pos, segmentStart.m_pos, segmentStart.m_obj, topResolver);
+            segmentMarker->m_startsSegment = true;
+            bidiRuns.addRun(segmentMarker);
+            // Do not collapse midpoints between segments
+            topResolver.midpointState().betweenMidpoints = false;
+        }
+        topResolver.setPosition(segmentStart, numberOfIsolateAncestors(segmentStart));
+        constructBidiRunsForSegment(topResolver, bidiRuns, segmentEnd, override, previousLineBrokeCleanly);
+    }
+}
+
+// This function constructs line boxes for all of the text runs in the resolver and computes their position.
+RootInlineBox* RenderBlock::createLineBoxesFromBidiRuns(BidiRunList<BidiRun>& bidiRuns, const InlineIterator& end, LineInfo& lineInfo, VerticalPositionCache& verticalPositionCache, BidiRun* trailingSpaceRun, WordMeasurements& wordMeasurements)
+{
+    if (!bidiRuns.runCount())
+        return 0;
+
+    // FIXME: Why is this only done when we had runs?
+    lineInfo.setLastLine(!end.m_obj);
+
+    RootInlineBox* lineBox = constructLine(bidiRuns, lineInfo);
+    if (!lineBox)
+        return 0;
+
+    lineBox->setEndsWithBreak(lineInfo.previousLineBrokeCleanly());
+    
+#if ENABLE(SVG)
+    bool isSVGRootInlineBox = lineBox->isSVGRootInlineBox();
+#else
+    bool isSVGRootInlineBox = false;
+#endif
+    
+    GlyphOverflowAndFallbackFontsMap textBoxDataMap;
+    
+    // Now we position all of our text runs horizontally.
+    if (!isSVGRootInlineBox)
+        computeInlineDirectionPositionsForLine(lineBox, lineInfo, bidiRuns.firstRun(), trailingSpaceRun, end.atEnd(), textBoxDataMap, verticalPositionCache, wordMeasurements);
+    
+    // Now position our text runs vertically.
+    computeBlockDirectionPositionsForLine(lineBox, bidiRuns.firstRun(), textBoxDataMap, verticalPositionCache);
+    
+#if ENABLE(SVG)
+    // SVG text layout code computes vertical & horizontal positions on its own.
+    // Note that we still need to execute computeVerticalPositionsForLine() as
+    // it calls InlineTextBox::positionLineBox(), which tracks whether the box
+    // contains reversed text or not. If we wouldn't do that editing and thus
+    // text selection in RTL boxes would not work as expected.
+    if (isSVGRootInlineBox) {
+        ASSERT(isSVGText());
+        static_cast<SVGRootInlineBox*>(lineBox)->computePerCharacterLayoutInformation();
+    }
+#endif
+    
+    // Compute our overflow now.
+    lineBox->computeOverflow(lineBox->lineTop(), lineBox->lineBottom(), textBoxDataMap);
+
+    return lineBox;
+}
+
+// Like LayoutState for layout(), LineLayoutState keeps track of global information
+// during an entire linebox tree layout pass (aka layoutInlineChildren).
+class LineLayoutState {
+public:
+    LineLayoutState(bool fullLayout, LayoutUnit& repaintLogicalTop, LayoutUnit& repaintLogicalBottom, RenderFlowThread* flowThread)
+        : m_lastFloat(0)
+        , m_endLine(0)
+        , m_floatIndex(0)
+        , m_endLineLogicalTop(0)
+        , m_endLineMatched(false)
+        , m_checkForFloatsFromLastLine(false)
+        , m_isFullLayout(fullLayout)
+        , m_repaintLogicalTop(repaintLogicalTop)
+        , m_repaintLogicalBottom(repaintLogicalBottom)
+        , m_usesRepaintBounds(false)
+        , m_flowThread(flowThread)
+    { }
+
+    void markForFullLayout() { m_isFullLayout = true; }
+    bool isFullLayout() const { return m_isFullLayout; }
+
+    bool usesRepaintBounds() const { return m_usesRepaintBounds; }
+
+    void setRepaintRange(LayoutUnit logicalHeight)
+    { 
+        m_usesRepaintBounds = true;
+        m_repaintLogicalTop = m_repaintLogicalBottom = logicalHeight; 
+    }
+    
+    void updateRepaintRangeFromBox(RootInlineBox* box, LayoutUnit paginationDelta = 0)
+    {
+        m_usesRepaintBounds = true;
+        m_repaintLogicalTop = min(m_repaintLogicalTop, box->logicalTopVisualOverflow() + min<LayoutUnit>(paginationDelta, 0));
+        m_repaintLogicalBottom = max(m_repaintLogicalBottom, box->logicalBottomVisualOverflow() + max<LayoutUnit>(paginationDelta, 0));
+    }
+    
+    bool endLineMatched() const { return m_endLineMatched; }
+    void setEndLineMatched(bool endLineMatched) { m_endLineMatched = endLineMatched; }
+
+    bool checkForFloatsFromLastLine() const { return m_checkForFloatsFromLastLine; }
+    void setCheckForFloatsFromLastLine(bool check) { m_checkForFloatsFromLastLine = check; }
+
+    LineInfo& lineInfo() { return m_lineInfo; }
+    const LineInfo& lineInfo() const { return m_lineInfo; }
+
+    LayoutUnit endLineLogicalTop() const { return m_endLineLogicalTop; }
+    void setEndLineLogicalTop(LayoutUnit logicalTop) { m_endLineLogicalTop = logicalTop; }
+
+    RootInlineBox* endLine() const { return m_endLine; }
+    void setEndLine(RootInlineBox* line) { m_endLine = line; }
+
+    RenderBlock::FloatingObject* lastFloat() const { return m_lastFloat; }
+    void setLastFloat(RenderBlock::FloatingObject* lastFloat) { m_lastFloat = lastFloat; }
+
+    Vector<RenderBlock::FloatWithRect>& floats() { return m_floats; }
+    
+    unsigned floatIndex() const { return m_floatIndex; }
+    void setFloatIndex(unsigned floatIndex) { m_floatIndex = floatIndex; }
+    
+    RenderFlowThread* flowThread() const { return m_flowThread; }
+    void setFlowThread(RenderFlowThread* thread) { m_flowThread = thread; }
+
+private:
+    Vector<RenderBlock::FloatWithRect> m_floats;
+    RenderBlock::FloatingObject* m_lastFloat;
+    RootInlineBox* m_endLine;
+    LineInfo m_lineInfo;
+    unsigned m_floatIndex;
+    LayoutUnit m_endLineLogicalTop;
+    bool m_endLineMatched;
+    bool m_checkForFloatsFromLastLine;
+    
+    bool m_isFullLayout;
+
+    // FIXME: Should this be a range object instead of two ints?
+    LayoutUnit& m_repaintLogicalTop;
+    LayoutUnit& m_repaintLogicalBottom;
+
+    bool m_usesRepaintBounds;
+    
+    RenderFlowThread* m_flowThread;
+};
+
+static void deleteLineRange(LineLayoutState& layoutState, RenderArena* arena, RootInlineBox* startLine, RootInlineBox* stopLine = 0)
+{
+    RootInlineBox* boxToDelete = startLine;
+    while (boxToDelete && boxToDelete != stopLine) {
+        layoutState.updateRepaintRangeFromBox(boxToDelete);
+        // Note: deleteLineRange(renderArena(), firstRootBox()) is not identical to deleteLineBoxTree().
+        // deleteLineBoxTree uses nextLineBox() instead of nextRootBox() when traversing.
+        RootInlineBox* next = boxToDelete->nextRootBox();
+        boxToDelete->deleteLine(arena);
+        boxToDelete = next;
+    }
+}
+
+void RenderBlock::layoutRunsAndFloats(LineLayoutState& layoutState, bool hasInlineChild)
+{
+    // We want to skip ahead to the first dirty line
+    InlineBidiResolver resolver;
+    RootInlineBox* startLine = determineStartPosition(layoutState, resolver);
+
+    unsigned consecutiveHyphenatedLines = 0;
+    if (startLine) {
+        for (RootInlineBox* line = startLine->prevRootBox(); line && line->isHyphenated(); line = line->prevRootBox())
+            consecutiveHyphenatedLines++;
+    }
+
+    // FIXME: This would make more sense outside of this function, but since
+    // determineStartPosition can change the fullLayout flag we have to do this here. Failure to call
+    // determineStartPosition first will break fast/repaint/line-flow-with-floats-9.html.
+    if (layoutState.isFullLayout() && hasInlineChild && !selfNeedsLayout()) {
+        setNeedsLayout(true, MarkOnlyThis); // Mark as needing a full layout to force us to repaint.
+        RenderView* v = view();
+        if (v && !v->doingFullRepaint() && hasLayer()) {
+            // 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.
+            repaintUsingContainer(containerForRepaint(), pixelSnappedIntRect(layer()->repaintRect()));
+        }
+    }
+
+    if (containsFloats())
+        layoutState.setLastFloat(m_floatingObjects->set().last());
+
+    // 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;
+    if (!layoutState.isFullLayout() && startLine)
+        determineEndPosition(layoutState, startLine, cleanLineStart, cleanLineBidiStatus);
+
+    if (startLine) {
+        if (!layoutState.usesRepaintBounds())
+            layoutState.setRepaintRange(logicalHeight());
+        deleteLineRange(layoutState, renderArena(), startLine);
+    }
+
+    if (!layoutState.isFullLayout() && 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->renderer();
+            if (!lastObject->isBR())
+                lastObject = lastRootBox()->firstLeafChild()->renderer();
+            if (lastObject->isBR()) {
+                EClear clear = lastObject->style()->clear();
+                if (clear != CNONE)
+                    newLine(clear);
+            }
+        }
+    }
+
+    layoutRunsAndFloatsInRange(layoutState, resolver, cleanLineStart, cleanLineBidiStatus, consecutiveHyphenatedLines);
+    linkToEndLineIfNeeded(layoutState);
+    repaintDirtyFloats(layoutState.floats());
+}
+
+RenderBlock::RenderTextInfo::RenderTextInfo()
+    : m_text(0)
+    , m_font(0)
+{
+}
+
+RenderBlock::RenderTextInfo::~RenderTextInfo()
+{
+}
+
+// Before restarting the layout loop with a new logicalHeight, remove all floats that were added and reset the resolver.
+inline const InlineIterator& RenderBlock::restartLayoutRunsAndFloatsInRange(LayoutUnit oldLogicalHeight, LayoutUnit newLogicalHeight,  FloatingObject* lastFloatFromPreviousLine, InlineBidiResolver& resolver,  const InlineIterator& oldEnd)
+{
+    removeFloatingObjectsBelow(lastFloatFromPreviousLine, oldLogicalHeight);
+    setLogicalHeight(newLogicalHeight);
+    resolver.setPositionIgnoringNestedIsolates(oldEnd);
+    return oldEnd;
+}
+
+void RenderBlock::layoutRunsAndFloatsInRange(LineLayoutState& layoutState, InlineBidiResolver& resolver, const InlineIterator& cleanLineStart, const BidiStatus& cleanLineBidiStatus, unsigned consecutiveHyphenatedLines)
+{
+    RenderStyle* styleToUse = style();
+    bool paginated = view()->layoutState() && view()->layoutState()->isPaginated();
+    LineMidpointState& lineMidpointState = resolver.midpointState();
+    InlineIterator end = resolver.position();
+    bool checkForEndLineMatch = layoutState.endLine();
+    RenderTextInfo renderTextInfo;
+    VerticalPositionCache verticalPositionCache;
+
+    LineBreaker lineBreaker(this);
+
+    LayoutUnit absoluteLogicalTop;
+    ExclusionShapeInsideInfo* exclusionShapeInsideInfo = layoutExclusionShapeInsideInfo();
+    if (exclusionShapeInsideInfo) {
+        ASSERT(exclusionShapeInsideInfo->owner() == this || allowsExclusionShapeInsideInfoSharing());
+        if (exclusionShapeInsideInfo != this->exclusionShapeInsideInfo()) {
+            // FIXME Bug 100284: If subsequent LayoutStates are pushed, we will have to add
+            // their offsets from the original shape-inside container.
+            absoluteLogicalTop = logicalTop();
+        }
+        // Begin layout at the logical top of our shape inside.
+        if (logicalHeight() + absoluteLogicalTop < exclusionShapeInsideInfo->shapeLogicalTop())
+            setLogicalHeight(exclusionShapeInsideInfo->shapeLogicalTop() - absoluteLogicalTop);
+    }
+
+    if (layoutState.flowThread()) {
+        // In a flow thread we need to update absoluteLogicalTop in every run to match to the current logical top increased by the height of the current line to calculate the right values for the
+        // actual shape when a line is beginning in a new region which has a shape on it. Usecase: shape-inside is applied not on the first, but on either of the following regions in the region chain.
+        absoluteLogicalTop = logicalTop() + lineHeight(layoutState.lineInfo().isFirstLine(), isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes);
+    }
+
+    while (!end.atEnd()) {
+        // FIXME: Is this check necessary before the first iteration or can it be moved to the end?
+        if (checkForEndLineMatch) {
+            layoutState.setEndLineMatched(matchedEndLine(layoutState, resolver, cleanLineStart, cleanLineBidiStatus));
+            if (layoutState.endLineMatched()) {
+                resolver.setPosition(InlineIterator(resolver.position().root(), 0, 0), 0);
+                break;
+            }
+        }
+
+        lineMidpointState.reset();
+
+        layoutState.lineInfo().setEmpty(true);
+        layoutState.lineInfo().resetRunsFromLeadingWhitespace();
+
+        const InlineIterator oldEnd = end;
+        bool isNewUBAParagraph = layoutState.lineInfo().previousLineBrokeCleanly();
+        FloatingObject* lastFloatFromPreviousLine = (containsFloats()) ? m_floatingObjects->set().last() : 0;
+        // FIXME: Bug 95361: It is possible for a line to grow beyond lineHeight, in which
+        // case these segments may be incorrect.
+        if (layoutState.flowThread())
+            exclusionShapeInsideInfo = layoutExclusionShapeInsideInfo();
+        if (exclusionShapeInsideInfo) {
+            LayoutUnit lineTop = logicalHeight() + absoluteLogicalTop;
+            exclusionShapeInsideInfo->computeSegmentsForLine(lineTop, lineHeight(layoutState.lineInfo().isFirstLine(), isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes));
+        }
+        WordMeasurements wordMeasurements;
+        end = lineBreaker.nextLineBreak(resolver, layoutState.lineInfo(), renderTextInfo, lastFloatFromPreviousLine, consecutiveHyphenatedLines, wordMeasurements);
+        renderTextInfo.m_lineBreakIterator.resetPriorContext();
+        if (resolver.position().atEnd()) {
+            // FIXME: We shouldn't be creating any runs in nextLineBreak to begin with!
+            // Once BidiRunList is separated from BidiResolver this will not be needed.
+            resolver.runs().deleteRuns();
+            resolver.markCurrentRunEmpty(); // FIXME: This can probably be replaced by an ASSERT (or just removed).
+            layoutState.setCheckForFloatsFromLastLine(true);
+            resolver.setPosition(InlineIterator(resolver.position().root(), 0, 0), 0);
+            break;
+        }
+        ASSERT(end != resolver.position());
+
+        if (exclusionShapeInsideInfo && wordMeasurements.size() && exclusionShapeInsideInfo->adjustLogicalLineTop(wordMeasurements[0].width)) {
+            end = restartLayoutRunsAndFloatsInRange(logicalHeight(), exclusionShapeInsideInfo->logicalLineTop() - absoluteLogicalTop, lastFloatFromPreviousLine, resolver, oldEnd);
+            continue;
+        }
+
+        // This is a short-cut for empty lines.
+        if (layoutState.lineInfo().isEmpty()) {
+            if (lastRootBox())
+                lastRootBox()->setLineBreakInfo(end.m_obj, end.m_pos, resolver.status());
+        } else {
+            VisualDirectionOverride override = (styleToUse->rtlOrdering() == VisualOrder ? (styleToUse->direction() == LTR ? VisualLeftToRightOverride : VisualRightToLeftOverride) : NoVisualOverride);
+
+            if (isNewUBAParagraph && styleToUse->unicodeBidi() == Plaintext && !resolver.context()->parent()) {
+                TextDirection direction = styleToUse->direction();
+                determineDirectionality(direction, resolver.position());
+                resolver.setStatus(BidiStatus(direction, isOverride(styleToUse->unicodeBidi())));
+            }
+            // FIXME: This ownership is reversed. We should own the BidiRunList and pass it to createBidiRunsForLine.
+            BidiRunList<BidiRun>& bidiRuns = resolver.runs();
+            constructBidiRunsForLine(this, resolver, bidiRuns, end, override, layoutState.lineInfo().previousLineBrokeCleanly());
+            ASSERT(resolver.position() == end);
+
+            BidiRun* trailingSpaceRun = !layoutState.lineInfo().previousLineBrokeCleanly() ? handleTrailingSpaces(bidiRuns, resolver.context()) : 0;
+
+            if (bidiRuns.runCount() && lineBreaker.lineWasHyphenated()) {
+                bidiRuns.logicallyLastRun()->m_hasHyphen = true;
+                consecutiveHyphenatedLines++;
+            } else
+                consecutiveHyphenatedLines = 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.
+
+            LayoutUnit oldLogicalHeight = logicalHeight();
+            RootInlineBox* lineBox = createLineBoxesFromBidiRuns(bidiRuns, end, layoutState.lineInfo(), verticalPositionCache, trailingSpaceRun, wordMeasurements);
+
+            bidiRuns.deleteRuns();
+            resolver.markCurrentRunEmpty(); // FIXME: This can probably be replaced by an ASSERT (or just removed).
+
+            if (lineBox) {
+                lineBox->setLineBreakInfo(end.m_obj, end.m_pos, resolver.status());
+                if (layoutState.usesRepaintBounds())
+                    layoutState.updateRepaintRangeFromBox(lineBox);
+
+                if (paginated) {
+                    LayoutUnit adjustment = 0;
+                    adjustLinePositionForPagination(lineBox, adjustment, layoutState.flowThread());
+                    if (adjustment) {
+                        LayoutUnit oldLineWidth = availableLogicalWidthForLine(oldLogicalHeight, layoutState.lineInfo().isFirstLine());
+                        lineBox->adjustBlockDirectionPosition(adjustment);
+                        if (layoutState.usesRepaintBounds())
+                            layoutState.updateRepaintRangeFromBox(lineBox);
+
+                        if (availableLogicalWidthForLine(oldLogicalHeight + adjustment, layoutState.lineInfo().isFirstLine()) != oldLineWidth) {
+                            // We have to delete this line, remove all floats that got added, and let line layout re-run.
+                            lineBox->deleteLine(renderArena());
+                            end = restartLayoutRunsAndFloatsInRange(oldLogicalHeight, oldLogicalHeight + adjustment, lastFloatFromPreviousLine, resolver, oldEnd);
+                            continue;
+                        }
+
+                        setLogicalHeight(lineBox->lineBottomWithLeading());
+                    }
+
+                    if (layoutState.flowThread())
+                        lineBox->setContainingRegion(regionAtBlockOffset(lineBox->lineTopWithLeading()));
+                }
+            }
+        }
+
+        for (size_t i = 0; i < lineBreaker.positionedObjects().size(); ++i)
+            setStaticPositions(this, lineBreaker.positionedObjects()[i]);
+
+        if (!layoutState.lineInfo().isEmpty()) {
+            layoutState.lineInfo().setFirstLine(false);
+            newLine(lineBreaker.clear());
+        }
+
+        if (m_floatingObjects && lastRootBox()) {
+            const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
+            FloatingObjectSetIterator it = floatingObjectSet.begin();
+            FloatingObjectSetIterator end = floatingObjectSet.end();
+            if (layoutState.lastFloat()) {
+                FloatingObjectSetIterator lastFloatIterator = floatingObjectSet.find(layoutState.lastFloat());
+                ASSERT(lastFloatIterator != end);
+                ++lastFloatIterator;
+                it = lastFloatIterator;
+            }
+            for (; it != end; ++it) {
+                FloatingObject* f = *it;
+                appendFloatingObjectToLastLine(f);
+                ASSERT(f->m_renderer == layoutState.floats()[layoutState.floatIndex()].object);
+                // If a float's geometry has changed, give up on syncing with clean lines.
+                if (layoutState.floats()[layoutState.floatIndex()].rect != f->frameRect())
+                    checkForEndLineMatch = false;
+                layoutState.setFloatIndex(layoutState.floatIndex() + 1);
+            }
+            layoutState.setLastFloat(!floatingObjectSet.isEmpty() ? floatingObjectSet.last() : 0);
+        }
+
+        lineMidpointState.reset();
+        resolver.setPosition(end, numberOfIsolateAncestors(end));
+    }
+
+    if (paginated && !style()->hasAutoWidows()) {
+        // Check the line boxes to make sure we didn't create unacceptable widows.
+        // However, we'll prioritize orphans - so nothing we do here should create
+        // a new orphan.
+
+        RootInlineBox* lineBox = lastRootBox();
+
+        // Count from the end of the block backwards, to see how many hanging
+        // lines we have.
+        RootInlineBox* firstLineInBlock = firstRootBox();
+        int numLinesHanging = 1;
+        while (lineBox && lineBox != firstLineInBlock && !lineBox->isFirstAfterPageBreak()) {
+            ++numLinesHanging;
+            lineBox = lineBox->prevRootBox();
+        }
+
+        // If there were no breaks in the block, we didn't create any widows.
+        if (!lineBox || !lineBox->isFirstAfterPageBreak() || lineBox == firstLineInBlock)
+            return;
+
+        if (numLinesHanging < style()->widows()) {
+            // We have detected a widow. Now we need to work out how many
+            // lines there are on the previous page, and how many we need
+            // to steal.
+            int numLinesNeeded = style()->widows() - numLinesHanging;
+            RootInlineBox* currentFirstLineOfNewPage = lineBox;
+
+            // Count the number of lines in the previous page.
+            lineBox = lineBox->prevRootBox();
+            int numLinesInPreviousPage = 1;
+            while (lineBox && lineBox != firstLineInBlock && !lineBox->isFirstAfterPageBreak()) {
+                ++numLinesInPreviousPage;
+                lineBox = lineBox->prevRootBox();
+            }
+
+            // If there was an explicit value for orphans, respect that. If not, we still
+            // shouldn't create a situation where we make an orphan bigger than the initial value.
+            // This means that setting widows implies we also care about orphans, but given
+            // the specification says the initial orphan value is non-zero, this is ok. The
+            // author is always free to set orphans explicitly as well.
+            int orphans = style()->hasAutoOrphans() ? style()->initialOrphans() : style()->orphans();
+            int numLinesAvailable = numLinesInPreviousPage - orphans;
+            if (numLinesAvailable <= 0)
+                return;
+
+            int numLinesToTake = min(numLinesAvailable, numLinesNeeded);
+            // Wind back from our first widowed line.
+            lineBox = currentFirstLineOfNewPage;
+            for (int i = 0; i < numLinesToTake; ++i)
+                lineBox = lineBox->prevRootBox();
+
+            // We now want to break at this line. Remember for next layout and trigger relayout.
+            setBreakAtLineToAvoidWidow(lineBox);
+            markLinesDirtyInBlockRange(lastRootBox()->lineBottomWithLeading(), lineBox->lineBottomWithLeading(), lineBox);
+        }
+    }
+}
+
+void RenderBlock::linkToEndLineIfNeeded(LineLayoutState& layoutState)
+{
+    if (layoutState.endLine()) {
+        if (layoutState.endLineMatched()) {
+            bool paginated = view()->layoutState() && view()->layoutState()->isPaginated();
+            // Attach all the remaining lines, and then adjust their y-positions as needed.
+            LayoutUnit delta = logicalHeight() - layoutState.endLineLogicalTop();
+            for (RootInlineBox* line = layoutState.endLine(); line; line = line->nextRootBox()) {
+                line->attachLine();
+                if (paginated) {
+                    delta -= line->paginationStrut();
+                    adjustLinePositionForPagination(line, delta, layoutState.flowThread());
+                }
+                if (delta) {
+                    layoutState.updateRepaintRangeFromBox(line, delta);
+                    line->adjustBlockDirectionPosition(delta);
+                }
+                if (layoutState.flowThread())
+                    line->setContainingRegion(regionAtBlockOffset(line->lineTopWithLeading()));
+                if (Vector<RenderBox*>* cleanLineFloats = line->floatsPtr()) {
+                    Vector<RenderBox*>::iterator end = cleanLineFloats->end();
+                    for (Vector<RenderBox*>::iterator f = cleanLineFloats->begin(); f != end; ++f) {
+                        FloatingObject* floatingObject = insertFloatingObject(*f);
+                        ASSERT(!floatingObject->m_originatingLine);
+                        floatingObject->m_originatingLine = line;
+                        setLogicalHeight(logicalTopForChild(*f) - marginBeforeForChild(*f) + delta);
+                        positionNewFloats();
+                    }
+                }
+            }
+            setLogicalHeight(lastRootBox()->lineBottomWithLeading());
+        } else {
+            // Delete all the remaining lines.
+            deleteLineRange(layoutState, renderArena(), layoutState.endLine());
+        }
+    }
+    
+    if (m_floatingObjects && (layoutState.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 (layoutState.checkForFloatsFromLastLine()) {
+            LayoutUnit bottomVisualOverflow = lastRootBox()->logicalBottomVisualOverflow();
+            LayoutUnit bottomLayoutOverflow = lastRootBox()->logicalBottomLayoutOverflow();
+            TrailingFloatsRootInlineBox* trailingFloatsLineBox = new (renderArena()) TrailingFloatsRootInlineBox(this);
+            m_lineBoxes.appendLineBox(trailingFloatsLineBox);
+            trailingFloatsLineBox->setConstructed();
+            GlyphOverflowAndFallbackFontsMap textBoxDataMap;
+            VerticalPositionCache verticalPositionCache;
+            LayoutUnit blockLogicalHeight = logicalHeight();
+            trailingFloatsLineBox->alignBoxesInBlockDirection(blockLogicalHeight, textBoxDataMap, verticalPositionCache);
+            trailingFloatsLineBox->setLineTopBottomPositions(blockLogicalHeight, blockLogicalHeight, blockLogicalHeight, blockLogicalHeight);
+            trailingFloatsLineBox->setPaginatedLineWidth(availableLogicalWidthForContent(blockLogicalHeight));
+            LayoutRect logicalLayoutOverflow(0, blockLogicalHeight, 1, bottomLayoutOverflow - blockLogicalHeight);
+            LayoutRect logicalVisualOverflow(0, blockLogicalHeight, 1, bottomVisualOverflow - blockLogicalHeight);
+            trailingFloatsLineBox->setOverflowFromLogicalRects(logicalLayoutOverflow, logicalVisualOverflow, trailingFloatsLineBox->lineTop(), trailingFloatsLineBox->lineBottom());
+            if (layoutState.flowThread())
+                trailingFloatsLineBox->setContainingRegion(regionAtBlockOffset(trailingFloatsLineBox->lineTopWithLeading()));
+        }
+
+        const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
+        FloatingObjectSetIterator it = floatingObjectSet.begin();
+        FloatingObjectSetIterator end = floatingObjectSet.end();
+        if (layoutState.lastFloat()) {
+            FloatingObjectSetIterator lastFloatIterator = floatingObjectSet.find(layoutState.lastFloat());
+            ASSERT(lastFloatIterator != end);
+            ++lastFloatIterator;
+            it = lastFloatIterator;
+        }
+        for (; it != end; ++it)
+            appendFloatingObjectToLastLine(*it);
+        layoutState.setLastFloat(!floatingObjectSet.isEmpty() ? floatingObjectSet.last() : 0);
+    }
+}
+
+void RenderBlock::repaintDirtyFloats(Vector<FloatWithRect>& floats)
+{
+    size_t floatCount = floats.size();
+    // Floats that did not have layout did not repaint when we laid them out. They would have
+    // painted by now if they had moved, but if they stayed at (0, 0), they still need to be
+    // painted.
+    for (size_t i = 0; i < floatCount; ++i) {
+        if (!floats[i].everHadLayout) {
+            RenderBox* f = floats[i].object;
+            if (!f->x() && !f->y() && f->checkForRepaintDuringLayout())
+                f->repaint();
+        }
+    }
+}
+
+void RenderBlock::layoutInlineChildren(bool relayoutChildren, LayoutUnit& repaintLogicalTop, LayoutUnit& repaintLogicalBottom)
+{
+    setLogicalHeight(borderBefore() + paddingBefore());
+    
+    // Lay out our hypothetical grid line as though it occurs at the top of the block.
+    if (view()->layoutState() && view()->layoutState()->lineGrid() == this)
+        layoutLineGridBox();
+
+    RenderFlowThread* flowThread = flowThreadContainingBlock();
+    bool clearLinesForPagination = firstLineBox() && flowThread && !flowThread->hasRegions();
+
+    // Figure out if we should clear out our line boxes.
+    // FIXME: Handle resize eventually!
+    bool isFullLayout = !firstLineBox() || selfNeedsLayout() || relayoutChildren || clearLinesForPagination;
+    LineLayoutState layoutState(isFullLayout, repaintLogicalTop, repaintLogicalBottom, flowThread);
+
+    if (isFullLayout)
+        lineBoxes()->deleteLineBoxes(renderArena());
+
+    // Text truncation kicks in in two cases:
+    //     1) If your overflow isn't visible and your text-overflow-mode isn't clip.
+    //     2) If you're an anonymous block with a block parent that satisfies #1.
+    // FIXME: CSS3 says that descendants that are clipped must also know how to truncate.  This is insanely
+    // difficult to figure out in general (especially in the middle of doing layout), so we only handle the
+    // simple case of an anonymous block truncating when it's parent is clipped.
+    bool hasTextOverflow = (style()->textOverflow() && hasOverflowClip())
+        || (isAnonymousBlock() && parent() && parent()->isRenderBlock() && parent()->style()->textOverflow() && parent()->hasOverflowClip());
+
+    // Walk all the lines and delete our ellipsis line boxes if they exist.
+    if (hasTextOverflow)
+         deleteEllipsisLineBoxes();
+
+    if (firstChild()) {
+        // In full layout mode, clear the line boxes of children upfront. Otherwise,
+        // siblings can run into stale root lineboxes during layout. Then layout
+        // the replaced elements later. In partial layout mode, line boxes are not
+        // deleted and only dirtied. In that case, we can layout the replaced
+        // elements at the same time.
+        bool hasInlineChild = false;
+        Vector<RenderBox*> replacedChildren;
+        for (InlineWalker walker(this); !walker.atEnd(); walker.advance()) {
+            RenderObject* o = walker.current();
+            if (!hasInlineChild && o->isInline())
+                hasInlineChild = true;
+
+            if (o->isReplaced() || o->isFloating() || o->isOutOfFlowPositioned()) {
+                RenderBox* box = toRenderBox(o);
+
+                if (relayoutChildren || box->hasRelativeDimensions())
+                    o->setChildNeedsLayout(true, MarkOnlyThis);
+
+                // If relayoutChildren is set and the child has percentage padding or an embedded content box, we also need to invalidate the childs pref widths.
+                if (relayoutChildren && box->needsPreferredWidthsRecalculation())
+                    o->setPreferredLogicalWidthsDirty(true, MarkOnlyThis);
+
+                if (o->isOutOfFlowPositioned())
+                    o->containingBlock()->insertPositionedObject(box);
+                else if (o->isFloating())
+                    layoutState.floats().append(FloatWithRect(box));
+                else if (isFullLayout || o->needsLayout()) {
+                    // Replaced element.
+                    box->dirtyLineBoxes(isFullLayout);
+                    if (isFullLayout)
+                        replacedChildren.append(box);
+                    else
+                        o->layoutIfNeeded();
+                }
+            } else if (o->isText() || (o->isRenderInline() && !walker.atEndOfInline())) {
+                if (!o->isText())
+                    toRenderInline(o)->updateAlwaysCreateLineBoxes(layoutState.isFullLayout());
+                if (layoutState.isFullLayout() || o->selfNeedsLayout())
+                    dirtyLineBoxesForRenderer(o, layoutState.isFullLayout());
+                o->setNeedsLayout(false);
+            }
+        }
+
+        for (size_t i = 0; i < replacedChildren.size(); i++)
+             replacedChildren[i]->layoutIfNeeded();
+
+        layoutRunsAndFloats(layoutState, hasInlineChild);
+    }
+
+    // Expand the last line to accommodate Ruby and emphasis marks.
+    int lastLineAnnotationsAdjustment = 0;
+    if (lastRootBox()) {
+        LayoutUnit lowestAllowedPosition = max(lastRootBox()->lineBottom(), logicalHeight() + paddingAfter());
+        if (!style()->isFlippedLinesWritingMode())
+            lastLineAnnotationsAdjustment = lastRootBox()->computeUnderAnnotationAdjustment(lowestAllowedPosition);
+        else
+            lastLineAnnotationsAdjustment = lastRootBox()->computeOverAnnotationAdjustment(lowestAllowedPosition);
+    }
+
+    // Now add in the bottom border/padding.
+    setLogicalHeight(logicalHeight() + lastLineAnnotationsAdjustment + borderAfter() + paddingAfter() + scrollbarLogicalHeight());
+
+    if (!firstLineBox() && hasLineIfEmpty())
+        setLogicalHeight(logicalHeight() + lineHeight(true, isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes));
+
+    // 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();
+}
+
+void RenderBlock::checkFloatsInCleanLine(RootInlineBox* line, Vector<FloatWithRect>& floats, size_t& floatIndex, bool& encounteredNewFloat, bool& dirtiedByFloat)
+{
+    Vector<RenderBox*>* cleanLineFloats = line->floatsPtr();
+    if (!cleanLineFloats)
+        return;
+
+    Vector<RenderBox*>::iterator end = cleanLineFloats->end();
+    for (Vector<RenderBox*>::iterator it = cleanLineFloats->begin(); it != end; ++it) {
+        RenderBox* floatingBox = *it;
+        floatingBox->layoutIfNeeded();
+        LayoutSize newSize(floatingBox->width() + floatingBox->marginWidth(), floatingBox->height() + floatingBox->marginHeight());
+        ASSERT_WITH_SECURITY_IMPLICATION(floatIndex < floats.size());
+        if (floats[floatIndex].object != floatingBox) {
+            encounteredNewFloat = true;
+            return;
+        }
+
+        if (floats[floatIndex].rect.size() != newSize) {
+            LayoutUnit floatTop = isHorizontalWritingMode() ? floats[floatIndex].rect.y() : floats[floatIndex].rect.x();
+            LayoutUnit floatHeight = isHorizontalWritingMode() ? max(floats[floatIndex].rect.height(), newSize.height())
+                                                                 : max(floats[floatIndex].rect.width(), newSize.width());
+            floatHeight = min(floatHeight, LayoutUnit::max() - floatTop);
+            line->markDirty();
+            markLinesDirtyInBlockRange(line->lineBottomWithLeading(), floatTop + floatHeight, line);
+            floats[floatIndex].rect.setSize(newSize);
+            dirtiedByFloat = true;
+        }
+        floatIndex++;
+    }
+}
+
+RootInlineBox* RenderBlock::determineStartPosition(LineLayoutState& layoutState, InlineBidiResolver& resolver)
+{
+    RootInlineBox* curr = 0;
+    RootInlineBox* last = 0;
+
+    // FIXME: This entire float-checking block needs to be broken into a new function.
+    bool dirtiedByFloat = false;
+    if (!layoutState.isFullLayout()) {
+        // Paginate all of the clean lines.
+        bool paginated = view()->layoutState() && view()->layoutState()->isPaginated();
+        LayoutUnit paginationDelta = 0;
+        size_t floatIndex = 0;
+        for (curr = firstRootBox(); curr && !curr->isDirty(); curr = curr->nextRootBox()) {
+            if (paginated) {
+                if (lineWidthForPaginatedLineChanged(curr, 0, layoutState.flowThread())) {
+                    curr->markDirty();
+                    break;
+                }
+                paginationDelta -= curr->paginationStrut();
+                adjustLinePositionForPagination(curr, paginationDelta, layoutState.flowThread());
+                if (paginationDelta) {
+                    if (containsFloats() || !layoutState.floats().isEmpty()) {
+                        // FIXME: Do better eventually.  For now if we ever shift because of pagination and floats are present just go to a full layout.
+                        layoutState.markForFullLayout();
+                        break;
+                    }
+
+                    layoutState.updateRepaintRangeFromBox(curr, paginationDelta);
+                    curr->adjustBlockDirectionPosition(paginationDelta);
+                }
+                if (layoutState.flowThread())
+                    curr->setContainingRegion(regionAtBlockOffset(curr->lineTopWithLeading()));
+            }
+
+            // If a new float has been inserted before this line or before its last known float, just do a full layout.
+            bool encounteredNewFloat = false;
+            checkFloatsInCleanLine(curr, layoutState.floats(), floatIndex, encounteredNewFloat, dirtiedByFloat);
+            if (encounteredNewFloat)
+                layoutState.markForFullLayout();
+
+            if (dirtiedByFloat || layoutState.isFullLayout())
+                break;
+        }
+        // Check if a new float has been inserted after the last known float.
+        if (!curr && floatIndex < layoutState.floats().size())
+            layoutState.markForFullLayout();
+    }
+
+    if (layoutState.isFullLayout()) {
+        // FIXME: This should just call deleteLineBoxTree, but that causes
+        // crashes for fast/repaint tests.
+        RenderArena* arena = renderArena();
+        curr = firstRootBox();
+        while (curr) {
+            // Note: This uses nextRootBox() insted of nextLineBox() like deleteLineBoxTree does.
+            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() || (prevRootBox->lineBreakObj()->isText() && prevRootBox->lineBreakPos() >= toRenderText(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();
+    }
+
+    unsigned numCleanFloats = 0;
+    if (!layoutState.floats().isEmpty()) {
+        LayoutUnit savedLogicalHeight = logicalHeight();
+        // Restore floats from clean lines.
+        RootInlineBox* line = firstRootBox();
+        while (line != curr) {
+            if (Vector<RenderBox*>* cleanLineFloats = line->floatsPtr()) {
+                Vector<RenderBox*>::iterator end = cleanLineFloats->end();
+                for (Vector<RenderBox*>::iterator f = cleanLineFloats->begin(); f != end; ++f) {
+                    FloatingObject* floatingObject = insertFloatingObject(*f);
+                    ASSERT(!floatingObject->m_originatingLine);
+                    floatingObject->m_originatingLine = line;
+                    setLogicalHeight(logicalTopForChild(*f) - marginBeforeForChild(*f));
+                    positionNewFloats();
+                    ASSERT(layoutState.floats()[numCleanFloats].object == *f);
+                    numCleanFloats++;
+                }
+            }
+            line = line->nextRootBox();
+        }
+        setLogicalHeight(savedLogicalHeight);
+    }
+    layoutState.setFloatIndex(numCleanFloats);
+
+    layoutState.lineInfo().setFirstLine(!last);
+    layoutState.lineInfo().setPreviousLineBrokeCleanly(!last || last->endsWithBreak());
+
+    if (last) {
+        setLogicalHeight(last->lineBottomWithLeading());
+        InlineIterator iter = InlineIterator(this, last->lineBreakObj(), last->lineBreakPos());
+        resolver.setPosition(iter, numberOfIsolateAncestors(iter));
+        resolver.setStatus(last->lineBreakBidiStatus());
+    } else {
+        TextDirection direction = style()->direction();
+        if (style()->unicodeBidi() == Plaintext)
+            determineDirectionality(direction, InlineIterator(this, bidiFirstSkippingEmptyInlines(this), 0));
+        resolver.setStatus(BidiStatus(direction, isOverride(style()->unicodeBidi())));
+        InlineIterator iter = InlineIterator(this, bidiFirstSkippingEmptyInlines(this, &resolver), 0);
+        resolver.setPosition(iter, numberOfIsolateAncestors(iter));
+    }
+    return curr;
+}
+
+void RenderBlock::determineEndPosition(LineLayoutState& layoutState, RootInlineBox* startLine, InlineIterator& cleanLineStart, BidiStatus& cleanLineBidiStatus)
+{
+    ASSERT(!layoutState.endLine());
+    size_t floatIndex = layoutState.floatIndex();
+    RootInlineBox* last = 0;
+    for (RootInlineBox* curr = startLine->nextRootBox(); curr; curr = curr->nextRootBox()) {
+        if (!curr->isDirty()) {
+            bool encounteredNewFloat = false;
+            bool dirtiedByFloat = false;
+            checkFloatsInCleanLine(curr, layoutState.floats(), floatIndex, encounteredNewFloat, dirtiedByFloat);
+            if (encounteredNewFloat)
+                return;
+        }
+        if (curr->isDirty())
+            last = 0;
+        else if (!last)
+            last = curr;
+    }
+
+    if (!last)
+        return;
+
+    // At this point, |last| is the first line in a run of clean lines that ends with the last line
+    // in the block.
+
+    RootInlineBox* prev = last->prevRootBox();
+    cleanLineStart = InlineIterator(this, prev->lineBreakObj(), prev->lineBreakPos());
+    cleanLineBidiStatus = prev->lineBreakBidiStatus();
+    layoutState.setEndLineLogicalTop(prev->lineBottomWithLeading());
+
+    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.
+
+    layoutState.setEndLine(last);
+}
+
+bool RenderBlock::checkPaginationAndFloatsAtEndLine(LineLayoutState& layoutState)
+{
+    LayoutUnit lineDelta = logicalHeight() - layoutState.endLineLogicalTop();
+
+    bool paginated = view()->layoutState() && view()->layoutState()->isPaginated();
+    if (paginated && layoutState.flowThread()) {
+        // Check all lines from here to the end, and see if the hypothetical new position for the lines will result
+        // in a different available line width.
+        for (RootInlineBox* lineBox = layoutState.endLine(); lineBox; lineBox = lineBox->nextRootBox()) {
+            if (paginated) {
+                // This isn't the real move we're going to do, so don't update the line box's pagination
+                // strut yet.
+                LayoutUnit oldPaginationStrut = lineBox->paginationStrut();
+                lineDelta -= oldPaginationStrut;
+                adjustLinePositionForPagination(lineBox, lineDelta, layoutState.flowThread());
+                lineBox->setPaginationStrut(oldPaginationStrut);
+            }
+            if (lineWidthForPaginatedLineChanged(lineBox, lineDelta, layoutState.flowThread()))
+                return false;
+        }
+    }
+    
+    if (!lineDelta || !m_floatingObjects)
+        return true;
+    
+    // See if any floats end in the range along which we want to shift the lines vertically.
+    LayoutUnit logicalTop = min(logicalHeight(), layoutState.endLineLogicalTop());
+
+    RootInlineBox* lastLine = layoutState.endLine();
+    while (RootInlineBox* nextLine = lastLine->nextRootBox())
+        lastLine = nextLine;
+
+    LayoutUnit logicalBottom = lastLine->lineBottomWithLeading() + absoluteValue(lineDelta);
+
+    const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
+    FloatingObjectSetIterator end = floatingObjectSet.end();
+    for (FloatingObjectSetIterator it = floatingObjectSet.begin(); it != end; ++it) {
+        FloatingObject* f = *it;
+        if (logicalBottomForFloat(f) >= logicalTop && logicalBottomForFloat(f) < logicalBottom)
+            return false;
+    }
+
+    return true;
+}
+
+bool RenderBlock::matchedEndLine(LineLayoutState& layoutState, const InlineBidiResolver& resolver, const InlineIterator& endLineStart, const BidiStatus& endLineStatus)
+{
+    if (resolver.position() == endLineStart) {
+        if (resolver.status() != endLineStatus)
+            return false;
+        return checkPaginationAndFloatsAtEndLine(layoutState);
+    }
+
+    // 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* originalEndLine = layoutState.endLine();
+    RootInlineBox* line = originalEndLine;
+    for (int i = 0; i < numLines && line; i++, line = line->nextRootBox()) {
+        if (line->lineBreakObj() == resolver.position().m_obj && line->lineBreakPos() == resolver.position().m_pos) {
+            // We have a match.
+            if (line->lineBreakBidiStatus() != resolver.status())
+                return false; // ...but the bidi state doesn't match.
+            
+            bool matched = false;
+            RootInlineBox* result = line->nextRootBox();
+            layoutState.setEndLine(result);
+            if (result) {
+                layoutState.setEndLineLogicalTop(line->lineBottomWithLeading());
+                matched = checkPaginationAndFloatsAtEndLine(layoutState);
+            }
+
+            // Now delete the lines that we failed to sync.
+            deleteLineRange(layoutState, renderArena(), originalEndLine, result);
+            return matched;
+        }
+    }
+
+    return false;
+}
+
+enum WhitespacePosition { LeadingWhitespace, TrailingWhitespace };
+static inline bool shouldCollapseWhiteSpace(const RenderStyle* style, const LineInfo& lineInfo, WhitespacePosition whitespacePosition)
+{
+    // CSS2 16.6.1
+    // If a space (U+0020) at the beginning of a line has 'white-space' set to 'normal', 'nowrap', or 'pre-line', it is removed.
+    // If a space (U+0020) at the end of a line has 'white-space' set to 'normal', 'nowrap', or 'pre-line', it is also removed.
+    // If spaces (U+0020) or tabs (U+0009) at the end of a line have 'white-space' set to 'pre-wrap', UAs may visually collapse them.
+    return style->collapseWhiteSpace()
+        || (whitespacePosition == TrailingWhitespace && style->whiteSpace() == PRE_WRAP && (!lineInfo.isEmpty() || !lineInfo.previousLineBrokeCleanly()));
+}
+
+static bool requiresLineBoxForContent(RenderInline* flow, const LineInfo& lineInfo)
+{
+    RenderObject* parent = flow->parent();
+    if (flow->document()->inNoQuirksMode() 
+        && (flow->style(lineInfo.isFirstLine())->lineHeight() != parent->style(lineInfo.isFirstLine())->lineHeight()
+        || flow->style()->verticalAlign() != parent->style()->verticalAlign()
+        || !parent->style()->font().fontMetrics().hasIdenticalAscentDescentAndLineGap(flow->style()->font().fontMetrics())))
+        return true;
+    return false;
+}
+
+static bool alwaysRequiresLineBox(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 isEmptyInline(flow) && toRenderInline(flow)->hasInlineDirectionBordersPaddingOrMargin();
+}
+
+static bool requiresLineBox(const InlineIterator& it, const LineInfo& lineInfo = LineInfo(), WhitespacePosition whitespacePosition = LeadingWhitespace)
+{
+    if (it.m_obj->isFloatingOrOutOfFlowPositioned())
+        return false;
+
+    if (it.m_obj->isRenderInline() && !alwaysRequiresLineBox(it.m_obj) && !requiresLineBoxForContent(toRenderInline(it.m_obj), lineInfo))
+        return false;
+
+    if (!shouldCollapseWhiteSpace(it.m_obj->style(), lineInfo, whitespacePosition) || it.m_obj->isBR())
+        return true;
+
+    UChar current = it.current();
+    bool notJustWhitespace = current != ' ' && current != '\t' && current != softHyphen && (current != '\n' || it.m_obj->preservesNewline());
+    return notJustWhitespace || isEmptyInline(it.m_obj);
+}
+
+bool RenderBlock::generatesLineBoxesForInlineChild(RenderObject* inlineObj)
+{
+    ASSERT(inlineObj->parent() == this);
+
+    InlineIterator it(this, inlineObj, 0);
+    // FIXME: We should pass correct value for WhitespacePosition.
+    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::LineBreaker::skipTrailingWhitespace(InlineIterator& iterator, const LineInfo& lineInfo)
+{
+    while (!iterator.atEnd() && !requiresLineBox(iterator, lineInfo, TrailingWhitespace)) {
+        RenderObject* object = iterator.m_obj;
+        if (object->isOutOfFlowPositioned())
+            setStaticPositions(m_block, toRenderBox(object));
+        else if (object->isFloating())
+            m_block->insertFloatingObject(toRenderBox(object));
+        iterator.increment();
+    }
+}
+
+void RenderBlock::LineBreaker::skipLeadingWhitespace(InlineBidiResolver& resolver, LineInfo& lineInfo,
+                                                     FloatingObject* lastFloatFromPreviousLine, LineWidth& width)
+{
+    while (!resolver.position().atEnd() && !requiresLineBox(resolver.position(), lineInfo, LeadingWhitespace)) {
+        RenderObject* object = resolver.position().m_obj;
+        if (object->isOutOfFlowPositioned()) {
+            setStaticPositions(m_block, toRenderBox(object));
+            if (object->style()->isOriginalDisplayInlineType()) {
+                resolver.runs().addRun(createRun(0, 1, object, resolver));
+                lineInfo.incrementRunsFromLeadingWhitespace();
+            }
+        } else if (object->isFloating()) {
+            // The top margin edge of a self-collapsing block that clears a float intrudes up into it by the height of the margin,
+            // so in order to place this first child float at the top content edge of the self-collapsing block add the margin back in before placement.
+            LayoutUnit marginOffset = (!object->previousSibling() && m_block->isSelfCollapsingBlock() && m_block->style()->clear() && m_block->getClearDelta(m_block, LayoutUnit())) ? m_block->collapsedMarginBeforeForChild(m_block) : LayoutUnit();
+            LayoutUnit oldLogicalHeight = m_block->logicalHeight();
+            m_block->setLogicalHeight(oldLogicalHeight + marginOffset);
+            m_block->positionNewFloatOnLine(m_block->insertFloatingObject(toRenderBox(object)), lastFloatFromPreviousLine, lineInfo, width);
+            m_block->setLogicalHeight(oldLogicalHeight);
+        } else if (object->isText() && object->style()->hasTextCombine() && object->isCombineText() && !toRenderCombineText(object)->isCombined()) {
+            toRenderCombineText(object)->combineText();
+            if (toRenderCombineText(object)->isCombined())
+                continue;
+        }
+        resolver.increment();
+    }
+    resolver.commitExplicitEmbedding();
+}
+
+// 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, LineMidpointState& lineMidpointState)
+{
+    RenderObject* next = bidiNextSkippingEmptyInlines(block, o);
+    while (next && next->isFloatingOrOutOfFlowPositioned())
+        next = bidiNextSkippingEmptyInlines(block, next);
+
+    if (next && !next->isBR() && next->isText() && toRenderText(next)->textLength() > 0) {
+        RenderText* nextText = toRenderText(next);
+        UChar nextChar = nextText->characterAt(0);
+        if (nextText->style()->isCollapsibleWhiteSpace(nextChar)) {
+            startIgnoringSpaces(lineMidpointState, InlineIterator(0, o, 0));
+            return true;
+        }
+    }
+
+    return false;
+}
+
+static ALWAYS_INLINE float textWidth(RenderText* text, unsigned from, unsigned len, const Font& font, float xPos, bool isFixedPitch, bool collapseWhiteSpace, HashSet<const SimpleFontData*>* fallbackFonts = 0, TextLayout* layout = 0)
+{
+    GlyphOverflow glyphOverflow;
+    if (isFixedPitch || (!from && len == text->textLength()) || text->style()->hasTextCombine())
+        return text->width(from, len, font, xPos, fallbackFonts, &glyphOverflow);
+
+    if (layout)
+        return Font::width(*layout, from, len, fallbackFonts);
+
+    TextRun run = RenderBlock::constructTextRun(text, font, text, from, len, text->style());
+    run.setCharactersLength(text->textLength() - from);
+    ASSERT(run.charactersLength() >= run.length());
+
+    run.setCharacterScanForCodePath(!text->canUseSimpleFontCodePath());
+    run.setTabSize(!collapseWhiteSpace, text->style()->tabSize());
+    run.setXPos(xPos);
+    return font.width(run, fallbackFonts, &glyphOverflow);
+}
+
+static void tryHyphenating(RenderText* text, const Font& font, const AtomicString& localeIdentifier, unsigned consecutiveHyphenatedLines, int consecutiveHyphenatedLinesLimit, int minimumPrefixLimit, int minimumSuffixLimit, unsigned lastSpace, unsigned pos, float xPos, int availableWidth, bool isFixedPitch, bool collapseWhiteSpace, int lastSpaceWordSpacing, InlineIterator& lineBreak, int nextBreakable, bool& hyphenated)
+{
+    // Map 'hyphenate-limit-{before,after}: auto;' to 2.
+    unsigned minimumPrefixLength;
+    unsigned minimumSuffixLength;
+
+    if (minimumPrefixLimit < 0)
+        minimumPrefixLength = 2;
+    else
+        minimumPrefixLength = static_cast<unsigned>(minimumPrefixLimit);
+
+    if (minimumSuffixLimit < 0)
+        minimumSuffixLength = 2;
+    else
+        minimumSuffixLength = static_cast<unsigned>(minimumSuffixLimit);
+
+    if (pos - lastSpace <= minimumSuffixLength)
+        return;
+
+    if (consecutiveHyphenatedLinesLimit >= 0 && consecutiveHyphenatedLines >= static_cast<unsigned>(consecutiveHyphenatedLinesLimit))
+        return;
+
+    int hyphenWidth = measureHyphenWidth(text, font);
+
+    float maxPrefixWidth = availableWidth - xPos - hyphenWidth - lastSpaceWordSpacing;
+    // If the maximum width available for the prefix before the hyphen is small, then it is very unlikely
+    // that an hyphenation opportunity exists, so do not bother to look for it.
+    if (maxPrefixWidth <= font.pixelSize() * 5 / 4)
+        return;
+
+    TextRun run = RenderBlock::constructTextRun(text, font, text, lastSpace, pos - lastSpace, text->style());
+    run.setCharactersLength(text->textLength() - lastSpace);
+    ASSERT(run.charactersLength() >= run.length());
+
+    run.setTabSize(!collapseWhiteSpace, text->style()->tabSize());
+    run.setXPos(xPos + lastSpaceWordSpacing);
+
+    unsigned prefixLength = font.offsetForPosition(run, maxPrefixWidth, false);
+    if (prefixLength < minimumPrefixLength)
+        return;
+
+    prefixLength = lastHyphenLocation(text->characters() + lastSpace, pos - lastSpace, min(prefixLength, pos - lastSpace - minimumSuffixLength) + 1, localeIdentifier);
+    if (!prefixLength || prefixLength < minimumPrefixLength)
+        return;
+
+    // When lastSapce is a space, which it always is except sometimes at the beginning of a line or after collapsed
+    // space, it should not count towards hyphenate-limit-before.
+    if (prefixLength == minimumPrefixLength) {
+        UChar characterAtLastSpace = text->characterAt(lastSpace);
+        if (characterAtLastSpace == ' ' || characterAtLastSpace == '\n' || characterAtLastSpace == '\t' || characterAtLastSpace == noBreakSpace)
+            return;
+    }
+
+    ASSERT(pos - lastSpace - prefixLength >= minimumSuffixLength);
+
+#if !ASSERT_DISABLED
+    float prefixWidth = hyphenWidth + textWidth(text, lastSpace, prefixLength, font, xPos, isFixedPitch, collapseWhiteSpace) + lastSpaceWordSpacing;
+    ASSERT(xPos + prefixWidth <= availableWidth);
+#else
+    UNUSED_PARAM(isFixedPitch);
+#endif
+
+    lineBreak.moveTo(text, lastSpace + prefixLength, nextBreakable);
+    hyphenated = true;
+}
+
+class TrailingObjects {
+public:
+    TrailingObjects();
+    void setTrailingWhitespace(RenderText*);
+    void clear();
+    void appendBoxIfNeeded(RenderBox*);
+
+    enum CollapseFirstSpaceOrNot { DoNotCollapseFirstSpace, CollapseFirstSpace };
+
+    void updateMidpointsForTrailingBoxes(LineMidpointState&, const InlineIterator& lBreak, CollapseFirstSpaceOrNot);
+
+private:
+    RenderText* m_whitespace;
+    Vector<RenderBox*, 4> m_boxes;
+};
+
+TrailingObjects::TrailingObjects()
+    : m_whitespace(0)
+{
+}
+
+inline void TrailingObjects::setTrailingWhitespace(RenderText* whitespace)
+{
+    ASSERT(whitespace);
+    m_whitespace = whitespace;
+}
+
+inline void TrailingObjects::clear()
+{
+    m_whitespace = 0;
+    m_boxes.clear();
+}
+
+inline void TrailingObjects::appendBoxIfNeeded(RenderBox* box)
+{
+    if (m_whitespace)
+        m_boxes.append(box);
+}
+
+void TrailingObjects::updateMidpointsForTrailingBoxes(LineMidpointState& lineMidpointState, const InlineIterator& lBreak, CollapseFirstSpaceOrNot collapseFirstSpace)
+{
+    if (!m_whitespace)
+        return;
+
+    // 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 (lineMidpointState.numMidpoints % 2) {
+        // Find the trailing space object's midpoint.
+        int trailingSpaceMidpoint = lineMidpointState.numMidpoints - 1;
+        for ( ; trailingSpaceMidpoint > 0 && lineMidpointState.midpoints[trailingSpaceMidpoint].m_obj != m_whitespace; --trailingSpaceMidpoint) { }
+        ASSERT(trailingSpaceMidpoint >= 0);
+        if (collapseFirstSpace == CollapseFirstSpace)
+            lineMidpointState.midpoints[trailingSpaceMidpoint].m_pos--;
+
+        // Now make sure every single trailingPositionedBox following the trailingSpaceMidpoint properly stops and starts
+        // ignoring spaces.
+        size_t currentMidpoint = trailingSpaceMidpoint + 1;
+        for (size_t i = 0; i < m_boxes.size(); ++i) {
+            if (currentMidpoint >= lineMidpointState.numMidpoints) {
+                // We don't have a midpoint for this box yet.
+                ensureLineBoxInsideIgnoredSpaces(lineMidpointState, m_boxes[i]);
+            } else {
+                ASSERT(lineMidpointState.midpoints[currentMidpoint].m_obj == m_boxes[i]);
+                ASSERT(lineMidpointState.midpoints[currentMidpoint + 1].m_obj == m_boxes[i]);
+            }
+            currentMidpoint += 2;
+        }
+    } else if (!lBreak.m_obj) {
+        ASSERT(m_whitespace->isText());
+        ASSERT(collapseFirstSpace == CollapseFirstSpace);
+        // Add a new end midpoint that stops right at the very end.
+        unsigned length = m_whitespace->textLength();
+        unsigned pos = length >= 2 ? length - 2 : UINT_MAX;
+        InlineIterator endMid(0, m_whitespace, pos);
+        startIgnoringSpaces(lineMidpointState, endMid);
+        for (size_t i = 0; i < m_boxes.size(); ++i) {
+            ensureLineBoxInsideIgnoredSpaces(lineMidpointState, m_boxes[i]);
+        }
+    }
+}
+
+void RenderBlock::LineBreaker::reset()
+{
+    m_positionedObjects.clear();
+    m_hyphenated = false;
+    m_clear = CNONE;
+}
+
+InlineIterator RenderBlock::LineBreaker::nextLineBreak(InlineBidiResolver& resolver, LineInfo& lineInfo, RenderTextInfo& renderTextInfo, FloatingObject* lastFloatFromPreviousLine, unsigned consecutiveHyphenatedLines, WordMeasurements& wordMeasurements)
+{
+    ExclusionShapeInsideInfo* exclusionShapeInsideInfo = m_block->layoutExclusionShapeInsideInfo();
+    if (!exclusionShapeInsideInfo || !exclusionShapeInsideInfo->hasSegments())
+        return nextSegmentBreak(resolver, lineInfo, renderTextInfo, lastFloatFromPreviousLine, consecutiveHyphenatedLines, wordMeasurements);
+
+    InlineIterator end = resolver.position();
+    InlineIterator oldEnd = end;
+
+    const SegmentList& segments = exclusionShapeInsideInfo->segments();
+    SegmentRangeList& segmentRanges = exclusionShapeInsideInfo->segmentRanges();
+
+    for (unsigned i = 0; i < segments.size() && !end.atEnd(); i++) {
+        InlineIterator segmentStart = resolver.position();
+        end = nextSegmentBreak(resolver, lineInfo, renderTextInfo, lastFloatFromPreviousLine, consecutiveHyphenatedLines, wordMeasurements);
+
+        ASSERT(segmentRanges.size() == i);
+        if (resolver.position().atEnd()) {
+            segmentRanges.append(LineSegmentRange(segmentStart, end));
+            break;
+        }
+        if (resolver.position() == end) {
+            // Nothing fit this segment
+            segmentRanges.append(LineSegmentRange(segmentStart, segmentStart));
+            resolver.setPositionIgnoringNestedIsolates(segmentStart);
+        } else {
+            // Note that resolver.position is already skipping some of the white space at the beginning of the line,
+            // so that's why segmentStart might be different than resolver.position().
+            LineSegmentRange range(resolver.position(), end);
+            segmentRanges.append(range);
+            resolver.setPosition(end, numberOfIsolateAncestors(end));
+
+            if (lineInfo.previousLineBrokeCleanly()) {
+                // If we hit a new line break, just stop adding anything to this line.
+                break;
+            }
+        }
+    }
+    resolver.setPositionIgnoringNestedIsolates(oldEnd);
+    return end;
+}
+
+static inline bool iteratorIsBeyondEndOfRenderCombineText(const InlineIterator& iter, RenderCombineText* renderer)
+{
+    return iter.m_obj == renderer && iter.m_pos >= renderer->textLength();
+}
+
+InlineIterator RenderBlock::LineBreaker::nextSegmentBreak(InlineBidiResolver& resolver, LineInfo& lineInfo, RenderTextInfo& renderTextInfo, FloatingObject* lastFloatFromPreviousLine, unsigned consecutiveHyphenatedLines, WordMeasurements& wordMeasurements)
+{
+    reset();
+
+    ASSERT(resolver.position().root() == m_block);
+
+    bool appliedStartWidth = resolver.position().m_pos > 0;
+    bool includeEndWidth = true;
+    LineMidpointState& lineMidpointState = resolver.midpointState();
+
+    LineWidth width(m_block, lineInfo.isFirstLine(), requiresIndent(lineInfo.isFirstLine(), lineInfo.previousLineBrokeCleanly(), m_block->style()));
+
+    skipLeadingWhitespace(resolver, lineInfo, lastFloatFromPreviousLine, width);
+
+    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;
+    TrailingObjects trailingObjects;
+
+    InlineIterator lBreak = resolver.position();
+
+    // FIXME: It is error-prone to split the position object out like this.
+    // Teach this code to work with objects instead of this split tuple.
+    InlineIterator current = resolver.position();
+    RenderObject* last = current.m_obj;
+    bool atStart = true;
+
+    bool startingNewParagraph = lineInfo.previousLineBrokeCleanly();
+    lineInfo.setPreviousLineBrokeCleanly(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.)
+    RenderStyle* blockStyle = m_block->style();
+    bool allowImagesToBreak = !m_block->document()->inQuirksMode() || !m_block->isTableCell() || !blockStyle->logicalWidth().isIntrinsicOrAuto();
+
+    EWhiteSpace currWS = blockStyle->whiteSpace();
+    EWhiteSpace lastWS = currWS;
+    while (current.m_obj) {
+        RenderStyle* currentStyle = current.m_obj->style();
+        RenderObject* next = bidiNextSkippingEmptyInlines(m_block, current.m_obj);
+        if (next && next->parent() && !next->parent()->isDescendantOf(current.m_obj->parent()))
+            includeEndWidth = true;
+
+        currWS = current.m_obj->isReplaced() ? current.m_obj->parent()->style()->whiteSpace() : currentStyle->whiteSpace();
+        lastWS = last->isReplaced() ? last->parent()->style()->whiteSpace() : last->style()->whiteSpace();
+
+        bool autoWrap = RenderStyle::autoWrap(currWS);
+        autoWrapWasEverTrueOnLine = autoWrapWasEverTrueOnLine || autoWrap;
+
+#if ENABLE(SVG)
+        bool preserveNewline = current.m_obj->isSVGInlineText() ? false : RenderStyle::preserveNewline(currWS);
+#else
+        bool preserveNewline = RenderStyle::preserveNewline(currWS);
+#endif
+
+        bool collapseWhiteSpace = RenderStyle::collapseWhiteSpace(currWS);
+
+        if (current.m_obj->isBR()) {
+            if (width.fitsOnLine()) {
+                lBreak.moveToStartOf(current.m_obj);
+                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 (startingNewParagraph)
+                    lineInfo.setEmpty(false, m_block, &width);
+                trailingObjects.clear();
+                lineInfo.setPreviousLineBrokeCleanly(true);
+
+                // A <br> with clearance always needs a linebox in case the lines below it get dirtied later and 
+                // need to check for floats to clear - so if we're ignoring spaces, stop ignoring them and add a
+                // run for this object.
+                if (ignoringSpaces && currentStyle->clear() != CNONE)
+                    ensureLineBoxInsideIgnoredSpaces(lineMidpointState, current.m_obj);
+
+                if (!lineInfo.isEmpty())
+                    m_clear = currentStyle->clear();
+            }
+            goto end;
+        }
+
+        if (current.m_obj->isOutOfFlowPositioned()) {
+            // If our original display wasn't an inline type, then we can
+            // go ahead and determine our static inline position now.
+            RenderBox* box = toRenderBox(current.m_obj);
+            bool isInlineType = box->style()->isOriginalDisplayInlineType();
+            if (!isInlineType)
+                m_block->setStaticInlinePositionForChild(box, m_block->logicalHeight(), m_block->startOffsetForContent(m_block->logicalHeight()));
+            else  {
+                // If our original display was an INLINE type, then we can go ahead
+                // and determine our static y position now.
+                box->layer()->setStaticBlockPosition(m_block->logicalHeight());
+            }
+
+            // If we're ignoring spaces, we have to stop and include this object and
+            // then start ignoring spaces again.
+            if (isInlineType || current.m_obj->container()->isRenderInline()) {
+                if (ignoringSpaces)
+                    ensureLineBoxInsideIgnoredSpaces(lineMidpointState, current.m_obj);
+                trailingObjects.appendBoxIfNeeded(box);
+            } else
+                m_positionedObjects.append(box);
+            width.addUncommittedWidth(inlineLogicalWidth(current.m_obj));
+            // Reset prior line break context characters.
+            renderTextInfo.m_lineBreakIterator.resetPriorContext();
+        } else if (current.m_obj->isFloating()) {
+            RenderBox* floatBox = toRenderBox(current.m_obj);
+            FloatingObject* f = m_block->insertFloatingObject(floatBox);
+            // 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)
+            // FIXME: Bug 110372: Properly position multiple stacked floats with non-rectangular shape outside.
+            if (floatsFitOnLine && width.fitsOnLine(m_block->logicalWidthForFloat(f))) {
+                m_block->positionNewFloatOnLine(f, lastFloatFromPreviousLine, lineInfo, width);
+                if (lBreak.m_obj == current.m_obj) {
+                    ASSERT(!lBreak.m_pos);
+                    lBreak.increment();
+                }
+            } else
+                floatsFitOnLine = false;
+            // Update prior line break context characters, using U+FFFD (OBJECT REPLACEMENT CHARACTER) for floating element.
+            renderTextInfo.m_lineBreakIterator.updatePriorContext(replacementCharacter);
+        } else if (current.m_obj->isRenderInline()) {
+            // Right now, we should only encounter empty inlines here.
+            ASSERT(isEmptyInline(current.m_obj));
+
+            RenderInline* flowBox = toRenderInline(current.m_obj);
+
+            // 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.
+            bool requiresLineBox = alwaysRequiresLineBox(current.m_obj);
+            if (requiresLineBox || requiresLineBoxForContent(flowBox, lineInfo)) {
+                // An empty inline that only has line-height, vertical-align or font-metrics will only get a
+                // line box to affect the height of the line if the rest of the line is not empty.
+                if (requiresLineBox)
+                    lineInfo.setEmpty(false, m_block, &width);
+                if (ignoringSpaces) {
+                    trailingObjects.clear();
+                    ensureLineBoxInsideIgnoredSpaces(lineMidpointState, current.m_obj);
+                } else if (blockStyle->collapseWhiteSpace() && resolver.position().m_obj == current.m_obj
+                    && shouldSkipWhitespaceAfterStartObject(m_block, current.m_obj, lineMidpointState)) {
+                    // Like with list markers, we start ignoring spaces to make sure that any
+                    // additional spaces we see will be discarded.
+                    currentCharacterIsSpace = true;
+                    ignoringSpaces = true;
+                }
+            }
+
+            width.addUncommittedWidth(inlineLogicalWidth(current.m_obj) + borderPaddingMarginStart(flowBox) + borderPaddingMarginEnd(flowBox));
+        } else if (current.m_obj->isReplaced()) {
+            RenderBox* replacedBox = toRenderBox(current.m_obj);
+
+            if (atStart)
+                width.updateAvailableWidth(replacedBox->logicalHeight());
+
+            // Break on replaced elements if either has normal white-space.
+            if ((autoWrap || RenderStyle::autoWrap(lastWS)) && (!current.m_obj->isImage() || allowImagesToBreak)) {
+                width.commit();
+                lBreak.moveToStartOf(current.m_obj);
+            }
+
+            if (ignoringSpaces)
+                stopIgnoringSpaces(lineMidpointState, InlineIterator(0, current.m_obj, 0));
+
+            lineInfo.setEmpty(false, m_block, &width);
+            ignoringSpaces = false;
+            currentCharacterIsSpace = false;
+            trailingObjects.clear();
+
+            // Optimize for a common case. If we can't find whitespace after the list
+            // item, then this is all moot.
+            LayoutUnit replacedLogicalWidth = m_block->logicalWidthForChild(replacedBox) + m_block->marginStartForChild(replacedBox) + m_block->marginEndForChild(replacedBox) + inlineLogicalWidth(current.m_obj);
+            if (current.m_obj->isListMarker()) {
+                if (blockStyle->collapseWhiteSpace() && shouldSkipWhitespaceAfterStartObject(m_block, current.m_obj, lineMidpointState)) {
+                    // Like with inline flows, we start ignoring spaces to make sure that any
+                    // additional spaces we see will be discarded.
+                    currentCharacterIsSpace = true;
+                    ignoringSpaces = true;
+                }
+                if (toRenderListMarker(current.m_obj)->isInside())
+                    width.addUncommittedWidth(replacedLogicalWidth);
+            } else
+                width.addUncommittedWidth(replacedLogicalWidth);
+            if (current.m_obj->isRubyRun())
+                width.applyOverhang(toRenderRubyRun(current.m_obj), last, next);
+            // Update prior line break context characters, using U+FFFD (OBJECT REPLACEMENT CHARACTER) for replaced element.
+            renderTextInfo.m_lineBreakIterator.updatePriorContext(replacementCharacter);
+        } else if (current.m_obj->isText()) {
+            if (!current.m_pos)
+                appliedStartWidth = false;
+
+            RenderText* t = toRenderText(current.m_obj);
+
+#if ENABLE(SVG)
+            bool isSVGText = t->isSVGInlineText();
+#endif
+
+            if (t->style()->hasTextCombine() && current.m_obj->isCombineText() && !toRenderCombineText(current.m_obj)->isCombined()) {
+                RenderCombineText* combineRenderer = toRenderCombineText(current.m_obj);
+                combineRenderer->combineText();
+                // The length of the renderer's text may have changed. Increment stale iterator positions
+                if (iteratorIsBeyondEndOfRenderCombineText(lBreak, combineRenderer)) {
+                    ASSERT(iteratorIsBeyondEndOfRenderCombineText(resolver.position(), combineRenderer));
+                    lBreak.increment();
+                    resolver.increment();
+                }
+            }
+
+            RenderStyle* style = t->style(lineInfo.isFirstLine());
+            const Font& f = style->font();
+            bool isFixedPitch = f.isFixedPitch();
+            bool canHyphenate = style->hyphens() == HyphensAuto && WebCore::canHyphenate(style->locale());
+
+            unsigned lastSpace = current.m_pos;
+            float wordSpacing = currentStyle->wordSpacing();
+            float lastSpaceWordSpacing = 0;
+            float wordSpacingForWordMeasurement = 0;
+
+            float wrapW = width.uncommittedWidth() + inlineLogicalWidth(current.m_obj, !appliedStartWidth, true);
+            float charWidth = 0;
+            // 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 = currentStyle->breakWords() && ((autoWrap && !width.committedWidth()) || currWS == PRE);
+            bool midWordBreak = false;
+            bool breakAll = currentStyle->wordBreak() == BreakAllWordBreak && autoWrap;
+            float hyphenWidth = 0;
+#if ENABLE(SVG)
+            if (isSVGText) {
+                breakWords = false;
+                breakAll = false;
+            }
+#endif
+
+            if (t->isWordBreak()) {
+                width.commit();
+                lBreak.moveToStartOf(current.m_obj);
+                ASSERT(current.m_pos == t->textLength());
+            }
+
+            if (renderTextInfo.m_text != t) {
+                updateCounterIfNeeded(t);
+                renderTextInfo.m_text = t;
+                renderTextInfo.m_font = &f;
+                renderTextInfo.m_layout = f.createLayout(t, width.currentWidth(), collapseWhiteSpace);
+                renderTextInfo.m_lineBreakIterator.resetStringAndReleaseIterator(t->text(), style->locale());
+            } else if (renderTextInfo.m_layout && renderTextInfo.m_font != &f) {
+                renderTextInfo.m_font = &f;
+                renderTextInfo.m_layout = f.createLayout(t, width.currentWidth(), collapseWhiteSpace);
+            }
+
+            TextLayout* textLayout = renderTextInfo.m_layout.get();
+
+            // Non-zero only when kerning is enabled and TextLayout isn't used, in which case we measure
+            // words with their trailing space, then subtract its width.
+            float wordTrailingSpaceWidth = (f.typesettingFeatures() & Kerning) && !textLayout ? f.width(constructTextRun(t, f, &space, 1, style)) + wordSpacing : 0;
+
+            UChar lastCharacter = renderTextInfo.m_lineBreakIterator.lastCharacter();
+            UChar secondToLastCharacter = renderTextInfo.m_lineBreakIterator.secondToLastCharacter();
+            for (; current.m_pos < t->textLength(); current.fastIncrementInTextNode()) {
+                bool previousCharacterIsSpace = currentCharacterIsSpace;
+                UChar c = current.current();
+                currentCharacterIsSpace = c == ' ' || c == '\t' || (!preserveNewline && (c == '\n'));
+
+                if (!collapseWhiteSpace || !currentCharacterIsSpace)
+                    lineInfo.setEmpty(false, m_block, &width);
+
+                if (c == softHyphen && autoWrap && !hyphenWidth && style->hyphens() != HyphensNone) {
+                    hyphenWidth = measureHyphenWidth(t, f);
+                    width.addUncommittedWidth(hyphenWidth);
+                }
+
+                bool applyWordSpacing = false;
+
+                if ((breakAll || breakWords) && !midWordBreak) {
+                    wrapW += charWidth;
+                    bool midWordBreakIsBeforeSurrogatePair = U16_IS_LEAD(c) && current.m_pos + 1 < t->textLength() && U16_IS_TRAIL(t->characters()[current.m_pos + 1]);
+                    charWidth = textWidth(t, current.m_pos, midWordBreakIsBeforeSurrogatePair ? 2 : 1, f, width.committedWidth() + wrapW, isFixedPitch, collapseWhiteSpace, 0, textLayout);
+                    midWordBreak = width.committedWidth() + wrapW + charWidth > width.availableWidth();
+                }
+
+                bool betweenWords = c == '\n' || (currWS != PRE && !atStart && isBreakable(renderTextInfo.m_lineBreakIterator, current.m_pos, current.m_nextBreakablePosition)
+                    && (style->hyphens() != HyphensNone || (current.previousInSameNode() != softHyphen)));
+
+                if (betweenWords || midWordBreak) {
+                    bool stoppedIgnoringSpaces = false;
+                    if (ignoringSpaces) {
+                        lastSpaceWordSpacing = 0;
+                        if (!currentCharacterIsSpace) {
+                            // Stop ignoring spaces and begin at this
+                            // new point.
+                            ignoringSpaces = false;
+                            wordSpacingForWordMeasurement = 0;
+                            lastSpace = current.m_pos; // e.g., "Foo    goo", don't add in any of the ignored spaces.
+                            stopIgnoringSpaces(lineMidpointState, InlineIterator(0, current.m_obj, current.m_pos));
+                            stoppedIgnoringSpaces = true;
+                        } else {
+                            // Just keep ignoring these spaces.
+                            goto nextCharacter;
+                        }
+                    }
+
+                    wordMeasurements.grow(wordMeasurements.size() + 1);
+                    WordMeasurement& wordMeasurement = wordMeasurements.last();
+                    
+                    wordMeasurement.renderer = t;
+                    wordMeasurement.endOffset = current.m_pos;
+                    wordMeasurement.startOffset = lastSpace;
+                    
+                    float additionalTmpW;
+                    if (wordTrailingSpaceWidth && c == ' ')
+                        additionalTmpW = textWidth(t, lastSpace, current.m_pos + 1 - lastSpace, f, width.currentWidth(), isFixedPitch, collapseWhiteSpace, &wordMeasurement.fallbackFonts, textLayout) - wordTrailingSpaceWidth;
+                    else
+                        additionalTmpW = textWidth(t, lastSpace, current.m_pos - lastSpace, f, width.currentWidth(), isFixedPitch, collapseWhiteSpace, &wordMeasurement.fallbackFonts, textLayout);
+
+                    wordMeasurement.width = additionalTmpW + wordSpacingForWordMeasurement;
+                    additionalTmpW += lastSpaceWordSpacing;
+                    width.addUncommittedWidth(additionalTmpW);
+                    if (!appliedStartWidth) {
+                        width.addUncommittedWidth(inlineLogicalWidth(current.m_obj, true, false));
+                        appliedStartWidth = true;
+                    }
+
+                    applyWordSpacing = wordSpacing && currentCharacterIsSpace;
+
+                    if (!width.committedWidth() && autoWrap && !width.fitsOnLine())
+                        width.fitBelowFloats();
+
+                    if (autoWrap || breakWords) {
+                        // If we break only after white-space, consider the current character
+                        // as candidate width for this line.
+                        bool lineWasTooWide = false;
+                        if (width.fitsOnLine() && currentCharacterIsSpace && currentStyle->breakOnlyAfterWhiteSpace() && !midWordBreak) {
+                            float charWidth = textWidth(t, current.m_pos, 1, f, width.currentWidth(), isFixedPitch, collapseWhiteSpace, &wordMeasurement.fallbackFonts, textLayout) + (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 (!width.fitsOnLine(charWidth)) {
+                                lineWasTooWide = true;
+                                lBreak.moveTo(current.m_obj, current.m_pos, current.m_nextBreakablePosition);
+                                skipTrailingWhitespace(lBreak, lineInfo);
+                            }
+                        }
+                        if (lineWasTooWide || !width.fitsOnLine()) {
+                            if (canHyphenate && !width.fitsOnLine()) {
+                                tryHyphenating(t, f, style->locale(), consecutiveHyphenatedLines, blockStyle->hyphenationLimitLines(), style->hyphenationLimitBefore(), style->hyphenationLimitAfter(), lastSpace, current.m_pos, width.currentWidth() - additionalTmpW, width.availableWidth(), isFixedPitch, collapseWhiteSpace, lastSpaceWordSpacing, lBreak, current.m_nextBreakablePosition, m_hyphenated);
+                                if (m_hyphenated)
+                                    goto end;
+                            }
+                            if (lBreak.atTextParagraphSeparator()) {
+                                if (!stoppedIgnoringSpaces && current.m_pos > 0)
+                                    ensureCharacterGetsLineBox(lineMidpointState, current);
+                                lBreak.increment();
+                                lineInfo.setPreviousLineBrokeCleanly(true);
+                                wordMeasurement.endOffset = lBreak.m_pos;
+                            }
+                            if (lBreak.m_obj && lBreak.m_pos && lBreak.m_obj->isText() && toRenderText(lBreak.m_obj)->textLength() && toRenderText(lBreak.m_obj)->characterAt(lBreak.m_pos - 1) == softHyphen && style->hyphens() != HyphensNone)
+                                m_hyphenated = true;
+                            if (lBreak.m_pos && lBreak.m_pos != (unsigned)wordMeasurement.endOffset && !wordMeasurement.width) {
+                                if (charWidth) {
+                                    wordMeasurement.endOffset = lBreak.m_pos;
+                                    wordMeasurement.width = charWidth;
+                                }
+                            }
+                            // Didn't fit. Jump to the end unless there's still an opportunity to collapse whitespace.
+                            if (ignoringSpaces || !collapseWhiteSpace || !currentCharacterIsSpace || !previousCharacterIsSpace)
+                                goto end;
+                        } else {
+                            if (!betweenWords || (midWordBreak && !autoWrap))
+                                width.addUncommittedWidth(-additionalTmpW);
+                            if (hyphenWidth) {
+                                // Subtract the width of the soft hyphen out since we fit on a line.
+                                width.addUncommittedWidth(-hyphenWidth);
+                                hyphenWidth = 0;
+                            }
+                        }
+                    }
+
+                    if (c == '\n' && preserveNewline) {
+                        if (!stoppedIgnoringSpaces && current.m_pos > 0)
+                            ensureCharacterGetsLineBox(lineMidpointState, current);
+                        lBreak.moveTo(current.m_obj, current.m_pos, current.m_nextBreakablePosition);
+                        lBreak.increment();
+                        lineInfo.setPreviousLineBrokeCleanly(true);
+                        return lBreak;
+                    }
+
+                    if (autoWrap && betweenWords) {
+                        width.commit();
+                        wrapW = 0;
+                        lBreak.moveTo(current.m_obj, current.m_pos, current.m_nextBreakablePosition);
+                        // 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 && !U16_IS_TRAIL(c) && !(category(c) & (Mark_NonSpacing | Mark_Enclosing | Mark_SpacingCombining))) {
+                        // Remember this as a breakable position in case
+                        // adding the end width forces a break.
+                        lBreak.moveTo(current.m_obj, current.m_pos, current.m_nextBreakablePosition);
+                        midWordBreak &= (breakWords || breakAll);
+                    }
+
+                    if (betweenWords) {
+                        lastSpaceWordSpacing = applyWordSpacing ? wordSpacing : 0;
+                        wordSpacingForWordMeasurement = (applyWordSpacing && wordMeasurement.width) ? wordSpacing : 0;
+                        lastSpace = current.m_pos;
+                    }
+
+                    if (!ignoringSpaces && currentStyle->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.
+                            startIgnoringSpaces(lineMidpointState, ignoreStart);
+                            trailingObjects.updateMidpointsForTrailingBoxes(lineMidpointState, InlineIterator(), TrailingObjects::DoNotCollapseFirstSpace);
+                        }
+                    }
+                } else if (ignoringSpaces) {
+                    // Stop ignoring spaces and begin at this
+                    // new point.
+                    ignoringSpaces = false;
+                    lastSpaceWordSpacing = applyWordSpacing ? wordSpacing : 0;
+                    wordSpacingForWordMeasurement = (applyWordSpacing && wordMeasurements.last().width) ? wordSpacing : 0;
+                    lastSpace = current.m_pos; // e.g., "Foo    goo", don't add in any of the ignored spaces.
+                    stopIgnoringSpaces(lineMidpointState, InlineIterator(0, current.m_obj, current.m_pos));
+                }
+
+#if ENABLE(SVG)
+                if (isSVGText && current.m_pos > 0) {
+                    // Force creation of new InlineBoxes for each absolute positioned character (those that start new text chunks).
+                    if (toRenderSVGInlineText(t)->characterStartsNewTextChunk(current.m_pos))
+                        ensureCharacterGetsLineBox(lineMidpointState, current);
+                }
+#endif
+
+                if (currentCharacterIsSpace && !previousCharacterIsSpace) {
+                    ignoreStart.m_obj = current.m_obj;
+                    ignoreStart.m_pos = current.m_pos;
+                }
+
+                if (!currentCharacterIsSpace && previousCharacterIsSpace) {
+                    if (autoWrap && currentStyle->breakOnlyAfterWhiteSpace())
+                        lBreak.moveTo(current.m_obj, current.m_pos, current.m_nextBreakablePosition);
+                }
+
+                if (collapseWhiteSpace && currentCharacterIsSpace && !ignoringSpaces)
+                    trailingObjects.setTrailingWhitespace(toRenderText(current.m_obj));
+                else if (!currentStyle->collapseWhiteSpace() || !currentCharacterIsSpace)
+                    trailingObjects.clear();
+
+                atStart = false;
+            nextCharacter:
+                secondToLastCharacter = lastCharacter;
+                lastCharacter = c;
+            }
+
+            renderTextInfo.m_lineBreakIterator.setPriorContext(lastCharacter, secondToLastCharacter);
+
+            wordMeasurements.grow(wordMeasurements.size() + 1);
+            WordMeasurement& wordMeasurement = wordMeasurements.last();
+            wordMeasurement.renderer = t;
+
+            // IMPORTANT: current.m_pos is > length here!
+            float additionalTmpW = ignoringSpaces ? 0 : textWidth(t, lastSpace, current.m_pos - lastSpace, f, width.currentWidth(), isFixedPitch, collapseWhiteSpace, &wordMeasurement.fallbackFonts, textLayout);
+            wordMeasurement.startOffset = lastSpace;
+            wordMeasurement.endOffset = current.m_pos;
+            wordMeasurement.width = ignoringSpaces ? 0 : additionalTmpW + wordSpacingForWordMeasurement;
+            additionalTmpW += lastSpaceWordSpacing;
+            width.addUncommittedWidth(additionalTmpW + inlineLogicalWidth(current.m_obj, !appliedStartWidth, includeEndWidth));
+            includeEndWidth = false;
+
+            if (!width.fitsOnLine()) {
+                if (canHyphenate)
+                    tryHyphenating(t, f, style->locale(), consecutiveHyphenatedLines, blockStyle->hyphenationLimitLines(), style->hyphenationLimitBefore(), style->hyphenationLimitAfter(), lastSpace, current.m_pos, width.currentWidth() - additionalTmpW, width.availableWidth(), isFixedPitch, collapseWhiteSpace, lastSpaceWordSpacing, lBreak, current.m_nextBreakablePosition, m_hyphenated);
+
+                if (!m_hyphenated && lBreak.previousInSameNode() == softHyphen && style->hyphens() != HyphensNone)
+                    m_hyphenated = true;
+
+                if (m_hyphenated)
+                    goto end;
+            }
+        } else
+            ASSERT_NOT_REACHED();
+
+        bool checkForBreak = autoWrap;
+        if (width.committedWidth() && !width.fitsOnLine() && lBreak.m_obj && currWS == NOWRAP)
+            checkForBreak = true;
+        else if (next && current.m_obj->isText() && next->isText() && !next->isBR() && (autoWrap || next->style()->autoWrap())) {
+            if (autoWrap && currentCharacterIsSpace)
+                checkForBreak = true;
+            else {
+                RenderText* nextText = toRenderText(next);
+                if (nextText->textLength()) {
+                    UChar c = nextText->characterAt(0);
+                    // 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 the uncommitted width. Just update and continue.
+                    checkForBreak = !currentCharacterIsSpace && (c == ' ' || c == '\t' || (c == '\n' && !next->preservesNewline()));
+                } else if (nextText->isWordBreak())
+                    checkForBreak = true;
+
+                if (!width.fitsOnLine() && !width.committedWidth())
+                    width.fitBelowFloats();
+
+                bool canPlaceOnLine = width.fitsOnLine() || !autoWrapWasEverTrueOnLine;
+                if (canPlaceOnLine && checkForBreak) {
+                    width.commit();
+                    lBreak.moveToStartOf(next);
+                }
+            }
+        }
+
+        if (checkForBreak && !width.fitsOnLine()) {
+            // if we have floats, try to get below them.
+            if (currentCharacterIsSpace && !ignoringSpaces && currentStyle->collapseWhiteSpace())
+                trailingObjects.clear();
+
+            if (width.committedWidth())
+                goto end;
+
+            width.fitBelowFloats();
+
+            // |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 (!width.fitsOnLine())
+                goto end;
+        } else if (blockStyle->autoWrap() && !width.fitsOnLine() && !width.committedWidth()) {
+            // If the container autowraps but the current child does not then we still need to ensure that it
+            // wraps and moves below any floats.
+            width.fitBelowFloats();
+        }
+
+        if (!current.m_obj->isFloatingOrOutOfFlowPositioned()) {
+            last = current.m_obj;
+            if (last->isReplaced() && autoWrap && (!last->isImage() || allowImagesToBreak) && (!last->isListMarker() || toRenderListMarker(last)->isInside())) {
+                width.commit();
+                lBreak.moveToStartOf(next);
+            }
+        }
+
+        // Clear out our character space bool, since inline <pre>s don't collapse whitespace
+        // with adjacent inline normal/nowrap spans.
+        if (!collapseWhiteSpace)
+            currentCharacterIsSpace = false;
+
+        current.moveToStartOf(next);
+        atStart = false;
+    }
+
+    if (width.fitsOnLine() || lastWS == NOWRAP)
+        lBreak.clear();
+
+ end:
+    if (lBreak == resolver.position() && (!lBreak.m_obj || !lBreak.m_obj->isBR())) {
+        // we just add as much as possible
+        if (blockStyle->whiteSpace() == PRE && !current.m_pos) {
+            lBreak.moveTo(last, last->isText() ? last->length() : 0);
+        } else if (lBreak.m_obj) {
+            // 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.moveTo(current.m_obj, current.m_pos);
+        }
+    }
+
+    // FIXME Bug 100049: We do not need to consume input in a multi-segment line
+    // unless no segment will.
+    // make sure we consume at least one char/object.
+    if (lBreak == resolver.position())
+        lBreak.increment();
+
+    // Sanity check our midpoints.
+    checkMidpoints(lineMidpointState, lBreak);
+
+    trailingObjects.updateMidpointsForTrailingBoxes(lineMidpointState, lBreak, TrailingObjects::CollapseFirstSpace);
+
+    // 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.m_pos > 0) {
+        lBreak.m_pos--;
+        lBreak.increment();
+    }
+
+    return lBreak;
+}
+
+void RenderBlock::addOverflowFromInlineChildren()
+{
+    LayoutUnit endPadding = hasOverflowClip() ? paddingEnd() : LayoutUnit();
+    // FIXME: Need to find another way to do this, since scrollbars could show when we don't want them to.
+    if (hasOverflowClip() && !endPadding && node() && node()->isRootEditableElement() && style()->isLeftToRightDirection())
+        endPadding = 1;
+    for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) {
+        addLayoutOverflow(curr->paddedLayoutOverflowRect(endPadding));
+        if (!hasOverflowClip())
+            addVisualOverflow(curr->visualOverflowRect(curr->lineTop(), curr->lineBottom()));
+    }
+}
+
+void RenderBlock::deleteEllipsisLineBoxes()
+{
+    ETextAlign textAlign = style()->textAlign();
+    bool ltr = style()->isLeftToRightDirection();
+    bool firstLine = true;
+    for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) {
+        if (curr->hasEllipsisBox()) {
+            curr->clearTruncation();
+
+            // Shift the line back where it belongs if we cannot accomodate an ellipsis.
+            float logicalLeft = pixelSnappedLogicalLeftOffsetForLine(curr->lineTop(), firstLine);
+            float availableLogicalWidth = logicalRightOffsetForLine(curr->lineTop(), false) - logicalLeft;
+            float totalLogicalWidth = curr->logicalWidth();
+            updateLogicalWidthForAlignment(textAlign, 0, logicalLeft, totalLogicalWidth, availableLogicalWidth, 0);
+
+            if (ltr)
+                curr->adjustLogicalPosition((logicalLeft - curr->logicalLeft()), 0);
+            else
+                curr->adjustLogicalPosition(-(curr->logicalLeft() - logicalLeft), 0);
+        }
+        firstLine = false;
+    }
+}
+
+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"
+    const Font& font = style()->font();
+    DEFINE_STATIC_LOCAL(AtomicString, ellipsisStr, (&horizontalEllipsis, 1));
+    const Font& firstLineFont = firstLineStyle()->font();
+    int firstLineEllipsisWidth = firstLineFont.width(constructTextRun(this, firstLineFont, &horizontalEllipsis, 1, firstLineStyle()));
+    int ellipsisWidth = (font == firstLineFont) ? firstLineEllipsisWidth : font.width(constructTextRun(this, font, &horizontalEllipsis, 1, style()));
+
+    // 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()->isLeftToRightDirection();
+    ETextAlign textAlign = style()->textAlign();
+    bool firstLine = true;
+    for (RootInlineBox* curr = firstRootBox(); curr; curr = curr->nextRootBox()) {
+        // FIXME: Use pixelSnappedLogicalRightOffsetForLine instead of snapping it ourselves once the column workaround in said method has been fixed.
+        // https://bugs.webkit.org/show_bug.cgi?id=105461
+        int blockRightEdge = snapSizeToPixel(logicalRightOffsetForLine(curr->lineTop(), firstLine), curr->x());
+        int blockLeftEdge = pixelSnappedLogicalLeftOffsetForLine(curr->lineTop(), firstLine);
+        int lineBoxEdge = ltr ? snapSizeToPixel(curr->x() + curr->logicalWidth(), curr->x()) : snapSizeToPixel(curr->x(), 0);
+        if ((ltr && lineBoxEdge > blockRightEdge) || (!ltr && lineBoxEdge < blockLeftEdge)) {
+            // 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.
+
+            LayoutUnit width = firstLine ? firstLineEllipsisWidth : ellipsisWidth;
+            LayoutUnit blockEdge = ltr ? blockRightEdge : blockLeftEdge;
+            if (curr->lineCanAccommodateEllipsis(ltr, blockEdge, lineBoxEdge, width)) {
+                float totalLogicalWidth = curr->placeEllipsis(ellipsisStr, ltr, blockLeftEdge, blockRightEdge, width);
+
+                float logicalLeft = 0; // We are only intersted in the delta from the base position.
+                float truncatedWidth = pixelSnappedLogicalRightOffsetForLine(curr->lineTop(), firstLine);
+                updateLogicalWidthForAlignment(textAlign, 0, logicalLeft, totalLogicalWidth, truncatedWidth, 0);
+                if (ltr)
+                    curr->adjustLogicalPosition(logicalLeft, 0);
+                else
+                    curr->adjustLogicalPosition(-(truncatedWidth - (logicalLeft + totalLogicalWidth)), 0);
+            }
+        }
+        firstLine = false;
+    }
+}
+
+bool RenderBlock::positionNewFloatOnLine(FloatingObject* newFloat, FloatingObject* lastFloatFromPreviousLine, LineInfo& lineInfo, LineWidth& width)
+{
+    if (!positionNewFloats())
+        return false;
+
+    width.shrinkAvailableWidthForNewFloatIfNeeded(newFloat);
+
+    // We only connect floats to lines for pagination purposes if the floats occur at the start of
+    // the line and the previous line had a hard break (so this line is either the first in the block
+    // or follows a <br>).
+    if (!newFloat->m_paginationStrut || !lineInfo.previousLineBrokeCleanly() || !lineInfo.isEmpty())
+        return true;
+
+    const FloatingObjectSet& floatingObjectSet = m_floatingObjects->set();
+    ASSERT(floatingObjectSet.last() == newFloat);
+
+    LayoutUnit floatLogicalTop = logicalTopForFloat(newFloat);
+    int paginationStrut = newFloat->m_paginationStrut;
+
+    if (floatLogicalTop - paginationStrut != logicalHeight() + lineInfo.floatPaginationStrut())
+        return true;
+
+    FloatingObjectSetIterator it = floatingObjectSet.end();
+    --it; // Last float is newFloat, skip that one.
+    FloatingObjectSetIterator begin = floatingObjectSet.begin();
+    while (it != begin) {
+        --it;
+        FloatingObject* f = *it;
+        if (f == lastFloatFromPreviousLine)
+            break;
+        if (logicalTopForFloat(f) == logicalHeight() + lineInfo.floatPaginationStrut()) {
+            f->m_paginationStrut += paginationStrut;
+            RenderBox* o = f->m_renderer;
+            setLogicalTopForChild(o, logicalTopForChild(o) + marginBeforeForChild(o) + paginationStrut);
+            if (o->isRenderBlock())
+                toRenderBlock(o)->setChildNeedsLayout(true, MarkOnlyThis);
+            o->layoutIfNeeded();
+            // Save the old logical top before calling removePlacedObject which will set
+            // isPlaced to false. Otherwise it will trigger an assert in logicalTopForFloat.
+            LayoutUnit oldLogicalTop = logicalTopForFloat(f);
+            m_floatingObjects->removePlacedObject(f);
+            setLogicalTopForFloat(f, oldLogicalTop + paginationStrut);
+            m_floatingObjects->addPlacedObject(f);
+        }
+    }
+
+    // Just update the line info's pagination strut without altering our logical height yet. If the line ends up containing
+    // no content, then we don't want to improperly grow the height of the block.
+    lineInfo.setFloatPaginationStrut(lineInfo.floatPaginationStrut() + paginationStrut);
+    return true;
+}
+
+LayoutUnit RenderBlock::startAlignedOffsetForLine(LayoutUnit position, bool firstLine)
+{
+    ETextAlign textAlign = style()->textAlign();
+
+    if (textAlign == TASTART) // FIXME: Handle TAEND here
+        return startOffsetForLine(position, firstLine);
+
+    // updateLogicalWidthForAlignment() handles the direction of the block so no need to consider it here
+    float totalLogicalWidth = 0;
+    float logicalLeft = logicalLeftOffsetForLine(logicalHeight(), false);
+    float availableLogicalWidth = logicalRightOffsetForLine(logicalHeight(), false) - logicalLeft;
+    updateLogicalWidthForAlignment(textAlign, 0, logicalLeft, totalLogicalWidth, availableLogicalWidth, 0);
+
+    if (!style()->isLeftToRightDirection())
+        return logicalWidth() - logicalLeft;
+    return logicalLeft;
+}
+
+
+void RenderBlock::layoutLineGridBox()
+{
+    if (style()->lineGrid() == RenderStyle::initialLineGrid()) {
+        setLineGridBox(0);
+        return;
+    }
+    
+    setLineGridBox(0);
+
+    RootInlineBox* lineGridBox = new (renderArena()) RootInlineBox(this);
+    lineGridBox->setHasTextChildren(); // Needed to make the line ascent/descent actually be honored in quirks mode.
+    lineGridBox->setConstructed();
+    GlyphOverflowAndFallbackFontsMap textBoxDataMap;
+    VerticalPositionCache verticalPositionCache;
+    lineGridBox->alignBoxesInBlockDirection(logicalHeight(), textBoxDataMap, verticalPositionCache);
+    
+    setLineGridBox(lineGridBox);
+    
+    // FIXME: If any of the characteristics of the box change compared to the old one, then we need to do a deep dirtying
+    // (similar to what happens when the page height changes). Ideally, though, we only do this if someone is actually snapping
+    // to this grid.
+}
+
+}
diff --git a/Source/core/rendering/RenderBox.cpp b/Source/core/rendering/RenderBox.cpp
new file mode 100644
index 0000000..c61b155
--- /dev/null
+++ b/Source/core/rendering/RenderBox.cpp
@@ -0,0 +1,4587 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
+ *           (C) 2005, 2006 Samuel Weinig (sam.weinig@gmail.com)
+ * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010 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 "core/rendering/RenderBox.h"
+
+#include <math.h>
+#include <algorithm>
+#include "HTMLNames.h"
+#include "core/dom/Document.h"
+#include "core/dom/WebCoreMemoryInstrumentation.h"
+#include "core/editing/htmlediting.h"
+#include "core/html/HTMLElement.h"
+#include "core/html/HTMLFrameOwnerElement.h"
+#include "core/loader/cache/CachedImage.h"
+#include "core/page/Chrome.h"
+#include "core/page/ChromeClient.h"
+#include "core/page/Frame.h"
+#include "core/page/FrameView.h"
+#include "core/page/Page.h"
+#include "core/platform/ScrollbarTheme.h"
+#include "core/platform/graphics/FloatQuad.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/platform/graphics/ImageBuffer.h"
+#include "core/platform/graphics/transforms/TransformState.h"
+#include "core/rendering/HitTestResult.h"
+#include "core/rendering/PaintInfo.h"
+#include "core/rendering/RenderArena.h"
+#include "core/rendering/RenderBoxRegionInfo.h"
+#include "core/rendering/RenderFlexibleBox.h"
+#include "core/rendering/RenderFlowThread.h"
+#include "core/rendering/RenderGeometryMap.h"
+#include "core/rendering/RenderInline.h"
+#include "core/rendering/RenderLayer.h"
+#include "core/rendering/RenderLayerCompositor.h"
+#include "core/rendering/RenderPart.h"
+#include "core/rendering/RenderRegion.h"
+#include "core/rendering/RenderTableCell.h"
+#include "core/rendering/RenderTheme.h"
+#include "core/rendering/RenderView.h"
+#include <wtf/MemoryInstrumentationHashMap.h>
+
+using namespace std;
+
+namespace WTF {
+template<> struct SequenceMemoryInstrumentationTraits<WebCore::LayoutUnit> {
+    template <typename I> static void reportMemoryUsage(I, I, MemoryClassInfo&) { }
+};
+}
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+// Used by flexible boxes when flexing this element and by table cells.
+typedef WTF::HashMap<const RenderBox*, LayoutUnit> OverrideSizeMap;
+static OverrideSizeMap* gOverrideHeightMap = 0;
+static OverrideSizeMap* gOverrideWidthMap = 0;
+
+// Used by grid elements to properly size their grid items.
+static OverrideSizeMap* gOverrideContainingBlockLogicalHeightMap = 0;
+static OverrideSizeMap* gOverrideContainingBlockLogicalWidthMap = 0;
+
+
+// Size of border belt for autoscroll. When mouse pointer in border belt,
+// autoscroll is started.
+static const int autoscrollBeltSize = 20;
+static const unsigned backgroundObscurationTestMaxDepth = 4;
+
+bool RenderBox::s_hadOverflowClip = false;
+
+static bool skipBodyBackground(const RenderBox* bodyElementRenderer)
+{
+    ASSERT(bodyElementRenderer->isBody());
+    // The <body> only paints its background if the root element has defined a background independent of the body,
+    // or if the <body>'s parent is not the document element's renderer (e.g. inside SVG foreignObject).
+    RenderObject* documentElementRenderer = bodyElementRenderer->document()->documentElement()->renderer();
+    return documentElementRenderer
+        && !documentElementRenderer->hasBackground()
+        && (documentElementRenderer == bodyElementRenderer->parent());
+}
+
+RenderBox::RenderBox(ContainerNode* node)
+    : RenderBoxModelObject(node)
+    , m_minPreferredLogicalWidth(-1)
+    , m_maxPreferredLogicalWidth(-1)
+    , m_inlineBoxWrapper(0)
+{
+    setIsBox();
+}
+
+RenderBox::~RenderBox()
+{
+}
+
+LayoutRect RenderBox::borderBoxRectInRegion(RenderRegion* region, LayoutUnit offsetFromTopOfFirstPage, RenderBoxRegionInfoFlags cacheFlag) const
+{
+    if (!region)
+        return borderBoxRect();
+    
+    // Compute the logical width and placement in this region.
+    RenderBoxRegionInfo* boxInfo = renderBoxRegionInfo(region, offsetFromTopOfFirstPage, cacheFlag);
+    if (!boxInfo)
+        return borderBoxRect();
+
+    // We have cached insets.
+    LayoutUnit logicalWidth = boxInfo->logicalWidth();
+    LayoutUnit logicalLeft = boxInfo->logicalLeft();
+        
+    // Now apply the parent inset since it is cumulative whenever anything in the containing block chain shifts.
+    // FIXME: Doesn't work right with perpendicular writing modes.
+    const RenderBlock* currentBox = containingBlock();
+    offsetFromTopOfFirstPage -= logicalTop();
+    RenderBoxRegionInfo* currentBoxInfo = currentBox->renderBoxRegionInfo(region, offsetFromTopOfFirstPage);
+    while (currentBoxInfo && currentBoxInfo->isShifted()) {
+        if (currentBox->style()->direction() == LTR)
+            logicalLeft += currentBoxInfo->logicalLeft();
+        else
+            logicalLeft -= (currentBox->logicalWidth() - currentBoxInfo->logicalWidth()) - currentBoxInfo->logicalLeft();
+        offsetFromTopOfFirstPage -= logicalTop();
+        currentBox = currentBox->containingBlock();
+        region = currentBox->clampToStartAndEndRegions(region);
+        currentBoxInfo = currentBox->renderBoxRegionInfo(region, offsetFromTopOfFirstPage);
+    }
+    
+    if (cacheFlag == DoNotCacheRenderBoxRegionInfo)
+        delete boxInfo;
+
+    if (isHorizontalWritingMode())
+        return LayoutRect(logicalLeft, 0, logicalWidth, height());
+    return LayoutRect(0, logicalLeft, width(), logicalWidth);
+}
+
+void RenderBox::clearRenderBoxRegionInfo()
+{
+    if (isRenderFlowThread())
+        return;
+
+    RenderFlowThread* flowThread = flowThreadContainingBlock();
+    if (flowThread)
+        flowThread->removeRenderBoxRegionInfo(this);
+}
+
+void RenderBox::willBeDestroyed()
+{
+    clearOverrideSize();
+    clearContainingBlockOverrideSize();
+
+    RenderBlock::removePercentHeightDescendantIfNeeded(this);
+
+    ExclusionShapeOutsideInfo::removeInfo(this);
+
+    RenderBoxModelObject::willBeDestroyed();
+}
+
+void RenderBox::removeFloatingOrPositionedChildFromBlockLists()
+{
+    ASSERT(isFloatingOrOutOfFlowPositioned());
+
+    if (documentBeingDestroyed())
+        return;
+
+    if (isFloating()) {
+        RenderBlock* parentBlock = 0;
+        for (RenderObject* curr = parent(); curr && !curr->isRenderView(); curr = curr->parent()) {
+            if (curr->isRenderBlock()) {
+                RenderBlock* currBlock = toRenderBlock(curr);
+                if (!parentBlock || currBlock->containsFloat(this))
+                    parentBlock = currBlock;
+            }
+        }
+
+        if (parentBlock) {
+            RenderObject* parent = parentBlock->parent();
+            if (parent && parent->isFlexibleBoxIncludingDeprecated())
+                parentBlock = toRenderBlock(parent);
+
+            parentBlock->markSiblingsWithFloatsForLayout(this);
+            parentBlock->markAllDescendantsWithFloatsForLayout(this, false);
+        }
+    }
+
+    if (isOutOfFlowPositioned())
+        RenderBlock::removePositionedObject(this);
+}
+
+void RenderBox::styleWillChange(StyleDifference diff, const RenderStyle* newStyle)
+{
+    s_hadOverflowClip = hasOverflowClip();
+
+    RenderStyle* oldStyle = style();
+    if (oldStyle) {
+        // 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 >= StyleDifferenceRepaint && node() &&
+            (node()->hasTagName(htmlTag) || node()->hasTagName(bodyTag))) {
+            view()->repaint();
+            
+            if (oldStyle->hasEntirelyFixedBackground() != newStyle->hasEntirelyFixedBackground())
+                view()->compositor()->rootFixedBackgroundsChanged();
+        }
+        
+        // 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 == StyleDifferenceLayout && parent() && oldStyle->position() != newStyle->position()) {
+            markContainingBlocksForLayout();
+            if (oldStyle->position() == StaticPosition)
+                repaint();
+            else if (newStyle->hasOutOfFlowPosition())
+                parent()->setChildNeedsLayout(true);
+            if (isFloating() && !isOutOfFlowPositioned() && newStyle->hasOutOfFlowPosition())
+                removeFloatingOrPositionedChildFromBlockLists();
+        }
+    } else if (newStyle && isBody())
+        view()->repaint();
+
+    RenderBoxModelObject::styleWillChange(diff, newStyle);
+}
+
+void RenderBox::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
+{
+    // Horizontal writing mode definition is updated in RenderBoxModelObject::updateFromStyle,
+    // (as part of the RenderBoxModelObject::styleDidChange call below). So, we can safely cache the horizontal
+    // writing mode value before style change here.
+    bool oldHorizontalWritingMode = isHorizontalWritingMode();
+
+    RenderBoxModelObject::styleDidChange(diff, oldStyle);
+
+    RenderStyle* newStyle = style();
+    if (needsLayout() && oldStyle) {
+        RenderBlock::removePercentHeightDescendantIfNeeded(this);
+
+        // Normally we can do optimized positioning layout for absolute/fixed positioned objects. There is one special case, however, which is
+        // when the positioned object's margin-before is changed. In this case the parent has to get a layout in order to run margin collapsing
+        // to determine the new static position.
+        if (isOutOfFlowPositioned() && newStyle->hasStaticBlockPosition(isHorizontalWritingMode()) && oldStyle->marginBefore() != newStyle->marginBefore()
+            && parent() && !parent()->normalChildNeedsLayout())
+            parent()->setChildNeedsLayout(true);
+    }
+
+    if (RenderBlock::hasPercentHeightContainerMap() && firstChild()
+        && oldHorizontalWritingMode != isHorizontalWritingMode())
+        RenderBlock::clearPercentHeightDescendantsFrom(this);
+
+    // 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 && newStyle && oldStyle->effectiveZoom() != newStyle->effectiveZoom()) {
+        if (int left = layer()->scrollXOffset()) {
+            left = (left / oldStyle->effectiveZoom()) * newStyle->effectiveZoom();
+            layer()->scrollToXOffset(left);
+        }
+        if (int top = layer()->scrollYOffset()) {
+            top = (top / oldStyle->effectiveZoom()) * newStyle->effectiveZoom();
+            layer()->scrollToYOffset(top);
+        }
+    }
+
+    // Our opaqueness might have changed without triggering layout.
+    if (diff == StyleDifferenceRepaint || diff == StyleDifferenceRepaintLayer) {
+        RenderObject* parentToInvalidate = parent();
+        for (unsigned i = 0; i < backgroundObscurationTestMaxDepth && parentToInvalidate; ++i) {
+            parentToInvalidate->invalidateBackgroundObscurationStatus();
+            parentToInvalidate = parentToInvalidate->parent();
+        }
+    }
+
+    bool isBodyRenderer = isBody();
+    bool isRootRenderer = isRoot();
+
+    // Set the text color if we're the body.
+    if (isBodyRenderer)
+        document()->setTextColor(newStyle->visitedDependentColor(CSSPropertyColor));
+
+    if (isRootRenderer || isBodyRenderer) {
+        // Propagate the new writing mode and direction up to the RenderView.
+        RenderView* viewRenderer = view();
+        RenderStyle* viewStyle = viewRenderer->style();
+        if (viewStyle->direction() != newStyle->direction() && (isRootRenderer || !document()->directionSetOnDocumentElement())) {
+            viewStyle->setDirection(newStyle->direction());
+            if (isBodyRenderer)
+                document()->documentElement()->renderer()->style()->setDirection(newStyle->direction());
+            setNeedsLayoutAndPrefWidthsRecalc();
+        }
+
+        if (viewStyle->writingMode() != newStyle->writingMode() && (isRootRenderer || !document()->writingModeSetOnDocumentElement())) {
+            viewStyle->setWritingMode(newStyle->writingMode());
+            viewRenderer->setHorizontalWritingMode(newStyle->isHorizontalWritingMode());
+            viewRenderer->markAllDescendantsWithFloatsForLayout();
+            if (isBodyRenderer) {
+                document()->documentElement()->renderer()->style()->setWritingMode(newStyle->writingMode());
+                document()->documentElement()->renderer()->setHorizontalWritingMode(newStyle->isHorizontalWritingMode());
+            }
+            setNeedsLayoutAndPrefWidthsRecalc();
+        }
+
+        frame()->view()->recalculateScrollbarOverlayStyle();
+    }
+
+    updateExclusionShapeOutsideInfoAfterStyleChange(style()->shapeOutside(), oldStyle ? oldStyle->shapeOutside() : 0);
+}
+
+void RenderBox::updateExclusionShapeOutsideInfoAfterStyleChange(const ExclusionShapeValue* shapeOutside, const ExclusionShapeValue* oldShapeOutside)
+{
+    // FIXME: A future optimization would do a deep comparison for equality. (bug 100811)
+    if (shapeOutside == oldShapeOutside)
+        return;
+
+    if (shapeOutside) {
+        ExclusionShapeOutsideInfo* exclusionShapeOutsideInfo = ExclusionShapeOutsideInfo::ensureInfo(this);
+        exclusionShapeOutsideInfo->dirtyShapeSize();
+    } else
+        ExclusionShapeOutsideInfo::removeInfo(this);
+}
+
+void RenderBox::updateFromStyle()
+{
+    RenderBoxModelObject::updateFromStyle();
+
+    RenderStyle* styleToUse = style();
+    bool isRootObject = isRoot();
+    bool isViewObject = isRenderView();
+
+    // The root and the RenderView always paint their backgrounds/borders.
+    if (isRootObject || isViewObject)
+        setHasBoxDecorations(true);
+
+    setFloating(!isOutOfFlowPositioned() && styleToUse->isFloating());
+
+    // We also handle <body> and <html>, whose overflow applies to the viewport.
+    if (styleToUse->overflowX() != OVISIBLE && !isRootObject && isRenderBlock()) {
+        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() == node() &&
+                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(styleToUse->hasTransformRelatedProperty());
+    setHasReflection(styleToUse->boxReflect());
+}
+
+void RenderBox::layout()
+{
+    StackStats::LayoutCheckPoint layoutCheckPoint;
+    ASSERT(needsLayout());
+
+    RenderObject* child = firstChild();
+    if (!child) {
+        setNeedsLayout(false);
+        return;
+    }
+
+    LayoutStateMaintainer statePusher(view(), this, locationOffset(), style()->isFlippedBlocksWritingMode());
+    while (child) {
+        child->layoutIfNeeded();
+        ASSERT(!child->needsLayout());
+        child = child->nextSibling();
+    }
+    statePusher.pop();
+    invalidateBackgroundObscurationStatus();
+    setNeedsLayout(false);
+}
+
+// More IE extensions.  clientWidth and clientHeight represent the interior of an object
+// excluding border and scrollbar.
+LayoutUnit RenderBox::clientWidth() const
+{
+    return width() - borderLeft() - borderRight() - verticalScrollbarWidth();
+}
+
+LayoutUnit RenderBox::clientHeight() const
+{
+    return height() - borderTop() - borderBottom() - horizontalScrollbarHeight();
+}
+
+int RenderBox::pixelSnappedClientWidth() const
+{
+    return snapSizeToPixel(clientWidth(), x() + clientLeft());
+}
+
+int RenderBox::pixelSnappedClientHeight() const
+{
+    return snapSizeToPixel(clientHeight(), y() + clientTop());
+}
+
+int RenderBox::pixelSnappedOffsetWidth() const
+{
+    return snapSizeToPixel(offsetWidth(), x() + clientLeft());
+}
+
+int RenderBox::pixelSnappedOffsetHeight() const
+{
+    return snapSizeToPixel(offsetHeight(), y() + clientTop());
+}
+
+int RenderBox::scrollWidth() const
+{
+    if (hasOverflowClip())
+        return layer()->scrollWidth();
+    // For objects with visible overflow, this matches IE.
+    // FIXME: Need to work right with writing modes.
+    if (style()->isLeftToRightDirection())
+        return snapSizeToPixel(max(clientWidth(), layoutOverflowRect().maxX() - borderLeft()), x() + clientLeft());
+    return clientWidth() - min<LayoutUnit>(0, layoutOverflowRect().x() - borderLeft());
+}
+
+int RenderBox::scrollHeight() const
+{
+    if (hasOverflowClip())
+        return layer()->scrollHeight();
+    // For objects with visible overflow, this matches IE.
+    // FIXME: Need to work right with writing modes.
+    return snapSizeToPixel(max(clientHeight(), layoutOverflowRect().maxY() - borderTop()), y() + clientTop());
+}
+
+int RenderBox::scrollLeft() const
+{
+    return hasOverflowClip() ? layer()->scrollXOffset() : 0;
+}
+
+int RenderBox::scrollTop() const
+{
+    return hasOverflowClip() ? layer()->scrollYOffset() : 0;
+}
+
+void RenderBox::setScrollLeft(int newLeft)
+{
+    if (hasOverflowClip())
+        layer()->scrollToXOffset(newLeft, RenderLayer::ScrollOffsetClamped);
+}
+
+void RenderBox::setScrollTop(int newTop)
+{
+    if (hasOverflowClip())
+        layer()->scrollToYOffset(newTop, RenderLayer::ScrollOffsetClamped);
+}
+
+void RenderBox::absoluteRects(Vector<IntRect>& rects, const LayoutPoint& accumulatedOffset) const
+{
+    rects.append(pixelSnappedIntRect(accumulatedOffset, size()));
+}
+
+void RenderBox::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed) const
+{
+    quads.append(localToAbsoluteQuad(FloatRect(0, 0, width(), height()), 0 /* mode */, wasFixed));
+}
+
+void RenderBox::updateLayerTransform()
+{
+    // Transform-origin depends on box size, so we need to update the layer transform after layout.
+    if (hasLayer())
+        layer()->updateTransform();
+}
+
+LayoutUnit RenderBox::constrainLogicalWidthInRegionByMinMax(LayoutUnit logicalWidth, LayoutUnit availableWidth, RenderBlock* cb, RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage) const
+{
+    RenderStyle* styleToUse = style();
+    if (!styleToUse->logicalMaxWidth().isUndefined())
+        logicalWidth = min(logicalWidth, computeLogicalWidthInRegionUsing(MaxSize, styleToUse->logicalMaxWidth(), availableWidth, cb, region, offsetFromLogicalTopOfFirstPage));
+    return max(logicalWidth, computeLogicalWidthInRegionUsing(MinSize, styleToUse->logicalMinWidth(), availableWidth, cb, region, offsetFromLogicalTopOfFirstPage));
+}
+
+LayoutUnit RenderBox::constrainLogicalHeightByMinMax(LayoutUnit logicalHeight, LayoutUnit intrinsicContentHeight) const
+{
+    RenderStyle* styleToUse = style();
+    if (!styleToUse->logicalMaxHeight().isUndefined()) {
+        LayoutUnit maxH = computeLogicalHeightUsing(styleToUse->logicalMaxHeight(), intrinsicContentHeight);
+        if (maxH != -1)
+            logicalHeight = min(logicalHeight, maxH);
+    }
+    return max(logicalHeight, computeLogicalHeightUsing(styleToUse->logicalMinHeight(), intrinsicContentHeight));
+}
+
+LayoutUnit RenderBox::constrainContentBoxLogicalHeightByMinMax(LayoutUnit logicalHeight, LayoutUnit intrinsicContentHeight) const
+{
+    RenderStyle* styleToUse = style();
+    if (!styleToUse->logicalMaxHeight().isUndefined()) {
+        LayoutUnit maxH = computeContentLogicalHeight(styleToUse->logicalMaxHeight(), intrinsicContentHeight);
+        if (maxH != -1)
+            logicalHeight = min(logicalHeight, maxH);
+    }
+    return max(logicalHeight, computeContentLogicalHeight(styleToUse->logicalMinHeight(), intrinsicContentHeight));
+}
+
+IntRect RenderBox::absoluteContentBox() const
+{
+    // This is wrong with transforms and flipped writing modes.
+    IntRect rect = pixelSnappedIntRect(contentBoxRect());
+    FloatPoint absPos = localToAbsolute();
+    rect.move(absPos.x(), absPos.y());
+    return rect;
+}
+
+FloatQuad RenderBox::absoluteContentQuad() const
+{
+    LayoutRect rect = contentBoxRect();
+    return localToAbsoluteQuad(FloatRect(rect));
+}
+
+LayoutRect RenderBox::outlineBoundsForRepaint(const RenderLayerModelObject* repaintContainer, const RenderGeometryMap* geometryMap) const
+{
+    LayoutRect box = borderBoundingBox();
+    adjustRectForOutlineAndShadow(box);
+
+    FloatQuad containerRelativeQuad;
+    if (geometryMap)
+        containerRelativeQuad = geometryMap->mapToContainer(box, repaintContainer);
+    else
+        containerRelativeQuad = localToContainerQuad(FloatRect(box), repaintContainer);
+
+    box = containerRelativeQuad.enclosingBoundingBox();
+
+    // FIXME: layoutDelta needs to be applied in parts before/after transforms and
+    // repaint containers. https://bugs.webkit.org/show_bug.cgi?id=23308
+    box.move(view()->layoutDelta());
+
+    return box;
+}
+
+void RenderBox::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint& additionalOffset, const RenderLayerModelObject*)
+{
+    if (!size().isEmpty())
+        rects.append(pixelSnappedIntRect(additionalOffset, size()));
+}
+
+LayoutRect RenderBox::reflectionBox() const
+{
+    LayoutRect result;
+    if (!style()->boxReflect())
+        return result;
+    LayoutRect box = borderBoxRect();
+    result = box;
+    switch (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 RenderBox::reflectionOffset() const
+{
+    if (!style()->boxReflect())
+        return 0;
+    RenderView* renderView = view();
+    if (style()->boxReflect()->direction() == ReflectionLeft || style()->boxReflect()->direction() == ReflectionRight)
+        return valueForLength(style()->boxReflect()->offset(), borderBoxRect().width(), renderView);
+    return valueForLength(style()->boxReflect()->offset(), borderBoxRect().height(), renderView);
+}
+
+LayoutRect RenderBox::reflectedRect(const LayoutRect& r) const
+{
+    if (!style()->boxReflect())
+        return LayoutRect();
+
+    LayoutRect box = borderBoxRect();
+    LayoutRect result = r;
+    switch (style()->boxReflect()->direction()) {
+        case ReflectionBelow:
+            result.setY(box.maxY() + reflectionOffset() + (box.maxY() - r.maxY()));
+            break;
+        case ReflectionAbove:
+            result.setY(box.y() - reflectionOffset() - box.height() + (box.maxY() - r.maxY()));
+            break;
+        case ReflectionLeft:
+            result.setX(box.x() - reflectionOffset() - box.width() + (box.maxX() - r.maxX()));
+            break;
+        case ReflectionRight:
+            result.setX(box.maxX() + reflectionOffset() + (box.maxX() - r.maxX()));
+            break;
+    }
+    return result;
+}
+
+bool RenderBox::includeVerticalScrollbarSize() const
+{
+    return hasOverflowClip() && !layer()->hasOverlayScrollbars()
+        && (style()->overflowY() == OSCROLL || style()->overflowY() == OAUTO);
+}
+
+bool RenderBox::includeHorizontalScrollbarSize() const
+{
+    return hasOverflowClip() && !layer()->hasOverlayScrollbars()
+        && (style()->overflowX() == OSCROLL || style()->overflowX() == OAUTO);
+}
+
+int RenderBox::verticalScrollbarWidth() const
+{
+    return includeVerticalScrollbarSize() ? layer()->verticalScrollbarWidth() : 0;
+}
+
+int RenderBox::horizontalScrollbarHeight() const
+{
+    return includeHorizontalScrollbarSize() ? layer()->horizontalScrollbarHeight() : 0;
+}
+
+int RenderBox::instrinsicScrollbarLogicalWidth() const
+{
+    if (!hasOverflowClip())
+        return 0;
+
+    if (isHorizontalWritingMode() && style()->overflowY() == OSCROLL) {
+        ASSERT(layer()->hasVerticalScrollbar());
+        return verticalScrollbarWidth();
+    }
+
+    if (!isHorizontalWritingMode() && style()->overflowX() == OSCROLL) {
+        ASSERT(layer()->hasHorizontalScrollbar());
+        return horizontalScrollbarHeight();
+    }
+
+    return 0;
+}
+
+bool RenderBox::scroll(ScrollDirection direction, ScrollGranularity granularity, float multiplier, Node** stopNode)
+{
+    RenderLayer* l = layer();
+    if (l && l->scroll(direction, granularity, multiplier)) {
+        if (stopNode)
+            *stopNode = node();
+        return true;
+    }
+
+    if (stopNode && *stopNode && *stopNode == node())
+        return true;
+
+    RenderBlock* b = containingBlock();
+    if (b && !b->isRenderView())
+        return b->scroll(direction, granularity, multiplier, stopNode);
+    return false;
+}
+
+bool RenderBox::logicalScroll(ScrollLogicalDirection direction, ScrollGranularity granularity, float multiplier, Node** stopNode)
+{
+    bool scrolled = false;
+    
+    RenderLayer* l = layer();
+    if (l) {
+        if (l->scroll(logicalToPhysical(direction, isHorizontalWritingMode(), style()->isFlippedBlocksWritingMode()), granularity, multiplier))
+            scrolled = true;
+        
+        if (scrolled) {
+            if (stopNode)
+                *stopNode = node();
+            return true;
+        }
+    }
+
+    if (stopNode && *stopNode && *stopNode == node())
+        return true;
+
+    RenderBlock* b = containingBlock();
+    if (b && !b->isRenderView())
+        return b->logicalScroll(direction, granularity, multiplier, stopNode);
+    return false;
+}
+
+bool RenderBox::canBeScrolledAndHasScrollableArea() const
+{
+    return canBeProgramaticallyScrolled() && (scrollHeight() != clientHeight() || scrollWidth() != clientWidth());
+}
+    
+bool RenderBox::canBeProgramaticallyScrolled() const
+{
+    return (hasOverflowClip() && (scrollsOverflow() || (node() && node()->rendererIsEditable()))) || (node() && node()->isDocumentNode());
+}
+
+bool RenderBox::usesCompositedScrolling() const
+{
+    return hasOverflowClip() && hasLayer() && layer()->usesCompositedScrolling();
+}
+
+void RenderBox::autoscroll(const IntPoint& position)
+{
+    if (layer())
+        layer()->autoscroll(position);
+}
+
+// There are two kinds of renderer that can autoscroll.
+bool RenderBox::canAutoscroll() const
+{
+    // Check for a box that can be scrolled in its own right.
+    if (canBeScrolledAndHasScrollableArea())
+        return true;
+
+    // Check for a box that represents the top level of a web page.
+    if (node() != document())
+        return false;
+    Frame* frame = this->frame();
+    if (!frame)
+        return false;
+    Page* page = frame->page();
+    return page && page->mainFrame() == frame && frame->view()->isScrollable();
+}
+
+// If specified point is in border belt, returned offset denotes direction of
+// scrolling.
+IntSize RenderBox::calculateAutoscrollDirection(const IntPoint& windowPoint) const
+{
+    if (!frame())
+        return IntSize();
+
+    FrameView* frameView = frame()->view();
+    if (!frameView)
+        return IntSize();
+
+    IntSize offset;
+    IntPoint point = frameView->windowToContents(windowPoint);
+    IntRect box(absoluteBoundingBoxRect());
+
+    if (point.x() < box.x() + autoscrollBeltSize)
+        point.move(-autoscrollBeltSize, 0);
+    else if (point.x() > box.maxX() - autoscrollBeltSize)
+        point.move(autoscrollBeltSize, 0);
+
+    if (point.y() < box.y() + autoscrollBeltSize)
+        point.move(0, -autoscrollBeltSize);
+    else if (point.y() > box.maxY() - autoscrollBeltSize)
+        point.move(0, autoscrollBeltSize);
+    return frameView->contentsToWindow(point) - windowPoint;
+}
+
+RenderBox* RenderBox::findAutoscrollable(RenderObject* renderer)
+{
+    while (renderer && !(renderer->isBox() && toRenderBox(renderer)->canAutoscroll())) {
+        if (!renderer->parent() && renderer->node() == renderer->document() && renderer->document()->ownerElement())
+            renderer = renderer->document()->ownerElement()->renderer();
+        else
+            renderer = renderer->parent();
+    }
+
+    return renderer && renderer->isBox() ? toRenderBox(renderer) : 0;
+}
+
+void RenderBox::panScroll(const IntPoint& source)
+{
+    if (layer())
+        layer()->panScrollFromPoint(source);
+}
+
+bool RenderBox::needsPreferredWidthsRecalculation() const
+{
+    return style()->paddingStart().isPercent() || style()->paddingEnd().isPercent();
+}
+
+IntSize RenderBox::scrolledContentOffset() const
+{
+    ASSERT(hasOverflowClip());
+    ASSERT(hasLayer());
+    return layer()->scrolledContentOffset();
+}
+
+LayoutSize RenderBox::cachedSizeForOverflowClip() const
+{
+    ASSERT(hasOverflowClip());
+    ASSERT(hasLayer());
+    return layer()->size();
+}
+
+void RenderBox::applyCachedClipAndScrollOffsetForRepaint(LayoutRect& paintRect) const
+{
+    paintRect.move(-scrolledContentOffset()); // For overflow:auto/scroll/hidden.
+
+    // Do not clip scroll layer contents to reduce the number of repaints while scrolling.
+    if (usesCompositedScrolling())
+        return;
+
+    // height() is inaccurate if we're in the middle of a layout of this RenderBox, 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.
+    LayoutRect clipRect(LayoutPoint(), cachedSizeForOverflowClip());
+    paintRect = intersection(paintRect, clipRect);
+}
+
+void RenderBox::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const
+{
+    minLogicalWidth = minPreferredLogicalWidth() - borderAndPaddingLogicalWidth();
+    maxLogicalWidth = maxPreferredLogicalWidth() - borderAndPaddingLogicalWidth();
+}
+
+LayoutUnit RenderBox::minPreferredLogicalWidth() const
+{
+    if (preferredLogicalWidthsDirty()) {
+#ifndef NDEBUG
+        SetLayoutNeededForbiddenScope layoutForbiddenScope(const_cast<RenderBox*>(this));
+#endif
+        const_cast<RenderBox*>(this)->computePreferredLogicalWidths();
+    }
+        
+    return m_minPreferredLogicalWidth;
+}
+
+LayoutUnit RenderBox::maxPreferredLogicalWidth() const
+{
+    if (preferredLogicalWidthsDirty()) {
+#ifndef NDEBUG
+        SetLayoutNeededForbiddenScope layoutForbiddenScope(const_cast<RenderBox*>(this));
+#endif
+        const_cast<RenderBox*>(this)->computePreferredLogicalWidths();
+    }
+        
+    return m_maxPreferredLogicalWidth;
+}
+
+bool RenderBox::hasOverrideHeight() const
+{
+    return gOverrideHeightMap && gOverrideHeightMap->contains(this);
+}
+
+bool RenderBox::hasOverrideWidth() const
+{
+    return gOverrideWidthMap && gOverrideWidthMap->contains(this);
+}
+
+void RenderBox::setOverrideLogicalContentHeight(LayoutUnit height)
+{
+    if (!gOverrideHeightMap)
+        gOverrideHeightMap = new OverrideSizeMap();
+    gOverrideHeightMap->set(this, height);
+}
+
+void RenderBox::setOverrideLogicalContentWidth(LayoutUnit width)
+{
+    if (!gOverrideWidthMap)
+        gOverrideWidthMap = new OverrideSizeMap();
+    gOverrideWidthMap->set(this, width);
+}
+
+void RenderBox::clearOverrideLogicalContentHeight()
+{
+    if (gOverrideHeightMap)
+        gOverrideHeightMap->remove(this);
+}
+
+void RenderBox::clearOverrideLogicalContentWidth()
+{
+    if (gOverrideWidthMap)
+        gOverrideWidthMap->remove(this);
+}
+
+void RenderBox::clearOverrideSize()
+{
+    clearOverrideLogicalContentHeight();
+    clearOverrideLogicalContentWidth();
+}
+
+LayoutUnit RenderBox::overrideLogicalContentWidth() const
+{
+    ASSERT(hasOverrideWidth());
+    return gOverrideWidthMap->get(this);
+}
+
+LayoutUnit RenderBox::overrideLogicalContentHeight() const
+{
+    ASSERT(hasOverrideHeight());
+    return gOverrideHeightMap->get(this);
+}
+
+LayoutUnit RenderBox::overrideContainingBlockContentLogicalWidth() const
+{
+    ASSERT(hasOverrideContainingBlockLogicalWidth());
+    return gOverrideContainingBlockLogicalWidthMap->get(this);
+}
+
+LayoutUnit RenderBox::overrideContainingBlockContentLogicalHeight() const
+{
+    ASSERT(hasOverrideContainingBlockLogicalHeight());
+    return gOverrideContainingBlockLogicalHeightMap->get(this);
+}
+
+bool RenderBox::hasOverrideContainingBlockLogicalWidth() const
+{
+    return gOverrideContainingBlockLogicalWidthMap && gOverrideContainingBlockLogicalWidthMap->contains(this);
+}
+
+bool RenderBox::hasOverrideContainingBlockLogicalHeight() const
+{
+    return gOverrideContainingBlockLogicalHeightMap && gOverrideContainingBlockLogicalHeightMap->contains(this);
+}
+
+void RenderBox::setOverrideContainingBlockContentLogicalWidth(LayoutUnit logicalWidth)
+{
+    if (!gOverrideContainingBlockLogicalWidthMap)
+        gOverrideContainingBlockLogicalWidthMap = new OverrideSizeMap;
+    gOverrideContainingBlockLogicalWidthMap->set(this, logicalWidth);
+}
+
+void RenderBox::setOverrideContainingBlockContentLogicalHeight(LayoutUnit logicalHeight)
+{
+    if (!gOverrideContainingBlockLogicalHeightMap)
+        gOverrideContainingBlockLogicalHeightMap = new OverrideSizeMap;
+    gOverrideContainingBlockLogicalHeightMap->set(this, logicalHeight);
+}
+
+void RenderBox::clearContainingBlockOverrideSize()
+{
+    if (gOverrideContainingBlockLogicalWidthMap)
+        gOverrideContainingBlockLogicalWidthMap->remove(this);
+    clearOverrideContainingBlockContentLogicalHeight();
+}
+
+void RenderBox::clearOverrideContainingBlockContentLogicalHeight()
+{
+    if (gOverrideContainingBlockLogicalHeightMap)
+        gOverrideContainingBlockLogicalHeightMap->remove(this);
+}
+
+LayoutUnit RenderBox::adjustBorderBoxLogicalWidthForBoxSizing(LayoutUnit width) const
+{
+    LayoutUnit bordersPlusPadding = borderAndPaddingLogicalWidth();
+    if (style()->boxSizing() == CONTENT_BOX)
+        return width + bordersPlusPadding;
+    return max(width, bordersPlusPadding);
+}
+
+LayoutUnit RenderBox::adjustBorderBoxLogicalHeightForBoxSizing(LayoutUnit height) const
+{
+    LayoutUnit bordersPlusPadding = borderAndPaddingLogicalHeight();
+    if (style()->boxSizing() == CONTENT_BOX)
+        return height + bordersPlusPadding;
+    return max(height, bordersPlusPadding);
+}
+
+LayoutUnit RenderBox::adjustContentBoxLogicalWidthForBoxSizing(LayoutUnit width) const
+{
+    if (style()->boxSizing() == BORDER_BOX)
+        width -= borderAndPaddingLogicalWidth();
+    return max<LayoutUnit>(0, width);
+}
+
+LayoutUnit RenderBox::adjustContentBoxLogicalHeightForBoxSizing(LayoutUnit height) const
+{
+    if (style()->boxSizing() == BORDER_BOX)
+        height -= borderAndPaddingLogicalHeight();
+    return max<LayoutUnit>(0, height);
+}
+
+// Hit Testing
+bool RenderBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action)
+{
+    LayoutPoint adjustedLocation = accumulatedOffset + location();
+
+    // Check kids first.
+    for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
+        if (!child->hasLayer() && child->nodeAtPoint(request, result, locationInContainer, adjustedLocation, action)) {
+            updateHitTestResult(result, locationInContainer.point() - toLayoutSize(adjustedLocation));
+            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).
+    LayoutRect boundsRect = borderBoxRectInRegion(locationInContainer.region());
+    boundsRect.moveBy(adjustedLocation);
+    if (visibleToHitTestRequest(request) && action == HitTestForeground && locationInContainer.intersects(boundsRect)) {
+        updateHitTestResult(result, locationInContainer.point() - toLayoutSize(adjustedLocation));
+        if (!result.addNodeToRectBasedTestResult(node(), request, locationInContainer, boundsRect))
+            return true;
+    }
+
+    return false;
+}
+
+// --------------------- painting stuff -------------------------------
+
+void RenderBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    LayoutPoint adjustedPaintOffset = paintOffset + location();
+    // default implementation. Just pass paint through to the children
+    PaintInfo childInfo(paintInfo);
+    childInfo.updatePaintingRootForChildren(this);
+    for (RenderObject* child = firstChild(); child; child = child->nextSibling())
+        child->paint(childInfo, adjustedPaintOffset);
+}
+
+void RenderBox::paintRootBoxFillLayers(const PaintInfo& paintInfo)
+{
+    if (paintInfo.skipRootBackground())
+        return;
+
+    RenderObject* rootBackgroundRenderer = rendererForRootBackground();
+    
+    const FillLayer* bgLayer = rootBackgroundRenderer->style()->backgroundLayers();
+    Color bgColor = rootBackgroundRenderer->style()->visitedDependentColor(CSSPropertyBackgroundColor);
+
+    paintFillLayers(paintInfo, bgColor, bgLayer, view()->backgroundRect(this), BackgroundBleedNone, CompositeSourceOver, rootBackgroundRenderer);
+}
+
+BackgroundBleedAvoidance RenderBox::determineBackgroundBleedAvoidance(GraphicsContext* context) const
+{
+    if (context->paintingDisabled())
+        return BackgroundBleedNone;
+
+    const RenderStyle* style = this->style();
+
+    if (!style->hasBackground() || !style->hasBorder() || !style->hasBorderRadius() || borderImageIsLoadedAndCanBeRendered())
+        return BackgroundBleedNone;
+
+    AffineTransform ctm = context->getCTM();
+    FloatSize contextScaling(static_cast<float>(ctm.xScale()), static_cast<float>(ctm.yScale()));
+
+    // Because RoundedRect uses IntRect internally the inset applied by the 
+    // BackgroundBleedShrinkBackground strategy cannot be less than one integer
+    // layout coordinate, even with subpixel layout enabled. To take that into
+    // account, we clamp the contextScaling to 1.0 for the following test so
+    // that borderObscuresBackgroundEdge can only return true if the border
+    // widths are greater than 2 in both layout coordinates and screen
+    // coordinates.
+    // This precaution will become obsolete if RoundedRect is ever promoted to
+    // a sub-pixel representation.
+    if (contextScaling.width() > 1) 
+        contextScaling.setWidth(1);
+    if (contextScaling.height() > 1) 
+        contextScaling.setHeight(1);
+
+    if (borderObscuresBackgroundEdge(contextScaling))
+        return BackgroundBleedShrinkBackground;
+    if (!style->hasAppearance() && borderObscuresBackground() && backgroundHasOpaqueTopLayer())
+        return BackgroundBleedBackgroundOverBorder;
+
+    return BackgroundBleedUseTransparencyLayer;
+}
+
+void RenderBox::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    if (!paintInfo.shouldPaintWithinRoot(this))
+        return;
+
+    LayoutRect paintRect = borderBoxRectInRegion(paintInfo.renderRegion);
+    paintRect.moveBy(paintOffset);
+
+    BackgroundBleedAvoidance bleedAvoidance = determineBackgroundBleedAvoidance(paintInfo.context);
+
+    // FIXME: Should eventually give the theme control over whether the box shadow should paint, since controls could have
+    // custom shadows of their own.
+    if (!boxShadowShouldBeAppliedToBackground(bleedAvoidance))
+        paintBoxShadow(paintInfo, paintRect, style(), Normal);
+
+    GraphicsContextStateSaver stateSaver(*paintInfo.context, false);
+    if (bleedAvoidance == BackgroundBleedUseTransparencyLayer) {
+        // To avoid the background color bleeding out behind the border, we'll render background and border
+        // into a transparency layer, and then clip that in one go (which requires setting up the clip before
+        // beginning the layer).
+        RoundedRect border = style()->getRoundedBorderFor(paintRect, view());
+        stateSaver.save();
+        paintInfo.context->clipRoundedRect(border);
+        paintInfo.context->beginTransparencyLayer(1);
+    }
+
+    // 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.
+    IntRect snappedPaintRect(pixelSnappedIntRect(paintRect));
+    bool themePainted = style()->hasAppearance() && !theme()->paint(this, paintInfo, snappedPaintRect);
+    if (!themePainted) {
+        if (bleedAvoidance == BackgroundBleedBackgroundOverBorder)
+            paintBorder(paintInfo, paintRect, style(), bleedAvoidance);
+
+        paintBackground(paintInfo, paintRect, bleedAvoidance);
+
+        if (style()->hasAppearance())
+            theme()->paintDecorations(this, paintInfo, snappedPaintRect);
+    }
+    paintBoxShadow(paintInfo, paintRect, style(), Inset);
+
+    // The theme will tell us whether or not we should also paint the CSS border.
+    if (bleedAvoidance != BackgroundBleedBackgroundOverBorder && (!style()->hasAppearance() || (!themePainted && theme()->paintBorderOnly(this, paintInfo, snappedPaintRect))) && style()->hasBorder())
+        paintBorder(paintInfo, paintRect, style(), bleedAvoidance);
+
+    if (bleedAvoidance == BackgroundBleedUseTransparencyLayer)
+        paintInfo.context->endTransparencyLayer();
+}
+
+void RenderBox::paintBackground(const PaintInfo& paintInfo, const LayoutRect& paintRect, BackgroundBleedAvoidance bleedAvoidance)
+{
+    if (isRoot()) {
+        paintRootBoxFillLayers(paintInfo);
+        return;
+    }
+    if (isBody() && skipBodyBackground(this))
+        return;
+    if (backgroundIsKnownToBeObscured())
+        return;
+    paintFillLayers(paintInfo, style()->visitedDependentColor(CSSPropertyBackgroundColor), style()->backgroundLayers(), paintRect, bleedAvoidance);
+}
+
+LayoutRect RenderBox::backgroundPaintedExtent() const
+{
+    ASSERT(hasBackground());
+    LayoutRect backgroundRect = pixelSnappedIntRect(borderBoxRect());
+
+    Color backgroundColor = style()->visitedDependentColor(CSSPropertyBackgroundColor);
+    if (backgroundColor.isValid() && backgroundColor.alpha())
+        return backgroundRect;
+    if (!style()->backgroundLayers()->image() || style()->backgroundLayers()->next())
+        return backgroundRect;
+    BackgroundImageGeometry geometry;
+    const_cast<RenderBox*>(this)->calculateBackgroundImageGeometry(style()->backgroundLayers(), backgroundRect, geometry);
+    return geometry.destRect();
+}
+
+bool RenderBox::backgroundIsKnownToBeOpaqueInRect(const LayoutRect& localRect) const
+{
+    if (isBody() && skipBodyBackground(this))
+        return false;
+
+    Color backgroundColor = style()->visitedDependentColor(CSSPropertyBackgroundColor);
+    if (!backgroundColor.isValid() || backgroundColor.hasAlpha())
+        return false;
+
+    // If the element has appearance, it might be painted by theme.
+    // We cannot be sure if theme paints the background opaque.
+    // In this case it is safe to not assume opaqueness.
+    // FIXME: May be ask theme if it paints opaque.
+    if (style()->hasAppearance())
+        return false;
+    // FIXME: Check the opaqueness of background images.
+
+    // FIXME: Use rounded rect if border radius is present.
+    if (style()->hasBorderRadius())
+        return false;
+    // FIXME: The background color clip is defined by the last layer.
+    if (style()->backgroundLayers()->next())
+        return false;
+    LayoutRect backgroundRect;
+    switch (style()->backgroundClip()) {
+    case BorderFillBox:
+        backgroundRect = borderBoxRect();
+        break;
+    case PaddingFillBox:
+        backgroundRect = paddingBoxRect();
+        break;
+    case ContentFillBox:
+        backgroundRect = contentBoxRect();
+        break;
+    default:
+        break;
+    }
+    return backgroundRect.contains(localRect);
+}
+
+static bool isCandidateForOpaquenessTest(RenderBox* childBox)
+{
+    RenderStyle* childStyle = childBox->style();
+    if (childStyle->position() != StaticPosition && childBox->containingBlock() != childBox->parent())
+        return false;
+    if (childStyle->visibility() != VISIBLE || childStyle->shapeOutside())
+        return false;
+    if (!childBox->width() || !childBox->height())
+        return false;
+    if (RenderLayer* childLayer = childBox->layer()) {
+        if (childLayer->isComposited())
+            return false;
+        // FIXME: Deal with z-index.
+        if (!childStyle->hasAutoZIndex())
+            return false;
+        if (childLayer->hasTransform() || childLayer->isTransparent() || childLayer->hasFilter())
+            return false;
+    }
+    return true;
+}
+
+bool RenderBox::foregroundIsKnownToBeOpaqueInRect(const LayoutRect& localRect, unsigned maxDepthToTest) const
+{
+    if (!maxDepthToTest)
+        return false;
+    for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+        if (!child->isBox())
+            continue;
+        RenderBox* childBox = toRenderBox(child);
+        if (!isCandidateForOpaquenessTest(childBox))
+            continue;
+        LayoutPoint childLocation = childBox->location();
+        if (childBox->isRelPositioned())
+            childLocation.move(childBox->relativePositionOffset());
+        LayoutRect childLocalRect = localRect;
+        childLocalRect.moveBy(-childLocation);
+        if (childLocalRect.y() < 0 || childLocalRect.x() < 0) {
+            // If there is unobscured area above/left of a static positioned box then the rect is probably not covered.
+            if (childBox->style()->position() == StaticPosition)
+                return false;
+            continue;
+        }
+        if (childLocalRect.maxY() > childBox->height() || childLocalRect.maxX() > childBox->width())
+            continue;
+        if (childBox->backgroundIsKnownToBeOpaqueInRect(childLocalRect))
+            return true;
+        if (childBox->foregroundIsKnownToBeOpaqueInRect(childLocalRect, maxDepthToTest - 1))
+            return true;
+    }
+    return false;
+}
+
+bool RenderBox::computeBackgroundIsKnownToBeObscured()
+{
+    // Test to see if the children trivially obscure the background.
+    // FIXME: This test can be much more comprehensive.
+    if (!hasBackground())
+        return false;
+    // Table and root background painting is special.
+    if (isTable() || isRoot())
+        return false;
+
+    LayoutRect backgroundRect = backgroundPaintedExtent();
+    return foregroundIsKnownToBeOpaqueInRect(backgroundRect, backgroundObscurationTestMaxDepth);
+}
+
+bool RenderBox::backgroundHasOpaqueTopLayer() const
+{
+    const FillLayer* fillLayer = style()->backgroundLayers();
+    if (!fillLayer || fillLayer->clip() != BorderFillBox)
+        return false;
+
+    // Clipped with local scrolling
+    if (hasOverflowClip() && fillLayer->attachment() == LocalBackgroundAttachment)
+        return false;
+
+    if (fillLayer->hasOpaqueImage(this) && fillLayer->hasRepeatXY() && fillLayer->image()->canRender(this, style()->effectiveZoom()))
+        return true;
+
+    // If there is only one layer and no image, check whether the background color is opaque
+    if (!fillLayer->next() && !fillLayer->hasImage()) {
+        Color bgColor = style()->visitedDependentColor(CSSPropertyBackgroundColor);
+        if (bgColor.isValid() && bgColor.alpha() == 255)
+            return true;
+    }
+
+    return false;
+}
+
+void RenderBox::paintMask(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    if (!paintInfo.shouldPaintWithinRoot(this) || style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask || paintInfo.context->paintingDisabled())
+        return;
+
+    LayoutRect paintRect = LayoutRect(paintOffset, size());
+    paintMaskImages(paintInfo, paintRect);
+}
+
+void RenderBox::paintMaskImages(const PaintInfo& paintInfo, const LayoutRect& paintRect)
+{
+    // Figure out if we need to push a transparency layer to render our mask.
+    bool pushTransparencyLayer = false;
+    bool compositedMask = hasLayer() && layer()->hasCompositedMask();
+    bool flattenCompositingLayers = view()->frameView() && view()->frameView()->paintBehavior() & PaintBehaviorFlattenCompositingLayers;
+    CompositeOperator compositeOp = CompositeSourceOver;
+
+    bool allMaskImagesLoaded = true;
+    
+    if (!compositedMask || flattenCompositingLayers) {
+        pushTransparencyLayer = true;
+        StyleImage* maskBoxImage = style()->maskBoxImage().image();
+        const FillLayer* maskLayers = style()->maskLayers();
+
+        // Don't render a masked element until all the mask images have loaded, to prevent a flash of unmasked content.
+        if (maskBoxImage)
+            allMaskImagesLoaded &= maskBoxImage->isLoaded();
+
+        if (maskLayers)
+            allMaskImagesLoaded &= maskLayers->imagesAreLoaded();
+
+        paintInfo.context->setCompositeOperation(CompositeDestinationIn);
+        paintInfo.context->beginTransparencyLayer(1);
+        compositeOp = CompositeSourceOver;
+    }
+
+    if (allMaskImagesLoaded) {
+        paintFillLayers(paintInfo, Color(), style()->maskLayers(), paintRect, BackgroundBleedNone, compositeOp);
+        paintNinePieceImage(paintInfo.context, paintRect, style(), style()->maskBoxImage(), compositeOp);
+    }
+    
+    if (pushTransparencyLayer)
+        paintInfo.context->endTransparencyLayer();
+}
+
+LayoutRect RenderBox::maskClipRect()
+{
+    const NinePieceImage& maskBoxImage = style()->maskBoxImage();
+    if (maskBoxImage.image()) {
+        LayoutRect borderImageRect = borderBoxRect();
+        
+        // Apply outsets to the border box.
+        borderImageRect.expand(style()->maskBoxImageOutsets());
+        return borderImageRect;
+    }
+    
+    LayoutRect result;
+    LayoutRect borderBox = borderBoxRect();
+    for (const FillLayer* maskLayer = style()->maskLayers(); maskLayer; maskLayer = maskLayer->next()) {
+        if (maskLayer->image()) {
+            BackgroundImageGeometry geometry;
+            calculateBackgroundImageGeometry(maskLayer, borderBox, geometry);
+            result.unite(geometry.destRect());
+        }
+    }
+    return result;
+}
+
+void RenderBox::paintFillLayers(const PaintInfo& paintInfo, const Color& c, const FillLayer* fillLayer, const LayoutRect& rect,
+    BackgroundBleedAvoidance bleedAvoidance, CompositeOperator op, RenderObject* backgroundObject)
+{
+    Vector<const FillLayer*, 8> layers;
+    const FillLayer* curLayer = fillLayer;
+    while (curLayer) {
+        layers.append(curLayer);
+        // Stop traversal when an opaque layer is encountered.
+        // FIXME : It would be possible for the following occlusion culling test to be more aggressive 
+        // on layers with no repeat by testing whether the image covers the layout rect.
+        // Testing that here would imply duplicating a lot of calculations that are currently done in
+        // RenderBoxModelObject::paintFillLayerExtended. A more efficient solution might be to move
+        // the layer recursion into paintFillLayerExtended, or to compute the layer geometry here
+        // and pass it down.
+        
+        // The clipOccludesNextLayers condition must be evaluated first to avoid short-circuiting.
+        if (curLayer->clipOccludesNextLayers(curLayer == fillLayer) && curLayer->hasOpaqueImage(this) && curLayer->image()->canRender(this, style()->effectiveZoom()) && curLayer->hasRepeatXY())
+            break;
+        curLayer = curLayer->next();
+    }
+
+    Vector<const FillLayer*>::const_reverse_iterator topLayer = layers.rend();
+    for (Vector<const FillLayer*>::const_reverse_iterator it = layers.rbegin(); it != topLayer; ++it)
+        paintFillLayer(paintInfo, c, *it, rect, bleedAvoidance, op, backgroundObject);
+}
+
+void RenderBox::paintFillLayer(const PaintInfo& paintInfo, const Color& c, const FillLayer* fillLayer, const LayoutRect& rect,
+    BackgroundBleedAvoidance bleedAvoidance, CompositeOperator op, RenderObject* backgroundObject)
+{
+    paintFillLayerExtended(paintInfo, c, fillLayer, rect, bleedAvoidance, 0, LayoutSize(), op, backgroundObject);
+}
+
+static bool layersUseImage(WrappedImagePtr image, const FillLayer* layers)
+{
+    for (const FillLayer* curLayer = layers; curLayer; curLayer = curLayer->next()) {
+        if (curLayer->image() && image == curLayer->image()->data())
+            return true;
+    }
+
+    return false;
+}
+
+void RenderBox::imageChanged(WrappedImagePtr image, const IntRect*)
+{
+    if (!parent())
+        return;
+
+    if ((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);
+
+
+    if (hasLayer() && layer()->hasCompositedMask() && layersUseImage(image, style()->maskLayers()))
+        layer()->contentChanged(MaskImageChanged);
+}
+
+bool RenderBox::repaintLayerRectsForImage(WrappedImagePtr image, const FillLayer* layers, bool drawingBackground)
+{
+    LayoutRect rendererRect;
+    RenderBox* layerRenderer = 0;
+
+    for (const FillLayer* curLayer = layers; curLayer; curLayer = curLayer->next()) {
+        if (curLayer->image() && image == curLayer->image()->data() && curLayer->image()->canRender(this, 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()->hasBackground()));
+                if (drawingRootBackground) {
+                    layerRenderer = view();
+
+                    LayoutUnit rw;
+                    LayoutUnit rh;
+
+                    if (FrameView* frameView = toRenderView(layerRenderer)->frameView()) {
+                        rw = frameView->contentsWidth();
+                        rh = frameView->contentsHeight();
+                    } else {
+                        rw = layerRenderer->width();
+                        rh = layerRenderer->height();
+                    }
+                    rendererRect = LayoutRect(-layerRenderer->marginLeft(),
+                        -layerRenderer->marginTop(),
+                        max(layerRenderer->width() + layerRenderer->marginWidth() + layerRenderer->borderLeft() + layerRenderer->borderRight(), rw),
+                        max(layerRenderer->height() + layerRenderer->marginHeight() + layerRenderer->borderTop() + layerRenderer->borderBottom(), rh));
+                } else {
+                    layerRenderer = this;
+                    rendererRect = borderBoxRect();
+                }
+            }
+
+            BackgroundImageGeometry geometry;
+            layerRenderer->calculateBackgroundImageGeometry(curLayer, rendererRect, geometry);
+            layerRenderer->repaintRectangle(geometry.destRect());
+            if (geometry.destRect() == rendererRect)
+                return true;
+        }
+    }
+    return false;
+}
+
+bool RenderBox::pushContentsClip(PaintInfo& paintInfo, const LayoutPoint& accumulatedOffset)
+{
+    if (paintInfo.phase == PaintPhaseBlockBackground || paintInfo.phase == PaintPhaseSelfOutline || paintInfo.phase == PaintPhaseMask)
+        return false;
+        
+    bool isControlClip = hasControlClip();
+    bool isOverflowClip = hasOverflowClip() && !layer()->isSelfPaintingLayer();
+    
+    if (!isControlClip && !isOverflowClip)
+        return false;
+    
+    if (paintInfo.phase == PaintPhaseOutline)
+        paintInfo.phase = PaintPhaseChildOutlines;
+    else if (paintInfo.phase == PaintPhaseChildBlockBackground) {
+        paintInfo.phase = PaintPhaseBlockBackground;
+        paintObject(paintInfo, accumulatedOffset);
+        paintInfo.phase = PaintPhaseChildBlockBackgrounds;
+    }
+    IntRect clipRect = pixelSnappedIntRect(isControlClip ? controlClipRect(accumulatedOffset) : overflowClipRect(accumulatedOffset, paintInfo.renderRegion));
+    paintInfo.context->save();
+    if (style()->hasBorderRadius())
+        paintInfo.context->clipRoundedRect(style()->getRoundedInnerBorderFor(LayoutRect(accumulatedOffset, size())));
+    paintInfo.context->clip(clipRect);
+    return true;
+}
+
+void RenderBox::popContentsClip(PaintInfo& paintInfo, PaintPhase originalPhase, const LayoutPoint& accumulatedOffset)
+{
+    ASSERT(hasControlClip() || (hasOverflowClip() && !layer()->isSelfPaintingLayer()));
+
+    paintInfo.context->restore();
+    if (originalPhase == PaintPhaseOutline) {
+        paintInfo.phase = PaintPhaseSelfOutline;
+        paintObject(paintInfo, accumulatedOffset);
+        paintInfo.phase = originalPhase;
+    } else if (originalPhase == PaintPhaseChildBlockBackground)
+        paintInfo.phase = originalPhase;
+}
+
+LayoutRect RenderBox::overflowClipRect(const LayoutPoint& location, RenderRegion* region, OverlayScrollbarSizeRelevancy relevancy)
+{
+    // FIXME: When overflow-clip (CSS3) is implemented, we'll obtain the property
+    // here.
+    LayoutRect clipRect = borderBoxRectInRegion(region);
+    clipRect.setLocation(location + clipRect.location() + LayoutSize(borderLeft(), borderTop()));
+    clipRect.setSize(clipRect.size() - LayoutSize(borderLeft() + borderRight(), borderTop() + borderBottom()));
+
+    // Subtract out scrollbars if we have them.
+     if (layer()) {
+        if (style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft())
+            clipRect.move(layer()->verticalScrollbarWidth(relevancy), 0);
+        clipRect.contract(layer()->verticalScrollbarWidth(relevancy), layer()->horizontalScrollbarHeight(relevancy));
+     }
+
+    return clipRect;
+}
+
+LayoutRect RenderBox::clipRect(const LayoutPoint& location, RenderRegion* region)
+{
+    LayoutRect borderBoxRect = borderBoxRectInRegion(region);
+    LayoutRect clipRect = LayoutRect(borderBoxRect.location() + location, borderBoxRect.size());
+    RenderView* renderView = view();
+
+    if (!style()->clipLeft().isAuto()) {
+        LayoutUnit c = valueForLength(style()->clipLeft(), borderBoxRect.width(), renderView);
+        clipRect.move(c, 0);
+        clipRect.contract(c, 0);
+    }
+
+    // We don't use the region-specific border box's width and height since clip offsets are (stupidly) specified
+    // from the left and top edges. Therefore it's better to avoid constraining to smaller widths and heights.
+
+    if (!style()->clipRight().isAuto())
+        clipRect.contract(width() - valueForLength(style()->clipRight(), width(), renderView), 0);
+
+    if (!style()->clipTop().isAuto()) {
+        LayoutUnit c = valueForLength(style()->clipTop(), borderBoxRect.height(), renderView);
+        clipRect.move(0, c);
+        clipRect.contract(0, c);
+    }
+
+    if (!style()->clipBottom().isAuto())
+        clipRect.contract(0, height() - valueForLength(style()->clipBottom(), height(), renderView));
+
+    return clipRect;
+}
+
+LayoutUnit RenderBox::shrinkLogicalWidthToAvoidFloats(LayoutUnit childMarginStart, LayoutUnit childMarginEnd, const RenderBlock* cb, RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage) const
+{    
+    RenderRegion* containingBlockRegion = 0;
+    LayoutUnit logicalTopPosition = logicalTop();
+    LayoutUnit adjustedPageOffsetForContainingBlock = offsetFromLogicalTopOfFirstPage - logicalTop();
+    if (region) {
+        LayoutUnit offsetFromLogicalTopOfRegion = region ? region->logicalTopForFlowThreadContent() - offsetFromLogicalTopOfFirstPage : LayoutUnit();
+        logicalTopPosition = max(logicalTopPosition, logicalTopPosition + offsetFromLogicalTopOfRegion);
+        containingBlockRegion = cb->clampToStartAndEndRegions(region);
+    }
+
+    LayoutUnit result = cb->availableLogicalWidthForLine(logicalTopPosition, false, containingBlockRegion, adjustedPageOffsetForContainingBlock) - childMarginStart - childMarginEnd;
+
+    // We need to see if margins on either the start side or the end side can contain the floats in question. If they can,
+    // then just using the line width is inaccurate. In the case where a float completely fits, we don't need to use the line
+    // offset at all, but can instead push all the way to the content edge of the containing block. In the case where the float
+    // doesn't fit, we can use the line offset, but we need to grow it by the margin to reflect the fact that the margin was
+    // "consumed" by the float. Negative margins aren't consumed by the float, and so we ignore them.
+    if (childMarginStart > 0) {
+        LayoutUnit startContentSide = cb->startOffsetForContent(containingBlockRegion, adjustedPageOffsetForContainingBlock);
+        LayoutUnit startContentSideWithMargin = startContentSide + childMarginStart;
+        LayoutUnit startOffset = cb->startOffsetForLine(logicalTopPosition, false, containingBlockRegion, adjustedPageOffsetForContainingBlock);
+        if (startOffset > startContentSideWithMargin)
+            result += childMarginStart;
+        else
+            result += startOffset - startContentSide;
+    }
+    
+    if (childMarginEnd > 0) {
+        LayoutUnit endContentSide = cb->endOffsetForContent(containingBlockRegion, adjustedPageOffsetForContainingBlock);
+        LayoutUnit endContentSideWithMargin = endContentSide + childMarginEnd;
+        LayoutUnit endOffset = cb->endOffsetForLine(logicalTopPosition, false, containingBlockRegion, adjustedPageOffsetForContainingBlock);
+        if (endOffset > endContentSideWithMargin)
+            result += childMarginEnd;
+        else
+            result += endOffset - endContentSide;
+    }
+
+    return result;
+}
+
+LayoutUnit RenderBox::containingBlockLogicalWidthForContent() const
+{
+    if (hasOverrideContainingBlockLogicalWidth())
+        return overrideContainingBlockContentLogicalWidth();
+
+    RenderBlock* cb = containingBlock();
+    return cb->availableLogicalWidth();
+}
+
+LayoutUnit RenderBox::containingBlockLogicalHeightForContent(AvailableLogicalHeightType heightType) const
+{
+    if (hasOverrideContainingBlockLogicalHeight())
+        return overrideContainingBlockContentLogicalHeight();
+
+    RenderBlock* cb = containingBlock();
+    return cb->availableLogicalHeight(heightType);
+}
+
+LayoutUnit RenderBox::containingBlockLogicalWidthForContentInRegion(RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage) const
+{
+    if (!region)
+        return containingBlockLogicalWidthForContent();
+
+    RenderBlock* cb = containingBlock();
+    RenderRegion* containingBlockRegion = cb->clampToStartAndEndRegions(region);
+    // FIXME: It's unclear if a region's content should use the containing block's override logical width.
+    // If it should, the following line should call containingBlockLogicalWidthForContent.
+    LayoutUnit result = cb->availableLogicalWidth();
+    RenderBoxRegionInfo* boxInfo = cb->renderBoxRegionInfo(containingBlockRegion, offsetFromLogicalTopOfFirstPage - logicalTop());
+    if (!boxInfo)
+        return result;
+    return max<LayoutUnit>(0, result - (cb->logicalWidth() - boxInfo->logicalWidth()));
+}
+
+LayoutUnit RenderBox::containingBlockAvailableLineWidthInRegion(RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage) const
+{
+    RenderBlock* cb = containingBlock();
+    RenderRegion* containingBlockRegion = 0;
+    LayoutUnit logicalTopPosition = logicalTop();
+    LayoutUnit adjustedPageOffsetForContainingBlock = offsetFromLogicalTopOfFirstPage - logicalTop();
+    if (region) {
+        LayoutUnit offsetFromLogicalTopOfRegion = region ? region->logicalTopForFlowThreadContent() - offsetFromLogicalTopOfFirstPage : LayoutUnit();
+        logicalTopPosition = max(logicalTopPosition, logicalTopPosition + offsetFromLogicalTopOfRegion);
+        containingBlockRegion = cb->clampToStartAndEndRegions(region);
+    }
+    return cb->availableLogicalWidthForLine(logicalTopPosition, false, containingBlockRegion, adjustedPageOffsetForContainingBlock, availableLogicalHeight(IncludeMarginBorderPadding));
+}
+
+LayoutUnit RenderBox::perpendicularContainingBlockLogicalHeight() const
+{
+    if (hasOverrideContainingBlockLogicalHeight())
+        return overrideContainingBlockContentLogicalHeight();
+
+    RenderBlock* cb = containingBlock();
+    if (cb->hasOverrideHeight())
+        return cb->overrideLogicalContentHeight();
+
+    RenderStyle* containingBlockStyle = cb->style();
+    Length logicalHeightLength = containingBlockStyle->logicalHeight();
+
+    // FIXME: For now just support fixed heights.  Eventually should support percentage heights as well.
+    if (!logicalHeightLength.isFixed()) {
+        LayoutUnit fillFallbackExtent = containingBlockStyle->isHorizontalWritingMode() ? view()->frameView()->visibleHeight() : view()->frameView()->visibleWidth();
+        LayoutUnit fillAvailableExtent = containingBlock()->availableLogicalHeight(ExcludeMarginBorderPadding);
+        return min(fillAvailableExtent, fillFallbackExtent);
+    }
+
+    // Use the content box logical height as specified by the style.
+    return cb->adjustContentBoxLogicalHeightForBoxSizing(logicalHeightLength.value());
+}
+
+void RenderBox::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags mode, bool* wasFixed) const
+{
+    if (repaintContainer == this)
+        return;
+
+    if (RenderView* v = view()) {
+        if (v->layoutStateEnabled() && !repaintContainer) {
+            LayoutState* layoutState = v->layoutState();
+            LayoutSize offset = layoutState->m_paintOffset + locationOffset();
+            if (style()->hasPaintOffset() && layer())
+                offset += layer()->paintOffset();
+            transformState.move(offset);
+            return;
+        }
+    }
+
+    bool containerSkipped;
+    RenderObject* o = container(repaintContainer, &containerSkipped);
+    if (!o)
+        return;
+
+    bool isFixedPos = style()->position() == FixedPosition;
+    bool hasTransform = hasLayer() && layer()->transform();
+    // If this box has a transform, it acts as a fixed position container for fixed descendants,
+    // and may itself also be fixed position. So propagate 'fixed' up only if this box is fixed position.
+    if (hasTransform && !isFixedPos)
+        mode &= ~IsFixed;
+    else if (isFixedPos)
+        mode |= IsFixed;
+
+    if (wasFixed)
+        *wasFixed = mode & IsFixed;
+    
+    LayoutSize containerOffset = offsetFromContainer(o, roundedLayoutPoint(transformState.mappedPoint()));
+    
+    bool preserve3D = mode & UseTransforms && (o->style()->preserves3D() || style()->preserves3D());
+    if (mode & UseTransforms && shouldUseTransformFromContainer(o)) {
+        TransformationMatrix t;
+        getTransformFromContainer(o, containerOffset, t);
+        transformState.applyTransform(t, preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
+    } else
+        transformState.move(containerOffset.width(), containerOffset.height(), preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
+
+    if (containerSkipped) {
+        // There can't be a transform between repaintContainer and o, because transforms create containers, so it should be safe
+        // to just subtract the delta between the repaintContainer and o.
+        LayoutSize containerOffset = repaintContainer->offsetFromAncestorContainer(o);
+        transformState.move(-containerOffset.width(), -containerOffset.height(), preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
+        return;
+    }
+
+    mode &= ~ApplyContainerFlip;
+    if (o->isRenderFlowThread()) {
+        // Transform from render flow coordinates into region coordinates.
+        RenderRegion* region = toRenderFlowThread(o)->mapFromFlowToRegion(transformState);
+        if (region)
+            region->mapLocalToContainer(region->containerForRepaint(), transformState, mode, wasFixed);
+        return;
+    }
+
+    o->mapLocalToContainer(repaintContainer, transformState, mode, wasFixed);
+}
+
+const RenderObject* RenderBox::pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const
+{
+    ASSERT(ancestorToStopAt != this);
+
+    bool ancestorSkipped;
+    RenderObject* container = this->container(ancestorToStopAt, &ancestorSkipped);
+    if (!container)
+        return 0;
+
+    bool isFixedPos = style()->position() == FixedPosition;
+    bool hasTransform = hasLayer() && layer()->transform();
+
+    LayoutSize adjustmentForSkippedAncestor;
+    if (ancestorSkipped) {
+        // There can't be a transform between repaintContainer and o, because transforms create containers, so it should be safe
+        // to just subtract the delta between the ancestor and o.
+        adjustmentForSkippedAncestor = -ancestorToStopAt->offsetFromAncestorContainer(container);
+    }
+
+    bool offsetDependsOnPoint = false;
+    LayoutSize containerOffset = offsetFromContainer(container, LayoutPoint(), &offsetDependsOnPoint);
+
+    if (container->isRenderFlowThread())
+        offsetDependsOnPoint = true;
+    
+    bool preserve3D = container->style()->preserves3D() || style()->preserves3D();
+    if (shouldUseTransformFromContainer(container)) {
+        TransformationMatrix t;
+        getTransformFromContainer(container, containerOffset, t);
+        t.translateRight(adjustmentForSkippedAncestor.width(), adjustmentForSkippedAncestor.height());
+        
+        geometryMap.push(this, t, preserve3D, offsetDependsOnPoint, isFixedPos, hasTransform);
+    } else {
+        containerOffset += adjustmentForSkippedAncestor;
+        geometryMap.push(this, containerOffset, preserve3D, offsetDependsOnPoint, isFixedPos, hasTransform);
+    }
+    
+    return ancestorSkipped ? ancestorToStopAt : container;
+}
+
+void RenderBox::mapAbsoluteToLocalPoint(MapCoordinatesFlags mode, TransformState& transformState) const
+{
+    bool isFixedPos = style()->position() == FixedPosition;
+    bool hasTransform = hasLayer() && layer()->transform();
+    if (hasTransform && !isFixedPos) {
+        // If this box has a transform, it acts as a fixed position container for fixed descendants,
+        // and may itself also be fixed position. So propagate 'fixed' up only if this box is fixed position.
+        mode &= ~IsFixed;
+    } else if (isFixedPos)
+        mode |= IsFixed;
+
+    RenderBoxModelObject::mapAbsoluteToLocalPoint(mode, transformState);
+}
+
+LayoutSize RenderBox::offsetFromContainer(RenderObject* o, const LayoutPoint& point, bool* offsetDependsOnPoint) const
+{
+    ASSERT(o == container());
+
+    LayoutSize offset;    
+    if (hasPaintOffset())
+        offset += paintOffset();
+
+    if (!isInline() || isReplaced()) {
+        if (!style()->hasOutOfFlowPosition() && o->hasColumns()) {
+            RenderBlock* block = toRenderBlock(o);
+            LayoutRect columnRect(frameRect());
+            block->adjustStartEdgeForWritingModeIncludingColumns(columnRect);
+            offset += toSize(columnRect.location());
+            LayoutPoint columnPoint = block->flipForWritingModeIncludingColumns(point + offset);
+            offset = toLayoutSize(block->flipForWritingModeIncludingColumns(toLayoutPoint(offset)));
+            o->adjustForColumns(offset, columnPoint);
+            offset = block->flipForWritingMode(offset);
+
+            if (offsetDependsOnPoint)
+                *offsetDependsOnPoint = true;
+        } else
+            offset += topLeftLocationOffset();
+    }
+
+    if (o->hasOverflowClip())
+        offset -= toRenderBox(o)->scrolledContentOffset();
+
+    if (style()->position() == AbsolutePosition && o->isInFlowPositioned() && o->isRenderInline())
+        offset += toRenderInline(o)->offsetForInFlowPositionedInline(this);
+
+    return offset;
+}
+
+InlineBox* RenderBox::createInlineBox()
+{
+    return new (renderArena()) InlineBox(this);
+}
+
+void RenderBox::dirtyLineBoxes(bool fullLayout)
+{
+    if (m_inlineBoxWrapper) {
+        if (fullLayout) {
+            m_inlineBoxWrapper->destroy(renderArena());
+            m_inlineBoxWrapper = 0;
+        } else
+            m_inlineBoxWrapper->dirtyLineBoxes();
+    }
+}
+
+void RenderBox::positionLineBox(InlineBox* box)
+{
+    if (isOutOfFlowPositioned()) {
+        // Cache the x position only if we were an INLINE type originally.
+        bool wasInline = style()->isOriginalDisplayInlineType();
+        if (wasInline) {
+            // 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.
+            RootInlineBox* root = box->root();
+            root->block()->setStaticInlinePositionForChild(this, root->lineTopWithLeading(), roundedLayoutUnit(box->logicalLeft()));
+            if (style()->hasStaticInlinePosition(box->isHorizontal()))
+                setChildNeedsLayout(true, MarkOnlyThis); // Just go ahead and mark the positioned object as needing layout, so it will update its position properly.
+        } else {
+            // 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 y() of the box.
+            layer()->setStaticBlockPosition(box->logicalTop());
+            if (style()->hasStaticBlockPosition(box->isHorizontal()))
+                setChildNeedsLayout(true, MarkOnlyThis); // 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()) {
+        setLocation(roundedLayoutPoint(box->topLeft()));
+        // m_inlineBoxWrapper should already be 0. Deleting it is a safeguard against security issues.
+        ASSERT(!m_inlineBoxWrapper);
+        if (m_inlineBoxWrapper)
+            deleteLineBoxWrapper();
+        m_inlineBoxWrapper = box;
+    }
+}
+
+void RenderBox::deleteLineBoxWrapper()
+{
+    if (m_inlineBoxWrapper) {
+        if (!documentBeingDestroyed())
+            m_inlineBoxWrapper->remove();
+        m_inlineBoxWrapper->destroy(renderArena());
+        m_inlineBoxWrapper = 0;
+    }
+}
+
+LayoutRect RenderBox::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const
+{
+    if (style()->visibility() != VISIBLE && !enclosingLayer()->hasVisibleContent())
+        return LayoutRect();
+
+    LayoutRect r = visualOverflowRect();
+
+    RenderView* v = view();
+    if (v) {
+        // FIXME: layoutDelta needs to be applied in parts before/after transforms and
+        // repaint containers. https://bugs.webkit.org/show_bug.cgi?id=23308
+        r.move(v->layoutDelta());
+    }
+    
+    if (style()) {
+        // We have to use maximalOutlineSize() because a child might have an outline
+        // that projects outside of our overflowRect.
+        if (v) {
+            ASSERT(style()->outlineSize() <= v->maximalOutlineSize());
+            r.inflate(v->maximalOutlineSize());
+        }
+    }
+    
+    computeRectForRepaint(repaintContainer, r);
+    return r;
+}
+
+void RenderBox::computeRectForRepaint(const RenderLayerModelObject* repaintContainer, LayoutRect& rect, bool fixed) const
+{
+    // The rect we compute at each step is shifted by our x/y offset in the parent container's coordinate space.
+    // Only when we cross a writing mode boundary will we have to possibly flipForWritingMode (to convert into a more appropriate
+    // offset corner for the enclosing container).  This allows for a fully RL or BT document to repaint
+    // properly even during layout, since the rect remains flipped all the way until the end.
+    //
+    // RenderView::computeRectForRepaint then converts the rect to physical coordinates.  We also convert to
+    // physical when we hit a repaintContainer boundary.  Therefore the final rect returned is always in the
+    // physical coordinate space of the repaintContainer.
+    RenderStyle* styleToUse = style();
+    if (RenderView* v = view()) {
+        // LayoutState is only valid for root-relative, non-fixed position repainting
+        if (v->layoutStateEnabled() && !repaintContainer && styleToUse->position() != FixedPosition) {
+            LayoutState* layoutState = v->layoutState();
+
+            if (layer() && layer()->transform())
+                rect = layer()->transform()->mapRect(pixelSnappedIntRect(rect));
+
+            // We can't trust the bits on RenderObject, because this might be called while re-resolving style.
+            if (styleToUse->hasPaintOffset() && layer())
+                rect.move(layer()->paintOffset());
+
+            rect.moveBy(location());
+            rect.move(layoutState->m_paintOffset);
+            if (layoutState->m_clipped)
+                rect.intersect(layoutState->m_clipRect);
+            return;
+        }
+    }
+
+    if (hasReflection())
+        rect.unite(reflectedRect(rect));
+
+    if (repaintContainer == this) {
+        if (repaintContainer->style()->isFlippedBlocksWritingMode())
+            flipForWritingMode(rect);
+        return;
+    }
+
+    bool containerSkipped;
+    RenderObject* o = container(repaintContainer, &containerSkipped);
+    if (!o)
+        return;
+
+    if (isWritingModeRoot() && !isOutOfFlowPositioned())
+        flipForWritingMode(rect);
+
+    LayoutPoint topLeft = rect.location();
+    topLeft.move(locationOffset());
+
+    EPosition position = styleToUse->position();
+
+    // 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 (hasLayer() && layer()->transform()) {
+        fixed = position == FixedPosition;
+        rect = layer()->transform()->mapRect(pixelSnappedIntRect(rect));
+        topLeft = rect.location();
+        topLeft.move(locationOffset());
+    } else if (position == FixedPosition)
+        fixed = true;
+
+    if (position == AbsolutePosition && o->isInFlowPositioned() && o->isRenderInline())
+        topLeft += toRenderInline(o)->offsetForInFlowPositionedInline(this);
+    else if (styleToUse->hasPaintOffset() && layer()) {
+        // 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().
+        topLeft += layer()->paintOffset();
+    }
+    
+    if (position != AbsolutePosition && position != FixedPosition && o->hasColumns() && o->isBlockFlow()) {
+        LayoutRect repaintRect(topLeft, rect.size());
+        toRenderBlock(o)->adjustRectForColumns(repaintRect);
+        topLeft = repaintRect.location();
+        rect = repaintRect;
+    }
+
+    // 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.
+    rect.setLocation(topLeft);
+    if (o->hasOverflowClip()) {
+        RenderBox* containerBox = toRenderBox(o);
+        containerBox->applyCachedClipAndScrollOffsetForRepaint(rect);
+        if (rect.isEmpty())
+            return;
+    }
+
+    if (containerSkipped) {
+        // If the repaintContainer is below o, then we need to map the rect into repaintContainer's coordinates.
+        LayoutSize containerOffset = repaintContainer->offsetFromAncestorContainer(o);
+        rect.move(-containerOffset);
+        return;
+    }
+
+    o->computeRectForRepaint(repaintContainer, rect, fixed);
+}
+
+void RenderBox::repaintDuringLayoutIfMoved(const LayoutRect& oldRect)
+{
+    if (oldRect.location() != m_frameRect.location()) {
+        LayoutRect newRect = m_frameRect;
+        // 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_frameRect = oldRect;
+        repaint();
+        repaintOverhangingFloats(true);
+        m_frameRect = newRect;
+        repaint();
+        repaintOverhangingFloats(true);
+    }
+}
+
+void RenderBox::repaintOverhangingFloats(bool)
+{
+}
+
+void RenderBox::updateLogicalWidth()
+{
+    LogicalExtentComputedValues computedValues;
+    computeLogicalWidthInRegion(computedValues);
+
+    setLogicalWidth(computedValues.m_extent);
+    setLogicalLeft(computedValues.m_position);
+    setMarginStart(computedValues.m_margins.m_start);
+    setMarginEnd(computedValues.m_margins.m_end);
+}
+
+void RenderBox::computeLogicalWidthInRegion(LogicalExtentComputedValues& computedValues, RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage) const
+{
+    computedValues.m_extent = logicalWidth();
+    computedValues.m_position = logicalLeft();
+    computedValues.m_margins.m_start = marginStart();
+    computedValues.m_margins.m_end = marginEnd();
+
+    if (isOutOfFlowPositioned()) {
+        // FIXME: This calculation is not patched for block-flow yet.
+        // https://bugs.webkit.org/show_bug.cgi?id=46500
+        computePositionedLogicalWidth(computedValues, region, offsetFromLogicalTopOfFirstPage);
+        return;
+    }
+
+    // If layout is limited to a subtree, the subtree root's logical 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.
+    // FIXME: Account for block-flow in flexible boxes.
+    // https://bugs.webkit.org/show_bug.cgi?id=46418
+    if (hasOverrideWidth() && (style()->borderFit() == BorderFitLines || parent()->isFlexibleBoxIncludingDeprecated())) {
+        computedValues.m_extent = overrideLogicalContentWidth() + borderAndPaddingLogicalWidth();
+        return;
+    }
+
+    // FIXME: Account for block-flow in flexible boxes.
+    // https://bugs.webkit.org/show_bug.cgi?id=46418
+    bool inVerticalBox = parent()->isDeprecatedFlexibleBox() && (parent()->style()->boxOrient() == VERTICAL);
+    bool stretching = (parent()->style()->boxAlign() == BSTRETCH);
+    bool treatAsReplaced = shouldComputeSizeAsReplaced() && (!inVerticalBox || !stretching);
+
+    RenderStyle* styleToUse = style();
+    Length logicalWidthLength = treatAsReplaced ? Length(computeReplacedLogicalWidth(), Fixed) : styleToUse->logicalWidth();
+
+    RenderBlock* cb = containingBlock();
+    LayoutUnit containerLogicalWidth = max<LayoutUnit>(0, containingBlockLogicalWidthForContentInRegion(region, offsetFromLogicalTopOfFirstPage));
+    bool hasPerpendicularContainingBlock = cb->isHorizontalWritingMode() != isHorizontalWritingMode();
+    
+    if (isInline() && !isInlineBlockOrInlineTable()) {
+        // just calculate margins
+        RenderView* renderView = view();
+        computedValues.m_margins.m_start = minimumValueForLength(styleToUse->marginStart(), containerLogicalWidth, renderView);
+        computedValues.m_margins.m_end = minimumValueForLength(styleToUse->marginEnd(), containerLogicalWidth, renderView);
+        if (treatAsReplaced)
+            computedValues.m_extent = max<LayoutUnit>(floatValueForLength(logicalWidthLength, 0) + borderAndPaddingLogicalWidth(), minPreferredLogicalWidth());
+        return;
+    }
+
+    // Width calculations
+    if (treatAsReplaced)
+        computedValues.m_extent = logicalWidthLength.value() + borderAndPaddingLogicalWidth();
+    else {
+        LayoutUnit containerWidthInInlineDirection = containerLogicalWidth;
+        if (hasPerpendicularContainingBlock)
+            containerWidthInInlineDirection = perpendicularContainingBlockLogicalHeight();
+        LayoutUnit preferredWidth = computeLogicalWidthInRegionUsing(MainOrPreferredSize, styleToUse->logicalWidth(), containerWidthInInlineDirection, cb, region, offsetFromLogicalTopOfFirstPage);
+        computedValues.m_extent = constrainLogicalWidthInRegionByMinMax(preferredWidth, containerWidthInInlineDirection, cb, region, offsetFromLogicalTopOfFirstPage);
+    }
+
+    // Margin calculations.
+    if (hasPerpendicularContainingBlock || isFloating() || isInline()) {
+        RenderView* renderView = view();
+        computedValues.m_margins.m_start = minimumValueForLength(styleToUse->marginStart(), containerLogicalWidth, renderView);
+        computedValues.m_margins.m_end = minimumValueForLength(styleToUse->marginEnd(), containerLogicalWidth, renderView);
+    } else {
+        LayoutUnit containerLogicalWidthForAutoMargins = containerLogicalWidth;
+        if (avoidsFloats() && cb->containsFloats())
+            containerLogicalWidthForAutoMargins = containingBlockAvailableLineWidthInRegion(region, offsetFromLogicalTopOfFirstPage);
+        bool hasInvertedDirection = cb->style()->isLeftToRightDirection() != style()->isLeftToRightDirection();
+        computeInlineDirectionMargins(cb, containerLogicalWidthForAutoMargins, computedValues.m_extent,
+            hasInvertedDirection ? computedValues.m_margins.m_end : computedValues.m_margins.m_start,
+            hasInvertedDirection ? computedValues.m_margins.m_start : computedValues.m_margins.m_end);
+    }
+    
+    if (!hasPerpendicularContainingBlock && containerLogicalWidth && containerLogicalWidth != (computedValues.m_extent + computedValues.m_margins.m_start + computedValues.m_margins.m_end)
+        && !isFloating() && !isInline() && !cb->isFlexibleBoxIncludingDeprecated() && !cb->isRenderGrid()) {
+        LayoutUnit newMargin = containerLogicalWidth - computedValues.m_extent - cb->marginStartForChild(this);
+        bool hasInvertedDirection = cb->style()->isLeftToRightDirection() != style()->isLeftToRightDirection();
+        if (hasInvertedDirection)
+            computedValues.m_margins.m_start = newMargin;
+        else
+            computedValues.m_margins.m_end = newMargin;
+    }
+}
+
+LayoutUnit RenderBox::fillAvailableMeasure(LayoutUnit availableLogicalWidth) const
+{
+    LayoutUnit marginStart = 0;
+    LayoutUnit marginEnd = 0;
+    return fillAvailableMeasure(availableLogicalWidth, marginStart, marginEnd);
+}
+
+LayoutUnit RenderBox::fillAvailableMeasure(LayoutUnit availableLogicalWidth, LayoutUnit& marginStart, LayoutUnit& marginEnd) const
+{
+    RenderView* renderView = view();
+    marginStart = minimumValueForLength(style()->marginStart(), availableLogicalWidth, renderView);
+    marginEnd = minimumValueForLength(style()->marginEnd(), availableLogicalWidth, renderView);
+    return availableLogicalWidth - marginStart - marginEnd;
+}
+
+LayoutUnit RenderBox::computeIntrinsicLogicalWidthUsing(Length logicalWidthLength, LayoutUnit availableLogicalWidth, LayoutUnit borderAndPadding) const
+{
+    if (logicalWidthLength.type() == FillAvailable)
+        return fillAvailableMeasure(availableLogicalWidth);
+
+    LayoutUnit minLogicalWidth = 0;
+    LayoutUnit maxLogicalWidth = 0;
+    computeIntrinsicLogicalWidths(minLogicalWidth, maxLogicalWidth);
+
+    if (logicalWidthLength.type() == MinContent)
+        return minLogicalWidth + borderAndPadding;
+
+    if (logicalWidthLength.type() == MaxContent)
+        return maxLogicalWidth + borderAndPadding;
+
+    if (logicalWidthLength.type() == FitContent) {
+        minLogicalWidth += borderAndPadding;
+        maxLogicalWidth += borderAndPadding;
+        return max(minLogicalWidth, min(maxLogicalWidth, fillAvailableMeasure(availableLogicalWidth)));
+    }
+
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
+LayoutUnit RenderBox::computeLogicalWidthInRegionUsing(SizeType widthType, Length logicalWidth, LayoutUnit availableLogicalWidth,
+    const RenderBlock* cb, RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage) const
+{
+    if (!logicalWidth.isIntrinsicOrAuto()) {
+        // FIXME: If the containing block flow is perpendicular to our direction we need to use the available logical height instead.
+        return adjustBorderBoxLogicalWidthForBoxSizing(valueForLength(logicalWidth, availableLogicalWidth, view()));
+    }
+
+    if (logicalWidth.isIntrinsic())
+        return computeIntrinsicLogicalWidthUsing(logicalWidth, availableLogicalWidth, borderAndPaddingLogicalWidth());
+
+    LayoutUnit marginStart = 0;
+    LayoutUnit marginEnd = 0;
+    LayoutUnit logicalWidthResult = fillAvailableMeasure(availableLogicalWidth, marginStart, marginEnd);
+
+    if (shrinkToAvoidFloats() && cb->containsFloats())
+        logicalWidthResult = min(logicalWidthResult, shrinkLogicalWidthToAvoidFloats(marginStart, marginEnd, cb, region, offsetFromLogicalTopOfFirstPage));        
+
+    if (widthType == MainOrPreferredSize && sizesLogicalWidthToFitContent(widthType))
+        return max(minPreferredLogicalWidth(), min(maxPreferredLogicalWidth(), logicalWidthResult));
+    return logicalWidthResult;
+}
+
+static bool flexItemHasStretchAlignment(const RenderObject* flexitem)
+{
+    RenderObject* parent = flexitem->parent();
+    return flexitem->style()->alignSelf() == AlignStretch || (flexitem->style()->alignSelf() == AlignAuto && parent->style()->alignItems() == AlignStretch);
+}
+
+static bool isStretchingColumnFlexItem(const RenderObject* flexitem)
+{
+    RenderObject* parent = flexitem->parent();
+    if (parent->isDeprecatedFlexibleBox() && parent->style()->boxOrient() == VERTICAL && parent->style()->boxAlign() == BSTRETCH)
+        return true;
+
+    // We don't stretch multiline flexboxes because they need to apply line spacing (align-content) first.
+    if (parent->isFlexibleBox() && parent->style()->flexWrap() == FlexNoWrap && parent->style()->isColumnFlexDirection() && flexItemHasStretchAlignment(flexitem))
+        return true;
+    return false;
+}
+
+bool RenderBox::sizesLogicalWidthToFitContent(SizeType 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() || (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 logicalWidth = (widthType == MaxSize) ? style()->logicalMaxWidth() : style()->logicalWidth();
+    if (logicalWidth.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.
+    // FIXME: Think about block-flow here.  Need to find out how marquee direction relates to
+    // block-flow (as well as how marquee overflow should relate to block flow).
+    // https://bugs.webkit.org/show_bug.cgi?id=46472
+    if (parent()->style()->overflowX() == OMARQUEE) {
+        EMarqueeDirection dir = parent()->style()->marqueeDirection();
+        if (dir == MAUTO || dir == MFORWARD || dir == MBACKWARD || dir == MLEFT || dir == MRIGHT)
+            return true;
+    }
+
+    // Flexible box items should shrink wrap, so we lay them out at their intrinsic widths.
+    // In the case of columns that have a stretch alignment, we go ahead and layout at the
+    // stretched size to avoid an extra layout when applying alignment.
+    if (parent()->isFlexibleBox()) {
+        // For multiline columns, we need to apply align-content first, so we can't stretch now.
+        if (!parent()->style()->isColumnFlexDirection() || parent()->style()->flexWrap() != FlexNoWrap)
+            return true;
+        if (!flexItemHasStretchAlignment(this))
+            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.
+    // FIXME: Think about block-flow here.
+    // https://bugs.webkit.org/show_bug.cgi?id=46473
+    if (parent()->isDeprecatedFlexibleBox() && (parent()->style()->boxOrient() == HORIZONTAL || parent()->style()->boxAlign() != BSTRETCH))
+        return true;
+
+    // Button, input, select, textarea, and legend treat width value of 'auto' as 'intrinsic' unless it's in a
+    // stretching column flexbox.
+    // FIXME: Think about block-flow here.
+    // https://bugs.webkit.org/show_bug.cgi?id=46473
+    if (logicalWidth.type() == Auto && !isStretchingColumnFlexItem(this) && node() && (node()->hasTagName(inputTag) || node()->hasTagName(selectTag) || node()->hasTagName(buttonTag) || node()->hasTagName(textareaTag) || node()->hasTagName(legendTag)))
+        return true;
+
+    if (isHorizontalWritingMode() != containingBlock()->isHorizontalWritingMode())
+        return true;
+
+    return false;
+}
+
+void RenderBox::computeInlineDirectionMargins(RenderBlock* containingBlock, LayoutUnit containerWidth, LayoutUnit childWidth, LayoutUnit& marginStart, LayoutUnit& marginEnd) const
+{
+    const RenderStyle* containingBlockStyle = containingBlock->style();
+    Length marginStartLength = style()->marginStartUsing(containingBlockStyle);
+    Length marginEndLength = style()->marginEndUsing(containingBlockStyle);
+    RenderView* renderView = view();
+
+    if (isFloating() || isInline()) {
+        // Inline blocks/tables and floats don't have their margins increased.
+        marginStart = minimumValueForLength(marginStartLength, containerWidth, renderView);
+        marginEnd = minimumValueForLength(marginEndLength, containerWidth, renderView);
+        return;
+    }
+
+    // Case One: The object is being centered in the containing block's available logical width.
+    if ((marginStartLength.isAuto() && marginEndLength.isAuto() && childWidth < containerWidth)
+        || (!marginStartLength.isAuto() && !marginEndLength.isAuto() && containingBlock->style()->textAlign() == WEBKIT_CENTER)) {
+        // Other browsers center the margin box for align=center elements so we match them here.
+        LayoutUnit marginStartWidth = minimumValueForLength(marginStartLength, containerWidth, renderView);
+        LayoutUnit marginEndWidth = minimumValueForLength(marginEndLength, containerWidth, renderView);
+        LayoutUnit centeredMarginBoxStart = max<LayoutUnit>(0, (containerWidth - childWidth - marginStartWidth - marginEndWidth) / 2);
+        marginStart = centeredMarginBoxStart + marginStartWidth;
+        marginEnd = containerWidth - childWidth - marginStart + marginEndWidth;
+        return;
+    } 
+    
+    // Case Two: The object is being pushed to the start of the containing block's available logical width.
+    if (marginEndLength.isAuto() && childWidth < containerWidth) {
+        marginStart = valueForLength(marginStartLength, containerWidth, renderView);
+        marginEnd = containerWidth - childWidth - marginStart;
+        return;
+    } 
+    
+    // Case Three: The object is being pushed to the end of the containing block's available logical width.
+    bool pushToEndFromTextAlign = !marginEndLength.isAuto() && ((!containingBlockStyle->isLeftToRightDirection() && containingBlockStyle->textAlign() == WEBKIT_LEFT)
+        || (containingBlockStyle->isLeftToRightDirection() && containingBlockStyle->textAlign() == WEBKIT_RIGHT));
+    if ((marginStartLength.isAuto() && childWidth < containerWidth) || pushToEndFromTextAlign) {
+        marginEnd = valueForLength(marginEndLength, containerWidth, renderView);
+        marginStart = containerWidth - childWidth - marginEnd;
+        return;
+    } 
+    
+    // Case Four: Either no auto margins, or our width is >= the container width (css2.1, 10.3.3).  In that case
+    // auto margins will just turn into 0.
+    marginStart = minimumValueForLength(marginStartLength, containerWidth, renderView);
+    marginEnd = minimumValueForLength(marginEndLength, containerWidth, renderView);
+}
+
+RenderBoxRegionInfo* RenderBox::renderBoxRegionInfo(RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage, RenderBoxRegionInfoFlags cacheFlag) const
+{
+    // Make sure nobody is trying to call this with a null region.
+    if (!region)
+        return 0;
+
+    // If we have computed our width in this region already, it will be cached, and we can
+    // just return it.
+    RenderBoxRegionInfo* boxInfo = region->renderBoxRegionInfo(this);
+    if (boxInfo && cacheFlag == CacheRenderBoxRegionInfo)
+        return boxInfo;
+
+    // No cached value was found, so we have to compute our insets in this region.
+    // FIXME: For now we limit this computation to normal RenderBlocks. Future patches will expand
+    // support to cover all boxes.
+    RenderFlowThread* flowThread = flowThreadContainingBlock();
+    if (isRenderFlowThread() || !flowThread || !canHaveBoxInfoInRegion() || flowThread->style()->writingMode() != style()->writingMode())
+        return 0;
+
+    LogicalExtentComputedValues computedValues;
+    computeLogicalWidthInRegion(computedValues, region, offsetFromLogicalTopOfFirstPage);
+
+    // Now determine the insets based off where this object is supposed to be positioned.
+    RenderBlock* cb = containingBlock();
+    RenderRegion* clampedContainingBlockRegion = cb->clampToStartAndEndRegions(region);
+    RenderBoxRegionInfo* containingBlockInfo = cb->renderBoxRegionInfo(clampedContainingBlockRegion,
+        offsetFromLogicalTopOfFirstPage - logicalTop());
+    LayoutUnit containingBlockLogicalWidth = cb->logicalWidth();
+    LayoutUnit containingBlockLogicalWidthInRegion = containingBlockInfo ? containingBlockInfo->logicalWidth() : containingBlockLogicalWidth;
+    
+    LayoutUnit marginStartInRegion = computedValues.m_margins.m_start;
+    LayoutUnit startMarginDelta = marginStartInRegion - marginStart();
+    LayoutUnit logicalWidthInRegion = computedValues.m_extent;
+    LayoutUnit logicalLeftInRegion = computedValues.m_position;
+    LayoutUnit widthDelta = logicalWidthInRegion - logicalWidth();
+    LayoutUnit logicalLeftDelta = isOutOfFlowPositioned() ? logicalLeftInRegion - logicalLeft() : startMarginDelta;
+    LayoutUnit logicalRightInRegion = containingBlockLogicalWidthInRegion - (logicalLeftInRegion + logicalWidthInRegion);
+    LayoutUnit oldLogicalRight = containingBlockLogicalWidth - (logicalLeft() + logicalWidth());
+    LayoutUnit logicalRightDelta = isOutOfFlowPositioned() ? logicalRightInRegion - oldLogicalRight : startMarginDelta;
+
+    LayoutUnit logicalLeftOffset = 0;
+    
+    if (!isOutOfFlowPositioned() && avoidsFloats() && cb->containsFloats()) {
+        LayoutUnit startPositionDelta = cb->computeStartPositionDeltaForChildAvoidingFloats(this, marginStartInRegion, region, offsetFromLogicalTopOfFirstPage);
+        if (cb->style()->isLeftToRightDirection())
+            logicalLeftDelta += startPositionDelta;
+        else
+            logicalRightDelta += startPositionDelta;
+    }
+
+    if (cb->style()->isLeftToRightDirection())
+        logicalLeftOffset += logicalLeftDelta;
+    else
+        logicalLeftOffset -= (widthDelta + logicalRightDelta);
+    
+    LayoutUnit logicalRightOffset = logicalWidth() - (logicalLeftOffset + logicalWidthInRegion);
+    bool isShifted = (containingBlockInfo && containingBlockInfo->isShifted())
+            || (style()->isLeftToRightDirection() && logicalLeftOffset)
+            || (!style()->isLeftToRightDirection() && logicalRightOffset);
+
+    // FIXME: Although it's unlikely, these boxes can go outside our bounds, and so we will need to incorporate them into overflow.
+    if (cacheFlag == CacheRenderBoxRegionInfo)
+        return region->setRenderBoxRegionInfo(this, logicalLeftOffset, logicalWidthInRegion, isShifted);
+    return new RenderBoxRegionInfo(logicalLeftOffset, logicalWidthInRegion, isShifted);
+}
+
+static bool shouldFlipBeforeAfterMargins(const RenderStyle* containingBlockStyle, const RenderStyle* childStyle)
+{
+    ASSERT(containingBlockStyle->isHorizontalWritingMode() != childStyle->isHorizontalWritingMode());
+    WritingMode childWritingMode = childStyle->writingMode();
+    bool shouldFlip = false;
+    switch (containingBlockStyle->writingMode()) {
+    case TopToBottomWritingMode:
+        shouldFlip = (childWritingMode == RightToLeftWritingMode);
+        break;
+    case BottomToTopWritingMode:
+        shouldFlip = (childWritingMode == RightToLeftWritingMode);
+        break;
+    case RightToLeftWritingMode:
+        shouldFlip = (childWritingMode == BottomToTopWritingMode);
+        break;
+    case LeftToRightWritingMode:
+        shouldFlip = (childWritingMode == BottomToTopWritingMode);
+        break;
+    }
+
+    if (!containingBlockStyle->isLeftToRightDirection())
+        shouldFlip = !shouldFlip;
+
+    return shouldFlip;
+}
+
+void RenderBox::updateLogicalHeight()
+{
+    LogicalExtentComputedValues computedValues;
+    computeLogicalHeight(logicalHeight(), logicalTop(), computedValues);
+
+    setLogicalHeight(computedValues.m_extent);
+    setLogicalTop(computedValues.m_position);
+    setMarginBefore(computedValues.m_margins.m_before);
+    setMarginAfter(computedValues.m_margins.m_after);
+}
+
+void RenderBox::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues& computedValues) const
+{
+    computedValues.m_extent = logicalHeight;
+    computedValues.m_position = logicalTop;
+
+    // Cell height is managed by the table and inline non-replaced elements do not support a height property.
+    if (isTableCell() || (isInline() && !isReplaced()))
+        return;
+
+    Length h;
+    if (isOutOfFlowPositioned())
+        computePositionedLogicalHeight(computedValues);
+    else {
+        RenderBlock* cb = containingBlock();
+        bool hasPerpendicularContainingBlock = cb->isHorizontalWritingMode() != isHorizontalWritingMode();
+    
+        if (!hasPerpendicularContainingBlock) {
+            bool shouldFlipBeforeAfter = cb->style()->writingMode() != style()->writingMode();
+            computeBlockDirectionMargins(cb,
+                shouldFlipBeforeAfter ? computedValues.m_margins.m_after : computedValues.m_margins.m_before,
+                shouldFlipBeforeAfter ? computedValues.m_margins.m_before : computedValues.m_margins.m_after);
+        }
+
+        // For tables, calculate margins only.
+        if (isTable()) {
+            if (hasPerpendicularContainingBlock) {
+                bool shouldFlipBeforeAfter = shouldFlipBeforeAfterMargins(cb->style(), style());
+                computeInlineDirectionMargins(cb, containingBlockLogicalWidthForContent(), computedValues.m_extent,
+                    shouldFlipBeforeAfter ? computedValues.m_margins.m_after : computedValues.m_margins.m_before,
+                    shouldFlipBeforeAfter ? computedValues.m_margins.m_before : computedValues.m_margins.m_after);
+            }
+            return;
+        }
+
+        // FIXME: Account for block-flow in flexible boxes.
+        // https://bugs.webkit.org/show_bug.cgi?id=46418
+        bool inHorizontalBox = parent()->isDeprecatedFlexibleBox() && parent()->style()->boxOrient() == HORIZONTAL;
+        bool stretching = parent()->style()->boxAlign() == BSTRETCH;
+        bool treatAsReplaced = shouldComputeSizeAsReplaced() && (!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.
+        // FIXME: Account for block-flow in flexible boxes.
+        // https://bugs.webkit.org/show_bug.cgi?id=46418
+        if (hasOverrideHeight() && parent()->isFlexibleBoxIncludingDeprecated())
+            h = Length(overrideLogicalContentHeight(), Fixed);
+        else if (treatAsReplaced)
+            h = Length(computeReplacedLogicalHeight(), Fixed);
+        else {
+            h = style()->logicalHeight();
+            checkMinMaxHeight = true;
+        }
+
+        // Block children of horizontal flexible boxes fill the height of the box.
+        // FIXME: Account for block-flow in flexible boxes.
+        // https://bugs.webkit.org/show_bug.cgi?id=46418
+        if (h.isAuto() && parent()->isDeprecatedFlexibleBox() && parent()->style()->boxOrient() == HORIZONTAL
+                && parent()->isStretchingChildren()) {
+            h = Length(parentBox()->contentLogicalHeight() - marginBefore() - marginAfter() - borderAndPaddingLogicalHeight(), Fixed);
+            checkMinMaxHeight = false;
+        }
+
+        LayoutUnit heightResult;
+        if (checkMinMaxHeight) {
+            heightResult = computeLogicalHeightUsing(style()->logicalHeight(), computedValues.m_extent - borderAndPaddingLogicalHeight());
+            if (heightResult == -1)
+                heightResult = computedValues.m_extent;
+            heightResult = constrainLogicalHeightByMinMax(heightResult, computedValues.m_extent - borderAndPaddingLogicalHeight());
+        } 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.
+            ASSERT(h.isFixed());
+            heightResult = h.value() + borderAndPaddingLogicalHeight();
+        }
+
+        computedValues.m_extent = heightResult;
+        
+        if (hasPerpendicularContainingBlock) {
+            bool shouldFlipBeforeAfter = shouldFlipBeforeAfterMargins(cb->style(), style());
+            computeInlineDirectionMargins(cb, containingBlockLogicalWidthForContent(), heightResult,
+                    shouldFlipBeforeAfter ? computedValues.m_margins.m_after : computedValues.m_margins.m_before,
+                    shouldFlipBeforeAfter ? computedValues.m_margins.m_before : computedValues.m_margins.m_after);
+        }
+    }
+
+    // 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. When we're printing, we also need this quirk if the body or root has a percentage 
+    // height since we don't set a height in RenderView when we're printing. So without this quirk, the 
+    // height has nothing to be a percentage of, and it ends up being 0. That is bad.
+    bool paginatedContentNeedsBaseHeight = document()->printing() && h.isPercent()
+        && (isRoot() || (isBody() && document()->documentElement()->renderer()->style()->logicalHeight().isPercent())) && !isInline();
+    if (stretchesToViewport() || paginatedContentNeedsBaseHeight) {
+        LayoutUnit margins = collapsedMarginBefore() + collapsedMarginAfter();
+        LayoutUnit visibleHeight = viewLogicalHeightForPercentages();
+        if (isRoot())
+            computedValues.m_extent = max(computedValues.m_extent, visibleHeight - margins);
+        else {
+            LayoutUnit marginsBordersPadding = margins + parentBox()->marginBefore() + parentBox()->marginAfter() + parentBox()->borderAndPaddingLogicalHeight();
+            computedValues.m_extent = max(computedValues.m_extent, visibleHeight - marginsBordersPadding);
+        }
+    }
+}
+
+LayoutUnit RenderBox::viewLogicalHeightForPercentages() const
+{
+    if (document()->printing())
+        return static_cast<LayoutUnit>(view()->pageLogicalHeight());
+    return view()->viewLogicalHeight();
+}
+
+LayoutUnit RenderBox::computeLogicalHeightUsing(const Length& height, LayoutUnit intrinsicContentHeight) const
+{
+    LayoutUnit logicalHeight = computeContentAndScrollbarLogicalHeightUsing(height, intrinsicContentHeight);
+    if (logicalHeight != -1)
+        logicalHeight = adjustBorderBoxLogicalHeightForBoxSizing(logicalHeight);
+    return logicalHeight;
+}
+
+LayoutUnit RenderBox::computeContentLogicalHeight(const Length& height, LayoutUnit intrinsicContentHeight) const
+{
+    LayoutUnit heightIncludingScrollbar = computeContentAndScrollbarLogicalHeightUsing(height, intrinsicContentHeight);
+    if (heightIncludingScrollbar == -1)
+        return -1;
+    return std::max<LayoutUnit>(0, adjustContentBoxLogicalHeightForBoxSizing(heightIncludingScrollbar) - scrollbarLogicalHeight());
+}
+
+LayoutUnit RenderBox::computeIntrinsicLogicalContentHeightUsing(Length logicalHeightLength, LayoutUnit intrinsicContentHeight, LayoutUnit borderAndPadding) const
+{
+    // FIXME(cbiesinger): The css-sizing spec is considering changing what min-content/max-content should resolve to.
+    // If that happens, this code will have to change.
+    if (logicalHeightLength.isMinContent() || logicalHeightLength.isMaxContent() || logicalHeightLength.isFitContent())
+        return intrinsicContentHeight;
+    if (logicalHeightLength.isFillAvailable())
+        return containingBlock()->availableLogicalHeight(ExcludeMarginBorderPadding) - borderAndPadding;
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
+LayoutUnit RenderBox::computeContentAndScrollbarLogicalHeightUsing(const Length& height, LayoutUnit intrinsicContentHeight) const
+{
+    // FIXME(cbiesinger): The css-sizing spec is considering changing what min-content/max-content should resolve to.
+    // If that happens, this code will have to change.
+    if (height.isIntrinsic())
+        return computeIntrinsicLogicalContentHeightUsing(height, intrinsicContentHeight, borderAndPaddingLogicalHeight());
+    if (height.isFixed())
+        return height.value();
+    if (height.isPercent())
+        return computePercentageLogicalHeight(height);
+    if (height.isViewportPercentage())
+        return valueForLength(height, 0, view());
+    return -1;
+}
+
+bool RenderBox::skipContainingBlockForPercentHeightCalculation(const RenderBox* containingBlock) const
+{
+    // For quirks mode and anonymous blocks, we skip auto-height containingBlocks when computing percentages.
+    // For standards mode, we treat the percentage as auto if it has an auto-height containing block.
+    if (!document()->inQuirksMode() && !containingBlock->isAnonymousBlock())
+        return false;
+    return !containingBlock->isTableCell() && !containingBlock->isOutOfFlowPositioned() && containingBlock->style()->logicalHeight().isAuto() && isHorizontalWritingMode() == containingBlock->isHorizontalWritingMode();
+}
+
+LayoutUnit RenderBox::computePercentageLogicalHeight(const Length& height) const
+{
+    LayoutUnit availableHeight = -1;
+    
+    bool skippedAutoHeightContainingBlock = false;
+    RenderBlock* cb = containingBlock();
+    const RenderBox* containingBlockChild = this;
+    LayoutUnit rootMarginBorderPaddingHeight = 0;
+    while (!cb->isRenderView() && skipContainingBlockForPercentHeightCalculation(cb)) {
+        if (cb->isBody() || cb->isRoot())
+            rootMarginBorderPaddingHeight += cb->marginBefore() + cb->marginAfter() + cb->borderAndPaddingLogicalHeight();
+        skippedAutoHeightContainingBlock = true;
+        containingBlockChild = cb;
+        cb = cb->containingBlock();
+        cb->addPercentHeightDescendant(const_cast<RenderBox*>(this));
+    }
+
+    RenderStyle* cbstyle = cb->style();
+
+    // 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 isOutOfFlowPositionedWithSpecifiedHeight = cb->isOutOfFlowPositioned() && (!cbstyle->logicalHeight().isAuto() || (!cbstyle->logicalTop().isAuto() && !cbstyle->logicalBottom().isAuto()));
+
+    bool includeBorderPadding = isTable();
+
+    if (isHorizontalWritingMode() != cb->isHorizontalWritingMode())
+        availableHeight = containingBlockChild->containingBlockLogicalWidthForContent();
+    else if (hasOverrideContainingBlockLogicalHeight())
+        availableHeight = overrideContainingBlockContentLogicalHeight();
+    else if (cb->isTableCell()) {
+        if (!skippedAutoHeightContainingBlock) {
+            // 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->hasOverrideHeight()) {
+                // 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 = toRenderTableCell(cb);
+                if (scrollsOverflowY() && (!cell->style()->logicalHeight().isAuto() || !cell->table()->style()->logicalHeight().isAuto()))
+                    return 0;
+                return -1;
+            }
+            availableHeight = cb->overrideLogicalContentHeight();
+            includeBorderPadding = true;
+        }
+    } else if (cbstyle->logicalHeight().isFixed()) {
+        LayoutUnit contentBoxHeight = cb->adjustContentBoxLogicalHeightForBoxSizing(cbstyle->logicalHeight().value());
+        availableHeight = max<LayoutUnit>(0, cb->constrainContentBoxLogicalHeightByMinMax(contentBoxHeight - cb->scrollbarLogicalHeight(), -1));
+    } else if (cbstyle->logicalHeight().isPercent() && !isOutOfFlowPositionedWithSpecifiedHeight) {
+        // We need to recur and compute the percentage height for our containing block.
+        LayoutUnit heightWithScrollbar = cb->computePercentageLogicalHeight(cbstyle->logicalHeight());
+        if (heightWithScrollbar != -1) {
+            LayoutUnit contentBoxHeightWithScrollbar = cb->adjustContentBoxLogicalHeightForBoxSizing(heightWithScrollbar);
+            // We need to adjust for min/max height because this method does not
+            // handle the min/max of the current block, its caller does. So the
+            // return value from the recursive call will not have been adjusted
+            // yet.
+            LayoutUnit contentBoxHeight = cb->constrainContentBoxLogicalHeightByMinMax(contentBoxHeightWithScrollbar - cb->scrollbarLogicalHeight(), -1);
+            availableHeight = max<LayoutUnit>(0, contentBoxHeight);
+        }
+    } else if (isOutOfFlowPositionedWithSpecifiedHeight) {
+        // Don't allow this to affect the block' height() member variable, since this
+        // can get called while the block is still laying out its kids.
+        LogicalExtentComputedValues computedValues;
+        cb->computeLogicalHeight(cb->logicalHeight(), 0, computedValues);
+        availableHeight = computedValues.m_extent - cb->borderAndPaddingLogicalHeight() - cb->scrollbarLogicalHeight();
+    } else if (cb->isRenderView())
+        availableHeight = viewLogicalHeightForPercentages();
+
+    if (availableHeight == -1)
+        return availableHeight;
+
+    availableHeight -= rootMarginBorderPaddingHeight;
+
+    LayoutUnit result = valueForLength(height, availableHeight);
+    if (includeBorderPadding) {
+        // FIXME: Table cells should default to box-sizing: border-box so we can avoid this hack.
+        // 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 -= borderAndPaddingLogicalHeight();
+        return max<LayoutUnit>(0, result);
+    }
+    return result;
+}
+
+LayoutUnit RenderBox::computeReplacedLogicalWidth(ShouldComputePreferred shouldComputePreferred) const
+{
+    return computeReplacedLogicalWidthRespectingMinMaxWidth(computeReplacedLogicalWidthUsing(style()->logicalWidth()), shouldComputePreferred);
+}
+
+LayoutUnit RenderBox::computeReplacedLogicalWidthRespectingMinMaxWidth(LayoutUnit logicalWidth, ShouldComputePreferred shouldComputePreferred) const
+{
+    LayoutUnit minLogicalWidth = (shouldComputePreferred == ComputePreferred && style()->logicalMinWidth().isPercent()) || style()->logicalMinWidth().isUndefined() ? logicalWidth : computeReplacedLogicalWidthUsing(style()->logicalMinWidth());
+    LayoutUnit maxLogicalWidth = (shouldComputePreferred == ComputePreferred && style()->logicalMaxWidth().isPercent()) || style()->logicalMaxWidth().isUndefined() ? logicalWidth : computeReplacedLogicalWidthUsing(style()->logicalMaxWidth());
+    return max(minLogicalWidth, min(logicalWidth, maxLogicalWidth));
+}
+
+LayoutUnit RenderBox::computeReplacedLogicalWidthUsing(Length logicalWidth) const
+{
+    switch (logicalWidth.type()) {
+        case Fixed:
+            return adjustContentBoxLogicalWidthForBoxSizing(logicalWidth.value());
+        case MinContent:
+        case MaxContent: {
+            // MinContent/MaxContent don't need the availableLogicalWidth argument.
+            LayoutUnit availableLogicalWidth = 0;
+            return computeIntrinsicLogicalWidthUsing(logicalWidth, availableLogicalWidth, borderAndPaddingLogicalWidth()) - borderAndPaddingLogicalWidth();
+        }
+        case ViewportPercentageWidth:
+        case ViewportPercentageHeight:
+        case ViewportPercentageMin:
+        case ViewportPercentageMax:
+            return adjustContentBoxLogicalWidthForBoxSizing(valueForLength(logicalWidth, 0, view()));
+        case FitContent:
+        case FillAvailable:
+        case Percent: 
+        case Calculated: {
+            // FIXME: containingBlockLogicalWidthForContent() is wrong if the replaced element's block-flow is perpendicular to the
+            // containing block's block-flow.
+            // https://bugs.webkit.org/show_bug.cgi?id=46496
+            const LayoutUnit cw = isOutOfFlowPositioned() ? containingBlockLogicalWidthForPositioned(toRenderBoxModelObject(container())) : containingBlockLogicalWidthForContent();
+            Length containerLogicalWidth = containingBlock()->style()->logicalWidth();
+            // FIXME: Handle cases when containing block width is calculated or viewport percent.
+            // https://bugs.webkit.org/show_bug.cgi?id=91071
+            if (logicalWidth.isIntrinsic())
+                return computeIntrinsicLogicalWidthUsing(logicalWidth, cw, borderAndPaddingLogicalWidth()) - borderAndPaddingLogicalWidth();
+            if (cw > 0 || (!cw && (containerLogicalWidth.isFixed() || containerLogicalWidth.isPercent())))
+                return adjustContentBoxLogicalWidthForBoxSizing(minimumValueForLength(logicalWidth, cw));
+        }
+        // fall through
+        case Intrinsic:
+        case MinIntrinsic:
+        case Auto:
+        case Relative:
+        case Undefined:
+            return intrinsicLogicalWidth();
+    }
+
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
+LayoutUnit RenderBox::computeReplacedLogicalHeight() const
+{
+    return computeReplacedLogicalHeightRespectingMinMaxHeight(computeReplacedLogicalHeightUsing(style()->logicalHeight()));
+}
+
+LayoutUnit RenderBox::computeReplacedLogicalHeightRespectingMinMaxHeight(LayoutUnit logicalHeight) const
+{
+    LayoutUnit minLogicalHeight = computeReplacedLogicalHeightUsing(style()->logicalMinHeight());
+    LayoutUnit maxLogicalHeight = style()->logicalMaxHeight().isUndefined() ? logicalHeight : computeReplacedLogicalHeightUsing(style()->logicalMaxHeight());
+    return max(minLogicalHeight, min(logicalHeight, maxLogicalHeight));
+}
+
+LayoutUnit RenderBox::computeReplacedLogicalHeightUsing(Length logicalHeight) const
+{
+    switch (logicalHeight.type()) {
+        case Fixed:
+            return adjustContentBoxLogicalHeightForBoxSizing(logicalHeight.value());
+        case Percent:
+        case Calculated:
+        {
+            RenderObject* cb = isOutOfFlowPositioned() ? container() : containingBlock();
+            while (cb->isAnonymous()) {
+                cb = cb->containingBlock();
+                toRenderBlock(cb)->addPercentHeightDescendant(const_cast<RenderBox*>(this));
+            }
+
+            // FIXME: This calculation is not patched for block-flow yet.
+            // https://bugs.webkit.org/show_bug.cgi?id=46500
+            if (cb->isOutOfFlowPositioned() && cb->style()->height().isAuto() && !(cb->style()->top().isAuto() || cb->style()->bottom().isAuto())) {
+                ASSERT_WITH_SECURITY_IMPLICATION(cb->isRenderBlock());
+                RenderBlock* block = toRenderBlock(cb);
+                LogicalExtentComputedValues computedValues;
+                block->computeLogicalHeight(block->logicalHeight(), 0, computedValues);
+                LayoutUnit newContentHeight = computedValues.m_extent - block->borderAndPaddingLogicalHeight() - block->scrollbarLogicalHeight();
+                LayoutUnit newHeight = block->adjustContentBoxLogicalHeightForBoxSizing(newContentHeight);
+                return adjustContentBoxLogicalHeightForBoxSizing(valueForLength(logicalHeight, newHeight));
+            }
+            
+            // FIXME: availableLogicalHeight() is wrong if the replaced element's block-flow is perpendicular to the
+            // containing block's block-flow.
+            // https://bugs.webkit.org/show_bug.cgi?id=46496
+            LayoutUnit availableHeight;
+            if (isOutOfFlowPositioned())
+                availableHeight = containingBlockLogicalHeightForPositioned(toRenderBoxModelObject(cb));
+            else {
+                availableHeight = containingBlockLogicalHeightForContent(IncludeMarginBorderPadding);
+                // 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.
+                // FIXME: This needs to be made block-flow-aware.  If the cell and image are perpendicular block-flows, this isn't right.
+                // https://bugs.webkit.org/show_bug.cgi?id=46997
+                while (cb && !cb->isRenderView() && (cb->style()->logicalHeight().isAuto() || cb->style()->logicalHeight().isPercent())) {
+                    if (cb->isTableCell()) {
+                        // Don't let table cells squeeze percent-height replaced elements
+                        // <http://bugs.webkit.org/show_bug.cgi?id=15359>
+                        availableHeight = max(availableHeight, intrinsicLogicalHeight());
+                        return valueForLength(logicalHeight, availableHeight - borderAndPaddingLogicalHeight());
+                    }
+                    toRenderBlock(cb)->addPercentHeightDescendant(const_cast<RenderBox*>(this));
+                    cb = cb->containingBlock();
+                }
+            }
+            return adjustContentBoxLogicalHeightForBoxSizing(valueForLength(logicalHeight, availableHeight));
+        }
+        case ViewportPercentageWidth:
+        case ViewportPercentageHeight:
+        case ViewportPercentageMin:
+        case ViewportPercentageMax:
+            return adjustContentBoxLogicalHeightForBoxSizing(valueForLength(logicalHeight, 0, view()));
+        case MinContent:
+        case MaxContent:
+        case FitContent:
+        case FillAvailable:
+            return adjustContentBoxLogicalHeightForBoxSizing(computeIntrinsicLogicalContentHeightUsing(logicalHeight, intrinsicLogicalHeight(), borderAndPaddingHeight()));
+        default:
+            return intrinsicLogicalHeight();
+    }
+}
+
+LayoutUnit RenderBox::availableLogicalHeight(AvailableLogicalHeightType heightType) const
+{
+    return constrainLogicalHeightByMinMax(availableLogicalHeightUsing(style()->logicalHeight(), heightType), -1);
+}
+
+LayoutUnit RenderBox::availableLogicalHeightUsing(const Length& h, AvailableLogicalHeightType heightType) const
+{
+    if (isRenderView())
+        return isHorizontalWritingMode() ? toRenderView(this)->frameView()->visibleHeight() : toRenderView(this)->frameView()->visibleWidth();
+
+    // 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())) {
+        if (hasOverrideHeight())
+            return overrideLogicalContentHeight();
+        return logicalHeight() - borderAndPaddingLogicalHeight();
+    }
+
+    if (h.isPercent() && isOutOfFlowPositioned()) {
+        // FIXME: This is wrong if the containingBlock has a perpendicular writing mode.
+        LayoutUnit availableHeight = containingBlockLogicalHeightForPositioned(containingBlock());
+        return adjustContentBoxLogicalHeightForBoxSizing(valueForLength(h, availableHeight));
+    }
+
+    LayoutUnit heightIncludingScrollbar = computeContentAndScrollbarLogicalHeightUsing(h, -1);
+    if (heightIncludingScrollbar != -1)
+        return std::max<LayoutUnit>(0, adjustContentBoxLogicalHeightForBoxSizing(heightIncludingScrollbar) - scrollbarLogicalHeight());
+
+    // FIXME: Check logicalTop/logicalBottom here to correctly handle vertical writing-mode.
+    // https://bugs.webkit.org/show_bug.cgi?id=46500
+    if (isRenderBlock() && isOutOfFlowPositioned() && style()->height().isAuto() && !(style()->top().isAuto() || style()->bottom().isAuto())) {
+        RenderBlock* block = const_cast<RenderBlock*>(toRenderBlock(this));
+        LogicalExtentComputedValues computedValues;
+        block->computeLogicalHeight(block->logicalHeight(), 0, computedValues);
+        LayoutUnit newContentHeight = computedValues.m_extent - block->borderAndPaddingLogicalHeight() - block->scrollbarLogicalHeight();
+        return adjustContentBoxLogicalHeightForBoxSizing(newContentHeight);
+    }
+
+    // FIXME: This is wrong if the containingBlock has a perpendicular writing mode.
+    LayoutUnit availableHeight = containingBlockLogicalHeightForContent(heightType);
+    if (heightType == ExcludeMarginBorderPadding) {
+        // FIXME: Margin collapsing hasn't happened yet, so this incorrectly removes collapsed margins.
+        availableHeight -= marginBefore() + marginAfter() + borderAndPaddingLogicalHeight();
+    }
+    return availableHeight;
+}
+
+void RenderBox::computeBlockDirectionMargins(const RenderBlock* containingBlock, LayoutUnit& marginBefore, LayoutUnit& marginAfter) const
+{
+    if (isTableCell()) {
+        // FIXME: Not right if we allow cells to have different directionality than the table.  If we do allow this, though,
+        // we may just do it with an extra anonymous block inside the cell.
+        marginBefore = 0;
+        marginAfter = 0;
+        return;
+    }
+
+    // Margins are calculated with respect to the logical width of
+    // the containing block (8.3)
+    LayoutUnit cw = containingBlockLogicalWidthForContent();
+    RenderView* renderView = view();
+    RenderStyle* containingBlockStyle = containingBlock->style();
+    marginBefore = minimumValueForLength(style()->marginBeforeUsing(containingBlockStyle), cw, renderView);
+    marginAfter = minimumValueForLength(style()->marginAfterUsing(containingBlockStyle), cw, renderView);
+}
+
+void RenderBox::computeAndSetBlockDirectionMargins(const RenderBlock* containingBlock)
+{
+    LayoutUnit marginBefore;
+    LayoutUnit marginAfter;
+    computeBlockDirectionMargins(containingBlock, marginBefore, marginAfter);
+    containingBlock->setMarginBeforeForChild(this, marginBefore);
+    containingBlock->setMarginAfterForChild(this, marginAfter);
+}
+
+LayoutUnit RenderBox::containingBlockLogicalWidthForPositioned(const RenderBoxModelObject* containingBlock, RenderRegion* region,
+    LayoutUnit offsetFromLogicalTopOfFirstPage, bool checkForPerpendicularWritingMode) const
+{
+    if (checkForPerpendicularWritingMode && containingBlock->isHorizontalWritingMode() != isHorizontalWritingMode())
+        return containingBlockLogicalHeightForPositioned(containingBlock, false);
+
+    // Use viewport as container for top-level fixed-position elements.
+    if (style()->position() == FixedPosition && containingBlock->isRenderView()) {
+        const RenderView* view = static_cast<const RenderView*>(containingBlock);
+        if (FrameView* frameView = view->frameView()) {
+            LayoutRect viewportRect = frameView->viewportConstrainedVisibleContentRect();
+            return containingBlock->isHorizontalWritingMode() ? viewportRect.width() : viewportRect.height();
+        }
+    }
+
+    if (containingBlock->isBox()) {
+        RenderFlowThread* flowThread = flowThreadContainingBlock();
+        if (!flowThread)
+            return toRenderBox(containingBlock)->clientLogicalWidth();
+
+        const RenderBlock* cb = toRenderBlock(containingBlock);
+        RenderBoxRegionInfo* boxInfo = 0;
+        if (!region) {
+            if (containingBlock->isRenderFlowThread() && !checkForPerpendicularWritingMode)
+                return toRenderFlowThread(containingBlock)->contentLogicalWidthOfFirstRegion();
+            if (isWritingModeRoot()) {
+                LayoutUnit cbPageOffset = offsetFromLogicalTopOfFirstPage - logicalTop();
+                RenderRegion* cbRegion = cb->regionAtBlockOffset(cbPageOffset);
+                if (cbRegion) {
+                    cbRegion = cb->clampToStartAndEndRegions(cbRegion);
+                    boxInfo = cb->renderBoxRegionInfo(cbRegion, cbPageOffset);
+                }
+            }
+        } else if (region && flowThread->isHorizontalWritingMode() == containingBlock->isHorizontalWritingMode()) {
+            RenderRegion* containingBlockRegion = cb->clampToStartAndEndRegions(region);
+            boxInfo = cb->renderBoxRegionInfo(containingBlockRegion, offsetFromLogicalTopOfFirstPage - logicalTop());
+        }
+        return (boxInfo) ? max<LayoutUnit>(0, cb->clientLogicalWidth() - (cb->logicalWidth() - boxInfo->logicalWidth())) : cb->clientLogicalWidth();
+    }
+
+    ASSERT(containingBlock->isRenderInline() && containingBlock->isInFlowPositioned());
+
+    const RenderInline* flow = toRenderInline(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;
+
+    LayoutUnit fromLeft;
+    LayoutUnit fromRight;
+    if (containingBlock->style()->isLeftToRightDirection()) {
+        fromLeft = first->logicalLeft() + first->borderLogicalLeft();
+        fromRight = last->logicalLeft() + last->logicalWidth() - last->borderLogicalRight();
+    } else {
+        fromRight = first->logicalLeft() + first->logicalWidth() - first->borderLogicalRight();
+        fromLeft = last->logicalLeft() + last->borderLogicalLeft();
+    }
+
+    return max<LayoutUnit>(0, fromRight - fromLeft);
+}
+
+LayoutUnit RenderBox::containingBlockLogicalHeightForPositioned(const RenderBoxModelObject* containingBlock, bool checkForPerpendicularWritingMode) const
+{
+    if (checkForPerpendicularWritingMode && containingBlock->isHorizontalWritingMode() != isHorizontalWritingMode())
+        return containingBlockLogicalWidthForPositioned(containingBlock, 0, 0, false);
+
+    // Use viewport as container for top-level fixed-position elements.
+    if (style()->position() == FixedPosition && containingBlock->isRenderView()) {
+        const RenderView* view = static_cast<const RenderView*>(containingBlock);
+        if (FrameView* frameView = view->frameView()) {
+            LayoutRect viewportRect = frameView->viewportConstrainedVisibleContentRect();
+            return containingBlock->isHorizontalWritingMode() ? viewportRect.height() : viewportRect.width();
+        }
+    }
+
+    if (containingBlock->isBox()) {
+        const RenderBlock* cb = toRenderBlock(containingBlock);
+        LayoutUnit result = cb->clientLogicalHeight();
+        RenderFlowThread* flowThread = flowThreadContainingBlock();
+        if (flowThread && containingBlock->isRenderFlowThread() && flowThread->isHorizontalWritingMode() == containingBlock->isHorizontalWritingMode())
+            return toRenderFlowThread(containingBlock)->contentLogicalHeightOfFirstRegion();
+        return result;
+    }
+        
+    ASSERT(containingBlock->isRenderInline() && containingBlock->isInFlowPositioned());
+
+    const RenderInline* flow = toRenderInline(containingBlock);
+    InlineFlowBox* first = flow->firstLineBox();
+    InlineFlowBox* last = flow->lastLineBox();
+
+    // If the containing block is empty, return a height of 0.
+    if (!first || !last)
+        return 0;
+
+    LayoutUnit heightResult;
+    LayoutRect boundingBox = flow->linesBoundingBox();
+    if (containingBlock->isHorizontalWritingMode())
+        heightResult = boundingBox.height();
+    else
+        heightResult = boundingBox.width();
+    heightResult -= (containingBlock->borderBefore() + containingBlock->borderAfter());
+    return heightResult;
+}
+
+static void computeInlineStaticDistance(Length& logicalLeft, Length& logicalRight, const RenderBox* child, const RenderBoxModelObject* containerBlock, LayoutUnit containerLogicalWidth, RenderRegion* region)
+{
+    if (!logicalLeft.isAuto() || !logicalRight.isAuto())
+        return;
+
+    // FIXME: The static distance computation has not been patched for mixed writing modes yet.
+    if (child->parent()->style()->direction() == LTR) {
+        LayoutUnit staticPosition = child->layer()->staticInlinePosition() - containerBlock->borderLogicalLeft();
+        for (RenderObject* curr = child->parent(); curr && curr != containerBlock; curr = curr->container()) {
+            if (curr->isBox()) {
+                staticPosition += toRenderBox(curr)->logicalLeft();
+                if (region && curr->isRenderBlock()) {
+                    const RenderBlock* cb = toRenderBlock(curr);
+                    region = cb->clampToStartAndEndRegions(region);
+                    RenderBoxRegionInfo* boxInfo = cb->renderBoxRegionInfo(region, region->logicalTopForFlowThreadContent());
+                    if (boxInfo)
+                        staticPosition += boxInfo->logicalLeft();
+                }
+            }
+        }
+        logicalLeft.setValue(Fixed, staticPosition);
+    } else {
+        RenderBox* enclosingBox = child->parent()->enclosingBox();
+        LayoutUnit staticPosition = child->layer()->staticInlinePosition() + containerLogicalWidth + containerBlock->borderLogicalLeft();
+        for (RenderObject* curr = enclosingBox; curr; curr = curr->container()) {
+            if (curr->isBox()) {
+                if (curr != containerBlock)
+                    staticPosition -= toRenderBox(curr)->logicalLeft();
+                if (curr == enclosingBox)
+                    staticPosition -= enclosingBox->logicalWidth();
+                if (region && curr->isRenderBlock()) {
+                     const RenderBlock* cb = toRenderBlock(curr);
+                     region = cb->clampToStartAndEndRegions(region);
+                     RenderBoxRegionInfo* boxInfo = cb->renderBoxRegionInfo(region, region->logicalTopForFlowThreadContent());
+                     if (boxInfo) {
+                        if (curr != containerBlock)
+                            staticPosition -= cb->logicalWidth() - (boxInfo->logicalLeft() + boxInfo->logicalWidth());
+                        if (curr == enclosingBox)
+                            staticPosition += enclosingBox->logicalWidth() - boxInfo->logicalWidth();
+                    }
+                }
+            }
+            if (curr == containerBlock)
+                break;
+        }
+        logicalRight.setValue(Fixed, staticPosition);
+    }
+}
+
+void RenderBox::computePositionedLogicalWidth(LogicalExtentComputedValues& computedValues, RenderRegion* region, LayoutUnit offsetFromLogicalTopOfFirstPage) const
+{
+    if (isReplaced()) {
+        // FIXME: Positioned replaced elements inside a flow thread are not working properly
+        // with variable width regions (see https://bugs.webkit.org/show_bug.cgi?id=69896 ).
+        computePositionedLogicalWidthReplaced(computedValues);
+        return;
+    }
+
+    // QUESTIONS
+    // FIXME 1: 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 2: Can perhaps optimize out cases when max-width/min-width are greater
+    // than or less than the computed 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 computePositionedLogicalWidthUsing()
+    // correspond to text from the spec)
+
+
+    // We don't use containingBlock(), since we may be positioned by an enclosing
+    // relative positioned inline.
+    const RenderBoxModelObject* containerBlock = toRenderBoxModelObject(container());
+    
+    const LayoutUnit containerLogicalWidth = containingBlockLogicalWidthForPositioned(containerBlock, region, offsetFromLogicalTopOfFirstPage);
+
+    // Use the container block's direction except when calculating the static distance
+    // This conforms with the reference results for abspos-replaced-width-margin-000.htm
+    // of the CSS 2.1 test suite
+    TextDirection containerDirection = containerBlock->style()->direction();
+
+    bool isHorizontal = isHorizontalWritingMode();
+    const LayoutUnit bordersPlusPadding = borderAndPaddingLogicalWidth();
+    const Length marginLogicalLeft = isHorizontal ? style()->marginLeft() : style()->marginTop();
+    const Length marginLogicalRight = isHorizontal ? style()->marginRight() : style()->marginBottom();
+
+    Length logicalLeftLength = style()->logicalLeft();
+    Length logicalRightLength = style()->logicalRight();
+
+    /*---------------------------------------------------------------------------*\
+     * 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 1
+    // Calculate the static distance if needed.
+    computeInlineStaticDistance(logicalLeftLength, logicalRightLength, this, containerBlock, containerLogicalWidth, region);
+    
+    // Calculate constraint equation values for 'width' case.
+    computePositionedLogicalWidthUsing(style()->logicalWidth(), containerBlock, containerDirection,
+                                       containerLogicalWidth, bordersPlusPadding,
+                                       logicalLeftLength, logicalRightLength, marginLogicalLeft, marginLogicalRight,
+                                       computedValues);
+
+    // Calculate constraint equation values for 'max-width' case.
+    if (!style()->logicalMaxWidth().isUndefined()) {
+        LogicalExtentComputedValues maxValues;
+
+        computePositionedLogicalWidthUsing(style()->logicalMaxWidth(), containerBlock, containerDirection,
+                                           containerLogicalWidth, bordersPlusPadding,
+                                           logicalLeftLength, logicalRightLength, marginLogicalLeft, marginLogicalRight,
+                                           maxValues);
+
+        if (computedValues.m_extent > maxValues.m_extent) {
+            computedValues.m_extent = maxValues.m_extent;
+            computedValues.m_position = maxValues.m_position;
+            computedValues.m_margins.m_start = maxValues.m_margins.m_start;
+            computedValues.m_margins.m_end = maxValues.m_margins.m_end;
+        }
+    }
+
+    // Calculate constraint equation values for 'min-width' case.
+    if (!style()->logicalMinWidth().isZero() || style()->logicalMinWidth().isIntrinsic()) {
+        LogicalExtentComputedValues minValues;
+
+        computePositionedLogicalWidthUsing(style()->logicalMinWidth(), containerBlock, containerDirection,
+                                           containerLogicalWidth, bordersPlusPadding,
+                                           logicalLeftLength, logicalRightLength, marginLogicalLeft, marginLogicalRight,
+                                           minValues);
+
+        if (computedValues.m_extent < minValues.m_extent) {
+            computedValues.m_extent = minValues.m_extent;
+            computedValues.m_position = minValues.m_position;
+            computedValues.m_margins.m_start = minValues.m_margins.m_start;
+            computedValues.m_margins.m_end = minValues.m_margins.m_end;
+        }
+    }
+
+    computedValues.m_extent += bordersPlusPadding;
+    
+    // Adjust logicalLeft if we need to for the flipped version of our writing mode in regions.
+    // FIXME: Add support for other types of objects as containerBlock, not only RenderBlock.
+    RenderFlowThread* flowThread = flowThreadContainingBlock();
+    if (flowThread && !region && isWritingModeRoot() && isHorizontalWritingMode() == containerBlock->isHorizontalWritingMode() && containerBlock->isRenderBlock()) {
+        ASSERT(containerBlock->canHaveBoxInfoInRegion());
+        LayoutUnit logicalLeftPos = computedValues.m_position;
+        const RenderBlock* cb = toRenderBlock(containerBlock);
+        LayoutUnit cbPageOffset = offsetFromLogicalTopOfFirstPage - logicalTop();
+        RenderRegion* cbRegion = cb->regionAtBlockOffset(cbPageOffset);
+        if (cbRegion) {
+            cbRegion = cb->clampToStartAndEndRegions(cbRegion);
+            RenderBoxRegionInfo* boxInfo = cb->renderBoxRegionInfo(cbRegion, cbPageOffset);
+            if (boxInfo) {
+                logicalLeftPos += boxInfo->logicalLeft();
+                computedValues.m_position = logicalLeftPos;
+            }
+        }
+    }
+}
+
+static void computeLogicalLeftPositionedOffset(LayoutUnit& logicalLeftPos, const RenderBox* child, LayoutUnit logicalWidthValue, const RenderBoxModelObject* containerBlock, LayoutUnit containerLogicalWidth)
+{
+    // Deal with differing writing modes here.  Our offset needs to be in the containing block's coordinate space. If the containing block is flipped
+    // along this axis, then we need to flip the coordinate.  This can only happen if the containing block is both a flipped mode and perpendicular to us.
+    if (containerBlock->isHorizontalWritingMode() != child->isHorizontalWritingMode() && containerBlock->style()->isFlippedBlocksWritingMode()) {
+        logicalLeftPos = containerLogicalWidth - logicalWidthValue - logicalLeftPos;
+        logicalLeftPos += (child->isHorizontalWritingMode() ? containerBlock->borderRight() : containerBlock->borderBottom());
+    } else
+        logicalLeftPos += (child->isHorizontalWritingMode() ? containerBlock->borderLeft() : containerBlock->borderTop());
+}
+
+void RenderBox::computePositionedLogicalWidthUsing(Length logicalWidth, const RenderBoxModelObject* containerBlock, TextDirection containerDirection,
+                                                   LayoutUnit containerLogicalWidth, LayoutUnit bordersPlusPadding,
+                                                   Length logicalLeft, Length logicalRight, Length marginLogicalLeft, Length marginLogicalRight,
+                                                   LogicalExtentComputedValues& computedValues) const
+{
+    if (logicalWidth.isIntrinsic())
+        logicalWidth = Length(computeIntrinsicLogicalWidthUsing(logicalWidth, containerLogicalWidth, bordersPlusPadding) - bordersPlusPadding, Fixed);
+
+    // 'left' and 'right' cannot both be 'auto' because one would of been
+    // converted to the static position already
+    ASSERT(!(logicalLeft.isAuto() && logicalRight.isAuto()));
+
+    LayoutUnit logicalLeftValue = 0;
+
+    const LayoutUnit containerRelativeLogicalWidth = containingBlockLogicalWidthForPositioned(containerBlock, 0, 0, false);
+
+    bool logicalWidthIsAuto = logicalWidth.isIntrinsicOrAuto();
+    bool logicalLeftIsAuto = logicalLeft.isAuto();
+    bool logicalRightIsAuto = logicalRight.isAuto();
+    RenderView* renderView = view();
+    LayoutUnit& marginLogicalLeftValue = style()->isLeftToRightDirection() ? computedValues.m_margins.m_start : computedValues.m_margins.m_end;
+    LayoutUnit& marginLogicalRightValue = style()->isLeftToRightDirection() ? computedValues.m_margins.m_end : computedValues.m_margins.m_start;
+
+    if (!logicalLeftIsAuto && !logicalWidthIsAuto && !logicalRightIsAuto) {
+        /*-----------------------------------------------------------------------*\
+         * 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.
+
+        logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
+        computedValues.m_extent = adjustContentBoxLogicalWidthForBoxSizing(valueForLength(logicalWidth, containerLogicalWidth, renderView));
+
+        const LayoutUnit availableSpace = containerLogicalWidth - (logicalLeftValue + computedValues.m_extent + valueForLength(logicalRight, containerLogicalWidth, renderView) + bordersPlusPadding);
+
+        // Margins are now the only unknown
+        if (marginLogicalLeft.isAuto() && marginLogicalRight.isAuto()) {
+            // Both margins auto, solve for equality
+            if (availableSpace >= 0) {
+                marginLogicalLeftValue = availableSpace / 2; // split the difference
+                marginLogicalRightValue = availableSpace - marginLogicalLeftValue; // account for odd valued differences
+            } else {
+                // Use the containing block's direction rather than the parent block's
+                // per CSS 2.1 reference test abspos-non-replaced-width-margin-000.
+                if (containerDirection == LTR) {
+                    marginLogicalLeftValue = 0;
+                    marginLogicalRightValue = availableSpace; // will be negative
+                } else {
+                    marginLogicalLeftValue = availableSpace; // will be negative
+                    marginLogicalRightValue = 0;
+                }
+            }
+        } else if (marginLogicalLeft.isAuto()) {
+            // Solve for left margin
+            marginLogicalRightValue = valueForLength(marginLogicalRight, containerRelativeLogicalWidth, renderView);
+            marginLogicalLeftValue = availableSpace - marginLogicalRightValue;
+        } else if (marginLogicalRight.isAuto()) {
+            // Solve for right margin
+            marginLogicalLeftValue = valueForLength(marginLogicalLeft, containerRelativeLogicalWidth, renderView);
+            marginLogicalRightValue = availableSpace - marginLogicalLeftValue;
+        } else {
+            // Over-constrained, solve for left if direction is RTL
+            marginLogicalLeftValue = valueForLength(marginLogicalLeft, containerRelativeLogicalWidth, renderView);
+            marginLogicalRightValue = valueForLength(marginLogicalRight, containerRelativeLogicalWidth, renderView);
+
+            // Use the containing block's direction rather than the parent block's
+            // per CSS 2.1 reference test abspos-non-replaced-width-margin-000.
+            if (containerDirection == RTL)
+                logicalLeftValue = (availableSpace + logicalLeftValue) - marginLogicalLeftValue - marginLogicalRightValue;
+        }
+    } 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.
+        marginLogicalLeftValue = minimumValueForLength(marginLogicalLeft, containerRelativeLogicalWidth, renderView);
+        marginLogicalRightValue = minimumValueForLength(marginLogicalRight, containerRelativeLogicalWidth, renderView);
+
+        const LayoutUnit availableSpace = containerLogicalWidth - (marginLogicalLeftValue + marginLogicalRightValue + bordersPlusPadding);
+
+        // FIXME: Is there a faster way to find the correct case?
+        // Use rule/case that applies.
+        if (logicalLeftIsAuto && logicalWidthIsAuto && !logicalRightIsAuto) {
+            // RULE 1: (use shrink-to-fit for width, and solve of left)
+            LayoutUnit logicalRightValue = valueForLength(logicalRight, containerLogicalWidth, renderView);
+
+            // FIXME: would it be better to have shrink-to-fit in one step?
+            LayoutUnit preferredWidth = maxPreferredLogicalWidth() - bordersPlusPadding;
+            LayoutUnit preferredMinWidth = minPreferredLogicalWidth() - bordersPlusPadding;
+            LayoutUnit availableWidth = availableSpace - logicalRightValue;
+            computedValues.m_extent = min(max(preferredMinWidth, availableWidth), preferredWidth);
+            logicalLeftValue = availableSpace - (computedValues.m_extent + logicalRightValue);
+        } else if (!logicalLeftIsAuto && logicalWidthIsAuto && logicalRightIsAuto) {
+            // RULE 3: (use shrink-to-fit for width, and no need solve of right)
+            logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
+
+            // FIXME: would it be better to have shrink-to-fit in one step?
+            LayoutUnit preferredWidth = maxPreferredLogicalWidth() - bordersPlusPadding;
+            LayoutUnit preferredMinWidth = minPreferredLogicalWidth() - bordersPlusPadding;
+            LayoutUnit availableWidth = availableSpace - logicalLeftValue;
+            computedValues.m_extent = min(max(preferredMinWidth, availableWidth), preferredWidth);
+        } else if (logicalLeftIsAuto && !logicalWidthIsAuto && !logicalRightIsAuto) {
+            // RULE 4: (solve for left)
+            computedValues.m_extent = adjustContentBoxLogicalWidthForBoxSizing(valueForLength(logicalWidth, containerLogicalWidth, renderView));
+            logicalLeftValue = availableSpace - (computedValues.m_extent + valueForLength(logicalRight, containerLogicalWidth, renderView));
+        } else if (!logicalLeftIsAuto && logicalWidthIsAuto && !logicalRightIsAuto) {
+            // RULE 5: (solve for width)
+            logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
+            computedValues.m_extent = availableSpace - (logicalLeftValue + valueForLength(logicalRight, containerLogicalWidth, renderView));
+        } else if (!logicalLeftIsAuto && !logicalWidthIsAuto && logicalRightIsAuto) {
+            // RULE 6: (no need solve for right)
+            logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
+            computedValues.m_extent = adjustContentBoxLogicalWidthForBoxSizing(valueForLength(logicalWidth, containerLogicalWidth, renderView));
+        }
+    }
+
+    // Use computed values to calculate the horizontal position.
+
+    // FIXME: This hack is needed to calculate the  logical left position for a 'rtl' relatively
+    // positioned, inline because right now, it is using the logical left position
+    // 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->isRenderInline() && !containerBlock->style()->isLeftToRightDirection()) {
+        const RenderInline* flow = toRenderInline(containerBlock);
+        InlineFlowBox* firstLine = flow->firstLineBox();
+        InlineFlowBox* lastLine = flow->lastLineBox();
+        if (firstLine && lastLine && firstLine != lastLine) {
+            computedValues.m_position = logicalLeftValue + marginLogicalLeftValue + lastLine->borderLogicalLeft() + (lastLine->logicalLeft() - firstLine->logicalLeft());
+            return;
+        }
+    }
+
+    computedValues.m_position = logicalLeftValue + marginLogicalLeftValue;
+    computeLogicalLeftPositionedOffset(computedValues.m_position, this, computedValues.m_extent, containerBlock, containerLogicalWidth);
+}
+
+static void computeBlockStaticDistance(Length& logicalTop, Length& logicalBottom, const RenderBox* child, const RenderBoxModelObject* containerBlock)
+{
+    if (!logicalTop.isAuto() || !logicalBottom.isAuto())
+        return;
+    
+    // FIXME: The static distance computation has not been patched for mixed writing modes.
+    LayoutUnit staticLogicalTop = child->layer()->staticBlockPosition() - containerBlock->borderBefore();
+    for (RenderObject* curr = child->parent(); curr && curr != containerBlock; curr = curr->container()) {
+        if (curr->isBox() && !curr->isTableRow())
+            staticLogicalTop += toRenderBox(curr)->logicalTop();
+    }
+    logicalTop.setValue(Fixed, staticLogicalTop);
+}
+
+void RenderBox::computePositionedLogicalHeight(LogicalExtentComputedValues& computedValues) const
+{
+    if (isReplaced()) {
+        computePositionedLogicalHeightReplaced(computedValues);
+        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 computePositionedLogicalHeightUsing()
+    // correspond to text from the spec)
+
+
+    // We don't use containingBlock(), since we may be positioned by an enclosing relpositioned inline.
+    const RenderBoxModelObject* containerBlock = toRenderBoxModelObject(container());
+
+    const LayoutUnit containerLogicalHeight = containingBlockLogicalHeightForPositioned(containerBlock);
+
+    RenderStyle* styleToUse = style();
+    const LayoutUnit bordersPlusPadding = borderAndPaddingLogicalHeight();
+    const Length marginBefore = styleToUse->marginBefore();
+    const Length marginAfter = styleToUse->marginAfter();
+    Length logicalTopLength = styleToUse->logicalTop();
+    Length logicalBottomLength = styleToUse->logicalBottom();
+
+    /*---------------------------------------------------------------------------*\
+     * 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 1
+    // Calculate the static distance if needed.
+    computeBlockStaticDistance(logicalTopLength, logicalBottomLength, this, containerBlock);
+
+    // Calculate constraint equation values for 'height' case.
+    LayoutUnit logicalHeight = computedValues.m_extent;
+    computePositionedLogicalHeightUsing(styleToUse->logicalHeight(), containerBlock, containerLogicalHeight, bordersPlusPadding, logicalHeight,
+                                        logicalTopLength, logicalBottomLength, marginBefore, marginAfter,
+                                        computedValues);
+
+    // Avoid doing any work in the common case (where the values of min-height and max-height are their defaults).
+    // see FIXME 2
+
+    // Calculate constraint equation values for 'max-height' case.
+    if (!styleToUse->logicalMaxHeight().isUndefined()) {
+        LogicalExtentComputedValues maxValues;
+
+        computePositionedLogicalHeightUsing(styleToUse->logicalMaxHeight(), containerBlock, containerLogicalHeight, bordersPlusPadding, logicalHeight,
+                                            logicalTopLength, logicalBottomLength, marginBefore, marginAfter,
+                                            maxValues);
+
+        if (computedValues.m_extent > maxValues.m_extent) {
+            computedValues.m_extent = maxValues.m_extent;
+            computedValues.m_position = maxValues.m_position;
+            computedValues.m_margins.m_before = maxValues.m_margins.m_before;
+            computedValues.m_margins.m_after = maxValues.m_margins.m_after;
+        }
+    }
+
+    // Calculate constraint equation values for 'min-height' case.
+    if (!styleToUse->logicalMinHeight().isZero() || styleToUse->logicalMinHeight().isIntrinsic()) {
+        LogicalExtentComputedValues minValues;
+
+        computePositionedLogicalHeightUsing(styleToUse->logicalMinHeight(), containerBlock, containerLogicalHeight, bordersPlusPadding, logicalHeight,
+                                            logicalTopLength, logicalBottomLength, marginBefore, marginAfter,
+                                            minValues);
+
+        if (computedValues.m_extent < minValues.m_extent) {
+            computedValues.m_extent = minValues.m_extent;
+            computedValues.m_position = minValues.m_position;
+            computedValues.m_margins.m_before = minValues.m_margins.m_before;
+            computedValues.m_margins.m_after = minValues.m_margins.m_after;
+        }
+    }
+
+    // Set final height value.
+    computedValues.m_extent += bordersPlusPadding;
+    
+    // Adjust logicalTop if we need to for perpendicular writing modes in regions.
+    // FIXME: Add support for other types of objects as containerBlock, not only RenderBlock.
+    RenderFlowThread* flowThread = flowThreadContainingBlock();
+    if (flowThread && isHorizontalWritingMode() != containerBlock->isHorizontalWritingMode() && containerBlock->isRenderBlock()) {
+        ASSERT(containerBlock->canHaveBoxInfoInRegion());
+        LayoutUnit logicalTopPos = computedValues.m_position;
+        const RenderBlock* cb = toRenderBlock(containerBlock);
+        LayoutUnit cbPageOffset = cb->offsetFromLogicalTopOfFirstPage() - logicalLeft();
+        RenderRegion* cbRegion = cb->regionAtBlockOffset(cbPageOffset);
+        if (cbRegion) {
+            cbRegion = cb->clampToStartAndEndRegions(cbRegion);
+            RenderBoxRegionInfo* boxInfo = cb->renderBoxRegionInfo(cbRegion, cbPageOffset);
+            if (boxInfo) {
+                logicalTopPos += boxInfo->logicalLeft();
+                computedValues.m_position = logicalTopPos;
+            }
+        }
+    }
+}
+
+static void computeLogicalTopPositionedOffset(LayoutUnit& logicalTopPos, const RenderBox* child, LayoutUnit logicalHeightValue, const RenderBoxModelObject* containerBlock, LayoutUnit containerLogicalHeight)
+{
+    // Deal with differing writing modes here.  Our offset needs to be in the containing block's coordinate space. If the containing block is flipped
+    // along this axis, then we need to flip the coordinate.  This can only happen if the containing block is both a flipped mode and perpendicular to us.
+    if ((child->style()->isFlippedBlocksWritingMode() && child->isHorizontalWritingMode() != containerBlock->isHorizontalWritingMode())
+        || (child->style()->isFlippedBlocksWritingMode() != containerBlock->style()->isFlippedBlocksWritingMode() && child->isHorizontalWritingMode() == containerBlock->isHorizontalWritingMode()))
+        logicalTopPos = containerLogicalHeight - logicalHeightValue - logicalTopPos;
+
+    // Our offset is from the logical bottom edge in a flipped environment, e.g., right for vertical-rl and bottom for horizontal-bt.
+    if (containerBlock->style()->isFlippedBlocksWritingMode() && child->isHorizontalWritingMode() == containerBlock->isHorizontalWritingMode()) {
+        if (child->isHorizontalWritingMode())
+            logicalTopPos += containerBlock->borderBottom();
+        else
+            logicalTopPos += containerBlock->borderRight();
+    } else {
+        if (child->isHorizontalWritingMode())
+            logicalTopPos += containerBlock->borderTop();
+        else
+            logicalTopPos += containerBlock->borderLeft();
+    }
+}
+
+void RenderBox::computePositionedLogicalHeightUsing(Length logicalHeightLength, const RenderBoxModelObject* containerBlock,
+                                                    LayoutUnit containerLogicalHeight, LayoutUnit bordersPlusPadding, LayoutUnit logicalHeight,
+                                                    Length logicalTop, Length logicalBottom, Length marginBefore, Length marginAfter,
+                                                    LogicalExtentComputedValues& computedValues) const
+{
+    // 'top' and 'bottom' cannot both be 'auto' because 'top would of been
+    // converted to the static position in computePositionedLogicalHeight()
+    ASSERT(!(logicalTop.isAuto() && logicalBottom.isAuto()));
+
+    LayoutUnit logicalHeightValue;
+    LayoutUnit contentLogicalHeight = logicalHeight - bordersPlusPadding;
+
+    const LayoutUnit containerRelativeLogicalWidth = containingBlockLogicalWidthForPositioned(containerBlock, 0, 0, false);
+
+    LayoutUnit logicalTopValue = 0;
+
+    bool logicalHeightIsAuto = logicalHeightLength.isAuto();
+    bool logicalTopIsAuto = logicalTop.isAuto();
+    bool logicalBottomIsAuto = logicalBottom.isAuto();
+    RenderView* renderView = view();
+
+    // Height is never unsolved for tables.
+    if (isTable()) {
+        logicalHeightLength.setValue(Fixed, contentLogicalHeight);
+        logicalHeightIsAuto = false;
+    }
+
+    LayoutUnit resolvedLogicalHeight;
+    if (logicalHeightLength.isIntrinsic())
+        resolvedLogicalHeight = computeIntrinsicLogicalContentHeightUsing(logicalHeightLength, contentLogicalHeight, bordersPlusPadding);
+    else
+        resolvedLogicalHeight = adjustContentBoxLogicalHeightForBoxSizing(valueForLength(logicalHeightLength, containerLogicalHeight, renderView));
+
+    if (!logicalTopIsAuto && !logicalHeightIsAuto && !logicalBottomIsAuto) {
+        /*-----------------------------------------------------------------------*\
+         * 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.
+
+        logicalHeightValue = resolvedLogicalHeight;
+        logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
+
+        const LayoutUnit availableSpace = containerLogicalHeight - (logicalTopValue + logicalHeightValue + valueForLength(logicalBottom, containerLogicalHeight, renderView) + bordersPlusPadding);
+
+        // Margins are now the only unknown
+        if (marginBefore.isAuto() && marginAfter.isAuto()) {
+            // Both margins auto, solve for equality
+            // NOTE: This may result in negative values.
+            computedValues.m_margins.m_before = availableSpace / 2; // split the difference
+            computedValues.m_margins.m_after = availableSpace - computedValues.m_margins.m_before; // account for odd valued differences
+        } else if (marginBefore.isAuto()) {
+            // Solve for top margin
+            computedValues.m_margins.m_after = valueForLength(marginAfter, containerRelativeLogicalWidth, renderView);
+            computedValues.m_margins.m_before = availableSpace - computedValues.m_margins.m_after;
+        } else if (marginAfter.isAuto()) {
+            // Solve for bottom margin
+            computedValues.m_margins.m_before = valueForLength(marginBefore, containerRelativeLogicalWidth, renderView);
+            computedValues.m_margins.m_after = availableSpace - computedValues.m_margins.m_before;
+        } else {
+            // Over-constrained, (no need solve for bottom)
+            computedValues.m_margins.m_before = valueForLength(marginBefore, containerRelativeLogicalWidth, renderView);
+            computedValues.m_margins.m_after = valueForLength(marginAfter, containerRelativeLogicalWidth, renderView);
+        }
+    } 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.
+        computedValues.m_margins.m_before = minimumValueForLength(marginBefore, containerRelativeLogicalWidth, renderView);
+        computedValues.m_margins.m_after = minimumValueForLength(marginAfter, containerRelativeLogicalWidth, renderView);
+
+        const LayoutUnit availableSpace = containerLogicalHeight - (computedValues.m_margins.m_before + computedValues.m_margins.m_after + bordersPlusPadding);
+
+        // Use rule/case that applies.
+        if (logicalTopIsAuto && logicalHeightIsAuto && !logicalBottomIsAuto) {
+            // RULE 1: (height is content based, solve of top)
+            logicalHeightValue = contentLogicalHeight;
+            logicalTopValue = availableSpace - (logicalHeightValue + valueForLength(logicalBottom, containerLogicalHeight, renderView));
+        } else if (!logicalTopIsAuto && logicalHeightIsAuto && logicalBottomIsAuto) {
+            // RULE 3: (height is content based, no need solve of bottom)
+            logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
+            logicalHeightValue = contentLogicalHeight;
+        } else if (logicalTopIsAuto && !logicalHeightIsAuto && !logicalBottomIsAuto) {
+            // RULE 4: (solve of top)
+            logicalHeightValue = resolvedLogicalHeight;
+            logicalTopValue = availableSpace - (logicalHeightValue + valueForLength(logicalBottom, containerLogicalHeight, renderView));
+        } else if (!logicalTopIsAuto && logicalHeightIsAuto && !logicalBottomIsAuto) {
+            // RULE 5: (solve of height)
+            logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
+            logicalHeightValue = max<LayoutUnit>(0, availableSpace - (logicalTopValue + valueForLength(logicalBottom, containerLogicalHeight, renderView)));
+        } else if (!logicalTopIsAuto && !logicalHeightIsAuto && logicalBottomIsAuto) {
+            // RULE 6: (no need solve of bottom)
+            logicalHeightValue = resolvedLogicalHeight;
+            logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
+        }
+    }
+    computedValues.m_extent = logicalHeightValue;
+
+    // Use computed values to calculate the vertical position.
+    computedValues.m_position = logicalTopValue + computedValues.m_margins.m_before;
+    computeLogicalTopPositionedOffset(computedValues.m_position, this, logicalHeightValue, containerBlock, containerLogicalHeight);
+}
+
+void RenderBox::computePositionedLogicalWidthReplaced(LogicalExtentComputedValues& computedValues) const
+{
+    // The following is based off of the W3C Working Draft from April 11, 2006 of
+    // CSS 2.1: Section 10.3.8 "Absolutely 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 RenderBoxModelObject* containerBlock = toRenderBoxModelObject(container());
+
+    const LayoutUnit containerLogicalWidth = containingBlockLogicalWidthForPositioned(containerBlock);
+    const LayoutUnit containerRelativeLogicalWidth = containingBlockLogicalWidthForPositioned(containerBlock, 0, 0, false);
+
+    // To match WinIE, in quirks mode use the parent's 'direction' property
+    // instead of the the container block's.
+    TextDirection containerDirection = containerBlock->style()->direction();
+
+    // Variables to solve.
+    bool isHorizontal = isHorizontalWritingMode();
+    Length logicalLeft = style()->logicalLeft();
+    Length logicalRight = style()->logicalRight();
+    Length marginLogicalLeft = isHorizontal ? style()->marginLeft() : style()->marginTop();
+    Length marginLogicalRight = isHorizontal ? style()->marginRight() : style()->marginBottom();
+    LayoutUnit& marginLogicalLeftAlias = style()->isLeftToRightDirection() ? computedValues.m_margins.m_start : computedValues.m_margins.m_end;
+    LayoutUnit& marginLogicalRightAlias = style()->isLeftToRightDirection() ? computedValues.m_margins.m_end : computedValues.m_margins.m_start;
+
+    /*-----------------------------------------------------------------------*\
+     * 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 computeReplacedWidth().  This means that the steps to produce
+    // correct max/min in the non-replaced version, are not necessary.
+    computedValues.m_extent = computeReplacedLogicalWidth() + borderAndPaddingLogicalWidth();
+
+    const LayoutUnit availableSpace = containerLogicalWidth - computedValues.m_extent;
+
+    /*-----------------------------------------------------------------------*\
+     * 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 1
+    computeInlineStaticDistance(logicalLeft, logicalRight, this, containerBlock, containerLogicalWidth, 0); // FIXME: Pass the region.
+
+    /*-----------------------------------------------------------------------*\
+     * 3. If 'left' or 'right' are 'auto', replace any 'auto' on 'margin-left'
+     *    or 'margin-right' with '0'.
+    \*-----------------------------------------------------------------------*/
+    if (logicalLeft.isAuto() || logicalRight.isAuto()) {
+        if (marginLogicalLeft.isAuto())
+            marginLogicalLeft.setValue(Fixed, 0);
+        if (marginLogicalRight.isAuto())
+            marginLogicalRight.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').
+    \*-----------------------------------------------------------------------*/
+    LayoutUnit logicalLeftValue = 0;
+    LayoutUnit logicalRightValue = 0;
+    RenderView* renderView = view();
+
+    if (marginLogicalLeft.isAuto() && marginLogicalRight.isAuto()) {
+        // 'left' and 'right' cannot be 'auto' due to step 3
+        ASSERT(!(logicalLeft.isAuto() && logicalRight.isAuto()));
+
+        logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
+        logicalRightValue = valueForLength(logicalRight, containerLogicalWidth, renderView);
+
+        LayoutUnit difference = availableSpace - (logicalLeftValue + logicalRightValue);
+        if (difference > 0) {
+            marginLogicalLeftAlias = difference / 2; // split the difference
+            marginLogicalRightAlias = difference - marginLogicalLeftAlias; // account for odd valued differences
+        } else {
+            // Use the containing block's direction rather than the parent block's
+            // per CSS 2.1 reference test abspos-replaced-width-margin-000.
+            if (containerDirection == LTR) {
+                marginLogicalLeftAlias = 0;
+                marginLogicalRightAlias = difference; // will be negative
+            } else {
+                marginLogicalLeftAlias = difference; // will be negative
+                marginLogicalRightAlias = 0;
+            }
+        }
+
+    /*-----------------------------------------------------------------------*\
+     * 5. If at this point there is an 'auto' left, solve the equation for
+     *    that value.
+    \*-----------------------------------------------------------------------*/
+    } else if (logicalLeft.isAuto()) {
+        marginLogicalLeftAlias = valueForLength(marginLogicalLeft, containerRelativeLogicalWidth, renderView);
+        marginLogicalRightAlias = valueForLength(marginLogicalRight, containerRelativeLogicalWidth, renderView);
+        logicalRightValue = valueForLength(logicalRight, containerLogicalWidth, renderView);
+
+        // Solve for 'left'
+        logicalLeftValue = availableSpace - (logicalRightValue + marginLogicalLeftAlias + marginLogicalRightAlias);
+    } else if (logicalRight.isAuto()) {
+        marginLogicalLeftAlias = valueForLength(marginLogicalLeft, containerRelativeLogicalWidth, renderView);
+        marginLogicalRightAlias = valueForLength(marginLogicalRight, containerRelativeLogicalWidth, renderView);
+        logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
+
+        // Solve for 'right'
+        logicalRightValue = availableSpace - (logicalLeftValue + marginLogicalLeftAlias + marginLogicalRightAlias);
+    } else if (marginLogicalLeft.isAuto()) {
+        marginLogicalRightAlias = valueForLength(marginLogicalRight, containerRelativeLogicalWidth, renderView);
+        logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
+        logicalRightValue = valueForLength(logicalRight, containerLogicalWidth, renderView);
+
+        // Solve for 'margin-left'
+        marginLogicalLeftAlias = availableSpace - (logicalLeftValue + logicalRightValue + marginLogicalRightAlias);
+    } else if (marginLogicalRight.isAuto()) {
+        marginLogicalLeftAlias = valueForLength(marginLogicalLeft, containerRelativeLogicalWidth, renderView);
+        logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
+        logicalRightValue = valueForLength(logicalRight, containerLogicalWidth, renderView);
+
+        // Solve for 'margin-right'
+        marginLogicalRightAlias = availableSpace - (logicalLeftValue + logicalRightValue + marginLogicalLeftAlias);
+    } else {
+        // Nothing is 'auto', just calculate the values.
+        marginLogicalLeftAlias = valueForLength(marginLogicalLeft, containerRelativeLogicalWidth, renderView);
+        marginLogicalRightAlias = valueForLength(marginLogicalRight, containerRelativeLogicalWidth, renderView);
+        logicalRightValue = valueForLength(logicalRight, containerLogicalWidth, renderView);
+        logicalLeftValue = valueForLength(logicalLeft, containerLogicalWidth, renderView);
+        // If the containing block is right-to-left, then push the left position as far to the right as possible
+        if (containerDirection == RTL) {
+            int totalLogicalWidth = computedValues.m_extent + logicalLeftValue + logicalRightValue +  marginLogicalLeftAlias + marginLogicalRightAlias;
+            logicalLeftValue = containerLogicalWidth - (totalLogicalWidth - logicalLeftValue);
+        }
+    }
+
+    /*-----------------------------------------------------------------------*\
+     * 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: Constraints imposed by the width of the containing block and its content have already been accounted for above.
+
+    // FIXME: Deal with differing writing modes here.  Our offset needs to be in the containing block's coordinate space, so that
+    // can make the result here rather complicated to compute.
+
+    // Use computed values to calculate the horizontal position.
+
+    // FIXME: This hack is needed to calculate the logical left position for a 'rtl' relatively
+    // positioned, inline containing block because right now, it is using the logical left position
+    // 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->isRenderInline() && !containerBlock->style()->isLeftToRightDirection()) {
+        const RenderInline* flow = toRenderInline(containerBlock);
+        InlineFlowBox* firstLine = flow->firstLineBox();
+        InlineFlowBox* lastLine = flow->lastLineBox();
+        if (firstLine && lastLine && firstLine != lastLine) {
+            computedValues.m_position = logicalLeftValue + marginLogicalLeftAlias + lastLine->borderLogicalLeft() + (lastLine->logicalLeft() - firstLine->logicalLeft());
+            return;
+        }
+    }
+
+    LayoutUnit logicalLeftPos = logicalLeftValue + marginLogicalLeftAlias;
+    computeLogicalLeftPositionedOffset(logicalLeftPos, this, computedValues.m_extent, containerBlock, containerLogicalWidth);
+    computedValues.m_position = logicalLeftPos;
+}
+
+void RenderBox::computePositionedLogicalHeightReplaced(LogicalExtentComputedValues& computedValues) const
+{
+    // The following is based off of the W3C Working Draft from April 11, 2006 of
+    // CSS 2.1: Section 10.6.5 "Absolutely 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 RenderBoxModelObject* containerBlock = toRenderBoxModelObject(container());
+
+    const LayoutUnit containerLogicalHeight = containingBlockLogicalHeightForPositioned(containerBlock);
+    const LayoutUnit containerRelativeLogicalWidth = containingBlockLogicalWidthForPositioned(containerBlock, 0, 0, false);
+
+    // Variables to solve.
+    Length marginBefore = style()->marginBefore();
+    Length marginAfter = style()->marginAfter();
+    LayoutUnit& marginBeforeAlias = computedValues.m_margins.m_before;
+    LayoutUnit& marginAfterAlias = computedValues.m_margins.m_after;
+
+    Length logicalTop = style()->logicalTop();
+    Length logicalBottom = style()->logicalBottom();
+    RenderView* renderView = view();
+
+    /*-----------------------------------------------------------------------*\
+     * 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 computeReplacedHeight().  This means that the steps to produce
+    // correct max/min in the non-replaced version, are not necessary.
+    computedValues.m_extent = computeReplacedLogicalHeight() + borderAndPaddingLogicalHeight();
+    const LayoutUnit availableSpace = containerLogicalHeight - computedValues.m_extent;
+
+    /*-----------------------------------------------------------------------*\
+     * 2. If both 'top' and 'bottom' have the value 'auto', replace 'top'
+     *    with the element's static position.
+    \*-----------------------------------------------------------------------*/
+    // see FIXME 1
+    computeBlockStaticDistance(logicalTop, logicalBottom, this, containerBlock);
+
+    /*-----------------------------------------------------------------------*\
+     * 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 (logicalTop.isAuto() || logicalBottom.isAuto()) {
+        if (marginBefore.isAuto())
+            marginBefore.setValue(Fixed, 0);
+        if (marginAfter.isAuto())
+            marginAfter.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.
+    \*-----------------------------------------------------------------------*/
+    LayoutUnit logicalTopValue = 0;
+    LayoutUnit logicalBottomValue = 0;
+
+    if (marginBefore.isAuto() && marginAfter.isAuto()) {
+        // 'top' and 'bottom' cannot be 'auto' due to step 2 and 3 combined.
+        ASSERT(!(logicalTop.isAuto() || logicalBottom.isAuto()));
+
+        logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
+        logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight, renderView);
+
+        LayoutUnit difference = availableSpace - (logicalTopValue + logicalBottomValue);
+        // NOTE: This may result in negative values.
+        marginBeforeAlias =  difference / 2; // split the difference
+        marginAfterAlias = difference - marginBeforeAlias; // account for odd valued differences
+
+    /*-----------------------------------------------------------------------*\
+     * 5. If at this point there is only one 'auto' left, solve the equation
+     *    for that value.
+    \*-----------------------------------------------------------------------*/
+    } else if (logicalTop.isAuto()) {
+        marginBeforeAlias = valueForLength(marginBefore, containerRelativeLogicalWidth, renderView);
+        marginAfterAlias = valueForLength(marginAfter, containerRelativeLogicalWidth, renderView);
+        logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight, renderView);
+
+        // Solve for 'top'
+        logicalTopValue = availableSpace - (logicalBottomValue + marginBeforeAlias + marginAfterAlias);
+    } else if (logicalBottom.isAuto()) {
+        marginBeforeAlias = valueForLength(marginBefore, containerRelativeLogicalWidth, renderView);
+        marginAfterAlias = valueForLength(marginAfter, containerRelativeLogicalWidth, renderView);
+        logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
+
+        // Solve for 'bottom'
+        // NOTE: It is not necessary to solve for 'bottom' because we don't ever
+        // use the value.
+    } else if (marginBefore.isAuto()) {
+        marginAfterAlias = valueForLength(marginAfter, containerRelativeLogicalWidth, renderView);
+        logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
+        logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight, renderView);
+
+        // Solve for 'margin-top'
+        marginBeforeAlias = availableSpace - (logicalTopValue + logicalBottomValue + marginAfterAlias);
+    } else if (marginAfter.isAuto()) {
+        marginBeforeAlias = valueForLength(marginBefore, containerRelativeLogicalWidth, renderView);
+        logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
+        logicalBottomValue = valueForLength(logicalBottom, containerLogicalHeight, renderView);
+
+        // Solve for 'margin-bottom'
+        marginAfterAlias = availableSpace - (logicalTopValue + logicalBottomValue + marginBeforeAlias);
+    } else {
+        // Nothing is 'auto', just calculate the values.
+        marginBeforeAlias = valueForLength(marginBefore, containerRelativeLogicalWidth, renderView);
+        marginAfterAlias = valueForLength(marginAfter, containerRelativeLogicalWidth, renderView);
+        logicalTopValue = valueForLength(logicalTop, containerLogicalHeight, renderView);
+        // 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.
+    LayoutUnit logicalTopPos = logicalTopValue + marginBeforeAlias;
+    computeLogicalTopPositionedOffset(logicalTopPos, this, computedValues.m_extent, containerBlock, containerLogicalHeight);
+    computedValues.m_position = logicalTopPos;
+}
+
+LayoutRect RenderBox::localCaretRect(InlineBox* box, int caretOffset, LayoutUnit* 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.
+
+    LayoutRect rect(location(), LayoutSize(caretWidth, height()));
+    bool ltr = box ? box->isLeftToRightDirection() : style()->isLeftToRightDirection();
+
+    if ((!caretOffset) ^ ltr)
+        rect.move(LayoutSize(width() - caretWidth, 0));
+
+    if (box) {
+        RootInlineBox* rootBox = box->root();
+        LayoutUnit top = rootBox->lineTop();
+        rect.setY(top);
+        rect.setHeight(rootBox->lineBottom() - 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
+    LayoutUnit fontHeight = style()->fontMetrics().height();
+    if (fontHeight > rect.height() || (!isReplaced() && !isTable()))
+        rect.setHeight(fontHeight);
+
+    if (extraWidthToEndOfLine)
+        *extraWidthToEndOfLine = x() + width() - rect.maxX();
+
+    // Move to local coords
+    rect.moveBy(-location());
+
+    // FIXME: Border/padding should be added for all elements but this workaround
+    // is needed because we use offsets inside an "atomic" element to represent
+    // positions before and after the element in deprecated editing offsets.
+    if (node() && !(editingIgnoresContent(node()) || isTableElement(node()))) {
+        rect.setX(rect.x() + borderLeft() + paddingLeft());
+        rect.setY(rect.y() + paddingTop() + borderTop());
+    }
+
+    if (!isHorizontalWritingMode())
+        return rect.transposedRect();
+
+    return rect;
+}
+
+VisiblePosition RenderBox::positionForPoint(const LayoutPoint& point)
+{
+    // no children...return this render object's element, if there is one, and offset 0
+    if (!firstChild())
+        return createVisiblePosition(nonPseudoNode() ? firstPositionInOrBeforeNode(nonPseudoNode()) : Position());
+
+    if (isTable() && nonPseudoNode()) {
+        LayoutUnit right = contentWidth() + borderAndPaddingWidth();
+        LayoutUnit bottom = contentHeight() + borderAndPaddingHeight();
+        
+        if (point.x() < 0 || point.x() > right || point.y() < 0 || point.y() > bottom) {
+            if (point.x() <= right / 2)
+                return createVisiblePosition(firstPositionInOrBeforeNode(nonPseudoNode()));
+            return createVisiblePosition(lastPositionInOrAfterNode(nonPseudoNode()));
+        }
+    }
+
+    // Pass off to the closest child.
+    LayoutUnit minDist = LayoutUnit::max();
+    RenderBox* closestRenderer = 0;
+    LayoutPoint adjustedPoint = point;
+    if (isTableRow())
+        adjustedPoint.moveBy(location());
+
+    for (RenderObject* renderObject = firstChild(); renderObject; renderObject = renderObject->nextSibling()) {
+        if ((!renderObject->firstChild() && !renderObject->isInline() && !renderObject->isBlockFlow() )
+            || renderObject->style()->visibility() != VISIBLE)
+            continue;
+        
+        if (!renderObject->isBox())
+            continue;
+        
+        RenderBox* renderer = toRenderBox(renderObject);
+
+        LayoutUnit top = renderer->borderTop() + renderer->paddingTop() + (isTableRow() ? LayoutUnit() : renderer->y());
+        LayoutUnit bottom = top + renderer->contentHeight();
+        LayoutUnit left = renderer->borderLeft() + renderer->paddingLeft() + (isTableRow() ? LayoutUnit() : renderer->x());
+        LayoutUnit right = left + renderer->contentWidth();
+        
+        if (point.x() <= right && point.x() >= left && point.y() <= top && point.y() >= bottom) {
+            if (renderer->isTableRow())
+                return renderer->positionForPoint(point + adjustedPoint - renderer->locationOffset());
+            return renderer->positionForPoint(point - renderer->locationOffset());
+        }
+
+        // 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.
+        LayoutPoint cmp;
+        if (point.x() > right) {
+            if (point.y() < top)
+                cmp = LayoutPoint(right, top);
+            else if (point.y() > bottom)
+                cmp = LayoutPoint(right, bottom);
+            else
+                cmp = LayoutPoint(right, point.y());
+        } else if (point.x() < left) {
+            if (point.y() < top)
+                cmp = LayoutPoint(left, top);
+            else if (point.y() > bottom)
+                cmp = LayoutPoint(left, bottom);
+            else
+                cmp = LayoutPoint(left, point.y());
+        } else {
+            if (point.y() < top)
+                cmp = LayoutPoint(point.x(), top);
+            else
+                cmp = LayoutPoint(point.x(), bottom);
+        }
+
+        LayoutSize difference = cmp - point;
+
+        LayoutUnit dist = difference.width() * difference.width() + difference.height() * difference.height();
+        if (dist < minDist) {
+            closestRenderer = renderer;
+            minDist = dist;
+        }
+    }
+    
+    if (closestRenderer)
+        return closestRenderer->positionForPoint(adjustedPoint - closestRenderer->locationOffset());
+    
+    return createVisiblePosition(firstPositionInOrBeforeNode(nonPseudoNode()));
+}
+
+bool RenderBox::shrinkToAvoidFloats() const
+{
+    // Floating objects don't shrink.  Objects that don't avoid floats don't shrink.  Marquees don't shrink.
+    if ((isInline() && !isHTMLMarquee()) || !avoidsFloats() || isFloating())
+        return false;
+    
+    // Only auto width objects can possibly shrink to avoid floats.
+    return style()->width().isAuto();
+}
+
+bool RenderBox::avoidsFloats() const
+{
+    return isReplaced() || hasOverflowClip() || isHR() || isLegend() || isWritingModeRoot() || isDeprecatedFlexItem();
+}
+
+void RenderBox::addVisualEffectOverflow()
+{
+    if (!style()->boxShadow() && !style()->hasBorderImageOutsets())
+        return;
+
+    bool isFlipped = style()->isFlippedBlocksWritingMode();
+    bool isHorizontal = isHorizontalWritingMode();
+    
+    LayoutRect borderBox = borderBoxRect();
+    LayoutUnit overflowMinX = borderBox.x();
+    LayoutUnit overflowMaxX = borderBox.maxX();
+    LayoutUnit overflowMinY = borderBox.y();
+    LayoutUnit overflowMaxY = borderBox.maxY();
+    
+    // Compute box-shadow overflow first.
+    if (style()->boxShadow()) {
+        LayoutUnit shadowLeft;
+        LayoutUnit shadowRight;
+        LayoutUnit shadowTop;
+        LayoutUnit shadowBottom;
+        style()->getBoxShadowExtent(shadowTop, shadowRight, shadowBottom, shadowLeft);
+
+        // In flipped blocks writing modes such as vertical-rl, the physical right shadow value is actually at the lower x-coordinate.
+        overflowMinX = borderBox.x() + ((!isFlipped || isHorizontal) ? shadowLeft : -shadowRight);
+        overflowMaxX = borderBox.maxX() + ((!isFlipped || isHorizontal) ? shadowRight : -shadowLeft);
+        overflowMinY = borderBox.y() + ((!isFlipped || !isHorizontal) ? shadowTop : -shadowBottom);
+        overflowMaxY = borderBox.maxY() + ((!isFlipped || !isHorizontal) ? shadowBottom : -shadowTop);
+    }
+
+    // Now compute border-image-outset overflow.
+    if (style()->hasBorderImageOutsets()) {
+        LayoutBoxExtent borderOutsets = style()->borderImageOutsets();
+        
+        // In flipped blocks writing modes, the physical sides are inverted. For example in vertical-rl, the right
+        // border is at the lower x coordinate value.
+        overflowMinX = min(overflowMinX, borderBox.x() - ((!isFlipped || isHorizontal) ? borderOutsets.left() : borderOutsets.right()));
+        overflowMaxX = max(overflowMaxX, borderBox.maxX() + ((!isFlipped || isHorizontal) ? borderOutsets.right() : borderOutsets.left()));
+        overflowMinY = min(overflowMinY, borderBox.y() - ((!isFlipped || !isHorizontal) ? borderOutsets.top() : borderOutsets.bottom()));
+        overflowMaxY = max(overflowMaxY, borderBox.maxY() + ((!isFlipped || !isHorizontal) ? borderOutsets.bottom() : borderOutsets.top()));
+    }
+
+    // Add in the final overflow with shadows and outsets combined.
+    addVisualOverflow(LayoutRect(overflowMinX, overflowMinY, overflowMaxX - overflowMinX, overflowMaxY - overflowMinY));
+}
+
+void RenderBox::addOverflowFromChild(RenderBox* child, const LayoutSize& delta)
+{
+    // Never allow flow threads to propagate overflow up to a parent.
+    if (child->isRenderFlowThread())
+        return;
+
+    // Only propagate layout overflow from the child if the child isn't clipping its overflow.  If it is, then
+    // its overflow is internal to it, and we don't care about it.  layoutOverflowRectForPropagation takes care of this
+    // and just propagates the border box rect instead.
+    LayoutRect childLayoutOverflowRect = child->layoutOverflowRectForPropagation(style());
+    childLayoutOverflowRect.move(delta);
+    addLayoutOverflow(childLayoutOverflowRect);
+            
+    // Add in visual overflow from the child.  Even if the child clips its overflow, it may still
+    // have visual overflow of its own set from box shadows or reflections.  It is unnecessary to propagate this
+    // overflow if we are clipping our own overflow.
+    if (child->hasSelfPaintingLayer() || hasOverflowClip())
+        return;
+    LayoutRect childVisualOverflowRect = child->visualOverflowRectForPropagation(style());
+    childVisualOverflowRect.move(delta);
+    addVisualOverflow(childVisualOverflowRect);
+}
+
+void RenderBox::addLayoutOverflow(const LayoutRect& rect)
+{
+    LayoutRect clientBox = clientBoxRect();
+    if (clientBox.contains(rect) || rect.isEmpty())
+        return;
+    
+    // For overflow clip objects, we don't want to propagate overflow into unreachable areas.
+    LayoutRect overflowRect(rect);
+    if (hasOverflowClip() || isRenderView()) {
+        // Overflow is in the block's coordinate space and thus is flipped for horizontal-bt and vertical-rl 
+        // writing modes.  At this stage that is actually a simplification, since we can treat horizontal-tb/bt as the same
+        // and vertical-lr/rl as the same.
+        bool hasTopOverflow = !style()->isLeftToRightDirection() && !isHorizontalWritingMode();
+        bool hasLeftOverflow = !style()->isLeftToRightDirection() && isHorizontalWritingMode();
+        if (isFlexibleBox() && style()->isReverseFlexDirection()) {
+            RenderFlexibleBox* flexibleBox = toRenderFlexibleBox(this);
+            if (flexibleBox->isHorizontalFlow())
+                hasLeftOverflow = true;
+            else
+                hasTopOverflow = true;
+        }
+
+        if (hasColumns() && style()->columnProgression() == ReverseColumnProgression) {
+            if (isHorizontalWritingMode() ^ !style()->hasInlineColumnAxis())
+                hasLeftOverflow = !hasLeftOverflow;
+            else
+                hasTopOverflow = !hasTopOverflow;
+        }
+
+        if (!hasTopOverflow)
+            overflowRect.shiftYEdgeTo(max(overflowRect.y(), clientBox.y()));
+        else
+            overflowRect.shiftMaxYEdgeTo(min(overflowRect.maxY(), clientBox.maxY()));
+        if (!hasLeftOverflow)
+            overflowRect.shiftXEdgeTo(max(overflowRect.x(), clientBox.x()));
+        else
+            overflowRect.shiftMaxXEdgeTo(min(overflowRect.maxX(), clientBox.maxX()));
+        
+        // Now re-test with the adjusted rectangle and see if it has become unreachable or fully
+        // contained.
+        if (clientBox.contains(overflowRect) || overflowRect.isEmpty())
+            return;
+    }
+
+    if (!m_overflow)
+        m_overflow = adoptPtr(new RenderOverflow(clientBox, borderBoxRect()));
+    
+    m_overflow->addLayoutOverflow(overflowRect);
+}
+
+void RenderBox::addVisualOverflow(const LayoutRect& rect)
+{
+    LayoutRect borderBox = borderBoxRect();
+    if (borderBox.contains(rect) || rect.isEmpty())
+        return;
+        
+    if (!m_overflow)
+        m_overflow = adoptPtr(new RenderOverflow(clientBoxRect(), borderBox));
+    
+    m_overflow->addVisualOverflow(rect);
+}
+
+void RenderBox::clearLayoutOverflow()
+{
+    if (!m_overflow)
+        return;
+    
+    if (visualOverflowRect() == borderBoxRect()) {
+        m_overflow.clear();
+        return;
+    }
+    
+    m_overflow->setLayoutOverflow(borderBoxRect());
+}
+
+inline static bool percentageLogicalHeightIsResolvable(const RenderBox* box)
+{
+    return RenderBox::percentageLogicalHeightIsResolvableFromBlock(box->containingBlock(), box->isOutOfFlowPositioned());
+}
+
+bool RenderBox::percentageLogicalHeightIsResolvableFromBlock(const RenderBlock* containingBlock, bool isOutOfFlowPositioned)
+{
+    // 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. We still skip anonymous containing blocks in both modes, though, and look
+    // only at explicit containers.
+    const RenderBlock* cb = containingBlock;
+    bool inQuirksMode = cb->document()->inQuirksMode();
+    while (!cb->isRenderView() && !cb->isBody() && !cb->isTableCell() && !cb->isOutOfFlowPositioned() && cb->style()->logicalHeight().isAuto()) {
+        if (!inQuirksMode && !cb->isAnonymousBlock())
+            break;
+        cb = cb->containingBlock();
+    }
+
+    // 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.
+    // FIXME: We can't just check top/bottom here.
+    // https://bugs.webkit.org/show_bug.cgi?id=46500
+    bool isOutOfFlowPositionedWithSpecifiedHeight = cb->isOutOfFlowPositioned() && (!cb->style()->logicalHeight().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())
+        return true;
+
+    // Otherwise we only use our percentage height if our containing block had a specified
+    // height.
+    if (cb->style()->logicalHeight().isFixed())
+        return true;
+    if (cb->style()->logicalHeight().isPercent() && !isOutOfFlowPositionedWithSpecifiedHeight)
+        return percentageLogicalHeightIsResolvableFromBlock(cb->containingBlock(), cb->isOutOfFlowPositioned());
+    if (cb->isRenderView() || inQuirksMode || isOutOfFlowPositionedWithSpecifiedHeight)
+        return true;
+    if (cb->isRoot() && isOutOfFlowPositioned) {
+        // 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 computePercentageLogicalHeight on a positioned containing block.
+        return true;
+    }
+
+    return false;
+}
+
+bool RenderBox::hasUnsplittableScrollingOverflow() const
+{
+    // We will paginate as long as we don't scroll overflow in the pagination direction.
+    bool isHorizontal = isHorizontalWritingMode();
+    if ((isHorizontal && !scrollsOverflowY()) || (!isHorizontal && !scrollsOverflowX()))
+        return false;
+    
+    // We do have overflow. We'll still be willing to paginate as long as the block
+    // has auto logical height, auto or undefined max-logical-height and a zero or auto min-logical-height.
+    // Note this is just a heuristic, and it's still possible to have overflow under these
+    // conditions, but it should work out to be good enough for common cases. Paginating overflow
+    // with scrollbars present is not the end of the world and is what we used to do in the old model anyway.
+    return !style()->logicalHeight().isIntrinsicOrAuto()
+        || (!style()->logicalMaxHeight().isIntrinsicOrAuto() && !style()->logicalMaxHeight().isUndefined() && (!style()->logicalMaxHeight().isPercent() || percentageLogicalHeightIsResolvable(this)))
+        || (!style()->logicalMinHeight().isIntrinsicOrAuto() && style()->logicalMinHeight().isPositive() && (!style()->logicalMinHeight().isPercent() || percentageLogicalHeightIsResolvable(this)));
+}
+
+bool RenderBox::isUnsplittableForPagination() const
+{
+    return isReplaced() || hasUnsplittableScrollingOverflow() || (parent() && isWritingModeRoot());
+}
+
+LayoutUnit RenderBox::lineHeight(bool /*firstLine*/, LineDirectionMode direction, LinePositionMode /*linePositionMode*/) const
+{
+    if (isReplaced())
+        return direction == HorizontalLine ? m_marginBox.top() + height() + m_marginBox.bottom() : m_marginBox.right() + width() + m_marginBox.left();
+    return 0;
+}
+
+int RenderBox::baselinePosition(FontBaseline baselineType, bool /*firstLine*/, LineDirectionMode direction, LinePositionMode linePositionMode) const
+{
+    ASSERT(linePositionMode == PositionOnContainingLine);
+    if (isReplaced()) {
+        int result = direction == HorizontalLine ? m_marginBox.top() + height() + m_marginBox.bottom() : m_marginBox.right() + width() + m_marginBox.left();
+        if (baselineType == AlphabeticBaseline)
+            return result;
+        return result - result / 2;
+    }
+    return 0;
+}
+
+
+RenderLayer* RenderBox::enclosingFloatPaintingLayer() const
+{
+    const RenderObject* curr = this;
+    while (curr) {
+        RenderLayer* layer = curr->hasLayer() && curr->isBox() ? toRenderBox(curr)->layer() : 0;
+        if (layer && layer->isSelfPaintingLayer())
+            return layer;
+        curr = curr->parent();
+    }
+    return 0;
+}
+
+LayoutRect RenderBox::logicalVisualOverflowRectForPropagation(RenderStyle* parentStyle) const
+{
+    LayoutRect rect = visualOverflowRectForPropagation(parentStyle);
+    if (!parentStyle->isHorizontalWritingMode())
+        return rect.transposedRect();
+    return rect;
+}
+
+LayoutRect RenderBox::visualOverflowRectForPropagation(RenderStyle* parentStyle) const
+{
+    // If the writing modes of the child and parent match, then we don't have to 
+    // do anything fancy. Just return the result.
+    LayoutRect rect = visualOverflowRect();
+    if (parentStyle->writingMode() == style()->writingMode())
+        return rect;
+    
+    // We are putting ourselves into our parent's coordinate space.  If there is a flipped block mismatch
+    // in a particular axis, then we have to flip the rect along that axis.
+    if (style()->writingMode() == RightToLeftWritingMode || parentStyle->writingMode() == RightToLeftWritingMode)
+        rect.setX(width() - rect.maxX());
+    else if (style()->writingMode() == BottomToTopWritingMode || parentStyle->writingMode() == BottomToTopWritingMode)
+        rect.setY(height() - rect.maxY());
+
+    return rect;
+}
+
+LayoutRect RenderBox::logicalLayoutOverflowRectForPropagation(RenderStyle* parentStyle) const
+{
+    LayoutRect rect = layoutOverflowRectForPropagation(parentStyle);
+    if (!parentStyle->isHorizontalWritingMode())
+        return rect.transposedRect();
+    return rect;
+}
+
+LayoutRect RenderBox::layoutOverflowRectForPropagation(RenderStyle* parentStyle) const
+{
+    // Only propagate interior layout overflow if we don't clip it.
+    LayoutRect rect = borderBoxRect();
+    if (!hasOverflowClip())
+        rect.unite(layoutOverflowRect());
+
+    bool hasTransform = hasLayer() && layer()->transform();
+    if (hasPaintOffset() || hasTransform) {
+        // If we are relatively positioned or if we have a transform, then we have to convert
+        // this rectangle into physical coordinates, apply relative positioning and transforms
+        // to it, and then convert it back.
+        flipForWritingMode(rect);
+        
+        if (hasTransform)
+            rect = layer()->currentTransform().mapRect(rect);
+
+        if (hasPaintOffset())
+            rect.move(paintOffset());
+        
+        // Now we need to flip back.
+        flipForWritingMode(rect);
+    }
+    
+    // If the writing modes of the child and parent match, then we don't have to 
+    // do anything fancy. Just return the result.
+    if (parentStyle->writingMode() == style()->writingMode())
+        return rect;
+    
+    // We are putting ourselves into our parent's coordinate space.  If there is a flipped block mismatch
+    // in a particular axis, then we have to flip the rect along that axis.
+    if (style()->writingMode() == RightToLeftWritingMode || parentStyle->writingMode() == RightToLeftWritingMode)
+        rect.setX(width() - rect.maxX());
+    else if (style()->writingMode() == BottomToTopWritingMode || parentStyle->writingMode() == BottomToTopWritingMode)
+        rect.setY(height() - rect.maxY());
+
+    return rect;
+}
+
+LayoutRect RenderBox::overflowRectForPaintRejection() const
+{
+    LayoutRect overflowRect = visualOverflowRect();
+    if (!m_overflow || !usesCompositedScrolling())
+        return overflowRect;
+
+    overflowRect.unite(layoutOverflowRect());
+    overflowRect.move(-scrolledContentOffset());
+    return overflowRect;
+}
+
+LayoutUnit RenderBox::offsetLeft() const
+{
+    return adjustedPositionRelativeToOffsetParent(topLeftLocation()).x();
+}
+
+LayoutUnit RenderBox::offsetTop() const
+{
+    return adjustedPositionRelativeToOffsetParent(topLeftLocation()).y();
+}
+
+LayoutPoint RenderBox::flipForWritingModeForChild(const RenderBox* child, const LayoutPoint& point) const
+{
+    if (!style()->isFlippedBlocksWritingMode())
+        return point;
+    
+    // The child is going to add in its x() and y(), so we have to make sure it ends up in
+    // the right place.
+    if (isHorizontalWritingMode())
+        return LayoutPoint(point.x(), point.y() + height() - child->height() - (2 * child->y()));
+    return LayoutPoint(point.x() + width() - child->width() - (2 * child->x()), point.y());
+}
+
+void RenderBox::flipForWritingMode(LayoutRect& rect) const
+{
+    if (!style()->isFlippedBlocksWritingMode())
+        return;
+
+    if (isHorizontalWritingMode())
+        rect.setY(height() - rect.maxY());
+    else
+        rect.setX(width() - rect.maxX());
+}
+
+LayoutUnit RenderBox::flipForWritingMode(LayoutUnit position) const
+{
+    if (!style()->isFlippedBlocksWritingMode())
+        return position;
+    return logicalHeight() - position;
+}
+
+LayoutPoint RenderBox::flipForWritingMode(const LayoutPoint& position) const
+{
+    if (!style()->isFlippedBlocksWritingMode())
+        return position;
+    return isHorizontalWritingMode() ? LayoutPoint(position.x(), height() - position.y()) : LayoutPoint(width() - position.x(), position.y());
+}
+
+LayoutPoint RenderBox::flipForWritingModeIncludingColumns(const LayoutPoint& point) const
+{
+    if (!hasColumns() || !style()->isFlippedBlocksWritingMode())
+        return flipForWritingMode(point);
+    return toRenderBlock(this)->flipForWritingModeIncludingColumns(point);
+}
+
+LayoutSize RenderBox::flipForWritingMode(const LayoutSize& offset) const
+{
+    if (!style()->isFlippedBlocksWritingMode())
+        return offset;
+    return isHorizontalWritingMode() ? LayoutSize(offset.width(), height() - offset.height()) : LayoutSize(width() - offset.width(), offset.height());
+}
+
+FloatPoint RenderBox::flipForWritingMode(const FloatPoint& position) const
+{
+    if (!style()->isFlippedBlocksWritingMode())
+        return position;
+    return isHorizontalWritingMode() ? FloatPoint(position.x(), height() - position.y()) : FloatPoint(width() - position.x(), position.y());
+}
+
+void RenderBox::flipForWritingMode(FloatRect& rect) const
+{
+    if (!style()->isFlippedBlocksWritingMode())
+        return;
+
+    if (isHorizontalWritingMode())
+        rect.setY(height() - rect.maxY());
+    else
+        rect.setX(width() - rect.maxX());
+}
+
+LayoutPoint RenderBox::topLeftLocation() const
+{
+    RenderBlock* containerBlock = containingBlock();
+    if (!containerBlock || containerBlock == this)
+        return location();
+    return containerBlock->flipForWritingModeForChild(this, location());
+}
+
+LayoutSize RenderBox::topLeftLocationOffset() const
+{
+    RenderBlock* containerBlock = containingBlock();
+    if (!containerBlock || containerBlock == this)
+        return locationOffset();
+    
+    LayoutRect rect(frameRect());
+    containerBlock->flipForWritingMode(rect); // FIXME: This is wrong if we are an absolutely positioned object enclosed by a relative-positioned inline.
+    return LayoutSize(rect.x(), rect.y());
+}
+
+bool RenderBox::hasRelativeDimensions() const
+{
+    return style()->height().isPercent() || style()->width().isPercent()
+            || style()->maxHeight().isPercent() || style()->maxWidth().isPercent()
+            || style()->minHeight().isPercent() || style()->minWidth().isPercent();
+}
+
+bool RenderBox::hasRelativeLogicalHeight() const
+{
+    return style()->logicalHeight().isPercent()
+            || style()->logicalMinHeight().isPercent()
+            || style()->logicalMaxHeight().isPercent();
+}
+
+bool RenderBox::hasViewportPercentageLogicalHeight() const
+{
+    return style()->logicalHeight().isViewportPercentage()
+        || style()->logicalMinHeight().isViewportPercentage()
+        || style()->logicalMaxHeight().isViewportPercentage();
+}
+
+static void markBoxForRelayoutAfterSplit(RenderBox* box)
+{
+    // FIXME: The table code should handle that automatically. If not,
+    // we should fix it and remove the table part checks.
+    if (box->isTable()) {
+        // Because we may have added some sections with already computed column structures, we need to
+        // sync the table structure with them now. This avoids crashes when adding new cells to the table.
+        toRenderTable(box)->forceSectionsRecalc();
+    } else if (box->isTableSection())
+        toRenderTableSection(box)->setNeedsCellRecalc();
+
+    box->setNeedsLayoutAndPrefWidthsRecalc();
+}
+
+RenderObject* RenderBox::splitAnonymousBoxesAroundChild(RenderObject* beforeChild)
+{
+    bool didSplitParentAnonymousBoxes = false;
+
+    while (beforeChild->parent() != this) {
+        RenderBox* boxToSplit = toRenderBox(beforeChild->parent());
+        if (boxToSplit->firstChild() != beforeChild && boxToSplit->isAnonymous()) {
+            didSplitParentAnonymousBoxes = true;
+
+            // We have to split the parent box into two boxes and move children
+            // from |beforeChild| to end into the new post box.
+            RenderBox* postBox = boxToSplit->createAnonymousBoxWithSameTypeAs(this);
+            postBox->setChildrenInline(boxToSplit->childrenInline());
+            RenderBox* parentBox = toRenderBox(boxToSplit->parent());
+            // We need to invalidate the |parentBox| before inserting the new node
+            // so that the table repainting logic knows the structure is dirty.
+            // See for example RenderTableCell:clippedOverflowRectForRepaint.
+            markBoxForRelayoutAfterSplit(parentBox);
+            parentBox->virtualChildren()->insertChildNode(parentBox, postBox, boxToSplit->nextSibling());
+            boxToSplit->moveChildrenTo(postBox, beforeChild, 0, true);
+
+            markBoxForRelayoutAfterSplit(boxToSplit);
+            markBoxForRelayoutAfterSplit(postBox);
+
+            beforeChild = postBox;
+        } else
+            beforeChild = boxToSplit;
+    }
+
+    if (didSplitParentAnonymousBoxes)
+        markBoxForRelayoutAfterSplit(this);
+
+    ASSERT(beforeChild->parent() == this);
+    return beforeChild;
+}
+
+void RenderBox::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, PlatformMemoryTypes::Rendering);
+    RenderBoxModelObject::reportMemoryUsage(memoryObjectInfo);
+    info.addWeakPointer(m_inlineBoxWrapper);
+    info.addMember(m_overflow, "overflow");
+}
+
+void RenderBox::reportStaticMembersMemoryUsage(MemoryInstrumentation* memoryInstrumentation)
+{
+    memoryInstrumentation->addRootObject(gOverrideHeightMap, WebCoreMemoryTypes::RenderingStructures);
+    memoryInstrumentation->addRootObject(gOverrideWidthMap, WebCoreMemoryTypes::RenderingStructures);
+    memoryInstrumentation->addRootObject(gOverrideContainingBlockLogicalHeightMap, WebCoreMemoryTypes::RenderingStructures);
+    memoryInstrumentation->addRootObject(gOverrideContainingBlockLogicalWidthMap, WebCoreMemoryTypes::RenderingStructures);
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderBox.h b/Source/core/rendering/RenderBox.h
new file mode 100644
index 0000000..ae0b8c8
--- /dev/null
+++ b/Source/core/rendering/RenderBox.h
@@ -0,0 +1,729 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * 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 "core/platform/ScrollTypes.h"
+#include "core/rendering/exclusions/ExclusionShapeOutsideInfo.h"
+#include "core/rendering/RenderBoxModelObject.h"
+#include "core/rendering/RenderOverflow.h"
+
+namespace WebCore {
+
+class RenderBoxRegionInfo;
+class RenderRegion;
+struct PaintInfo;
+
+enum SizeType { MainOrPreferredSize, MinSize, MaxSize };
+enum AvailableLogicalHeightType { ExcludeMarginBorderPadding, IncludeMarginBorderPadding };
+enum OverlayScrollbarSizeRelevancy { IgnoreOverlayScrollbarSize, IncludeOverlayScrollbarSize };
+
+enum ShouldComputePreferred { ComputeActual, ComputePreferred };
+
+class RenderBox : public RenderBoxModelObject {
+public:
+    explicit RenderBox(ContainerNode*);
+    virtual ~RenderBox();
+
+    // hasAutoZIndex only returns true if the element is positioned or a flex-item since
+    // position:static elements that are not flex-items get their z-index coerced to auto.
+    virtual bool requiresLayer() const OVERRIDE { return isRoot() || isPositioned() || createsGroup() || hasClipPath() || hasOverflowClip() || hasTransform() || hasHiddenBackface() || hasReflection() || style()->specifiesColumns() || !style()->hasAutoZIndex() || isFloatingWithShapeOutside(); }
+
+    virtual bool backgroundIsKnownToBeOpaqueInRect(const LayoutRect& localRect) const OVERRIDE FINAL;
+
+    // Use this with caution! No type checking is done!
+    RenderBox* firstChildBox() const;
+    RenderBox* lastChildBox() const;
+
+    LayoutUnit x() const { return m_frameRect.x(); }
+    LayoutUnit y() const { return m_frameRect.y(); }
+    LayoutUnit width() const { return m_frameRect.width(); }
+    LayoutUnit height() const { return m_frameRect.height(); }
+
+    int pixelSnappedWidth() const { return m_frameRect.pixelSnappedWidth(); }
+    int pixelSnappedHeight() const { return m_frameRect.pixelSnappedHeight(); }
+
+    // These represent your location relative to your container as a physical offset.
+    // In layout related methods you almost always want the logical location (e.g. x() and y()).
+    LayoutUnit top() const { return topLeftLocation().y(); }
+    LayoutUnit left() const { return topLeftLocation().x(); }
+
+    void setX(LayoutUnit x) { m_frameRect.setX(x); }
+    void setY(LayoutUnit y) { m_frameRect.setY(y); }
+    void setWidth(LayoutUnit width) { m_frameRect.setWidth(width); }
+    void setHeight(LayoutUnit height) { m_frameRect.setHeight(height); }
+
+    LayoutUnit logicalLeft() const { return style()->isHorizontalWritingMode() ? x() : y(); }
+    LayoutUnit logicalRight() const { return logicalLeft() + logicalWidth(); }
+    LayoutUnit logicalTop() const { return style()->isHorizontalWritingMode() ? y() : x(); }
+    LayoutUnit logicalBottom() const { return logicalTop() + logicalHeight(); }
+    LayoutUnit logicalWidth() const { return style()->isHorizontalWritingMode() ? width() : height(); }
+    LayoutUnit logicalHeight() const { return style()->isHorizontalWritingMode() ? height() : width(); }
+
+    LayoutUnit constrainLogicalWidthInRegionByMinMax(LayoutUnit, LayoutUnit, RenderBlock*, RenderRegion* = 0, LayoutUnit offsetFromLogicalTopOfFirstPage = 0) const;
+    LayoutUnit constrainLogicalHeightByMinMax(LayoutUnit logicalHeight, LayoutUnit intrinsicContentHeight) const;
+    LayoutUnit constrainContentBoxLogicalHeightByMinMax(LayoutUnit logicalHeight, LayoutUnit intrinsicContentHeight) const;
+
+    int pixelSnappedLogicalHeight() const { return style()->isHorizontalWritingMode() ? pixelSnappedHeight() : pixelSnappedWidth(); }
+    int pixelSnappedLogicalWidth() const { return style()->isHorizontalWritingMode() ? pixelSnappedWidth() : pixelSnappedHeight(); }
+
+    void setLogicalLeft(LayoutUnit left)
+    {
+        if (style()->isHorizontalWritingMode())
+            setX(left);
+        else
+            setY(left);
+    }
+    void setLogicalTop(LayoutUnit top)
+    {
+        if (style()->isHorizontalWritingMode())
+            setY(top);
+        else
+            setX(top);
+    }
+    void setLogicalLocation(const LayoutPoint& location)
+    {
+        if (style()->isHorizontalWritingMode())
+            setLocation(location);
+        else
+            setLocation(location.transposedPoint());
+    }
+    void setLogicalWidth(LayoutUnit size)
+    {
+        if (style()->isHorizontalWritingMode())
+            setWidth(size);
+        else
+            setHeight(size);
+    }
+    void setLogicalHeight(LayoutUnit size)
+    {
+        if (style()->isHorizontalWritingMode())
+            setHeight(size);
+        else
+            setWidth(size);
+    }
+    void setLogicalSize(const LayoutSize& size)
+    {
+        if (style()->isHorizontalWritingMode())
+            setSize(size);
+        else
+            setSize(size.transposedSize());
+    }
+
+    LayoutPoint location() const { return m_frameRect.location(); }
+    LayoutSize locationOffset() const { return LayoutSize(x(), y()); }
+    LayoutSize size() const { return m_frameRect.size(); }
+    IntSize pixelSnappedSize() const { return m_frameRect.pixelSnappedSize(); }
+
+    void setLocation(const LayoutPoint& location) { m_frameRect.setLocation(location); }
+    
+    void setSize(const LayoutSize& size) { m_frameRect.setSize(size); }
+    void move(LayoutUnit dx, LayoutUnit dy) { m_frameRect.move(dx, dy); }
+
+    LayoutRect frameRect() const { return m_frameRect; }
+    IntRect pixelSnappedFrameRect() const { return pixelSnappedIntRect(m_frameRect); }
+    void setFrameRect(const LayoutRect& rect) { m_frameRect = rect; }
+
+    LayoutRect borderBoxRect() const { return LayoutRect(LayoutPoint(), size()); }
+    LayoutRect paddingBoxRect() const { return LayoutRect(borderLeft(), borderTop(), contentWidth() + paddingLeft() + paddingRight(), contentHeight() + paddingTop() + paddingBottom()); }
+    IntRect pixelSnappedBorderBoxRect() const { return IntRect(IntPoint(), m_frameRect.pixelSnappedSize()); }
+    virtual IntRect borderBoundingBox() const OVERRIDE FINAL { return pixelSnappedBorderBoxRect(); }
+
+    // The content area of the box (excludes padding - and intrinsic padding for table cells, etc... - and border).
+    LayoutRect contentBoxRect() const { return LayoutRect(borderLeft() + paddingLeft(), borderTop() + paddingTop(), contentWidth(), contentHeight()); }
+    // The content box in absolute coords. Ignores transforms.
+    IntRect absoluteContentBox() const;
+    // The content box converted to absolute coords (taking transforms into account).
+    FloatQuad absoluteContentQuad() const;
+
+    // This returns the content area of the box (excluding padding and border). The only difference with contentBoxRect is that computedCSSContentBoxRect
+    // does include the intrinsic padding in the content box as this is what some callers expect (like getComputedStyle).
+    LayoutRect computedCSSContentBoxRect() const { return LayoutRect(borderLeft() + computedCSSPaddingLeft(), borderTop() + computedCSSPaddingTop(), clientWidth() - computedCSSPaddingLeft() - computedCSSPaddingRight(), clientHeight() - computedCSSPaddingTop() - computedCSSPaddingBottom()); }
+
+    // Bounds of the outline box in absolute coords. Respects transforms
+    virtual LayoutRect outlineBoundsForRepaint(const RenderLayerModelObject* /*repaintContainer*/, const RenderGeometryMap*) const OVERRIDE FINAL;
+    virtual void addFocusRingRects(Vector<IntRect>&, const LayoutPoint& additionalOffset, const RenderLayerModelObject* paintContainer = 0) OVERRIDE;
+
+    // Use this with caution! No type checking is done!
+    RenderBox* previousSiblingBox() const;
+    RenderBox* nextSiblingBox() const;
+    RenderBox* parentBox() const;
+
+    // Visual and layout overflow are in the coordinate space of the box.  This means that they aren't purely physical directions.
+    // For horizontal-tb and vertical-lr they will match physical directions, but for horizontal-bt and vertical-rl, the top/bottom and left/right
+    // respectively are flipped when compared to their physical counterparts.  For example minX is on the left in vertical-lr,
+    // but it is on the right in vertical-rl.
+    LayoutRect layoutOverflowRect() const { return m_overflow ? m_overflow->layoutOverflowRect() : clientBoxRect(); }
+    IntRect pixelSnappedLayoutOverflowRect() const { return pixelSnappedIntRect(layoutOverflowRect()); }
+    LayoutSize maxLayoutOverflow() const { return LayoutSize(layoutOverflowRect().maxX(), layoutOverflowRect().maxY()); }
+    LayoutUnit logicalLeftLayoutOverflow() const { return style()->isHorizontalWritingMode() ? layoutOverflowRect().x() : layoutOverflowRect().y(); }
+    LayoutUnit logicalRightLayoutOverflow() const { return style()->isHorizontalWritingMode() ? layoutOverflowRect().maxX() : layoutOverflowRect().maxY(); }
+    
+    virtual LayoutRect visualOverflowRect() const { return m_overflow ? m_overflow->visualOverflowRect() : borderBoxRect(); }
+    LayoutUnit logicalLeftVisualOverflow() const { return style()->isHorizontalWritingMode() ? visualOverflowRect().x() : visualOverflowRect().y(); }
+    LayoutUnit logicalRightVisualOverflow() const { return style()->isHorizontalWritingMode() ? visualOverflowRect().maxX() : visualOverflowRect().maxY(); }
+
+    LayoutRect overflowRectForPaintRejection() const;
+    
+    void addLayoutOverflow(const LayoutRect&);
+    void addVisualOverflow(const LayoutRect&);
+    
+    void addVisualEffectOverflow();
+    void addOverflowFromChild(RenderBox* child) { addOverflowFromChild(child, child->locationOffset()); }
+    void addOverflowFromChild(RenderBox* child, const LayoutSize& delta);
+    void clearLayoutOverflow();
+    
+    void updateLayerTransform();
+
+    LayoutUnit contentWidth() const { return clientWidth() - paddingLeft() - paddingRight(); }
+    LayoutUnit contentHeight() const { return clientHeight() - paddingTop() - paddingBottom(); }
+    LayoutUnit contentLogicalWidth() const { return style()->isHorizontalWritingMode() ? contentWidth() : contentHeight(); }
+    LayoutUnit contentLogicalHeight() const { return style()->isHorizontalWritingMode() ? contentHeight() : contentWidth(); }
+
+    // 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 LayoutUnit offsetWidth() const { return width(); }
+    virtual LayoutUnit offsetHeight() const { return height(); }
+
+    virtual int pixelSnappedOffsetWidth() const OVERRIDE FINAL;
+    virtual int pixelSnappedOffsetHeight() const OVERRIDE FINAL;
+
+    // More IE extensions.  clientWidth and clientHeight represent the interior of an object
+    // excluding border and scrollbar.  clientLeft/Top are just the borderLeftWidth and borderTopWidth.
+    LayoutUnit clientLeft() const { return borderLeft(); }
+    LayoutUnit clientTop() const { return borderTop(); }
+    LayoutUnit clientWidth() const;
+    LayoutUnit clientHeight() const;
+    LayoutUnit clientLogicalWidth() const { return style()->isHorizontalWritingMode() ? clientWidth() : clientHeight(); }
+    LayoutUnit clientLogicalHeight() const { return style()->isHorizontalWritingMode() ? clientHeight() : clientWidth(); }
+    LayoutUnit clientLogicalBottom() const { return borderBefore() + clientLogicalHeight(); }
+    LayoutRect clientBoxRect() const { return LayoutRect(clientLeft(), clientTop(), clientWidth(), clientHeight()); }
+
+    int pixelSnappedClientWidth() const;
+    int pixelSnappedClientHeight() 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 LayoutUnit marginTop() const OVERRIDE { return m_marginBox.top(); }
+    virtual LayoutUnit marginBottom() const OVERRIDE { return m_marginBox.bottom(); }
+    virtual LayoutUnit marginLeft() const OVERRIDE { return m_marginBox.left(); }
+    virtual LayoutUnit marginRight() const OVERRIDE { return m_marginBox.right(); }
+    void setMarginTop(LayoutUnit margin) { m_marginBox.setTop(margin); }
+    void setMarginBottom(LayoutUnit margin) { m_marginBox.setBottom(margin); }
+    void setMarginLeft(LayoutUnit margin) { m_marginBox.setLeft(margin); }
+    void setMarginRight(LayoutUnit margin) { m_marginBox.setRight(margin); }
+
+    LayoutUnit marginLogicalLeft() const { return m_marginBox.logicalLeft(style()->writingMode()); }
+    LayoutUnit marginLogicalRight() const { return m_marginBox.logicalRight(style()->writingMode()); }
+    
+    virtual LayoutUnit marginBefore(const RenderStyle* overrideStyle = 0) const OVERRIDE FINAL { return m_marginBox.before((overrideStyle ? overrideStyle : style())->writingMode()); }
+    virtual LayoutUnit marginAfter(const RenderStyle* overrideStyle = 0) const OVERRIDE FINAL { return m_marginBox.after((overrideStyle ? overrideStyle : style())->writingMode()); }
+    virtual LayoutUnit marginStart(const RenderStyle* overrideStyle = 0) const OVERRIDE FINAL
+    {
+        const RenderStyle* styleToUse = overrideStyle ? overrideStyle : style();
+        return m_marginBox.start(styleToUse->writingMode(), styleToUse->direction());
+    }
+    virtual LayoutUnit marginEnd(const RenderStyle* overrideStyle = 0) const OVERRIDE FINAL
+    {
+        const RenderStyle* styleToUse = overrideStyle ? overrideStyle : style();
+        return m_marginBox.end(styleToUse->writingMode(), styleToUse->direction());
+    }
+    void setMarginBefore(LayoutUnit value, const RenderStyle* overrideStyle = 0) { m_marginBox.setBefore((overrideStyle ? overrideStyle : style())->writingMode(), value); }
+    void setMarginAfter(LayoutUnit value, const RenderStyle* overrideStyle = 0) { m_marginBox.setAfter((overrideStyle ? overrideStyle : style())->writingMode(), value); }
+    void setMarginStart(LayoutUnit value, const RenderStyle* overrideStyle = 0)
+    {
+        const RenderStyle* styleToUse = overrideStyle ? overrideStyle : style();
+        m_marginBox.setStart(styleToUse->writingMode(), styleToUse->direction(), value);
+    }
+    void setMarginEnd(LayoutUnit value, const RenderStyle* overrideStyle = 0)
+    {
+        const RenderStyle* styleToUse = overrideStyle ? overrideStyle : style();
+        m_marginBox.setEnd(styleToUse->writingMode(), styleToUse->direction(), value);
+    }
+
+    // The following five 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 box, such as a leaf element, this formula will simply return
+    // the margin of the element.  Blocks override the maxMarginBefore and maxMarginAfter
+    // methods.
+    enum MarginSign { PositiveMargin, NegativeMargin };
+    virtual bool isSelfCollapsingBlock() const { return false; }
+    virtual LayoutUnit collapsedMarginBefore() const { return marginBefore(); }
+    virtual LayoutUnit collapsedMarginAfter() const { return marginAfter(); }
+
+    virtual void absoluteRects(Vector<IntRect>&, const LayoutPoint& accumulatedOffset) const;
+    virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const;
+    
+    LayoutRect reflectionBox() const;
+    int reflectionOffset() const;
+    // Given a rect in the object's coordinate space, returns the corresponding rect in the reflection.
+    LayoutRect reflectedRect(const LayoutRect&) const;
+
+    virtual void layout();
+    virtual void paint(PaintInfo&, const LayoutPoint&);
+    virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
+
+    virtual LayoutUnit minPreferredLogicalWidth() const;
+    virtual LayoutUnit maxPreferredLogicalWidth() const;
+
+    // FIXME: We should rename these back to overrideLogicalHeight/Width and have them store
+    // the border-box height/width like the regular height/width accessors on RenderBox.
+    // Right now, these are different than contentHeight/contentWidth because they still
+    // include the scrollbar height/width.
+    LayoutUnit overrideLogicalContentWidth() const;
+    LayoutUnit overrideLogicalContentHeight() const;
+    bool hasOverrideHeight() const;
+    bool hasOverrideWidth() const;
+    void setOverrideLogicalContentHeight(LayoutUnit);
+    void setOverrideLogicalContentWidth(LayoutUnit);
+    void clearOverrideSize();
+    void clearOverrideLogicalContentHeight();
+    void clearOverrideLogicalContentWidth();
+
+    LayoutUnit overrideContainingBlockContentLogicalWidth() const;
+    LayoutUnit overrideContainingBlockContentLogicalHeight() const;
+    bool hasOverrideContainingBlockLogicalWidth() const;
+    bool hasOverrideContainingBlockLogicalHeight() const;
+    void setOverrideContainingBlockContentLogicalWidth(LayoutUnit);
+    void setOverrideContainingBlockContentLogicalHeight(LayoutUnit);
+    void clearContainingBlockOverrideSize();
+    void clearOverrideContainingBlockContentLogicalHeight();
+
+    virtual LayoutSize offsetFromContainer(RenderObject*, const LayoutPoint&, bool* offsetDependsOnPoint = 0) const;
+    
+    LayoutUnit adjustBorderBoxLogicalWidthForBoxSizing(LayoutUnit width) const;
+    LayoutUnit adjustBorderBoxLogicalHeightForBoxSizing(LayoutUnit height) const;
+    LayoutUnit adjustContentBoxLogicalWidthForBoxSizing(LayoutUnit width) const;
+    LayoutUnit adjustContentBoxLogicalHeightForBoxSizing(LayoutUnit height) const;
+
+    struct ComputedMarginValues {
+        ComputedMarginValues()
+            : m_before(0)
+            , m_after(0)
+            , m_start(0)
+            , m_end(0)
+        {
+        }
+        LayoutUnit m_before;
+        LayoutUnit m_after;
+        LayoutUnit m_start;
+        LayoutUnit m_end;
+    };
+    struct LogicalExtentComputedValues {
+        LogicalExtentComputedValues()
+            : m_extent(0)
+            , m_position(0)
+        {
+        }
+
+        LayoutUnit m_extent;
+        LayoutUnit m_position;
+        ComputedMarginValues m_margins;
+    };
+    // Resolve auto margins in the inline direction of the containing block so that objects can be pushed to the start, middle or end
+    // of the containing block.
+    void computeInlineDirectionMargins(RenderBlock* containingBlock, LayoutUnit containerWidth, LayoutUnit childWidth, LayoutUnit& marginStart, LayoutUnit& marginEnd) const;
+
+    // Used to resolve margins in the containing block's block-flow direction.
+    void computeBlockDirectionMargins(const RenderBlock* containingBlock, LayoutUnit& marginBefore, LayoutUnit& marginAfter) const;
+    void computeAndSetBlockDirectionMargins(const RenderBlock* containingBlock);
+
+    enum RenderBoxRegionInfoFlags { CacheRenderBoxRegionInfo, DoNotCacheRenderBoxRegionInfo };
+    LayoutRect borderBoxRectInRegion(RenderRegion*, LayoutUnit offsetFromLogicalTopOfFirstPage = 0, RenderBoxRegionInfoFlags = CacheRenderBoxRegionInfo) const;
+    void clearRenderBoxRegionInfo();
+    
+    void positionLineBox(InlineBox*);
+
+    virtual InlineBox* createInlineBox();
+    void dirtyLineBoxes(bool fullLayout);
+
+    // 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.
+    InlineBox* inlineBoxWrapper() const { return m_inlineBoxWrapper; }
+    void setInlineBoxWrapper(InlineBox* boxWrapper) { m_inlineBoxWrapper = boxWrapper; }
+    void deleteLineBoxWrapper();
+
+    virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const OVERRIDE;
+    virtual void computeRectForRepaint(const RenderLayerModelObject* repaintContainer, LayoutRect&, bool fixed = false) const OVERRIDE;
+    void repaintDuringLayoutIfMoved(const LayoutRect&);
+    virtual void repaintOverhangingFloats(bool paintAllDescendants);
+
+    virtual LayoutUnit containingBlockLogicalWidthForContent() const;
+    LayoutUnit containingBlockLogicalHeightForContent(AvailableLogicalHeightType) const;
+
+    LayoutUnit containingBlockLogicalWidthForContentInRegion(RenderRegion*, LayoutUnit offsetFromLogicalTopOfFirstPage) const;
+    LayoutUnit containingBlockAvailableLineWidthInRegion(RenderRegion*, LayoutUnit offsetFromLogicalTopOfFirstPage) const;
+    LayoutUnit perpendicularContainingBlockLogicalHeight() const;
+
+    virtual void updateLogicalWidth();
+    virtual void updateLogicalHeight();
+    virtual void computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues&) const;
+
+    RenderBoxRegionInfo* renderBoxRegionInfo(RenderRegion*, LayoutUnit offsetFromLogicalTopOfFirstPage, RenderBoxRegionInfoFlags = CacheRenderBoxRegionInfo) const;
+    void computeLogicalWidthInRegion(LogicalExtentComputedValues&, RenderRegion* = 0, LayoutUnit offsetFromLogicalTopOfFirstPage = 0) const;
+
+    bool stretchesToViewport() const
+    {
+        return document()->inQuirksMode() && style()->logicalHeight().isAuto() && !isFloatingOrOutOfFlowPositioned() && (isRoot() || isBody()) && !document()->shouldDisplaySeamlesslyWithParent() && !isInline();
+    }
+
+    virtual LayoutSize intrinsicSize() const { return LayoutSize(); }
+    LayoutUnit intrinsicLogicalWidth() const { return style()->isHorizontalWritingMode() ? intrinsicSize().width() : intrinsicSize().height(); }
+    LayoutUnit intrinsicLogicalHeight() const { return style()->isHorizontalWritingMode() ? intrinsicSize().height() : intrinsicSize().width(); }
+
+    // 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 sizesLogicalWidthToFitContent(SizeType) const;
+
+    LayoutUnit shrinkLogicalWidthToAvoidFloats(LayoutUnit childMarginStart, LayoutUnit childMarginEnd, const RenderBlock* cb, RenderRegion*, LayoutUnit offsetFromLogicalTopOfFirstPage) const;
+
+    LayoutUnit computeLogicalWidthInRegionUsing(SizeType, Length logicalWidth, LayoutUnit availableLogicalWidth, const RenderBlock* containingBlock, RenderRegion*, LayoutUnit offsetFromLogicalTopOfFirstPage) const;
+    LayoutUnit computeLogicalHeightUsing(const Length& height, LayoutUnit intrinsicContentHeight) const;
+    LayoutUnit computeContentLogicalHeight(const Length& height, LayoutUnit intrinsicContentHeight) const;
+    LayoutUnit computeContentAndScrollbarLogicalHeightUsing(const Length& height, LayoutUnit intrinsicContentHeight) const;
+    LayoutUnit computeReplacedLogicalWidthUsing(Length width) const;
+    LayoutUnit computeReplacedLogicalWidthRespectingMinMaxWidth(LayoutUnit logicalWidth, ShouldComputePreferred  = ComputeActual) const;
+    LayoutUnit computeReplacedLogicalHeightUsing(Length height) const;
+    LayoutUnit computeReplacedLogicalHeightRespectingMinMaxHeight(LayoutUnit logicalHeight) const;
+
+    virtual LayoutUnit computeReplacedLogicalWidth(ShouldComputePreferred  = ComputeActual) const;
+    virtual LayoutUnit computeReplacedLogicalHeight() const;
+
+    static bool percentageLogicalHeightIsResolvableFromBlock(const RenderBlock* containingBlock, bool outOfFlowPositioned);
+    LayoutUnit computePercentageLogicalHeight(const Length& height) const;
+
+    // Block flows subclass availableWidth/Height to handle multi column layout (shrinking the width/height available to children when laying out.)
+    virtual LayoutUnit availableLogicalWidth() const { return contentLogicalWidth(); }
+    virtual LayoutUnit availableLogicalHeight(AvailableLogicalHeightType) const;
+    LayoutUnit availableLogicalHeightUsing(const Length&, AvailableLogicalHeightType) const;
+    
+    // There are a few cases where we need to refer specifically to the available physical width and available physical height.
+    // Relative positioning is one of those cases, since left/top offsets are physical.
+    LayoutUnit availableWidth() const { return style()->isHorizontalWritingMode() ? availableLogicalWidth() : availableLogicalHeight(IncludeMarginBorderPadding); }
+    LayoutUnit availableHeight() const { return style()->isHorizontalWritingMode() ? availableLogicalHeight(IncludeMarginBorderPadding) : availableLogicalWidth(); }
+
+    virtual int verticalScrollbarWidth() const;
+    int horizontalScrollbarHeight() const;
+    int instrinsicScrollbarLogicalWidth() const;
+    int scrollbarLogicalHeight() const { return style()->isHorizontalWritingMode() ? horizontalScrollbarHeight() : verticalScrollbarWidth(); }
+    virtual bool scroll(ScrollDirection, ScrollGranularity, float multiplier = 1, Node** stopNode = 0);
+    virtual bool logicalScroll(ScrollLogicalDirection, ScrollGranularity, float multiplier = 1, Node** stopNode = 0);
+    bool canBeScrolledAndHasScrollableArea() const;
+    virtual bool canBeProgramaticallyScrolled() const;
+    virtual void autoscroll(const IntPoint&);
+    bool canAutoscroll() const;
+    IntSize calculateAutoscrollDirection(const IntPoint& windowPoint) const;
+    static RenderBox* findAutoscrollable(RenderObject*);
+    virtual void stopAutoscroll() { }
+    virtual void panScroll(const IntPoint&);
+
+    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()); }
+    bool usesCompositedScrolling() const;
+    
+    bool hasUnsplittableScrollingOverflow() const;
+    bool isUnsplittableForPagination() const;
+
+    virtual LayoutRect localCaretRect(InlineBox*, int caretOffset, LayoutUnit* extraWidthToEndOfLine = 0);
+
+    virtual LayoutRect overflowClipRect(const LayoutPoint& location, RenderRegion*, OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize);
+    LayoutRect clipRect(const LayoutPoint& location, RenderRegion*);
+    virtual bool hasControlClip() const { return false; }
+    virtual LayoutRect controlClipRect(const LayoutPoint&) const { return LayoutRect(); }
+    bool pushContentsClip(PaintInfo&, const LayoutPoint& accumulatedOffset);
+    void popContentsClip(PaintInfo&, PaintPhase originalPhase, const LayoutPoint& accumulatedOffset);
+
+    virtual void paintObject(PaintInfo&, const LayoutPoint&) { ASSERT_NOT_REACHED(); }
+    virtual void paintBoxDecorations(PaintInfo&, const LayoutPoint&);
+    virtual void paintMask(PaintInfo&, const LayoutPoint&);
+    virtual void imageChanged(WrappedImagePtr, const IntRect* = 0);
+
+    // 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.
+    bool tryLayoutDoingPositionedMovementOnly()
+    {
+        LayoutUnit oldWidth = width();
+        updateLogicalWidth();
+        // If we shrink to fit our width may have changed, so we still need full layout.
+        if (oldWidth != width())
+            return false;
+        updateLogicalHeight();
+        return true;
+    }
+
+    LayoutRect maskClipRect();
+
+    virtual VisiblePosition positionForPoint(const LayoutPoint&);
+
+    void removeFloatingOrPositionedChildFromBlockLists();
+    
+    RenderLayer* enclosingFloatPaintingLayer() const;
+    
+    virtual int firstLineBoxBaseline() const { return -1; }
+    virtual int inlineBlockBaseline(LineDirectionMode) const { return -1; } // Returns -1 if we should skip this box when computing the baseline of an inline-block.
+
+    bool shrinkToAvoidFloats() const;
+    virtual bool avoidsFloats() const;
+
+    virtual void markForPaginationRelayoutIfNeeded() { }
+
+    bool isWritingModeRoot() const { return !parent() || parent()->style()->writingMode() != style()->writingMode(); }
+
+    bool isDeprecatedFlexItem() const { return !isInline() && !isFloatingOrOutOfFlowPositioned() && parent() && parent()->isDeprecatedFlexibleBox(); }
+    
+    virtual LayoutUnit lineHeight(bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const;
+    virtual int baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const OVERRIDE;
+
+    virtual LayoutUnit offsetLeft() const OVERRIDE;
+    virtual LayoutUnit offsetTop() const OVERRIDE;
+
+    LayoutPoint flipForWritingModeForChild(const RenderBox* child, const LayoutPoint&) const;
+    LayoutUnit flipForWritingMode(LayoutUnit position) const; // The offset is in the block direction (y for horizontal writing modes, x for vertical writing modes).
+    LayoutPoint flipForWritingMode(const LayoutPoint&) const;
+    LayoutPoint flipForWritingModeIncludingColumns(const LayoutPoint&) const;
+    LayoutSize flipForWritingMode(const LayoutSize&) const;
+    void flipForWritingMode(LayoutRect&) const;
+    FloatPoint flipForWritingMode(const FloatPoint&) const;
+    void flipForWritingMode(FloatRect&) const;
+    // These represent your location relative to your container as a physical offset.
+    // In layout related methods you almost always want the logical location (e.g. x() and y()).
+    LayoutPoint topLeftLocation() const;
+    LayoutSize topLeftLocationOffset() const;
+
+    LayoutRect logicalVisualOverflowRectForPropagation(RenderStyle*) const;
+    LayoutRect visualOverflowRectForPropagation(RenderStyle*) const;
+    LayoutRect logicalLayoutOverflowRectForPropagation(RenderStyle*) const;
+    LayoutRect layoutOverflowRectForPropagation(RenderStyle*) const;
+
+    RenderOverflow* hasRenderOverflow() const { return m_overflow.get(); }    
+    bool hasVisualOverflow() const { return m_overflow && !borderBoxRect().contains(m_overflow->visualOverflowRect()); }
+
+    virtual bool needsPreferredWidthsRecalculation() const;
+    virtual void computeIntrinsicRatioInformation(FloatSize& /* intrinsicSize */, double& /* intrinsicRatio */, bool& /* isPercentageIntrinsicSize */) const { }
+
+    IntSize scrolledContentOffset() const;
+    LayoutSize cachedSizeForOverflowClip() const;
+    void applyCachedClipAndScrollOffsetForRepaint(LayoutRect& paintRect) const;
+
+    virtual bool hasRelativeDimensions() const;
+    virtual bool hasRelativeLogicalHeight() const;
+    bool hasViewportPercentageLogicalHeight() const;
+
+    bool hasHorizontalLayoutOverflow() const
+    {
+        if (RenderOverflow* overflow = hasRenderOverflow()) {
+            LayoutRect layoutOverflowRect = overflow->layoutOverflowRect();
+            flipForWritingMode(layoutOverflowRect);
+            return layoutOverflowRect.x() < x() || layoutOverflowRect.maxX() > x() + logicalWidth();
+        }
+
+        return false;
+    }
+
+    bool hasVerticalLayoutOverflow() const
+    {
+        if (RenderOverflow* overflow = hasRenderOverflow()) {
+            LayoutRect layoutOverflowRect = overflow->layoutOverflowRect();
+            flipForWritingMode(layoutOverflowRect);
+            return layoutOverflowRect.y() < y() || layoutOverflowRect.maxY() > y() + logicalHeight();
+        }
+
+        return false;
+    }
+
+    virtual RenderBox* createAnonymousBoxWithSameTypeAs(const RenderObject*) const
+    {
+        ASSERT_NOT_REACHED();
+        return 0;
+    }
+
+    bool hasSameDirectionAs(const RenderBox* object) const { return style()->direction() == object->style()->direction(); }
+
+    virtual void reportMemoryUsage(MemoryObjectInfo*) const OVERRIDE;
+    static void reportStaticMembersMemoryUsage(MemoryInstrumentation*);
+
+    ExclusionShapeOutsideInfo* exclusionShapeOutsideInfo() const
+    {
+        return isFloatingWithShapeOutside() && ExclusionShapeOutsideInfo::isEnabledFor(this) ? ExclusionShapeOutsideInfo::info(this) : 0;
+    }
+
+protected:
+    virtual void willBeDestroyed();
+
+    virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle);
+    virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+    virtual void updateFromStyle() OVERRIDE;
+
+    LayoutRect backgroundPaintedExtent() const;
+    virtual bool foregroundIsKnownToBeOpaqueInRect(const LayoutRect& localRect, unsigned maxDepthToTest) const;
+    virtual bool computeBackgroundIsKnownToBeObscured() OVERRIDE;
+
+    void paintBackground(const PaintInfo&, const LayoutRect&, BackgroundBleedAvoidance = BackgroundBleedNone);
+    
+    void paintFillLayer(const PaintInfo&, const Color&, const FillLayer*, const LayoutRect&, BackgroundBleedAvoidance, CompositeOperator, RenderObject* backgroundObject);
+    void paintFillLayers(const PaintInfo&, const Color&, const FillLayer*, const LayoutRect&, BackgroundBleedAvoidance = BackgroundBleedNone, CompositeOperator = CompositeSourceOver, RenderObject* backgroundObject = 0);
+
+    void paintMaskImages(const PaintInfo&, const LayoutRect&);
+
+    BackgroundBleedAvoidance determineBackgroundBleedAvoidance(GraphicsContext*) const;
+    bool backgroundHasOpaqueTopLayer() const;
+
+    void computePositionedLogicalWidth(LogicalExtentComputedValues&, RenderRegion* = 0, LayoutUnit offsetFromLogicalTopOfFirstPage = 0) const;
+
+    LayoutUnit computeIntrinsicLogicalWidthUsing(Length logicalWidthLength, LayoutUnit availableLogicalWidth, LayoutUnit borderAndPadding) const;
+    LayoutUnit computeIntrinsicLogicalContentHeightUsing(Length logicalHeightLength, LayoutUnit intrinsicContentHeight, LayoutUnit borderAndPadding) const;
+    
+    virtual bool shouldComputeSizeAsReplaced() const { return isReplaced() && !isInlineBlockOrInlineTable(); }
+
+    virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = 0) const OVERRIDE;
+    virtual const RenderObject* pushMappingToContainer(const RenderLayerModelObject*, RenderGeometryMap&) const OVERRIDE;
+    virtual void mapAbsoluteToLocalPoint(MapCoordinatesFlags, TransformState&) const;
+
+    void paintRootBoxFillLayers(const PaintInfo&);
+
+    RenderObject* splitAnonymousBoxesAroundChild(RenderObject* beforeChild);
+ 
+private:
+    void updateExclusionShapeOutsideInfoAfterStyleChange(const ExclusionShapeValue* shapeOutside, const ExclusionShapeValue* oldShapeOutside);
+
+    bool includeVerticalScrollbarSize() const;
+    bool includeHorizontalScrollbarSize() const;
+
+    // Returns true if we did a full repaint
+    bool repaintLayerRectsForImage(WrappedImagePtr image, const FillLayer* layers, bool drawingBackground);
+
+    bool skipContainingBlockForPercentHeightCalculation(const RenderBox* containingBlock) const;
+   
+    LayoutUnit containingBlockLogicalWidthForPositioned(const RenderBoxModelObject* containingBlock, RenderRegion* = 0,
+        LayoutUnit offsetFromLogicalTopOfFirstPage = 0, bool checkForPerpendicularWritingMode = true) const;
+    LayoutUnit containingBlockLogicalHeightForPositioned(const RenderBoxModelObject* containingBlock, bool checkForPerpendicularWritingMode = true) const;
+
+    LayoutUnit viewLogicalHeightForPercentages() const;
+
+    void computePositionedLogicalHeight(LogicalExtentComputedValues&) const;
+    void computePositionedLogicalWidthUsing(Length logicalWidth, const RenderBoxModelObject* containerBlock, TextDirection containerDirection,
+                                            LayoutUnit containerLogicalWidth, LayoutUnit bordersPlusPadding,
+                                            Length logicalLeft, Length logicalRight, Length marginLogicalLeft, Length marginLogicalRight,
+                                            LogicalExtentComputedValues&) const;
+    void computePositionedLogicalHeightUsing(Length logicalHeightLength, const RenderBoxModelObject* containerBlock,
+                                             LayoutUnit containerLogicalHeight, LayoutUnit bordersPlusPadding, LayoutUnit logicalHeight,
+                                             Length logicalTop, Length logicalBottom, Length marginLogicalTop, Length marginLogicalBottom,
+                                             LogicalExtentComputedValues&) const;
+
+    void computePositionedLogicalHeightReplaced(LogicalExtentComputedValues&) const;
+    void computePositionedLogicalWidthReplaced(LogicalExtentComputedValues&) const;
+
+    LayoutUnit fillAvailableMeasure(LayoutUnit availableLogicalWidth) const;
+    LayoutUnit fillAvailableMeasure(LayoutUnit availableLogicalWidth, LayoutUnit& marginStart, LayoutUnit& marginEnd) const;
+
+    virtual void computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const;
+
+    // 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 computePreferredLogicalWidths() { setPreferredLogicalWidthsDirty(false); }
+
+    virtual LayoutRect frameRectForStickyPositioning() const OVERRIDE FINAL { return frameRect(); }
+
+private:
+    // The width/height of the contents + borders + padding.  The x/y location is relative to our container (which is not always our parent).
+    LayoutRect m_frameRect;
+
+protected:
+    LayoutBoxExtent m_marginBox;
+
+    // The preferred logical width of the element if it were to break its lines at every possible opportunity.
+    LayoutUnit m_minPreferredLogicalWidth;
+    
+    // The preferred logical width of the element if it never breaks any lines at all.
+    LayoutUnit m_maxPreferredLogicalWidth;
+
+    // For inline replaced elements, the inline box that owns us.
+    InlineBox* m_inlineBoxWrapper;
+
+    // Our overflow information.
+    OwnPtr<RenderOverflow> m_overflow;
+
+private:
+    // Used to store state between styleWillChange and styleDidChange
+    static bool s_hadOverflowClip;
+};
+
+inline RenderBox* toRenderBox(RenderObject* object)
+{ 
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isBox());
+    return static_cast<RenderBox*>(object);
+}
+
+inline const RenderBox* toRenderBox(const RenderObject* object)
+{ 
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isBox());
+    return static_cast<const RenderBox*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderBox(const RenderBox*);
+
+inline RenderBox* RenderBox::previousSiblingBox() const
+{
+    return toRenderBox(previousSibling());
+}
+
+inline RenderBox* RenderBox::nextSiblingBox() const
+{ 
+    return toRenderBox(nextSibling());
+}
+
+inline RenderBox* RenderBox::parentBox() const
+{
+    return toRenderBox(parent());
+}
+
+inline RenderBox* RenderBox::firstChildBox() const
+{
+    return toRenderBox(firstChild());
+}
+
+inline RenderBox* RenderBox::lastChildBox() const
+{
+    return toRenderBox(lastChild());
+}
+
+} // namespace WebCore
+
+#endif // RenderBox_h
diff --git a/Source/core/rendering/RenderBoxModelObject.cpp b/Source/core/rendering/RenderBoxModelObject.cpp
new file mode 100644
index 0000000..a811c9d
--- /dev/null
+++ b/Source/core/rendering/RenderBoxModelObject.cpp
@@ -0,0 +1,2663 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
+ *           (C) 2005, 2006 Samuel Weinig (sam.weinig@gmail.com)
+ * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2010 Google 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 "core/rendering/RenderBoxModelObject.h"
+
+#include "HTMLNames.h"
+#include "core/html/HTMLFrameOwnerElement.h"
+#include "core/page/Page.h"
+#include "core/page/Settings.h"
+#include "core/page/scrolling/ScrollingConstraints.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/platform/graphics/ImageBuffer.h"
+#include "core/platform/graphics/Path.h"
+#include "core/platform/graphics/transforms/TransformState.h"
+#include "core/rendering/ImageQualityController.h"
+#include "core/rendering/RenderBlock.h"
+#include "core/rendering/RenderInline.h"
+#include "core/rendering/RenderLayer.h"
+#include "core/rendering/RenderLayerBacking.h"
+#include "core/rendering/RenderLayerCompositor.h"
+#include "core/rendering/RenderView.h"
+#include <wtf/CurrentTime.h>
+
+using namespace std;
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+// The HashMap for storing continuation pointers.
+// An inline can be split with blocks occuring in between the inline content.
+// When this occurs we need a pointer to the 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.
+// <b><i><p>Hello</p></i></b>. In this example the <i> will have a block as
+// its continuation but the <b> will just have an inline as its continuation.
+typedef HashMap<const RenderBoxModelObject*, RenderBoxModelObject*> ContinuationMap;
+static ContinuationMap* continuationMap = 0;
+
+// This HashMap is similar to the continuation map, but connects first-letter
+// renderers to their remaining text fragments.
+typedef HashMap<const RenderBoxModelObject*, RenderObject*> FirstLetterRemainingTextMap;
+static FirstLetterRemainingTextMap* firstLetterRemainingTextMap = 0;
+
+void RenderBoxModelObject::setSelectionState(SelectionState state)
+{
+    if (state == SelectionInside && selectionState() != SelectionNone)
+        return;
+
+    if ((state == SelectionStart && selectionState() == SelectionEnd)
+        || (state == SelectionEnd && selectionState() == SelectionStart))
+        RenderObject::setSelectionState(SelectionBoth);
+    else
+        RenderObject::setSelectionState(state);
+
+    // FIXME: We should consider whether it is OK propagating to ancestor RenderInlines.
+    // This is a workaround for http://webkit.org/b/32123
+    // The containing block can be null in case of an orphaned tree.
+    RenderBlock* containingBlock = this->containingBlock();
+    if (containingBlock && !containingBlock->isRenderView())
+        containingBlock->setSelectionState(state);
+}
+
+void RenderBoxModelObject::contentChanged(ContentChangeType changeType)
+{
+    if (!hasLayer())
+        return;
+
+    layer()->contentChanged(changeType);
+}
+
+bool RenderBoxModelObject::hasAcceleratedCompositing() const
+{
+    return view()->compositor()->hasAcceleratedCompositing();
+}
+
+bool RenderBoxModelObject::startTransition(double timeOffset, CSSPropertyID propertyId, const RenderStyle* fromStyle, const RenderStyle* toStyle)
+{
+    ASSERT(hasLayer());
+    ASSERT(isComposited());
+    return layer()->backing()->startTransition(timeOffset, propertyId, fromStyle, toStyle);
+}
+
+void RenderBoxModelObject::transitionPaused(double timeOffset, CSSPropertyID propertyId)
+{
+    ASSERT(hasLayer());
+    ASSERT(isComposited());
+    layer()->backing()->transitionPaused(timeOffset, propertyId);
+}
+
+void RenderBoxModelObject::transitionFinished(CSSPropertyID propertyId)
+{
+    ASSERT(hasLayer());
+    ASSERT(isComposited());
+    layer()->backing()->transitionFinished(propertyId);
+}
+
+bool RenderBoxModelObject::startAnimation(double timeOffset, const CSSAnimationData* animation, const KeyframeList& keyframes)
+{
+    ASSERT(hasLayer());
+    ASSERT(isComposited());
+    return layer()->backing()->startAnimation(timeOffset, animation, keyframes);
+}
+
+void RenderBoxModelObject::animationPaused(double timeOffset, const String& name)
+{
+    ASSERT(hasLayer());
+    ASSERT(isComposited());
+    layer()->backing()->animationPaused(timeOffset, name);
+}
+
+void RenderBoxModelObject::animationFinished(const String& name)
+{
+    ASSERT(hasLayer());
+    ASSERT(isComposited());
+    layer()->backing()->animationFinished(name);
+}
+
+void RenderBoxModelObject::suspendAnimations(double time)
+{
+    ASSERT(hasLayer());
+    ASSERT(isComposited());
+    layer()->backing()->suspendAnimations(time);
+}
+
+bool RenderBoxModelObject::shouldPaintAtLowQuality(GraphicsContext* context, Image* image, const void* layer, const LayoutSize& size)
+{
+    return ImageQualityController::imageQualityController()->shouldPaintAtLowQuality(context, this, image, layer, size);
+}
+
+RenderBoxModelObject::RenderBoxModelObject(ContainerNode* node)
+    : RenderLayerModelObject(node)
+{
+}
+
+RenderBoxModelObject::~RenderBoxModelObject()
+{
+    ImageQualityController::remove(this);
+}
+
+void RenderBoxModelObject::willBeDestroyed()
+{
+    // A continuation of this RenderObject should be destroyed at subclasses.
+    ASSERT(!continuation());
+
+    // If this is a first-letter object with a remaining text fragment then the
+    // entry needs to be cleared from the map.
+    if (firstLetterRemainingText())
+        setFirstLetterRemainingText(0);
+
+    RenderLayerModelObject::willBeDestroyed();
+}
+
+void RenderBoxModelObject::updateFromStyle()
+{
+    RenderLayerModelObject::updateFromStyle();
+
+    // Set the appropriate bits for a box model object.  Since all bits are cleared in styleWillChange,
+    // we only check for bits that could possibly be set to true.
+    RenderStyle* styleToUse = style();
+    setHasBoxDecorations(hasBackground() || styleToUse->hasBorder() || styleToUse->hasAppearance() || styleToUse->boxShadow());
+    setInline(styleToUse->isDisplayInlineType());
+    setPositionState(styleToUse->position());
+    setHorizontalWritingMode(styleToUse->isHorizontalWritingMode());
+}
+
+static LayoutSize accumulateInFlowPositionOffsets(const RenderObject* child)
+{
+    if (!child->isAnonymousBlock() || !child->isInFlowPositioned())
+        return LayoutSize();
+    LayoutSize offset;
+    RenderObject* p = toRenderBlock(child)->inlineElementContinuation();
+    while (p && p->isRenderInline()) {
+        if (p->isInFlowPositioned()) {
+            RenderInline* renderInline = toRenderInline(p);
+            offset += renderInline->offsetForInFlowPosition();
+        }
+        p = p->parent();
+    }
+    return offset;
+}
+
+bool RenderBoxModelObject::hasAutoHeightOrContainingBlockWithAutoHeight() const
+{
+    Length logicalHeightLength = style()->logicalHeight();
+    if (logicalHeightLength.isAuto())
+        return true;
+
+    // For percentage heights: The percentage is calculated with respect to the height of the generated box's
+    // containing block. If the height of the containing block is not specified explicitly (i.e., it depends
+    // on content height), and this element is not absolutely positioned, the value computes to 'auto'.
+    if (!logicalHeightLength.isPercent() || isOutOfFlowPositioned() || document()->inQuirksMode())
+        return false;
+
+    // Anonymous block boxes are ignored when resolving percentage values that would refer to it:
+    // the closest non-anonymous ancestor box is used instead.
+    RenderBlock* cb = containingBlock(); 
+    while (cb->isAnonymous())
+        cb = cb->containingBlock();
+
+    // Matching RenderBox::percentageLogicalHeightIsResolvableFromBlock() by
+    // ignoring table cell's attribute value, where it says that 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.
+    if (cb->isTableCell())
+        return false;
+    
+    if (!cb->style()->logicalHeight().isAuto() || (!cb->style()->logicalTop().isAuto() && !cb->style()->logicalBottom().isAuto()))
+        return false;
+
+    return true;
+}
+
+LayoutSize RenderBoxModelObject::relativePositionOffset() const
+{
+    LayoutSize offset = accumulateInFlowPositionOffsets(this);
+
+    RenderBlock* containingBlock = this->containingBlock();
+
+    // Objects that shrink to avoid floats normally use available line width when computing containing block width.  However
+    // in the case of relative positioning using percentages, we can't do this.  The offset should always be resolved using the
+    // available width of the containing block.  Therefore we don't use containingBlockLogicalWidthForContent() here, but instead explicitly
+    // call availableWidth on our containing block.
+    if (!style()->left().isAuto()) {
+        if (!style()->right().isAuto() && !containingBlock->style()->isLeftToRightDirection())
+            offset.setWidth(-valueForLength(style()->right(), containingBlock->availableWidth(), view()));
+        else
+            offset.expand(valueForLength(style()->left(), containingBlock->availableWidth(), view()), 0);
+    } else if (!style()->right().isAuto()) {
+        offset.expand(-valueForLength(style()->right(), containingBlock->availableWidth(), view()), 0);
+    }
+
+    // If the containing block of a relatively positioned element does not
+    // specify a height, a percentage top or bottom offset should be resolved as
+    // auto. An exception to this is if the containing block has the WinIE quirk
+    // where <html> and <body> assume the size of the viewport. In this case,
+    // calculate the percent offset based on this height.
+    // See <https://bugs.webkit.org/show_bug.cgi?id=26396>.
+    if (!style()->top().isAuto()
+        && (!containingBlock->hasAutoHeightOrContainingBlockWithAutoHeight()
+            || !style()->top().isPercent()
+            || containingBlock->stretchesToViewport()))
+        offset.expand(0, valueForLength(style()->top(), containingBlock->availableHeight(), view()));
+
+    else if (!style()->bottom().isAuto()
+        && (!containingBlock->hasAutoHeightOrContainingBlockWithAutoHeight()
+            || !style()->bottom().isPercent()
+            || containingBlock->stretchesToViewport()))
+        offset.expand(0, -valueForLength(style()->bottom(), containingBlock->availableHeight(), view()));
+
+    return offset;
+}
+
+LayoutPoint RenderBoxModelObject::adjustedPositionRelativeToOffsetParent(const LayoutPoint& startPoint) const
+{
+    // If the element is the HTML body element or doesn't have a parent
+    // return 0 and stop this algorithm.
+    if (isBody() || !parent())
+        return LayoutPoint();
+
+    LayoutPoint referencePoint = startPoint;
+    referencePoint.move(parent()->offsetForColumns(referencePoint));
+    
+    // If the offsetParent of the element is null, or is the HTML body element,
+    // return the distance between the canvas origin and the left border edge 
+    // of the element and stop this algorithm.
+    Element* element = offsetParent();
+    if (!element)
+        return referencePoint;
+
+    if (const RenderBoxModelObject* offsetParent = element->renderBoxModelObject()) {
+        if (offsetParent->isBox() && !offsetParent->isBody())
+            referencePoint.move(-toRenderBox(offsetParent)->borderLeft(), -toRenderBox(offsetParent)->borderTop());
+        if (!isOutOfFlowPositioned()) {
+            if (isRelPositioned())
+                referencePoint.move(relativePositionOffset());
+            else if (isStickyPositioned())
+                referencePoint.move(stickyPositionOffset());
+
+            for (const RenderObject* current = parent(); current != offsetParent && current->parent(); current = current->parent()) {
+                // FIXME: What are we supposed to do inside SVG content?
+                if (current->isBox() && !current->isTableRow())
+                    referencePoint.moveBy(toRenderBox(current)->topLeftLocation());
+                referencePoint.move(current->parent()->offsetForColumns(referencePoint));
+            }
+            if (offsetParent->isBox() && offsetParent->isBody() && !offsetParent->isPositioned())
+                referencePoint.moveBy(toRenderBox(offsetParent)->topLeftLocation());
+        }
+    }
+
+    return referencePoint;
+}
+
+void RenderBoxModelObject::computeStickyPositionConstraints(StickyPositionViewportConstraints& constraints, const FloatRect& viewportRect) const
+{
+    RenderBlock* containingBlock = this->containingBlock();
+
+    LayoutRect containerContentRect = containingBlock->contentBoxRect();
+    LayoutUnit maxWidth = containingBlock->availableLogicalWidth();
+
+    // Sticky positioned element ignore any override logical width on the containing block (as they don't call
+    // containingBlockLogicalWidthForContent). It's unclear whether this is totally fine.
+    LayoutBoxExtent minMargin(minimumValueForLength(style()->marginTop(), maxWidth, view()),
+        minimumValueForLength(style()->marginRight(), maxWidth, view()),
+        minimumValueForLength(style()->marginBottom(), maxWidth, view()),
+        minimumValueForLength(style()->marginLeft(), maxWidth, view()));
+
+    // Compute the container-relative area within which the sticky element is allowed to move.
+    containerContentRect.contract(minMargin);
+    // Map to the view to avoid including page scale factor.
+    constraints.setAbsoluteContainingBlockRect(containingBlock->localToContainerQuad(FloatRect(containerContentRect), view()).boundingBox());
+
+    LayoutRect stickyBoxRect = frameRectForStickyPositioning();
+    LayoutRect flippedStickyBoxRect = stickyBoxRect;
+    containingBlock->flipForWritingMode(flippedStickyBoxRect);
+    LayoutPoint stickyLocation = flippedStickyBoxRect.location();
+
+    // FIXME: sucks to call localToAbsolute again, but we can't just offset from the previously computed rect if there are transforms.
+    // Map to the view to avoid including page scale factor.
+    FloatRect absContainerFrame = containingBlock->localToContainerQuad(FloatRect(FloatPoint(), containingBlock->size()), view()).boundingBox();
+
+    // We can't call localToAbsolute on |this| because that will recur. FIXME: For now, assume that |this| is not transformed.
+    FloatRect absoluteStickyBoxRect(absContainerFrame.location() + stickyLocation, flippedStickyBoxRect.size());
+    constraints.setAbsoluteStickyBoxRect(absoluteStickyBoxRect);
+
+    if (!style()->left().isAuto()) {
+        constraints.setLeftOffset(valueForLength(style()->left(), viewportRect.width(), view()));
+        constraints.addAnchorEdge(ViewportConstraints::AnchorEdgeLeft);
+    }
+
+    if (!style()->right().isAuto()) {
+        constraints.setRightOffset(valueForLength(style()->right(), viewportRect.width(), view()));
+        constraints.addAnchorEdge(ViewportConstraints::AnchorEdgeRight);
+    }
+
+    if (!style()->top().isAuto()) {
+        constraints.setTopOffset(valueForLength(style()->top(), viewportRect.height(), view()));
+        constraints.addAnchorEdge(ViewportConstraints::AnchorEdgeTop);
+    }
+
+    if (!style()->bottom().isAuto()) {
+        constraints.setBottomOffset(valueForLength(style()->bottom(), viewportRect.height(), view()));
+        constraints.addAnchorEdge(ViewportConstraints::AnchorEdgeBottom);
+    }
+}
+
+LayoutSize RenderBoxModelObject::stickyPositionOffset() const
+{
+    LayoutRect viewportRect = view()->frameView()->viewportConstrainedVisibleContentRect();
+    
+    StickyPositionViewportConstraints constraints;
+    computeStickyPositionConstraints(constraints, viewportRect);
+    
+    // The sticky offset is physical, so we can just return the delta computed in absolute coords (though it may be wrong with transforms).
+    return LayoutSize(constraints.computeStickyOffset(viewportRect));
+}
+
+LayoutSize RenderBoxModelObject::offsetForInFlowPosition() const
+{
+    if (isRelPositioned())
+        return relativePositionOffset();
+
+    if (isStickyPositioned())
+        return stickyPositionOffset();
+
+    return LayoutSize();
+}
+
+LayoutSize RenderBoxModelObject::paintOffset() const
+{
+    LayoutSize offset = offsetForInFlowPosition();
+
+    if (isBox() && isFloating())
+        if (ExclusionShapeOutsideInfo* shapeOutside = toRenderBox(this)->exclusionShapeOutsideInfo())
+            offset -= shapeOutside->shapeLogicalOffset();
+
+    return offset;
+}
+
+LayoutUnit RenderBoxModelObject::offsetLeft() const
+{
+    // Note that RenderInline and RenderBox override this to pass a different
+    // startPoint to adjustedPositionRelativeToOffsetParent.
+    return adjustedPositionRelativeToOffsetParent(LayoutPoint()).x();
+}
+
+LayoutUnit RenderBoxModelObject::offsetTop() const
+{
+    // Note that RenderInline and RenderBox override this to pass a different
+    // startPoint to adjustedPositionRelativeToOffsetParent.
+    return adjustedPositionRelativeToOffsetParent(LayoutPoint()).y();
+}
+
+int RenderBoxModelObject::pixelSnappedOffsetWidth() const
+{
+    return snapSizeToPixel(offsetWidth(), offsetLeft());
+}
+
+int RenderBoxModelObject::pixelSnappedOffsetHeight() const
+{
+    return snapSizeToPixel(offsetHeight(), offsetTop());
+}
+
+LayoutUnit RenderBoxModelObject::computedCSSPadding(Length padding) const
+{
+    LayoutUnit w = 0;
+    RenderView* renderView = 0;
+    if (padding.isPercent())
+        w = containingBlockLogicalWidthForContent();
+    else if (padding.isViewportPercentage())
+        renderView = view();
+    return minimumValueForLength(padding, w, renderView);
+}
+
+RoundedRect RenderBoxModelObject::getBackgroundRoundedRect(const LayoutRect& borderRect, InlineFlowBox* box, LayoutUnit inlineBoxWidth, LayoutUnit inlineBoxHeight,
+    bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
+{
+    RenderView* renderView = view();
+    RoundedRect border = style()->getRoundedBorderFor(borderRect, renderView, includeLogicalLeftEdge, includeLogicalRightEdge);
+    if (box && (box->nextLineBox() || box->prevLineBox())) {
+        RoundedRect segmentBorder = style()->getRoundedBorderFor(LayoutRect(0, 0, inlineBoxWidth, inlineBoxHeight), renderView, includeLogicalLeftEdge, includeLogicalRightEdge);
+        border.setRadii(segmentBorder.radii());
+    }
+
+    return border;
+}
+
+void RenderBoxModelObject::clipRoundedInnerRect(GraphicsContext * context, const LayoutRect& rect, const RoundedRect& clipRect)
+{
+    if (clipRect.isRenderable())
+        context->clipRoundedRect(clipRect);
+    else {
+        // We create a rounded rect for each of the corners and clip it, while making sure we clip opposing corners together.
+        if (!clipRect.radii().topLeft().isEmpty() || !clipRect.radii().bottomRight().isEmpty()) {
+            IntRect topCorner(clipRect.rect().x(), clipRect.rect().y(), rect.maxX() - clipRect.rect().x(), rect.maxY() - clipRect.rect().y());
+            RoundedRect::Radii topCornerRadii;
+            topCornerRadii.setTopLeft(clipRect.radii().topLeft());
+            context->clipRoundedRect(RoundedRect(topCorner, topCornerRadii));
+
+            IntRect bottomCorner(rect.x(), rect.y(), clipRect.rect().maxX() - rect.x(), clipRect.rect().maxY() - rect.y());
+            RoundedRect::Radii bottomCornerRadii;
+            bottomCornerRadii.setBottomRight(clipRect.radii().bottomRight());
+            context->clipRoundedRect(RoundedRect(bottomCorner, bottomCornerRadii));
+        } 
+
+        if (!clipRect.radii().topRight().isEmpty() || !clipRect.radii().bottomLeft().isEmpty()) {
+            IntRect topCorner(rect.x(), clipRect.rect().y(), clipRect.rect().maxX() - rect.x(), rect.maxY() - clipRect.rect().y());
+            RoundedRect::Radii topCornerRadii;
+            topCornerRadii.setTopRight(clipRect.radii().topRight());
+            context->clipRoundedRect(RoundedRect(topCorner, topCornerRadii));
+
+            IntRect bottomCorner(clipRect.rect().x(), rect.y(), rect.maxX() - clipRect.rect().x(), clipRect.rect().maxY() - rect.y());
+            RoundedRect::Radii bottomCornerRadii;
+            bottomCornerRadii.setBottomLeft(clipRect.radii().bottomLeft());
+            context->clipRoundedRect(RoundedRect(bottomCorner, bottomCornerRadii));
+        }
+    }
+}
+
+static LayoutRect shrinkRectByOnePixel(GraphicsContext* context, const LayoutRect& rect)
+{
+    LayoutRect shrunkRect = rect;
+    AffineTransform transform = context->getCTM();
+    shrunkRect.inflateX(-static_cast<LayoutUnit>(ceil(1 / transform.xScale())));
+    shrunkRect.inflateY(-static_cast<LayoutUnit>(ceil(1 / transform.yScale())));
+    return shrunkRect;
+}
+
+LayoutRect RenderBoxModelObject::borderInnerRectAdjustedForBleedAvoidance(GraphicsContext* context, const LayoutRect& rect, BackgroundBleedAvoidance bleedAvoidance) const
+{
+    // We shrink the rectangle by one pixel on each side to make it fully overlap the anti-aliased background border
+    return (bleedAvoidance == BackgroundBleedBackgroundOverBorder) ? shrinkRectByOnePixel(context, rect) : rect;
+}
+
+RoundedRect RenderBoxModelObject::backgroundRoundedRectAdjustedForBleedAvoidance(GraphicsContext* context, const LayoutRect& borderRect, BackgroundBleedAvoidance bleedAvoidance, InlineFlowBox* box, const LayoutSize& boxSize, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
+{
+    if (bleedAvoidance == BackgroundBleedShrinkBackground) {
+        // We shrink the rectangle by one pixel on each side because the bleed is one pixel maximum.
+        return getBackgroundRoundedRect(shrinkRectByOnePixel(context, borderRect), box, boxSize.width(), boxSize.height(), includeLogicalLeftEdge, includeLogicalRightEdge);
+    }
+    if (bleedAvoidance == BackgroundBleedBackgroundOverBorder)
+        return style()->getRoundedInnerBorderFor(borderRect, includeLogicalLeftEdge, includeLogicalRightEdge);
+
+    return getBackgroundRoundedRect(borderRect, box, boxSize.width(), boxSize.height(), includeLogicalLeftEdge, includeLogicalRightEdge);
+}
+
+static void applyBoxShadowForBackground(GraphicsContext* context, RenderStyle* style)
+{
+    const ShadowData* boxShadow = style->boxShadow();
+    while (boxShadow->style() != Normal)
+        boxShadow = boxShadow->next();
+
+    FloatSize shadowOffset(boxShadow->x(), boxShadow->y());
+    if (!boxShadow->isWebkitBoxShadow())
+        context->setShadow(shadowOffset, boxShadow->blur(), boxShadow->color(), style->colorSpace());
+    else
+        context->setLegacyShadow(shadowOffset, boxShadow->blur(), boxShadow->color(), style->colorSpace());
+}
+
+void RenderBoxModelObject::paintFillLayerExtended(const PaintInfo& paintInfo, const Color& color, const FillLayer* bgLayer, const LayoutRect& rect,
+    BackgroundBleedAvoidance bleedAvoidance, InlineFlowBox* box, const LayoutSize& boxSize, CompositeOperator op, RenderObject* backgroundObject)
+{
+    GraphicsContext* context = paintInfo.context;
+    if (context->paintingDisabled() || rect.isEmpty())
+        return;
+
+    bool includeLeftEdge = box ? box->includeLogicalLeftEdge() : true;
+    bool includeRightEdge = box ? box->includeLogicalRightEdge() : true;
+
+    bool hasRoundedBorder = style()->hasBorderRadius() && (includeLeftEdge || includeRightEdge);
+    bool clippedWithLocalScrolling = hasOverflowClip() && bgLayer->attachment() == LocalBackgroundAttachment;
+    bool isBorderFill = bgLayer->clip() == BorderFillBox;
+    bool isRoot = this->isRoot();
+
+    Color bgColor = color;
+    StyleImage* bgImage = bgLayer->image();
+    bool shouldPaintBackgroundImage = bgImage && bgImage->canRender(this, style()->effectiveZoom());
+    
+    bool forceBackgroundToWhite = false;
+    if (document()->printing()) {
+        if (style()->printColorAdjust() == PrintColorAdjustEconomy)
+            forceBackgroundToWhite = true;
+        if (document()->settings() && document()->settings()->shouldPrintBackgrounds())
+            forceBackgroundToWhite = false;
+    }
+
+    // When printing backgrounds is disabled or using economy mode,
+    // 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 (forceBackgroundToWhite) {
+        // Note that we can't reuse this variable below because the bgColor might be changed
+        bool shouldPaintBackgroundColor = !bgLayer->next() && bgColor.isValid() && bgColor.alpha();
+        if (shouldPaintBackgroundImage || shouldPaintBackgroundColor) {
+            bgColor = Color::white;
+            shouldPaintBackgroundImage = false;
+        }
+    }
+
+    bool colorVisible = bgColor.isValid() && bgColor.alpha();
+    
+    // Fast path for drawing simple color backgrounds.
+    if (!isRoot && !clippedWithLocalScrolling && !shouldPaintBackgroundImage && isBorderFill && !bgLayer->next()) {
+        if (!colorVisible)
+            return;
+
+        bool boxShadowShouldBeAppliedToBackground = this->boxShadowShouldBeAppliedToBackground(bleedAvoidance, box);
+        GraphicsContextStateSaver shadowStateSaver(*context, boxShadowShouldBeAppliedToBackground);
+        if (boxShadowShouldBeAppliedToBackground)
+            applyBoxShadowForBackground(context, style());
+
+        if (hasRoundedBorder && bleedAvoidance != BackgroundBleedUseTransparencyLayer) {
+            RoundedRect border = backgroundRoundedRectAdjustedForBleedAvoidance(context, rect, bleedAvoidance, box, boxSize, includeLeftEdge, includeRightEdge);
+            if (border.isRenderable())
+                context->fillRoundedRect(border, bgColor, style()->colorSpace());
+            else {
+                context->save();
+                clipRoundedInnerRect(context, rect, border);
+                context->fillRect(border.rect(), bgColor, style()->colorSpace());
+                context->restore();
+            }
+        } else
+            context->fillRect(pixelSnappedIntRect(rect), bgColor, style()->colorSpace());
+        
+        return;
+    }
+
+    // BorderFillBox radius clipping is taken care of by BackgroundBleedUseTransparencyLayer
+    bool clipToBorderRadius = hasRoundedBorder && !(isBorderFill && bleedAvoidance == BackgroundBleedUseTransparencyLayer);
+    GraphicsContextStateSaver clipToBorderStateSaver(*context, clipToBorderRadius);
+    if (clipToBorderRadius) {
+        RoundedRect border = isBorderFill ? backgroundRoundedRectAdjustedForBleedAvoidance(context, rect, bleedAvoidance, box, boxSize, includeLeftEdge, includeRightEdge) : getBackgroundRoundedRect(rect, box, boxSize.width(), boxSize.height(), includeLeftEdge, includeRightEdge);
+
+        // Clip to the padding or content boxes as necessary.
+        if (bgLayer->clip() == ContentFillBox) {
+            border = style()->getRoundedInnerBorderFor(border.rect(),
+                paddingTop() + borderTop(), paddingBottom() + borderBottom(), paddingLeft() + borderLeft(), paddingRight() + borderRight(), includeLeftEdge, includeRightEdge);
+        } else if (bgLayer->clip() == PaddingFillBox)
+            border = style()->getRoundedInnerBorderFor(border.rect(), includeLeftEdge, includeRightEdge);
+
+        clipRoundedInnerRect(context, rect, border);
+    }
+    
+    int bLeft = includeLeftEdge ? borderLeft() : 0;
+    int bRight = includeRightEdge ? borderRight() : 0;
+    LayoutUnit pLeft = includeLeftEdge ? paddingLeft() : LayoutUnit();
+    LayoutUnit pRight = includeRightEdge ? paddingRight() : LayoutUnit();
+
+    GraphicsContextStateSaver clipWithScrollingStateSaver(*context, clippedWithLocalScrolling);
+    LayoutRect scrolledPaintRect = rect;
+    if (clippedWithLocalScrolling) {
+        // Clip to the overflow area.
+        RenderBox* thisBox = toRenderBox(this);
+        context->clip(thisBox->overflowClipRect(rect.location(), paintInfo.renderRegion));
+        
+        // Adjust the paint rect to reflect a scrolled content box with borders at the ends.
+        IntSize offset = thisBox->scrolledContentOffset();
+        scrolledPaintRect.move(-offset);
+        scrolledPaintRect.setWidth(bLeft + layer()->scrollWidth() + bRight);
+        scrolledPaintRect.setHeight(borderTop() + layer()->scrollHeight() + borderBottom());
+    }
+    
+    GraphicsContextStateSaver backgroundClipStateSaver(*context, false);
+    OwnPtr<ImageBuffer> maskImage;
+    IntRect maskRect;
+
+    if (bgLayer->clip() == PaddingFillBox || bgLayer->clip() == ContentFillBox) {
+        // Clip to the padding or content boxes as necessary.
+        if (!clipToBorderRadius) {
+            bool includePadding = bgLayer->clip() == ContentFillBox;
+            LayoutRect clipRect = LayoutRect(scrolledPaintRect.x() + bLeft + (includePadding ? pLeft : LayoutUnit()),
+                scrolledPaintRect.y() + borderTop() + (includePadding ? paddingTop() : LayoutUnit()),
+                scrolledPaintRect.width() - bLeft - bRight - (includePadding ? pLeft + pRight : LayoutUnit()),
+                scrolledPaintRect.height() - borderTop() - borderBottom() - (includePadding ? paddingTop() + paddingBottom() : LayoutUnit()));
+            backgroundClipStateSaver.save();
+            context->clip(clipRect);
+        }
+    } 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.
+        maskRect = pixelSnappedIntRect(rect);
+        maskRect.intersect(paintInfo.rect);
+
+        // Now create the mask.
+        maskImage = context->createCompatibleBuffer(maskRect.size());
+        if (!maskImage)
+            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, PaintBehaviorForceBlackText, 0, paintInfo.renderRegion);
+        if (box) {
+            RootInlineBox* root = box->root();
+            box->paint(info, LayoutPoint(scrolledPaintRect.x() - box->x(), scrolledPaintRect.y() - box->y()), root->lineTop(), root->lineBottom());
+        } else {
+            LayoutSize localOffset = isBox() ? toRenderBox(this)->locationOffset() : LayoutSize();
+            paint(info, scrolledPaintRect.location() - localOffset);
+        }
+
+        // The mask has been created.  Now we just need to clip to it.
+        backgroundClipStateSaver.save();
+        context->clip(maskRect);
+        context->beginTransparencyLayer(1);
+    }
+
+    // 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 isOpaqueRoot = false;
+    if (isRoot) {
+        isOpaqueRoot = true;
+        if (!bgLayer->next() && !(bgColor.isValid() && bgColor.alpha() == 255) && view()->frameView()) {
+            Element* ownerElement = document()->ownerElement();
+            if (ownerElement) {
+                if (!ownerElement->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();
+                    if (body) {
+                        // Can't scroll a frameset document anyway.
+                        isOpaqueRoot = body->hasLocalName(framesetTag);
+                    }
+#if ENABLE(SVG)
+                    else {
+                        // SVG documents and XML documents with SVG root nodes are transparent.
+                        isOpaqueRoot = !document()->hasSVGRootNode();
+                    }
+#endif
+                }
+            } else
+                isOpaqueRoot = !view()->frameView()->isTransparent();
+        }
+        view()->frameView()->setContentIsOpaque(isOpaqueRoot);
+    }
+
+    // Paint the color first underneath all images, culled if background image occludes it.
+    // FIXME: In the bgLayer->hasFiniteBounds() case, we could improve the culling test
+    // by verifying whether the background image covers the entire layout rect.
+    if (!bgLayer->next()) {
+        IntRect backgroundRect(pixelSnappedIntRect(scrolledPaintRect));
+        bool boxShadowShouldBeAppliedToBackground = this->boxShadowShouldBeAppliedToBackground(bleedAvoidance, box);
+        if (boxShadowShouldBeAppliedToBackground || !shouldPaintBackgroundImage || !bgLayer->hasOpaqueImage(this) || !bgLayer->hasRepeatXY()) {
+            if (!boxShadowShouldBeAppliedToBackground)
+                backgroundRect.intersect(paintInfo.rect);
+
+            // If we have an alpha and we are painting the root element, go ahead and blend with the base background color.
+            Color baseColor;
+            bool shouldClearBackground = false;
+            if (isOpaqueRoot) {
+                baseColor = view()->frameView()->baseBackgroundColor();
+                if (!baseColor.alpha())
+                    shouldClearBackground = true;
+            }
+
+            GraphicsContextStateSaver shadowStateSaver(*context, boxShadowShouldBeAppliedToBackground);
+            if (boxShadowShouldBeAppliedToBackground)
+                applyBoxShadowForBackground(context, style());
+
+            if (baseColor.alpha()) {
+                if (bgColor.alpha())
+                    baseColor = baseColor.blend(bgColor);
+
+                context->fillRect(backgroundRect, baseColor, style()->colorSpace(), CompositeCopy);
+            } else if (bgColor.alpha()) {
+                CompositeOperator operation = shouldClearBackground ? CompositeCopy : context->compositeOperation();
+                context->fillRect(backgroundRect, bgColor, style()->colorSpace(), operation);
+            } else if (shouldClearBackground)
+                context->clearRect(backgroundRect);
+        }
+    }
+
+    // no progressive loading of the background image
+    if (shouldPaintBackgroundImage) {
+        BackgroundImageGeometry geometry;
+        calculateBackgroundImageGeometry(bgLayer, scrolledPaintRect, geometry, backgroundObject);
+        geometry.clip(paintInfo.rect);
+        if (!geometry.destRect().isEmpty()) {
+            CompositeOperator compositeOp = op == CompositeSourceOver ? bgLayer->composite() : op;
+            RenderObject* clientForBackgroundImage = backgroundObject ? backgroundObject : this;
+            RefPtr<Image> image = bgImage->image(clientForBackgroundImage, geometry.tileSize());
+            bool useLowQualityScaling = shouldPaintAtLowQuality(context, image.get(), bgLayer, geometry.tileSize());
+            context->drawTiledImage(image.get(), style()->colorSpace(), geometry.destRect(), geometry.relativePhase(), geometry.tileSize(), 
+                compositeOp, useLowQualityScaling, bgLayer->blendMode());
+        }
+    }
+
+    if (bgLayer->clip() == TextFillBox) {
+        context->drawImageBuffer(maskImage.get(), ColorSpaceDeviceRGB, maskRect, CompositeDestinationIn);
+        context->endTransparencyLayer();
+    }
+}
+
+static inline int resolveWidthForRatio(int height, const FloatSize& intrinsicRatio)
+{
+    return ceilf(height * intrinsicRatio.width() / intrinsicRatio.height());
+}
+
+static inline int resolveHeightForRatio(int width, const FloatSize& intrinsicRatio)
+{
+    return ceilf(width * intrinsicRatio.height() / intrinsicRatio.width());
+}
+
+static inline IntSize resolveAgainstIntrinsicWidthOrHeightAndRatio(const IntSize& size, const FloatSize& intrinsicRatio, int useWidth, int useHeight)
+{
+    if (intrinsicRatio.isEmpty()) {
+        if (useWidth)
+            return IntSize(useWidth, size.height());
+        return IntSize(size.width(), useHeight);
+    }
+
+    if (useWidth)
+        return IntSize(useWidth, resolveHeightForRatio(useWidth, intrinsicRatio));
+    return IntSize(resolveWidthForRatio(useHeight, intrinsicRatio), useHeight);
+}
+
+static inline IntSize resolveAgainstIntrinsicRatio(const IntSize& size, const FloatSize& intrinsicRatio)
+{
+    // Two possible solutions: (size.width(), solutionHeight) or (solutionWidth, size.height())
+    // "... must be assumed to be the largest dimensions..." = easiest answer: the rect with the largest surface area.
+
+    int solutionWidth = resolveWidthForRatio(size.height(), intrinsicRatio);
+    int solutionHeight = resolveHeightForRatio(size.width(), intrinsicRatio);
+    if (solutionWidth <= size.width()) {
+        if (solutionHeight <= size.height()) {
+            // If both solutions fit, choose the one covering the larger area.
+            int areaOne = solutionWidth * size.height();
+            int areaTwo = size.width() * solutionHeight;
+            if (areaOne < areaTwo)
+                return IntSize(size.width(), solutionHeight);
+            return IntSize(solutionWidth, size.height());
+        }
+
+        // Only the first solution fits.
+        return IntSize(solutionWidth, size.height());
+    }
+
+    // Only the second solution fits, assert that.
+    ASSERT(solutionHeight <= size.height());
+    return IntSize(size.width(), solutionHeight);
+}
+
+IntSize RenderBoxModelObject::calculateImageIntrinsicDimensions(StyleImage* image, const IntSize& positioningAreaSize, ScaleByEffectiveZoomOrNot shouldScaleOrNot) const
+{
+    // A generated image without a fixed size, will always return the container size as intrinsic size.
+    if (image->isGeneratedImage() && image->usesImageContainerSize())
+        return IntSize(positioningAreaSize.width(), positioningAreaSize.height());
+
+    Length intrinsicWidth;
+    Length intrinsicHeight;
+    FloatSize intrinsicRatio;
+    image->computeIntrinsicDimensions(this, intrinsicWidth, intrinsicHeight, intrinsicRatio);
+
+    // Intrinsic dimensions expressed as percentages must be resolved relative to the dimensions of the rectangle
+    // that establishes the coordinate system for the 'background-position' property. 
+    
+    // FIXME: Remove unnecessary rounding when layout is off ints: webkit.org/b/63656
+    if (intrinsicWidth.isPercent() && intrinsicHeight.isPercent() && intrinsicRatio.isEmpty()) {
+        // Resolve width/height percentages against positioningAreaSize, only if no intrinsic ratio is provided.
+        int resolvedWidth = static_cast<int>(round(positioningAreaSize.width() * intrinsicWidth.percent() / 100));
+        int resolvedHeight = static_cast<int>(round(positioningAreaSize.height() * intrinsicHeight.percent() / 100));
+        return IntSize(resolvedWidth, resolvedHeight);
+    }
+
+    IntSize resolvedSize(intrinsicWidth.isFixed() ? intrinsicWidth.value() : 0, intrinsicHeight.isFixed() ? intrinsicHeight.value() : 0);
+    IntSize minimumSize(resolvedSize.width() > 0 ? 1 : 0, resolvedSize.height() > 0 ? 1 : 0);
+    if (shouldScaleOrNot == ScaleByEffectiveZoom)
+        resolvedSize.scale(style()->effectiveZoom());
+    resolvedSize.clampToMinimumSize(minimumSize);
+
+    if (!resolvedSize.isEmpty())
+        return resolvedSize;
+
+    // If the image has one of either an intrinsic width or an intrinsic height:
+    // * and an intrinsic aspect ratio, then the missing dimension is calculated from the given dimension and the ratio.
+    // * and no intrinsic aspect ratio, then the missing dimension is assumed to be the size of the rectangle that
+    //   establishes the coordinate system for the 'background-position' property.
+    if (resolvedSize.width() > 0 || resolvedSize.height() > 0)
+        return resolveAgainstIntrinsicWidthOrHeightAndRatio(positioningAreaSize, intrinsicRatio, resolvedSize.width(), resolvedSize.height());
+
+    // If the image has no intrinsic dimensions and has an intrinsic ratio the dimensions must be assumed to be the
+    // largest dimensions at that ratio such that neither dimension exceeds the dimensions of the rectangle that
+    // establishes the coordinate system for the 'background-position' property.
+    if (!intrinsicRatio.isEmpty())
+        return resolveAgainstIntrinsicRatio(positioningAreaSize, intrinsicRatio);
+
+    // If the image has no intrinsic ratio either, then the dimensions must be assumed to be the rectangle that
+    // establishes the coordinate system for the 'background-position' property.
+    return positioningAreaSize;
+}
+
+static inline void applySubPixelHeuristicForTileSize(LayoutSize& tileSize, const IntSize& positioningAreaSize)
+{
+    tileSize.setWidth(positioningAreaSize.width() - tileSize.width() <= 1 ? tileSize.width().ceil() : tileSize.width().floor());
+    tileSize.setHeight(positioningAreaSize.height() - tileSize.height() <= 1 ? tileSize.height().ceil() : tileSize.height().floor());
+}
+
+IntSize RenderBoxModelObject::calculateFillTileSize(const FillLayer* fillLayer, const IntSize& positioningAreaSize) const
+{
+    StyleImage* image = fillLayer->image();
+    EFillSizeType type = fillLayer->size().type;
+
+    IntSize imageIntrinsicSize = calculateImageIntrinsicDimensions(image, positioningAreaSize, ScaleByEffectiveZoom);
+    imageIntrinsicSize.scale(1 / image->imageScaleFactor(), 1 / image->imageScaleFactor());
+    RenderView* renderView = view();
+    switch (type) {
+        case SizeLength: {
+            LayoutSize tileSize = positioningAreaSize;
+
+            Length layerWidth = fillLayer->size().size.width();
+            Length layerHeight = fillLayer->size().size.height();
+
+            if (layerWidth.isFixed())
+                tileSize.setWidth(layerWidth.value());
+            else if (layerWidth.isPercent() || layerWidth.isViewportPercentage())
+                tileSize.setWidth(valueForLength(layerWidth, positioningAreaSize.width(), renderView));
+            
+            if (layerHeight.isFixed())
+                tileSize.setHeight(layerHeight.value());
+            else if (layerHeight.isPercent() || layerHeight.isViewportPercentage())
+                tileSize.setHeight(valueForLength(layerHeight, positioningAreaSize.height(), renderView));
+
+            applySubPixelHeuristicForTileSize(tileSize, positioningAreaSize);
+
+            // If one of the values is auto we have to use the appropriate
+            // scale to maintain our aspect ratio.
+            if (layerWidth.isAuto() && !layerHeight.isAuto()) {
+                if (imageIntrinsicSize.height())
+                    tileSize.setWidth(imageIntrinsicSize.width() * tileSize.height() / imageIntrinsicSize.height());
+            } else if (!layerWidth.isAuto() && layerHeight.isAuto()) {
+                if (imageIntrinsicSize.width())
+                    tileSize.setHeight(imageIntrinsicSize.height() * tileSize.width() / imageIntrinsicSize.width());
+            } else if (layerWidth.isAuto() && layerHeight.isAuto()) {
+                // If both width and height are auto, use the image's intrinsic size.
+                tileSize = imageIntrinsicSize;
+            }
+            
+            tileSize.clampNegativeToZero();
+            return flooredIntSize(tileSize);
+        }
+        case SizeNone: {
+            // If both values are ‘auto’ then the intrinsic width and/or height of the image should be used, if any.
+            if (!imageIntrinsicSize.isEmpty())
+                return imageIntrinsicSize;
+
+            // If the image has neither an intrinsic width nor an intrinsic height, its size is determined as for ‘contain’.
+            type = Contain;
+        }
+        case Contain:
+        case Cover: {
+            float horizontalScaleFactor = imageIntrinsicSize.width()
+                ? static_cast<float>(positioningAreaSize.width()) / imageIntrinsicSize.width() : 1;
+            float verticalScaleFactor = imageIntrinsicSize.height()
+                ? static_cast<float>(positioningAreaSize.height()) / imageIntrinsicSize.height() : 1;
+            float scaleFactor = type == Contain ? min(horizontalScaleFactor, verticalScaleFactor) : max(horizontalScaleFactor, verticalScaleFactor);
+            return IntSize(max(1, static_cast<int>(imageIntrinsicSize.width() * scaleFactor)), max(1, static_cast<int>(imageIntrinsicSize.height() * scaleFactor)));
+       }
+    }
+
+    ASSERT_NOT_REACHED();
+    return IntSize();
+}
+
+void RenderBoxModelObject::BackgroundImageGeometry::setNoRepeatX(int xOffset)
+{
+    m_destRect.move(max(xOffset, 0), 0);
+    m_phase.setX(-min(xOffset, 0));
+    m_destRect.setWidth(m_tileSize.width() + min(xOffset, 0));
+}
+void RenderBoxModelObject::BackgroundImageGeometry::setNoRepeatY(int yOffset)
+{
+    m_destRect.move(0, max(yOffset, 0));
+    m_phase.setY(-min(yOffset, 0));
+    m_destRect.setHeight(m_tileSize.height() + min(yOffset, 0));
+}
+
+void RenderBoxModelObject::BackgroundImageGeometry::useFixedAttachment(const IntPoint& attachmentPoint)
+{
+    IntPoint alignedPoint = attachmentPoint;
+    m_phase.move(max(alignedPoint.x() - m_destRect.x(), 0), max(alignedPoint.y() - m_destRect.y(), 0));
+}
+
+void RenderBoxModelObject::BackgroundImageGeometry::clip(const IntRect& clipRect)
+{
+    m_destRect.intersect(clipRect);
+}
+
+IntPoint RenderBoxModelObject::BackgroundImageGeometry::relativePhase() const
+{
+    IntPoint phase = m_phase;
+    phase += m_destRect.location() - m_destOrigin;
+    return phase;
+}
+
+bool RenderBoxModelObject::fixedBackgroundPaintsInLocalCoordinates() const
+{
+    if (!isRoot())
+        return false;
+
+    if (view()->frameView() && view()->frameView()->paintBehavior() & PaintBehaviorFlattenCompositingLayers)
+        return false;
+
+    RenderLayer* rootLayer = view()->layer();
+    if (!rootLayer || !rootLayer->isComposited())
+        return false;
+
+    return rootLayer->backing()->backgroundLayerPaintsFixedRootBackground();
+}
+
+void RenderBoxModelObject::calculateBackgroundImageGeometry(const FillLayer* fillLayer, const LayoutRect& paintRect,
+    BackgroundImageGeometry& geometry, RenderObject* backgroundObject)
+{
+    LayoutUnit left = 0;
+    LayoutUnit top = 0;
+    IntSize positioningAreaSize;
+    IntRect snappedPaintRect = pixelSnappedIntRect(paintRect);
+
+    // Determine the background positioning area and set destRect to the background painting area.
+    // destRect will be adjusted later if the background is non-repeating.
+    bool fixedAttachment = fillLayer->attachment() == FixedBackgroundAttachment;
+
+#if ENABLE(FAST_MOBILE_SCROLLING)
+    if (view()->frameView() && view()->frameView()->canBlitOnScroll()) {
+        // As a side effect of an optimization to blit on scroll, we do not honor the CSS
+        // property "background-attachment: fixed" because it may result in rendering
+        // artifacts. Note, these artifacts only appear if we are blitting on scroll of
+        // a page that has fixed background images.
+        fixedAttachment = false;
+    }
+#endif
+
+    if (!fixedAttachment) {
+        geometry.setDestRect(snappedPaintRect);
+
+        LayoutUnit right = 0;
+        LayoutUnit bottom = 0;
+        // Scroll and Local.
+        if (fillLayer->origin() != BorderFillBox) {
+            left = borderLeft();
+            right = borderRight();
+            top = borderTop();
+            bottom = borderBottom();
+            if (fillLayer->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 background positioning area.
+        if (isRoot()) {
+            positioningAreaSize = pixelSnappedIntSize(toRenderBox(this)->size() - LayoutSize(left + right, top + bottom), toRenderBox(this)->location());
+            left += marginLeft();
+            top += marginTop();
+        } else
+            positioningAreaSize = pixelSnappedIntSize(paintRect.size() - LayoutSize(left + right, top + bottom), paintRect.location());
+    } else {
+        IntRect viewportRect = pixelSnappedIntRect(viewRect());
+        if (fixedBackgroundPaintsInLocalCoordinates())
+            viewportRect.setLocation(IntPoint());
+        else if (FrameView* frameView = view()->frameView())
+            viewportRect.setLocation(IntPoint(frameView->scrollOffsetForFixedPosition()));
+        
+        geometry.setDestRect(pixelSnappedIntRect(viewportRect));
+        positioningAreaSize = geometry.destRect().size();
+    }
+
+    RenderObject* clientForBackgroundImage = backgroundObject ? backgroundObject : this;
+    IntSize fillTileSize = calculateFillTileSize(fillLayer, positioningAreaSize);
+    fillLayer->image()->setContainerSizeForRenderer(clientForBackgroundImage, fillTileSize, style()->effectiveZoom());
+    geometry.setTileSize(fillTileSize);
+
+    EFillRepeat backgroundRepeatX = fillLayer->repeatX();
+    EFillRepeat backgroundRepeatY = fillLayer->repeatY();
+    RenderView* renderView = view();
+    int availableWidth = positioningAreaSize.width() - geometry.tileSize().width();
+    int availableHeight = positioningAreaSize.height() - geometry.tileSize().height();
+
+    LayoutUnit computedXPosition = minimumValueForLength(fillLayer->xPosition(), availableWidth, renderView, true);
+    if (backgroundRepeatX == RepeatFill)
+        geometry.setPhaseX(geometry.tileSize().width() ? geometry.tileSize().width() - roundToInt(computedXPosition + left) % geometry.tileSize().width() : 0);
+    else {
+        int xOffset = fillLayer->backgroundXOrigin() == RightEdge ? availableWidth - computedXPosition : computedXPosition;
+        geometry.setNoRepeatX(left + xOffset);
+    }
+    LayoutUnit computedYPosition = minimumValueForLength(fillLayer->yPosition(), availableHeight, renderView, true);
+    if (backgroundRepeatY == RepeatFill)
+        geometry.setPhaseY(geometry.tileSize().height() ? geometry.tileSize().height() - roundToInt(computedYPosition + top) % geometry.tileSize().height() : 0);
+    else {
+        int yOffset = fillLayer->backgroundYOrigin() == BottomEdge ? availableHeight - computedYPosition : computedYPosition;
+        geometry.setNoRepeatY(top + yOffset);
+    }
+
+    if (fixedAttachment)
+        geometry.useFixedAttachment(snappedPaintRect.location());
+
+    geometry.clip(snappedPaintRect);
+    geometry.setDestOrigin(geometry.destRect().location());
+}
+
+static LayoutUnit computeBorderImageSide(Length borderSlice, LayoutUnit borderSide, LayoutUnit imageSide, LayoutUnit boxExtent, RenderView* renderView)
+{
+    if (borderSlice.isRelative())
+        return borderSlice.value() * borderSide;
+    if (borderSlice.isAuto())
+        return imageSide;
+    return valueForLength(borderSlice, boxExtent, renderView);
+}
+
+bool RenderBoxModelObject::paintNinePieceImage(GraphicsContext* graphicsContext, const LayoutRect& rect, const RenderStyle* style,
+                                               const NinePieceImage& ninePieceImage, CompositeOperator op)
+{
+    StyleImage* styleImage = ninePieceImage.image();
+    if (!styleImage)
+        return false;
+
+    if (!styleImage->isLoaded())
+        return true; // Never paint a nine-piece image incrementally, but don't paint the fallback borders either.
+
+    if (!styleImage->canRender(this, style->effectiveZoom()))
+        return false;
+
+    // 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.
+    LayoutRect rectWithOutsets = rect;
+    rectWithOutsets.expand(style->imageOutsets(ninePieceImage));
+    IntRect borderImageRect = pixelSnappedIntRect(rectWithOutsets);
+
+    IntSize imageSize = calculateImageIntrinsicDimensions(styleImage, borderImageRect.size(), DoNotScaleByEffectiveZoom);
+
+    // If both values are ‘auto’ then the intrinsic width and/or height of the image should be used, if any.
+    styleImage->setContainerSizeForRenderer(this, imageSize, style->effectiveZoom());
+
+    int imageWidth = imageSize.width();
+    int imageHeight = imageSize.height();
+    RenderView* renderView = view();
+
+    float imageScaleFactor = styleImage->imageScaleFactor();
+    int topSlice = min<int>(imageHeight, valueForLength(ninePieceImage.imageSlices().top(), imageHeight, renderView)) * imageScaleFactor;
+    int rightSlice = min<int>(imageWidth, valueForLength(ninePieceImage.imageSlices().right(), imageWidth, renderView)) * imageScaleFactor;
+    int bottomSlice = min<int>(imageHeight, valueForLength(ninePieceImage.imageSlices().bottom(), imageHeight, renderView)) * imageScaleFactor;
+    int leftSlice = min<int>(imageWidth, valueForLength(ninePieceImage.imageSlices().left(), imageWidth, renderView)) * imageScaleFactor;
+
+    ENinePieceImageRule hRule = ninePieceImage.horizontalRule();
+    ENinePieceImageRule vRule = ninePieceImage.verticalRule();
+
+    int topWidth = computeBorderImageSide(ninePieceImage.borderSlices().top(), style->borderTopWidth(), topSlice, borderImageRect.height(), renderView);
+    int rightWidth = computeBorderImageSide(ninePieceImage.borderSlices().right(), style->borderRightWidth(), rightSlice, borderImageRect.width(), renderView);
+    int bottomWidth = computeBorderImageSide(ninePieceImage.borderSlices().bottom(), style->borderBottomWidth(), bottomSlice, borderImageRect.height(), renderView);
+    int leftWidth = computeBorderImageSide(ninePieceImage.borderSlices().left(), style->borderLeftWidth(), leftSlice, borderImageRect.width(), renderView);
+    
+    // Reduce the widths if they're too large.
+    // The spec says: Given Lwidth as the width of the border image area, Lheight as its height, and Wside as the border image width
+    // offset for the side, let f = min(Lwidth/(Wleft+Wright), Lheight/(Wtop+Wbottom)). If f < 1, then all W are reduced by
+    // multiplying them by f.
+    int borderSideWidth = max(1, leftWidth + rightWidth);
+    int borderSideHeight = max(1, topWidth + bottomWidth);
+    float borderSideScaleFactor = min((float)borderImageRect.width() / borderSideWidth, (float)borderImageRect.height() / borderSideHeight);
+    if (borderSideScaleFactor < 1) {
+        topWidth *= borderSideScaleFactor;
+        rightWidth *= borderSideScaleFactor;
+        bottomWidth *= borderSideScaleFactor;
+        leftWidth *= borderSideScaleFactor;
+    }
+
+    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 = ninePieceImage.fill() && (imageWidth - leftSlice - rightSlice) > 0 && (borderImageRect.width() - leftWidth - rightWidth) > 0
+                      && (imageHeight - topSlice - bottomSlice) > 0 && (borderImageRect.height() - topWidth - bottomWidth) > 0;
+
+    RefPtr<Image> image = styleImage->image(this, imageSize);
+    ColorSpace colorSpace = style->colorSpace();
+    
+    float destinationWidth = borderImageRect.width() - leftWidth - rightWidth;
+    float destinationHeight = borderImageRect.height() - topWidth - bottomWidth;
+    
+    float sourceWidth = imageWidth - leftSlice - rightSlice;
+    float sourceHeight = imageHeight - topSlice - bottomSlice;
+    
+    float leftSideScale = drawLeft ? (float)leftWidth / leftSlice : 1;
+    float rightSideScale = drawRight ? (float)rightWidth / rightSlice : 1;
+    float topSideScale = drawTop ? (float)topWidth / topSlice : 1;
+    float bottomSideScale = drawBottom ? (float)bottomWidth / bottomSlice : 1;
+    
+    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.get(), colorSpace, IntRect(borderImageRect.location(), IntSize(leftWidth, topWidth)),
+                                       LayoutRect(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.get(), colorSpace, IntRect(borderImageRect.x(), borderImageRect.maxY() - bottomWidth, leftWidth, bottomWidth),
+                                       LayoutRect(0, imageHeight - bottomSlice, leftSlice, bottomSlice), op);
+
+        // Paint the left edge.
+        // Have to scale and tile into the border rect.
+        if (sourceHeight > 0)
+            graphicsContext->drawTiledImage(image.get(), colorSpace, IntRect(borderImageRect.x(), borderImageRect.y() + topWidth, leftWidth,
+                                            destinationHeight),
+                                            IntRect(0, topSlice, leftSlice, sourceHeight),
+                                            FloatSize(leftSideScale, leftSideScale), 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.get(), colorSpace, IntRect(borderImageRect.maxX() - rightWidth, borderImageRect.y(), rightWidth, topWidth),
+                                       LayoutRect(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.get(), colorSpace, IntRect(borderImageRect.maxX() - rightWidth, borderImageRect.maxY() - bottomWidth, rightWidth, bottomWidth),
+                                       LayoutRect(imageWidth - rightSlice, imageHeight - bottomSlice, rightSlice, bottomSlice), op);
+
+        // Paint the right edge.
+        if (sourceHeight > 0)
+            graphicsContext->drawTiledImage(image.get(), colorSpace, IntRect(borderImageRect.maxX() - rightWidth, borderImageRect.y() + topWidth, rightWidth,
+                                            destinationHeight),
+                                            IntRect(imageWidth - rightSlice, topSlice, rightSlice, sourceHeight),
+                                            FloatSize(rightSideScale, rightSideScale),
+                                            Image::StretchTile, (Image::TileRule)vRule, op);
+    }
+
+    // Paint the top edge.
+    if (drawTop && sourceWidth > 0)
+        graphicsContext->drawTiledImage(image.get(), colorSpace, IntRect(borderImageRect.x() + leftWidth, borderImageRect.y(), destinationWidth, topWidth),
+                                        IntRect(leftSlice, 0, sourceWidth, topSlice),
+                                        FloatSize(topSideScale, topSideScale), (Image::TileRule)hRule, Image::StretchTile, op);
+
+    // Paint the bottom edge.
+    if (drawBottom && sourceWidth > 0)
+        graphicsContext->drawTiledImage(image.get(), colorSpace, IntRect(borderImageRect.x() + leftWidth, borderImageRect.maxY() - bottomWidth,
+                                        destinationWidth, bottomWidth),
+                                        IntRect(leftSlice, imageHeight - bottomSlice, sourceWidth, bottomSlice),
+                                        FloatSize(bottomSideScale, bottomSideScale),
+                                        (Image::TileRule)hRule, Image::StretchTile, op);
+
+    // Paint the middle.
+    if (drawMiddle) {
+        FloatSize middleScaleFactor(1, 1);
+        if (drawTop)
+            middleScaleFactor.setWidth(topSideScale);
+        else if (drawBottom)
+            middleScaleFactor.setWidth(bottomSideScale);
+        if (drawLeft)
+            middleScaleFactor.setHeight(leftSideScale);
+        else if (drawRight)
+            middleScaleFactor.setHeight(rightSideScale);
+            
+        // For "stretch" rules, just override the scale factor and replace. We only had to do this for the
+        // center tile, since sides don't even use the scale factor unless they have a rule other than "stretch".
+        // The middle however can have "stretch" specified in one axis but not the other, so we have to
+        // correct the scale here.
+        if (hRule == StretchImageRule)
+            middleScaleFactor.setWidth(destinationWidth / sourceWidth);
+            
+        if (vRule == StretchImageRule)
+            middleScaleFactor.setHeight(destinationHeight / sourceHeight);
+        
+        graphicsContext->drawTiledImage(image.get(), colorSpace,
+            IntRect(borderImageRect.x() + leftWidth, borderImageRect.y() + topWidth, destinationWidth, destinationHeight),
+            IntRect(leftSlice, topSlice, sourceWidth, sourceHeight),
+            middleScaleFactor, (Image::TileRule)hRule, (Image::TileRule)vRule, op);
+    }
+
+    return true;
+}
+
+class BorderEdge {
+public:
+    BorderEdge(int edgeWidth, const Color& edgeColor, EBorderStyle edgeStyle, bool edgeIsTransparent, bool edgeIsPresent = true)
+        : width(edgeWidth)
+        , color(edgeColor)
+        , style(edgeStyle)
+        , isTransparent(edgeIsTransparent)
+        , isPresent(edgeIsPresent)
+    {
+        if (style == DOUBLE && edgeWidth < 3)
+            style = SOLID;
+    }
+    
+    BorderEdge()
+        : width(0)
+        , style(BHIDDEN)
+        , isTransparent(false)
+        , isPresent(false)
+    {
+    }
+    
+    bool hasVisibleColorAndStyle() const { return style > BHIDDEN && !isTransparent; }
+    bool shouldRender() const { return isPresent && width && hasVisibleColorAndStyle(); }
+    bool presentButInvisible() const { return usedWidth() && !hasVisibleColorAndStyle(); }
+    bool obscuresBackgroundEdge(float scale) const
+    {
+        if (!isPresent || isTransparent || (width * scale) < 2 || color.hasAlpha() || style == BHIDDEN)
+            return false;
+
+        if (style == DOTTED || style == DASHED)
+            return false;
+
+        if (style == DOUBLE)
+            return width >= 5 * scale; // The outer band needs to be >= 2px wide at unit scale.
+
+        return true;
+    }
+    bool obscuresBackground() const
+    {
+        if (!isPresent || isTransparent || color.hasAlpha() || style == BHIDDEN)
+            return false;
+
+        if (style == DOTTED || style == DASHED || style == DOUBLE)
+            return false;
+
+        return true;
+    }
+
+    int usedWidth() const { return isPresent ? width : 0; }
+    
+    void getDoubleBorderStripeWidths(int& outerWidth, int& innerWidth) const
+    {
+        int fullWidth = usedWidth();
+        outerWidth = fullWidth / 3;
+        innerWidth = fullWidth * 2 / 3;
+
+        // We need certain integer rounding results
+        if (fullWidth % 3 == 2)
+            outerWidth += 1;
+
+        if (fullWidth % 3 == 1)
+            innerWidth += 1;
+    }
+    
+    int width;
+    Color color;
+    EBorderStyle style;
+    bool isTransparent;
+    bool isPresent;
+};
+
+static bool allCornersClippedOut(const RoundedRect& border, const LayoutRect& clipRect)
+{
+    LayoutRect boundingRect = border.rect();
+    if (clipRect.contains(boundingRect))
+        return false;
+
+    RoundedRect::Radii radii = border.radii();
+
+    LayoutRect topLeftRect(boundingRect.location(), radii.topLeft());
+    if (clipRect.intersects(topLeftRect))
+        return false;
+
+    LayoutRect topRightRect(boundingRect.location(), radii.topRight());
+    topRightRect.setX(boundingRect.maxX() - topRightRect.width());
+    if (clipRect.intersects(topRightRect))
+        return false;
+
+    LayoutRect bottomLeftRect(boundingRect.location(), radii.bottomLeft());
+    bottomLeftRect.setY(boundingRect.maxY() - bottomLeftRect.height());
+    if (clipRect.intersects(bottomLeftRect))
+        return false;
+
+    LayoutRect bottomRightRect(boundingRect.location(), radii.bottomRight());
+    bottomRightRect.setX(boundingRect.maxX() - bottomRightRect.width());
+    bottomRightRect.setY(boundingRect.maxY() - bottomRightRect.height());
+    if (clipRect.intersects(bottomRightRect))
+        return false;
+
+    return true;
+}
+
+static bool borderWillArcInnerEdge(const LayoutSize& firstRadius, const FloatSize& secondRadius)
+{
+    return !firstRadius.isZero() || !secondRadius.isZero();
+}
+
+enum BorderEdgeFlag {
+    TopBorderEdge = 1 << BSTop,
+    RightBorderEdge = 1 << BSRight,
+    BottomBorderEdge = 1 << BSBottom,
+    LeftBorderEdge = 1 << BSLeft,
+    AllBorderEdges = TopBorderEdge | BottomBorderEdge | LeftBorderEdge | RightBorderEdge
+};
+
+static inline BorderEdgeFlag edgeFlagForSide(BoxSide side)
+{
+    return static_cast<BorderEdgeFlag>(1 << side);
+}
+
+static inline bool includesEdge(BorderEdgeFlags flags, BoxSide side)
+{
+    return flags & edgeFlagForSide(side);
+}
+
+static inline bool includesAdjacentEdges(BorderEdgeFlags flags)
+{
+    return (flags & (TopBorderEdge | RightBorderEdge)) == (TopBorderEdge | RightBorderEdge)
+        || (flags & (RightBorderEdge | BottomBorderEdge)) == (RightBorderEdge | BottomBorderEdge)
+        || (flags & (BottomBorderEdge | LeftBorderEdge)) == (BottomBorderEdge | LeftBorderEdge)
+        || (flags & (LeftBorderEdge | TopBorderEdge)) == (LeftBorderEdge | TopBorderEdge);
+}
+
+inline bool edgesShareColor(const BorderEdge& firstEdge, const BorderEdge& secondEdge)
+{
+    return firstEdge.color == secondEdge.color;
+}
+
+inline bool styleRequiresClipPolygon(EBorderStyle style)
+{
+    return style == DOTTED || style == DASHED; // These are drawn with a stroke, so we have to clip to get corner miters.
+}
+
+static bool borderStyleFillsBorderArea(EBorderStyle style)
+{
+    return !(style == DOTTED || style == DASHED || style == DOUBLE);
+}
+
+static bool borderStyleHasInnerDetail(EBorderStyle style)
+{
+    return style == GROOVE || style == RIDGE || style == DOUBLE;
+}
+
+static bool borderStyleIsDottedOrDashed(EBorderStyle style)
+{
+    return style == DOTTED || style == DASHED;
+}
+
+// OUTSET darkens the bottom and right (and maybe lightens the top and left)
+// INSET darkens the top and left (and maybe lightens the bottom and right)
+static inline bool borderStyleHasUnmatchedColorsAtCorner(EBorderStyle style, BoxSide side, BoxSide adjacentSide)
+{
+    // These styles match at the top/left and bottom/right.
+    if (style == INSET || style == GROOVE || style == RIDGE || style == OUTSET) {
+        const BorderEdgeFlags topRightFlags = edgeFlagForSide(BSTop) | edgeFlagForSide(BSRight);
+        const BorderEdgeFlags bottomLeftFlags = edgeFlagForSide(BSBottom) | edgeFlagForSide(BSLeft);
+
+        BorderEdgeFlags flags = edgeFlagForSide(side) | edgeFlagForSide(adjacentSide);
+        return flags == topRightFlags || flags == bottomLeftFlags;
+    }
+    return false;
+}
+
+static inline bool colorsMatchAtCorner(BoxSide side, BoxSide adjacentSide, const BorderEdge edges[])
+{
+    if (edges[side].shouldRender() != edges[adjacentSide].shouldRender())
+        return false;
+
+    if (!edgesShareColor(edges[side], edges[adjacentSide]))
+        return false;
+
+    return !borderStyleHasUnmatchedColorsAtCorner(edges[side].style, side, adjacentSide);
+}
+
+
+static inline bool colorNeedsAntiAliasAtCorner(BoxSide side, BoxSide adjacentSide, const BorderEdge edges[])
+{
+    if (!edges[side].color.hasAlpha())
+        return false;
+
+    if (edges[side].shouldRender() != edges[adjacentSide].shouldRender())
+        return false;
+
+    if (!edgesShareColor(edges[side], edges[adjacentSide]))
+        return true;
+
+    return borderStyleHasUnmatchedColorsAtCorner(edges[side].style, side, adjacentSide);
+}
+
+// This assumes that we draw in order: top, bottom, left, right.
+static inline bool willBeOverdrawn(BoxSide side, BoxSide adjacentSide, const BorderEdge edges[])
+{
+    switch (side) {
+    case BSTop:
+    case BSBottom:
+        if (edges[adjacentSide].presentButInvisible())
+            return false;
+
+        if (!edgesShareColor(edges[side], edges[adjacentSide]) && edges[adjacentSide].color.hasAlpha())
+            return false;
+        
+        if (!borderStyleFillsBorderArea(edges[adjacentSide].style))
+            return false;
+
+        return true;
+
+    case BSLeft:
+    case BSRight:
+        // These draw last, so are never overdrawn.
+        return false;
+    }
+    return false;
+}
+
+static inline bool borderStylesRequireMitre(BoxSide side, BoxSide adjacentSide, EBorderStyle style, EBorderStyle adjacentStyle)
+{
+    if (style == DOUBLE || adjacentStyle == DOUBLE || adjacentStyle == GROOVE || adjacentStyle == RIDGE)
+        return true;
+
+    if (borderStyleIsDottedOrDashed(style) != borderStyleIsDottedOrDashed(adjacentStyle))
+        return true;
+
+    if (style != adjacentStyle)
+        return true;
+
+    return borderStyleHasUnmatchedColorsAtCorner(style, side, adjacentSide);
+}
+
+static bool joinRequiresMitre(BoxSide side, BoxSide adjacentSide, const BorderEdge edges[], bool allowOverdraw)
+{
+    if ((edges[side].isTransparent && edges[adjacentSide].isTransparent) || !edges[adjacentSide].isPresent)
+        return false;
+
+    if (allowOverdraw && willBeOverdrawn(side, adjacentSide, edges))
+        return false;
+
+    if (!edgesShareColor(edges[side], edges[adjacentSide]))
+        return true;
+
+    if (borderStylesRequireMitre(side, adjacentSide, edges[side].style, edges[adjacentSide].style))
+        return true;
+    
+    return false;
+}
+
+void RenderBoxModelObject::paintOneBorderSide(GraphicsContext* graphicsContext, const RenderStyle* style, const RoundedRect& outerBorder, const RoundedRect& innerBorder,
+    const IntRect& sideRect, BoxSide side, BoxSide adjacentSide1, BoxSide adjacentSide2, const BorderEdge edges[], const Path* path,
+    BackgroundBleedAvoidance bleedAvoidance, bool includeLogicalLeftEdge, bool includeLogicalRightEdge, bool antialias, const Color* overrideColor)
+{
+    const BorderEdge& edgeToRender = edges[side];
+    ASSERT(edgeToRender.width);
+    const BorderEdge& adjacentEdge1 = edges[adjacentSide1];
+    const BorderEdge& adjacentEdge2 = edges[adjacentSide2];
+
+    bool mitreAdjacentSide1 = joinRequiresMitre(side, adjacentSide1, edges, !antialias);
+    bool mitreAdjacentSide2 = joinRequiresMitre(side, adjacentSide2, edges, !antialias);
+    
+    bool adjacentSide1StylesMatch = colorsMatchAtCorner(side, adjacentSide1, edges);
+    bool adjacentSide2StylesMatch = colorsMatchAtCorner(side, adjacentSide2, edges);
+
+    const Color& colorToPaint = overrideColor ? *overrideColor : edgeToRender.color;
+
+    if (path) {
+        GraphicsContextStateSaver stateSaver(*graphicsContext);
+        if (innerBorder.isRenderable())
+            clipBorderSidePolygon(graphicsContext, outerBorder, innerBorder, side, adjacentSide1StylesMatch, adjacentSide2StylesMatch);
+        else
+            clipBorderSideForComplexInnerPath(graphicsContext, outerBorder, innerBorder, side, edges);
+        float thickness = max(max(edgeToRender.width, adjacentEdge1.width), adjacentEdge2.width);
+        drawBoxSideFromPath(graphicsContext, outerBorder.rect(), *path, edges, edgeToRender.width, thickness, side, style,
+            colorToPaint, edgeToRender.style, bleedAvoidance, includeLogicalLeftEdge, includeLogicalRightEdge);
+    } else {
+        bool clipForStyle = styleRequiresClipPolygon(edgeToRender.style) && (mitreAdjacentSide1 || mitreAdjacentSide2);
+        bool clipAdjacentSide1 = colorNeedsAntiAliasAtCorner(side, adjacentSide1, edges) && mitreAdjacentSide1;
+        bool clipAdjacentSide2 = colorNeedsAntiAliasAtCorner(side, adjacentSide2, edges) && mitreAdjacentSide2;
+        bool shouldClip = clipForStyle || clipAdjacentSide1 || clipAdjacentSide2;
+        
+        GraphicsContextStateSaver clipStateSaver(*graphicsContext, shouldClip);
+        if (shouldClip) {
+            bool aliasAdjacentSide1 = clipAdjacentSide1 || (clipForStyle && mitreAdjacentSide1);
+            bool aliasAdjacentSide2 = clipAdjacentSide2 || (clipForStyle && mitreAdjacentSide2);
+            clipBorderSidePolygon(graphicsContext, outerBorder, innerBorder, side, !aliasAdjacentSide1, !aliasAdjacentSide2);
+            // Since we clipped, no need to draw with a mitre.
+            mitreAdjacentSide1 = false;
+            mitreAdjacentSide2 = false;
+        }
+        
+        drawLineForBoxSide(graphicsContext, sideRect.x(), sideRect.y(), sideRect.maxX(), sideRect.maxY(), side, colorToPaint, edgeToRender.style,
+                mitreAdjacentSide1 ? adjacentEdge1.width : 0, mitreAdjacentSide2 ? adjacentEdge2.width : 0, antialias);
+    }
+}
+
+static IntRect calculateSideRect(const RoundedRect& outerBorder, const BorderEdge edges[], int side)
+{
+    IntRect sideRect = outerBorder.rect();
+    int width = edges[side].width;
+
+    if (side == BSTop)
+        sideRect.setHeight(width);
+    else if (side == BSBottom)
+        sideRect.shiftYEdgeTo(sideRect.maxY() - width);
+    else if (side == BSLeft)
+        sideRect.setWidth(width);
+    else
+        sideRect.shiftXEdgeTo(sideRect.maxX() - width);
+
+    return sideRect;
+}
+
+void RenderBoxModelObject::paintBorderSides(GraphicsContext* graphicsContext, const RenderStyle* style, const RoundedRect& outerBorder, const RoundedRect& innerBorder,
+    const IntPoint& innerBorderAdjustment, const BorderEdge edges[], BorderEdgeFlags edgeSet, BackgroundBleedAvoidance bleedAvoidance,
+    bool includeLogicalLeftEdge, bool includeLogicalRightEdge, bool antialias, const Color* overrideColor)
+{
+    bool renderRadii = outerBorder.isRounded();
+
+    Path roundedPath;
+    if (renderRadii)
+        roundedPath.addRoundedRect(outerBorder);
+    
+    // The inner border adjustment for bleed avoidance mode BackgroundBleedBackgroundOverBorder
+    // is only applied to sideRect, which is okay since BackgroundBleedBackgroundOverBorder
+    // is only to be used for solid borders and the shape of the border painted by drawBoxSideFromPath
+    // only depends on sideRect when painting solid borders.
+
+    if (edges[BSTop].shouldRender() && includesEdge(edgeSet, BSTop)) {
+        IntRect sideRect = outerBorder.rect();
+        sideRect.setHeight(edges[BSTop].width + innerBorderAdjustment.y());
+
+        bool usePath = renderRadii && (borderStyleHasInnerDetail(edges[BSTop].style) || borderWillArcInnerEdge(innerBorder.radii().topLeft(), innerBorder.radii().topRight()));
+        paintOneBorderSide(graphicsContext, style, outerBorder, innerBorder, sideRect, BSTop, BSLeft, BSRight, edges, usePath ? &roundedPath : 0, bleedAvoidance, includeLogicalLeftEdge, includeLogicalRightEdge, antialias, overrideColor);
+    }
+
+    if (edges[BSBottom].shouldRender() && includesEdge(edgeSet, BSBottom)) {
+        IntRect sideRect = outerBorder.rect();
+        sideRect.shiftYEdgeTo(sideRect.maxY() - edges[BSBottom].width - innerBorderAdjustment.y());
+
+        bool usePath = renderRadii && (borderStyleHasInnerDetail(edges[BSBottom].style) || borderWillArcInnerEdge(innerBorder.radii().bottomLeft(), innerBorder.radii().bottomRight()));
+        paintOneBorderSide(graphicsContext, style, outerBorder, innerBorder, sideRect, BSBottom, BSLeft, BSRight, edges, usePath ? &roundedPath : 0, bleedAvoidance, includeLogicalLeftEdge, includeLogicalRightEdge, antialias, overrideColor);
+    }
+
+    if (edges[BSLeft].shouldRender() && includesEdge(edgeSet, BSLeft)) {
+        IntRect sideRect = outerBorder.rect();
+        sideRect.setWidth(edges[BSLeft].width + innerBorderAdjustment.x());
+
+        bool usePath = renderRadii && (borderStyleHasInnerDetail(edges[BSLeft].style) || borderWillArcInnerEdge(innerBorder.radii().bottomLeft(), innerBorder.radii().topLeft()));
+        paintOneBorderSide(graphicsContext, style, outerBorder, innerBorder, sideRect, BSLeft, BSTop, BSBottom, edges, usePath ? &roundedPath : 0, bleedAvoidance, includeLogicalLeftEdge, includeLogicalRightEdge, antialias, overrideColor);
+    }
+
+    if (edges[BSRight].shouldRender() && includesEdge(edgeSet, BSRight)) {
+        IntRect sideRect = outerBorder.rect();
+        sideRect.shiftXEdgeTo(sideRect.maxX() - edges[BSRight].width - innerBorderAdjustment.x());
+
+        bool usePath = renderRadii && (borderStyleHasInnerDetail(edges[BSRight].style) || borderWillArcInnerEdge(innerBorder.radii().bottomRight(), innerBorder.radii().topRight()));
+        paintOneBorderSide(graphicsContext, style, outerBorder, innerBorder, sideRect, BSRight, BSTop, BSBottom, edges, usePath ? &roundedPath : 0, bleedAvoidance, includeLogicalLeftEdge, includeLogicalRightEdge, antialias, overrideColor);
+    }
+}
+
+void RenderBoxModelObject::paintTranslucentBorderSides(GraphicsContext* graphicsContext, const RenderStyle* style, const RoundedRect& outerBorder, const RoundedRect& innerBorder, const IntPoint& innerBorderAdjustment,
+    const BorderEdge edges[], BorderEdgeFlags edgesToDraw, BackgroundBleedAvoidance bleedAvoidance, bool includeLogicalLeftEdge, bool includeLogicalRightEdge, bool antialias)
+{
+    // willBeOverdrawn assumes that we draw in order: top, bottom, left, right.
+    // This is different from BoxSide enum order.
+    static const BoxSide paintOrder[] = { BSTop, BSBottom, BSLeft, BSRight };
+
+    while (edgesToDraw) {
+        // Find undrawn edges sharing a color.
+        Color commonColor;
+        
+        BorderEdgeFlags commonColorEdgeSet = 0;
+        for (size_t i = 0; i < sizeof(paintOrder) / sizeof(paintOrder[0]); ++i) {
+            BoxSide currSide = paintOrder[i];
+            if (!includesEdge(edgesToDraw, currSide))
+                continue;
+
+            bool includeEdge;
+            if (!commonColorEdgeSet) {
+                commonColor = edges[currSide].color;
+                includeEdge = true;
+            } else
+                includeEdge = edges[currSide].color == commonColor;
+
+            if (includeEdge)
+                commonColorEdgeSet |= edgeFlagForSide(currSide);
+        }
+
+        bool useTransparencyLayer = includesAdjacentEdges(commonColorEdgeSet) && commonColor.hasAlpha();
+        if (useTransparencyLayer) {
+            graphicsContext->beginTransparencyLayer(static_cast<float>(commonColor.alpha()) / 255);
+            commonColor = Color(commonColor.red(), commonColor.green(), commonColor.blue());
+        }
+
+        paintBorderSides(graphicsContext, style, outerBorder, innerBorder, innerBorderAdjustment, edges, commonColorEdgeSet, bleedAvoidance, includeLogicalLeftEdge, includeLogicalRightEdge, antialias, &commonColor);
+            
+        if (useTransparencyLayer)
+            graphicsContext->endTransparencyLayer();
+        
+        edgesToDraw &= ~commonColorEdgeSet;
+    }
+}
+
+void RenderBoxModelObject::paintBorder(const PaintInfo& info, const LayoutRect& rect, const RenderStyle* style,
+                                       BackgroundBleedAvoidance bleedAvoidance, bool includeLogicalLeftEdge, bool includeLogicalRightEdge)
+{
+    GraphicsContext* graphicsContext = info.context;
+    // border-image is not affected by border-radius.
+    if (paintNinePieceImage(graphicsContext, rect, style, style->borderImage()))
+        return;
+
+    if (graphicsContext->paintingDisabled())
+        return;
+
+    BorderEdge edges[4];
+    getBorderEdgeInfo(edges, style, includeLogicalLeftEdge, includeLogicalRightEdge);
+    RoundedRect outerBorder = style->getRoundedBorderFor(rect, view(), includeLogicalLeftEdge, includeLogicalRightEdge);
+    RoundedRect innerBorder = style->getRoundedInnerBorderFor(borderInnerRectAdjustedForBleedAvoidance(graphicsContext, rect, bleedAvoidance), includeLogicalLeftEdge, includeLogicalRightEdge);
+
+    bool haveAlphaColor = false;
+    bool haveAllSolidEdges = true;
+    bool haveAllDoubleEdges = true;
+    int numEdgesVisible = 4;
+    bool allEdgesShareColor = true;
+    int firstVisibleEdge = -1;
+    BorderEdgeFlags edgesToDraw = 0;
+
+    for (int i = BSTop; i <= BSLeft; ++i) {
+        const BorderEdge& currEdge = edges[i];
+
+        if (edges[i].shouldRender())
+            edgesToDraw |= edgeFlagForSide(static_cast<BoxSide>(i));
+
+        if (currEdge.presentButInvisible()) {
+            --numEdgesVisible;
+            allEdgesShareColor = false;
+            continue;
+        }
+        
+        if (!currEdge.width) {
+            --numEdgesVisible;
+            continue;
+        }
+
+        if (firstVisibleEdge == -1)
+            firstVisibleEdge = i;
+        else if (currEdge.color != edges[firstVisibleEdge].color)
+            allEdgesShareColor = false;
+
+        if (currEdge.color.hasAlpha())
+            haveAlphaColor = true;
+        
+        if (currEdge.style != SOLID)
+            haveAllSolidEdges = false;
+
+        if (currEdge.style != DOUBLE)
+            haveAllDoubleEdges = false;
+    }
+
+    // If no corner intersects the clip region, we can pretend outerBorder is
+    // rectangular to improve performance.
+    if (haveAllSolidEdges && outerBorder.isRounded() && allCornersClippedOut(outerBorder, info.rect))
+        outerBorder.setRadii(RoundedRect::Radii());
+
+    // isRenderable() check avoids issue described in https://bugs.webkit.org/show_bug.cgi?id=38787
+    if ((haveAllSolidEdges || haveAllDoubleEdges) && allEdgesShareColor && innerBorder.isRenderable()) {
+        // Fast path for drawing all solid edges and all unrounded double edges
+        if (numEdgesVisible == 4 && (outerBorder.isRounded() || haveAlphaColor)
+            && (haveAllSolidEdges || (!outerBorder.isRounded() && !innerBorder.isRounded()))) {
+            Path path;
+            
+            if (outerBorder.isRounded() && bleedAvoidance != BackgroundBleedUseTransparencyLayer)
+                path.addRoundedRect(outerBorder);
+            else
+                path.addRect(outerBorder.rect());
+
+            if (haveAllDoubleEdges) {
+                IntRect innerThirdRect = outerBorder.rect();
+                IntRect outerThirdRect = outerBorder.rect();
+                for (int side = BSTop; side <= BSLeft; ++side) {
+                    int outerWidth;
+                    int innerWidth;
+                    edges[side].getDoubleBorderStripeWidths(outerWidth, innerWidth);
+
+                    if (side == BSTop) {
+                        innerThirdRect.shiftYEdgeTo(innerThirdRect.y() + innerWidth);
+                        outerThirdRect.shiftYEdgeTo(outerThirdRect.y() + outerWidth);
+                    } else if (side == BSBottom) {
+                        innerThirdRect.setHeight(innerThirdRect.height() - innerWidth);
+                        outerThirdRect.setHeight(outerThirdRect.height() - outerWidth);
+                    } else if (side == BSLeft) {
+                        innerThirdRect.shiftXEdgeTo(innerThirdRect.x() + innerWidth);
+                        outerThirdRect.shiftXEdgeTo(outerThirdRect.x() + outerWidth);
+                    } else {
+                        innerThirdRect.setWidth(innerThirdRect.width() - innerWidth);
+                        outerThirdRect.setWidth(outerThirdRect.width() - outerWidth);
+                    }
+                }
+
+                RoundedRect outerThird = outerBorder;
+                RoundedRect innerThird = innerBorder;
+                innerThird.setRect(innerThirdRect);
+                outerThird.setRect(outerThirdRect);
+
+                if (outerThird.isRounded() && bleedAvoidance != BackgroundBleedUseTransparencyLayer)
+                    path.addRoundedRect(outerThird);
+                else
+                    path.addRect(outerThird.rect());
+
+                if (innerThird.isRounded() && bleedAvoidance != BackgroundBleedUseTransparencyLayer)
+                    path.addRoundedRect(innerThird);
+                else
+                    path.addRect(innerThird.rect());
+            }
+
+            if (innerBorder.isRounded())
+                path.addRoundedRect(innerBorder);
+            else
+                path.addRect(innerBorder.rect());
+            
+            graphicsContext->setFillRule(RULE_EVENODD);
+            graphicsContext->setFillColor(edges[firstVisibleEdge].color, style->colorSpace());
+            graphicsContext->fillPath(path);
+            return;
+        } 
+        // Avoid creating transparent layers
+        if (haveAllSolidEdges && numEdgesVisible != 4 && !outerBorder.isRounded() && haveAlphaColor) {
+            Path path;
+
+            for (int i = BSTop; i <= BSLeft; ++i) {
+                const BorderEdge& currEdge = edges[i];
+                if (currEdge.shouldRender()) {
+                    IntRect sideRect = calculateSideRect(outerBorder, edges, i);
+                    path.addRect(sideRect);
+                }
+            }
+
+            graphicsContext->setFillRule(RULE_NONZERO);
+            graphicsContext->setFillColor(edges[firstVisibleEdge].color, style->colorSpace());
+            graphicsContext->fillPath(path);
+            return;
+        }
+    }
+
+    bool clipToOuterBorder = outerBorder.isRounded();
+    GraphicsContextStateSaver stateSaver(*graphicsContext, clipToOuterBorder);
+    if (clipToOuterBorder) {
+        // Clip to the inner and outer radii rects.
+        if (bleedAvoidance != BackgroundBleedUseTransparencyLayer)
+            graphicsContext->clipRoundedRect(outerBorder);
+        // isRenderable() check avoids issue described in https://bugs.webkit.org/show_bug.cgi?id=38787
+        // The inside will be clipped out later (in clipBorderSideForComplexInnerPath)
+        if (innerBorder.isRenderable())
+            graphicsContext->clipOutRoundedRect(innerBorder);
+    }
+
+    // If only one edge visible antialiasing doesn't create seams
+    bool antialias = shouldAntialiasLines(graphicsContext) || numEdgesVisible == 1;
+    RoundedRect unadjustedInnerBorder = (bleedAvoidance == BackgroundBleedBackgroundOverBorder) ? style->getRoundedInnerBorderFor(rect, includeLogicalLeftEdge, includeLogicalRightEdge) : innerBorder;
+    IntPoint innerBorderAdjustment(innerBorder.rect().x() - unadjustedInnerBorder.rect().x(), innerBorder.rect().y() - unadjustedInnerBorder.rect().y());
+    if (haveAlphaColor)
+        paintTranslucentBorderSides(graphicsContext, style, outerBorder, unadjustedInnerBorder, innerBorderAdjustment, edges, edgesToDraw, bleedAvoidance, includeLogicalLeftEdge, includeLogicalRightEdge, antialias);
+    else
+        paintBorderSides(graphicsContext, style, outerBorder, unadjustedInnerBorder, innerBorderAdjustment, edges, edgesToDraw, bleedAvoidance, includeLogicalLeftEdge, includeLogicalRightEdge, antialias);
+}
+
+void RenderBoxModelObject::drawBoxSideFromPath(GraphicsContext* graphicsContext, const LayoutRect& borderRect, const Path& borderPath, const BorderEdge edges[],
+                                    float thickness, float drawThickness, BoxSide side, const RenderStyle* style, 
+                                    Color color, EBorderStyle borderStyle, BackgroundBleedAvoidance bleedAvoidance, bool includeLogicalLeftEdge, bool includeLogicalRightEdge)
+{
+    if (thickness <= 0)
+        return;
+
+    if (borderStyle == DOUBLE && thickness < 3)
+        borderStyle = SOLID;
+
+    switch (borderStyle) {
+    case BNONE:
+    case BHIDDEN:
+        return;
+    case DOTTED:
+    case DASHED: {
+        graphicsContext->setStrokeColor(color, style->colorSpace());
+
+        // The stroke is doubled here because the provided path is the 
+        // outside edge of the border so half the stroke is clipped off. 
+        // The extra multiplier is so that the clipping mask can antialias
+        // the edges to prevent jaggies.
+        graphicsContext->setStrokeThickness(drawThickness * 2 * 1.1f);
+        graphicsContext->setStrokeStyle(borderStyle == DASHED ? DashedStroke : DottedStroke);
+
+        // If the number of dashes that fit in the path is odd and non-integral then we
+        // will have an awkwardly-sized dash at the end of the path. To try to avoid that
+        // here, we simply make the whitespace dashes ever so slightly bigger.
+        // FIXME: This could be even better if we tried to manipulate the dash offset
+        // and possibly the gapLength to get the corners dash-symmetrical.
+        float dashLength = thickness * ((borderStyle == DASHED) ? 3.0f : 1.0f);
+        float gapLength = dashLength;
+        float numberOfDashes = borderPath.length() / dashLength;
+        // Don't try to show dashes if we have less than 2 dashes + 2 gaps.
+        // FIXME: should do this test per side.
+        if (numberOfDashes >= 4) {
+            bool evenNumberOfFullDashes = !((int)numberOfDashes % 2);
+            bool integralNumberOfDashes = !(numberOfDashes - (int)numberOfDashes);
+            if (!evenNumberOfFullDashes && !integralNumberOfDashes) {
+                float numberOfGaps = numberOfDashes / 2;
+                gapLength += (dashLength  / numberOfGaps);
+            }
+
+            DashArray lineDash;
+            lineDash.append(dashLength);
+            lineDash.append(gapLength);
+            graphicsContext->setLineDash(lineDash, dashLength);
+        }
+        
+        // FIXME: stroking the border path causes issues with tight corners:
+        // https://bugs.webkit.org/show_bug.cgi?id=58711
+        // Also, to get the best appearance we should stroke a path between the two borders.
+        graphicsContext->strokePath(borderPath);
+        return;
+    }
+    case DOUBLE: {
+        // Get the inner border rects for both the outer border line and the inner border line
+        int outerBorderTopWidth;
+        int innerBorderTopWidth;
+        edges[BSTop].getDoubleBorderStripeWidths(outerBorderTopWidth, innerBorderTopWidth);
+
+        int outerBorderRightWidth;
+        int innerBorderRightWidth;
+        edges[BSRight].getDoubleBorderStripeWidths(outerBorderRightWidth, innerBorderRightWidth);
+
+        int outerBorderBottomWidth;
+        int innerBorderBottomWidth;
+        edges[BSBottom].getDoubleBorderStripeWidths(outerBorderBottomWidth, innerBorderBottomWidth);
+
+        int outerBorderLeftWidth;
+        int innerBorderLeftWidth;
+        edges[BSLeft].getDoubleBorderStripeWidths(outerBorderLeftWidth, innerBorderLeftWidth);
+
+        // Draw inner border line
+        {
+            GraphicsContextStateSaver stateSaver(*graphicsContext);
+            RoundedRect innerClip = style->getRoundedInnerBorderFor(borderRect,
+                innerBorderTopWidth, innerBorderBottomWidth, innerBorderLeftWidth, innerBorderRightWidth,
+                includeLogicalLeftEdge, includeLogicalRightEdge);
+            
+            graphicsContext->clipRoundedRect(innerClip);
+            drawBoxSideFromPath(graphicsContext, borderRect, borderPath, edges, thickness, drawThickness, side, style, color, SOLID, bleedAvoidance, includeLogicalLeftEdge, includeLogicalRightEdge);
+        }
+
+        // Draw outer border line
+        {
+            GraphicsContextStateSaver stateSaver(*graphicsContext);
+            LayoutRect outerRect = borderRect;
+            if (bleedAvoidance == BackgroundBleedUseTransparencyLayer) {
+                outerRect.inflate(1);
+                ++outerBorderTopWidth;
+                ++outerBorderBottomWidth;
+                ++outerBorderLeftWidth;
+                ++outerBorderRightWidth;
+            }
+                
+            RoundedRect outerClip = style->getRoundedInnerBorderFor(outerRect,
+                outerBorderTopWidth, outerBorderBottomWidth, outerBorderLeftWidth, outerBorderRightWidth,
+                includeLogicalLeftEdge, includeLogicalRightEdge);
+            graphicsContext->clipOutRoundedRect(outerClip);
+            drawBoxSideFromPath(graphicsContext, borderRect, borderPath, edges, thickness, drawThickness, side, style, color, SOLID, bleedAvoidance, includeLogicalLeftEdge, includeLogicalRightEdge);
+        }
+        return;
+    }
+    case RIDGE:
+    case GROOVE:
+    {
+        EBorderStyle s1;
+        EBorderStyle s2;
+        if (borderStyle == GROOVE) {
+            s1 = INSET;
+            s2 = OUTSET;
+        } else {
+            s1 = OUTSET;
+            s2 = INSET;
+        }
+        
+        // Paint full border
+        drawBoxSideFromPath(graphicsContext, borderRect, borderPath, edges, thickness, drawThickness, side, style, color, s1, bleedAvoidance, includeLogicalLeftEdge, includeLogicalRightEdge);
+
+        // Paint inner only
+        GraphicsContextStateSaver stateSaver(*graphicsContext);
+        LayoutUnit topWidth = edges[BSTop].usedWidth() / 2;
+        LayoutUnit bottomWidth = edges[BSBottom].usedWidth() / 2;
+        LayoutUnit leftWidth = edges[BSLeft].usedWidth() / 2;
+        LayoutUnit rightWidth = edges[BSRight].usedWidth() / 2;
+
+        RoundedRect clipRect = style->getRoundedInnerBorderFor(borderRect,
+            topWidth, bottomWidth, leftWidth, rightWidth,
+            includeLogicalLeftEdge, includeLogicalRightEdge);
+
+        graphicsContext->clipRoundedRect(clipRect);
+        drawBoxSideFromPath(graphicsContext, borderRect, borderPath, edges, thickness, drawThickness, side, style, color, s2, bleedAvoidance, includeLogicalLeftEdge, includeLogicalRightEdge);
+        return;
+    }
+    case INSET:
+        if (side == BSTop || side == BSLeft)
+            color = color.dark();
+        break;
+    case OUTSET:
+        if (side == BSBottom || side == BSRight)
+            color = color.dark();
+        break;
+    default:
+        break;
+    }
+
+    graphicsContext->setStrokeStyle(NoStroke);
+    graphicsContext->setFillColor(color, style->colorSpace());
+    graphicsContext->drawRect(pixelSnappedIntRect(borderRect));
+}
+
+static void findInnerVertex(const FloatPoint& outerCorner, const FloatPoint& innerCorner, const FloatPoint& centerPoint, FloatPoint& result)
+{
+    // If the line between outer and inner corner is towards the horizontal, intersect with a vertical line through the center,
+    // otherwise with a horizontal line through the center. The points that form this line are arbitrary (we use 0, 100).
+    // Note that if findIntersection fails, it will leave result untouched.
+    float diffInnerOuterX = fabs(innerCorner.x() - outerCorner.x());
+    float diffInnerOuterY = fabs(innerCorner.y() - outerCorner.y());
+    float diffCenterOuterX = fabs(centerPoint.x() - outerCorner.x());
+    float diffCenterOuterY = fabs(centerPoint.y() - outerCorner.y());
+    if (diffInnerOuterY * diffCenterOuterX < diffCenterOuterY * diffInnerOuterX)
+        findIntersection(outerCorner, innerCorner, FloatPoint(centerPoint.x(), 0), FloatPoint(centerPoint.x(), 100), result);
+    else
+        findIntersection(outerCorner, innerCorner, FloatPoint(0, centerPoint.y()), FloatPoint(100, centerPoint.y()), result);
+}
+
+void RenderBoxModelObject::clipBorderSidePolygon(GraphicsContext* graphicsContext, const RoundedRect& outerBorder, const RoundedRect& innerBorder,
+                                                 BoxSide side, bool firstEdgeMatches, bool secondEdgeMatches)
+{
+    FloatPoint quad[4];
+
+    const LayoutRect& outerRect = outerBorder.rect();
+    const LayoutRect& innerRect = innerBorder.rect();
+
+    FloatPoint centerPoint(innerRect.location().x() + static_cast<float>(innerRect.width()) / 2, innerRect.location().y() + static_cast<float>(innerRect.height()) / 2);
+
+    // For each side, create a quad that encompasses all parts of that side that may draw,
+    // including areas inside the innerBorder.
+    //
+    //         0----------------3
+    //       0  \              /  0
+    //       |\  1----------- 2  /|
+    //       | 1                1 |   
+    //       | |                | |
+    //       | |                | |  
+    //       | 2                2 |  
+    //       |/  1------------2  \| 
+    //       3  /              \  3   
+    //         0----------------3
+    //
+    switch (side) {
+    case BSTop:
+        quad[0] = outerRect.minXMinYCorner();
+        quad[1] = innerRect.minXMinYCorner();
+        quad[2] = innerRect.maxXMinYCorner();
+        quad[3] = outerRect.maxXMinYCorner();
+
+        if (!innerBorder.radii().topLeft().isZero())
+            findInnerVertex(outerRect.minXMinYCorner(), innerRect.minXMinYCorner(), centerPoint, quad[1]);
+
+        if (!innerBorder.radii().topRight().isZero())
+            findInnerVertex(outerRect.maxXMinYCorner(), innerRect.maxXMinYCorner(), centerPoint, quad[2]);
+        break;
+
+    case BSLeft:
+        quad[0] = outerRect.minXMinYCorner();
+        quad[1] = innerRect.minXMinYCorner();
+        quad[2] = innerRect.minXMaxYCorner();
+        quad[3] = outerRect.minXMaxYCorner();
+
+        if (!innerBorder.radii().topLeft().isZero())
+            findInnerVertex(outerRect.minXMinYCorner(), innerRect.minXMinYCorner(), centerPoint, quad[1]);
+
+        if (!innerBorder.radii().bottomLeft().isZero())
+            findInnerVertex(outerRect.minXMaxYCorner(), innerRect.minXMaxYCorner(), centerPoint, quad[2]);
+        break;
+
+    case BSBottom:
+        quad[0] = outerRect.minXMaxYCorner();
+        quad[1] = innerRect.minXMaxYCorner();
+        quad[2] = innerRect.maxXMaxYCorner();
+        quad[3] = outerRect.maxXMaxYCorner();
+
+        if (!innerBorder.radii().bottomLeft().isZero())
+            findInnerVertex(outerRect.minXMaxYCorner(), innerRect.minXMaxYCorner(), centerPoint, quad[1]);
+
+        if (!innerBorder.radii().bottomRight().isZero())
+            findInnerVertex(outerRect.maxXMaxYCorner(), innerRect.maxXMaxYCorner(), centerPoint, quad[2]);
+        break;
+
+    case BSRight:
+        quad[0] = outerRect.maxXMinYCorner();
+        quad[1] = innerRect.maxXMinYCorner();
+        quad[2] = innerRect.maxXMaxYCorner();
+        quad[3] = outerRect.maxXMaxYCorner();
+
+        if (!innerBorder.radii().topRight().isZero())
+            findInnerVertex(outerRect.maxXMinYCorner(), innerRect.maxXMinYCorner(), centerPoint, quad[1]);
+
+        if (!innerBorder.radii().bottomRight().isZero())
+            findInnerVertex(outerRect.maxXMaxYCorner(), innerRect.maxXMaxYCorner(), centerPoint, quad[2]);
+        break;
+    }
+
+    // If the border matches both of its adjacent sides, don't anti-alias the clip, and
+    // if neither side matches, anti-alias the clip.
+    if (firstEdgeMatches == secondEdgeMatches) {
+        graphicsContext->clipConvexPolygon(4, quad, !firstEdgeMatches);
+        return;
+    }
+
+    // Square off the end which shouldn't be affected by antialiasing, and clip.
+    FloatPoint firstQuad[4];
+    firstQuad[0] = quad[0];
+    firstQuad[1] = quad[1];
+    firstQuad[2] = side == BSTop || side == BSBottom ? FloatPoint(quad[3].x(), quad[2].y())
+        : FloatPoint(quad[2].x(), quad[3].y());
+    firstQuad[3] = quad[3];
+    graphicsContext->clipConvexPolygon(4, firstQuad, !firstEdgeMatches);
+
+    FloatPoint secondQuad[4];
+    secondQuad[0] = quad[0];
+    secondQuad[1] = side == BSTop || side == BSBottom ? FloatPoint(quad[0].x(), quad[1].y())
+        : FloatPoint(quad[1].x(), quad[0].y());
+    secondQuad[2] = quad[2];
+    secondQuad[3] = quad[3];
+    // Antialiasing affects the second side.
+    graphicsContext->clipConvexPolygon(4, secondQuad, !secondEdgeMatches);
+}
+
+static IntRect calculateSideRectIncludingInner(const RoundedRect& outerBorder, const BorderEdge edges[], BoxSide side)
+{
+    IntRect sideRect = outerBorder.rect();
+    int width;
+
+    switch (side) {
+    case BSTop:
+        width = sideRect.height() - edges[BSBottom].width;
+        sideRect.setHeight(width);
+        break;
+    case BSBottom:
+        width = sideRect.height() - edges[BSTop].width;
+        sideRect.shiftYEdgeTo(sideRect.maxY() - width);
+        break;
+    case BSLeft:
+        width = sideRect.width() - edges[BSRight].width;
+        sideRect.setWidth(width);
+        break;
+    case BSRight:
+        width = sideRect.width() - edges[BSLeft].width;
+        sideRect.shiftXEdgeTo(sideRect.maxX() - width);
+        break;
+    }
+
+    return sideRect;
+}
+
+static RoundedRect calculateAdjustedInnerBorder(const RoundedRect&innerBorder, BoxSide side)
+{
+    // Expand the inner border as necessary to make it a rounded rect (i.e. radii contained within each edge).
+    // This function relies on the fact we only get radii not contained within each edge if one of the radii
+    // for an edge is zero, so we can shift the arc towards the zero radius corner.
+    RoundedRect::Radii newRadii = innerBorder.radii();
+    IntRect newRect = innerBorder.rect();
+
+    float overshoot;
+    float maxRadii;
+
+    switch (side) {
+    case BSTop:
+        overshoot = newRadii.topLeft().width() + newRadii.topRight().width() - newRect.width();
+        if (overshoot > 0) {
+            ASSERT(!(newRadii.topLeft().width() && newRadii.topRight().width()));
+            newRect.setWidth(newRect.width() + overshoot);
+            if (!newRadii.topLeft().width())
+                newRect.move(-overshoot, 0);
+        }
+        newRadii.setBottomLeft(IntSize(0, 0));
+        newRadii.setBottomRight(IntSize(0, 0));
+        maxRadii = max(newRadii.topLeft().height(), newRadii.topRight().height());
+        if (maxRadii > newRect.height())
+            newRect.setHeight(maxRadii);
+        break;
+
+    case BSBottom:
+        overshoot = newRadii.bottomLeft().width() + newRadii.bottomRight().width() - newRect.width();
+        if (overshoot > 0) {
+            ASSERT(!(newRadii.bottomLeft().width() && newRadii.bottomRight().width()));
+            newRect.setWidth(newRect.width() + overshoot);
+            if (!newRadii.bottomLeft().width())
+                newRect.move(-overshoot, 0);
+        }
+        newRadii.setTopLeft(IntSize(0, 0));
+        newRadii.setTopRight(IntSize(0, 0));
+        maxRadii = max(newRadii.bottomLeft().height(), newRadii.bottomRight().height());
+        if (maxRadii > newRect.height()) {
+            newRect.move(0, newRect.height() - maxRadii);
+            newRect.setHeight(maxRadii);
+        }
+        break;
+
+    case BSLeft:
+        overshoot = newRadii.topLeft().height() + newRadii.bottomLeft().height() - newRect.height();
+        if (overshoot > 0) {
+            ASSERT(!(newRadii.topLeft().height() && newRadii.bottomLeft().height()));
+            newRect.setHeight(newRect.height() + overshoot);
+            if (!newRadii.topLeft().height())
+                newRect.move(0, -overshoot);
+        }
+        newRadii.setTopRight(IntSize(0, 0));
+        newRadii.setBottomRight(IntSize(0, 0));
+        maxRadii = max(newRadii.topLeft().width(), newRadii.bottomLeft().width());
+        if (maxRadii > newRect.width())
+            newRect.setWidth(maxRadii);
+        break;
+
+    case BSRight:
+        overshoot = newRadii.topRight().height() + newRadii.bottomRight().height() - newRect.height();
+        if (overshoot > 0) {
+            ASSERT(!(newRadii.topRight().height() && newRadii.bottomRight().height()));
+            newRect.setHeight(newRect.height() + overshoot);
+            if (!newRadii.topRight().height())
+                newRect.move(0, -overshoot);
+        }
+        newRadii.setTopLeft(IntSize(0, 0));
+        newRadii.setBottomLeft(IntSize(0, 0));
+        maxRadii = max(newRadii.topRight().width(), newRadii.bottomRight().width());
+        if (maxRadii > newRect.width()) {
+            newRect.move(newRect.width() - maxRadii, 0);
+            newRect.setWidth(maxRadii);
+        }
+        break;
+    }
+
+    return RoundedRect(newRect, newRadii);
+}
+
+void RenderBoxModelObject::clipBorderSideForComplexInnerPath(GraphicsContext* graphicsContext, const RoundedRect& outerBorder, const RoundedRect& innerBorder,
+    BoxSide side, const class BorderEdge edges[])
+{
+    graphicsContext->clip(calculateSideRectIncludingInner(outerBorder, edges, side));
+    graphicsContext->clipOutRoundedRect(calculateAdjustedInnerBorder(innerBorder, side));
+}
+
+void RenderBoxModelObject::getBorderEdgeInfo(BorderEdge edges[], const RenderStyle* style, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
+{
+    bool horizontal = style->isHorizontalWritingMode();
+
+    edges[BSTop] = BorderEdge(style->borderTopWidth(),
+        style->visitedDependentColor(CSSPropertyBorderTopColor),
+        style->borderTopStyle(),
+        style->borderTopIsTransparent(),
+        horizontal || includeLogicalLeftEdge);
+
+    edges[BSRight] = BorderEdge(style->borderRightWidth(),
+        style->visitedDependentColor(CSSPropertyBorderRightColor),
+        style->borderRightStyle(),
+        style->borderRightIsTransparent(),
+        !horizontal || includeLogicalRightEdge);
+
+    edges[BSBottom] = BorderEdge(style->borderBottomWidth(),
+        style->visitedDependentColor(CSSPropertyBorderBottomColor),
+        style->borderBottomStyle(),
+        style->borderBottomIsTransparent(),
+        horizontal || includeLogicalRightEdge);
+
+    edges[BSLeft] = BorderEdge(style->borderLeftWidth(),
+        style->visitedDependentColor(CSSPropertyBorderLeftColor),
+        style->borderLeftStyle(),
+        style->borderLeftIsTransparent(),
+        !horizontal || includeLogicalLeftEdge);
+}
+
+bool RenderBoxModelObject::borderObscuresBackgroundEdge(const FloatSize& contextScale) const
+{
+    BorderEdge edges[4];
+    getBorderEdgeInfo(edges, style());
+
+    for (int i = BSTop; i <= BSLeft; ++i) {
+        const BorderEdge& currEdge = edges[i];
+        // FIXME: for vertical text
+        float axisScale = (i == BSTop || i == BSBottom) ? contextScale.height() : contextScale.width();
+        if (!currEdge.obscuresBackgroundEdge(axisScale))
+            return false;
+    }
+
+    return true;
+}
+
+bool RenderBoxModelObject::borderObscuresBackground() const
+{
+    if (!style()->hasBorder())
+        return false;
+
+    // Bail if we have any border-image for now. We could look at the image alpha to improve this.
+    if (style()->borderImage().image())
+        return false;
+
+    BorderEdge edges[4];
+    getBorderEdgeInfo(edges, style());
+
+    for (int i = BSTop; i <= BSLeft; ++i) {
+        const BorderEdge& currEdge = edges[i];
+        if (!currEdge.obscuresBackground())
+            return false;
+    }
+
+    return true;
+}
+
+bool RenderBoxModelObject::boxShadowShouldBeAppliedToBackground(BackgroundBleedAvoidance bleedAvoidance, InlineFlowBox* inlineFlowBox) const
+{
+    if (bleedAvoidance != BackgroundBleedNone)
+        return false;
+
+    if (style()->hasAppearance())
+        return false;
+
+    bool hasOneNormalBoxShadow = false;
+    for (const ShadowData* currentShadow = style()->boxShadow(); currentShadow; currentShadow = currentShadow->next()) {
+        if (currentShadow->style() != Normal)
+            continue;
+
+        if (hasOneNormalBoxShadow)
+            return false;
+        hasOneNormalBoxShadow = true;
+
+        if (currentShadow->spread())
+            return false;
+    }
+
+    if (!hasOneNormalBoxShadow)
+        return false;
+
+    Color backgroundColor = style()->visitedDependentColor(CSSPropertyBackgroundColor);
+    if (!backgroundColor.isValid() || backgroundColor.hasAlpha())
+        return false;
+
+    const FillLayer* lastBackgroundLayer = style()->backgroundLayers();
+    for (const FillLayer* next = lastBackgroundLayer->next(); next; next = lastBackgroundLayer->next())
+        lastBackgroundLayer = next;
+
+    if (lastBackgroundLayer->clip() != BorderFillBox)
+        return false;
+
+    if (lastBackgroundLayer->image() && style()->hasBorderRadius())
+        return false;
+
+    if (inlineFlowBox && !inlineFlowBox->boxShadowCanBeAppliedToBackground(*lastBackgroundLayer))
+        return false;
+
+    if (hasOverflowClip() && lastBackgroundLayer->attachment() == LocalBackgroundAttachment)
+        return false;
+
+    return true;
+}
+
+static inline IntRect areaCastingShadowInHole(const IntRect& holeRect, int shadowBlur, int shadowSpread, const IntSize& shadowOffset)
+{
+    IntRect bounds(holeRect);
+    
+    bounds.inflate(shadowBlur);
+
+    if (shadowSpread < 0)
+        bounds.inflate(-shadowSpread);
+    
+    IntRect offsetBounds = bounds;
+    offsetBounds.move(-shadowOffset);
+    return unionRect(bounds, offsetBounds);
+}
+
+void RenderBoxModelObject::paintBoxShadow(const PaintInfo& info, const LayoutRect& paintRect, const RenderStyle* s, ShadowStyle shadowStyle, bool includeLogicalLeftEdge, bool includeLogicalRightEdge)
+{
+    // FIXME: Deal with border-image.  Would be great to use border-image as a mask.
+    GraphicsContext* context = info.context;
+    if (context->paintingDisabled() || !s->boxShadow())
+        return;
+
+    RoundedRect border = (shadowStyle == Inset) ? s->getRoundedInnerBorderFor(paintRect, includeLogicalLeftEdge, includeLogicalRightEdge)
+                                                   : s->getRoundedBorderFor(paintRect, view(), includeLogicalLeftEdge, includeLogicalRightEdge);
+
+    bool hasBorderRadius = s->hasBorderRadius();
+    bool isHorizontal = s->isHorizontalWritingMode();
+    
+    bool hasOpaqueBackground = s->visitedDependentColor(CSSPropertyBackgroundColor).isValid() && s->visitedDependentColor(CSSPropertyBackgroundColor).alpha() == 255;
+    for (const ShadowData* shadow = s->boxShadow(); shadow; shadow = shadow->next()) {
+        if (shadow->style() != shadowStyle)
+            continue;
+
+        IntSize shadowOffset(shadow->x(), shadow->y());
+        int shadowBlur = shadow->blur();
+        int shadowSpread = shadow->spread();
+        
+        if (shadowOffset.isZero() && !shadowBlur && !shadowSpread)
+            continue;
+        
+        const Color& shadowColor = shadow->color();
+
+        if (shadow->style() == Normal) {
+            RoundedRect fillRect = border;
+            fillRect.inflate(shadowSpread);
+            if (fillRect.isEmpty())
+                continue;
+
+            IntRect shadowRect(border.rect());
+            shadowRect.inflate(shadowBlur + shadowSpread);
+            shadowRect.move(shadowOffset);
+
+            GraphicsContextStateSaver stateSaver(*context);
+            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(paintRect.pixelSnappedWidth() + max(0, shadowOffset.width()) + shadowBlur + 2 * shadowSpread + 1, 0);
+            shadowOffset -= extraOffset;
+            fillRect.move(extraOffset);
+
+            if (shadow->isWebkitBoxShadow())
+                context->setLegacyShadow(shadowOffset, shadowBlur, shadowColor, s->colorSpace());
+            else
+                context->setShadow(shadowOffset, shadowBlur, shadowColor, s->colorSpace());
+
+            if (hasBorderRadius) {
+                RoundedRect rectToClipOut = border;
+
+                // If the box is opaque, it is unnecessary to clip it out. However, doing so saves time
+                // when painting the shadow. On the other hand, it introduces subpixel gaps along the
+                // corners. Those are avoided by insetting the clipping path by one pixel.
+                if (hasOpaqueBackground) {
+                    rectToClipOut.inflateWithRadii(-1);
+                }
+
+                if (!rectToClipOut.isEmpty())
+                    context->clipOutRoundedRect(rectToClipOut);
+
+                RoundedRect influenceRect(shadowRect, border.radii());
+                influenceRect.expandRadii(2 * shadowBlur + shadowSpread);
+                if (allCornersClippedOut(influenceRect, info.rect))
+                    context->fillRect(fillRect.rect(), Color::black, s->colorSpace());
+                else {
+                    fillRect.expandRadii(shadowSpread);
+                    if (!fillRect.isRenderable())
+                        fillRect.adjustRadii();
+                    context->fillRoundedRect(fillRect, Color::black, s->colorSpace());
+                }
+            } else {
+                IntRect rectToClipOut = border.rect();
+
+                // If the box is opaque, it is unnecessary to clip it out. However, doing so saves time
+                // when painting the shadow. On the other hand, it introduces subpixel gaps along the
+                // edges if they are not pixel-aligned. Those are avoided by insetting the clipping path
+                // by one pixel.
+                if (hasOpaqueBackground) {
+                    // FIXME: The function to decide on the policy based on the transform should be a named function.
+                    // FIXME: It's not clear if this check is right. What about integral scale factors?
+                    AffineTransform transform = context->getCTM();
+                    if (transform.a() != 1 || (transform.d() != 1 && transform.d() != -1) || transform.b() || transform.c())
+                        rectToClipOut.inflate(-1);
+                }
+
+                if (!rectToClipOut.isEmpty())
+                    context->clipOut(rectToClipOut);
+                context->fillRect(fillRect.rect(), Color::black, s->colorSpace());
+            }
+        } else {
+            // Inset shadow.
+            IntRect holeRect(border.rect());
+            holeRect.inflate(-shadowSpread);
+
+            if (holeRect.isEmpty()) {
+                if (hasBorderRadius)
+                    context->fillRoundedRect(border, shadowColor, s->colorSpace());
+                else
+                    context->fillRect(border.rect(), shadowColor, s->colorSpace());
+                continue;
+            }
+
+            if (!includeLogicalLeftEdge) {
+                if (isHorizontal) {
+                    holeRect.move(-max(shadowOffset.width(), 0) - shadowBlur, 0);
+                    holeRect.setWidth(holeRect.width() + max(shadowOffset.width(), 0) + shadowBlur);
+                } else {
+                    holeRect.move(0, -max(shadowOffset.height(), 0) - shadowBlur);
+                    holeRect.setHeight(holeRect.height() + max(shadowOffset.height(), 0) + shadowBlur);
+                }
+            }
+            if (!includeLogicalRightEdge) {
+                if (isHorizontal)
+                    holeRect.setWidth(holeRect.width() - min(shadowOffset.width(), 0) + shadowBlur);
+                else
+                    holeRect.setHeight(holeRect.height() - min(shadowOffset.height(), 0) + shadowBlur);
+            }
+
+            Color fillColor(shadowColor.red(), shadowColor.green(), shadowColor.blue(), 255);
+
+            IntRect outerRect = areaCastingShadowInHole(border.rect(), shadowBlur, shadowSpread, shadowOffset);
+            RoundedRect roundedHole(holeRect, border.radii());
+
+            GraphicsContextStateSaver stateSaver(*context);
+            if (hasBorderRadius) {
+                Path path;
+                path.addRoundedRect(border);
+                context->clip(path);
+                roundedHole.shrinkRadii(shadowSpread);
+            } else
+                context->clip(border.rect());
+
+            IntSize extraOffset(2 * paintRect.pixelSnappedWidth() + max(0, shadowOffset.width()) + shadowBlur - 2 * shadowSpread + 1, 0);
+            context->translate(extraOffset.width(), extraOffset.height());
+            shadowOffset -= extraOffset;
+
+            if (shadow->isWebkitBoxShadow())
+                context->setLegacyShadow(shadowOffset, shadowBlur, shadowColor, s->colorSpace());
+            else
+                context->setShadow(shadowOffset, shadowBlur, shadowColor, s->colorSpace());
+
+            context->fillRectWithRoundedHole(outerRect, roundedHole, fillColor, s->colorSpace());
+        }
+    }
+}
+
+LayoutUnit RenderBoxModelObject::containingBlockLogicalWidthForContent() const
+{
+    return containingBlock()->availableLogicalWidth();
+}
+
+RenderBoxModelObject* RenderBoxModelObject::continuation() const
+{
+    if (!continuationMap)
+        return 0;
+    return continuationMap->get(this);
+}
+
+void RenderBoxModelObject::setContinuation(RenderBoxModelObject* continuation)
+{
+    if (continuation) {
+        if (!continuationMap)
+            continuationMap = new ContinuationMap;
+        continuationMap->set(this, continuation);
+    } else {
+        if (continuationMap)
+            continuationMap->remove(this);
+    }
+}
+
+RenderObject* RenderBoxModelObject::firstLetterRemainingText() const
+{
+    if (!firstLetterRemainingTextMap)
+        return 0;
+    return firstLetterRemainingTextMap->get(this);
+}
+
+void RenderBoxModelObject::setFirstLetterRemainingText(RenderObject* remainingText)
+{
+    if (remainingText) {
+        if (!firstLetterRemainingTextMap)
+            firstLetterRemainingTextMap = new FirstLetterRemainingTextMap;
+        firstLetterRemainingTextMap->set(this, remainingText);
+    } else if (firstLetterRemainingTextMap)
+        firstLetterRemainingTextMap->remove(this);
+}
+
+LayoutRect RenderBoxModelObject::localCaretRectForEmptyElement(LayoutUnit width, LayoutUnit textIndentOffset)
+{
+    ASSERT(!firstChild());
+
+    // 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();
+    LayoutUnit height = lineHeight(true, currentStyle->isHorizontalWritingMode() ? HorizontalLine : VerticalLine);
+
+    enum CaretAlignment { alignLeft, alignRight, alignCenter };
+
+    CaretAlignment alignment = alignLeft;
+
+    switch (currentStyle->textAlign()) {
+    case LEFT:
+    case WEBKIT_LEFT:
+        break;
+    case CENTER:
+    case WEBKIT_CENTER:
+        alignment = alignCenter;
+        break;
+    case RIGHT:
+    case WEBKIT_RIGHT:
+        alignment = alignRight;
+        break;
+    case JUSTIFY:
+    case TASTART:
+        if (!currentStyle->isLeftToRightDirection())
+            alignment = alignRight;
+        break;
+    case TAEND:
+        if (currentStyle->isLeftToRightDirection())
+            alignment = alignRight;
+        break;
+    }
+
+    LayoutUnit x = borderLeft() + paddingLeft();
+    LayoutUnit maxX = width - borderRight() - paddingRight();
+
+    switch (alignment) {
+    case alignLeft:
+        if (currentStyle->isLeftToRightDirection())
+            x += textIndentOffset;
+        break;
+    case alignCenter:
+        x = (x + maxX) / 2;
+        if (currentStyle->isLeftToRightDirection())
+            x += textIndentOffset / 2;
+        else
+            x -= textIndentOffset / 2;
+        break;
+    case alignRight:
+        x = maxX - caretWidth;
+        if (!currentStyle->isLeftToRightDirection())
+            x -= textIndentOffset;
+        break;
+    }
+    x = min(x, max<LayoutUnit>(maxX - caretWidth, 0));
+
+    LayoutUnit y = paddingTop() + borderTop();
+
+    return currentStyle->isHorizontalWritingMode() ? LayoutRect(x, y, caretWidth, height) : LayoutRect(y, x, height, caretWidth);
+}
+
+bool RenderBoxModelObject::shouldAntialiasLines(GraphicsContext* context)
+{
+    // FIXME: We may want to not antialias when scaled by an integral value,
+    // and we may want to antialias when translated by a non-integral value.
+    return !context->getCTM().isIdentityOrTranslationOrFlipped();
+}
+
+void RenderBoxModelObject::mapAbsoluteToLocalPoint(MapCoordinatesFlags mode, TransformState& transformState) const
+{
+    RenderObject* o = container();
+    if (!o)
+        return;
+
+    o->mapAbsoluteToLocalPoint(mode, transformState);
+
+    LayoutSize containerOffset = offsetFromContainer(o, LayoutPoint());
+
+    if (!style()->hasOutOfFlowPosition() && o->hasColumns()) {
+        RenderBlock* block = toRenderBlock(o);
+        LayoutPoint point(roundedLayoutPoint(transformState.mappedPoint()));
+        point -= containerOffset;
+        block->adjustForColumnRect(containerOffset, point);
+    }
+
+    bool preserve3D = mode & UseTransforms && (o->style()->preserves3D() || style()->preserves3D());
+    if (mode & UseTransforms && shouldUseTransformFromContainer(o)) {
+        TransformationMatrix t;
+        getTransformFromContainer(o, containerOffset, t);
+        transformState.applyTransform(t, preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
+    } else
+        transformState.move(containerOffset.width(), containerOffset.height(), preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
+}
+
+void RenderBoxModelObject::moveChildTo(RenderBoxModelObject* toBoxModelObject, RenderObject* child, RenderObject* beforeChild, bool fullRemoveInsert)
+{
+    // We assume that callers have cleared their positioned objects list for child moves (!fullRemoveInsert) so the
+    // positioned renderer maps don't become stale. It would be too slow to do the map lookup on each call.
+    ASSERT(!fullRemoveInsert || !isRenderBlock() || !toRenderBlock(this)->hasPositionedObjects());
+
+    ASSERT(this == child->parent());
+    ASSERT(!beforeChild || toBoxModelObject == beforeChild->parent());
+    if (fullRemoveInsert && (toBoxModelObject->isRenderBlock() || toBoxModelObject->isRenderInline())) {
+        // Takes care of adding the new child correctly if toBlock and fromBlock
+        // have different kind of children (block vs inline).
+        toBoxModelObject->addChild(virtualChildren()->removeChildNode(this, child), beforeChild);
+    } else
+        toBoxModelObject->virtualChildren()->insertChildNode(toBoxModelObject, virtualChildren()->removeChildNode(this, child, fullRemoveInsert), beforeChild, fullRemoveInsert);
+}
+
+void RenderBoxModelObject::moveChildrenTo(RenderBoxModelObject* toBoxModelObject, RenderObject* startChild, RenderObject* endChild, RenderObject* beforeChild, bool fullRemoveInsert)
+{
+    // This condition is rarely hit since this function is usually called on
+    // anonymous blocks which can no longer carry positioned objects (see r120761)
+    // or when fullRemoveInsert is false.
+    if (fullRemoveInsert && isRenderBlock()) {
+        RenderBlock* block = toRenderBlock(this);
+        block->removePositionedObjects(0);
+        block->removeFloatingObjects(); 
+    }
+
+    ASSERT(!beforeChild || toBoxModelObject == beforeChild->parent());
+    for (RenderObject* child = startChild; child && child != endChild; ) {
+        // Save our next sibling as moveChildTo will clear it.
+        RenderObject* nextSibling = child->nextSibling();
+        moveChildTo(toBoxModelObject, child, beforeChild, fullRemoveInsert);
+        child = nextSibling;
+    }
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderBoxModelObject.h b/Source/core/rendering/RenderBoxModelObject.h
new file mode 100644
index 0000000..8dc56e7
--- /dev/null
+++ b/Source/core/rendering/RenderBoxModelObject.h
@@ -0,0 +1,338 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * Copyright (C) 2003, 2006, 2007, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2010 Google 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 RenderBoxModelObject_h
+#define RenderBoxModelObject_h
+
+#include "core/platform/graphics/LayoutRect.h"
+#include "core/rendering/RenderLayerModelObject.h"
+#include "core/rendering/style/ShadowData.h"
+
+namespace WebCore {
+
+// Modes for some of the line-related functions.
+enum LinePositionMode { PositionOnContainingLine, PositionOfInteriorLineBoxes };
+enum LineDirectionMode { HorizontalLine, VerticalLine };
+typedef unsigned BorderEdgeFlags;
+
+enum BackgroundBleedAvoidance {
+    BackgroundBleedNone,
+    BackgroundBleedShrinkBackground,
+    BackgroundBleedUseTransparencyLayer,
+    BackgroundBleedBackgroundOverBorder
+};
+
+enum ContentChangeType {
+    ImageChanged,
+    MaskImageChanged,
+    CanvasChanged,
+    CanvasPixelsChanged,
+    VideoChanged,
+    FullScreenChanged
+};
+
+class KeyframeList;
+class StickyPositionViewportConstraints;
+
+// This class is the base for all objects that adhere to the CSS box model as described
+// at http://www.w3.org/TR/CSS21/box.html
+
+class RenderBoxModelObject : public RenderLayerModelObject {
+public:
+    RenderBoxModelObject(ContainerNode*);
+    virtual ~RenderBoxModelObject();
+    
+    LayoutSize relativePositionOffset() const;
+    LayoutSize relativePositionLogicalOffset() const { return style()->isHorizontalWritingMode() ? relativePositionOffset() : relativePositionOffset().transposedSize(); }
+
+    void computeStickyPositionConstraints(StickyPositionViewportConstraints&, const FloatRect& viewportRect) const;
+    LayoutSize stickyPositionOffset() const;
+    LayoutSize stickyPositionLogicalOffset() const { return style()->isHorizontalWritingMode() ? stickyPositionOffset() : stickyPositionOffset().transposedSize(); }
+
+    LayoutSize offsetForInFlowPosition() const;
+    LayoutSize paintOffset() const;
+
+    // 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 LayoutUnit offsetLeft() const;
+    virtual LayoutUnit offsetTop() const;
+    virtual LayoutUnit offsetWidth() const = 0;
+    virtual LayoutUnit offsetHeight() const = 0;
+
+    int pixelSnappedOffsetLeft() const { return roundToInt(offsetLeft()); }
+    int pixelSnappedOffsetTop() const { return roundToInt(offsetTop()); }
+    virtual int pixelSnappedOffsetWidth() const;
+    virtual int pixelSnappedOffsetHeight() const;
+
+    virtual void updateFromStyle() OVERRIDE;
+
+    virtual bool requiresLayer() const OVERRIDE { return isRoot() || isPositioned() || createsGroup() || hasClipPath() || hasTransform() || hasHiddenBackface() || hasReflection() || style()->specifiesColumns(); }
+
+    // This will work on inlines to return the bounding box of all of the lines' border boxes.
+    virtual IntRect borderBoundingBox() const = 0;
+
+    // These return the CSS computed padding values.
+    LayoutUnit computedCSSPaddingTop() const { return computedCSSPadding(style()->paddingTop()); }
+    LayoutUnit computedCSSPaddingBottom() const { return computedCSSPadding(style()->paddingBottom()); }
+    LayoutUnit computedCSSPaddingLeft() const { return computedCSSPadding(style()->paddingLeft()); }
+    LayoutUnit computedCSSPaddingRight() const { return computedCSSPadding(style()->paddingRight()); }
+    LayoutUnit computedCSSPaddingBefore() const { return computedCSSPadding(style()->paddingBefore()); }
+    LayoutUnit computedCSSPaddingAfter() const { return computedCSSPadding(style()->paddingAfter()); }
+    LayoutUnit computedCSSPaddingStart() const { return computedCSSPadding(style()->paddingStart()); }
+    LayoutUnit computedCSSPaddingEnd() const { return computedCSSPadding(style()->paddingEnd()); }
+
+    // These functions are used during layout. Table cells and the MathML
+    // code override them to include some extra intrinsic padding.
+    virtual LayoutUnit paddingTop() const { return computedCSSPaddingTop(); }
+    virtual LayoutUnit paddingBottom() const { return computedCSSPaddingBottom(); }
+    virtual LayoutUnit paddingLeft() const { return computedCSSPaddingLeft(); }
+    virtual LayoutUnit paddingRight() const { return computedCSSPaddingRight(); }
+    virtual LayoutUnit paddingBefore() const { return computedCSSPaddingBefore(); }
+    virtual LayoutUnit paddingAfter() const { return computedCSSPaddingAfter(); }
+    virtual LayoutUnit paddingStart() const { return computedCSSPaddingStart(); }
+    virtual LayoutUnit paddingEnd() const { return computedCSSPaddingEnd(); }
+
+    virtual int borderTop() const { return style()->borderTopWidth(); }
+    virtual int borderBottom() const { return style()->borderBottomWidth(); }
+    virtual int borderLeft() const { return style()->borderLeftWidth(); }
+    virtual int borderRight() const { return style()->borderRightWidth(); }
+    virtual int borderBefore() const { return style()->borderBeforeWidth(); }
+    virtual int borderAfter() const { return style()->borderAfterWidth(); }
+    virtual int borderStart() const { return style()->borderStartWidth(); }
+    virtual int borderEnd() const { return style()->borderEndWidth(); }
+
+    LayoutUnit borderAndPaddingHeight() const { return borderTop() + borderBottom() + paddingTop() + paddingBottom(); }
+    LayoutUnit borderAndPaddingWidth() const { return borderLeft() + borderRight() + paddingLeft() + paddingRight(); }
+    LayoutUnit borderAndPaddingLogicalHeight() const { return borderBefore() + borderAfter() + paddingBefore() + paddingAfter(); }
+    LayoutUnit borderAndPaddingLogicalWidth() const { return borderStart() + borderEnd() + paddingStart() + paddingEnd(); }
+    LayoutUnit borderAndPaddingLogicalLeft() const { return style()->isHorizontalWritingMode() ? borderLeft() + paddingLeft() : borderTop() + paddingTop(); }
+
+    LayoutUnit borderAndPaddingStart() const { return borderStart() + paddingStart(); }
+    LayoutUnit borderAndPaddingBefore() const { return borderBefore() + paddingBefore(); }
+    LayoutUnit borderLogicalLeft() const { return style()->isHorizontalWritingMode() ? borderLeft() : borderTop(); }
+    LayoutUnit borderLogicalRight() const { return style()->isHorizontalWritingMode() ? borderRight() : borderBottom(); }
+
+    LayoutUnit paddingLogicalLeft() const { return style()->isHorizontalWritingMode() ? paddingLeft() : paddingTop(); }
+    LayoutUnit paddingLogicalRight() const { return style()->isHorizontalWritingMode() ? paddingRight() : paddingBottom(); }
+    
+    virtual LayoutUnit marginTop() const = 0;
+    virtual LayoutUnit marginBottom() const = 0;
+    virtual LayoutUnit marginLeft() const = 0;
+    virtual LayoutUnit marginRight() const = 0;
+    virtual LayoutUnit marginBefore(const RenderStyle* otherStyle = 0) const = 0;
+    virtual LayoutUnit marginAfter(const RenderStyle* otherStyle = 0) const = 0;
+    virtual LayoutUnit marginStart(const RenderStyle* otherStyle = 0) const = 0;
+    virtual LayoutUnit marginEnd(const RenderStyle* otherStyle = 0) const = 0;
+    LayoutUnit marginHeight() const { return marginTop() + marginBottom(); }
+    LayoutUnit marginWidth() const { return marginLeft() + marginRight(); }
+    LayoutUnit marginLogicalHeight() const { return marginBefore() + marginAfter(); }
+    LayoutUnit marginLogicalWidth() const { return marginStart() + marginEnd(); }
+
+    bool hasInlineDirectionBordersPaddingOrMargin() const { return hasInlineDirectionBordersOrPadding() || marginStart()|| marginEnd(); }
+    bool hasInlineDirectionBordersOrPadding() const { return borderStart() || borderEnd() || paddingStart()|| paddingEnd(); }
+
+    virtual LayoutUnit containingBlockLogicalWidthForContent() const;
+
+    virtual void childBecameNonInline(RenderObject* /*child*/) { }
+
+    void paintBorder(const PaintInfo&, const LayoutRect&, const RenderStyle*, BackgroundBleedAvoidance = BackgroundBleedNone, bool includeLogicalLeftEdge = true, bool includeLogicalRightEdge = true);
+    bool paintNinePieceImage(GraphicsContext*, const LayoutRect&, const RenderStyle*, const NinePieceImage&, CompositeOperator = CompositeSourceOver);
+    void paintBoxShadow(const PaintInfo&, const LayoutRect&, const RenderStyle*, ShadowStyle, bool includeLogicalLeftEdge = true, bool includeLogicalRightEdge = true);
+    void paintFillLayerExtended(const PaintInfo&, const Color&, const FillLayer*, const LayoutRect&, BackgroundBleedAvoidance, InlineFlowBox* = 0, const LayoutSize& = LayoutSize(), CompositeOperator = CompositeSourceOver, RenderObject* backgroundObject = 0);
+
+    virtual bool boxShadowShouldBeAppliedToBackground(BackgroundBleedAvoidance, InlineFlowBox* = 0) const;
+
+    // Overridden by subclasses to determine line height and baseline position.
+    virtual LayoutUnit lineHeight(bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const = 0;
+    virtual int baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const = 0;
+
+    virtual void mapAbsoluteToLocalPoint(MapCoordinatesFlags, TransformState&) const OVERRIDE;
+
+    void highQualityRepaintTimerFired(Timer<RenderBoxModelObject>*);
+
+    virtual void setSelectionState(SelectionState s);
+
+    bool canHaveBoxInfoInRegion() const { return !isFloating() && !isReplaced() && !isInline() && !hasColumns() && !isTableCell() && isBlockFlow(); }
+
+    void contentChanged(ContentChangeType);
+    bool hasAcceleratedCompositing() const;
+
+    bool startTransition(double, CSSPropertyID, const RenderStyle* fromStyle, const RenderStyle* toStyle);
+    void transitionPaused(double timeOffset, CSSPropertyID);
+    void transitionFinished(CSSPropertyID);
+
+    bool startAnimation(double timeOffset, const CSSAnimationData*, const KeyframeList& keyframes);
+    void animationPaused(double timeOffset, const String& name);
+    void animationFinished(const String& name);
+
+    void suspendAnimations(double time = 0);
+
+protected:
+    virtual void willBeDestroyed();
+
+    class BackgroundImageGeometry {
+    public:
+        IntPoint destOrigin() const { return m_destOrigin; }
+        void setDestOrigin(const IntPoint& destOrigin)
+        {
+            m_destOrigin = destOrigin;
+        }
+        
+        IntRect destRect() const { return m_destRect; }
+        void setDestRect(const IntRect& destRect)
+        {
+            m_destRect = destRect;
+        }
+
+        // Returns the phase relative to the destination rectangle.
+        IntPoint relativePhase() const;
+        
+        IntPoint phase() const { return m_phase; }   
+        void setPhase(const IntPoint& phase)
+        {
+            m_phase = phase;
+        }
+
+        IntSize tileSize() const { return m_tileSize; }    
+        void setTileSize(const IntSize& tileSize)
+        {
+            m_tileSize = tileSize;
+        }
+        
+        void setPhaseX(int x) { m_phase.setX(x); }
+        void setPhaseY(int y) { m_phase.setY(y); }
+        
+        void setNoRepeatX(int xOffset);
+        void setNoRepeatY(int yOffset);
+        
+        void useFixedAttachment(const IntPoint& attachmentPoint);
+        
+        void clip(const IntRect&);
+    private:
+        IntRect m_destRect;
+        IntPoint m_destOrigin;
+        IntPoint m_phase;
+        IntSize m_tileSize;
+    };
+
+    LayoutPoint adjustedPositionRelativeToOffsetParent(const LayoutPoint&) const;
+
+    void calculateBackgroundImageGeometry(const FillLayer*, const LayoutRect& paintRect, BackgroundImageGeometry&, RenderObject* = 0);
+    void getBorderEdgeInfo(class BorderEdge[], const RenderStyle*, bool includeLogicalLeftEdge = true, bool includeLogicalRightEdge = true) const;
+    bool borderObscuresBackgroundEdge(const FloatSize& contextScale) const;
+    bool borderObscuresBackground() const;
+    RoundedRect backgroundRoundedRectAdjustedForBleedAvoidance(GraphicsContext*, const LayoutRect&, BackgroundBleedAvoidance, InlineFlowBox*, const LayoutSize&, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const;
+    LayoutRect borderInnerRectAdjustedForBleedAvoidance(GraphicsContext*, const LayoutRect&, BackgroundBleedAvoidance) const;
+
+    bool shouldPaintAtLowQuality(GraphicsContext*, Image*, const void*, const LayoutSize&);
+
+    RenderBoxModelObject* continuation() const;
+    void setContinuation(RenderBoxModelObject*);
+
+    LayoutRect localCaretRectForEmptyElement(LayoutUnit width, LayoutUnit textIndentOffset);
+
+    static bool shouldAntialiasLines(GraphicsContext*);
+
+    static void clipRoundedInnerRect(GraphicsContext*, const LayoutRect&, const RoundedRect& clipRect);
+
+    bool hasAutoHeightOrContainingBlockWithAutoHeight() const;
+
+public:
+    // For RenderBlocks and RenderInlines with m_style->styleType() == FIRST_LETTER, this tracks their remaining text fragments
+    RenderObject* firstLetterRemainingText() const;
+    void setFirstLetterRemainingText(RenderObject*);
+
+    // These functions are only used internally to manipulate the render tree structure via remove/insert/appendChildNode.
+    // Since they are typically called only to move objects around within anonymous blocks (which only have layers in
+    // the case of column spans), the default for fullRemoveInsert is false rather than true.
+    void moveChildTo(RenderBoxModelObject* toBoxModelObject, RenderObject* child, RenderObject* beforeChild, bool fullRemoveInsert = false);
+    void moveChildTo(RenderBoxModelObject* toBoxModelObject, RenderObject* child, bool fullRemoveInsert = false)
+    {
+        moveChildTo(toBoxModelObject, child, 0, fullRemoveInsert);
+    }
+    void moveAllChildrenTo(RenderBoxModelObject* toBoxModelObject, bool fullRemoveInsert = false)
+    {
+        moveAllChildrenTo(toBoxModelObject, 0, fullRemoveInsert);
+    }
+    void moveAllChildrenTo(RenderBoxModelObject* toBoxModelObject, RenderObject* beforeChild, bool fullRemoveInsert = false)
+    {
+        moveChildrenTo(toBoxModelObject, firstChild(), 0, beforeChild, fullRemoveInsert);
+    }
+    // Move all of the kids from |startChild| up to but excluding |endChild|. 0 can be passed as the |endChild| to denote
+    // that all the kids from |startChild| onwards should be moved.
+    void moveChildrenTo(RenderBoxModelObject* toBoxModelObject, RenderObject* startChild, RenderObject* endChild, bool fullRemoveInsert = false)
+    {
+        moveChildrenTo(toBoxModelObject, startChild, endChild, 0, fullRemoveInsert);
+    }
+    void moveChildrenTo(RenderBoxModelObject* toBoxModelObject, RenderObject* startChild, RenderObject* endChild, RenderObject* beforeChild, bool fullRemoveInsert = false);
+
+private:
+    LayoutUnit computedCSSPadding(Length) const;
+    virtual bool isBoxModelObject() const OVERRIDE FINAL { return true; }
+    
+    virtual LayoutRect frameRectForStickyPositioning() const = 0;
+
+    IntSize calculateFillTileSize(const FillLayer*, const IntSize& scaledPositioningAreaSize) const;
+
+    enum ScaleByEffectiveZoomOrNot { ScaleByEffectiveZoom, DoNotScaleByEffectiveZoom };
+    IntSize calculateImageIntrinsicDimensions(StyleImage*, const IntSize& scaledPositioningAreaSize, ScaleByEffectiveZoomOrNot) const;
+
+    RoundedRect getBackgroundRoundedRect(const LayoutRect&, InlineFlowBox*, LayoutUnit inlineBoxWidth, LayoutUnit inlineBoxHeight,
+        bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const;
+    
+    bool fixedBackgroundPaintsInLocalCoordinates() const;
+
+    void clipBorderSidePolygon(GraphicsContext*, const RoundedRect& outerBorder, const RoundedRect& innerBorder,
+                               BoxSide, bool firstEdgeMatches, bool secondEdgeMatches);
+    void clipBorderSideForComplexInnerPath(GraphicsContext*, const RoundedRect&, const RoundedRect&, BoxSide, const class BorderEdge[]);
+    void paintOneBorderSide(GraphicsContext*, const RenderStyle*, const RoundedRect& outerBorder, const RoundedRect& innerBorder,
+                                const IntRect& sideRect, BoxSide, BoxSide adjacentSide1, BoxSide adjacentSide2, const class BorderEdge[],
+                                const Path*, BackgroundBleedAvoidance, bool includeLogicalLeftEdge, bool includeLogicalRightEdge, bool antialias, const Color* overrideColor = 0);
+    void paintTranslucentBorderSides(GraphicsContext*, const RenderStyle*, const RoundedRect& outerBorder, const RoundedRect& innerBorder, const IntPoint& innerBorderAdjustment,
+        const class BorderEdge[], BorderEdgeFlags, BackgroundBleedAvoidance, bool includeLogicalLeftEdge, bool includeLogicalRightEdge, bool antialias = false);
+    void paintBorderSides(GraphicsContext*, const RenderStyle*, const RoundedRect& outerBorder, const RoundedRect& innerBorder,
+        const IntPoint& innerBorderAdjustment, const class BorderEdge[], BorderEdgeFlags, BackgroundBleedAvoidance,
+        bool includeLogicalLeftEdge, bool includeLogicalRightEdge, bool antialias = false, const Color* overrideColor = 0);
+    void drawBoxSideFromPath(GraphicsContext*, const LayoutRect&, const Path&, const class BorderEdge[],
+                            float thickness, float drawThickness, BoxSide, const RenderStyle*, 
+                            Color, EBorderStyle, BackgroundBleedAvoidance, bool includeLogicalLeftEdge, bool includeLogicalRightEdge);
+};
+
+inline RenderBoxModelObject* toRenderBoxModelObject(RenderObject* object)
+{ 
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isBoxModelObject());
+    return static_cast<RenderBoxModelObject*>(object);
+}
+
+inline const RenderBoxModelObject* toRenderBoxModelObject(const RenderObject* object)
+{ 
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isBoxModelObject());
+    return static_cast<const RenderBoxModelObject*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderBoxModelObject(const RenderBoxModelObject*);
+
+} // namespace WebCore
+
+#endif // RenderBoxModelObject_h
diff --git a/Source/core/rendering/RenderBoxRegionInfo.h b/Source/core/rendering/RenderBoxRegionInfo.h
new file mode 100644
index 0000000..402b53d
--- /dev/null
+++ b/Source/core/rendering/RenderBoxRegionInfo.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2011 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 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 RenderBoxRegionInfo_h
+#define RenderBoxRegionInfo_h
+
+#include "core/platform/LayoutUnit.h"
+#include <wtf/FastAllocBase.h>
+
+namespace WebCore {
+
+class RenderBoxRegionInfo {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    RenderBoxRegionInfo(LayoutUnit logicalLeft, LayoutUnit logicalWidth, bool isShifted)
+        : m_logicalLeft(logicalLeft)
+        , m_logicalWidth(logicalWidth)
+        , m_isShifted(isShifted)
+    { }
+
+    LayoutUnit logicalLeft() const { return m_logicalLeft; }
+    LayoutUnit logicalWidth() const { return m_logicalWidth; }
+    
+    void shiftLogicalLeft(LayoutUnit delta) { m_logicalLeft += delta; m_isShifted = true; }
+
+    bool isShifted() const { return m_isShifted; }
+
+private:
+    LayoutUnit m_logicalLeft;
+    LayoutUnit m_logicalWidth;
+    bool m_isShifted;
+};
+
+} // namespace WebCore
+
+#endif // RenderBoxRegionInfo_h
diff --git a/Source/core/rendering/RenderButton.cpp b/Source/core/rendering/RenderButton.cpp
new file mode 100644
index 0000000..d5cf64b
--- /dev/null
+++ b/Source/core/rendering/RenderButton.cpp
@@ -0,0 +1,158 @@
+/**
+ * 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 "core/rendering/RenderButton.h"
+
+#include "HTMLNames.h"
+#include "core/dom/Document.h"
+#include "core/html/HTMLInputElement.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/rendering/RenderTextFragment.h"
+#include "core/rendering/RenderTheme.h"
+#include "core/rendering/style/StyleInheritedData.h"
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+RenderButton::RenderButton(Element* element)
+    : RenderFlexibleBox(element)
+    , m_buttonText(0)
+    , m_inner(0)
+{
+}
+
+RenderButton::~RenderButton()
+{
+}
+
+void RenderButton::addChild(RenderObject* newChild, RenderObject* beforeChild)
+{
+    if (!m_inner) {
+        // Create an anonymous block.
+        ASSERT(!firstChild());
+        m_inner = createAnonymousBlock(style()->display());
+        setupInnerStyle(m_inner->style());
+        RenderFlexibleBox::addChild(m_inner);
+    }
+    
+    m_inner->addChild(newChild, beforeChild);
+}
+
+void RenderButton::removeChild(RenderObject* oldChild)
+{
+    // m_inner should be the only child, but checking for direct children who
+    // are not m_inner prevents security problems when that assumption is
+    // violated.
+    if (oldChild == m_inner || !m_inner || oldChild->parent() == this) {
+        ASSERT(oldChild == m_inner || !m_inner);
+        RenderFlexibleBox::removeChild(oldChild);
+        m_inner = 0;
+    } else
+        m_inner->removeChild(oldChild);
+}
+
+void RenderButton::styleWillChange(StyleDifference 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 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. Same goes for the other properties.
+        // FIXME: Make this hack unnecessary.
+        m_inner->style()->setFlexGrow(newStyle->initialFlexGrow());
+        m_inner->style()->setMarginTop(newStyle->initialMargin());
+        m_inner->style()->setMarginBottom(newStyle->initialMargin());
+    }
+    RenderBlock::styleWillChange(diff, newStyle);
+}
+
+void RenderButton::styleDidChange(StyleDifference 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.
+        setupInnerStyle(m_inner->style());
+}
+
+void RenderButton::setupInnerStyle(RenderStyle* innerStyle) 
+{
+    ASSERT(innerStyle->refCount() == 1);
+    // RenderBlock::createAnonymousBlock creates a new RenderStyle, so this is
+    // safe to modify.
+    innerStyle->setFlexGrow(1.0f);
+    // Use margin:auto instead of align-items:center to get safe centering, i.e.
+    // when the content overflows, treat it the same as align-items: flex-start.
+    innerStyle->setMarginTop(Length());
+    innerStyle->setMarginBottom(Length());
+    innerStyle->setFlexDirection(style()->flexDirection());
+}
+
+void RenderButton::updateFromElement()
+{
+    // If we're an input element, we may need to change our button text.
+    if (node()->hasTagName(inputTag)) {
+        HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
+        String value = input->valueWithDefault();
+        setText(value);
+    }
+}
+
+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);
+        }
+    }
+}
+
+String RenderButton::text() const
+{
+    return m_buttonText ? m_buttonText->text() : 0;
+}
+
+bool RenderButton::canHaveGeneratedChildren() const
+{
+    // Input elements can't have generated 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 !node()->hasTagName(inputTag);
+}
+
+LayoutRect RenderButton::controlClipRect(const LayoutPoint& additionalOffset) const
+{
+    // Clip to the padding box to at least give content the extra padding space.
+    return LayoutRect(additionalOffset.x() + borderLeft(), additionalOffset.y() + borderTop(), width() - borderLeft() - borderRight(), height() - borderTop() - borderBottom());
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderButton.h b/Source/core/rendering/RenderButton.h
new file mode 100644
index 0000000..53c2cb7
--- /dev/null
+++ b/Source/core/rendering/RenderButton.h
@@ -0,0 +1,87 @@
+/*
+ * 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 "core/rendering/RenderFlexibleBox.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 FINAL : public RenderFlexibleBox {
+public:
+    explicit RenderButton(Element*);
+    virtual ~RenderButton();
+
+    virtual const char* renderName() const { return "RenderButton"; }
+    virtual bool isRenderButton() const { return true; }
+
+    virtual bool canBeSelectionLeaf() const OVERRIDE { return node() && node()->rendererIsEditable(); }
+
+    virtual void addChild(RenderObject* newChild, RenderObject *beforeChild = 0);
+    virtual void removeChild(RenderObject*);
+    virtual void removeLeftoverAnonymousBlock(RenderBlock*) { }
+    virtual bool createsAnonymousWrapper() const { return true; }
+
+    void setupInnerStyle(RenderStyle*);
+    virtual void updateFromElement();
+
+    virtual bool canHaveGeneratedChildren() const OVERRIDE;
+    virtual bool hasControlClip() const { return true; }
+    virtual LayoutRect controlClipRect(const LayoutPoint&) const;
+
+    void setText(const String&);
+    String text() const;
+
+private:
+    virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle);
+    virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+
+    virtual bool hasLineIfEmpty() const { return node() && node()->toInputElement(); }
+
+    virtual bool requiresForcedStyleRecalcPropagation() const { return true; }
+
+    RenderTextFragment* m_buttonText;
+    RenderBlock* m_inner;
+};
+
+inline RenderButton* toRenderButton(RenderObject* object)
+{ 
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isRenderButton());
+    return static_cast<RenderButton*>(object);
+}
+
+inline const RenderButton* toRenderButton(const RenderObject* object)
+{ 
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isRenderButton());
+    return static_cast<const RenderButton*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderButton(const RenderButton*);
+
+} // namespace WebCore
+
+#endif // RenderButton_h
diff --git a/Source/core/rendering/RenderCombineText.cpp b/Source/core/rendering/RenderCombineText.cpp
new file mode 100644
index 0000000..c9c7fbc
--- /dev/null
+++ b/Source/core/rendering/RenderCombineText.cpp
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2011 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 "core/rendering/RenderCombineText.h"
+
+#include "core/rendering/RenderBlock.h"
+#include "core/rendering/style/StyleInheritedData.h"
+
+namespace WebCore {
+
+const float textCombineMargin = 1.1f; // Allow em + 10% margin
+
+RenderCombineText::RenderCombineText(Node* node, PassRefPtr<StringImpl> string)
+     : RenderText(node, string)
+     , m_combinedTextWidth(0)
+     , m_isCombined(false)
+     , m_needsFontUpdate(false)
+{
+}
+
+void RenderCombineText::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
+{
+    setStyleInternal(RenderStyle::clone(style()));
+    RenderText::styleDidChange(diff, oldStyle);
+
+    if (m_isCombined) {
+        RenderText::setTextInternal(originalText()); // This RenderCombineText has been combined once. Restore the original text for the next combineText().
+        m_isCombined = false;
+    }
+
+    m_needsFontUpdate = true;
+}
+
+void RenderCombineText::setTextInternal(PassRefPtr<StringImpl> text)
+{
+    RenderText::setTextInternal(text);
+
+    m_needsFontUpdate = true;
+}
+
+float RenderCombineText::width(unsigned from, unsigned length, const Font& font, float xPosition, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
+{
+    if (!characters())
+        return 0;
+
+    if (m_isCombined)
+        return font.size();
+
+    return RenderText::width(from, length, font, xPosition, fallbackFonts, glyphOverflow);
+}
+
+void RenderCombineText::adjustTextOrigin(FloatPoint& textOrigin, const FloatRect& boxRect) const
+{
+    if (m_isCombined)
+        textOrigin.move(boxRect.height() / 2 - ceilf(m_combinedTextWidth) / 2, style()->font().pixelSize());
+}
+
+void RenderCombineText::getStringToRender(int start, String& string, int& length) const
+{
+    ASSERT(start >= 0);
+    if (m_isCombined) {
+        string = originalText();
+        length = string.length();
+        return;
+    }
+ 
+    string = text();
+    string = string.substringSharingImpl(static_cast<unsigned>(start), length);
+}
+
+void RenderCombineText::combineText()
+{
+    if (!m_needsFontUpdate)
+        return;
+
+    m_isCombined = false;
+    m_needsFontUpdate = false;
+
+    // CSS3 spec says text-combine works only in vertical writing mode.
+    if (style()->isHorizontalWritingMode())
+        return;
+
+    TextRun run = RenderBlock::constructTextRun(this, originalFont(), this, style());
+    FontDescription description = originalFont().fontDescription();
+    float emWidth = description.computedSize() * textCombineMargin;
+    bool shouldUpdateFont = false;
+
+    description.setOrientation(Horizontal); // We are going to draw combined text horizontally.
+    m_combinedTextWidth = originalFont().width(run);
+    m_isCombined = m_combinedTextWidth <= emWidth;
+
+    FontSelector* fontSelector = style()->font().fontSelector();
+
+    if (m_isCombined)
+        shouldUpdateFont = style()->setFontDescription(description); // Need to change font orientation to horizontal.
+    else {
+        // Need to try compressed glyphs.
+        static const FontWidthVariant widthVariants[] = { HalfWidth, ThirdWidth, QuarterWidth };
+        for (size_t i = 0 ; i < WTF_ARRAY_LENGTH(widthVariants) ; ++i) {
+            description.setWidthVariant(widthVariants[i]);
+            Font compressedFont = Font(description, style()->font().letterSpacing(), style()->font().wordSpacing());
+            compressedFont.update(fontSelector);
+            float runWidth = compressedFont.width(run);
+            if (runWidth <= emWidth) {
+                m_combinedTextWidth = runWidth;
+                m_isCombined = true;
+
+                // Replace my font with the new one.
+                shouldUpdateFont = style()->setFontDescription(description);
+                break;
+            }
+        }
+    }
+
+    if (!m_isCombined)
+        shouldUpdateFont = style()->setFontDescription(originalFont().fontDescription());
+
+    if (shouldUpdateFont)
+        style()->font().update(fontSelector);
+
+    if (m_isCombined) {
+        DEFINE_STATIC_LOCAL(String, objectReplacementCharacterString, (&objectReplacementCharacter, 1));
+        RenderText::setTextInternal(objectReplacementCharacterString.impl());
+    }
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderCombineText.h b/Source/core/rendering/RenderCombineText.h
new file mode 100644
index 0000000..c53d6df
--- /dev/null
+++ b/Source/core/rendering/RenderCombineText.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2011 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 RenderCombineText_h
+#define RenderCombineText_h
+
+#include "core/platform/graphics/Font.h"
+#include "core/rendering/RenderText.h"
+
+namespace WebCore {
+
+class RenderCombineText FINAL : public RenderText {
+public:
+    RenderCombineText(Node*, PassRefPtr<StringImpl>);
+
+    void combineText();
+    void adjustTextOrigin(FloatPoint& textOrigin, const FloatRect& boxRect) const;
+    void getStringToRender(int, String& string, int& length) const;
+    bool isCombined() const { return m_isCombined; }
+    float combinedTextWidth(const Font& font) const { return font.size(); }
+    const Font& originalFont() const { return parent()->style()->font(); }
+
+private:
+    virtual bool isCombineText() const { return true; }
+    virtual float width(unsigned from, unsigned length, const Font&, float xPosition, HashSet<const SimpleFontData*>* fallbackFonts = 0, GlyphOverflow* = 0) const;
+    virtual const char* renderName() const { return "RenderCombineText"; }
+    virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+    virtual void setTextInternal(PassRefPtr<StringImpl>);
+
+    float m_combinedTextWidth;
+    bool m_isCombined : 1;
+    bool m_needsFontUpdate : 1;
+};
+
+inline RenderCombineText* toRenderCombineText(RenderObject* object)
+{ 
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isCombineText());
+    return static_cast<RenderCombineText*>(object);
+}
+
+inline const RenderCombineText* toRenderCombineText(const RenderObject* object)
+{ 
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isCombineText());
+    return static_cast<const RenderCombineText*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderCombineText(const RenderCombineText*);
+
+} // namespace WebCore
+
+#endif // RenderCombineText_h
diff --git a/Source/core/rendering/RenderCounter.cpp b/Source/core/rendering/RenderCounter.cpp
new file mode 100644
index 0000000..2d78cf3
--- /dev/null
+++ b/Source/core/rendering/RenderCounter.cpp
@@ -0,0 +1,635 @@
+/**
+ * Copyright (C) 2004 Allan Sandfeld Jensen (kde@carewolf.com)
+ * 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 "core/rendering/RenderCounter.h"
+
+#include "HTMLNames.h"
+#include "core/dom/Document.h"
+#include "core/dom/Element.h"
+#include "core/dom/NodeTraversal.h"
+#include "core/html/HTMLOListElement.h"
+#include "core/rendering/CounterNode.h"
+#include "core/rendering/RenderListItem.h"
+#include "core/rendering/RenderListMarker.h"
+#include "core/rendering/RenderView.h"
+#include "core/rendering/style/RenderStyle.h"
+#include <wtf/StdLibExtras.h>
+
+#ifndef NDEBUG
+#include <stdio.h>
+#endif
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+typedef HashMap<AtomicString, RefPtr<CounterNode> > CounterMap;
+typedef HashMap<const RenderObject*, OwnPtr<CounterMap> > CounterMaps;
+
+static CounterNode* makeCounterNode(RenderObject*, const AtomicString& identifier, bool alwaysCreateCounter);
+
+static CounterMaps& counterMaps()
+{
+    DEFINE_STATIC_LOCAL(CounterMaps, staticCounterMaps, ());
+    return staticCounterMaps;
+}
+
+// This function processes the renderer tree in the order of the DOM tree
+// including pseudo elements as defined in CSS 2.1.
+static RenderObject* previousInPreOrder(const RenderObject* object)
+{
+    Element* self = toElement(object->node());
+    Element* previous = ElementTraversal::previousIncludingPseudo(self);
+    while (previous && !previous->renderer())
+        previous = ElementTraversal::previousIncludingPseudo(previous);
+    return previous ? previous->renderer() : 0;
+}
+
+// This function processes the renderer tree in the order of the DOM tree
+// including pseudo elements as defined in CSS 2.1.
+static RenderObject* previousSiblingOrParent(const RenderObject* object)
+{
+    Element* self = toElement(object->node());
+    Element* previous = ElementTraversal::pseudoAwarePreviousSibling(self);
+    while (previous && !previous->renderer())
+        previous = ElementTraversal::pseudoAwarePreviousSibling(previous);
+    if (previous)
+        return previous->renderer();
+    previous = self->parentElement();
+    return previous ? previous->renderer() : 0;
+}
+
+static inline Element* parentElement(RenderObject* object)
+{
+    return toElement(object->node())->parentElement();
+}
+
+static inline bool areRenderersElementsSiblings(RenderObject* first, RenderObject* second)
+{
+    return parentElement(first) == parentElement(second);
+}
+
+// This function processes the renderer tree in the order of the DOM tree
+// including pseudo elements as defined in CSS 2.1.
+static RenderObject* nextInPreOrder(const RenderObject* object, const Element* stayWithin, bool skipDescendants = false)
+{
+    Element* self = toElement(object->node());
+    Element* next = skipDescendants ? ElementTraversal::nextIncludingPseudoSkippingChildren(self, stayWithin) : ElementTraversal::nextIncludingPseudo(self, stayWithin);
+    while (next && !next->renderer())
+        next = skipDescendants ? ElementTraversal::nextIncludingPseudoSkippingChildren(next, stayWithin) : ElementTraversal::nextIncludingPseudo(next, stayWithin);
+    return next ? next->renderer() : 0;
+}
+
+static bool planCounter(RenderObject* object, const AtomicString& identifier, 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;
+    Node* generatingNode = object->generatingNode();
+    // We must have a generating node or else we cannot have a counter.
+    if (!generatingNode)
+        return false;
+    RenderStyle* style = object->style();
+    ASSERT(style);
+
+    switch (style->styleType()) {
+    case NOPSEUDO:
+        // Sometimes nodes have more then one renderer. Only the first one gets the counter
+        // LayoutTests/http/tests/css/counter-crash.html
+        if (generatingNode->renderer() != object)
+            return false;
+        break;
+    case BEFORE:
+    case AFTER:
+        break;
+    default:
+        return false; // Counters are forbidden from all other pseudo elements.
+    }
+
+    const CounterDirectives directives = style->getCounterDirectives(identifier);
+    if (directives.isDefined()) {
+        value = directives.combinedValue();
+        isReset = directives.isReset();
+        return true;
+    }
+
+    if (identifier == "list-item") {
+        if (object->isListItem()) {
+            if (toRenderListItem(object)->hasExplicitValue()) {
+                value = toRenderListItem(object)->explicitValue();
+                isReset = true;
+                return true;
+            }
+            value = 1;
+            isReset = false;
+            return true;
+        }
+        if (Node* e = object->node()) {
+            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;
+}
+
+// - Finds the insertion point for the counter described by counterOwner, isReset and 
+// identifier in the CounterNode tree for identifier and sets parent and
+// previousSibling accordingly.
+// - The function returns true if the counter whose insertion point is searched is NOT
+// the root of the tree.
+// - The root of the tree is a counter reference that is not in the scope of any other
+// counter with the same identifier.
+// - All the counter references with the same identifier as this one that are in
+// children or subsequent siblings of the renderer that owns the root of the tree
+// form the rest of of the nodes of the tree.
+// - The root of the tree is always a reset type reference.
+// - A subtree rooted at any reset node in the tree is equivalent to all counter 
+// references that are in the scope of the counter or nested counter defined by that
+// reset node.
+// - Non-reset CounterNodes cannot have descendants.
+
+static bool findPlaceForCounter(RenderObject* counterOwner, const AtomicString& identifier, bool isReset, RefPtr<CounterNode>& parent, RefPtr<CounterNode>& previousSibling)
+{
+    // We cannot stop searching for counters with the same identifier before we also
+    // check this renderer, because it may affect the positioning in the tree of our counter.
+    RenderObject* searchEndRenderer = previousSiblingOrParent(counterOwner);
+    // We check renderers in preOrder from the renderer that our counter is attached to
+    // towards the begining of the document for counters with the same identifier as the one
+    // we are trying to find a place for. This is the next renderer to be checked.
+    RenderObject* currentRenderer = previousInPreOrder(counterOwner);
+    previousSibling = 0;
+    RefPtr<CounterNode> previousSiblingProtector = 0;
+
+    while (currentRenderer) {
+        CounterNode* currentCounter = makeCounterNode(currentRenderer, identifier, false);
+        if (searchEndRenderer == currentRenderer) {
+            // We may be at the end of our search.
+            if (currentCounter) {
+                // We have a suitable counter on the EndSearchRenderer.
+                if (previousSiblingProtector) { // But we already found another counter that we come after.
+                    if (currentCounter->actsAsReset()) {
+                        // We found a reset counter that is on a renderer that is a sibling of ours or a parent.
+                        if (isReset && areRenderersElementsSiblings(currentRenderer, counterOwner)) {
+                            // We are also a reset counter and the previous reset was on a sibling renderer
+                            // hence we are the next sibling of that counter if that reset is not a root or
+                            // we are a root node if that reset is a root.
+                            parent = currentCounter->parent();
+                            previousSibling = parent ? currentCounter : 0;
+                            return parent;
+                        }
+                        // We are not a reset node or the previous reset must be on an ancestor of our owner renderer
+                        // hence we must be a child of that reset counter.
+                        parent = currentCounter;
+                        // In some cases renders can be reparented (ex. nodes inside a table but not in a column or row).
+                        // In these cases the identified previousSibling will be invalid as its parent is different from
+                        // our identified parent.
+                        if (previousSiblingProtector->parent() != currentCounter)
+                            previousSiblingProtector = 0;
+
+                        previousSibling = previousSiblingProtector.get();
+                        return true;
+                    }
+                    // CurrentCounter, the counter at the EndSearchRenderer, is not reset.
+                    if (!isReset || !areRenderersElementsSiblings(currentRenderer, counterOwner)) {
+                        // If the node we are placing is not reset or we have found a counter that is attached
+                        // to an ancestor of the placed counter's owner renderer we know we are a sibling of that node.
+                        if (currentCounter->parent() != previousSiblingProtector->parent())
+                            return false;
+
+                        parent = currentCounter->parent();
+                        previousSibling = previousSiblingProtector.get();
+                        return true;
+                    }
+                } else { 
+                    // We are at the potential end of the search, but we had no previous sibling candidate
+                    // In this case we follow pretty much the same logic as above but no ASSERTs about 
+                    // previousSibling, and when we are a sibling of the end counter we must set previousSibling
+                    // to currentCounter.
+                    if (currentCounter->actsAsReset()) {
+                        if (isReset && areRenderersElementsSiblings(currentRenderer, counterOwner)) {
+                            parent = currentCounter->parent();
+                            previousSibling = currentCounter;
+                            return parent;
+                        }
+                        parent = currentCounter;
+                        previousSibling = previousSiblingProtector.get();
+                        return true;
+                    }
+                    if (!isReset || !areRenderersElementsSiblings(currentRenderer, counterOwner)) {
+                        parent = currentCounter->parent();
+                        previousSibling = currentCounter;
+                        return true;
+                    }
+                    previousSiblingProtector = currentCounter;
+                }
+            }
+            // We come here if the previous sibling or parent of our owner renderer had no
+            // good counter, or we are a reset node and the counter on the previous sibling
+            // of our owner renderer was not a reset counter.
+            // Set a new goal for the end of the search.
+            searchEndRenderer = previousSiblingOrParent(currentRenderer);
+        } else {
+            // We are searching descendants of a previous sibling of the renderer that the
+            // counter being placed is attached to.
+            if (currentCounter) {
+                // We found a suitable counter.
+                if (previousSiblingProtector) {
+                    // Since we had a suitable previous counter before, we should only consider this one as our 
+                    // previousSibling if it is a reset counter and hence the current previousSibling is its child.
+                    if (currentCounter->actsAsReset()) {
+                        previousSiblingProtector = currentCounter;
+                        // We are no longer interested in previous siblings of the currentRenderer or their children
+                        // as counters they may have attached cannot be the previous sibling of the counter we are placing.
+                        currentRenderer = parentElement(currentRenderer)->renderer();
+                        continue;
+                    }
+                } else
+                    previousSiblingProtector = currentCounter;
+                currentRenderer = previousSiblingOrParent(currentRenderer);
+                continue;
+            }
+        }
+        // This function is designed so that the same test is not done twice in an iteration, except for this one
+        // which may be done twice in some cases. Rearranging the decision points though, to accommodate this 
+        // performance improvement would create more code duplication than is worthwhile in my oppinion and may further
+        // impede the readability of this already complex algorithm.
+        if (previousSiblingProtector)
+            currentRenderer = previousSiblingOrParent(currentRenderer);
+        else
+            currentRenderer = previousInPreOrder(currentRenderer);
+    }
+    return false;
+}
+
+static CounterNode* makeCounterNode(RenderObject* object, const AtomicString& identifier, bool alwaysCreateCounter)
+{
+    ASSERT(object);
+
+    if (object->hasCounterNodeMap()) {
+        if (CounterMap* nodeMap = counterMaps().get(object)) {
+            if (CounterNode* node = nodeMap->get(identifier).get())
+                return node;
+        }
+    }
+
+    bool isReset = false;
+    int value = 0;
+    if (!planCounter(object, identifier, isReset, value) && !alwaysCreateCounter)
+        return 0;
+
+    RefPtr<CounterNode> newParent = 0;
+    RefPtr<CounterNode> newPreviousSibling = 0;
+    RefPtr<CounterNode> newNode = CounterNode::create(object, isReset, value);
+    if (findPlaceForCounter(object, identifier, isReset, newParent, newPreviousSibling))
+        newParent->insertAfter(newNode.get(), newPreviousSibling.get(), identifier);
+    CounterMap* nodeMap;
+    if (object->hasCounterNodeMap())
+        nodeMap = counterMaps().get(object);
+    else {
+        nodeMap = new CounterMap;
+        counterMaps().set(object, adoptPtr(nodeMap));
+        object->setHasCounterNodeMap(true);
+    }
+    nodeMap->set(identifier, newNode);
+    if (newNode->parent())
+        return newNode.get();
+    // Checking if some nodes that were previously counter tree root nodes
+    // should become children of this node now.
+    CounterMaps& maps = counterMaps();
+    Element* stayWithin = parentElement(object);
+    bool skipDescendants;
+    for (RenderObject* currentRenderer = nextInPreOrder(object, stayWithin); currentRenderer; currentRenderer = nextInPreOrder(currentRenderer, stayWithin, skipDescendants)) {
+        skipDescendants = false;
+        if (!currentRenderer->hasCounterNodeMap())
+            continue;
+        CounterNode* currentCounter = maps.get(currentRenderer)->get(identifier).get();
+        if (!currentCounter)
+            continue;
+        skipDescendants = true;
+        if (currentCounter->parent())
+            continue;
+        if (stayWithin == parentElement(currentRenderer) && currentCounter->hasResetType())
+            break;
+        newNode->insertAfter(currentCounter, newNode->lastChild(), identifier);
+    }
+    return newNode.get();
+}
+
+RenderCounter::RenderCounter(Document* node, const CounterContent& counter)
+    : RenderText(node, StringImpl::empty())
+    , m_counter(counter)
+    , m_counterNode(0)
+    , m_nextForSameCounter(0)
+{
+    view()->addRenderCounter();
+}
+
+RenderCounter::~RenderCounter()
+{
+    if (m_counterNode) {
+        m_counterNode->removeRenderer(this);
+        ASSERT(!m_counterNode);
+    }
+}
+
+void RenderCounter::willBeDestroyed()
+{
+    if (view())
+        view()->removeRenderCounter();
+    RenderText::willBeDestroyed();
+}
+
+const char* RenderCounter::renderName() const
+{
+    return "RenderCounter";
+}
+
+bool RenderCounter::isCounter() const
+{
+    return true;
+}
+
+PassRefPtr<StringImpl> RenderCounter::originalText() const
+{
+    if (!m_counterNode) {
+        RenderObject* beforeAfterContainer = parent();
+        while (true) {
+            if (!beforeAfterContainer)
+                return 0;
+            if (!beforeAfterContainer->isAnonymous() && !beforeAfterContainer->isPseudoElement())
+                return 0; // RenderCounters are restricted to before and after pseudo elements
+            PseudoId containerStyle = beforeAfterContainer->style()->styleType();
+            if ((containerStyle == BEFORE) || (containerStyle == AFTER))
+                break;
+            beforeAfterContainer = beforeAfterContainer->parent();
+        }
+        makeCounterNode(beforeAfterContainer, m_counter.identifier(), true)->addRenderer(const_cast<RenderCounter*>(this));
+        ASSERT(m_counterNode);
+    }
+    CounterNode* child = m_counterNode;
+    int value = child->actsAsReset() ? child->value() : child->countInParent();
+
+    String text = listMarkerText(m_counter.listStyle(), value);
+
+    if (!m_counter.separator().isNull()) {
+        if (!child->actsAsReset())
+            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::updateCounter()
+{
+    computePreferredLogicalWidths(0);
+}
+
+void RenderCounter::computePreferredLogicalWidths(float lead)
+{
+#ifndef NDEBUG
+    // FIXME: We shouldn't be modifying the tree in computePreferredLogicalWidths.
+    // Instead, we should properly hook the appropriate changes in the DOM and modify
+    // the render tree then. When that's done, we also won't need to override
+    // computePreferredLogicalWidths at all.
+    // https://bugs.webkit.org/show_bug.cgi?id=104829
+    SetLayoutNeededForbiddenScope layoutForbiddenScope(this, false);
+#endif
+
+    setTextInternal(originalText());
+
+    RenderText::computePreferredLogicalWidths(lead);
+}
+
+void RenderCounter::invalidate()
+{
+    m_counterNode->removeRenderer(this);
+    ASSERT(!m_counterNode);
+    if (documentBeingDestroyed())
+        return;
+    setNeedsLayoutAndPrefWidthsRecalc();
+}
+
+static void destroyCounterNodeWithoutMapRemoval(const AtomicString& identifier, CounterNode* node)
+{
+    CounterNode* previous;
+    for (RefPtr<CounterNode> child = node->lastDescendant(); child && child != node; child = previous) {
+        previous = child->previousInPreOrder();
+        child->parent()->removeChild(child.get());
+        ASSERT(counterMaps().get(child->owner())->get(identifier) == child);
+        counterMaps().get(child->owner())->remove(identifier);
+    }
+    if (CounterNode* parent = node->parent())
+        parent->removeChild(node);
+}
+
+void RenderCounter::destroyCounterNodes(RenderObject* owner)
+{
+    CounterMaps& maps = counterMaps();
+    CounterMaps::iterator mapsIterator = maps.find(owner);
+    if (mapsIterator == maps.end())
+        return;
+    CounterMap* map = mapsIterator->value.get();
+    CounterMap::const_iterator end = map->end();
+    for (CounterMap::const_iterator it = map->begin(); it != end; ++it) {
+        destroyCounterNodeWithoutMapRemoval(it->key, it->value.get());
+    }
+    maps.remove(mapsIterator);
+    owner->setHasCounterNodeMap(false);
+}
+
+void RenderCounter::destroyCounterNode(RenderObject* owner, const AtomicString& identifier)
+{
+    CounterMap* map = counterMaps().get(owner);
+    if (!map)
+        return;
+    CounterMap::iterator mapIterator = map->find(identifier);
+    if (mapIterator == map->end())
+        return;
+    destroyCounterNodeWithoutMapRemoval(identifier, mapIterator->value.get());
+    map->remove(mapIterator);
+    // We do not delete "map" here even if empty because we expect to reuse
+    // it soon. In order for a renderer to lose all its counters permanently,
+    // a style change for the renderer involving removal of all counter
+    // directives must occur, in which case, RenderCounter::destroyCounterNodes()
+    // must be called.
+    // The destruction of the Renderer (possibly caused by the removal of its 
+    // associated DOM node) is the other case that leads to the permanent
+    // destruction of all counters attached to a Renderer. In this case
+    // RenderCounter::destroyCounterNodes() must be and is now called, too.
+    // RenderCounter::destroyCounterNodes() handles destruction of the counter
+    // map associated with a renderer, so there is no risk in leaking the map.
+}
+
+void RenderCounter::rendererRemovedFromTree(RenderObject* renderer)
+{
+    ASSERT(renderer->view());
+    if (!renderer->view()->hasRenderCounters())
+        return;
+    RenderObject* currentRenderer = renderer->lastLeafChild();
+    if (!currentRenderer)
+        currentRenderer = renderer;
+    while (true) {
+        destroyCounterNodes(currentRenderer);
+        if (currentRenderer == renderer)
+            break;
+        currentRenderer = currentRenderer->previousInPreOrder();
+    }
+}
+
+static void updateCounters(RenderObject* renderer)
+{
+    ASSERT(renderer->style());
+    const CounterDirectiveMap* directiveMap = renderer->style()->counterDirectives();
+    if (!directiveMap)
+        return;
+    CounterDirectiveMap::const_iterator end = directiveMap->end();
+    if (!renderer->hasCounterNodeMap()) {
+        for (CounterDirectiveMap::const_iterator it = directiveMap->begin(); it != end; ++it)
+            makeCounterNode(renderer, it->key, false);
+        return;
+    }
+    CounterMap* counterMap = counterMaps().get(renderer);
+    ASSERT(counterMap);
+    for (CounterDirectiveMap::const_iterator it = directiveMap->begin(); it != end; ++it) {
+        RefPtr<CounterNode> node = counterMap->get(it->key);
+        if (!node) {
+            makeCounterNode(renderer, it->key, false);
+            continue;
+        }
+        RefPtr<CounterNode> newParent = 0;
+        RefPtr<CounterNode> newPreviousSibling = 0;
+        
+        findPlaceForCounter(renderer, it->key, node->hasResetType(), newParent, newPreviousSibling);
+        if (node != counterMap->get(it->key))
+            continue;
+        CounterNode* parent = node->parent();
+        if (newParent == parent && newPreviousSibling == node->previousSibling())
+            continue;
+        if (parent)
+            parent->removeChild(node.get());
+        if (newParent)
+            newParent->insertAfter(node.get(), newPreviousSibling.get(), it->key);
+    }
+}
+
+void RenderCounter::rendererSubtreeAttached(RenderObject* renderer)
+{
+    ASSERT(renderer->view());
+    if (!renderer->view()->hasRenderCounters())
+        return;
+    Node* node = renderer->node();
+    if (node)
+        node = node->parentNode();
+    else
+        node = renderer->generatingNode();
+    if (node && !node->attached())
+        return; // No need to update if the parent is not attached yet
+    for (RenderObject* descendant = renderer; descendant; descendant = descendant->nextInPreOrder(renderer))
+        updateCounters(descendant);
+}
+
+void RenderCounter::rendererStyleChanged(RenderObject* renderer, const RenderStyle* oldStyle, const RenderStyle* newStyle)
+{
+    Node* node = renderer->generatingNode();
+    if (!node || !node->attached())
+        return; // cannot have generated content or if it can have, it will be handled during attaching
+    const CounterDirectiveMap* newCounterDirectives;
+    const CounterDirectiveMap* oldCounterDirectives;
+    if (oldStyle && (oldCounterDirectives = oldStyle->counterDirectives())) {
+        if (newStyle && (newCounterDirectives = newStyle->counterDirectives())) {
+            CounterDirectiveMap::const_iterator newMapEnd = newCounterDirectives->end();
+            CounterDirectiveMap::const_iterator oldMapEnd = oldCounterDirectives->end();
+            for (CounterDirectiveMap::const_iterator it = newCounterDirectives->begin(); it != newMapEnd; ++it) {
+                CounterDirectiveMap::const_iterator oldMapIt = oldCounterDirectives->find(it->key);
+                if (oldMapIt != oldMapEnd) {
+                    if (oldMapIt->value == it->value)
+                        continue;
+                    RenderCounter::destroyCounterNode(renderer, it->key);
+                }
+                // We must create this node here, because the changed node may be a node with no display such as
+                // as those created by the increment or reset directives and the re-layout that will happen will
+                // not catch the change if the node had no children.
+                makeCounterNode(renderer, it->key, false);
+            }
+            // Destroying old counters that do not exist in the new counterDirective map.
+            for (CounterDirectiveMap::const_iterator it = oldCounterDirectives->begin(); it !=oldMapEnd; ++it) {
+                if (!newCounterDirectives->contains(it->key))
+                    RenderCounter::destroyCounterNode(renderer, it->key);
+            }
+        } else {
+            if (renderer->hasCounterNodeMap())
+                RenderCounter::destroyCounterNodes(renderer);
+        }
+    } else if (newStyle && (newCounterDirectives = newStyle->counterDirectives())) {
+        CounterDirectiveMap::const_iterator newMapEnd = newCounterDirectives->end();
+        for (CounterDirectiveMap::const_iterator it = newCounterDirectives->begin(); it != newMapEnd; ++it) {
+            // We must create this node here, because the added node may be a node with no display such as
+            // as those created by the increment or reset directives and the re-layout that will happen will
+            // not catch the change if the node had no children.
+            makeCounterNode(renderer, it->key, false);
+        }
+    }
+}
+
+} // namespace WebCore
+
+#ifndef NDEBUG
+
+void showCounterRendererTree(const WebCore::RenderObject* renderer, const char* counterName)
+{
+    if (!renderer)
+        return;
+    const WebCore::RenderObject* root = renderer;
+    while (root->parent())
+        root = root->parent();
+
+    AtomicString identifier(counterName);
+    for (const WebCore::RenderObject* current = root; current; current = current->nextInPreOrder()) {
+        fprintf(stderr, "%c", (current == renderer) ? '*' : ' ');
+        for (const WebCore::RenderObject* parent = current; parent && parent != root; parent = parent->parent())
+            fprintf(stderr, "    ");
+        fprintf(stderr, "%p N:%p P:%p PS:%p NS:%p C:%p\n",
+            current, current->node(), current->parent(), current->previousSibling(),
+            current->nextSibling(), current->hasCounterNodeMap() ?
+            counterName ? WebCore::counterMaps().get(current)->get(identifier).get() : (WebCore::CounterNode*)1 : (WebCore::CounterNode*)0);
+    }
+    fflush(stderr);
+}
+
+#endif // NDEBUG
diff --git a/Source/core/rendering/RenderCounter.h b/Source/core/rendering/RenderCounter.h
new file mode 100644
index 0000000..654af70
--- /dev/null
+++ b/Source/core/rendering/RenderCounter.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2004 Allan Sandfeld Jensen (kde@carewolf.com)
+ * Copyright (C) 2006, 2007, 2008, 2009 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 "core/rendering/RenderText.h"
+#include "core/rendering/style/CounterContent.h"
+
+namespace WebCore {
+
+class CounterNode;
+
+class RenderCounter FINAL : public RenderText {
+public:
+    RenderCounter(Document*, const CounterContent&);
+    virtual ~RenderCounter();
+
+    static void destroyCounterNodes(RenderObject*);
+    static void destroyCounterNode(RenderObject*, const AtomicString& identifier);
+    static void rendererSubtreeAttached(RenderObject*);
+    static void rendererRemovedFromTree(RenderObject*);
+    static void rendererStyleChanged(RenderObject*, const RenderStyle* oldStyle, const RenderStyle* newStyle);
+
+    void updateCounter();
+
+protected:
+    virtual void willBeDestroyed();
+
+private:
+    virtual const char* renderName() const;
+    virtual bool isCounter() const;
+    virtual PassRefPtr<StringImpl> originalText() const;
+    
+    virtual void computePreferredLogicalWidths(float leadWidth) OVERRIDE;
+
+    // Removes the reference to the CounterNode associated with this renderer.
+    // This is used to cause a counter display update when the CounterNode tree changes.
+    void invalidate();
+
+    CounterContent m_counter;
+    CounterNode* m_counterNode;
+    RenderCounter* m_nextForSameCounter;
+    friend class CounterNode;
+};
+
+inline RenderCounter* toRenderCounter(RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isCounter());
+    return static_cast<RenderCounter*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderCounter(const RenderCounter*);
+
+} // namespace WebCore
+
+#ifndef NDEBUG
+// Outside the WebCore namespace for ease of invocation from gdb.
+void showCounterRendererTree(const WebCore::RenderObject*, const char* counterName = 0);
+#endif
+
+#endif // RenderCounter_h
diff --git a/Source/core/rendering/RenderDeprecatedFlexibleBox.cpp b/Source/core/rendering/RenderDeprecatedFlexibleBox.cpp
new file mode 100644
index 0000000..248a192
--- /dev/null
+++ b/Source/core/rendering/RenderDeprecatedFlexibleBox.cpp
@@ -0,0 +1,1108 @@
+/*
+ * This file is part of the render object implementation for KHTML.
+ *
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * 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 "core/rendering/RenderDeprecatedFlexibleBox.h"
+
+#include "core/page/UseCounter.h"
+#include "core/platform/graphics/Font.h"
+#include "core/rendering/LayoutRepainter.h"
+#include "core/rendering/RenderLayer.h"
+#include "core/rendering/RenderView.h"
+#include <wtf/StdLibExtras.h>
+#include <wtf/unicode/CharacterNames.h>
+
+using namespace std;
+
+namespace WebCore {
+
+class FlexBoxIterator {
+public:
+    FlexBoxIterator(RenderDeprecatedFlexibleBox* parent)
+        : m_box(parent)
+        , m_largestOrdinal(1)
+    {
+        if (m_box->style()->boxOrient() == HORIZONTAL && !m_box->style()->isLeftToRightDirection())
+            m_forward = m_box->style()->boxDirection() != BNORMAL;
+        else
+            m_forward = m_box->style()->boxDirection() == BNORMAL;
+        if (!m_forward) {
+            // No choice, since we're going backwards, we have to find out the highest ordinal up front.
+            RenderBox* child = m_box->firstChildBox();
+            while (child) {
+                if (child->style()->boxOrdinalGroup() > m_largestOrdinal)
+                    m_largestOrdinal = child->style()->boxOrdinalGroup();
+                child = child->nextSiblingBox();
+            }
+        }
+
+        reset();
+    }
+
+    void reset()
+    {
+        m_currentChild = 0;
+        m_ordinalIteration = -1;
+    }
+
+    RenderBox* first()
+    {
+        reset();
+        return next();
+    }
+
+    RenderBox* next()
+    {
+        do {
+            if (!m_currentChild) {
+                ++m_ordinalIteration;
+
+                if (!m_ordinalIteration)
+                    m_currentOrdinal = m_forward ? 1 : m_largestOrdinal;
+                else {
+                    if (m_ordinalIteration >= m_ordinalValues.size() + 1)
+                        return 0;
+
+                    // Only copy+sort the values once per layout even if the iterator is reset.
+                    if (static_cast<size_t>(m_ordinalValues.size()) != m_sortedOrdinalValues.size()) {
+                        copyToVector(m_ordinalValues, m_sortedOrdinalValues);
+                        sort(m_sortedOrdinalValues.begin(), m_sortedOrdinalValues.end());
+                    }
+                    m_currentOrdinal = m_forward ? m_sortedOrdinalValues[m_ordinalIteration - 1] : m_sortedOrdinalValues[m_sortedOrdinalValues.size() - m_ordinalIteration];
+                }
+
+                m_currentChild = m_forward ? m_box->firstChildBox() : m_box->lastChildBox();
+            } else
+                m_currentChild = m_forward ? m_currentChild->nextSiblingBox() : m_currentChild->previousSiblingBox();
+
+            if (m_currentChild && notFirstOrdinalValue())
+                m_ordinalValues.add(m_currentChild->style()->boxOrdinalGroup());
+        } while (!m_currentChild || (!m_currentChild->isAnonymous()
+                 && m_currentChild->style()->boxOrdinalGroup() != m_currentOrdinal));
+        return m_currentChild;
+    }
+
+private:
+    bool notFirstOrdinalValue()
+    {
+        unsigned int firstOrdinalValue = m_forward ? 1 : m_largestOrdinal;
+        return m_currentOrdinal == firstOrdinalValue && m_currentChild->style()->boxOrdinalGroup() != firstOrdinalValue;
+    }
+
+    RenderDeprecatedFlexibleBox* m_box;
+    RenderBox* m_currentChild;
+    bool m_forward;
+    unsigned int m_currentOrdinal;
+    unsigned int m_largestOrdinal;
+    HashSet<unsigned int> m_ordinalValues;
+    Vector<unsigned int> m_sortedOrdinalValues;
+    int m_ordinalIteration;
+};
+
+RenderDeprecatedFlexibleBox::RenderDeprecatedFlexibleBox(Element* element)
+    : RenderBlock(element)
+{
+    setChildrenInline(false); // All of our children must be block-level
+    m_stretchingChildren = false;
+    if (!isAnonymous()) {
+        const KURL& url = document()->url();
+        if (url.protocolIs("chrome"))
+            UseCounter::count(document(), UseCounter::DeprecatedFlexboxChrome);
+        else if (url.protocolIs("chrome-extension"))
+            UseCounter::count(document(), UseCounter::DeprecatedFlexboxChromeExtension);
+        else
+            UseCounter::count(document(), UseCounter::DeprecatedFlexboxWebContent);
+    }
+}
+
+RenderDeprecatedFlexibleBox::~RenderDeprecatedFlexibleBox()
+{
+}
+
+RenderDeprecatedFlexibleBox* RenderDeprecatedFlexibleBox::createAnonymous(Document* document)
+{
+    RenderDeprecatedFlexibleBox* renderer = new (document->renderArena()) RenderDeprecatedFlexibleBox(0);
+    renderer->setDocumentForAnonymous(document);
+    return renderer;
+}
+
+static LayoutUnit marginWidthForChild(RenderBox* child)
+{
+    // 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 marginLeft = child->style()->marginLeft();
+    Length marginRight = child->style()->marginRight();
+    LayoutUnit margin = 0;
+    if (marginLeft.isFixed())
+        margin += marginLeft.value();
+    if (marginRight.isFixed())
+        margin += marginRight.value();
+    return margin;
+}
+
+static bool childDoesNotAffectWidthOrFlexing(RenderObject* child)
+{
+    // Positioned children and collapsed children don't affect the min/max width.
+    return child->isOutOfFlowPositioned() || child->style()->visibility() == COLLAPSE;
+}
+
+static LayoutUnit contentWidthForChild(RenderBox* child)
+{
+    if (child->hasOverrideWidth())
+        return child->overrideLogicalContentWidth();
+    return child->logicalWidth() - child->borderAndPaddingLogicalWidth();
+}
+
+static LayoutUnit contentHeightForChild(RenderBox* child)
+{
+    if (child->hasOverrideHeight())
+        return child->overrideLogicalContentHeight();
+    return child->logicalHeight() - child->borderAndPaddingLogicalHeight();
+}
+
+void RenderDeprecatedFlexibleBox::styleWillChange(StyleDifference diff, const RenderStyle* newStyle)
+{
+    RenderStyle* oldStyle = style();
+    if (oldStyle && !oldStyle->lineClamp().isNone() && newStyle->lineClamp().isNone())
+        clearLineClamp();
+
+    RenderBlock::styleWillChange(diff, newStyle);
+}
+
+void RenderDeprecatedFlexibleBox::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const
+{
+    if (hasMultipleLines() || isVertical()) {
+        for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
+            if (childDoesNotAffectWidthOrFlexing(child))
+                continue;
+
+            LayoutUnit margin = marginWidthForChild(child);
+            LayoutUnit width = child->minPreferredLogicalWidth() + margin;
+            minLogicalWidth = max(width, minLogicalWidth);
+
+            width = child->maxPreferredLogicalWidth() + margin;
+            maxLogicalWidth = max(width, maxLogicalWidth);
+        }
+    } else {
+        for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
+            if (childDoesNotAffectWidthOrFlexing(child))
+                continue;
+
+            LayoutUnit margin = marginWidthForChild(child);
+            minLogicalWidth += child->minPreferredLogicalWidth() + margin;
+            maxLogicalWidth += child->maxPreferredLogicalWidth() + margin;
+        }
+    }
+
+    maxLogicalWidth = max(minLogicalWidth, maxLogicalWidth);
+
+    LayoutUnit scrollbarWidth = instrinsicScrollbarLogicalWidth();
+    maxLogicalWidth += scrollbarWidth;
+    minLogicalWidth += scrollbarWidth;
+}
+
+void RenderDeprecatedFlexibleBox::computePreferredLogicalWidths()
+{
+    ASSERT(preferredLogicalWidthsDirty());
+
+    m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = 0;
+    if (style()->width().isFixed() && style()->width().value() > 0)
+        m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = adjustContentBoxLogicalWidthForBoxSizing(style()->width().value());
+    else
+        computeIntrinsicLogicalWidths(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);
+
+    if (style()->minWidth().isFixed() && style()->minWidth().value() > 0) {
+        m_maxPreferredLogicalWidth = max(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->minWidth().value()));
+        m_minPreferredLogicalWidth = max(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->minWidth().value()));
+    }
+
+    if (style()->maxWidth().isFixed()) {
+        m_maxPreferredLogicalWidth = min(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->maxWidth().value()));
+        m_minPreferredLogicalWidth = min(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->maxWidth().value()));
+    }
+
+    LayoutUnit borderAndPadding = borderAndPaddingLogicalWidth();
+    m_minPreferredLogicalWidth += borderAndPadding;
+    m_maxPreferredLogicalWidth += borderAndPadding;
+
+    setPreferredLogicalWidthsDirty(false);
+}
+
+void RenderDeprecatedFlexibleBox::layoutBlock(bool relayoutChildren, LayoutUnit)
+{
+    ASSERT(needsLayout());
+
+    if (!relayoutChildren && simplifiedLayout())
+        return;
+
+    LayoutRepainter repainter(*this, checkForRepaintDuringLayout());
+    LayoutStateMaintainer statePusher(view(), this, locationOffset(), hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode());
+
+    // Regions changing widths can force us to relayout our children.
+    RenderFlowThread* flowThread = flowThreadContainingBlock();
+    if (logicalWidthChangedInRegions(flowThread))
+        relayoutChildren = true;
+    if (updateRegionsAndExclusionsLogicalSize(flowThread))
+        relayoutChildren = true;
+
+    LayoutSize previousSize = size();
+
+    updateLogicalWidth();
+    updateLogicalHeight();
+
+    if (previousSize != size()
+        || (parent()->isDeprecatedFlexibleBox() && parent()->style()->boxOrient() == HORIZONTAL
+        && parent()->style()->boxAlign() == BSTRETCH))
+        relayoutChildren = true;
+
+    setHeight(0);
+
+    m_stretchingChildren = false;
+
+    initMaxMarginValues();
+
+    if (isHorizontal())
+        layoutHorizontalBox(relayoutChildren);
+    else
+        layoutVerticalBox(relayoutChildren);
+
+    LayoutUnit oldClientAfterEdge = clientLogicalBottom();
+    updateLogicalHeight();
+
+    if (previousSize.height() != height())
+        relayoutChildren = true;
+
+    layoutPositionedObjects(relayoutChildren || isRoot());
+
+    computeRegionRangeForBlock(flowThread);
+
+    if (!isFloatingOrOutOfFlowPositioned() && 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.
+        LayoutUnit pos = maxPositiveMarginBefore();
+        LayoutUnit neg = maxNegativeMarginBefore();
+        if (maxPositiveMarginAfter() > pos)
+            pos = maxPositiveMarginAfter();
+        if (maxNegativeMarginAfter() > neg)
+            neg = maxNegativeMarginAfter();
+        setMaxMarginBeforeValues(pos, neg);
+        setMaxMarginAfterValues(0, 0);
+    }
+
+    computeOverflow(oldClientAfterEdge);
+
+    statePusher.pop();
+
+    updateLayerTransform();
+
+    if (view()->layoutState()->pageLogicalHeight())
+        setPageLogicalOffset(view()->layoutState()->pageLogicalOffset(this, logicalTop()));
+
+    // Update our scrollbars if we're overflow:auto/scroll/hidden now that we know if
+    // we overflow or not.
+    if (hasOverflowClip())
+        layer()->updateScrollInfoAfterLayout();
+
+    // Repaint with our new bounds if they are different from our old bounds.
+    repainter.repaintAfterLayout();
+
+    setNeedsLayout(false);
+}
+
+// The first walk over our kids is to find out if we have any flexible children.
+static void gatherFlexChildrenInfo(FlexBoxIterator& iterator, bool relayoutChildren, unsigned int& highestFlexGroup, unsigned int& lowestFlexGroup, bool& haveFlex)
+{
+    for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
+        // Check to see if this child flexes.
+        if (!childDoesNotAffectWidthOrFlexing(child) && 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->clearOverrideSize();
+            if (!relayoutChildren)
+                child->setChildNeedsLayout(true, MarkOnlyThis);
+            haveFlex = true;
+            unsigned int flexGroup = child->style()->boxFlexGroup();
+            if (lowestFlexGroup == 0)
+                lowestFlexGroup = flexGroup;
+            if (flexGroup < lowestFlexGroup)
+                lowestFlexGroup = flexGroup;
+            if (flexGroup > highestFlexGroup)
+                highestFlexGroup = flexGroup;
+        }
+    }
+}
+
+void RenderDeprecatedFlexibleBox::layoutHorizontalBox(bool relayoutChildren)
+{
+    LayoutUnit toAdd = borderBottom() + paddingBottom() + horizontalScrollbarHeight();
+    LayoutUnit yPos = borderTop() + paddingTop();
+    LayoutUnit xPos = borderLeft() + paddingLeft();
+    bool heightSpecified = false;
+    LayoutUnit oldHeight = 0;
+
+    LayoutUnit remainingSpace = 0;
+
+
+    FlexBoxIterator iterator(this);
+    unsigned int highestFlexGroup = 0;
+    unsigned int lowestFlexGroup = 0;
+    bool haveFlex = false, flexingChildren = false;
+    gatherFlexChildrenInfo(iterator, relayoutChildren, highestFlexGroup, lowestFlexGroup, haveFlex);
+
+    RenderBlock::startDelayUpdateScrollInfo();
+
+    // 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.
+        setHeight(yPos);
+
+        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.
+        LayoutUnit maxAscent = 0, maxDescent = 0;
+        for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
+            // make sure we relayout children if we need it.
+            if (relayoutChildren || (child->isReplaced() && (child->style()->width().isPercent() || child->style()->height().isPercent())))
+                child->setChildNeedsLayout(true, MarkOnlyThis);
+
+            if (child->isOutOfFlowPositioned())
+                continue;
+
+            // Compute the child's vertical margins.
+            child->computeAndSetBlockDirectionMargins(this);
+
+            if (!child->needsLayout())
+                child->markForPaginationRelayoutIfNeeded();
+
+            // Now do the layout.
+            child->layoutIfNeeded();
+
+            // Update our height and overflow height.
+            if (style()->boxAlign() == BBASELINE) {
+                LayoutUnit ascent = child->firstLineBoxBaseline();
+                if (ascent == -1)
+                    ascent = child->height() + child->marginBottom();
+                ascent += child->marginTop();
+                LayoutUnit descent = (child->height() + child->marginHeight()) - ascent;
+
+                // Update our maximum ascent.
+                maxAscent = max(maxAscent, ascent);
+
+                // Update our maximum descent.
+                maxDescent = max(maxDescent, descent);
+
+                // Now update our height.
+                setHeight(max(yPos + maxAscent + maxDescent, height()));
+            }
+            else
+                setHeight(max(height(), yPos + child->height() + child->marginHeight()));
+        }
+
+        if (!iterator.first() && hasLineIfEmpty())
+            setHeight(height() + lineHeight(true, style()->isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes));
+
+        setHeight(height() + toAdd);
+
+        oldHeight = height();
+        updateLogicalHeight();
+
+        relayoutChildren = false;
+        if (oldHeight != height())
+            heightSpecified = true;
+
+        // Now that our height is actually known, we can place our boxes.
+        m_stretchingChildren = (style()->boxAlign() == BSTRETCH);
+        for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
+            if (child->isOutOfFlowPositioned()) {
+                child->containingBlock()->insertPositionedObject(child);
+                RenderLayer* childLayer = child->layer();
+                childLayer->setStaticInlinePosition(xPos); // FIXME: Not right for regions.
+                if (childLayer->staticBlockPosition() != yPos) {
+                    childLayer->setStaticBlockPosition(yPos);
+                    if (child->style()->hasStaticBlockPosition(style()->isHorizontalWritingMode()))
+                        child->setChildNeedsLayout(true, MarkOnlyThis);
+                }
+                continue;
+            }
+            
+            if (child->style()->visibility() == COLLAPSE) {
+                // visibility: collapsed children do not participate in our positioning.
+                // But we need to lay them down.
+                child->layoutIfNeeded();
+                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.
+            LayoutUnit oldChildHeight = child->height();
+            child->updateLogicalHeight();
+            if (oldChildHeight != child->height())
+                child->setChildNeedsLayout(true, MarkOnlyThis);
+
+            if (!child->needsLayout())
+                child->markForPaginationRelayoutIfNeeded();
+
+            child->layoutIfNeeded();
+
+            // We can place the child now, using our value of box-align.
+            xPos += child->marginLeft();
+            LayoutUnit childY = yPos;
+            switch (style()->boxAlign()) {
+                case BCENTER:
+                    childY += child->marginTop() + max<LayoutUnit>(0, (contentHeight() - (child->height() + child->marginHeight())) / 2);
+                    break;
+                case BBASELINE: {
+                    LayoutUnit ascent = child->firstLineBoxBaseline();
+                    if (ascent == -1)
+                        ascent = child->height() + child->marginBottom();
+                    ascent += child->marginTop();
+                    childY += child->marginTop() + (maxAscent - ascent);
+                    break;
+                }
+                case BEND:
+                    childY += contentHeight() - child->marginBottom() - child->height();
+                    break;
+                default: // BSTART
+                    childY += child->marginTop();
+                    break;
+            }
+
+            placeChild(child, LayoutPoint(xPos, childY));
+
+            xPos += child->width() + child->marginRight();
+        }
+
+        remainingSpace = borderLeft() + paddingLeft() + contentWidth() - xPos;
+
+        m_stretchingChildren = false;
+        if (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.
+                LayoutUnit 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).
+                    LayoutUnit groupRemainingSpaceAtBeginning = groupRemainingSpace;
+                    float totalFlex = 0.0f;
+                    for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
+                        if (allowedChildFlex(child, expanding, i))
+                            totalFlex += child->style()->boxFlex();
+                    }
+                    LayoutUnit spaceAvailableThisPass = groupRemainingSpace;
+                    for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
+                        LayoutUnit allowedFlex = allowedChildFlex(child, expanding, i);
+                        if (allowedFlex) {
+                            LayoutUnit projectedFlex = (allowedFlex == LayoutUnit::max()) ? allowedFlex : LayoutUnit(allowedFlex * (totalFlex / child->style()->boxFlex()));
+                            spaceAvailableThisPass = expanding ? min(spaceAvailableThisPass, projectedFlex) : max(spaceAvailableThisPass, projectedFlex);
+                        }
+                    }
+
+                    // 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.
+                    for (RenderBox* child = iterator.first(); child && spaceAvailableThisPass && totalFlex; child = iterator.next()) {
+                        if (child->style()->visibility() == COLLAPSE)
+                            continue;
+
+                        if (allowedChildFlex(child, expanding, i)) {
+                            LayoutUnit spaceAdd = LayoutUnit(spaceAvailableThisPass * (child->style()->boxFlex() / totalFlex));
+                            if (spaceAdd) {
+                                child->setOverrideLogicalContentWidth(contentWidthForChild(child) + spaceAdd);
+                                flexingChildren = true;
+                                relayoutChildren = true;
+                            }
+
+                            spaceAvailableThisPass -= spaceAdd;
+                            remainingSpace -= spaceAdd;
+                            groupRemainingSpace -= spaceAdd;
+
+                            totalFlex -= child->style()->boxFlex();
+                        }
+                    }
+                    if (groupRemainingSpace == groupRemainingSpaceAtBeginning) {
+                        // This is not advancing, avoid getting stuck by distributing the remaining pixels.
+                        LayoutUnit spaceAdd = groupRemainingSpace > 0 ? 1 : -1;
+                        for (RenderBox* child = iterator.first(); child && groupRemainingSpace; child = iterator.next()) {
+                            if (allowedChildFlex(child, expanding, i)) {
+                                child->setOverrideLogicalContentWidth(contentWidthForChild(child) + spaceAdd);
+                                flexingChildren = true;
+                                relayoutChildren = true;
+                                remainingSpace -= spaceAdd;
+                                groupRemainingSpace -= spaceAdd;
+                            }
+                        }
+                    }
+                } while (absoluteValue(groupRemainingSpace) >= 1);
+            }
+
+            // We didn't find any children that could grow.
+            if (haveFlex && !flexingChildren)
+                haveFlex = false;
+        }
+    } while (haveFlex);
+
+    RenderBlock::finishDelayUpdateScrollInfo();
+
+    if (remainingSpace > 0 && ((style()->isLeftToRightDirection() && style()->boxPack() != Start)
+        || (!style()->isLeftToRightDirection() && style()->boxPack() != End))) {
+        // Children must be repositioned.
+        LayoutUnit offset = 0;
+        if (style()->boxPack() == Justify) {
+            // Determine the total number of children.
+            int totalChildren = 0;
+            for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
+                if (childDoesNotAffectWidthOrFlexing(child))
+                    continue;
+                ++totalChildren;
+            }
+
+            // Iterate over the children and space them out according to the
+            // justification level.
+            if (totalChildren > 1) {
+                --totalChildren;
+                bool firstChild = true;
+                for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
+                    if (childDoesNotAffectWidthOrFlexing(child))
+                        continue;
+
+                    if (firstChild) {
+                        firstChild = false;
+                        continue;
+                    }
+
+                    offset += remainingSpace/totalChildren;
+                    remainingSpace -= (remainingSpace/totalChildren);
+                    --totalChildren;
+
+                    placeChild(child, child->location() + LayoutSize(offset, 0));
+                }
+            }
+        } else {
+            if (style()->boxPack() == Center)
+                offset += remainingSpace / 2;
+            else // END for LTR, START for RTL
+                offset += remainingSpace;
+            for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
+                if (childDoesNotAffectWidthOrFlexing(child))
+                    continue;
+
+                placeChild(child, child->location() + LayoutSize(offset, 0));
+            }
+        }
+    }
+
+    // So that the computeLogicalHeight 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)
+        setHeight(oldHeight);
+}
+
+void RenderDeprecatedFlexibleBox::layoutVerticalBox(bool relayoutChildren)
+{
+    LayoutUnit yPos = borderTop() + paddingTop();
+    LayoutUnit toAdd = borderBottom() + paddingBottom() + horizontalScrollbarHeight();
+    bool heightSpecified = false;
+    LayoutUnit oldHeight = 0;
+
+    LayoutUnit remainingSpace = 0;
+
+    FlexBoxIterator iterator(this);
+    unsigned int highestFlexGroup = 0;
+    unsigned int lowestFlexGroup = 0;
+    bool haveFlex = false, flexingChildren = false;
+    gatherFlexChildrenInfo(iterator, relayoutChildren, highestFlexGroup, lowestFlexGroup, haveFlex);
+
+    // 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().isNone();
+    if (haveLineClamp)
+        applyLineClamp(iterator, relayoutChildren);
+
+    RenderBlock::startDelayUpdateScrollInfo();
+
+    // 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 {
+        setHeight(borderTop() + paddingTop());
+        LayoutUnit minHeight = height() + toAdd;
+
+        for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
+            // 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, MarkOnlyThis);
+
+            if (child->isOutOfFlowPositioned()) {
+                child->containingBlock()->insertPositionedObject(child);
+                RenderLayer* childLayer = child->layer();
+                childLayer->setStaticInlinePosition(borderStart() + paddingStart()); // FIXME: Not right for regions.
+                if (childLayer->staticBlockPosition() != height()) {
+                    childLayer->setStaticBlockPosition(height());
+                    if (child->style()->hasStaticBlockPosition(style()->isHorizontalWritingMode()))
+                        child->setChildNeedsLayout(true, MarkOnlyThis);
+                }
+                continue;
+            }
+            
+            if (child->style()->visibility() == COLLAPSE) {
+                // visibility: collapsed children do not participate in our positioning.
+                // But we need to lay them down.
+                child->layoutIfNeeded();
+                continue;
+            }
+
+            // Compute the child's vertical margins.
+            child->computeAndSetBlockDirectionMargins(this);
+
+            // Add in the child's marginTop to our height.
+            setHeight(height() + child->marginTop());
+
+            if (!child->needsLayout())
+                child->markForPaginationRelayoutIfNeeded();
+
+            // Now do a layout.
+            child->layoutIfNeeded();
+
+            // We can place the child now, using our value of box-align.
+            LayoutUnit childX = borderLeft() + paddingLeft();
+            switch (style()->boxAlign()) {
+                case BCENTER:
+                case BBASELINE: // Baseline just maps to center for vertical boxes
+                    childX += child->marginLeft() + max<LayoutUnit>(0, (contentWidth() - (child->width() + child->marginWidth())) / 2);
+                    break;
+                case BEND:
+                    if (!style()->isLeftToRightDirection())
+                        childX += child->marginLeft();
+                    else
+                        childX += contentWidth() - child->marginRight() - child->width();
+                    break;
+                default: // BSTART/BSTRETCH
+                    if (style()->isLeftToRightDirection())
+                        childX += child->marginLeft();
+                    else
+                        childX += contentWidth() - child->marginRight() - child->width();
+                    break;
+            }
+
+            // Place the child.
+            placeChild(child, LayoutPoint(childX, height()));
+            setHeight(height() + child->height() + child->marginBottom());
+        }
+
+        yPos = height();
+
+        if (!iterator.first() && hasLineIfEmpty())
+            setHeight(height() + lineHeight(true, style()->isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes));
+
+        setHeight(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 (height() < minHeight)
+            setHeight(minHeight);
+
+        // Now we have to calc our height, so we know how much space we have remaining.
+        oldHeight = height();
+        updateLogicalHeight();
+        if (oldHeight != height())
+            heightSpecified = true;
+
+        remainingSpace = borderTop() + paddingTop() + contentHeight() - yPos;
+
+        if (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.
+                LayoutUnit 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).
+                    LayoutUnit groupRemainingSpaceAtBeginning = groupRemainingSpace;
+                    float totalFlex = 0.0f;
+                    for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
+                        if (allowedChildFlex(child, expanding, i))
+                            totalFlex += child->style()->boxFlex();
+                    }
+                    LayoutUnit spaceAvailableThisPass = groupRemainingSpace;
+                    for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
+                        LayoutUnit allowedFlex = allowedChildFlex(child, expanding, i);
+                        if (allowedFlex) {
+                            LayoutUnit projectedFlex = (allowedFlex == LayoutUnit::max()) ? allowedFlex : static_cast<LayoutUnit>(allowedFlex * (totalFlex / child->style()->boxFlex()));
+                            spaceAvailableThisPass = expanding ? min(spaceAvailableThisPass, projectedFlex) : max(spaceAvailableThisPass, projectedFlex);
+                        }
+                    }
+
+                    // 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.
+                    for (RenderBox* child = iterator.first(); child && spaceAvailableThisPass && totalFlex; child = iterator.next()) {
+                        if (allowedChildFlex(child, expanding, i)) {
+                            LayoutUnit spaceAdd = static_cast<LayoutUnit>(spaceAvailableThisPass * (child->style()->boxFlex() / totalFlex));
+                            if (spaceAdd) {
+                                child->setOverrideLogicalContentHeight(contentHeightForChild(child) + spaceAdd);
+                                flexingChildren = true;
+                                relayoutChildren = true;
+                            }
+
+                            spaceAvailableThisPass -= spaceAdd;
+                            remainingSpace -= spaceAdd;
+                            groupRemainingSpace -= spaceAdd;
+
+                            totalFlex -= child->style()->boxFlex();
+                        }
+                    }
+                    if (groupRemainingSpace == groupRemainingSpaceAtBeginning) {
+                        // This is not advancing, avoid getting stuck by distributing the remaining pixels.
+                        LayoutUnit spaceAdd = groupRemainingSpace > 0 ? 1 : -1;
+                        for (RenderBox* child = iterator.first(); child && groupRemainingSpace; child = iterator.next()) {
+                            if (allowedChildFlex(child, expanding, i)) {
+                                child->setOverrideLogicalContentHeight(contentHeightForChild(child) + spaceAdd);
+                                flexingChildren = true;
+                                relayoutChildren = true;
+                                remainingSpace -= spaceAdd;
+                                groupRemainingSpace -= spaceAdd;
+                            }
+                        }
+                    }
+                } while (absoluteValue(groupRemainingSpace) >= 1);
+            }
+
+            // We didn't find any children that could grow.
+            if (haveFlex && !flexingChildren)
+                haveFlex = false;
+        }
+    } while (haveFlex);
+
+    RenderBlock::finishDelayUpdateScrollInfo();
+
+    if (style()->boxPack() != Start && remainingSpace > 0) {
+        // Children must be repositioned.
+        LayoutUnit offset = 0;
+        if (style()->boxPack() == Justify) {
+            // Determine the total number of children.
+            int totalChildren = 0;
+            for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
+                if (childDoesNotAffectWidthOrFlexing(child))
+                    continue;
+
+                ++totalChildren;
+            }
+
+            // Iterate over the children and space them out according to the
+            // justification level.
+            if (totalChildren > 1) {
+                --totalChildren;
+                bool firstChild = true;
+                for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
+                    if (childDoesNotAffectWidthOrFlexing(child))
+                        continue;
+
+                    if (firstChild) {
+                        firstChild = false;
+                        continue;
+                    }
+
+                    offset += remainingSpace/totalChildren;
+                    remainingSpace -= (remainingSpace/totalChildren);
+                    --totalChildren;
+                    placeChild(child, child->location() + LayoutSize(0, offset));
+                }
+            }
+        } else {
+            if (style()->boxPack() == Center)
+                offset += remainingSpace / 2;
+            else // END
+                offset += remainingSpace;
+            for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
+                if (childDoesNotAffectWidthOrFlexing(child))
+                    continue;
+                placeChild(child, child->location() + LayoutSize(0, offset));
+            }
+        }
+    }
+
+    // So that the computeLogicalHeight 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)
+        setHeight(oldHeight);
+}
+
+void RenderDeprecatedFlexibleBox::applyLineClamp(FlexBoxIterator& iterator, bool relayoutChildren)
+{
+    int maxLineCount = 0;
+    for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
+        if (childDoesNotAffectWidthOrFlexing(child))
+            continue;
+
+        child->clearOverrideSize();
+        if (relayoutChildren || (child->isReplaced() && (child->style()->width().isPercent() || child->style()->height().isPercent()))
+            || (child->style()->height().isAuto() && child->isBlockFlow())) {
+            child->setChildNeedsLayout(true, MarkOnlyThis);
+
+            // Dirty all the positioned objects.
+            if (child->isRenderBlock()) {
+                toRenderBlock(child)->markPositionedObjectsForLayout();
+                toRenderBlock(child)->clearTruncation();
+            }
+        }
+        child->layoutIfNeeded();
+        if (child->style()->height().isAuto() && child->isBlockFlow())
+            maxLineCount = max(maxLineCount, toRenderBlock(child)->lineCount());
+    }
+
+    // Get the number 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.
+    LineClampValue lineClamp = style()->lineClamp();
+    int numVisibleLines = lineClamp.isPercentage() ? max(1, (maxLineCount + 1) * lineClamp.value() / 100) : lineClamp.value();
+    if (numVisibleLines >= maxLineCount)
+        return;
+
+    for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
+        if (childDoesNotAffectWidthOrFlexing(child) || !child->style()->height().isAuto() || !child->isBlockFlow())
+            continue;
+
+        RenderBlock* blockChild = toRenderBlock(child);
+        int lineCount = blockChild->lineCount();
+        if (lineCount <= numVisibleLines)
+            continue;
+
+        LayoutUnit newHeight = blockChild->heightForLineCount(numVisibleLines);
+        if (newHeight == child->height())
+            continue;
+
+        child->setChildNeedsLayout(true, MarkOnlyThis);
+        child->setOverrideLogicalContentHeight(newHeight - child->borderAndPaddingHeight());
+        child->layoutIfNeeded();
+
+        // 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;
+
+        RootInlineBox* lastVisibleLine = blockChild->lineAtIndex(numVisibleLines - 1);
+        if (!lastVisibleLine)
+            continue;
+
+        const UChar ellipsisAndSpace[2] = { horizontalEllipsis, ' ' };
+        DEFINE_STATIC_LOCAL(AtomicString, ellipsisAndSpaceStr, (ellipsisAndSpace, 2));
+        DEFINE_STATIC_LOCAL(AtomicString, ellipsisStr, (&horizontalEllipsis, 1));
+        const Font& font = style(numVisibleLines == 1)->font();
+
+        // Get ellipsis width, and if the last child is an anchor, it will go after the ellipsis, so add in a space and the anchor width too
+        LayoutUnit totalWidth;
+        InlineBox* anchorBox = lastLine->lastChild();
+        if (anchorBox && anchorBox->renderer()->style()->isLink())
+            totalWidth = anchorBox->logicalWidth() + font.width(constructTextRun(this, font, ellipsisAndSpace, 2, style()));
+        else {
+            anchorBox = 0;
+            totalWidth = font.width(constructTextRun(this, font, &horizontalEllipsis, 1, style()));
+        }
+
+        // See if this width can be accommodated on the last visible line
+        RenderBlock* destBlock = toRenderBlock(lastVisibleLine->renderer());
+        RenderBlock* srcBlock = toRenderBlock(lastLine->renderer());
+
+        // FIXME: Directions of src/destBlock could be different from our direction and from one another.
+        if (!srcBlock->style()->isLeftToRightDirection())
+            continue;
+
+        bool leftToRight = destBlock->style()->isLeftToRightDirection();
+        if (!leftToRight)
+            continue;
+
+        LayoutUnit blockRightEdge = destBlock->logicalRightOffsetForLine(lastVisibleLine->y(), false);
+        if (!lastVisibleLine->lineCanAccommodateEllipsis(leftToRight, blockRightEdge, lastVisibleLine->x() + lastVisibleLine->logicalWidth(), totalWidth))
+            continue;
+
+        // Let the truncation code kick in.
+        // FIXME: the text alignment should be recomputed after the width changes due to truncation.
+        LayoutUnit blockLeftEdge = destBlock->logicalLeftOffsetForLine(lastVisibleLine->y(), false);
+        lastVisibleLine->placeEllipsis(anchorBox ? ellipsisAndSpaceStr : ellipsisStr, leftToRight, blockLeftEdge, blockRightEdge, totalWidth, anchorBox);
+        destBlock->setHasMarkupTruncation(true);
+    }
+}
+
+void RenderDeprecatedFlexibleBox::clearLineClamp()
+{
+    FlexBoxIterator iterator(this);
+    for (RenderBox* child = iterator.first(); child; child = iterator.next()) {
+        if (childDoesNotAffectWidthOrFlexing(child))
+            continue;
+
+        child->clearOverrideSize();
+        if ((child->isReplaced() && (child->style()->width().isPercent() || child->style()->height().isPercent()))
+            || (child->style()->height().isAuto() && child->isBlockFlow())) {
+            child->setChildNeedsLayout(true);
+
+            if (child->isRenderBlock()) {
+                toRenderBlock(child)->markPositionedObjectsForLayout();
+                toRenderBlock(child)->clearTruncation();
+            }
+        }
+    }
+}
+
+void RenderDeprecatedFlexibleBox::placeChild(RenderBox* child, const LayoutPoint& location)
+{
+    LayoutRect oldRect = child->frameRect();
+
+    // Place the child.
+    child->setLocation(location);
+
+    // 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);
+}
+
+LayoutUnit RenderDeprecatedFlexibleBox::allowedChildFlex(RenderBox* child, bool expanding, unsigned int group)
+{
+    if (childDoesNotAffectWidthOrFlexing(child) || child->style()->boxFlex() == 0.0f || child->style()->boxFlexGroup() != group)
+        return 0;
+
+    if (expanding) {
+        if (isHorizontal()) {
+            // FIXME: For now just handle fixed values.
+            LayoutUnit maxWidth = LayoutUnit::max();
+            LayoutUnit width = contentWidthForChild(child);
+            if (!child->style()->maxWidth().isUndefined() && child->style()->maxWidth().isFixed())
+                maxWidth = child->style()->maxWidth().value();
+            else if (child->style()->maxWidth().type() == Intrinsic)
+                maxWidth = child->maxPreferredLogicalWidth();
+            else if (child->style()->maxWidth().type() == MinIntrinsic)
+                maxWidth = child->minPreferredLogicalWidth();
+            if (maxWidth == LayoutUnit::max())
+                return maxWidth;
+            return max<LayoutUnit>(0, maxWidth - width);
+        } else {
+            // FIXME: For now just handle fixed values.
+            LayoutUnit maxHeight = LayoutUnit::max();
+            LayoutUnit height = contentHeightForChild(child);
+            if (!child->style()->maxHeight().isUndefined() && child->style()->maxHeight().isFixed())
+                maxHeight = child->style()->maxHeight().value();
+            if (maxHeight == LayoutUnit::max())
+                return maxHeight;
+            return max<LayoutUnit>(0, maxHeight - height);
+        }
+    }
+
+    // FIXME: For now just handle fixed values.
+    if (isHorizontal()) {
+        LayoutUnit minWidth = child->minPreferredLogicalWidth();
+        LayoutUnit width = contentWidthForChild(child);
+        if (child->style()->minWidth().isFixed())
+            minWidth = child->style()->minWidth().value();
+        else if (child->style()->minWidth().type() == Intrinsic)
+            minWidth = child->maxPreferredLogicalWidth();
+        else if (child->style()->minWidth().type() == MinIntrinsic)
+            minWidth = child->minPreferredLogicalWidth();
+        else if (child->style()->minWidth().type() == Auto)
+            minWidth = 0;
+
+        LayoutUnit allowedShrinkage = min<LayoutUnit>(0, minWidth - width);
+        return allowedShrinkage;
+    } else {
+        Length minHeight = child->style()->minHeight();
+        if (minHeight.isFixed() || minHeight.isAuto()) {
+            LayoutUnit minHeight = child->style()->minHeight().value();
+            LayoutUnit height = contentHeightForChild(child);
+            LayoutUnit allowedShrinkage = min<LayoutUnit>(0, minHeight - height);
+            return allowedShrinkage;
+        }
+    }
+
+    return 0;
+}
+
+const char* RenderDeprecatedFlexibleBox::renderName() const
+{
+    if (isFloating())
+        return "RenderDeprecatedFlexibleBox (floating)";
+    if (isOutOfFlowPositioned())
+        return "RenderDeprecatedFlexibleBox (positioned)";
+    // FIXME: Temporary hack while the new generated content system is being implemented.
+    if (isPseudoElement())
+        return "RenderDeprecatedFlexibleBox (generated)";
+    if (isAnonymous())
+        return "RenderDeprecatedFlexibleBox (generated)";
+    if (isRelPositioned())
+        return "RenderDeprecatedFlexibleBox (relative positioned)";
+    return "RenderDeprecatedFlexibleBox";
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderDeprecatedFlexibleBox.h b/Source/core/rendering/RenderDeprecatedFlexibleBox.h
new file mode 100644
index 0000000..7d3df07
--- /dev/null
+++ b/Source/core/rendering/RenderDeprecatedFlexibleBox.h
@@ -0,0 +1,73 @@
+/*
+ * 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 RenderDeprecatedFlexibleBox_h
+#define RenderDeprecatedFlexibleBox_h
+
+#include "core/rendering/RenderBlock.h"
+
+namespace WebCore {
+
+class FlexBoxIterator;
+
+class RenderDeprecatedFlexibleBox FINAL : public RenderBlock {
+public:
+    RenderDeprecatedFlexibleBox(Element*);
+    virtual ~RenderDeprecatedFlexibleBox();
+
+    static RenderDeprecatedFlexibleBox* createAnonymous(Document*);
+
+    virtual const char* renderName() const;
+
+    virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle) OVERRIDE;
+
+    virtual void layoutBlock(bool relayoutChildren, LayoutUnit pageHeight = 0);
+    void layoutHorizontalBox(bool relayoutChildren);
+    void layoutVerticalBox(bool relayoutChildren);
+
+    virtual bool avoidsFloats() const { return true; }
+    virtual bool isDeprecatedFlexibleBox() const { return true; }
+    virtual bool isStretchingChildren() const { return m_stretchingChildren; }
+    virtual bool canCollapseAnonymousBlockChild() const OVERRIDE { return false; }
+
+    void placeChild(RenderBox* child, const LayoutPoint& location);
+
+protected:
+    virtual void computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const OVERRIDE;
+    virtual void computePreferredLogicalWidths() OVERRIDE;
+
+    LayoutUnit allowedChildFlex(RenderBox* 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_stretchingChildren;
+
+private:
+    void applyLineClamp(FlexBoxIterator&, bool relayoutChildren);
+    void clearLineClamp();
+};
+
+} // namespace WebCore
+
+#endif // RenderDeprecatedFlexibleBox_h
diff --git a/Source/core/rendering/RenderDetailsMarker.cpp b/Source/core/rendering/RenderDetailsMarker.cpp
new file mode 100644
index 0000000..0b8c299
--- /dev/null
+++ b/Source/core/rendering/RenderDetailsMarker.cpp
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 2010, 2011 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 "core/rendering/RenderDetailsMarker.h"
+
+#include "HTMLNames.h"
+#include "core/dom/Element.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/rendering/PaintInfo.h"
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+RenderDetailsMarker::RenderDetailsMarker(Element* element)
+    : RenderBlock(element)
+{
+}
+
+static Path createPath(const FloatPoint* path)
+{
+    Path result;
+    result.moveTo(FloatPoint(path[0].x(), path[0].y()));
+    for (int i = 1; i < 4; ++i)
+        result.addLineTo(FloatPoint(path[i].x(), path[i].y()));
+    return result;
+}
+
+static Path createDownArrowPath()
+{
+    FloatPoint points[4] = { FloatPoint(0.0f, 0.07f), FloatPoint(0.5f, 0.93f), FloatPoint(1.0f, 0.07f), FloatPoint(0.0f, 0.07f) };
+    return createPath(points);
+}
+
+static Path createUpArrowPath()
+{
+    FloatPoint points[4] = { FloatPoint(0.0f, 0.93f), FloatPoint(0.5f, 0.07f), FloatPoint(1.0f, 0.93f), FloatPoint(0.0f, 0.93f) };
+    return createPath(points);
+}
+
+static Path createLeftArrowPath()
+{
+    FloatPoint points[4] = { FloatPoint(1.0f, 0.0f), FloatPoint(0.14f, 0.5f), FloatPoint(1.0f, 1.0f), FloatPoint(1.0f, 0.0f) };
+    return createPath(points);
+}
+
+static Path createRightArrowPath()
+{
+    FloatPoint points[4] = { FloatPoint(0.0f, 0.0f), FloatPoint(0.86f, 0.5f), FloatPoint(0.0f, 1.0f), FloatPoint(0.0f, 0.0f) };
+    return createPath(points);
+}
+
+RenderDetailsMarker::Orientation RenderDetailsMarker::orientation() const
+{
+    switch (style()->writingMode()) {
+    case TopToBottomWritingMode:
+        if (style()->isLeftToRightDirection())
+            return isOpen() ? Down : Right;
+        return isOpen() ? Down : Left;
+    case RightToLeftWritingMode:
+        if (style()->isLeftToRightDirection())
+            return isOpen() ? Left : Down;
+        return isOpen() ? Left : Up;
+    case LeftToRightWritingMode:
+        if (style()->isLeftToRightDirection())
+            return isOpen() ? Right : Down;
+        return isOpen() ? Right : Up;
+    case BottomToTopWritingMode:
+        if (style()->isLeftToRightDirection())
+            return isOpen() ? Up : Right;
+        return isOpen() ? Up : Left;
+    }
+    return Right;
+}
+
+Path RenderDetailsMarker::getCanonicalPath() const
+{
+    switch (orientation()) {
+    case Left: return createLeftArrowPath();
+    case Right: return createRightArrowPath();
+    case Up: return createUpArrowPath();
+    case Down: return createDownArrowPath();
+    }
+
+    return Path();
+}
+
+Path RenderDetailsMarker::getPath(const LayoutPoint& origin) const
+{
+    Path result = getCanonicalPath();
+    result.transform(AffineTransform().scale(contentWidth(), contentHeight()));
+    result.translate(FloatSize(origin.x(), origin.y()));
+    return result;
+}
+
+void RenderDetailsMarker::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    if (paintInfo.phase != PaintPhaseForeground || style()->visibility() != VISIBLE) {
+        RenderBlock::paint(paintInfo, paintOffset);
+        return;
+    }
+
+    LayoutPoint boxOrigin(paintOffset + location());
+    LayoutRect overflowRect(visualOverflowRect());
+    overflowRect.moveBy(boxOrigin);
+    overflowRect.inflate(maximalOutlineSize(paintInfo.phase));
+
+    if (!paintInfo.rect.intersects(pixelSnappedIntRect(overflowRect)))
+        return;
+
+    const Color color(style()->visitedDependentColor(CSSPropertyColor));
+    paintInfo.context->setStrokeColor(color, style()->colorSpace());
+    paintInfo.context->setStrokeStyle(SolidStroke);
+    paintInfo.context->setStrokeThickness(1.0f);
+    paintInfo.context->setFillColor(color, style()->colorSpace());
+
+    boxOrigin.move(borderLeft() + paddingLeft(), borderTop() + paddingTop());
+    paintInfo.context->fillPath(getPath(boxOrigin));
+}
+
+bool RenderDetailsMarker::isOpen() const
+{
+    for (RenderObject* renderer = parent(); renderer; renderer = renderer->parent()) {
+        if (!renderer->node())
+            continue;
+        if (renderer->node()->hasTagName(detailsTag))
+            return !toElement(renderer->node())->getAttribute(openAttr).isNull();
+        if (renderer->node()->hasTagName(inputTag))
+            return true;
+    }
+
+    return false;
+}
+
+}
diff --git a/Source/core/rendering/RenderDetailsMarker.h b/Source/core/rendering/RenderDetailsMarker.h
new file mode 100644
index 0000000..d93a629
--- /dev/null
+++ b/Source/core/rendering/RenderDetailsMarker.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2010, 2011 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 RenderDetailsMarker_h
+#define RenderDetailsMarker_h
+
+#include "core/rendering/RenderBlock.h"
+
+namespace WebCore {
+
+class RenderDetailsMarker FINAL : public RenderBlock {
+public:
+    RenderDetailsMarker(Element*);
+
+    enum Orientation { Up, Down, Left, Right };
+
+    Orientation orientation() const;
+
+private:
+    virtual const char* renderName() const { return "RenderDetailsMarker"; }
+    virtual bool isDetailsMarker() const { return true; }
+    virtual void paint(PaintInfo&, const LayoutPoint&);
+
+    bool isOpen() const;
+    Path getCanonicalPath() const;
+    Path getPath(const LayoutPoint& origin) const;
+};
+
+inline RenderDetailsMarker* toRenderDetailsMarker(RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isDetailsMarker());
+    return static_cast<RenderDetailsMarker*>(object);
+}
+
+inline const RenderDetailsMarker* toRenderDetailsMarker(const RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isDetailsMarker());
+    return static_cast<const RenderDetailsMarker*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderDetailsMarker(const RenderDetailsMarker*);
+
+}
+
+#endif // RenderDetailsMarker_h
diff --git a/Source/core/rendering/RenderEmbeddedObject.cpp b/Source/core/rendering/RenderEmbeddedObject.cpp
new file mode 100644
index 0000000..9b9293d
--- /dev/null
+++ b/Source/core/rendering/RenderEmbeddedObject.cpp
@@ -0,0 +1,404 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 2000 Simon Hausmann <hausmann@kde.org>
+ *           (C) 2000 Stefan Schimanski (1Stein@gmx.de)
+ * Copyright (C) 2004, 2005, 2006, 2008, 2009, 2010 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 "core/rendering/RenderEmbeddedObject.h"
+
+#include "CSSValueKeywords.h"
+#include "HTMLNames.h"
+#include "core/dom/MouseEvent.h"
+#include "core/dom/Text.h"
+#include "core/html/HTMLEmbedElement.h"
+#include "core/html/HTMLIFrameElement.h"
+#include "core/html/HTMLObjectElement.h"
+#include "core/html/HTMLParamElement.h"
+#include "core/html/HTMLPlugInElement.h"
+#include "core/loader/FrameLoaderClient.h"
+#include "core/page/Chrome.h"
+#include "core/page/ChromeClient.h"
+#include "core/page/EventHandler.h"
+#include "core/page/Frame.h"
+#include "core/page/Page.h"
+#include "core/page/Settings.h"
+#include "core/platform/Cursor.h"
+#include "core/platform/LocalizedStrings.h"
+#include "core/platform/MIMETypeRegistry.h"
+#include "core/platform/PlatformMouseEvent.h"
+#include "core/platform/graphics/Font.h"
+#include "core/platform/graphics/FontSelector.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/platform/graphics/Path.h"
+#include "core/platform/graphics/TextRun.h"
+#include "core/plugins/PluginView.h"
+#include "core/rendering/HitTestResult.h"
+#include "core/rendering/PaintInfo.h"
+#include "core/rendering/RenderTheme.h"
+#include "core/rendering/RenderView.h"
+#include "core/rendering/RenderWidgetProtector.h"
+
+namespace WebCore {
+
+using namespace HTMLNames;
+    
+static const float replacementTextRoundedRectHeight = 18;
+static const float replacementTextRoundedRectLeftRightTextMargin = 6;
+static const float replacementTextRoundedRectOpacity = 0.20f;
+static const float replacementTextPressedRoundedRectOpacity = 0.65f;
+static const float replacementTextRoundedRectRadius = 5;
+static const float replacementTextTextOpacity = 0.55f;
+static const float replacementTextPressedTextOpacity = 0.65f;
+
+static const Color& replacementTextRoundedRectPressedColor()
+{
+    static const Color lightGray(205, 205, 205);
+    return lightGray;
+}
+    
+RenderEmbeddedObject::RenderEmbeddedObject(Element* element)
+    : RenderPart(element)
+    , m_hasFallbackContent(false)
+    , m_showsUnavailablePluginIndicator(false)
+    , m_unavailablePluginIndicatorIsPressed(false)
+    , m_mouseDownWasInUnavailablePluginIndicator(false)
+{
+    view()->frameView()->setIsVisuallyNonEmpty();
+}
+
+RenderEmbeddedObject::~RenderEmbeddedObject()
+{
+    if (frameView())
+        frameView()->removeWidgetToUpdate(this);
+}
+
+bool RenderEmbeddedObject::requiresLayer() const
+{
+    if (RenderPart::requiresLayer())
+        return true;
+    
+    return allowsAcceleratedCompositing();
+}
+
+bool RenderEmbeddedObject::allowsAcceleratedCompositing() const
+{
+    return widget() && widget()->isPluginView() && toPluginView(widget())->platformLayer();
+}
+
+static String unavailablePluginReplacementText(RenderEmbeddedObject::PluginUnavailabilityReason pluginUnavailabilityReason)
+{
+    switch (pluginUnavailabilityReason) {
+    case RenderEmbeddedObject::PluginMissing:
+        return missingPluginText();
+    case RenderEmbeddedObject::PluginCrashed:
+        return crashedPluginText();
+    case RenderEmbeddedObject::PluginBlockedByContentSecurityPolicy:
+        return blockedPluginByContentSecurityPolicyText();
+    case RenderEmbeddedObject::InsecurePluginVersion:
+        return insecurePluginVersionText();
+    case RenderEmbeddedObject::PluginInactive:
+        return inactivePluginText();
+    }
+
+    ASSERT_NOT_REACHED();
+    return String();
+}
+
+void RenderEmbeddedObject::setPluginUnavailabilityReason(PluginUnavailabilityReason pluginUnavailabilityReason)
+{
+    ASSERT(!m_showsUnavailablePluginIndicator);
+    m_showsUnavailablePluginIndicator = true;
+    m_pluginUnavailabilityReason = pluginUnavailabilityReason;
+
+    m_unavailablePluginReplacementText = unavailablePluginReplacementText(pluginUnavailabilityReason);
+}
+
+bool RenderEmbeddedObject::showsUnavailablePluginIndicator() const
+{
+    return m_showsUnavailablePluginIndicator;
+}
+
+void RenderEmbeddedObject::setUnavailablePluginIndicatorIsPressed(bool pressed)
+{
+    if (m_unavailablePluginIndicatorIsPressed == pressed)
+        return;
+    
+    m_unavailablePluginIndicatorIsPressed = pressed;
+    repaint();
+}
+
+void RenderEmbeddedObject::paintContents(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    Element* element = toElement(node());
+    if (!element || !element->isPluginElement())
+        return;
+
+    RenderPart::paintContents(paintInfo, paintOffset);
+}
+
+void RenderEmbeddedObject::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    Page* page = 0;
+    if (Frame* frame = this->frame())
+        page = frame->page();
+
+    if (showsUnavailablePluginIndicator()) {
+        if (page && paintInfo.phase == PaintPhaseForeground)
+            page->addRelevantUnpaintedObject(this, visualOverflowRect());
+        RenderReplaced::paint(paintInfo, paintOffset);
+        return;
+    }
+
+    if (page && paintInfo.phase == PaintPhaseForeground)
+        page->addRelevantRepaintedObject(this, visualOverflowRect());
+
+    RenderPart::paint(paintInfo, paintOffset);
+}
+
+void RenderEmbeddedObject::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    if (!showsUnavailablePluginIndicator())
+        return;
+
+    if (paintInfo.phase == PaintPhaseSelection)
+        return;
+    
+    GraphicsContext* context = paintInfo.context;
+    if (context->paintingDisabled())
+        return;
+    
+    FloatRect contentRect;
+    Path path;
+    FloatRect replacementTextRect;
+    Font font;
+    TextRun run("");
+    float textWidth;
+    if (!getReplacementTextGeometry(paintOffset, contentRect, path, replacementTextRect, font, run, textWidth))
+        return;
+    
+    GraphicsContextStateSaver stateSaver(*context);
+    context->clip(contentRect);
+    context->setAlpha(m_unavailablePluginIndicatorIsPressed ? replacementTextPressedRoundedRectOpacity : replacementTextRoundedRectOpacity);
+    context->setFillColor(m_unavailablePluginIndicatorIsPressed ? replacementTextRoundedRectPressedColor() : Color::white, style()->colorSpace());
+    context->fillPath(path);
+
+    const FontMetrics& fontMetrics = font.fontMetrics();
+    float labelX = roundf(replacementTextRect.location().x() + (replacementTextRect.size().width() - textWidth) / 2);
+    float labelY = roundf(replacementTextRect.location().y() + (replacementTextRect.size().height() - fontMetrics.height()) / 2 + fontMetrics.ascent());
+    context->setAlpha(m_unavailablePluginIndicatorIsPressed ? replacementTextPressedTextOpacity : replacementTextTextOpacity);
+    context->setFillColor(Color::black, style()->colorSpace());
+    context->drawBidiText(font, run, FloatPoint(labelX, labelY));
+}
+
+bool RenderEmbeddedObject::getReplacementTextGeometry(const LayoutPoint& accumulatedOffset, FloatRect& contentRect, Path& path, FloatRect& replacementTextRect, Font& font, TextRun& run, float& textWidth) const
+{
+    contentRect = contentBoxRect();
+    contentRect.moveBy(roundedIntPoint(accumulatedOffset));
+    
+    FontDescription fontDescription;
+    RenderTheme::defaultTheme()->systemFont(CSSValueWebkitSmallControl, fontDescription);
+    fontDescription.setWeight(FontWeightBold);
+    Settings* settings = document()->settings();
+    ASSERT(settings);
+    if (!settings)
+        return false;
+    fontDescription.setRenderingMode(settings->fontRenderingMode());
+    fontDescription.setComputedSize(fontDescription.specifiedSize());
+    font = Font(fontDescription, 0, 0);
+    font.update(0);
+
+    run = TextRun(m_unavailablePluginReplacementText);
+    textWidth = font.width(run);
+    
+    replacementTextRect.setSize(FloatSize(textWidth + replacementTextRoundedRectLeftRightTextMargin * 2, replacementTextRoundedRectHeight));
+    float x = (contentRect.size().width() / 2 - replacementTextRect.size().width() / 2) + contentRect.location().x();
+    float y = (contentRect.size().height() / 2 - replacementTextRect.size().height() / 2) + contentRect.location().y();
+    replacementTextRect.setLocation(FloatPoint(x, y));
+    
+    path.addRoundedRect(replacementTextRect, FloatSize(replacementTextRoundedRectRadius, replacementTextRoundedRectRadius));
+
+    return true;
+}
+
+void RenderEmbeddedObject::layout()
+{
+    StackStats::LayoutCheckPoint layoutCheckPoint;
+    ASSERT(needsLayout());
+
+    LayoutSize oldSize = contentBoxRect().size();
+
+    updateLogicalWidth();
+    updateLogicalHeight();
+
+    RenderPart::layout();
+
+    m_overflow.clear();
+    addVisualEffectOverflow();
+
+    updateLayerTransform();
+
+    if (!widget() && frameView())
+        frameView()->addWidgetToUpdate(this);
+
+    setNeedsLayout(false);
+
+    if (!canHaveChildren())
+        return;
+
+    // This code copied from RenderMedia::layout().
+    RenderObject* child = m_children.firstChild();
+
+    if (!child)
+        return;
+
+    RenderBox* childBox = toRenderBox(child);
+
+    if (!childBox)
+        return;
+    
+    LayoutSize newSize = contentBoxRect().size();
+    if (newSize == oldSize && !childBox->needsLayout())
+        return;
+    
+    // When calling layout() on a child node, a parent must either push a LayoutStateMaintainter, or
+    // instantiate LayoutStateDisabler. Since using a LayoutStateMaintainer is slightly more efficient,
+    // and this method will be called many times per second during playback, use a LayoutStateMaintainer:
+    LayoutStateMaintainer statePusher(view(), this, locationOffset(), hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode());
+    
+    childBox->setLocation(LayoutPoint(borderLeft(), borderTop()) + LayoutSize(paddingLeft(), paddingTop()));
+    childBox->style()->setHeight(Length(newSize.height(), Fixed));
+    childBox->style()->setWidth(Length(newSize.width(), Fixed));
+    childBox->setNeedsLayout(true, MarkOnlyThis);
+    childBox->layout();
+    setChildNeedsLayout(false);
+    
+    statePusher.pop();
+}
+
+void RenderEmbeddedObject::viewCleared()
+{
+    // This is required for <object> elements whose contents are rendered by WebCore (e.g. src="foo.html").
+    if (node() && widget() && widget()->isFrameView()) {
+        FrameView* view = toFrameView(widget());
+        int marginWidth = -1;
+        int marginHeight = -1;
+        if (node()->hasTagName(iframeTag)) {
+            HTMLIFrameElement* frame = static_cast<HTMLIFrameElement*>(node());
+            marginWidth = frame->marginWidth();
+            marginHeight = frame->marginHeight();
+        }
+        if (marginWidth != -1)
+            view->setMarginWidth(marginWidth);
+        if (marginHeight != -1)
+            view->setMarginHeight(marginHeight);
+    }
+}
+
+bool RenderEmbeddedObject::scroll(ScrollDirection direction, ScrollGranularity granularity, float, Node**)
+{
+    return false;
+}
+
+bool RenderEmbeddedObject::logicalScroll(ScrollLogicalDirection direction, ScrollGranularity granularity, float multiplier, Node** stopNode)
+{
+    return false;
+}
+
+bool RenderEmbeddedObject::isInUnavailablePluginIndicator(const LayoutPoint& point) const
+{
+    FloatRect contentRect;
+    Path path;
+    FloatRect replacementTextRect;
+    Font font;
+    TextRun run("");
+    float textWidth;
+    return getReplacementTextGeometry(IntPoint(), contentRect, path, replacementTextRect, font, run, textWidth)
+        && path.contains(point);
+}
+
+bool RenderEmbeddedObject::isInUnavailablePluginIndicator(MouseEvent* event) const
+{
+    return isInUnavailablePluginIndicator(roundedLayoutPoint(absoluteToLocal(event->absoluteLocation(), UseTransforms)));
+}
+
+static bool shouldUnavailablePluginMessageBeButton(Document* document, RenderEmbeddedObject::PluginUnavailabilityReason pluginUnavailabilityReason)
+{
+    Page* page = document->page();
+    return page && page->chrome()->client()->shouldUnavailablePluginMessageBeButton(pluginUnavailabilityReason);
+}
+
+void RenderEmbeddedObject::handleUnavailablePluginIndicatorEvent(Event* event)
+{
+    if (!shouldUnavailablePluginMessageBeButton(document(), m_pluginUnavailabilityReason))
+        return;
+    
+    if (!event->isMouseEvent())
+        return;
+    
+    MouseEvent* mouseEvent = static_cast<MouseEvent*>(event);
+    HTMLPlugInElement* element = toHTMLPlugInElement(node());
+    if (event->type() == eventNames().mousedownEvent && static_cast<MouseEvent*>(event)->button() == LeftButton) {
+        m_mouseDownWasInUnavailablePluginIndicator = isInUnavailablePluginIndicator(mouseEvent);
+        if (m_mouseDownWasInUnavailablePluginIndicator) {
+            if (Frame* frame = document()->frame()) {
+                frame->eventHandler()->setCapturingMouseEventsNode(element);
+                element->setIsCapturingMouseEvents(true);
+            }
+            setUnavailablePluginIndicatorIsPressed(true);
+        }
+        event->setDefaultHandled();
+    }        
+    if (event->type() == eventNames().mouseupEvent && static_cast<MouseEvent*>(event)->button() == LeftButton) {
+        if (m_unavailablePluginIndicatorIsPressed) {
+            if (Frame* frame = document()->frame()) {
+                frame->eventHandler()->setCapturingMouseEventsNode(0);
+                element->setIsCapturingMouseEvents(false);
+            }
+            setUnavailablePluginIndicatorIsPressed(false);
+        }
+        if (m_mouseDownWasInUnavailablePluginIndicator && isInUnavailablePluginIndicator(mouseEvent)) {
+            if (Page* page = document()->page())
+                page->chrome()->client()->unavailablePluginButtonClicked(element, m_pluginUnavailabilityReason);
+        }
+        m_mouseDownWasInUnavailablePluginIndicator = false;
+        event->setDefaultHandled();
+    }
+    if (event->type() == eventNames().mousemoveEvent) {
+        setUnavailablePluginIndicatorIsPressed(m_mouseDownWasInUnavailablePluginIndicator && isInUnavailablePluginIndicator(mouseEvent));
+        event->setDefaultHandled();
+    }
+}
+
+CursorDirective RenderEmbeddedObject::getCursor(const LayoutPoint& point, Cursor& cursor) const
+{
+    if (showsUnavailablePluginIndicator() && shouldUnavailablePluginMessageBeButton(document(), m_pluginUnavailabilityReason) && isInUnavailablePluginIndicator(point)) {
+        cursor = handCursor();
+        return SetCursor;
+    }
+    return RenderPart::getCursor(point, cursor);
+}
+
+bool RenderEmbeddedObject::canHaveChildren() const
+{
+    return false;
+}
+
+}
diff --git a/Source/core/rendering/RenderEmbeddedObject.h b/Source/core/rendering/RenderEmbeddedObject.h
new file mode 100644
index 0000000..56a28e8
--- /dev/null
+++ b/Source/core/rendering/RenderEmbeddedObject.h
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 2000 Simon Hausmann <hausmann@kde.org>
+ * Copyright (C) 2004, 2005, 2006, 2008, 2009, 2010, 2012 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 RenderEmbeddedObject_h
+#define RenderEmbeddedObject_h
+
+#include "core/rendering/RenderPart.h"
+
+namespace WebCore {
+
+class MouseEvent;
+class TextRun;
+
+// Renderer for embeds and objects, often, but not always, rendered via plug-ins.
+// For example, <embed src="foo.html"> does not invoke a plug-in.
+class RenderEmbeddedObject : public RenderPart {
+public:
+    RenderEmbeddedObject(Element*);
+    virtual ~RenderEmbeddedObject();
+
+    enum PluginUnavailabilityReason {
+        PluginMissing,
+        PluginCrashed,
+        PluginBlockedByContentSecurityPolicy,
+        InsecurePluginVersion,
+        PluginInactive,
+    };
+    void setPluginUnavailabilityReason(PluginUnavailabilityReason);
+    bool showsUnavailablePluginIndicator() const;
+
+    // FIXME: This belongs on HTMLObjectElement.
+    bool hasFallbackContent() const { return m_hasFallbackContent; }
+    void setHasFallbackContent(bool hasFallbackContent) { m_hasFallbackContent = hasFallbackContent; }
+
+    void handleUnavailablePluginIndicatorEvent(Event*);
+
+    bool allowsAcceleratedCompositing() const;
+
+protected:
+    virtual void paintReplaced(PaintInfo&, const LayoutPoint&) OVERRIDE FINAL;
+    virtual void paint(PaintInfo&, const LayoutPoint&) OVERRIDE FINAL;
+
+    virtual CursorDirective getCursor(const LayoutPoint&, Cursor&) const OVERRIDE FINAL;
+
+    const RenderObjectChildList* children() const { return &m_children; }
+    RenderObjectChildList* children() { return &m_children; }
+
+protected:
+    virtual void layout() OVERRIDE FINAL;
+
+private:
+    virtual const char* renderName() const { return "RenderEmbeddedObject"; }
+    virtual bool isEmbeddedObject() const OVERRIDE FINAL { return true; }
+
+    void paintSnapshotImage(PaintInfo&, const LayoutPoint&, Image*);
+    virtual void paintContents(PaintInfo&, const LayoutPoint&) OVERRIDE FINAL;
+
+    virtual bool requiresLayer() const OVERRIDE FINAL;
+
+    virtual void viewCleared() OVERRIDE FINAL;
+
+    virtual bool scroll(ScrollDirection, ScrollGranularity, float multiplier, Node** stopNode) OVERRIDE FINAL;
+    virtual bool logicalScroll(ScrollLogicalDirection, ScrollGranularity, float multiplier, Node** stopNode) OVERRIDE FINAL;
+
+    void setUnavailablePluginIndicatorIsPressed(bool);
+    bool isInUnavailablePluginIndicator(MouseEvent*) const;
+    bool isInUnavailablePluginIndicator(const LayoutPoint&) const;
+    bool getReplacementTextGeometry(const LayoutPoint& accumulatedOffset, FloatRect& contentRect, Path&, FloatRect& replacementTextRect, Font&, TextRun&, float& textWidth) const;
+
+    virtual bool canHaveChildren() const OVERRIDE FINAL;
+    virtual RenderObjectChildList* virtualChildren() OVERRIDE FINAL { return children(); }
+    virtual const RenderObjectChildList* virtualChildren() const OVERRIDE FINAL { return children(); }
+    
+    bool m_hasFallbackContent; // FIXME: This belongs on HTMLObjectElement.
+
+    bool m_showsUnavailablePluginIndicator;
+    PluginUnavailabilityReason m_pluginUnavailabilityReason;
+    String m_unavailablePluginReplacementText;
+    bool m_unavailablePluginIndicatorIsPressed;
+    bool m_mouseDownWasInUnavailablePluginIndicator;
+    RenderObjectChildList m_children;
+};
+
+inline RenderEmbeddedObject* toRenderEmbeddedObject(RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isEmbeddedObject());
+    return static_cast<RenderEmbeddedObject*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderEmbeddedObject(const RenderEmbeddedObject*);
+
+} // namespace WebCore
+
+#endif // RenderEmbeddedObject_h
diff --git a/Source/core/rendering/RenderFieldset.cpp b/Source/core/rendering/RenderFieldset.cpp
new file mode 100644
index 0000000..3f8ec31
--- /dev/null
+++ b/Source/core/rendering/RenderFieldset.cpp
@@ -0,0 +1,215 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2000 Dirk Mueller (mueller@kde.org)
+ * 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 "core/rendering/RenderFieldset.h"
+
+#include "CSSPropertyNames.h"
+#include "HTMLNames.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/rendering/PaintInfo.h"
+
+using std::min;
+using std::max;
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+RenderFieldset::RenderFieldset(Element* element)
+    : RenderBlock(element)
+{
+}
+
+void RenderFieldset::computePreferredLogicalWidths()
+{
+    RenderBlock::computePreferredLogicalWidths();
+    if (RenderBox* legend = findLegend()) {
+        int legendMinWidth = legend->minPreferredLogicalWidth();
+
+        Length legendMarginLeft = legend->style()->marginLeft();
+        Length legendMarginRight = legend->style()->marginLeft();
+
+        if (legendMarginLeft.isFixed())
+            legendMinWidth += legendMarginLeft.value();
+
+        if (legendMarginRight.isFixed())
+            legendMinWidth += legendMarginRight.value();
+
+        m_minPreferredLogicalWidth = max(m_minPreferredLogicalWidth, legendMinWidth + borderAndPaddingWidth());
+    }
+}
+
+RenderObject* RenderFieldset::layoutSpecialExcludedChild(bool relayoutChildren)
+{
+    RenderBox* legend = findLegend();
+    if (legend) {
+        if (relayoutChildren)
+            legend->setNeedsLayout(true);
+        legend->layoutIfNeeded();
+
+        LayoutUnit logicalLeft;
+        if (style()->isLeftToRightDirection()) {
+            switch (legend->style()->textAlign()) {
+            case CENTER:
+                logicalLeft = (logicalWidth() - logicalWidthForChild(legend)) / 2;
+                break;
+            case RIGHT:
+                logicalLeft = logicalWidth() - borderEnd() - paddingEnd() - logicalWidthForChild(legend);
+                break;
+            default:
+                logicalLeft = borderStart() + paddingStart() + marginStartForChild(legend);
+                break;
+            }
+        } else {
+            switch (legend->style()->textAlign()) {
+            case LEFT:
+                logicalLeft = borderStart() + paddingStart();
+                break;
+            case CENTER: {
+                // Make sure that the extra pixel goes to the end side in RTL (since it went to the end side
+                // in LTR).
+                LayoutUnit centeredWidth = logicalWidth() - logicalWidthForChild(legend);
+                logicalLeft = centeredWidth - centeredWidth / 2;
+                break;
+            }
+            default:
+                logicalLeft = logicalWidth() - borderStart() - paddingStart() - marginStartForChild(legend) - logicalWidthForChild(legend);
+                break;
+            }
+        }
+
+        setLogicalLeftForChild(legend, logicalLeft);
+
+        LayoutUnit fieldsetBorderBefore = borderBefore();
+        LayoutUnit legendLogicalHeight = logicalHeightForChild(legend);
+
+        LayoutUnit legendLogicalTop;
+        LayoutUnit collapsedLegendExtent;
+        // FIXME: We need to account for the legend's margin before too.
+        if (fieldsetBorderBefore > legendLogicalHeight) {
+            // The <legend> is smaller than the associated fieldset before border
+            // so the latter determines positioning of the <legend>. The sizing depends
+            // on the legend's margins as we want to still follow the author's cues.
+            // Firefox completely ignores the margins in this case which seems wrong.
+            legendLogicalTop = (fieldsetBorderBefore - legendLogicalHeight) / 2;
+            collapsedLegendExtent = max<LayoutUnit>(fieldsetBorderBefore, legendLogicalTop + legendLogicalHeight + marginAfterForChild(legend));
+        } else
+            collapsedLegendExtent = legendLogicalHeight + marginAfterForChild(legend);
+
+        setLogicalTopForChild(legend, legendLogicalTop);
+        setLogicalHeight(paddingBefore() + collapsedLegendExtent);
+    }
+    return legend;
+}
+
+RenderBox* RenderFieldset::findLegend(FindLegendOption option) const
+{
+    for (RenderObject* legend = firstChild(); legend; legend = legend->nextSibling()) {
+        if (option == IgnoreFloatingOrOutOfFlow && legend->isFloatingOrOutOfFlowPositioned())
+            continue;
+        
+        if (legend->node() && (legend->node()->hasTagName(legendTag)))
+            return toRenderBox(legend);
+    }
+    return 0;
+}
+
+void RenderFieldset::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    if (!paintInfo.shouldPaintWithinRoot(this))
+        return;
+
+    LayoutRect paintRect(paintOffset, size());
+    RenderBox* legend = findLegend();
+    if (!legend)
+        return RenderBlock::paintBoxDecorations(paintInfo, paintOffset);
+
+    // FIXME: We need to work with "rl" and "bt" block flow directions.  In those
+    // cases the legend is embedded in the right and bottom borders respectively.
+    // https://bugs.webkit.org/show_bug.cgi?id=47236
+    if (style()->isHorizontalWritingMode()) {
+        LayoutUnit yOff = (legend->y() > 0) ? LayoutUnit() : (legend->height() - borderTop()) / 2;
+        paintRect.setHeight(paintRect.height() - yOff);
+        paintRect.setY(paintRect.y() + yOff);
+    } else {
+        LayoutUnit xOff = (legend->x() > 0) ? LayoutUnit() : (legend->width() - borderLeft()) / 2;
+        paintRect.setWidth(paintRect.width() - xOff);
+        paintRect.setX(paintRect.x() + xOff);
+    }
+
+    if (!boxShadowShouldBeAppliedToBackground(determineBackgroundBleedAvoidance(paintInfo.context)))
+        paintBoxShadow(paintInfo, paintRect, style(), Normal);
+    paintFillLayers(paintInfo, style()->visitedDependentColor(CSSPropertyBackgroundColor), style()->backgroundLayers(), paintRect);
+    paintBoxShadow(paintInfo, paintRect, style(), Inset);
+
+    if (!style()->hasBorder())
+        return;
+    
+    // Create a clipping region around the legend and paint the border as normal
+    GraphicsContext* graphicsContext = paintInfo.context;
+    GraphicsContextStateSaver stateSaver(*graphicsContext);
+
+    // FIXME: We need to work with "rl" and "bt" block flow directions.  In those
+    // cases the legend is embedded in the right and bottom borders respectively.
+    // https://bugs.webkit.org/show_bug.cgi?id=47236
+    if (style()->isHorizontalWritingMode()) {
+        LayoutUnit clipTop = paintRect.y();
+        LayoutUnit clipHeight = max(static_cast<LayoutUnit>(style()->borderTopWidth()), legend->height() - ((legend->height() - borderTop()) / 2));
+        graphicsContext->clipOut(pixelSnappedIntRect(paintRect.x() + legend->x(), clipTop, legend->width(), clipHeight));
+    } else {
+        LayoutUnit clipLeft = paintRect.x();
+        LayoutUnit clipWidth = max(static_cast<LayoutUnit>(style()->borderLeftWidth()), legend->width());
+        graphicsContext->clipOut(pixelSnappedIntRect(clipLeft, paintRect.y() + legend->y(), clipWidth, legend->height()));
+    }
+
+    paintBorder(paintInfo, paintRect, style());
+}
+
+void RenderFieldset::paintMask(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    if (style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask)
+        return;
+
+    LayoutRect paintRect = LayoutRect(paintOffset, size());
+    RenderBox* legend = findLegend();
+    if (!legend)
+        return RenderBlock::paintMask(paintInfo, paintOffset);
+
+    // FIXME: We need to work with "rl" and "bt" block flow directions.  In those
+    // cases the legend is embedded in the right and bottom borders respectively.
+    // https://bugs.webkit.org/show_bug.cgi?id=47236
+    if (style()->isHorizontalWritingMode()) {
+        LayoutUnit yOff = (legend->y() > 0) ? LayoutUnit() : (legend->height() - borderTop()) / 2;
+        paintRect.expand(0, -yOff);
+        paintRect.move(0, yOff);
+    } else {
+        LayoutUnit xOff = (legend->x() > 0) ? LayoutUnit() : (legend->width() - borderLeft()) / 2;
+        paintRect.expand(-xOff, 0);
+        paintRect.move(xOff, 0);
+    }
+
+    paintMaskImages(paintInfo, paintRect);
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderFieldset.h b/Source/core/rendering/RenderFieldset.h
new file mode 100644
index 0000000..151d535
--- /dev/null
+++ b/Source/core/rendering/RenderFieldset.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2004, 2006, 2009 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 RenderFieldset_h
+#define RenderFieldset_h
+
+#include "core/rendering/RenderBlock.h"
+
+namespace WebCore {
+
+class RenderFieldset FINAL : public RenderBlock {
+public:
+    explicit RenderFieldset(Element*);
+
+    enum FindLegendOption { IgnoreFloatingOrOutOfFlow, IncludeFloatingOrOutOfFlow };
+    RenderBox* findLegend(FindLegendOption = IgnoreFloatingOrOutOfFlow) const;
+
+private:
+    virtual const char* renderName() const { return "RenderFieldSet"; }
+    virtual bool isFieldset() const { return true; }
+
+    virtual RenderObject* layoutSpecialExcludedChild(bool relayoutChildren);
+
+    virtual void computePreferredLogicalWidths();
+    virtual bool avoidsFloats() const { return true; }
+
+    virtual void paintBoxDecorations(PaintInfo&, const LayoutPoint&);
+    virtual void paintMask(PaintInfo&, const LayoutPoint&);
+};
+
+inline RenderFieldset* toRenderFieldset(RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isFieldset());
+    return static_cast<RenderFieldset*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderFieldset(const RenderFieldset*);
+
+} // namespace WebCore
+
+#endif // RenderFieldset_h
diff --git a/Source/core/rendering/RenderFileUploadControl.cpp b/Source/core/rendering/RenderFileUploadControl.cpp
new file mode 100644
index 0000000..4b2b657
--- /dev/null
+++ b/Source/core/rendering/RenderFileUploadControl.cpp
@@ -0,0 +1,252 @@
+/*
+ * Copyright (C) 2006, 2007, 2012 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 "core/rendering/RenderFileUploadControl.h"
+
+#include <math.h>
+#include "HTMLNames.h"
+#include "core/dom/ElementShadow.h"
+#include "core/dom/ShadowRoot.h"
+#include "core/editing/VisiblePosition.h"
+#include "core/fileapi/FileList.h"
+#include "core/html/HTMLInputElement.h"
+#include "core/platform/LocalizedStrings.h"
+#include "core/platform/graphics/Font.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/platform/graphics/Icon.h"
+#include "core/platform/graphics/TextRun.h"
+#include "core/rendering/PaintInfo.h"
+#include "core/rendering/RenderButton.h"
+#include "core/rendering/RenderText.h"
+#include "core/rendering/RenderTheme.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;
+
+RenderFileUploadControl::RenderFileUploadControl(HTMLInputElement* input)
+    : RenderBlock(input)
+    , m_canReceiveDroppedFiles(input->canReceiveDroppedFiles())
+{
+}
+
+RenderFileUploadControl::~RenderFileUploadControl()
+{
+}
+
+bool RenderFileUploadControl::canBeReplacedWithInlineRunIn() const
+{
+    return false;
+}
+
+void RenderFileUploadControl::updateFromElement()
+{
+    HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
+    ASSERT(input->isFileUpload());
+
+    if (HTMLInputElement* button = uploadButton()) {
+        bool newCanReceiveDroppedFilesState = input->canReceiveDroppedFiles();
+        if (m_canReceiveDroppedFiles != newCanReceiveDroppedFilesState) {
+            m_canReceiveDroppedFiles = newCanReceiveDroppedFilesState;
+            button->setActive(newCanReceiveDroppedFilesState);
+        }
+    }
+
+    // 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 = input->files();
+    ASSERT(files);
+    if (files && files->isEmpty())
+        repaint();
+}
+
+static int nodeWidth(Node* node)
+{
+    return (node && node->renderBox()) ? node->renderBox()->pixelSnappedWidth() : 0;
+}
+
+int RenderFileUploadControl::maxFilenameWidth() const
+{
+    HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
+    return max(0, contentBoxRect().pixelSnappedWidth() - nodeWidth(uploadButton()) - afterButtonSpacing
+        - (input->icon() ? iconWidth + iconFilenameSpacing : 0));
+}
+
+void RenderFileUploadControl::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    if (style()->visibility() != VISIBLE)
+        return;
+    
+    // Push a clip.
+    GraphicsContextStateSaver stateSaver(*paintInfo.context, false);
+    if (paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseChildBlockBackgrounds) {
+        IntRect clipRect = enclosingIntRect(LayoutRect(paintOffset.x() + borderLeft(), paintOffset.y() + borderTop(),
+                         width() - borderLeft() - borderRight(), height() - borderBottom() - borderTop() + buttonShadowHeight));
+        if (clipRect.isEmpty())
+            return;
+        stateSaver.save();
+        paintInfo.context->clip(clipRect);
+    }
+
+    if (paintInfo.phase == PaintPhaseForeground) {
+        const String& displayedFilename = fileTextValue();
+        const Font& font = style()->font();
+        TextRun textRun = constructTextRun(this, font, displayedFilename, style(), TextRun::AllowTrailingExpansion, RespectDirection | RespectDirectionOverride);
+        textRun.disableRoundingHacks();
+
+        // Determine where the filename should be placed
+        LayoutUnit contentLeft = paintOffset.x() + borderLeft() + paddingLeft();
+        HTMLInputElement* button = uploadButton();
+        if (!button)
+            return;
+
+        HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
+        LayoutUnit buttonWidth = nodeWidth(button);
+        LayoutUnit buttonAndIconWidth = buttonWidth + afterButtonSpacing
+            + (input->icon() ? iconWidth + iconFilenameSpacing : 0);
+        LayoutUnit textX;
+        if (style()->isLeftToRightDirection())
+            textX = contentLeft + buttonAndIconWidth;
+        else
+            textX = contentLeft + contentWidth() - buttonAndIconWidth - font.width(textRun);
+
+        LayoutUnit textY = 0;
+        // We want to match the button's baseline
+        // FIXME: Make this work with transforms.
+        if (RenderButton* buttonRenderer = toRenderButton(button->renderer()))
+            textY = paintOffset.y() + borderTop() + paddingTop() + buttonRenderer->baselinePosition(AlphabeticBaseline, true, HorizontalLine, PositionOnContainingLine);
+        else
+            textY = baselinePosition(AlphabeticBaseline, true, HorizontalLine, PositionOnContainingLine);
+
+        paintInfo.context->setFillColor(style()->visitedDependentColor(CSSPropertyColor), style()->colorSpace());
+        
+        // Draw the filename
+        paintInfo.context->drawBidiText(font, textRun, IntPoint(roundToInt(textX), roundToInt(textY)));
+        
+        if (input->icon()) {
+            // Determine where the icon should be placed
+            LayoutUnit iconY = paintOffset.y() + borderTop() + paddingTop() + (contentHeight() - iconHeight) / 2;
+            LayoutUnit iconX;
+            if (style()->isLeftToRightDirection())
+                iconX = contentLeft + buttonWidth + afterButtonSpacing;
+            else
+                iconX = contentLeft + contentWidth() - buttonWidth - afterButtonSpacing - iconWidth;
+
+            // Draw the file icon
+            input->icon()->paint(paintInfo.context, IntRect(roundToInt(iconX), roundToInt(iconY), iconWidth, iconHeight));
+        }
+    }
+
+    // Paint the children.
+    RenderBlock::paintObject(paintInfo, paintOffset);
+}
+
+void RenderFileUploadControl::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const
+{
+    // Figure out how big the filename space needs to be for a given number of characters
+    // (using "0" as the nominal character).
+    const UChar character = '0';
+    const String characterAsString = String(&character, 1);
+    const Font& font = style()->font();
+    // FIXME: Remove the need for this const_cast by making constructTextRun take a const RenderObject*.
+    RenderFileUploadControl* renderer = const_cast<RenderFileUploadControl*>(this);
+    float minDefaultLabelWidth = defaultWidthNumChars * font.width(constructTextRun(renderer, font, characterAsString, style(), TextRun::AllowTrailingExpansion));
+
+    const String label = theme()->fileListDefaultLabel(node()->toInputElement()->multiple());
+    float defaultLabelWidth = font.width(constructTextRun(renderer, font, label, style(), TextRun::AllowTrailingExpansion));
+    if (HTMLInputElement* button = uploadButton())
+        if (RenderObject* buttonRenderer = button->renderer())
+            defaultLabelWidth += buttonRenderer->maxPreferredLogicalWidth() + afterButtonSpacing;
+    maxLogicalWidth = static_cast<int>(ceilf(max(minDefaultLabelWidth, defaultLabelWidth)));
+
+    if (!style()->width().isPercent())
+        minLogicalWidth = maxLogicalWidth;
+}
+
+void RenderFileUploadControl::computePreferredLogicalWidths()
+{
+    ASSERT(preferredLogicalWidthsDirty());
+
+    m_minPreferredLogicalWidth = 0;
+    m_maxPreferredLogicalWidth = 0;
+
+    if (style()->width().isFixed() && style()->width().value() > 0)
+        m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = adjustContentBoxLogicalWidthForBoxSizing(style()->width().value());
+    else
+        computeIntrinsicLogicalWidths(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);
+
+    if (style()->minWidth().isFixed() && style()->minWidth().value() > 0) {
+        m_maxPreferredLogicalWidth = max(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->minWidth().value()));
+        m_minPreferredLogicalWidth = max(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->minWidth().value()));
+    }
+
+    if (style()->maxWidth().isFixed()) {
+        m_maxPreferredLogicalWidth = min(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->maxWidth().value()));
+        m_minPreferredLogicalWidth = min(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->maxWidth().value()));
+    }
+
+    int toAdd = borderAndPaddingWidth();
+    m_minPreferredLogicalWidth += toAdd;
+    m_maxPreferredLogicalWidth += toAdd;
+
+    setPreferredLogicalWidthsDirty(false);
+}
+
+VisiblePosition RenderFileUploadControl::positionForPoint(const LayoutPoint&)
+{
+    return VisiblePosition();
+}
+
+HTMLInputElement* RenderFileUploadControl::uploadButton() const
+{
+    HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
+
+    ASSERT(input->shadow());
+
+    Node* buttonNode = input->shadow()->oldestShadowRoot()->firstChild();
+    return buttonNode && buttonNode->isHTMLElement() && buttonNode->hasTagName(inputTag) ? static_cast<HTMLInputElement*>(buttonNode) : 0;
+}
+
+String RenderFileUploadControl::buttonValue()
+{
+    if (HTMLInputElement* button = uploadButton())
+        return button->value();
+    
+    return String();
+}
+
+String RenderFileUploadControl::fileTextValue() const
+{
+    HTMLInputElement* input = static_cast<HTMLInputElement*>(node());
+    ASSERT(input->files());
+    return theme()->fileListNameForWidth(input->files(), style()->font(), maxFilenameWidth(), input->multiple());
+}
+    
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderFileUploadControl.h b/Source/core/rendering/RenderFileUploadControl.h
new file mode 100644
index 0000000..eb19aa7
--- /dev/null
+++ b/Source/core/rendering/RenderFileUploadControl.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2006, 2007, 2009, 2012 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 RenderFileUploadControl_h
+#define RenderFileUploadControl_h
+
+#include "core/rendering/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 FINAL : public RenderBlock {
+public:
+    RenderFileUploadControl(HTMLInputElement*);
+    virtual ~RenderFileUploadControl();
+
+    virtual bool isFileUploadControl() const { return true; }
+
+    String buttonValue();
+    String fileTextValue() const;
+    
+private:
+    virtual const char* renderName() const { return "RenderFileUploadControl"; }
+
+    virtual bool canBeReplacedWithInlineRunIn() const OVERRIDE;
+    virtual void updateFromElement();
+    virtual void computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const OVERRIDE;
+    virtual void computePreferredLogicalWidths();
+    virtual void paintObject(PaintInfo&, const LayoutPoint&);
+
+    virtual bool requiresForcedStyleRecalcPropagation() const { return true; }
+
+    int maxFilenameWidth() const;
+    
+    virtual VisiblePosition positionForPoint(const LayoutPoint&);
+
+    HTMLInputElement* uploadButton() const;
+
+    bool m_canReceiveDroppedFiles;
+};
+
+inline RenderFileUploadControl* toRenderFileUploadControl(RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isFileUploadControl());
+    return static_cast<RenderFileUploadControl*>(object);
+}
+
+inline const RenderFileUploadControl* toRenderFileUploadControl(const RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isFileUploadControl());
+    return static_cast<const RenderFileUploadControl*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderFileUploadControl(const RenderFileUploadControl*);
+
+} // namespace WebCore
+
+#endif // RenderFileUploadControl_h
diff --git a/Source/core/rendering/RenderFlexibleBox.cpp b/Source/core/rendering/RenderFlexibleBox.cpp
new file mode 100644
index 0000000..eea7500
--- /dev/null
+++ b/Source/core/rendering/RenderFlexibleBox.cpp
@@ -0,0 +1,1452 @@
+/*
+ * Copyright (C) 2011 Google 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:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+ * OWNER 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 "core/rendering/RenderFlexibleBox.h"
+
+#include <limits>
+#include "core/rendering/LayoutRepainter.h"
+#include "core/rendering/RenderLayer.h"
+#include "core/rendering/RenderView.h"
+#include <wtf/MathExtras.h>
+
+namespace WebCore {
+
+// Normally, -1 and 0 are not valid in a HashSet, but these are relatively likely order: values. Instead,
+// we make the two smallest int values invalid order: values (in the css parser code we clamp them to
+// int min + 2).
+struct RenderFlexibleBox::OrderHashTraits : WTF::GenericHashTraits<int> {
+    static const bool emptyValueIsZero = false;
+    static int emptyValue() { return std::numeric_limits<int>::min(); }
+    static void constructDeletedValue(int& slot) { slot = std::numeric_limits<int>::min() + 1; }
+    static bool isDeletedValue(int value) { return value == std::numeric_limits<int>::min() + 1; }
+};
+
+RenderFlexibleBox::OrderIterator::OrderIterator(const RenderFlexibleBox* flexibleBox)
+    : m_flexibleBox(flexibleBox)
+    , m_currentChild(0)
+    , m_orderValuesIterator(0)
+{
+}
+
+void RenderFlexibleBox::OrderIterator::setOrderValues(const OrderHashSet& orderValues)
+{
+    reset();
+    copyToVector(orderValues, m_orderValues);
+    std::sort(m_orderValues.begin(), m_orderValues.end());
+}
+
+RenderBox* RenderFlexibleBox::OrderIterator::first()
+{
+    reset();
+    return next();
+}
+
+RenderBox* RenderFlexibleBox::OrderIterator::next()
+{
+    do {
+        if (!m_currentChild) {
+            if (m_orderValuesIterator == m_orderValues.end())
+                return 0;
+            if (m_orderValuesIterator) {
+                ++m_orderValuesIterator;
+                if (m_orderValuesIterator == m_orderValues.end())
+                    return 0;
+            } else
+                m_orderValuesIterator = m_orderValues.begin();
+
+            m_currentChild = m_flexibleBox->firstChildBox();
+        } else
+            m_currentChild = m_currentChild->nextSiblingBox();
+    } while (!m_currentChild || m_currentChild->style()->order() != *m_orderValuesIterator);
+
+    return m_currentChild;
+}
+
+void RenderFlexibleBox::OrderIterator::reset()
+{
+    m_currentChild = 0;
+    m_orderValuesIterator = 0;
+}
+
+struct RenderFlexibleBox::LineContext {
+    LineContext(LayoutUnit crossAxisOffset, LayoutUnit crossAxisExtent, size_t numberOfChildren, LayoutUnit maxAscent)
+        : crossAxisOffset(crossAxisOffset)
+        , crossAxisExtent(crossAxisExtent)
+        , numberOfChildren(numberOfChildren)
+        , maxAscent(maxAscent)
+    {
+    }
+
+    LayoutUnit crossAxisOffset;
+    LayoutUnit crossAxisExtent;
+    size_t numberOfChildren;
+    LayoutUnit maxAscent;
+};
+
+struct RenderFlexibleBox::Violation {
+    Violation(RenderBox* child, LayoutUnit childSize)
+        : child(child)
+        , childSize(childSize)
+    {
+    }
+
+    RenderBox* child;
+    LayoutUnit childSize;
+};
+
+
+RenderFlexibleBox::RenderFlexibleBox(Element* element)
+    : RenderBlock(element)
+    , m_orderIterator(this)
+    , m_numberOfInFlowChildrenOnFirstLine(-1)
+{
+    setChildrenInline(false); // All of our children must be block-level.
+}
+
+RenderFlexibleBox::~RenderFlexibleBox()
+{
+}
+
+RenderFlexibleBox* RenderFlexibleBox::createAnonymous(Document* document)
+{
+    RenderFlexibleBox* renderer = new (document->renderArena()) RenderFlexibleBox(0);
+    renderer->setDocumentForAnonymous(document);
+    return renderer;
+}
+
+const char* RenderFlexibleBox::renderName() const
+{
+    return "RenderFlexibleBox";
+}
+
+static LayoutUnit marginLogicalWidthForChild(RenderBox* child, RenderStyle* parentStyle)
+{
+    // A margin has three types: fixed, percentage, and auto (variable).
+    // Auto and percentage margins become 0 when computing min/max width.
+    // Fixed margins can be added in as is.
+    Length marginLeft = child->style()->marginStartUsing(parentStyle);
+    Length marginRight = child->style()->marginEndUsing(parentStyle);
+    LayoutUnit margin = 0;
+    if (marginLeft.isFixed())
+        margin += marginLeft.value();
+    if (marginRight.isFixed())
+        margin += marginRight.value();
+    return margin;
+}
+
+void RenderFlexibleBox::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const
+{
+    for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
+        if (child->isOutOfFlowPositioned())
+            continue;
+
+        LayoutUnit margin = marginLogicalWidthForChild(child, style());
+        bool hasOrthogonalWritingMode = child->isHorizontalWritingMode() != isHorizontalWritingMode();
+        LayoutUnit minPreferredLogicalWidth = hasOrthogonalWritingMode ? child->logicalHeight() : child->minPreferredLogicalWidth();
+        LayoutUnit maxPreferredLogicalWidth = hasOrthogonalWritingMode ? child->logicalHeight() : child->maxPreferredLogicalWidth();
+        minPreferredLogicalWidth += margin;
+        maxPreferredLogicalWidth += margin;
+        if (!isColumnFlow()) {
+            maxLogicalWidth += maxPreferredLogicalWidth;
+            if (isMultiline()) {
+                // For multiline, the min preferred width is if you put a break between each item.
+                minLogicalWidth = std::max(minLogicalWidth, minPreferredLogicalWidth);
+            } else
+                minLogicalWidth += minPreferredLogicalWidth;
+        } else {
+            minLogicalWidth = std::max(minPreferredLogicalWidth, minLogicalWidth);
+            if (isMultiline()) {
+                // For multiline, the max preferred width is if you never break between items.
+                maxLogicalWidth += maxPreferredLogicalWidth;
+            } else
+                maxLogicalWidth = std::max(maxPreferredLogicalWidth, maxLogicalWidth);
+        }
+    }
+
+    maxLogicalWidth = std::max(minLogicalWidth, maxLogicalWidth);
+
+    LayoutUnit scrollbarWidth = instrinsicScrollbarLogicalWidth();
+    maxLogicalWidth += scrollbarWidth;
+    minLogicalWidth += scrollbarWidth;
+}
+
+void RenderFlexibleBox::computePreferredLogicalWidths()
+{
+    ASSERT(preferredLogicalWidthsDirty());
+
+    m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = 0;
+
+    RenderStyle* styleToUse = style();
+    // FIXME: This should probably be checking for isSpecified since you should be able to use percentage, calc or viewport relative values for width.
+    if (styleToUse->logicalWidth().isFixed() && styleToUse->logicalWidth().value() > 0)
+        m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = adjustContentBoxLogicalWidthForBoxSizing(styleToUse->logicalWidth().value());
+    else
+        computeIntrinsicLogicalWidths(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);
+
+    // FIXME: This should probably be checking for isSpecified since you should be able to use percentage, calc or viewport relative values for min-width.
+    if (styleToUse->logicalMinWidth().isFixed() && styleToUse->logicalMinWidth().value() > 0) {
+        m_maxPreferredLogicalWidth = std::max(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->logicalMinWidth().value()));
+        m_minPreferredLogicalWidth = std::max(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->logicalMinWidth().value()));
+    }
+
+    // FIXME: This should probably be checking for isSpecified since you should be able to use percentage, calc or viewport relative values for maxWidth.
+    if (styleToUse->logicalMaxWidth().isFixed()) {
+        m_maxPreferredLogicalWidth = std::min(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->logicalMaxWidth().value()));
+        m_minPreferredLogicalWidth = std::min(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->logicalMaxWidth().value()));
+    }
+
+    LayoutUnit borderAndPadding = borderAndPaddingLogicalWidth();
+    m_minPreferredLogicalWidth += borderAndPadding;
+    m_maxPreferredLogicalWidth += borderAndPadding;
+
+    setPreferredLogicalWidthsDirty(false);
+}
+
+static int synthesizedBaselineFromContentBox(const RenderBox* box, LineDirectionMode direction)
+{
+    return direction == HorizontalLine ? box->borderTop() + box->paddingTop() + box->contentHeight() : box->borderRight() + box->paddingRight() + box->contentWidth();
+}
+
+int RenderFlexibleBox::baselinePosition(FontBaseline, bool, LineDirectionMode direction, LinePositionMode mode) const
+{
+    ASSERT(mode == PositionOnContainingLine);
+    int baseline = firstLineBoxBaseline();
+    if (baseline == -1)
+        baseline = synthesizedBaselineFromContentBox(this, direction);
+
+    int marginAscent = direction == HorizontalLine ? marginTop() : marginRight();
+    return baseline + marginAscent;
+}
+
+int RenderFlexibleBox::firstLineBoxBaseline() const
+{
+    if (isWritingModeRoot() || m_numberOfInFlowChildrenOnFirstLine <= 0)
+        return -1;
+    RenderBox* baselineChild = 0;
+    int childNumber = 0;
+    for (RenderBox* child = m_orderIterator.first(); child; child = m_orderIterator.next()) {
+        if (child->isOutOfFlowPositioned())
+            continue;
+        if (alignmentForChild(child) == AlignBaseline && !hasAutoMarginsInCrossAxis(child)) {
+            baselineChild = child;
+            break;
+        }
+        if (!baselineChild)
+            baselineChild = child;
+
+        ++childNumber;
+        if (childNumber == m_numberOfInFlowChildrenOnFirstLine)
+            break;
+    }
+
+    if (!baselineChild)
+        return -1;
+
+    if (!isColumnFlow() && hasOrthogonalFlow(baselineChild))
+        return crossAxisExtentForChild(baselineChild) + baselineChild->logicalTop();
+    if (isColumnFlow() && !hasOrthogonalFlow(baselineChild))
+        return mainAxisExtentForChild(baselineChild) + baselineChild->logicalTop();
+
+    int baseline = baselineChild->firstLineBoxBaseline();
+    if (baseline == -1) {
+        // FIXME: We should pass |direction| into firstLineBoxBaseline and stop bailing out if we're a writing mode root.
+        // This would also fix some cases where the flexbox is orthogonal to its container.
+        LineDirectionMode direction = isHorizontalWritingMode() ? HorizontalLine : VerticalLine;
+        return synthesizedBaselineFromContentBox(baselineChild, direction) + baselineChild->logicalTop();
+    }
+
+    return baseline + baselineChild->logicalTop();
+}
+
+int RenderFlexibleBox::inlineBlockBaseline(LineDirectionMode direction) const
+{
+    int baseline = firstLineBoxBaseline();
+    if (baseline != -1)
+        return baseline;
+
+    int marginAscent = direction == HorizontalLine ? marginTop() : marginRight();
+    return synthesizedBaselineFromContentBox(this, direction) + marginAscent;
+}
+
+static EAlignItems resolveAlignment(const RenderStyle* parentStyle, const RenderStyle* childStyle)
+{
+    EAlignItems align = childStyle->alignSelf();
+    if (align == AlignAuto)
+        align = parentStyle->alignItems();
+    return align;
+}
+
+void RenderFlexibleBox::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
+{
+    RenderBlock::styleDidChange(diff, oldStyle);
+
+    if (oldStyle && oldStyle->alignItems() == AlignStretch && diff == StyleDifferenceLayout) {
+        // Flex items that were previously stretching need to be relayed out so we can compute new available cross axis space.
+        // This is only necessary for stretching since other alignment values don't change the size of the box.
+        for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
+            EAlignItems previousAlignment = resolveAlignment(oldStyle, child->style());
+            if (previousAlignment == AlignStretch && previousAlignment != resolveAlignment(style(), child->style()))
+                child->setChildNeedsLayout(true, MarkOnlyThis);
+        }
+    }
+}
+
+void RenderFlexibleBox::layoutBlock(bool relayoutChildren, LayoutUnit)
+{
+    ASSERT(needsLayout());
+
+    if (!relayoutChildren && simplifiedLayout())
+        return;
+
+    LayoutRepainter repainter(*this, checkForRepaintDuringLayout());
+
+    if (updateLogicalWidthAndColumnWidth())
+        relayoutChildren = true;
+
+    LayoutUnit previousHeight = logicalHeight();
+    setLogicalHeight(borderAndPaddingLogicalHeight() + scrollbarLogicalHeight());
+
+    LayoutStateMaintainer statePusher(view(), this, locationOffset(), hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode());
+
+    // Regions changing widths can force us to relayout our children.
+    RenderFlowThread* flowThread = flowThreadContainingBlock();
+    if (logicalWidthChangedInRegions(flowThread))
+        relayoutChildren = true;
+    if (updateRegionsAndExclusionsLogicalSize(flowThread))
+        relayoutChildren = true;
+
+    m_numberOfInFlowChildrenOnFirstLine = -1;
+
+    RenderBlock::startDelayUpdateScrollInfo();
+
+    Vector<LineContext> lineContexts;
+    OrderHashSet orderValues;
+    computeMainAxisPreferredSizes(orderValues);
+    m_orderIterator.setOrderValues(orderValues);
+
+    ChildFrameRects oldChildRects;
+    appendChildFrameRects(oldChildRects);
+    layoutFlexItems(relayoutChildren, lineContexts);
+
+    updateLogicalHeight();
+    repositionLogicalHeightDependentFlexItems(lineContexts);
+
+    RenderBlock::finishDelayUpdateScrollInfo();
+
+    if (logicalHeight() != previousHeight)
+        relayoutChildren = true;
+
+    layoutPositionedObjects(relayoutChildren || isRoot());
+
+    computeRegionRangeForBlock(flowThread);
+
+    repaintChildrenDuringLayoutIfMoved(oldChildRects);
+    // FIXME: css3/flexbox/repaint-rtl-column.html seems to repaint more overflow than it needs to.
+    computeOverflow(clientLogicalBottomAfterRepositioning());
+    statePusher.pop();
+
+    updateLayerTransform();
+
+    // Update our scroll information if we're overflow:auto/scroll/hidden now that we know if
+    // we overflow or not.
+    updateScrollInfoAfterLayout();
+
+    repainter.repaintAfterLayout();
+
+    setNeedsLayout(false);
+}
+
+void RenderFlexibleBox::appendChildFrameRects(ChildFrameRects& childFrameRects)
+{
+    for (RenderBox* child = m_orderIterator.first(); child; child = m_orderIterator.next()) {
+        if (!child->isOutOfFlowPositioned())
+            childFrameRects.append(child->frameRect());
+    }
+}
+
+void RenderFlexibleBox::repaintChildrenDuringLayoutIfMoved(const ChildFrameRects& oldChildRects)
+{
+    size_t childIndex = 0;
+    for (RenderBox* child = m_orderIterator.first(); child; child = m_orderIterator.next()) {
+        if (child->isOutOfFlowPositioned())
+            continue;
+
+        // 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(oldChildRects[childIndex]);
+        ++childIndex;
+    }
+    ASSERT(childIndex == oldChildRects.size());
+}
+
+void RenderFlexibleBox::paintChildren(PaintInfo& paintInfo, const LayoutPoint& paintOffset, PaintInfo& paintInfoForChild, bool usePrintRect)
+{
+    for (RenderBox* child = m_orderIterator.first(); child; child = m_orderIterator.next()) {
+        if (!paintChild(child, paintInfo, paintOffset, paintInfoForChild, usePrintRect))
+            return;
+    }
+}
+
+void RenderFlexibleBox::repositionLogicalHeightDependentFlexItems(Vector<LineContext>& lineContexts)
+{
+    LayoutUnit crossAxisStartEdge = lineContexts.isEmpty() ? LayoutUnit() : lineContexts[0].crossAxisOffset;
+    alignFlexLines(lineContexts);
+
+    // If we have a single line flexbox, the line height is all the available space.
+    // For flex-direction: row, this means we need to use the height, so we do this after calling updateLogicalHeight.
+    if (!isMultiline() && lineContexts.size() == 1)
+        lineContexts[0].crossAxisExtent = crossAxisContentExtent();
+    alignChildren(lineContexts);
+
+    if (style()->flexWrap() == FlexWrapReverse)
+        flipForWrapReverse(lineContexts, crossAxisStartEdge);
+
+    // direction:rtl + flex-direction:column means the cross-axis direction is flipped.
+    flipForRightToLeftColumn();
+}
+
+LayoutUnit RenderFlexibleBox::clientLogicalBottomAfterRepositioning()
+{
+    LayoutUnit maxChildLogicalBottom = 0;
+    for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
+        if (child->isOutOfFlowPositioned())
+            continue;
+        LayoutUnit childLogicalBottom = logicalTopForChild(child) + logicalHeightForChild(child) + marginAfterForChild(child);
+        maxChildLogicalBottom = std::max(maxChildLogicalBottom, childLogicalBottom);
+    }
+    return std::max(clientLogicalBottom(), maxChildLogicalBottom);
+}
+
+bool RenderFlexibleBox::hasOrthogonalFlow(RenderBox* child) const
+{
+    // FIXME: If the child is a flexbox, then we need to check isHorizontalFlow.
+    return isHorizontalFlow() != child->isHorizontalWritingMode();
+}
+
+bool RenderFlexibleBox::isColumnFlow() const
+{
+    return style()->isColumnFlexDirection();
+}
+
+bool RenderFlexibleBox::isHorizontalFlow() const
+{
+    if (isHorizontalWritingMode())
+        return !isColumnFlow();
+    return isColumnFlow();
+}
+
+bool RenderFlexibleBox::isLeftToRightFlow() const
+{
+    if (isColumnFlow())
+        return style()->writingMode() == TopToBottomWritingMode || style()->writingMode() == LeftToRightWritingMode;
+    return style()->isLeftToRightDirection() ^ (style()->flexDirection() == FlowRowReverse);
+}
+
+bool RenderFlexibleBox::isMultiline() const
+{
+    return style()->flexWrap() != FlexNoWrap;
+}
+
+Length RenderFlexibleBox::flexBasisForChild(RenderBox* child) const
+{
+    Length flexLength = child->style()->flexBasis();
+    if (flexLength.isAuto())
+        flexLength = isHorizontalFlow() ? child->style()->width() : child->style()->height();
+    return flexLength;
+}
+
+void RenderFlexibleBox::setCrossAxisExtent(LayoutUnit extent)
+{
+    if (isHorizontalFlow())
+        setHeight(extent);
+    else
+        setWidth(extent);
+}
+
+LayoutUnit RenderFlexibleBox::crossAxisExtentForChild(RenderBox* child) const
+{
+    return isHorizontalFlow() ? child->height() : child->width();
+}
+
+LayoutUnit RenderFlexibleBox::mainAxisExtentForChild(RenderBox* child) const
+{
+    return isHorizontalFlow() ? child->width() : child->height();
+}
+
+LayoutUnit RenderFlexibleBox::crossAxisExtent() const
+{
+    return isHorizontalFlow() ? height() : width();
+}
+
+LayoutUnit RenderFlexibleBox::mainAxisExtent() const
+{
+    return isHorizontalFlow() ? width() : height();
+}
+
+LayoutUnit RenderFlexibleBox::crossAxisContentExtent() const
+{
+    return isHorizontalFlow() ? contentHeight() : contentWidth();
+}
+
+LayoutUnit RenderFlexibleBox::mainAxisContentExtent(LayoutUnit contentLogicalHeight)
+{
+    if (isColumnFlow()) {
+        LogicalExtentComputedValues computedValues;
+        LayoutUnit borderPaddingAndScrollbar = borderAndPaddingLogicalHeight() + scrollbarLogicalHeight();
+        // FIXME: Remove this std:max once we enable saturated layout arithmetic. It's just here to handle overflow.
+        LayoutUnit borderBoxLogicalHeight = std::max(contentLogicalHeight, contentLogicalHeight + borderPaddingAndScrollbar);
+        computeLogicalHeight(borderBoxLogicalHeight, logicalTop(), computedValues);
+        return std::max(LayoutUnit(0), computedValues.m_extent - borderPaddingAndScrollbar);
+    }
+    return contentLogicalWidth();
+}
+
+LayoutUnit RenderFlexibleBox::computeMainAxisExtentForChild(RenderBox* child, SizeType sizeType, const Length& size)
+{
+    // FIXME: This is wrong for orthogonal flows. It should use the flexbox's writing-mode, not the child's in order
+    // to figure out the logical height/width.
+    if (isColumnFlow()) {
+        if (child->style()->logicalHeight().isIntrinsic() || child->style()->logicalMinHeight().isIntrinsic() ||
+            child->style()->logicalMaxHeight().isIntrinsic()) {
+            if (child->needsLayout())
+                child->layout();
+        }
+        return child->computeContentLogicalHeight(size, child->logicalHeight() - child->borderAndPaddingLogicalHeight());
+    }
+    // FIXME: Figure out how this should work for regions and pass in the appropriate values.
+    LayoutUnit offsetFromLogicalTopOfFirstPage = 0;
+    RenderRegion* region = 0;
+    return child->computeLogicalWidthInRegionUsing(sizeType, size, contentLogicalWidth(), this, region, offsetFromLogicalTopOfFirstPage) - child->borderAndPaddingLogicalWidth();
+}
+
+WritingMode RenderFlexibleBox::transformedWritingMode() const
+{
+    WritingMode mode = style()->writingMode();
+    if (!isColumnFlow())
+        return mode;
+
+    switch (mode) {
+    case TopToBottomWritingMode:
+    case BottomToTopWritingMode:
+        return style()->isLeftToRightDirection() ? LeftToRightWritingMode : RightToLeftWritingMode;
+    case LeftToRightWritingMode:
+    case RightToLeftWritingMode:
+        return style()->isLeftToRightDirection() ? TopToBottomWritingMode : BottomToTopWritingMode;
+    }
+    ASSERT_NOT_REACHED();
+    return TopToBottomWritingMode;
+}
+
+LayoutUnit RenderFlexibleBox::flowAwareBorderStart() const
+{
+    if (isHorizontalFlow())
+        return isLeftToRightFlow() ? borderLeft() : borderRight();
+    return isLeftToRightFlow() ? borderTop() : borderBottom();
+}
+
+LayoutUnit RenderFlexibleBox::flowAwareBorderEnd() const
+{
+    if (isHorizontalFlow())
+        return isLeftToRightFlow() ? borderRight() : borderLeft();
+    return isLeftToRightFlow() ? borderBottom() : borderTop();
+}
+
+LayoutUnit RenderFlexibleBox::flowAwareBorderBefore() const
+{
+    switch (transformedWritingMode()) {
+    case TopToBottomWritingMode:
+        return borderTop();
+    case BottomToTopWritingMode:
+        return borderBottom();
+    case LeftToRightWritingMode:
+        return borderLeft();
+    case RightToLeftWritingMode:
+        return borderRight();
+    }
+    ASSERT_NOT_REACHED();
+    return borderTop();
+}
+
+LayoutUnit RenderFlexibleBox::flowAwareBorderAfter() const
+{
+    switch (transformedWritingMode()) {
+    case TopToBottomWritingMode:
+        return borderBottom();
+    case BottomToTopWritingMode:
+        return borderTop();
+    case LeftToRightWritingMode:
+        return borderRight();
+    case RightToLeftWritingMode:
+        return borderLeft();
+    }
+    ASSERT_NOT_REACHED();
+    return borderTop();
+}
+
+LayoutUnit RenderFlexibleBox::flowAwarePaddingStart() const
+{
+    if (isHorizontalFlow())
+        return isLeftToRightFlow() ? paddingLeft() : paddingRight();
+    return isLeftToRightFlow() ? paddingTop() : paddingBottom();
+}
+
+LayoutUnit RenderFlexibleBox::flowAwarePaddingEnd() const
+{
+    if (isHorizontalFlow())
+        return isLeftToRightFlow() ? paddingRight() : paddingLeft();
+    return isLeftToRightFlow() ? paddingBottom() : paddingTop();
+}
+
+LayoutUnit RenderFlexibleBox::flowAwarePaddingBefore() const
+{
+    switch (transformedWritingMode()) {
+    case TopToBottomWritingMode:
+        return paddingTop();
+    case BottomToTopWritingMode:
+        return paddingBottom();
+    case LeftToRightWritingMode:
+        return paddingLeft();
+    case RightToLeftWritingMode:
+        return paddingRight();
+    }
+    ASSERT_NOT_REACHED();
+    return paddingTop();
+}
+
+LayoutUnit RenderFlexibleBox::flowAwarePaddingAfter() const
+{
+    switch (transformedWritingMode()) {
+    case TopToBottomWritingMode:
+        return paddingBottom();
+    case BottomToTopWritingMode:
+        return paddingTop();
+    case LeftToRightWritingMode:
+        return paddingRight();
+    case RightToLeftWritingMode:
+        return paddingLeft();
+    }
+    ASSERT_NOT_REACHED();
+    return paddingTop();
+}
+
+LayoutUnit RenderFlexibleBox::flowAwareMarginStartForChild(RenderBox* child) const
+{
+    if (isHorizontalFlow())
+        return isLeftToRightFlow() ? child->marginLeft() : child->marginRight();
+    return isLeftToRightFlow() ? child->marginTop() : child->marginBottom();
+}
+
+LayoutUnit RenderFlexibleBox::flowAwareMarginEndForChild(RenderBox* child) const
+{
+    if (isHorizontalFlow())
+        return isLeftToRightFlow() ? child->marginRight() : child->marginLeft();
+    return isLeftToRightFlow() ? child->marginBottom() : child->marginTop();
+}
+
+LayoutUnit RenderFlexibleBox::flowAwareMarginBeforeForChild(RenderBox* child) const
+{
+    switch (transformedWritingMode()) {
+    case TopToBottomWritingMode:
+        return child->marginTop();
+    case BottomToTopWritingMode:
+        return child->marginBottom();
+    case LeftToRightWritingMode:
+        return child->marginLeft();
+    case RightToLeftWritingMode:
+        return child->marginRight();
+    }
+    ASSERT_NOT_REACHED();
+    return marginTop();
+}
+
+LayoutUnit RenderFlexibleBox::flowAwareMarginAfterForChild(RenderBox* child) const
+{
+    switch (transformedWritingMode()) {
+    case TopToBottomWritingMode:
+        return child->marginBottom();
+    case BottomToTopWritingMode:
+        return child->marginTop();
+    case LeftToRightWritingMode:
+        return child->marginRight();
+    case RightToLeftWritingMode:
+        return child->marginLeft();
+    }
+    ASSERT_NOT_REACHED();
+    return marginBottom();
+}
+
+LayoutUnit RenderFlexibleBox::crossAxisMarginExtentForChild(RenderBox* child) const
+{
+    return isHorizontalFlow() ? child->marginHeight() : child->marginWidth();
+}
+
+LayoutUnit RenderFlexibleBox::crossAxisScrollbarExtent() const
+{
+    return isHorizontalFlow() ? horizontalScrollbarHeight() : verticalScrollbarWidth();
+}
+
+LayoutPoint RenderFlexibleBox::flowAwareLocationForChild(RenderBox* child) const
+{
+    return isHorizontalFlow() ? child->location() : child->location().transposedPoint();
+}
+
+void RenderFlexibleBox::setFlowAwareLocationForChild(RenderBox* child, const LayoutPoint& location)
+{
+    if (isHorizontalFlow())
+        child->setLocation(location);
+    else
+        child->setLocation(location.transposedPoint());
+}
+
+LayoutUnit RenderFlexibleBox::mainAxisBorderAndPaddingExtentForChild(RenderBox* child) const
+{
+    return isHorizontalFlow() ? child->borderAndPaddingWidth() : child->borderAndPaddingHeight();
+}
+
+LayoutUnit RenderFlexibleBox::mainAxisScrollbarExtentForChild(RenderBox* child) const
+{
+    return isHorizontalFlow() ? child->verticalScrollbarWidth() : child->horizontalScrollbarHeight();
+}
+
+LayoutUnit RenderFlexibleBox::preferredMainAxisContentExtentForChild(RenderBox* child)
+{
+    Length flexBasis = flexBasisForChild(child);
+    if (flexBasis.isAuto()) {
+        LayoutUnit mainAxisExtent = hasOrthogonalFlow(child) ? child->logicalHeight() : child->maxPreferredLogicalWidth();
+        ASSERT(mainAxisExtent - mainAxisBorderAndPaddingExtentForChild(child) >= 0);
+        return mainAxisExtent - mainAxisBorderAndPaddingExtentForChild(child);
+    }
+    return std::max(LayoutUnit(0), computeMainAxisExtentForChild(child, MainOrPreferredSize, flexBasis));
+}
+
+void RenderFlexibleBox::layoutFlexItems(bool relayoutChildren, Vector<LineContext>& lineContexts)
+{
+    OrderedFlexItemList orderedChildren;
+    LayoutUnit preferredMainAxisExtent;
+    double totalFlexGrow;
+    double totalWeightedFlexShrink;
+    LayoutUnit minMaxAppliedMainAxisExtent;
+
+    m_orderIterator.first();
+    LayoutUnit crossAxisOffset = flowAwareBorderBefore() + flowAwarePaddingBefore();
+    while (computeNextFlexLine(orderedChildren, preferredMainAxisExtent, totalFlexGrow, totalWeightedFlexShrink, minMaxAppliedMainAxisExtent)) {
+        LayoutUnit availableFreeSpace = mainAxisContentExtent(preferredMainAxisExtent) - preferredMainAxisExtent;
+        FlexSign flexSign = (minMaxAppliedMainAxisExtent < preferredMainAxisExtent + availableFreeSpace) ? PositiveFlexibility : NegativeFlexibility;
+        InflexibleFlexItemSize inflexibleItems;
+        Vector<LayoutUnit> childSizes;
+        while (!resolveFlexibleLengths(flexSign, orderedChildren, availableFreeSpace, totalFlexGrow, totalWeightedFlexShrink, inflexibleItems, childSizes)) {
+            ASSERT(totalFlexGrow >= 0 && totalWeightedFlexShrink >= 0);
+            ASSERT(inflexibleItems.size() > 0);
+        }
+
+        layoutAndPlaceChildren(crossAxisOffset, orderedChildren, childSizes, availableFreeSpace, relayoutChildren, lineContexts);
+    }
+    if (hasLineIfEmpty()) {
+        // Even if computeNextFlexLine returns true, the flexbox might not have
+        // a line because all our children might be out of flow positioned.
+        // Instead of just checking if we have a line, make sure the flexbox
+        // has at least a line's worth of height to cover this case.
+        LayoutUnit minHeight = borderAndPaddingLogicalHeight()
+            + lineHeight(true, isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes)
+            + scrollbarLogicalHeight();
+        if (height() < minHeight)
+            setLogicalHeight(minHeight);
+    }
+}
+
+LayoutUnit RenderFlexibleBox::autoMarginOffsetInMainAxis(const OrderedFlexItemList& children, LayoutUnit& availableFreeSpace)
+{
+    if (availableFreeSpace <= 0)
+        return 0;
+
+    int numberOfAutoMargins = 0;
+    bool isHorizontal = isHorizontalFlow();
+    for (size_t i = 0; i < children.size(); ++i) {
+        RenderBox* child = children[i];
+        if (child->isOutOfFlowPositioned())
+            continue;
+        if (isHorizontal) {
+            if (child->style()->marginLeft().isAuto())
+                ++numberOfAutoMargins;
+            if (child->style()->marginRight().isAuto())
+                ++numberOfAutoMargins;
+        } else {
+            if (child->style()->marginTop().isAuto())
+                ++numberOfAutoMargins;
+            if (child->style()->marginBottom().isAuto())
+                ++numberOfAutoMargins;
+        }
+    }
+    if (!numberOfAutoMargins)
+        return 0;
+
+    LayoutUnit sizeOfAutoMargin = availableFreeSpace / numberOfAutoMargins;
+    availableFreeSpace = 0;
+    return sizeOfAutoMargin;
+}
+
+void RenderFlexibleBox::updateAutoMarginsInMainAxis(RenderBox* child, LayoutUnit autoMarginOffset)
+{
+    ASSERT(autoMarginOffset >= 0);
+
+    if (isHorizontalFlow()) {
+        if (child->style()->marginLeft().isAuto())
+            child->setMarginLeft(autoMarginOffset);
+        if (child->style()->marginRight().isAuto())
+            child->setMarginRight(autoMarginOffset);
+    } else {
+        if (child->style()->marginTop().isAuto())
+            child->setMarginTop(autoMarginOffset);
+        if (child->style()->marginBottom().isAuto())
+            child->setMarginBottom(autoMarginOffset);
+    }
+}
+
+bool RenderFlexibleBox::hasAutoMarginsInCrossAxis(RenderBox* child) const
+{
+    if (isHorizontalFlow())
+        return child->style()->marginTop().isAuto() || child->style()->marginBottom().isAuto();
+    return child->style()->marginLeft().isAuto() || child->style()->marginRight().isAuto();
+}
+
+LayoutUnit RenderFlexibleBox::availableAlignmentSpaceForChild(LayoutUnit lineCrossAxisExtent, RenderBox* child)
+{
+    ASSERT(!child->isOutOfFlowPositioned());
+    LayoutUnit childCrossExtent = crossAxisMarginExtentForChild(child) + crossAxisExtentForChild(child);
+    return lineCrossAxisExtent - childCrossExtent;
+}
+
+bool RenderFlexibleBox::updateAutoMarginsInCrossAxis(RenderBox* child, LayoutUnit availableAlignmentSpace)
+{
+    ASSERT(!child->isOutOfFlowPositioned());
+    ASSERT(availableAlignmentSpace >= 0);
+
+    bool isHorizontal = isHorizontalFlow();
+    Length start = isHorizontal ? child->style()->marginTop() : child->style()->marginLeft();
+    Length end = isHorizontal ? child->style()->marginBottom() : child->style()->marginRight();
+    if (start.isAuto() && end.isAuto()) {
+        adjustAlignmentForChild(child, availableAlignmentSpace / 2);
+        if (isHorizontal) {
+            child->setMarginTop(availableAlignmentSpace / 2);
+            child->setMarginBottom(availableAlignmentSpace / 2);
+        } else {
+            child->setMarginLeft(availableAlignmentSpace / 2);
+            child->setMarginRight(availableAlignmentSpace / 2);
+        }
+        return true;
+    }
+    if (start.isAuto()) {
+        adjustAlignmentForChild(child, availableAlignmentSpace);
+        if (isHorizontal)
+            child->setMarginTop(availableAlignmentSpace);
+        else
+            child->setMarginLeft(availableAlignmentSpace);
+        return true;
+    }
+    if (end.isAuto()) {
+        if (isHorizontal)
+            child->setMarginBottom(availableAlignmentSpace);
+        else
+            child->setMarginRight(availableAlignmentSpace);
+        return true;
+    }
+    return false;
+}
+
+LayoutUnit RenderFlexibleBox::marginBoxAscentForChild(RenderBox* child)
+{
+    LayoutUnit ascent = child->firstLineBoxBaseline();
+    if (ascent == -1)
+        ascent = crossAxisExtentForChild(child);
+    return ascent + flowAwareMarginBeforeForChild(child);
+}
+
+LayoutUnit RenderFlexibleBox::computeChildMarginValue(Length margin, RenderView* view)
+{
+    // When resolving the margins, we use the content size for resolving percent and calc (for percents in calc expressions) margins.
+    // Fortunately, percent margins are always computed with respect to the block's width, even for margin-top and margin-bottom.
+    LayoutUnit availableSize = contentLogicalWidth();
+    return minimumValueForLength(margin, availableSize, view);
+}
+
+void RenderFlexibleBox::computeMainAxisPreferredSizes(OrderHashSet& orderValues)
+{
+    RenderView* renderView = view();
+    for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
+        orderValues.add(child->style()->order());
+
+        if (child->isOutOfFlowPositioned())
+            continue;
+
+        child->clearOverrideSize();
+
+        // Only need to layout here if we will need to get the logicalHeight of the child in computeNextFlexLine.
+        if (hasOrthogonalFlow(child) && flexBasisForChild(child).isAuto()) {
+            child->setChildNeedsLayout(true, MarkOnlyThis);
+            child->layout();
+        }
+
+        // Before running the flex algorithm, 'auto' has a margin of 0.
+        // Also, if we're not auto sizing, we don't do a layout that computes the start/end margins.
+        if (isHorizontalFlow()) {
+            child->setMarginLeft(computeChildMarginValue(child->style()->marginLeft(), renderView));
+            child->setMarginRight(computeChildMarginValue(child->style()->marginRight(), renderView));
+        } else {
+            child->setMarginTop(computeChildMarginValue(child->style()->marginTop(), renderView));
+            child->setMarginBottom(computeChildMarginValue(child->style()->marginBottom(), renderView));
+        }
+    }
+}
+
+LayoutUnit RenderFlexibleBox::adjustChildSizeForMinAndMax(RenderBox* child, LayoutUnit childSize)
+{
+    Length max = isHorizontalFlow() ? child->style()->maxWidth() : child->style()->maxHeight();
+    if (max.isSpecifiedOrIntrinsic()) {
+        LayoutUnit maxExtent = computeMainAxisExtentForChild(child, MaxSize, max);
+        if (maxExtent != -1 && childSize > maxExtent)
+            childSize = maxExtent;
+    }
+
+    Length min = isHorizontalFlow() ? child->style()->minWidth() : child->style()->minHeight();
+    LayoutUnit minExtent = 0;
+    if (min.isSpecifiedOrIntrinsic())
+        minExtent = computeMainAxisExtentForChild(child, MinSize, min);
+    return std::max(childSize, minExtent);
+}
+
+bool RenderFlexibleBox::computeNextFlexLine(OrderedFlexItemList& orderedChildren, LayoutUnit& preferredMainAxisExtent, double& totalFlexGrow, double& totalWeightedFlexShrink, LayoutUnit& minMaxAppliedMainAxisExtent)
+{
+    orderedChildren.clear();
+    preferredMainAxisExtent = 0;
+    totalFlexGrow = totalWeightedFlexShrink = 0;
+    minMaxAppliedMainAxisExtent = 0;
+
+    if (!m_orderIterator.currentChild())
+        return false;
+
+    LayoutUnit lineBreakLength = mainAxisContentExtent(LayoutUnit::max());
+    bool lineHasInFlowItem = false;
+
+    for (RenderBox* child = m_orderIterator.currentChild(); child; child = m_orderIterator.next()) {
+        if (child->isOutOfFlowPositioned()) {
+            orderedChildren.append(child);
+            continue;
+        }
+
+        LayoutUnit childMainAxisExtent = preferredMainAxisContentExtentForChild(child);
+        LayoutUnit childMainAxisMarginBoxExtent = mainAxisBorderAndPaddingExtentForChild(child) + childMainAxisExtent;
+        childMainAxisMarginBoxExtent += isHorizontalFlow() ? child->marginWidth() : child->marginHeight();
+
+        if (isMultiline() && preferredMainAxisExtent + childMainAxisMarginBoxExtent > lineBreakLength && lineHasInFlowItem)
+            break;
+        orderedChildren.append(child);
+        lineHasInFlowItem  = true;
+        preferredMainAxisExtent += childMainAxisMarginBoxExtent;
+        totalFlexGrow += child->style()->flexGrow();
+        totalWeightedFlexShrink += child->style()->flexShrink() * childMainAxisExtent;
+
+        LayoutUnit childMinMaxAppliedMainAxisExtent = adjustChildSizeForMinAndMax(child, childMainAxisExtent);
+        minMaxAppliedMainAxisExtent += childMinMaxAppliedMainAxisExtent - childMainAxisExtent + childMainAxisMarginBoxExtent;
+    }
+    return true;
+}
+
+void RenderFlexibleBox::freezeViolations(const Vector<Violation>& violations, LayoutUnit& availableFreeSpace, double& totalFlexGrow, double& totalWeightedFlexShrink, InflexibleFlexItemSize& inflexibleItems)
+{
+    for (size_t i = 0; i < violations.size(); ++i) {
+        RenderBox* child = violations[i].child;
+        LayoutUnit childSize = violations[i].childSize;
+        LayoutUnit preferredChildSize = preferredMainAxisContentExtentForChild(child);
+        availableFreeSpace -= childSize - preferredChildSize;
+        totalFlexGrow -= child->style()->flexGrow();
+        totalWeightedFlexShrink -= child->style()->flexShrink() * preferredChildSize;
+        inflexibleItems.set(child, childSize);
+    }
+}
+
+// Returns true if we successfully ran the algorithm and sized the flex items.
+bool RenderFlexibleBox::resolveFlexibleLengths(FlexSign flexSign, const OrderedFlexItemList& children, LayoutUnit& availableFreeSpace, double& totalFlexGrow, double& totalWeightedFlexShrink, InflexibleFlexItemSize& inflexibleItems, Vector<LayoutUnit>& childSizes)
+{
+    childSizes.clear();
+    LayoutUnit totalViolation = 0;
+    LayoutUnit usedFreeSpace = 0;
+    Vector<Violation> minViolations;
+    Vector<Violation> maxViolations;
+    for (size_t i = 0; i < children.size(); ++i) {
+        RenderBox* child = children[i];
+        if (child->isOutOfFlowPositioned()) {
+            childSizes.append(0);
+            continue;
+        }
+
+        if (inflexibleItems.contains(child))
+            childSizes.append(inflexibleItems.get(child));
+        else {
+            LayoutUnit preferredChildSize = preferredMainAxisContentExtentForChild(child);
+            LayoutUnit childSize = preferredChildSize;
+            double extraSpace = 0;
+            if (availableFreeSpace > 0 && totalFlexGrow > 0 && flexSign == PositiveFlexibility && std::isfinite(totalFlexGrow))
+                extraSpace = availableFreeSpace * child->style()->flexGrow() / totalFlexGrow;
+            else if (availableFreeSpace < 0 && totalWeightedFlexShrink > 0 && flexSign == NegativeFlexibility && std::isfinite(totalWeightedFlexShrink))
+                extraSpace = availableFreeSpace * child->style()->flexShrink() * preferredChildSize / totalWeightedFlexShrink;
+            if (std::isfinite(extraSpace))
+                childSize += roundedLayoutUnit(extraSpace);
+
+            LayoutUnit adjustedChildSize = adjustChildSizeForMinAndMax(child, childSize);
+            childSizes.append(adjustedChildSize);
+            usedFreeSpace += adjustedChildSize - preferredChildSize;
+
+            LayoutUnit violation = adjustedChildSize - childSize;
+            if (violation > 0)
+                minViolations.append(Violation(child, adjustedChildSize));
+            else if (violation < 0)
+                maxViolations.append(Violation(child, adjustedChildSize));
+            totalViolation += violation;
+        }
+    }
+
+    if (totalViolation)
+        freezeViolations(totalViolation < 0 ? maxViolations : minViolations, availableFreeSpace, totalFlexGrow, totalWeightedFlexShrink, inflexibleItems);
+    else
+        availableFreeSpace -= usedFreeSpace;
+
+    return !totalViolation;
+}
+
+static LayoutUnit initialJustifyContentOffset(LayoutUnit availableFreeSpace, EJustifyContent justifyContent, unsigned numberOfChildren)
+{
+    if (justifyContent == JustifyFlexEnd)
+        return availableFreeSpace;
+    if (justifyContent == JustifyCenter)
+        return availableFreeSpace / 2;
+    if (justifyContent == JustifySpaceAround) {
+        if (availableFreeSpace > 0 && numberOfChildren)
+            return availableFreeSpace / (2 * numberOfChildren);
+        else
+            return availableFreeSpace / 2;
+    }
+    return 0;
+}
+
+static LayoutUnit justifyContentSpaceBetweenChildren(LayoutUnit availableFreeSpace, EJustifyContent justifyContent, unsigned numberOfChildren)
+{
+    if (availableFreeSpace > 0 && numberOfChildren > 1) {
+        if (justifyContent == JustifySpaceBetween)
+            return availableFreeSpace / (numberOfChildren - 1);
+        if (justifyContent == JustifySpaceAround)
+            return availableFreeSpace / numberOfChildren;
+    }
+    return 0;
+}
+
+void RenderFlexibleBox::setLogicalOverrideSize(RenderBox* child, LayoutUnit childPreferredSize)
+{
+    if (hasOrthogonalFlow(child))
+        child->setOverrideLogicalContentHeight(childPreferredSize - child->borderAndPaddingLogicalHeight());
+    else
+        child->setOverrideLogicalContentWidth(childPreferredSize - child->borderAndPaddingLogicalWidth());
+}
+
+void RenderFlexibleBox::prepareChildForPositionedLayout(RenderBox* child, LayoutUnit mainAxisOffset, LayoutUnit crossAxisOffset, PositionedLayoutMode layoutMode)
+{
+    ASSERT(child->isOutOfFlowPositioned());
+    child->containingBlock()->insertPositionedObject(child);
+    RenderLayer* childLayer = child->layer();
+    LayoutUnit inlinePosition = isColumnFlow() ? crossAxisOffset : mainAxisOffset;
+    if (layoutMode == FlipForRowReverse && style()->flexDirection() == FlowRowReverse)
+        inlinePosition = mainAxisExtent() - mainAxisOffset;
+    childLayer->setStaticInlinePosition(inlinePosition); // FIXME: Not right for regions.
+
+    LayoutUnit staticBlockPosition = isColumnFlow() ? mainAxisOffset : crossAxisOffset;
+    if (childLayer->staticBlockPosition() != staticBlockPosition) {
+        childLayer->setStaticBlockPosition(staticBlockPosition);
+        if (child->style()->hasStaticBlockPosition(style()->isHorizontalWritingMode()))
+            child->setChildNeedsLayout(true, MarkOnlyThis);
+    }
+}
+
+EAlignItems RenderFlexibleBox::alignmentForChild(RenderBox* child) const
+{
+    EAlignItems align = resolveAlignment(style(), child->style());
+
+    if (align == AlignBaseline && hasOrthogonalFlow(child))
+        align = AlignFlexStart;
+
+    if (style()->flexWrap() == FlexWrapReverse) {
+        if (align == AlignFlexStart)
+            align = AlignFlexEnd;
+        else if (align == AlignFlexEnd)
+            align = AlignFlexStart;
+    }
+
+    return align;
+}
+
+size_t RenderFlexibleBox::numberOfInFlowPositionedChildren(const OrderedFlexItemList& children) const
+{
+    size_t count = 0;
+    for (size_t i = 0; i < children.size(); ++i) {
+        RenderBox* child = children[i];
+        if (!child->isOutOfFlowPositioned())
+            ++count;
+    }
+    return count;
+}
+
+bool RenderFlexibleBox::needToStretchChild(RenderBox* child)
+{
+    if (alignmentForChild(child) != AlignStretch)
+        return false;
+
+    Length crossAxisLength = isHorizontalFlow() ? child->style()->height() : child->style()->width();
+    return crossAxisLength.isAuto();
+}
+
+void RenderFlexibleBox::resetAutoMarginsAndLogicalTopInCrossAxis(RenderBox* child)
+{
+    if (hasAutoMarginsInCrossAxis(child))
+        child->updateLogicalHeight();
+}
+
+void RenderFlexibleBox::layoutAndPlaceChildren(LayoutUnit& crossAxisOffset, const OrderedFlexItemList& children, const Vector<LayoutUnit>& childSizes, LayoutUnit availableFreeSpace, bool relayoutChildren, Vector<LineContext>& lineContexts)
+{
+    ASSERT(childSizes.size() == children.size());
+
+    size_t numberOfChildrenForJustifyContent = numberOfInFlowPositionedChildren(children);
+    LayoutUnit autoMarginOffset = autoMarginOffsetInMainAxis(children, availableFreeSpace);
+    LayoutUnit mainAxisOffset = flowAwareBorderStart() + flowAwarePaddingStart();
+    mainAxisOffset += initialJustifyContentOffset(availableFreeSpace, style()->justifyContent(), numberOfChildrenForJustifyContent);
+    if (style()->flexDirection() == FlowRowReverse)
+        mainAxisOffset += isHorizontalFlow() ? verticalScrollbarWidth() : horizontalScrollbarHeight();
+
+    LayoutUnit totalMainExtent = mainAxisExtent();
+    LayoutUnit maxAscent = 0, maxDescent = 0; // Used when align-items: baseline.
+    LayoutUnit maxChildCrossAxisExtent = 0;
+    size_t seenInFlowPositionedChildren = 0;
+    bool shouldFlipMainAxis = !isColumnFlow() && !isLeftToRightFlow();
+    for (size_t i = 0; i < children.size(); ++i) {
+        RenderBox* child = children[i];
+        if (child->isOutOfFlowPositioned()) {
+            prepareChildForPositionedLayout(child, mainAxisOffset, crossAxisOffset, FlipForRowReverse);
+            continue;
+        }
+
+        LayoutUnit childPreferredSize = childSizes[i] + mainAxisBorderAndPaddingExtentForChild(child);
+        setLogicalOverrideSize(child, childPreferredSize);
+        // FIXME: Can avoid laying out here in some cases. See https://webkit.org/b/87905.
+        if (needToStretchChild(child) || childPreferredSize != mainAxisExtentForChild(child))
+            child->setChildNeedsLayout(true, MarkOnlyThis);
+        else {
+            // To avoid double applying margin changes in updateAutoMarginsInCrossAxis, we reset the margins here.
+            resetAutoMarginsAndLogicalTopInCrossAxis(child);
+        }
+        updateBlockChildDirtyBitsBeforeLayout(relayoutChildren, child);
+        child->layoutIfNeeded();
+
+        updateAutoMarginsInMainAxis(child, autoMarginOffset);
+
+        LayoutUnit childCrossAxisMarginBoxExtent;
+        if (alignmentForChild(child) == AlignBaseline && !hasAutoMarginsInCrossAxis(child)) {
+            LayoutUnit ascent = marginBoxAscentForChild(child);
+            LayoutUnit descent = (crossAxisMarginExtentForChild(child) + crossAxisExtentForChild(child)) - ascent;
+
+            maxAscent = std::max(maxAscent, ascent);
+            maxDescent = std::max(maxDescent, descent);
+
+            childCrossAxisMarginBoxExtent = maxAscent + maxDescent;
+        } else
+            childCrossAxisMarginBoxExtent = crossAxisExtentForChild(child) + crossAxisMarginExtentForChild(child);
+        if (!isColumnFlow())
+            setLogicalHeight(std::max(logicalHeight(), crossAxisOffset + flowAwareBorderAfter() + flowAwarePaddingAfter() + childCrossAxisMarginBoxExtent + crossAxisScrollbarExtent()));
+        maxChildCrossAxisExtent = std::max(maxChildCrossAxisExtent, childCrossAxisMarginBoxExtent);
+
+        mainAxisOffset += flowAwareMarginStartForChild(child);
+
+        LayoutUnit childMainExtent = mainAxisExtentForChild(child);
+        LayoutPoint childLocation(shouldFlipMainAxis ? totalMainExtent - mainAxisOffset - childMainExtent : mainAxisOffset,
+            crossAxisOffset + flowAwareMarginBeforeForChild(child));
+
+        // FIXME: Supporting layout deltas.
+        setFlowAwareLocationForChild(child, childLocation);
+        mainAxisOffset += childMainExtent + flowAwareMarginEndForChild(child);
+
+        ++seenInFlowPositionedChildren;
+        if (seenInFlowPositionedChildren < numberOfChildrenForJustifyContent)
+            mainAxisOffset += justifyContentSpaceBetweenChildren(availableFreeSpace, style()->justifyContent(), numberOfChildrenForJustifyContent);
+    }
+
+    if (isColumnFlow())
+        setLogicalHeight(mainAxisOffset + flowAwareBorderEnd() + flowAwarePaddingEnd() + scrollbarLogicalHeight());
+
+    if (style()->flexDirection() == FlowColumnReverse) {
+        // We have to do an extra pass for column-reverse to reposition the flex items since the start depends
+        // on the height of the flexbox, which we only know after we've positioned all the flex items.
+        updateLogicalHeight();
+        layoutColumnReverse(children, crossAxisOffset, availableFreeSpace);
+    }
+
+    if (m_numberOfInFlowChildrenOnFirstLine == -1)
+        m_numberOfInFlowChildrenOnFirstLine = seenInFlowPositionedChildren;
+    lineContexts.append(LineContext(crossAxisOffset, maxChildCrossAxisExtent, children.size(), maxAscent));
+    crossAxisOffset += maxChildCrossAxisExtent;
+}
+
+void RenderFlexibleBox::layoutColumnReverse(const OrderedFlexItemList& children, LayoutUnit crossAxisOffset, LayoutUnit availableFreeSpace)
+{
+    // This is similar to the logic in layoutAndPlaceChildren, except we place the children
+    // starting from the end of the flexbox. We also don't need to layout anything since we're
+    // just moving the children to a new position.
+    size_t numberOfChildrenForJustifyContent = numberOfInFlowPositionedChildren(children);
+    LayoutUnit mainAxisOffset = logicalHeight() - flowAwareBorderEnd() - flowAwarePaddingEnd();
+    mainAxisOffset -= initialJustifyContentOffset(availableFreeSpace, style()->justifyContent(), numberOfChildrenForJustifyContent);
+    mainAxisOffset -= isHorizontalFlow() ? verticalScrollbarWidth() : horizontalScrollbarHeight();
+
+    size_t seenInFlowPositionedChildren = 0;
+    for (size_t i = 0; i < children.size(); ++i) {
+        RenderBox* child = children[i];
+        if (child->isOutOfFlowPositioned()) {
+            child->layer()->setStaticBlockPosition(mainAxisOffset);
+            continue;
+        }
+        mainAxisOffset -= mainAxisExtentForChild(child) + flowAwareMarginEndForChild(child);
+
+        setFlowAwareLocationForChild(child, LayoutPoint(mainAxisOffset, crossAxisOffset + flowAwareMarginBeforeForChild(child)));
+
+        mainAxisOffset -= flowAwareMarginStartForChild(child);
+
+        ++seenInFlowPositionedChildren;
+        if (seenInFlowPositionedChildren < numberOfChildrenForJustifyContent)
+            mainAxisOffset -= justifyContentSpaceBetweenChildren(availableFreeSpace, style()->justifyContent(), numberOfChildrenForJustifyContent);
+    }
+}
+
+static LayoutUnit initialAlignContentOffset(LayoutUnit availableFreeSpace, EAlignContent alignContent, unsigned numberOfLines)
+{
+    if (alignContent == AlignContentFlexEnd)
+        return availableFreeSpace;
+    if (alignContent == AlignContentCenter)
+        return availableFreeSpace / 2;
+    if (alignContent == AlignContentSpaceAround) {
+        if (availableFreeSpace > 0 && numberOfLines)
+            return availableFreeSpace / (2 * numberOfLines);
+        if (availableFreeSpace < 0)
+            return availableFreeSpace / 2;
+    }
+    return 0;
+}
+
+static LayoutUnit alignContentSpaceBetweenChildren(LayoutUnit availableFreeSpace, EAlignContent alignContent, unsigned numberOfLines)
+{
+    if (availableFreeSpace > 0 && numberOfLines > 1) {
+        if (alignContent == AlignContentSpaceBetween)
+            return availableFreeSpace / (numberOfLines - 1);
+        if (alignContent == AlignContentSpaceAround || alignContent == AlignContentStretch)
+            return availableFreeSpace / numberOfLines;
+    }
+    return 0;
+}
+
+void RenderFlexibleBox::alignFlexLines(Vector<LineContext>& lineContexts)
+{
+    if (!isMultiline() || style()->alignContent() == AlignContentFlexStart)
+        return;
+
+    LayoutUnit availableCrossAxisSpace = crossAxisContentExtent();
+    for (size_t i = 0; i < lineContexts.size(); ++i)
+        availableCrossAxisSpace -= lineContexts[i].crossAxisExtent;
+
+    RenderBox* child = m_orderIterator.first();
+    LayoutUnit lineOffset = initialAlignContentOffset(availableCrossAxisSpace, style()->alignContent(), lineContexts.size());
+    for (unsigned lineNumber = 0; lineNumber < lineContexts.size(); ++lineNumber) {
+        lineContexts[lineNumber].crossAxisOffset += lineOffset;
+        for (size_t childNumber = 0; childNumber < lineContexts[lineNumber].numberOfChildren; ++childNumber, child = m_orderIterator.next())
+            adjustAlignmentForChild(child, lineOffset);
+
+        if (style()->alignContent() == AlignContentStretch && availableCrossAxisSpace > 0)
+            lineContexts[lineNumber].crossAxisExtent += availableCrossAxisSpace / static_cast<unsigned>(lineContexts.size());
+
+        lineOffset += alignContentSpaceBetweenChildren(availableCrossAxisSpace, style()->alignContent(), lineContexts.size());
+    }
+}
+
+void RenderFlexibleBox::adjustAlignmentForChild(RenderBox* child, LayoutUnit delta)
+{
+    if (child->isOutOfFlowPositioned()) {
+        LayoutUnit staticInlinePosition = child->layer()->staticInlinePosition();
+        LayoutUnit staticBlockPosition = child->layer()->staticBlockPosition();
+        LayoutUnit mainAxis = isColumnFlow() ? staticBlockPosition : staticInlinePosition;
+        LayoutUnit crossAxis = isColumnFlow() ? staticInlinePosition : staticBlockPosition;
+        crossAxis += delta;
+        prepareChildForPositionedLayout(child, mainAxis, crossAxis, NoFlipForRowReverse);
+        return;
+    }
+
+    setFlowAwareLocationForChild(child, flowAwareLocationForChild(child) + LayoutSize(0, delta));
+}
+
+void RenderFlexibleBox::alignChildren(const Vector<LineContext>& lineContexts)
+{
+    // Keep track of the space between the baseline edge and the after edge of the box for each line.
+    Vector<LayoutUnit> minMarginAfterBaselines;
+
+    RenderBox* child = m_orderIterator.first();
+    for (size_t lineNumber = 0; lineNumber < lineContexts.size(); ++lineNumber) {
+        LayoutUnit minMarginAfterBaseline = LayoutUnit::max();
+        LayoutUnit lineCrossAxisExtent = lineContexts[lineNumber].crossAxisExtent;
+        LayoutUnit maxAscent = lineContexts[lineNumber].maxAscent;
+
+        for (size_t childNumber = 0; childNumber < lineContexts[lineNumber].numberOfChildren; ++childNumber, child = m_orderIterator.next()) {
+            ASSERT(child);
+            if (child->isOutOfFlowPositioned()) {
+                if (style()->flexWrap() == FlexWrapReverse)
+                    adjustAlignmentForChild(child, lineCrossAxisExtent);
+                continue;
+            }
+
+            if (updateAutoMarginsInCrossAxis(child, std::max(LayoutUnit(0), availableAlignmentSpaceForChild(lineCrossAxisExtent, child))))
+                continue;
+
+            switch (alignmentForChild(child)) {
+            case AlignAuto:
+                ASSERT_NOT_REACHED();
+                break;
+            case AlignStretch: {
+                applyStretchAlignmentToChild(child, lineCrossAxisExtent);
+                // Since wrap-reverse flips cross start and cross end, strech children should be aligned with the cross end.
+                if (style()->flexWrap() == FlexWrapReverse)
+                    adjustAlignmentForChild(child, availableAlignmentSpaceForChild(lineCrossAxisExtent, child));
+                break;
+            }
+            case AlignFlexStart:
+                break;
+            case AlignFlexEnd:
+                adjustAlignmentForChild(child, availableAlignmentSpaceForChild(lineCrossAxisExtent, child));
+                break;
+            case AlignCenter:
+                adjustAlignmentForChild(child, availableAlignmentSpaceForChild(lineCrossAxisExtent, child) / 2);
+                break;
+            case AlignBaseline: {
+                // FIXME: If we get here in columns, we want the use the descent, except we currently can't get the ascent/descent of orthogonal children.
+                // https://bugs.webkit.org/show_bug.cgi?id=98076
+                LayoutUnit ascent = marginBoxAscentForChild(child);
+                LayoutUnit startOffset = maxAscent - ascent;
+                adjustAlignmentForChild(child, startOffset);
+
+                if (style()->flexWrap() == FlexWrapReverse)
+                    minMarginAfterBaseline = std::min(minMarginAfterBaseline, availableAlignmentSpaceForChild(lineCrossAxisExtent, child) - startOffset);
+                break;
+            }
+            }
+        }
+        minMarginAfterBaselines.append(minMarginAfterBaseline);
+    }
+
+    if (style()->flexWrap() != FlexWrapReverse)
+        return;
+
+    // wrap-reverse flips the cross axis start and end. For baseline alignment, this means we
+    // need to align the after edge of baseline elements with the after edge of the flex line.
+    child = m_orderIterator.first();
+    for (size_t lineNumber = 0; lineNumber < lineContexts.size(); ++lineNumber) {
+        LayoutUnit minMarginAfterBaseline = minMarginAfterBaselines[lineNumber];
+        for (size_t childNumber = 0; childNumber < lineContexts[lineNumber].numberOfChildren; ++childNumber, child = m_orderIterator.next()) {
+            ASSERT(child);
+            if (alignmentForChild(child) == AlignBaseline && !hasAutoMarginsInCrossAxis(child) && minMarginAfterBaseline)
+                adjustAlignmentForChild(child, minMarginAfterBaseline);
+        }
+    }
+}
+
+void RenderFlexibleBox::applyStretchAlignmentToChild(RenderBox* child, LayoutUnit lineCrossAxisExtent)
+{
+    if (!isColumnFlow() && child->style()->logicalHeight().isAuto()) {
+        // FIXME: If the child has orthogonal flow, then it already has an override height set, so use it.
+        if (!hasOrthogonalFlow(child)) {
+            LayoutUnit stretchedLogicalHeight = child->logicalHeight() + availableAlignmentSpaceForChild(lineCrossAxisExtent, child);
+            ASSERT(!child->needsLayout());
+            LayoutUnit desiredLogicalHeight = child->constrainLogicalHeightByMinMax(stretchedLogicalHeight, child->logicalHeight() - child->borderAndPaddingLogicalHeight());
+
+            // FIXME: Can avoid laying out here in some cases. See https://webkit.org/b/87905.
+            if (desiredLogicalHeight != child->logicalHeight()) {
+                child->setOverrideLogicalContentHeight(desiredLogicalHeight - child->borderAndPaddingLogicalHeight());
+                child->setLogicalHeight(0);
+                child->setChildNeedsLayout(true, MarkOnlyThis);
+                child->layout();
+            }
+        }
+    } else if (isColumnFlow() && child->style()->logicalWidth().isAuto()) {
+        // FIXME: If the child doesn't have orthogonal flow, then it already has an override width set, so use it.
+        if (hasOrthogonalFlow(child)) {
+            LayoutUnit childWidth = std::max<LayoutUnit>(0, lineCrossAxisExtent - crossAxisMarginExtentForChild(child));
+            childWidth = child->constrainLogicalWidthInRegionByMinMax(childWidth, childWidth, this);
+
+            if (childWidth != child->logicalWidth()) {
+                child->setOverrideLogicalContentWidth(childWidth - child->borderAndPaddingLogicalWidth());
+                child->setChildNeedsLayout(true, MarkOnlyThis);
+                child->layout();
+            }
+        }
+    }
+}
+
+void RenderFlexibleBox::flipForRightToLeftColumn()
+{
+    if (style()->isLeftToRightDirection() || !isColumnFlow())
+        return;
+
+    LayoutUnit crossExtent = crossAxisExtent();
+    for (RenderBox* child = m_orderIterator.first(); child; child = m_orderIterator.next()) {
+        if (child->isOutOfFlowPositioned())
+            continue;
+        LayoutPoint location = flowAwareLocationForChild(child);
+        location.setY(crossExtent - crossAxisExtentForChild(child) - location.y());
+        setFlowAwareLocationForChild(child, location);
+    }
+}
+
+void RenderFlexibleBox::flipForWrapReverse(const Vector<LineContext>& lineContexts, LayoutUnit crossAxisStartEdge)
+{
+    LayoutUnit contentExtent = crossAxisContentExtent();
+    RenderBox* child = m_orderIterator.first();
+    for (size_t lineNumber = 0; lineNumber < lineContexts.size(); ++lineNumber) {
+        for (size_t childNumber = 0; childNumber < lineContexts[lineNumber].numberOfChildren; ++childNumber, child = m_orderIterator.next()) {
+            ASSERT(child);
+            LayoutUnit lineCrossAxisExtent = lineContexts[lineNumber].crossAxisExtent;
+            LayoutUnit originalOffset = lineContexts[lineNumber].crossAxisOffset - crossAxisStartEdge;
+            LayoutUnit newOffset = contentExtent - originalOffset - lineCrossAxisExtent;
+            adjustAlignmentForChild(child, newOffset - originalOffset);
+        }
+    }
+}
+
+}
diff --git a/Source/core/rendering/RenderFlexibleBox.h b/Source/core/rendering/RenderFlexibleBox.h
new file mode 100644
index 0000000..6c13e64
--- /dev/null
+++ b/Source/core/rendering/RenderFlexibleBox.h
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2011 Google 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:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+ * OWNER 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 RenderFlexibleBox_h
+#define RenderFlexibleBox_h
+
+#include "core/rendering/RenderBlock.h"
+
+namespace WebCore {
+
+class RenderFlexibleBox : public RenderBlock {
+public:
+    RenderFlexibleBox(Element*);
+    virtual ~RenderFlexibleBox();
+
+    static RenderFlexibleBox* createAnonymous(Document*);
+
+    virtual const char* renderName() const OVERRIDE;
+
+    virtual bool isFlexibleBox() const OVERRIDE FINAL { return true; }
+    virtual bool avoidsFloats() const OVERRIDE FINAL { return true; }
+    virtual bool canCollapseAnonymousBlockChild() const OVERRIDE FINAL { return false; }
+    virtual void layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeight = 0) OVERRIDE FINAL;
+
+    virtual int baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const OVERRIDE;
+    virtual int firstLineBoxBaseline() const OVERRIDE;
+    virtual int inlineBlockBaseline(LineDirectionMode) const OVERRIDE;
+
+    virtual void paintChildren(PaintInfo& forSelf, const LayoutPoint&, PaintInfo& forChild, bool usePrintRect) OVERRIDE FINAL;
+
+    bool isHorizontalFlow() const;
+
+protected:
+    virtual void computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const OVERRIDE;
+    virtual void computePreferredLogicalWidths() OVERRIDE;
+
+    virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+
+private:
+    enum FlexSign {
+        PositiveFlexibility,
+        NegativeFlexibility,
+    };
+
+    enum PositionedLayoutMode {
+        FlipForRowReverse,
+        NoFlipForRowReverse,
+    };
+
+    struct OrderHashTraits;
+    typedef HashSet<int, DefaultHash<int>::Hash, OrderHashTraits> OrderHashSet;
+
+    class OrderIterator {
+        WTF_MAKE_NONCOPYABLE(OrderIterator);
+    public:
+        OrderIterator(const RenderFlexibleBox*);
+        void setOrderValues(const OrderHashSet&);
+        RenderBox* currentChild() const { return m_currentChild; }
+        RenderBox* first();
+        RenderBox* next();
+        void reset();
+
+    private:
+        const RenderFlexibleBox* m_flexibleBox;
+        RenderBox* m_currentChild;
+        Vector<int> m_orderValues;
+        Vector<int>::const_iterator m_orderValuesIterator;
+    };
+
+    typedef HashMap<const RenderBox*, LayoutUnit> InflexibleFlexItemSize;
+    typedef Vector<RenderBox*> OrderedFlexItemList;
+
+    struct LineContext;
+    struct Violation;
+
+    // Use an inline capacity of 8, since flexbox containers usually have less than 8 children.
+    typedef Vector<LayoutRect, 8> ChildFrameRects;
+
+    bool hasOrthogonalFlow(RenderBox* child) const;
+    bool isColumnFlow() const;
+    bool isLeftToRightFlow() const;
+    bool isMultiline() const;
+    Length flexBasisForChild(RenderBox* child) const;
+    void setCrossAxisExtent(LayoutUnit);
+    LayoutUnit crossAxisExtentForChild(RenderBox* child) const;
+    LayoutUnit mainAxisExtentForChild(RenderBox* child) const;
+    LayoutUnit crossAxisExtent() const;
+    LayoutUnit mainAxisExtent() const;
+    LayoutUnit crossAxisContentExtent() const;
+    LayoutUnit mainAxisContentExtent(LayoutUnit contentLogicalHeight);
+    LayoutUnit computeMainAxisExtentForChild(RenderBox* child, SizeType, const Length& size);
+    WritingMode transformedWritingMode() const;
+    LayoutUnit flowAwareBorderStart() const;
+    LayoutUnit flowAwareBorderEnd() const;
+    LayoutUnit flowAwareBorderBefore() const;
+    LayoutUnit flowAwareBorderAfter() const;
+    LayoutUnit flowAwarePaddingStart() const;
+    LayoutUnit flowAwarePaddingEnd() const;
+    LayoutUnit flowAwarePaddingBefore() const;
+    LayoutUnit flowAwarePaddingAfter() const;
+    LayoutUnit flowAwareMarginStartForChild(RenderBox* child) const;
+    LayoutUnit flowAwareMarginEndForChild(RenderBox* child) const;
+    LayoutUnit flowAwareMarginBeforeForChild(RenderBox* child) const;
+    LayoutUnit flowAwareMarginAfterForChild(RenderBox* child) const;
+    LayoutUnit crossAxisMarginExtentForChild(RenderBox* child) const;
+    LayoutUnit crossAxisScrollbarExtent() const;
+    LayoutPoint flowAwareLocationForChild(RenderBox* child) const;
+    // FIXME: Supporting layout deltas.
+    void setFlowAwareLocationForChild(RenderBox* child, const LayoutPoint&);
+    void adjustAlignmentForChild(RenderBox* child, LayoutUnit);
+    EAlignItems alignmentForChild(RenderBox* child) const;
+    LayoutUnit mainAxisBorderAndPaddingExtentForChild(RenderBox* child) const;
+    LayoutUnit mainAxisScrollbarExtentForChild(RenderBox* child) const;
+    LayoutUnit preferredMainAxisContentExtentForChild(RenderBox* child);
+
+    void layoutFlexItems(bool relayoutChildren, Vector<LineContext>&);
+    LayoutUnit autoMarginOffsetInMainAxis(const OrderedFlexItemList&, LayoutUnit& availableFreeSpace);
+    void updateAutoMarginsInMainAxis(RenderBox* child, LayoutUnit autoMarginOffset);
+    bool hasAutoMarginsInCrossAxis(RenderBox* child) const;
+    bool updateAutoMarginsInCrossAxis(RenderBox* child, LayoutUnit availableAlignmentSpace);
+    void repositionLogicalHeightDependentFlexItems(Vector<LineContext>&);
+    LayoutUnit clientLogicalBottomAfterRepositioning();
+    void appendChildFrameRects(ChildFrameRects&);
+    void repaintChildrenDuringLayoutIfMoved(const ChildFrameRects&);
+
+    LayoutUnit availableAlignmentSpaceForChild(LayoutUnit lineCrossAxisExtent, RenderBox*);
+    LayoutUnit marginBoxAscentForChild(RenderBox*);
+
+    LayoutUnit computeChildMarginValue(Length margin, RenderView*);
+    void computeMainAxisPreferredSizes(OrderHashSet&);
+    LayoutUnit adjustChildSizeForMinAndMax(RenderBox*, LayoutUnit childSize);
+    bool computeNextFlexLine(OrderedFlexItemList& orderedChildren, LayoutUnit& preferredMainAxisExtent, double& totalFlexGrow, double& totalWeightedFlexShrink, LayoutUnit& minMaxAppliedMainAxisExtent);
+
+    bool resolveFlexibleLengths(FlexSign, const OrderedFlexItemList&, LayoutUnit& availableFreeSpace, double& totalFlexGrow, double& totalWeightedFlexShrink, InflexibleFlexItemSize&, Vector<LayoutUnit>& childSizes);
+    void freezeViolations(const Vector<Violation>&, LayoutUnit& availableFreeSpace, double& totalFlexGrow, double& totalWeightedFlexShrink, InflexibleFlexItemSize&);
+
+    void resetAutoMarginsAndLogicalTopInCrossAxis(RenderBox*);
+    bool needToStretchChild(RenderBox*);
+    void setLogicalOverrideSize(RenderBox* child, LayoutUnit childPreferredSize);
+    void prepareChildForPositionedLayout(RenderBox* child, LayoutUnit mainAxisOffset, LayoutUnit crossAxisOffset, PositionedLayoutMode);
+    size_t numberOfInFlowPositionedChildren(const OrderedFlexItemList&) const;
+    void layoutAndPlaceChildren(LayoutUnit& crossAxisOffset, const OrderedFlexItemList&, const Vector<LayoutUnit>& childSizes, LayoutUnit availableFreeSpace, bool relayoutChildren, Vector<LineContext>&);
+    void layoutColumnReverse(const OrderedFlexItemList&, LayoutUnit crossAxisOffset, LayoutUnit availableFreeSpace);
+    void alignFlexLines(Vector<LineContext>&);
+    void alignChildren(const Vector<LineContext>&);
+    void applyStretchAlignmentToChild(RenderBox*, LayoutUnit lineCrossAxisExtent);
+    void flipForRightToLeftColumn();
+    void flipForWrapReverse(const Vector<LineContext>&, LayoutUnit crossAxisStartEdge);
+
+    mutable OrderIterator m_orderIterator;
+    int m_numberOfInFlowChildrenOnFirstLine;
+};
+
+inline RenderFlexibleBox* toRenderFlexibleBox(RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isFlexibleBox());
+    return static_cast<RenderFlexibleBox*>(object);
+}
+
+inline const RenderFlexibleBox* toRenderFlexibleBox(const RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isFlexibleBox());
+    return static_cast<const RenderFlexibleBox*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderFlexibleBox(const RenderFlexibleBox*);
+
+} // namespace WebCore
+
+#endif // RenderFlexibleBox_h
diff --git a/Source/core/rendering/RenderFlowThread.cpp b/Source/core/rendering/RenderFlowThread.cpp
new file mode 100644
index 0000000..2f1788b
--- /dev/null
+++ b/Source/core/rendering/RenderFlowThread.cpp
@@ -0,0 +1,991 @@
+/*
+ * Copyright (C) 2011 Adobe Systems Incorporated. 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 THE COPYRIGHT HOLDER "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 THE COPYRIGHT HOLDER 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 "core/rendering/RenderFlowThread.h"
+
+#include "core/dom/Node.h"
+#include "core/platform/PODIntervalTree.h"
+#include "core/platform/graphics/transforms/TransformState.h"
+#include "core/rendering/FlowThreadController.h"
+#include "core/rendering/HitTestRequest.h"
+#include "core/rendering/HitTestResult.h"
+#include "core/rendering/PaintInfo.h"
+#include "core/rendering/RenderBoxRegionInfo.h"
+#include "core/rendering/RenderLayer.h"
+#include "core/rendering/RenderRegion.h"
+#include "core/rendering/RenderView.h"
+
+namespace WebCore {
+
+RenderFlowThread::RenderFlowThread()
+    : RenderBlock(0)
+    , m_autoLogicalHeightRegionsCount(0)
+    , m_regionsInvalidated(false)
+    , m_regionsHaveUniformLogicalWidth(true)
+    , m_regionsHaveUniformLogicalHeight(true)
+    , m_overset(true)
+    , m_hasRegionsWithStyling(false)
+    , m_dispatchRegionLayoutUpdateEvent(false)
+    , m_pageLogicalSizeChanged(false)
+    , m_inConstrainedLayoutPhase(false)
+    , m_needsTwoPhasesLayout(false)
+{
+    setFlowThreadState(InsideOutOfFlowThread);
+}
+
+PassRefPtr<RenderStyle> RenderFlowThread::createFlowThreadStyle(RenderStyle* parentStyle)
+{
+    RefPtr<RenderStyle> newStyle(RenderStyle::create());
+    newStyle->inheritFrom(parentStyle);
+    newStyle->setDisplay(BLOCK);
+    newStyle->setPosition(AbsolutePosition);
+    newStyle->setZIndex(0);
+    newStyle->setLeft(Length(0, Fixed));
+    newStyle->setTop(Length(0, Fixed));
+    newStyle->setWidth(Length(100, Percent));
+    newStyle->setHeight(Length(100, Percent));
+    newStyle->font().update(0);
+    
+    return newStyle.release();
+}
+
+void RenderFlowThread::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
+{
+    RenderBlock::styleDidChange(diff, oldStyle);
+
+    if (oldStyle && oldStyle->writingMode() != style()->writingMode())
+        m_regionsInvalidated = true;
+}
+
+void RenderFlowThread::removeFlowChildInfo(RenderObject* child)
+{
+    if (child->isBox())
+        removeRenderBoxRegionInfo(toRenderBox(child));
+    clearRenderObjectCustomStyle(child);
+}
+
+void RenderFlowThread::addRegionToThread(RenderRegion* renderRegion)
+{
+    ASSERT(renderRegion);
+    m_regionList.add(renderRegion);
+    renderRegion->setIsValid(true);
+}
+
+void RenderFlowThread::removeRegionFromThread(RenderRegion* renderRegion)
+{
+    ASSERT(renderRegion);
+    m_regionList.remove(renderRegion);
+}
+
+void RenderFlowThread::invalidateRegions()
+{
+    if (m_regionsInvalidated) {
+        ASSERT(selfNeedsLayout());
+        return;
+    }
+
+    m_regionRangeMap.clear();
+    m_breakBeforeToRegionMap.clear();
+    m_breakAfterToRegionMap.clear();
+    setNeedsLayout(true);
+
+    m_regionsInvalidated = true;
+}
+
+class CurrentRenderFlowThreadDisabler {
+    WTF_MAKE_NONCOPYABLE(CurrentRenderFlowThreadDisabler);
+public:
+    CurrentRenderFlowThreadDisabler(RenderView* view)
+        : m_view(view)
+        , m_renderFlowThread(0)
+    {
+        m_renderFlowThread = m_view->flowThreadController()->currentRenderFlowThread();
+        if (m_renderFlowThread)
+            view->flowThreadController()->setCurrentRenderFlowThread(0);
+    }
+    ~CurrentRenderFlowThreadDisabler()
+    {
+        if (m_renderFlowThread)
+            m_view->flowThreadController()->setCurrentRenderFlowThread(m_renderFlowThread);
+    }
+private:
+    RenderView* m_view;
+    RenderFlowThread* m_renderFlowThread;
+};
+
+void RenderFlowThread::validateRegions()
+{
+    if (m_regionsInvalidated) {
+        m_regionsInvalidated = false;
+        m_regionsHaveUniformLogicalWidth = true;
+        m_regionsHaveUniformLogicalHeight = true;
+
+        if (hasRegions()) {
+            LayoutUnit previousRegionLogicalWidth = 0;
+            LayoutUnit previousRegionLogicalHeight = 0;
+            bool firstRegionVisited = false;
+            
+            for (RenderRegionList::iterator iter = m_regionList.begin(); iter != m_regionList.end(); ++iter) {
+                RenderRegion* region = *iter;
+                ASSERT(!region->needsLayout() || region->isRenderRegionSet());
+
+                region->deleteAllRenderBoxRegionInfo();
+
+                // In the normal layout phase we need to initialize the overrideLogicalContentHeight for auto-height regions.
+                // See initializeRegionsOverrideLogicalContentHeight for the explanation.
+                // Also, if we have auto-height regions we can't assume m_regionsHaveUniformLogicalHeight to be true in the first phase
+                // because the auto-height regions don't have their height computed yet.
+                if (!inConstrainedLayoutPhase() && region->hasAutoLogicalHeight()) {
+                    region->setOverrideLogicalContentHeight(region->maxPageLogicalHeight());
+                    m_regionsHaveUniformLogicalHeight = false;
+                }
+
+                LayoutUnit regionLogicalWidth = region->pageLogicalWidth();
+                LayoutUnit regionLogicalHeight = region->pageLogicalHeight();
+
+                if (!firstRegionVisited)
+                    firstRegionVisited = true;
+                else {
+                    if (m_regionsHaveUniformLogicalWidth && previousRegionLogicalWidth != regionLogicalWidth)
+                        m_regionsHaveUniformLogicalWidth = false;
+                    if (m_regionsHaveUniformLogicalHeight && previousRegionLogicalHeight != regionLogicalHeight)
+                        m_regionsHaveUniformLogicalHeight = false;
+                }
+
+                previousRegionLogicalWidth = regionLogicalWidth;
+            }
+        }
+    }
+
+    updateLogicalWidth(); // Called to get the maximum logical width for the region.
+    updateRegionsFlowThreadPortionRect();
+}
+
+void RenderFlowThread::layout()
+{
+    StackStats::LayoutCheckPoint layoutCheckPoint;
+
+    m_pageLogicalSizeChanged = m_regionsInvalidated && everHadLayout();
+
+    // In case this is the second pass of the normal phase we need to update the auto-height regions to their initial value.
+    // If the region chain was invalidated this will happen anyway.
+    if (!m_regionsInvalidated && !inConstrainedLayoutPhase())
+        initializeRegionsOverrideLogicalContentHeight();
+
+    validateRegions();
+
+    // This is the first phase of the layout and because we have auto-height regions we'll need a second
+    // pass to update the flow with the computed auto-height regions.
+    m_needsTwoPhasesLayout = !inConstrainedLayoutPhase() && hasAutoLogicalHeightRegions();
+
+    CurrentRenderFlowThreadMaintainer currentFlowThreadSetter(this);
+    RenderBlock::layout();
+
+    m_pageLogicalSizeChanged = false;
+
+    if (lastRegion())
+        lastRegion()->expandToEncompassFlowThreadContentsIfNeeded();
+
+    if (shouldDispatchRegionLayoutUpdateEvent())
+        dispatchRegionLayoutUpdateEvent();
+}
+
+void RenderFlowThread::updateLogicalWidth()
+{
+    LayoutUnit logicalWidth = initialLogicalWidth();
+    for (RenderRegionList::iterator iter = m_regionList.begin(); iter != m_regionList.end(); ++iter) {
+        RenderRegion* region = *iter;
+        ASSERT(!region->needsLayout() || region->isRenderRegionSet());
+        logicalWidth = max(region->pageLogicalWidth(), logicalWidth);
+    }
+    setLogicalWidth(logicalWidth);
+
+    // If the regions have non-uniform logical widths, then insert inset information for the RenderFlowThread.
+    for (RenderRegionList::iterator iter = m_regionList.begin(); iter != m_regionList.end(); ++iter) {
+        RenderRegion* region = *iter;
+        LayoutUnit regionLogicalWidth = region->pageLogicalWidth();
+        if (regionLogicalWidth != logicalWidth) {
+            LayoutUnit logicalLeft = style()->direction() == LTR ? LayoutUnit() : logicalWidth - regionLogicalWidth;
+            region->setRenderBoxRegionInfo(this, logicalLeft, regionLogicalWidth, false);
+        }
+    }
+}
+
+void RenderFlowThread::computeLogicalHeight(LayoutUnit, LayoutUnit logicalTop, LogicalExtentComputedValues& computedValues) const
+{
+    computedValues.m_position = logicalTop;
+    computedValues.m_extent = 0;
+
+    for (RenderRegionList::const_iterator iter = m_regionList.begin(); iter != m_regionList.end(); ++iter) {
+        RenderRegion* region = *iter;
+        ASSERT(!region->needsLayout() || region->isRenderRegionSet());
+
+        computedValues.m_extent += region->logicalHeightOfAllFlowThreadContent();
+    }
+}
+
+LayoutRect RenderFlowThread::computeRegionClippingRect(const LayoutPoint& offset, const LayoutRect& flowThreadPortionRect, const LayoutRect& flowThreadPortionOverflowRect) const
+{
+    LayoutRect regionClippingRect(offset + (flowThreadPortionOverflowRect.location() - flowThreadPortionRect.location()), flowThreadPortionOverflowRect.size());
+    if (style()->isFlippedBlocksWritingMode())
+        regionClippingRect.move(flowThreadPortionRect.size() - flowThreadPortionOverflowRect.size());
+    return regionClippingRect;
+}
+
+void RenderFlowThread::paintFlowThreadPortionInRegion(PaintInfo& paintInfo, RenderRegion* region, LayoutRect flowThreadPortionRect, LayoutRect flowThreadPortionOverflowRect, const LayoutPoint& paintOffset) const
+{
+    GraphicsContext* context = paintInfo.context;
+    if (!context)
+        return;
+
+    // RenderFlowThread should start painting its content in a position that is offset
+    // from the region rect's current position. The amount of offset is equal to the location of
+    // the flow thread portion in the flow thread's local coordinates.
+    // Note that we have to pixel snap the location at which we're going to paint, since this is necessary
+    // to minimize the amount of incorrect snapping that would otherwise occur.
+    // If we tried to paint by applying a non-integral translation, then all the
+    // layout code that attempted to pixel snap would be incorrect.
+    IntPoint adjustedPaintOffset;
+    LayoutPoint portionLocation;
+    if (style()->isFlippedBlocksWritingMode()) {
+        LayoutRect flippedFlowThreadPortionRect(flowThreadPortionRect);
+        flipForWritingMode(flippedFlowThreadPortionRect);
+        portionLocation = flippedFlowThreadPortionRect.location();
+    } else
+        portionLocation = flowThreadPortionRect.location();
+    adjustedPaintOffset = roundedIntPoint(paintOffset - portionLocation);
+
+    // The clipping rect for the region is set up by assuming the flowThreadPortionRect is going to paint offset from adjustedPaintOffset.
+    // Remember that we pixel snapped and moved the paintOffset and stored the snapped result in adjustedPaintOffset. Now we add back in
+    // the flowThreadPortionRect's location to get the spot where we expect the portion to actually paint. This can be non-integral and
+    // that's ok. We then pixel snap the resulting clipping rect to account for snapping that will occur when the flow thread paints.
+    IntRect regionClippingRect = pixelSnappedIntRect(computeRegionClippingRect(adjustedPaintOffset + portionLocation, flowThreadPortionRect, flowThreadPortionOverflowRect));
+
+    PaintInfo info(paintInfo);
+    info.rect.intersect(regionClippingRect);
+
+    if (!info.rect.isEmpty()) {
+        context->save();
+
+        context->clip(regionClippingRect);
+
+        context->translate(adjustedPaintOffset.x(), adjustedPaintOffset.y());
+        info.rect.moveBy(-adjustedPaintOffset);
+        
+        layer()->paint(context, info.rect, 0, 0, region, RenderLayer::PaintLayerTemporaryClipRects);
+
+        context->restore();
+    }
+}
+
+bool RenderFlowThread::hitTestFlowThreadPortionInRegion(RenderRegion* region, LayoutRect flowThreadPortionRect, LayoutRect flowThreadPortionOverflowRect, const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset) const
+{
+    LayoutRect regionClippingRect = computeRegionClippingRect(accumulatedOffset, flowThreadPortionRect, flowThreadPortionOverflowRect);
+    if (!regionClippingRect.contains(locationInContainer.point()))
+        return false;
+
+    LayoutSize renderFlowThreadOffset;
+    if (style()->isFlippedBlocksWritingMode()) {
+        LayoutRect flippedFlowThreadPortionRect(flowThreadPortionRect);
+        flipForWritingMode(flippedFlowThreadPortionRect);
+        renderFlowThreadOffset = accumulatedOffset - flippedFlowThreadPortionRect.location();
+    } else
+        renderFlowThreadOffset = accumulatedOffset - flowThreadPortionRect.location();
+
+    // Always ignore clipping, since the RenderFlowThread has nothing to do with the bounds of the FrameView.
+    HitTestRequest newRequest(request.type() | HitTestRequest::IgnoreClipping | HitTestRequest::DisallowShadowContent);
+    HitTestResult tempResult(result);
+
+    // Make a new temporary HitTestLocation in the new region.
+    HitTestLocation newHitTestLocation(locationInContainer, -renderFlowThreadOffset, region);
+
+    bool isPointInsideFlowThread = layer()->hitTest(newRequest, newHitTestLocation, tempResult);
+
+    // We want to make sure we hit a node from the content inside the flow thread.
+    isPointInsideFlowThread = isPointInsideFlowThread && !tempResult.innerNode()->isDocumentNode();
+    if (isPointInsideFlowThread)
+        result = tempResult;
+
+    // FIXME: Should we set result.m_localPoint back to the RenderRegion's coordinate space or leave it in the RenderFlowThread's coordinate
+    // space? Right now it's staying in the RenderFlowThread's coordinate space, which may end up being ok. We will know more when we get around to
+    // patching positionForPoint.
+    return isPointInsideFlowThread;
+}
+
+bool RenderFlowThread::shouldRepaint(const LayoutRect& r) const
+{
+    if (view()->printing() || r.isEmpty())
+        return false;
+
+    return true;
+}
+
+void RenderFlowThread::repaintRectangleInRegions(const LayoutRect& repaintRect) const
+{
+    if (!shouldRepaint(repaintRect) || !hasValidRegionInfo())
+        return;
+
+    LayoutStateDisabler layoutStateDisabler(view()); // We can't use layout state to repaint, since the regions are somewhere else.
+
+    // We can't use currentFlowThread as it is possible to have interleaved flow threads and the wrong one could be used.
+    // Let each region figure out the proper enclosing flow thread.
+    CurrentRenderFlowThreadDisabler disabler(view());
+    
+    for (RenderRegionList::const_iterator iter = m_regionList.begin(); iter != m_regionList.end(); ++iter) {
+        RenderRegion* region = *iter;
+
+        region->repaintFlowThreadContent(repaintRect);
+    }
+}
+
+RenderRegion* RenderFlowThread::regionAtBlockOffset(LayoutUnit offset, bool extendLastRegion, RegionAutoGenerationPolicy autoGenerationPolicy)
+{
+    ASSERT(!m_regionsInvalidated);
+
+    if (autoGenerationPolicy == AllowRegionAutoGeneration)
+        autoGenerateRegionsToBlockOffset(offset);
+
+    if (offset <= 0)
+        return m_regionList.isEmpty() ? 0 : m_regionList.first();
+
+    RegionSearchAdapter adapter(offset);
+    m_regionIntervalTree.allOverlapsWithAdapter<RegionSearchAdapter>(adapter);
+
+    // If no region was found, the offset is in the flow thread overflow.
+    // The last region will contain the offset if extendLastRegion is set or if the last region is a set.
+    if (!adapter.result() && !m_regionList.isEmpty() && (extendLastRegion || m_regionList.last()->isRenderRegionSet()))
+        return m_regionList.last();
+
+    return adapter.result();
+}
+
+LayoutUnit RenderFlowThread::pageLogicalTopForOffset(LayoutUnit offset)
+{
+    RenderRegion* region = regionAtBlockOffset(offset);
+    return region ? region->pageLogicalTopForOffset(offset) : LayoutUnit();
+}
+
+LayoutUnit RenderFlowThread::pageLogicalWidthForOffset(LayoutUnit offset)
+{
+    RenderRegion* region = regionAtBlockOffset(offset, true);
+    return region ? region->pageLogicalWidth() : contentLogicalWidth();
+}
+
+LayoutUnit RenderFlowThread::pageLogicalHeightForOffset(LayoutUnit offset)
+{
+    RenderRegion* region = regionAtBlockOffset(offset);
+    if (!region)
+        return 0;
+
+    return region->pageLogicalHeight();
+}
+
+LayoutUnit RenderFlowThread::pageRemainingLogicalHeightForOffset(LayoutUnit offset, PageBoundaryRule pageBoundaryRule)
+{
+    RenderRegion* region = regionAtBlockOffset(offset);
+    if (!region)
+        return 0;
+
+    LayoutUnit pageLogicalTop = region->pageLogicalTopForOffset(offset);
+    LayoutUnit pageLogicalHeight = region->pageLogicalHeight();
+    LayoutUnit pageLogicalBottom = pageLogicalTop + pageLogicalHeight;
+    LayoutUnit remainingHeight = pageLogicalBottom - offset;
+    if (pageBoundaryRule == IncludePageBoundary) {
+        // If IncludePageBoundary is set, the line exactly on the top edge of a
+        // region will act as being part of the previous region.
+        remainingHeight = intMod(remainingHeight, pageLogicalHeight);
+    }
+    return remainingHeight;
+}
+
+RenderRegion* RenderFlowThread::mapFromFlowToRegion(TransformState& transformState) const
+{
+    if (!hasValidRegionInfo())
+        return 0;
+
+    LayoutRect boxRect = transformState.mappedQuad().enclosingBoundingBox();
+    flipForWritingMode(boxRect);
+
+    // FIXME: We need to refactor RenderObject::absoluteQuads to be able to split the quads across regions,
+    // for now we just take the center of the mapped enclosing box and map it to a region.
+    // Note: Using the center in order to avoid rounding errors.
+
+    LayoutPoint center = boxRect.center();
+    RenderRegion* renderRegion = const_cast<RenderFlowThread*>(this)->regionAtBlockOffset(isHorizontalWritingMode() ? center.y() : center.x(), true, DisallowRegionAutoGeneration);
+    if (!renderRegion)
+        return 0;
+
+    LayoutRect flippedRegionRect(renderRegion->flowThreadPortionRect());
+    flipForWritingMode(flippedRegionRect);
+
+    transformState.move(renderRegion->contentBoxRect().location() - flippedRegionRect.location());
+
+    return renderRegion;
+}
+
+void RenderFlowThread::removeRenderBoxRegionInfo(RenderBox* box)
+{
+    if (!hasRegions())
+        return;
+
+    // If the region chain was invalidated the next layout will clear the box information from all the regions.
+    if (m_regionsInvalidated) {
+        ASSERT(selfNeedsLayout());
+        return;
+    }
+
+    RenderRegion* startRegion;
+    RenderRegion* endRegion;
+    getRegionRangeForBox(box, startRegion, endRegion);
+
+    for (RenderRegionList::iterator iter = m_regionList.find(startRegion); iter != m_regionList.end(); ++iter) {
+        RenderRegion* region = *iter;
+        region->removeRenderBoxRegionInfo(box);
+        if (region == endRegion)
+            break;
+    }
+
+#ifndef NDEBUG
+    // We have to make sure we did not leave any RenderBoxRegionInfo attached.
+    for (RenderRegionList::iterator iter = m_regionList.begin(); iter != m_regionList.end(); ++iter) {
+        RenderRegion* region = *iter;
+        ASSERT(!region->renderBoxRegionInfo(box));
+    }
+#endif
+
+    m_regionRangeMap.remove(box);
+}
+
+bool RenderFlowThread::logicalWidthChangedInRegions(const RenderBlock* block, LayoutUnit offsetFromLogicalTopOfFirstPage)
+{
+    if (!hasRegions())
+        return false;
+
+    RenderRegion* startRegion;
+    RenderRegion* endRegion;
+    getRegionRangeForBox(block, startRegion, endRegion);
+
+    // When the region chain is invalidated the box information is discarded so we must assume the width has changed.
+    if (m_pageLogicalSizeChanged && !startRegion)
+        return true;
+
+    // Not necessary for the flow thread, since we already computed the correct info for it.
+    if (block == this)
+        return false;
+
+    for (RenderRegionList::iterator iter = m_regionList.find(startRegion); iter != m_regionList.end(); ++iter) {
+        RenderRegion* region = *iter;
+        ASSERT(!region->needsLayout() || region->isRenderRegionSet());
+
+        OwnPtr<RenderBoxRegionInfo> oldInfo = region->takeRenderBoxRegionInfo(block);
+        if (!oldInfo)
+            continue;
+
+        LayoutUnit oldLogicalWidth = oldInfo->logicalWidth();
+        RenderBoxRegionInfo* newInfo = block->renderBoxRegionInfo(region, offsetFromLogicalTopOfFirstPage);
+        if (!newInfo || newInfo->logicalWidth() != oldLogicalWidth)
+            return true;
+
+        if (region == endRegion)
+            break;
+    }
+
+    return false;
+}
+
+LayoutUnit RenderFlowThread::contentLogicalWidthOfFirstRegion() const
+{
+    RenderRegion* firstValidRegionInFlow = firstRegion();
+    if (!firstValidRegionInFlow)
+        return 0;
+    return isHorizontalWritingMode() ? firstValidRegionInFlow->contentWidth() : firstValidRegionInFlow->contentHeight();
+}
+
+LayoutUnit RenderFlowThread::contentLogicalHeightOfFirstRegion() const
+{
+    RenderRegion* firstValidRegionInFlow = firstRegion();
+    if (!firstValidRegionInFlow)
+        return 0;
+    return isHorizontalWritingMode() ? firstValidRegionInFlow->contentHeight() : firstValidRegionInFlow->contentWidth();
+}
+
+LayoutUnit RenderFlowThread::contentLogicalLeftOfFirstRegion() const
+{
+    RenderRegion* firstValidRegionInFlow = firstRegion();
+    if (!firstValidRegionInFlow)
+        return 0;
+    return isHorizontalWritingMode() ? firstValidRegionInFlow->flowThreadPortionRect().x() : firstValidRegionInFlow->flowThreadPortionRect().y();
+}
+
+RenderRegion* RenderFlowThread::firstRegion() const
+{
+    if (!hasValidRegionInfo())
+        return 0;
+    return m_regionList.first();
+}
+
+RenderRegion* RenderFlowThread::lastRegion() const
+{
+    if (!hasValidRegionInfo())
+        return 0;
+    return m_regionList.last();
+}
+
+void RenderFlowThread::clearRenderObjectCustomStyle(const RenderObject* object,
+    const RenderRegion* oldStartRegion, const RenderRegion* oldEndRegion,
+    const RenderRegion* newStartRegion, const RenderRegion* newEndRegion)
+{
+    // Clear the styles for the object in the regions.
+    // The styles are not cleared for the regions that are contained in both ranges.
+    bool insideOldRegionRange = false;
+    bool insideNewRegionRange = false;
+    for (RenderRegionList::iterator iter = m_regionList.begin(); iter != m_regionList.end(); ++iter) {
+        RenderRegion* region = *iter;
+
+        if (oldStartRegion == region)
+            insideOldRegionRange = true;
+        if (newStartRegion == region)
+            insideNewRegionRange = true;
+
+        if (!(insideOldRegionRange && insideNewRegionRange))
+            region->clearObjectStyleInRegion(object);
+
+        if (oldEndRegion == region)
+            insideOldRegionRange = false;
+        if (newEndRegion == region)
+            insideNewRegionRange = false;
+    }
+}
+
+void RenderFlowThread::setRegionRangeForBox(const RenderBox* box, LayoutUnit offsetFromLogicalTopOfFirstPage)
+{
+    if (!hasRegions())
+        return;
+
+    // FIXME: Not right for differing writing-modes.
+    RenderRegion* startRegion = regionAtBlockOffset(offsetFromLogicalTopOfFirstPage, true);
+    RenderRegion* endRegion = regionAtBlockOffset(offsetFromLogicalTopOfFirstPage + box->logicalHeight(), true);
+    RenderRegionRangeMap::iterator it = m_regionRangeMap.find(box);
+    if (it == m_regionRangeMap.end()) {
+        m_regionRangeMap.set(box, RenderRegionRange(startRegion, endRegion));
+        clearRenderObjectCustomStyle(box);
+        return;
+    }
+
+    // If nothing changed, just bail.
+    RenderRegionRange& range = it->value;
+    if (range.startRegion() == startRegion && range.endRegion() == endRegion)
+        return;
+
+    // Delete any info that we find before our new startRegion and after our new endRegion.
+    for (RenderRegionList::iterator iter = m_regionList.begin(); iter != m_regionList.end(); ++iter) {
+        RenderRegion* region = *iter;
+        if (region == startRegion) {
+            iter = m_regionList.find(endRegion);
+            continue;
+        }
+
+        region->removeRenderBoxRegionInfo(box);
+
+        if (region == range.endRegion())
+            break;
+    }
+
+    clearRenderObjectCustomStyle(box, range.startRegion(), range.endRegion(), startRegion, endRegion);
+    range.setRange(startRegion, endRegion);
+}
+
+void RenderFlowThread::getRegionRangeForBox(const RenderBox* box, RenderRegion*& startRegion, RenderRegion*& endRegion) const
+{
+    startRegion = 0;
+    endRegion = 0;
+    RenderRegionRangeMap::const_iterator it = m_regionRangeMap.find(box);
+    if (it == m_regionRangeMap.end())
+        return;
+
+    const RenderRegionRange& range = it->value;
+    startRegion = range.startRegion();
+    endRegion = range.endRegion();
+    ASSERT(m_regionList.contains(startRegion) && m_regionList.contains(endRegion));
+}
+
+void RenderFlowThread::applyBreakAfterContent(LayoutUnit clientHeight)
+{
+    // Simulate a region break at height. If it points inside an auto logical height region,
+    // then it may determine the region override logical content height.
+    addForcedRegionBreak(clientHeight, this, false);
+}
+
+void RenderFlowThread::computeOverflowStateForRegions(LayoutUnit oldClientAfterEdge)
+{
+    LayoutUnit height = oldClientAfterEdge;
+
+    // FIXME: the visual overflow of middle region (if it is the last one to contain any content in a render flow thread)
+    // might not be taken into account because the render flow thread height is greater that that regions height + its visual overflow
+    // because of how computeLogicalHeight is implemented for RenderFlowThread (as a sum of all regions height).
+    // This means that the middle region will be marked as fit (even if it has visual overflow flowing into the next region)
+    if (hasRenderOverflow()
+        && ( (isHorizontalWritingMode() && visualOverflowRect().maxY() > clientBoxRect().maxY())
+            || (!isHorizontalWritingMode() && visualOverflowRect().maxX() > clientBoxRect().maxX())))
+        height = isHorizontalWritingMode() ? visualOverflowRect().maxY() : visualOverflowRect().maxX();
+
+    RenderRegion* lastReg = lastRegion();
+    for (RenderRegionList::iterator iter = m_regionList.begin(); iter != m_regionList.end(); ++iter) {
+        RenderRegion* region = *iter;
+        LayoutUnit flowMin = height - (isHorizontalWritingMode() ? region->flowThreadPortionRect().y() : region->flowThreadPortionRect().x());
+        LayoutUnit flowMax = height - (isHorizontalWritingMode() ? region->flowThreadPortionRect().maxY() : region->flowThreadPortionRect().maxX());
+        RenderRegion::RegionState previousState = region->regionState();
+        RenderRegion::RegionState state = RenderRegion::RegionFit;
+        if (flowMin <= 0)
+            state = RenderRegion::RegionEmpty;
+        if (flowMax > 0 && region == lastReg)
+            state = RenderRegion::RegionOverset;
+        region->setRegionState(state);
+        // determine whether the NamedFlow object should dispatch a regionLayoutUpdate event
+        // FIXME: currently it cannot determine whether a region whose regionOverset state remained either "fit" or "overset" has actually
+        // changed, so it just assumes that the NamedFlow should dispatch the event
+        if (previousState != state
+            || state == RenderRegion::RegionFit
+            || state == RenderRegion::RegionOverset)
+            setDispatchRegionLayoutUpdateEvent(true);
+    }
+
+    // With the regions overflow state computed we can also set the overset flag for the named flow.
+    // If there are no valid regions in the chain, overset is true.
+    m_overset = lastReg ? lastReg->regionState() == RenderRegion::RegionOverset : true;
+}
+
+bool RenderFlowThread::regionInRange(const RenderRegion* targetRegion, const RenderRegion* startRegion, const RenderRegion* endRegion) const
+{
+    ASSERT(targetRegion);
+
+    for (RenderRegionList::const_iterator it = m_regionList.find(const_cast<RenderRegion*>(startRegion)); it != m_regionList.end(); ++it) {
+        const RenderRegion* currRegion = *it;
+        if (targetRegion == currRegion)
+            return true;
+        if (currRegion == endRegion)
+            break;
+    }
+
+    return false;
+}
+
+// Check if the content is flown into at least a region with region styling rules.
+void RenderFlowThread::checkRegionsWithStyling()
+{
+    bool hasRegionsWithStyling = false;
+    for (RenderRegionList::iterator iter = m_regionList.begin(); iter != m_regionList.end(); ++iter) {
+        RenderRegion* region = *iter;
+        if (region->hasCustomRegionStyle()) {
+            hasRegionsWithStyling = true;
+            break;
+        }
+    }
+    m_hasRegionsWithStyling = hasRegionsWithStyling;
+}
+
+bool RenderFlowThread::objectInFlowRegion(const RenderObject* object, const RenderRegion* region) const
+{
+    ASSERT(object);
+    ASSERT(region);
+
+    RenderFlowThread* flowThread = object->flowThreadContainingBlock();
+    if (flowThread != this)
+        return false;
+    if (!m_regionList.contains(const_cast<RenderRegion*>(region)))
+        return false;
+
+    RenderBox* enclosingBox = object->enclosingBox();
+    RenderRegion* enclosingBoxStartRegion = 0;
+    RenderRegion* enclosingBoxEndRegion = 0;
+    getRegionRangeForBox(enclosingBox, enclosingBoxStartRegion, enclosingBoxEndRegion);
+    if (!regionInRange(region, enclosingBoxStartRegion, enclosingBoxEndRegion))
+        return false;
+
+    if (object->isBox())
+        return true;
+
+    LayoutRect objectABBRect = object->absoluteBoundingBoxRect(true);
+    if (!objectABBRect.width())
+        objectABBRect.setWidth(1);
+    if (!objectABBRect.height())
+        objectABBRect.setHeight(1); 
+    if (objectABBRect.intersects(region->absoluteBoundingBoxRect(true)))
+        return true;
+
+    if (region == lastRegion()) {
+        // If the object does not intersect any of the enclosing box regions
+        // then the object is in last region.
+        for (RenderRegionList::const_iterator it = m_regionList.find(enclosingBoxStartRegion); it != m_regionList.end(); ++it) {
+            const RenderRegion* currRegion = *it;
+            if (currRegion == region)
+                break;
+            if (objectABBRect.intersects(currRegion->absoluteBoundingBoxRect(true)))
+                return false;
+        }
+        return true;
+    }
+
+    return false;
+}
+
+#ifndef NDEBUG
+bool RenderFlowThread::isAutoLogicalHeightRegionsCountConsistent() const
+{
+    unsigned autoLogicalHeightRegions = 0;
+    for (RenderRegionList::const_iterator iter = m_regionList.begin(); iter != m_regionList.end(); ++iter) {
+        const RenderRegion* region = *iter;
+        if (region->hasAutoLogicalHeight())
+            autoLogicalHeightRegions++;
+    }
+
+    return autoLogicalHeightRegions == m_autoLogicalHeightRegionsCount;
+}
+#endif
+
+// During the normal layout phase of the named flow the regions are initialized with a height equal to their max-height.
+// This way unforced breaks are automatically placed when a region is full and the content height/position correctly estimated.
+// Also, the region where a forced break falls is exactly the region found at the forced break offset inside the flow content.
+void RenderFlowThread::initializeRegionsOverrideLogicalContentHeight(RenderRegion* startRegion)
+{
+    ASSERT(!inConstrainedLayoutPhase());
+    if (!hasAutoLogicalHeightRegions())
+        return;
+
+    RenderRegionList::iterator regionIter = startRegion ? m_regionList.find(startRegion) : m_regionList.begin();
+    for (; regionIter != m_regionList.end(); ++regionIter) {
+        RenderRegion* region = *regionIter;
+        if (region->hasAutoLogicalHeight())
+            region->setOverrideLogicalContentHeight(region->maxPageLogicalHeight());
+    }
+}
+
+void RenderFlowThread::markAutoLogicalHeightRegionsForLayout()
+{
+    ASSERT(hasAutoLogicalHeightRegions());
+
+    for (RenderRegionList::iterator iter = m_regionList.begin(); iter != m_regionList.end(); ++iter) {
+        RenderRegion* region = *iter;
+        if (!region->hasAutoLogicalHeight())
+            continue;
+
+        // FIXME: We need to find a way to avoid marking all the regions ancestors for layout
+        // as we are already inside layout.
+        region->setNeedsLayout(true);
+    }
+}
+
+void RenderFlowThread::updateRegionsFlowThreadPortionRect(const RenderRegion* lastRegionWithContent)
+{
+    ASSERT(!lastRegionWithContent || (!inConstrainedLayoutPhase() && hasAutoLogicalHeightRegions()));
+    LayoutUnit logicalHeight = 0;
+    bool emptyRegionsSegment = false;
+    // FIXME: Optimize not to clear the interval all the time. This implies manually managing the tree nodes lifecycle.
+    m_regionIntervalTree.clear();
+    m_regionIntervalTree.initIfNeeded();
+    for (RenderRegionList::iterator iter = m_regionList.begin(); iter != m_regionList.end(); ++iter) {
+        RenderRegion* region = *iter;
+
+        // If we find an empty auto-height region, clear the overrideLogicalContentHeight value.
+        if (emptyRegionsSegment && region->hasAutoLogicalHeight())
+            region->clearOverrideLogicalContentHeight();
+
+        LayoutUnit regionLogicalWidth = region->pageLogicalWidth();
+        LayoutUnit regionLogicalHeight = std::min<LayoutUnit>(LayoutUnit::max() / 2 - logicalHeight, region->logicalHeightOfAllFlowThreadContent());
+
+        LayoutRect regionRect(style()->direction() == LTR ? LayoutUnit() : logicalWidth() - regionLogicalWidth, logicalHeight, regionLogicalWidth, regionLogicalHeight);
+
+        region->setFlowThreadPortionRect(isHorizontalWritingMode() ? regionRect : regionRect.transposedRect());
+
+        m_regionIntervalTree.add(RegionIntervalTree::createInterval(logicalHeight, logicalHeight + regionLogicalHeight, region));
+
+        logicalHeight += regionLogicalHeight;
+
+        // Once we find the last region with content the next regions are considered empty.
+        if (lastRegionWithContent == region)
+            emptyRegionsSegment = true;
+    }
+
+    ASSERT(!lastRegionWithContent || emptyRegionsSegment);
+}
+
+// Even if we require the break to occur at offsetBreakInFlowThread, because regions may have min/max-height values,
+// it is possible that the break will occur at a different offset than the original one required.
+// offsetBreakAdjustment measures the different between the requested break offset and the current break offset.
+bool RenderFlowThread::addForcedRegionBreak(LayoutUnit offsetBreakInFlowThread, RenderObject* breakChild, bool isBefore, LayoutUnit* offsetBreakAdjustment)
+{
+    // We take breaks into account for height computation for auto logical height regions
+    // only in the layout phase in which we lay out the flows threads unconstrained
+    // and we use the content breaks to determine the overrideContentLogicalHeight for
+    // auto logical height regions.
+    if (inConstrainedLayoutPhase())
+        return false;
+
+    // Breaks can come before or after some objects. We need to track these objects, so that if we get
+    // multiple breaks for the same object (for example because of multiple layouts on the same object),
+    // we need to invalidate every other region after the old one and start computing from fresh.
+    RenderObjectToRegionMap& mapToUse = isBefore ? m_breakBeforeToRegionMap : m_breakAfterToRegionMap;
+    RenderObjectToRegionMap::iterator iter = mapToUse.find(breakChild);
+    if (iter != mapToUse.end()) {
+        RenderRegionList::iterator regionIter = m_regionList.find(iter->value);
+        ASSERT(regionIter != m_regionList.end());
+        ASSERT((*regionIter)->hasAutoLogicalHeight());
+        initializeRegionsOverrideLogicalContentHeight(*regionIter);
+
+        // We need to update the regions flow thread portion rect because we are going to process
+        // a break on these regions.
+        updateRegionsFlowThreadPortionRect();
+    }
+
+    // Simulate a region break at offsetBreakInFlowThread. If it points inside an auto logical height region,
+    // then it determines the region override logical content height.
+    RenderRegion* region = regionAtBlockOffset(offsetBreakInFlowThread);
+    if (!region)
+        return false;
+
+    bool lastBreakAfterContent = breakChild == this;
+    bool overrideLogicalContentHeightComputed = false;
+
+    LayoutUnit currentRegionOffsetInFlowThread = isHorizontalWritingMode() ? region->flowThreadPortionRect().y() : region->flowThreadPortionRect().x();
+    LayoutUnit offsetBreakInCurrentRegion = offsetBreakInFlowThread - currentRegionOffsetInFlowThread;
+
+    if (region->hasAutoLogicalHeight()) {
+        // A forced break can appear only in an auto-height region that didn't have a forced break before.
+        // This ASSERT is a good-enough heuristic to verify the above condition.
+        ASSERT(region->maxPageLogicalHeight() == region->overrideLogicalContentHeight());
+
+        mapToUse.set(breakChild, region);
+
+        overrideLogicalContentHeightComputed = true;
+
+        // Compute the region height pretending that the offsetBreakInCurrentRegion is the logicalHeight for the auto-height region.
+        LayoutUnit regionOverrideLogicalContentHeight = region->computeReplacedLogicalHeightRespectingMinMaxHeight(offsetBreakInCurrentRegion);
+
+        // The new height of this region needs to be smaller than the initial value, the max height. A forced break is the only way to change the initial
+        // height of an auto-height region besides content ending.
+        ASSERT(regionOverrideLogicalContentHeight <= region->maxPageLogicalHeight());
+
+        region->setOverrideLogicalContentHeight(regionOverrideLogicalContentHeight);
+
+        currentRegionOffsetInFlowThread += regionOverrideLogicalContentHeight;
+    } else
+        currentRegionOffsetInFlowThread += isHorizontalWritingMode() ? region->flowThreadPortionRect().height() : region->flowThreadPortionRect().width();
+
+    // If the break was found inside an auto-height region its size changed so we need to recompute the flow thread portion rectangles.
+    // Also, if this is the last break after the content we need to clear the overrideLogicalContentHeight value on the last empty regions.
+    if (hasAutoLogicalHeightRegions() && lastBreakAfterContent)
+        updateRegionsFlowThreadPortionRect(region);
+    else if (overrideLogicalContentHeightComputed)
+        updateRegionsFlowThreadPortionRect();
+
+    if (offsetBreakAdjustment)
+        *offsetBreakAdjustment = max<LayoutUnit>(0, currentRegionOffsetInFlowThread - offsetBreakInFlowThread);
+
+    return overrideLogicalContentHeightComputed;
+}
+
+void RenderFlowThread::incrementAutoLogicalHeightRegions()
+{
+    if (!m_autoLogicalHeightRegionsCount)
+        view()->flowThreadController()->incrementFlowThreadsWithAutoLogicalHeightRegions();
+    ++m_autoLogicalHeightRegionsCount;
+}
+
+void RenderFlowThread::decrementAutoLogicalHeightRegions()
+{
+    ASSERT(m_autoLogicalHeightRegionsCount > 0);
+    --m_autoLogicalHeightRegionsCount;
+    if (!m_autoLogicalHeightRegionsCount)
+        view()->flowThreadController()->decrementFlowThreadsWithAutoLogicalHeightRegions();
+}
+
+void RenderFlowThread::collectLayerFragments(LayerFragments& layerFragments, const LayoutRect& layerBoundingBox, const LayoutRect& dirtyRect)
+{
+    ASSERT(!m_regionsInvalidated);
+    
+    for (RenderRegionList::const_iterator iter = m_regionList.begin(); iter != m_regionList.end(); ++iter) {
+        RenderRegion* region = *iter;
+        region->collectLayerFragments(layerFragments, layerBoundingBox, dirtyRect);
+    }
+}
+
+LayoutRect RenderFlowThread::fragmentsBoundingBox(const LayoutRect& layerBoundingBox)
+{
+    ASSERT(!m_regionsInvalidated);
+    
+    LayoutRect result;
+    for (RenderRegionList::const_iterator iter = m_regionList.begin(); iter != m_regionList.end(); ++iter) {
+        RenderRegion* region = *iter;
+        LayerFragments fragments;
+        region->collectLayerFragments(fragments, layerBoundingBox, PaintInfo::infiniteRect());
+        for (size_t i = 0; i < fragments.size(); ++i) {
+            const LayerFragment& fragment = fragments.at(i);
+            LayoutRect fragmentRect(layerBoundingBox);
+            fragmentRect.intersect(fragment.paginationClip);
+            fragmentRect.moveBy(fragment.paginationOffset);
+            result.unite(fragmentRect);
+        }
+    }
+    
+    return result;
+}
+
+void RenderFlowThread::RegionSearchAdapter::collectIfNeeded(const RegionInterval& interval)
+{
+    if (m_result)
+        return;
+    if (interval.low() <= m_offset && interval.high() > m_offset)
+        m_result = interval.data();
+}
+
+CurrentRenderFlowThreadMaintainer::CurrentRenderFlowThreadMaintainer(RenderFlowThread* renderFlowThread)
+    : m_renderFlowThread(renderFlowThread)
+    , m_previousRenderFlowThread(0)
+{
+    if (!m_renderFlowThread)
+        return;
+    RenderView* view = m_renderFlowThread->view();
+    m_previousRenderFlowThread = view->flowThreadController()->currentRenderFlowThread();
+    ASSERT(!m_previousRenderFlowThread || !renderFlowThread->isRenderNamedFlowThread());
+    view->flowThreadController()->setCurrentRenderFlowThread(m_renderFlowThread);
+}
+
+CurrentRenderFlowThreadMaintainer::~CurrentRenderFlowThreadMaintainer()
+{
+    if (!m_renderFlowThread)
+        return;
+    RenderView* view = m_renderFlowThread->view();
+    ASSERT(view->flowThreadController()->currentRenderFlowThread() == m_renderFlowThread);
+    view->flowThreadController()->setCurrentRenderFlowThread(m_previousRenderFlowThread);
+}
+
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderFlowThread.h b/Source/core/rendering/RenderFlowThread.h
new file mode 100644
index 0000000..573144c
--- /dev/null
+++ b/Source/core/rendering/RenderFlowThread.h
@@ -0,0 +1,297 @@
+/*
+ * Copyright (C) 2011 Adobe Systems Incorporated. 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 THE COPYRIGHT HOLDER "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 THE COPYRIGHT HOLDER 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 RenderFlowThread_h
+#define RenderFlowThread_h
+
+
+#include "core/rendering/RenderBlock.h"
+#include <wtf/HashCountedSet.h>
+#include <wtf/ListHashSet.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/UnusedParam.h>
+
+namespace WebCore {
+
+struct LayerFragment;
+typedef Vector<LayerFragment, 1> LayerFragments;
+class RenderFlowThread;
+class RenderStyle;
+class RenderRegion;
+
+typedef ListHashSet<RenderRegion*> RenderRegionList;
+
+// RenderFlowThread is used to collect all the render objects that participate in a
+// flow thread. It will also help in doing the layout. However, it will not render
+// directly to screen. Instead, RenderRegion objects will redirect their paint 
+// and nodeAtPoint methods to this object. Each RenderRegion will actually be a viewPort
+// of the RenderFlowThread.
+
+class RenderFlowThread: public RenderBlock {
+public:
+    RenderFlowThread();
+    virtual ~RenderFlowThread() { };
+    
+    virtual bool isRenderFlowThread() const OVERRIDE FINAL { return true; }
+
+    virtual void layout() OVERRIDE FINAL;
+
+    // Always create a RenderLayer for the RenderFlowThread so that we 
+    // can easily avoid drawing the children directly.
+    virtual bool requiresLayer() const OVERRIDE FINAL { return true; }
+    
+    void removeFlowChildInfo(RenderObject*);
+#ifndef NDEBUG
+    bool hasChildInfo(RenderObject* child) const { return child && child->isBox() && m_regionRangeMap.contains(toRenderBox(child)); }
+#endif
+
+    virtual void addRegionToThread(RenderRegion*);
+    virtual void removeRegionFromThread(RenderRegion*);
+    const RenderRegionList& renderRegionList() const { return m_regionList; }
+
+    virtual void updateLogicalWidth() OVERRIDE FINAL;
+    virtual void computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues&) const OVERRIDE;
+
+    void paintFlowThreadPortionInRegion(PaintInfo&, RenderRegion*, LayoutRect flowThreadPortionRect, LayoutRect flowThreadPortionOverflowRect, const LayoutPoint&) const;
+    bool hitTestFlowThreadPortionInRegion(RenderRegion*, LayoutRect flowThreadPortionRect, LayoutRect flowThreadPortionOverflowRect, const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset) const;
+
+    bool hasRegions() const { return m_regionList.size(); }
+    // Check if the content is flown into at least a region with region styling rules.
+    bool hasRegionsWithStyling() const { return m_hasRegionsWithStyling; }
+    void checkRegionsWithStyling();
+
+    void validateRegions();
+    void invalidateRegions();
+    bool hasValidRegionInfo() const { return !m_regionsInvalidated && !m_regionList.isEmpty(); }
+
+    static PassRefPtr<RenderStyle> createFlowThreadStyle(RenderStyle* parentStyle);
+
+    void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+
+    void repaintRectangleInRegions(const LayoutRect&) const;
+
+    LayoutUnit pageLogicalTopForOffset(LayoutUnit);
+    LayoutUnit pageLogicalWidthForOffset(LayoutUnit);
+    LayoutUnit pageLogicalHeightForOffset(LayoutUnit);
+    LayoutUnit pageRemainingLogicalHeightForOffset(LayoutUnit, PageBoundaryRule = IncludePageBoundary);
+    
+    enum RegionAutoGenerationPolicy {
+        AllowRegionAutoGeneration,
+        DisallowRegionAutoGeneration,
+    };
+    RenderRegion* regionAtBlockOffset(LayoutUnit, bool extendLastRegion = false, RegionAutoGenerationPolicy = AllowRegionAutoGeneration);
+
+    bool regionsHaveUniformLogicalWidth() const { return m_regionsHaveUniformLogicalWidth; }
+    bool regionsHaveUniformLogicalHeight() const { return m_regionsHaveUniformLogicalHeight; }
+
+    RenderRegion* mapFromFlowToRegion(TransformState&) const;
+
+    void removeRenderBoxRegionInfo(RenderBox*);
+    bool logicalWidthChangedInRegions(const RenderBlock*, LayoutUnit offsetFromLogicalTopOfFirstPage);
+
+    LayoutUnit contentLogicalWidthOfFirstRegion() const;
+    LayoutUnit contentLogicalHeightOfFirstRegion() const;
+    LayoutUnit contentLogicalLeftOfFirstRegion() const;
+    
+    RenderRegion* firstRegion() const;
+    RenderRegion* lastRegion() const;
+
+    void setRegionRangeForBox(const RenderBox*, LayoutUnit offsetFromLogicalTopOfFirstPage);
+    void getRegionRangeForBox(const RenderBox*, RenderRegion*& startRegion, RenderRegion*& endRegion) const;
+
+    void clearRenderObjectCustomStyle(const RenderObject*,
+        const RenderRegion* oldStartRegion = 0, const RenderRegion* oldEndRegion = 0,
+        const RenderRegion* newStartRegion = 0, const RenderRegion* newEndRegion = 0);
+    
+    void computeOverflowStateForRegions(LayoutUnit oldClientAfterEdge);
+
+    bool overset() const { return m_overset; }
+
+    // Check if the object is in region and the region is part of this flow thread.
+    bool objectInFlowRegion(const RenderObject*, const RenderRegion*) const;
+
+    void markAutoLogicalHeightRegionsForLayout();
+
+    bool addForcedRegionBreak(LayoutUnit, RenderObject* breakChild, bool isBefore, LayoutUnit* offsetBreakAdjustment = 0);
+    void applyBreakAfterContent(LayoutUnit);
+
+    bool pageLogicalSizeChanged() const { return m_pageLogicalSizeChanged; }
+
+    bool hasAutoLogicalHeightRegions() const { ASSERT(isAutoLogicalHeightRegionsCountConsistent()); return m_autoLogicalHeightRegionsCount; }
+    void incrementAutoLogicalHeightRegions();
+    void decrementAutoLogicalHeightRegions();
+
+#ifndef NDEBUG
+    bool isAutoLogicalHeightRegionsCountConsistent() const;
+#endif
+
+    void collectLayerFragments(LayerFragments&, const LayoutRect& layerBoundingBox, const LayoutRect& dirtyRect);
+    LayoutRect fragmentsBoundingBox(const LayoutRect& layerBoundingBox);
+
+    void setInConstrainedLayoutPhase(bool value) { m_inConstrainedLayoutPhase = value; }
+    bool inConstrainedLayoutPhase() const { return m_inConstrainedLayoutPhase; }
+
+    bool needsTwoPhasesLayout() const { return m_needsTwoPhasesLayout; }
+    void clearNeedsTwoPhasesLayout() { m_needsTwoPhasesLayout = false; }
+
+protected:
+    virtual const char* renderName() const = 0;
+
+    // Overridden by columns/pages to set up an initial logical width of the page width even when
+    // no regions have been generated yet.
+    virtual LayoutUnit initialLogicalWidth() const { return 0; };
+
+    void updateRegionsFlowThreadPortionRect(const RenderRegion* = 0);
+    bool shouldRepaint(const LayoutRect&) const;
+    bool regionInRange(const RenderRegion* targetRegion, const RenderRegion* startRegion, const RenderRegion* endRegion) const;
+
+    LayoutRect computeRegionClippingRect(const LayoutPoint&, const LayoutRect&, const LayoutRect&) const;
+
+    void setDispatchRegionLayoutUpdateEvent(bool value) { m_dispatchRegionLayoutUpdateEvent = value; }
+    bool shouldDispatchRegionLayoutUpdateEvent() { return m_dispatchRegionLayoutUpdateEvent; }
+    
+    // Override if the flow thread implementation supports dispatching events when the flow layout is updated (e.g. for named flows)
+    virtual void dispatchRegionLayoutUpdateEvent() { m_dispatchRegionLayoutUpdateEvent = false; }
+
+    void initializeRegionsOverrideLogicalContentHeight(RenderRegion* = 0);
+
+    virtual void autoGenerateRegionsToBlockOffset(LayoutUnit) { };
+
+    RenderRegionList m_regionList;
+
+    class RenderRegionRange {
+    public:
+        RenderRegionRange()
+        {
+            setRange(0, 0);
+        }
+
+        RenderRegionRange(RenderRegion* start, RenderRegion* end)
+        {
+            setRange(start, end);
+        }
+        
+        void setRange(RenderRegion* start, RenderRegion* end)
+        {
+            m_startRegion = start;
+            m_endRegion = end;
+        }
+
+        RenderRegion* startRegion() const { return m_startRegion; }
+        RenderRegion* endRegion() const { return m_endRegion; }
+
+    private:
+        RenderRegion* m_startRegion;
+        RenderRegion* m_endRegion;
+    };
+
+    typedef PODInterval<LayoutUnit, RenderRegion*> RegionInterval;
+    typedef PODIntervalTree<LayoutUnit, RenderRegion*> RegionIntervalTree;
+
+    class RegionSearchAdapter {
+    public:
+        RegionSearchAdapter(LayoutUnit offset)
+            : m_offset(offset)
+            , m_result(0)
+        {
+        }
+
+        const LayoutUnit& lowValue() const { return m_offset; }
+        const LayoutUnit& highValue() const { return m_offset; }
+        void collectIfNeeded(const RegionInterval&);
+
+        RenderRegion* result() const { return m_result; }
+
+    private:
+        LayoutUnit m_offset;
+        RenderRegion* m_result;
+    };
+
+    // A maps from RenderBox
+    typedef HashMap<const RenderBox*, RenderRegionRange> RenderRegionRangeMap;
+    RenderRegionRangeMap m_regionRangeMap;
+
+    typedef HashMap<RenderObject*, RenderRegion*> RenderObjectToRegionMap;
+    RenderObjectToRegionMap m_breakBeforeToRegionMap;
+    RenderObjectToRegionMap m_breakAfterToRegionMap;
+
+    unsigned m_autoLogicalHeightRegionsCount;
+
+    RegionIntervalTree m_regionIntervalTree;
+
+    bool m_regionsInvalidated : 1;
+    bool m_regionsHaveUniformLogicalWidth : 1;
+    bool m_regionsHaveUniformLogicalHeight : 1;
+    bool m_overset : 1;
+    bool m_hasRegionsWithStyling : 1;
+    bool m_dispatchRegionLayoutUpdateEvent : 1;
+    bool m_pageLogicalSizeChanged : 1;
+    bool m_inConstrainedLayoutPhase : 1;
+    bool m_needsTwoPhasesLayout : 1;
+};
+
+inline RenderFlowThread* toRenderFlowThread(RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isRenderFlowThread());
+    return static_cast<RenderFlowThread*>(object);
+}
+
+inline const RenderFlowThread* toRenderFlowThread(const RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isRenderFlowThread());
+    return static_cast<const RenderFlowThread*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderFlowThread(const RenderFlowThread*);
+
+class CurrentRenderFlowThreadMaintainer {
+    WTF_MAKE_NONCOPYABLE(CurrentRenderFlowThreadMaintainer);
+public:
+    CurrentRenderFlowThreadMaintainer(RenderFlowThread*);
+    ~CurrentRenderFlowThreadMaintainer();
+private:
+    RenderFlowThread* m_renderFlowThread;
+    RenderFlowThread* m_previousRenderFlowThread;
+};
+
+// These structures are used by PODIntervalTree for debugging.
+#ifndef NDEBUG
+template <> struct ValueToString<LayoutUnit> {
+    static String string(const LayoutUnit value) { return String::number(value.toFloat()); }
+};
+
+template <> struct ValueToString<RenderRegion*> {
+    static String string(const RenderRegion* value) { return String::format("%p", value); }
+};
+#endif
+
+} // namespace WebCore
+
+#endif // RenderFlowThread_h
diff --git a/Source/core/rendering/RenderFrame.cpp b/Source/core/rendering/RenderFrame.cpp
new file mode 100644
index 0000000..a4219d6
--- /dev/null
+++ b/Source/core/rendering/RenderFrame.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 2000 Simon Hausmann <hausmann@kde.org>
+ *           (C) 2000 Stefan Schimanski (1Stein@gmx.de)
+ * Copyright (C) 2004, 2005, 2006, 2009 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 "core/rendering/RenderFrame.h"
+
+#include "core/html/HTMLFrameElement.h"
+#include "core/page/FrameView.h"
+#include "core/rendering/RenderView.h"
+
+namespace WebCore {
+
+RenderFrame::RenderFrame(HTMLFrameElement* frame)
+    : RenderFrameBase(frame)
+{
+    setInline(false);
+}
+
+FrameEdgeInfo RenderFrame::edgeInfo() const
+{
+    HTMLFrameElement* element = static_cast<HTMLFrameElement*>(node());
+    return FrameEdgeInfo(element->noResize(), element->hasFrameBorder());
+}
+
+void RenderFrame::updateFromElement()
+{
+    if (parent() && parent()->isFrameSet())
+        toRenderFrameSet(parent())->notifyFrameEdgeInfoChanged();
+}
+
+void RenderFrame::viewCleared()
+{
+    HTMLFrameElement* element = static_cast<HTMLFrameElement*>(node());
+    if (!element || !widget() || !widget()->isFrameView())
+        return;
+
+    FrameView* view = toFrameView(widget());
+
+    int marginWidth = element->marginWidth();
+    int marginHeight = element->marginHeight();
+
+    if (marginWidth != -1)
+        view->setMarginWidth(marginWidth);
+    if (marginHeight != -1)
+        view->setMarginHeight(marginHeight);
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderFrame.h b/Source/core/rendering/RenderFrame.h
new file mode 100644
index 0000000..dd2c483
--- /dev/null
+++ b/Source/core/rendering/RenderFrame.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 2000 Simon Hausmann <hausmann@kde.org>
+ * Copyright (C) 2006, 2009 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 RenderFrame_h
+#define RenderFrame_h
+
+#include "core/rendering/RenderFrameBase.h"
+#include "core/rendering/RenderFrameSet.h"
+
+namespace WebCore {
+
+class HTMLFrameElement;
+
+class RenderFrame FINAL : public RenderFrameBase {
+public:
+    explicit RenderFrame(HTMLFrameElement*);
+
+    FrameEdgeInfo edgeInfo() const;
+
+private:
+    virtual const char* renderName() const { return "RenderFrame"; }
+    virtual bool isFrame() const { return true; }
+
+    virtual void updateFromElement();
+
+    virtual void viewCleared();
+};
+
+inline RenderFrame* toRenderFrame(RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isFrame());
+    return static_cast<RenderFrame*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderFrame(const RenderFrame*);
+
+} // namespace WebCore
+
+#endif // RenderFrame_h
diff --git a/Source/core/rendering/RenderFrameBase.cpp b/Source/core/rendering/RenderFrameBase.cpp
new file mode 100644
index 0000000..ca922ac
--- /dev/null
+++ b/Source/core/rendering/RenderFrameBase.cpp
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2010 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 "core/rendering/RenderFrameBase.h"
+
+#include "core/html/HTMLFrameElementBase.h"
+#include "core/page/Frame.h"
+#include "core/page/FrameView.h"
+#include "core/rendering/RenderView.h"
+
+namespace WebCore {
+    
+RenderFrameBase::RenderFrameBase(Element* element)
+    : RenderPart(element)
+{
+}
+
+inline bool shouldExpandFrame(LayoutUnit width, LayoutUnit height, bool hasFixedWidth, bool hasFixedHeight)
+{
+    // If the size computed to zero never expand.
+    if (!width || !height)
+        return false;
+    // Really small fixed size frames can't be meant to be scrolled and are there probably by mistake. Avoid expanding.
+    static unsigned smallestUsefullyScrollableDimension = 8;
+    if (hasFixedWidth && width < LayoutUnit(smallestUsefullyScrollableDimension))
+        return false;
+    if (hasFixedHeight && height < LayoutUnit(smallestUsefullyScrollableDimension))
+        return false;
+    return true;
+}
+
+void RenderFrameBase::layoutWithFlattening(bool hasFixedWidth, bool hasFixedHeight)
+{
+    FrameView* childFrameView = toFrameView(widget());
+    RenderView* childRoot = childFrameView ? childFrameView->frame()->contentRenderer() : 0;
+
+    if (!childRoot || !shouldExpandFrame(width(), height(), hasFixedWidth, hasFixedHeight)) {
+        updateWidgetPosition();
+        if (childFrameView)
+            childFrameView->layout();
+        setNeedsLayout(false);
+        return;
+    }
+
+    // need to update to calculate min/max correctly
+    updateWidgetPosition();
+
+    // if scrollbars are off, and the width or height are fixed
+    // we obey them and do not expand. With frame flattening
+    // no subframe much ever become scrollable.
+
+    HTMLFrameElementBase* element = static_cast<HTMLFrameElementBase*>(node());
+    bool isScrollable = element->scrollingMode() != ScrollbarAlwaysOff;
+
+    // consider iframe inset border
+    int hBorder = borderLeft() + borderRight();
+    int vBorder = borderTop() + borderBottom();
+
+    // make sure minimum preferred width is enforced
+    if (isScrollable || !hasFixedWidth) {
+        setWidth(max(width(), childRoot->minPreferredLogicalWidth() + hBorder));
+        // update again to pass the new width to the child frame
+        updateWidgetPosition();
+        childFrameView->layout();
+    }
+
+    // expand the frame by setting frame height = content height
+    if (isScrollable || !hasFixedHeight || childRoot->isFrameSet())
+        setHeight(max<LayoutUnit>(height(), childFrameView->contentsHeight() + vBorder));
+    if (isScrollable || !hasFixedWidth || childRoot->isFrameSet())
+        setWidth(max<LayoutUnit>(width(), childFrameView->contentsWidth() + hBorder));
+
+    updateWidgetPosition();
+
+    ASSERT(!childFrameView->layoutPending());
+    ASSERT(!childRoot->needsLayout());
+    ASSERT(!childRoot->firstChild() || !childRoot->firstChild()->firstChild() || !childRoot->firstChild()->firstChild()->needsLayout());
+
+    setNeedsLayout(false);
+}
+
+}
diff --git a/Source/core/rendering/RenderFrameBase.h b/Source/core/rendering/RenderFrameBase.h
new file mode 100644
index 0000000..2b38b67
--- /dev/null
+++ b/Source/core/rendering/RenderFrameBase.h
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2010 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 RenderFrameBase_h
+#define RenderFrameBase_h
+
+#include "core/rendering/RenderPart.h"
+
+namespace WebCore {
+
+// Base class for RenderFrame and RenderIFrame
+class RenderFrameBase : public RenderPart {
+protected:
+    explicit RenderFrameBase(Element*);
+
+public:
+    void layoutWithFlattening(bool fixedWidth, bool fixedHeight);
+};
+
+} // namespace WebCore
+
+#endif // RenderFrameBase_h
diff --git a/Source/core/rendering/RenderFrameSet.cpp b/Source/core/rendering/RenderFrameSet.cpp
new file mode 100644
index 0000000..c10093f
--- /dev/null
+++ b/Source/core/rendering/RenderFrameSet.cpp
@@ -0,0 +1,818 @@
+/**
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 2000 Simon Hausmann <hausmann@kde.org>
+ *           (C) 2000 Stefan Schimanski (1Stein@gmx.de)
+ * 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 "core/rendering/RenderFrameSet.h"
+
+#include "core/dom/Document.h"
+#include "core/dom/EventNames.h"
+#include "core/dom/MouseEvent.h"
+#include "core/dom/WebCoreMemoryInstrumentation.h"
+#include "core/html/HTMLFrameSetElement.h"
+#include "core/page/EventHandler.h"
+#include "core/page/Frame.h"
+#include "core/page/FrameView.h"
+#include "core/page/Settings.h"
+#include "core/platform/Cursor.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/rendering/HitTestRequest.h"
+#include "core/rendering/HitTestResult.h"
+#include "core/rendering/PaintInfo.h"
+#include "core/rendering/RenderFrame.h"
+#include "core/rendering/RenderLayer.h"
+#include "core/rendering/RenderView.h"
+#include <wtf/MemoryInstrumentationVector.h>
+
+namespace WebCore {
+
+RenderFrameSet::RenderFrameSet(HTMLFrameSetElement* frameSet)
+    : RenderBox(frameSet)
+    , m_isResizing(false)
+    , m_isChildResizing(false)
+{
+    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;
+    ColorSpace colorSpace = style()->colorSpace();
+    context->fillRect(borderRect, frameSet()->hasBorderColor() ? style()->visitedDependentColor(CSSPropertyBorderLeftColor) : borderFillColor(), colorSpace);
+    
+    // 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.location(), IntSize(1, height())), borderStartEdgeColor(), colorSpace);
+        context->fillRect(IntRect(IntPoint(borderRect.maxX() - 1, borderRect.y()), IntSize(1, height())), borderEndEdgeColor(), colorSpace);
+    }
+}
+
+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;
+    ColorSpace colorSpace = style()->colorSpace();
+    context->fillRect(borderRect, frameSet()->hasBorderColor() ? style()->visitedDependentColor(CSSPropertyBorderLeftColor) : borderFillColor(), colorSpace);
+
+    // 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.location(), IntSize(width(), 1)), borderStartEdgeColor(), colorSpace);
+        context->fillRect(IntRect(IntPoint(borderRect.x(), borderRect.maxY() - 1), IntSize(width(), 1)), borderEndEdgeColor(), colorSpace);
+    }
+}
+
+void RenderFrameSet::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    if (paintInfo.phase != PaintPhaseForeground)
+        return;
+    
+    RenderObject* child = firstChild();
+    if (!child)
+        return;
+
+    LayoutPoint adjustedPaintOffset = paintOffset + location();
+
+    size_t rows = m_rows.m_sizes.size();
+    size_t cols = m_cols.m_sizes.size();
+    LayoutUnit borderThickness = frameSet()->border();
+    
+    LayoutUnit yPos = 0;
+    for (size_t r = 0; r < rows; r++) {
+        LayoutUnit xPos = 0;
+        for (size_t c = 0; c < cols; c++) {
+            child->paint(paintInfo, adjustedPaintOffset);
+            xPos += m_cols.m_sizes[c];
+            if (borderThickness && m_cols.m_allowBorder[c + 1]) {
+                paintColumnBorder(paintInfo, pixelSnappedIntRect(LayoutRect(adjustedPaintOffset.x() + xPos, adjustedPaintOffset.y() + 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, pixelSnappedIntRect(LayoutRect(adjustedPaintOffset.x(), adjustedPaintOffset.y() + yPos, width(), borderThickness)));
+            yPos += borderThickness;
+        }
+    }
+}
+
+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].intValue(), 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(intValueForLength(grid[i], 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].intValue(), 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].intValue(), 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;
+            }
+        }
+    } else if (remainingLen && countFixed) {
+        // If we don't have any percentage columns/rows we only have
+        // fixed columns. Spread the remainder equally over all fixed
+        // columns/rows.
+        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::notifyFrameEdgeInfoChanged()
+{
+    if (needsLayout())
+        return;
+    // FIXME: We should only recompute the edge info with respect to the frame that changed
+    // and its adjacent frame(s) instead of recomputing the edge info for the entire frameset.
+    computeEdgeInfo();
+}
+
+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;
+
+    size_t rows = m_rows.m_sizes.size();
+    size_t cols = m_cols.m_sizes.size();
+    for (size_t r = 0; r < rows; ++r) {
+        for (size_t c = 0; c < cols; ++c) {
+            FrameEdgeInfo edgeInfo;
+            if (child->isFrameSet())
+                edgeInfo = toRenderFrameSet(child)->edgeInfo();
+            else
+                edgeInfo = toRenderFrame(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()
+{
+    StackStats::LayoutCheckPoint layoutCheckPoint;
+    ASSERT(needsLayout());
+
+    bool doFullRepaint = selfNeedsLayout() && checkForRepaintDuringLayout();
+    LayoutRect oldBounds;
+    RenderLayerModelObject* repaintContainer = 0;
+    if (doFullRepaint) {
+        repaintContainer = containerForRepaint();
+        oldBounds = clippedOverflowRectForRepaint(repaintContainer);
+    }
+
+    if (!parent()->isFrameSet() && !document()->printing()) {
+        setWidth(view()->viewWidth());
+        setHeight(view()->viewHeight());
+    }
+
+    unsigned cols = frameSet()->totalCols();
+    unsigned rows = frameSet()->totalRows();
+
+    if (m_rows.m_sizes.size() != rows || m_cols.m_sizes.size() != cols) {
+        m_rows.resize(rows);
+        m_cols.resize(cols);
+    }
+
+    LayoutUnit borderThickness = frameSet()->border();
+    layOutAxis(m_rows, frameSet()->rowLengths(), height() - (rows - 1) * borderThickness);
+    layOutAxis(m_cols, frameSet()->colLengths(), width() - (cols - 1) * borderThickness);
+
+    if (flattenFrameSet())
+        positionFramesWithFlattening();
+    else
+        positionFrames();
+
+    RenderBox::layout();
+
+    computeEdgeInfo();
+
+    updateLayerTransform();
+
+    if (doFullRepaint) {
+        repaintUsingContainer(repaintContainer, pixelSnappedIntRect(oldBounds));
+        LayoutRect newBounds = clippedOverflowRectForRepaint(repaintContainer);
+        if (newBounds != oldBounds)
+            repaintUsingContainer(repaintContainer, pixelSnappedIntRect(newBounds));
+    }
+
+    setNeedsLayout(false);
+}
+
+void RenderFrameSet::positionFrames()
+{
+    RenderBox* child = firstChildBox();
+    if (!child)
+        return;
+
+    int rows = frameSet()->totalRows();
+    int cols = frameSet()->totalCols();
+
+    int yPos = 0;
+    int borderThickness = frameSet()->border();
+    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->setLocation(IntPoint(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->nextSiblingBox();
+            if (!child)
+                return;
+        }
+        yPos += height + borderThickness;
+    }
+
+    // all the remaining frames are hidden to avoid ugly spurious unflowed frames
+    for (; child; child = child->nextSiblingBox()) {
+        child->setWidth(0);
+        child->setHeight(0);
+        child->setNeedsLayout(false);
+    }
+}
+
+void RenderFrameSet::positionFramesWithFlattening()
+{
+    RenderBox* child = firstChildBox();
+    if (!child)
+        return;
+
+    int rows = frameSet()->totalRows();
+    int cols = frameSet()->totalCols();
+
+    int borderThickness = frameSet()->border();
+    bool repaintNeeded = false;
+
+    // calculate frameset height based on actual content height to eliminate scrolling
+    bool out = false;
+    for (int r = 0; r < rows && !out; r++) {
+        int extra = 0;
+        int height = m_rows.m_sizes[r];
+
+        for (int c = 0; c < cols; c++) {
+            IntRect oldFrameRect = pixelSnappedIntRect(child->frameRect());
+
+            int width = m_cols.m_sizes[c];
+
+            bool fixedWidth = frameSet()->colLengths() && frameSet()->colLengths()[c].isFixed();
+            bool fixedHeight = frameSet()->rowLengths() && frameSet()->rowLengths()[r].isFixed();
+
+            // has to be resized and itself resize its contents
+            if (!fixedWidth)
+                child->setWidth(width ? width + extra / (cols - c) : 0);
+            else
+                child->setWidth(width);
+            child->setHeight(height);
+
+            child->setNeedsLayout(true);
+
+            if (child->isFrameSet())
+                toRenderFrameSet(child)->layout();
+            else
+                toRenderFrame(child)->layoutWithFlattening(fixedWidth, fixedHeight);
+
+            if (child->height() > m_rows.m_sizes[r])
+                m_rows.m_sizes[r] = child->height();
+            if (child->width() > m_cols.m_sizes[c])
+                m_cols.m_sizes[c] = child->width();
+
+            if (child->frameRect() != oldFrameRect)
+                repaintNeeded = true;
+
+            // difference between calculated frame width and the width it actually decides to have
+            extra += width - m_cols.m_sizes[c];
+
+            child = child->nextSiblingBox();
+            if (!child) {
+                out = true;
+                break;
+            }
+        }
+    }
+
+    int xPos = 0;
+    int yPos = 0;
+    out = false;
+    child = firstChildBox();
+    for (int r = 0; r < rows && !out; r++) {
+        xPos = 0;
+        for (int c = 0; c < cols; c++) {
+            // ensure the rows and columns are filled
+            IntRect oldRect = pixelSnappedIntRect(child->frameRect());
+
+            child->setLocation(IntPoint(xPos, yPos));
+            child->setHeight(m_rows.m_sizes[r]);
+            child->setWidth(m_cols.m_sizes[c]);
+
+            if (child->frameRect() != oldRect) {
+                repaintNeeded = true;
+
+                // update to final size
+                child->setNeedsLayout(true);
+                if (child->isFrameSet())
+                    toRenderFrameSet(child)->layout();
+                else
+                    toRenderFrame(child)->layoutWithFlattening(true, true);
+            }
+
+            xPos += m_cols.m_sizes[c] + borderThickness;
+            child = child->nextSiblingBox();
+            if (!child) {
+                out = true;
+                break;
+            }
+        }
+        yPos += m_rows.m_sizes[r] + borderThickness;
+    }
+
+    setWidth(xPos - borderThickness);
+    setHeight(yPos - borderThickness);
+
+    if (repaintNeeded)
+        repaint();
+
+    // all the remaining frames are hidden to avoid ugly spurious unflowed frames
+    for (; child; child = child->nextSiblingBox()) {
+        child->setWidth(0);
+        child->setHeight(0);
+        child->setNeedsLayout(false);
+    }
+}
+
+bool RenderFrameSet::flattenFrameSet() const
+{
+    return frame() && frame()->settings() && frame()->settings()->frameFlatteningEnabled();
+}
+
+void RenderFrameSet::startResizing(GridAxis& axis, int position)
+{
+    int split = hitTestSplit(axis, position);
+    if (split == noSplit || 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)
+        return;
+    axis.m_deltas[axis.m_splitBeingResized - 1] += delta;
+    axis.m_deltas[axis.m_splitBeingResized] -= delta;
+    setNeedsLayout(true);
+}
+
+bool RenderFrameSet::userResize(MouseEvent* evt)
+{
+    if (flattenFrameSet())
+        return false;
+
+    if (!m_isResizing) {
+        if (needsLayout())
+            return false;
+        if (evt->type() == eventNames().mousedownEvent && evt->button() == LeftButton) {
+            FloatPoint localPos = absoluteToLocal(evt->absoluteLocation(), UseTransforms);
+            startResizing(m_cols, localPos.x());
+            startResizing(m_rows, localPos.y());
+            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)) {
+            FloatPoint localPos = absoluteToLocal(evt->absoluteLocation(), UseTransforms);
+            continueResizing(m_cols, localPos.x());
+            continueResizing(m_rows, localPos.y());
+            if (evt->type() == eventNames().mouseupEvent && evt->button() == LeftButton) {
+                setIsResizing(false);
+                return true;
+            }
+        }
+    }
+
+    return false;
+}
+
+void RenderFrameSet::setIsResizing(bool isResizing)
+{
+    m_isResizing = isResizing;
+    for (RenderObject* ancestor = parent(); ancestor; ancestor = ancestor->parent()) {
+        if (ancestor->isFrameSet())
+            toRenderFrameSet(ancestor)->m_isChildResizing = isResizing;
+    }
+    if (Frame* frame = this->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::canResizeRow(const IntPoint& p) const
+{
+    int r = hitTestSplit(m_rows, p.y());
+    return r != noSplit && !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_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*) const
+{
+    return child->isFrame() || child->isFrameSet();
+}
+
+CursorDirective RenderFrameSet::getCursor(const LayoutPoint& point, Cursor& cursor) const
+{
+    IntPoint roundedPoint = roundedIntPoint(point);
+    if (canResizeRow(roundedPoint)) {
+        cursor = rowResizeCursor();
+        return SetCursor;
+    }
+    if (canResizeColumn(roundedPoint)) {
+        cursor = columnResizeCursor();
+        return SetCursor;
+    }
+    return RenderBox::getCursor(point, cursor);
+}
+
+void RenderFrameSet::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, PlatformMemoryTypes::Rendering);
+    RenderBox::reportMemoryUsage(memoryObjectInfo);
+    info.addMember(m_children, "children");
+    info.addMember(m_rows, "rows");
+    info.addMember(m_cols, "cols");
+}
+
+void RenderFrameSet::GridAxis::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, PlatformMemoryTypes::Rendering);
+    info.addMember(m_sizes, "sizes");
+    info.addMember(m_deltas, "deltas");
+    info.addMember(m_preventResize, "preventResize");
+    info.addMember(m_allowBorder, "allowBorder");
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderFrameSet.h b/Source/core/rendering/RenderFrameSet.h
new file mode 100644
index 0000000..ac9b55e
--- /dev/null
+++ b/Source/core/rendering/RenderFrameSet.h
@@ -0,0 +1,153 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 2000 Simon Hausmann <hausmann@kde.org>
+ * 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 "core/rendering/RenderBox.h"
+
+namespace WebCore {
+
+class HTMLFrameSetElement;
+class MouseEvent;
+class RenderFrame;
+
+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 FINAL : public RenderBox {
+public:
+    RenderFrameSet(HTMLFrameSetElement*);
+    virtual ~RenderFrameSet();
+
+    RenderObject* firstChild() const { ASSERT(children() == virtualChildren()); return children()->firstChild(); }
+    RenderObject* lastChild() const { ASSERT(children() == virtualChildren()); return children()->lastChild(); }
+
+    const RenderObjectChildList* children() const { return &m_children; }
+    RenderObjectChildList* children() { return &m_children; }
+
+    FrameEdgeInfo edgeInfo() const;
+
+    bool userResize(MouseEvent*);
+
+    bool isResizingRow() const;
+    bool isResizingColumn() const;
+
+    bool canResizeRow(const IntPoint&) const;
+    bool canResizeColumn(const IntPoint&) const;
+
+    void notifyFrameEdgeInfoChanged();
+
+    virtual void reportMemoryUsage(MemoryObjectInfo*) const OVERRIDE;
+
+private:
+    static const int noSplit = -1;
+
+    class GridAxis {
+        WTF_MAKE_NONCOPYABLE(GridAxis);
+    public:
+        GridAxis();
+        void resize(int);
+
+        void reportMemoryUsage(MemoryObjectInfo*) const;
+
+        Vector<int> m_sizes;
+        Vector<int> m_deltas;
+        Vector<bool> m_preventResize;
+        Vector<bool> m_allowBorder;
+        int m_splitBeingResized;
+        int m_splitResizeOffset;
+    };
+
+    virtual RenderObjectChildList* virtualChildren() { return children(); }
+    virtual const RenderObjectChildList* virtualChildren() const { return children(); }
+
+    virtual const char* renderName() const { return "RenderFrameSet"; }
+    virtual bool isFrameSet() const { return true; }
+
+    virtual void layout();
+    virtual void paint(PaintInfo&, const LayoutPoint&);
+    virtual bool isChildAllowed(RenderObject*, RenderStyle*) const;
+    virtual CursorDirective getCursor(const LayoutPoint&, Cursor&) const;
+
+    inline HTMLFrameSetElement* frameSet() const;
+
+    bool flattenFrameSet() const;
+
+    void setIsResizing(bool);
+
+    void layOutAxis(GridAxis&, const Length*, int availableSpace);
+    void computeEdgeInfo();
+    void fillFromEdgeInfo(const FrameEdgeInfo& edgeInfo, int r, int c);
+    void positionFrames();
+    void positionFramesWithFlattening();
+
+    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&, const IntRect&);
+    void paintColumnBorder(const PaintInfo&, const IntRect&);
+
+    RenderObjectChildList m_children;
+
+    GridAxis m_rows;
+    GridAxis m_cols;
+
+    bool m_isResizing;
+    bool m_isChildResizing;
+};
+
+
+inline RenderFrameSet* toRenderFrameSet(RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isFrameSet());
+    return static_cast<RenderFrameSet*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderFrameSet(const RenderFrameSet*);
+
+} // namespace WebCore
+
+#endif // RenderFrameSet_h
diff --git a/Source/core/rendering/RenderFullScreen.cpp b/Source/core/rendering/RenderFullScreen.cpp
new file mode 100644
index 0000000..3e87628
--- /dev/null
+++ b/Source/core/rendering/RenderFullScreen.cpp
@@ -0,0 +1,187 @@
+/*
+ * Copyright (C) 2010 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. 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 INC. 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 "core/rendering/RenderFullScreen.h"
+
+#include "core/rendering/RenderLayer.h"
+#include "core/rendering/RenderLayerCompositor.h"
+
+using namespace WebCore;
+
+class RenderFullScreenPlaceholder FINAL : public RenderBlock {
+public:
+    RenderFullScreenPlaceholder(RenderFullScreen* owner) 
+        : RenderBlock(0)
+        , m_owner(owner) 
+    {
+        setDocumentForAnonymous(owner->document());
+    }
+private:
+    virtual bool isRenderFullScreenPlaceholder() const { return true; }
+    virtual void willBeDestroyed();
+    RenderFullScreen* m_owner;
+};
+
+void RenderFullScreenPlaceholder::willBeDestroyed()
+{
+    m_owner->setPlaceholder(0);
+    RenderBlock::willBeDestroyed();
+}
+
+RenderFullScreen::RenderFullScreen()
+    : RenderFlexibleBox(0)
+    , m_placeholder(0)
+{
+    setReplaced(false); 
+}
+
+RenderFullScreen* RenderFullScreen::createAnonymous(Document* document)
+{
+    RenderFullScreen* renderer = new (document->renderArena()) RenderFullScreen();
+    renderer->setDocumentForAnonymous(document);
+    return renderer;
+}
+
+void RenderFullScreen::willBeDestroyed()
+{
+    if (m_placeholder) {
+        remove();
+        if (!m_placeholder->beingDestroyed())
+            m_placeholder->destroy();
+        ASSERT(!m_placeholder);
+    }
+
+    // RenderObjects are unretained, so notify the document (which holds a pointer to a RenderFullScreen)
+    // if it's RenderFullScreen is destroyed.
+    if (document() && document()->fullScreenRenderer() == this)
+        document()->fullScreenRendererDestroyed();
+
+    RenderFlexibleBox::willBeDestroyed();
+}
+
+static PassRefPtr<RenderStyle> createFullScreenStyle()
+{
+    RefPtr<RenderStyle> fullscreenStyle = RenderStyle::createDefaultStyle();
+
+    // Create a stacking context:
+    fullscreenStyle->setZIndex(INT_MAX);
+
+    fullscreenStyle->setFontDescription(FontDescription());
+    fullscreenStyle->font().update(0);
+
+    fullscreenStyle->setDisplay(FLEX);
+    fullscreenStyle->setJustifyContent(JustifyCenter);
+    fullscreenStyle->setAlignItems(AlignCenter);
+    fullscreenStyle->setFlexDirection(FlowColumn);
+    
+    fullscreenStyle->setPosition(FixedPosition);
+    fullscreenStyle->setWidth(Length(100.0, Percent));
+    fullscreenStyle->setHeight(Length(100.0, Percent));
+    fullscreenStyle->setLeft(Length(0, WebCore::Fixed));
+    fullscreenStyle->setTop(Length(0, WebCore::Fixed));
+    
+    fullscreenStyle->setBackgroundColor(Color::black);
+    
+    return fullscreenStyle.release();
+}
+
+RenderObject* RenderFullScreen::wrapRenderer(RenderObject* object, RenderObject* parent, Document* document)
+{
+    RenderFullScreen* fullscreenRenderer = RenderFullScreen::createAnonymous(document);
+    fullscreenRenderer->setStyle(createFullScreenStyle());
+    if (parent && !parent->isChildAllowed(fullscreenRenderer, fullscreenRenderer->style())) {
+        fullscreenRenderer->destroy();
+        return 0;
+    }
+    if (object) {
+        // |object->parent()| can be null if the object is not yet attached
+        // to |parent|.
+        if (RenderObject* parent = object->parent()) {
+            RenderBlock* containingBlock = object->containingBlock();
+            ASSERT(containingBlock);
+            // Since we are moving the |object| to a new parent |fullscreenRenderer|,
+            // the line box tree underneath our |containingBlock| is not longer valid.
+            containingBlock->deleteLineBoxTree();
+
+            parent->addChild(fullscreenRenderer, object);
+            object->remove();
+            
+            // Always just do a full layout to ensure that line boxes get deleted properly.
+            // Because objects moved from |parent| to |fullscreenRenderer|, we want to
+            // make new line boxes instead of leaving the old ones around.
+            parent->setNeedsLayoutAndPrefWidthsRecalc();
+            containingBlock->setNeedsLayoutAndPrefWidthsRecalc();
+        }
+        fullscreenRenderer->addChild(object);
+        fullscreenRenderer->setNeedsLayoutAndPrefWidthsRecalc();
+    }
+    document->setFullScreenRenderer(fullscreenRenderer);
+    return fullscreenRenderer;
+}
+
+void RenderFullScreen::unwrapRenderer()
+{
+    if (parent()) {
+        RenderObject* child;
+        while ((child = firstChild())) {
+            // We have to clear the override size, because as a flexbox, we
+            // may have set one on the child, and we don't want to leave that
+            // lying around on the child.
+            if (child->isBox())
+                toRenderBox(child)->clearOverrideSize();
+            child->remove();
+            parent()->addChild(child, this);
+            parent()->setNeedsLayoutAndPrefWidthsRecalc();
+        }
+    }
+    if (placeholder())
+        placeholder()->remove();
+    remove();
+    document()->setFullScreenRenderer(0);
+}
+
+void RenderFullScreen::setPlaceholder(RenderBlock* placeholder)
+{
+    m_placeholder = placeholder;
+}
+
+void RenderFullScreen::createPlaceholder(PassRefPtr<RenderStyle> style, const LayoutRect& frameRect)
+{
+    if (style->width().isAuto())
+        style->setWidth(Length(frameRect.width(), Fixed));
+    if (style->height().isAuto())
+        style->setHeight(Length(frameRect.height(), Fixed));
+
+    if (!m_placeholder) {
+        m_placeholder = new (document()->renderArena()) RenderFullScreenPlaceholder(this);
+        m_placeholder->setStyle(style);
+        if (parent()) {
+            parent()->addChild(m_placeholder, this);
+            parent()->setNeedsLayoutAndPrefWidthsRecalc();
+        }
+    } else
+        m_placeholder->setStyle(style);
+}
diff --git a/Source/core/rendering/RenderFullScreen.h b/Source/core/rendering/RenderFullScreen.h
new file mode 100644
index 0000000..6918ef9
--- /dev/null
+++ b/Source/core/rendering/RenderFullScreen.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2010 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. 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 INC. 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 RenderFullScreen_h
+#define RenderFullScreen_h
+
+#include "core/rendering/RenderFlexibleBox.h"
+#include "core/rendering/style/StyleInheritedData.h"
+
+namespace WebCore {
+
+class RenderFullScreen FINAL : public RenderFlexibleBox {
+public:
+    static RenderFullScreen* createAnonymous(Document*);
+
+    virtual bool isRenderFullScreen() const { return true; }
+    virtual const char* renderName() const { return "RenderFullScreen"; }
+
+    void setPlaceholder(RenderBlock*);
+    RenderBlock* placeholder() { return m_placeholder; }
+    void createPlaceholder(PassRefPtr<RenderStyle>, const LayoutRect& frameRect);
+
+
+    static RenderObject* wrapRenderer(RenderObject*, RenderObject*, Document*);
+    void unwrapRenderer();
+
+private:
+    RenderFullScreen();
+    virtual void willBeDestroyed();
+
+protected:
+    RenderBlock* m_placeholder;
+};
+    
+inline RenderFullScreen* toRenderFullScreen(RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(object->isRenderFullScreen());
+    return static_cast<RenderFullScreen*>(object);
+}
+    
+// This will catch anyone doing an unnecessary cast:
+void toRenderFullScreen(RenderFullScreen*);
+}
+
+#endif
diff --git a/Source/core/rendering/RenderGeometryMap.cpp b/Source/core/rendering/RenderGeometryMap.cpp
new file mode 100644
index 0000000..8776f0f
--- /dev/null
+++ b/Source/core/rendering/RenderGeometryMap.cpp
@@ -0,0 +1,308 @@
+/*
+ * Copyright (C) 2012 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 "core/rendering/RenderGeometryMap.h"
+
+#include "core/platform/graphics/transforms/TransformState.h"
+#include "core/rendering/RenderLayer.h"
+#include "core/rendering/RenderView.h"
+#include <wtf/TemporaryChange.h>
+
+namespace WebCore {
+
+RenderGeometryMap::RenderGeometryMap(MapCoordinatesFlags flags)
+    : m_insertionPosition(notFound)
+    , m_nonUniformStepsCount(0)
+    , m_transformedStepsCount(0)
+    , m_fixedStepsCount(0)
+    , m_mapCoordinatesFlags(flags)
+{
+}
+
+RenderGeometryMap::~RenderGeometryMap()
+{
+}
+
+void RenderGeometryMap::mapToContainer(TransformState& transformState, const RenderLayerModelObject* container) const
+{
+    // If the mapping includes something like columns, we have to go via renderers.
+    if (hasNonUniformStep()) {
+        m_mapping.last().m_renderer->mapLocalToContainer(container, transformState, ApplyContainerFlip | m_mapCoordinatesFlags);
+        transformState.flatten();
+        return;
+    }
+    
+    bool inFixed = false;
+#if !ASSERT_DISABLED
+    bool foundContainer = !container || (m_mapping.size() && m_mapping[0].m_renderer == container);
+#endif
+
+    for (int i = m_mapping.size() - 1; i >= 0; --i) {
+        const RenderGeometryMapStep& currentStep = m_mapping[i];
+
+        // If container is the RenderView (step 0) we want to apply its scroll offset.
+        if (i > 0 && currentStep.m_renderer == container) {
+#if !ASSERT_DISABLED
+            foundContainer = true;
+#endif
+            break;
+        }
+
+        // If this box has a transform, it acts as a fixed position container
+        // for fixed descendants, which prevents the propagation of 'fixed'
+        // unless the layer itself is also fixed position.
+        if (i && currentStep.m_hasTransform && !currentStep.m_isFixedPosition)
+            inFixed = false;
+        else if (currentStep.m_isFixedPosition)
+            inFixed = true;
+
+        if (!i) {
+            // A null container indicates mapping through the RenderView, so including its transform (the page scale).
+            if (!container && currentStep.m_transform)
+                transformState.applyTransform(*currentStep.m_transform.get());
+
+            // The root gets special treatment for fixed position
+            if (inFixed)
+                transformState.move(currentStep.m_offset.width(), currentStep.m_offset.height());
+        } else {
+            TransformState::TransformAccumulation accumulate = currentStep.m_accumulatingTransform ? TransformState::AccumulateTransform : TransformState::FlattenTransform;
+            if (currentStep.m_transform)
+                transformState.applyTransform(*currentStep.m_transform.get(), accumulate);
+            else
+                transformState.move(currentStep.m_offset.width(), currentStep.m_offset.height(), accumulate);
+        }
+    }
+
+    ASSERT(foundContainer);
+    transformState.flatten();    
+}
+
+FloatPoint RenderGeometryMap::mapToContainer(const FloatPoint& p, const RenderLayerModelObject* container) const
+{
+    FloatPoint result;
+    
+    if (!hasFixedPositionStep() && !hasTransformStep() && !hasNonUniformStep() && (!container || (m_mapping.size() && container == m_mapping[0].m_renderer)))
+        result = p + roundedIntSize(m_accumulatedOffset);
+    else {
+        TransformState transformState(TransformState::ApplyTransformDirection, p);
+        mapToContainer(transformState, container);
+        result = transformState.lastPlanarPoint();
+    }
+
+#if !ASSERT_DISABLED
+    FloatPoint rendererMappedResult = m_mapping.last().m_renderer->localToAbsolute(p, m_mapCoordinatesFlags);
+    ASSERT(roundedIntPoint(rendererMappedResult) == roundedIntPoint(result));
+//    if (roundedIntPoint(rendererMappedResult) != roundedIntPoint(result))
+//        fprintf(stderr, "Mismatched point\n");
+#endif
+
+    return result;
+}
+
+FloatQuad RenderGeometryMap::mapToContainer(const FloatRect& rect, const RenderLayerModelObject* container) const
+{
+    FloatRect result;
+    
+    if (!hasFixedPositionStep() && !hasTransformStep() && !hasNonUniformStep() && (!container || (m_mapping.size() && container == m_mapping[0].m_renderer))) {
+        result = rect;
+        result.move(m_accumulatedOffset);
+    } else {
+        TransformState transformState(TransformState::ApplyTransformDirection, rect.center(), rect);
+        mapToContainer(transformState, container);
+        result = transformState.lastPlanarQuad().boundingBox();
+    }
+
+#if !ASSERT_DISABLED
+    FloatRect rendererMappedResult = m_mapping.last().m_renderer->localToContainerQuad(rect, container, m_mapCoordinatesFlags).boundingBox();
+    // Inspector creates renderers with negative width <https://bugs.webkit.org/show_bug.cgi?id=87194>.
+    // Taking FloatQuad bounds avoids spurious assertions because of that.
+    ASSERT(enclosingIntRect(rendererMappedResult) == enclosingIntRect(FloatQuad(result).boundingBox()));
+//    if (enclosingIntRect(rendererMappedResult) != enclosingIntRect(FloatQuad(result).boundingBox()))
+//        fprintf(stderr, "Mismatched rects\n");
+#endif
+
+    return result;
+}
+
+void RenderGeometryMap::pushMappingsToAncestor(const RenderObject* renderer, const RenderLayerModelObject* ancestorRenderer)
+{
+    // We need to push mappings in reverse order here, so do insertions rather than appends.
+    TemporaryChange<size_t> positionChange(m_insertionPosition, m_mapping.size());
+    do {
+        renderer = renderer->pushMappingToContainer(ancestorRenderer, *this);
+    } while (renderer && renderer != ancestorRenderer);
+
+    ASSERT(m_mapping.isEmpty() || m_mapping[0].m_renderer->isRenderView());
+}
+
+static bool canMapBetweenRenderers(const RenderObject* renderer, const RenderObject* ancestor)
+{
+    for (const RenderObject* current = renderer; ; current = current->parent()) {
+        const RenderStyle* style = current->style();
+        if (style->position() == FixedPosition || style->isFlippedBlocksWritingMode())
+            return false;
+        
+        if (current->hasColumns() || current->hasTransform() || current->isRenderFlowThread())
+            return false;
+
+    #if ENABLE(SVG)
+        if (current->isSVGRoot())
+            return false;
+    #endif
+        if (current == ancestor)
+            break;
+    }
+
+    return true;
+}
+
+void RenderGeometryMap::pushMappingsToAncestor(const RenderLayer* layer, const RenderLayer* ancestorLayer)
+{
+    const RenderObject* renderer = layer->renderer();
+
+    // We have to visit all the renderers to detect flipped blocks. This might defeat the gains
+    // from mapping via layers.
+    bool canConvertInLayerTree = ancestorLayer ? canMapBetweenRenderers(layer->renderer(), ancestorLayer->renderer()) : false;
+
+//    fprintf(stderr, "RenderGeometryMap::pushMappingsToAncestor from layer %p to layer %p, canConvertInLayerTree=%d\n", layer, ancestorLayer, canConvertInLayerTree);
+
+    if (canConvertInLayerTree) {
+        LayoutPoint layerOffset;
+        layer->convertToLayerCoords(ancestorLayer, layerOffset);
+        
+        // The RenderView must be pushed first.
+        if (!m_mapping.size()) {
+            ASSERT(ancestorLayer->renderer()->isRenderView());
+            pushMappingsToAncestor(ancestorLayer->renderer(), 0);
+        }
+
+        TemporaryChange<size_t> positionChange(m_insertionPosition, m_mapping.size());
+        push(renderer, toLayoutSize(layerOffset), /*accumulatingTransform*/ true, /*isNonUniform*/ false, /*isFixedPosition*/ false, /*hasTransform*/ false);
+        return;
+    }
+    const RenderLayerModelObject* ancestorRenderer = ancestorLayer ? ancestorLayer->renderer() : 0;
+    pushMappingsToAncestor(renderer, ancestorRenderer);
+}
+
+void RenderGeometryMap::push(const RenderObject* renderer, const LayoutSize& offsetFromContainer, bool accumulatingTransform, bool isNonUniform, bool isFixedPosition, bool hasTransform)
+{
+//    fprintf(stderr, "RenderGeometryMap::push %p %d,%d isNonUniform=%d\n", renderer, offsetFromContainer.width().toInt(), offsetFromContainer.height().toInt(), isNonUniform);
+
+    ASSERT(m_insertionPosition != notFound);
+
+    m_mapping.insert(m_insertionPosition, RenderGeometryMapStep(renderer, accumulatingTransform, isNonUniform, isFixedPosition, hasTransform));
+
+    RenderGeometryMapStep& step = m_mapping[m_insertionPosition];
+    step.m_offset = offsetFromContainer;
+
+    stepInserted(step);
+}
+
+void RenderGeometryMap::push(const RenderObject* renderer, const TransformationMatrix& t, bool accumulatingTransform, bool isNonUniform, bool isFixedPosition, bool hasTransform)
+{
+    ASSERT(m_insertionPosition != notFound);
+
+    m_mapping.insert(m_insertionPosition, RenderGeometryMapStep(renderer, accumulatingTransform, isNonUniform, isFixedPosition, hasTransform));
+    
+    RenderGeometryMapStep& step = m_mapping[m_insertionPosition];
+    if (!t.isIntegerTranslation())
+        step.m_transform = adoptPtr(new TransformationMatrix(t));
+    else
+        step.m_offset = LayoutSize(t.e(), t.f());
+
+    stepInserted(step);
+}
+
+void RenderGeometryMap::pushView(const RenderView* view, const LayoutSize& scrollOffset, const TransformationMatrix* t)
+{
+    ASSERT(m_insertionPosition != notFound);
+    ASSERT(!m_insertionPosition); // The view should always be the first step.
+
+    m_mapping.insert(m_insertionPosition, RenderGeometryMapStep(view, false, false, false, t));
+    
+    RenderGeometryMapStep& step = m_mapping[m_insertionPosition];
+    step.m_offset = scrollOffset;
+    if (t)
+        step.m_transform = adoptPtr(new TransformationMatrix(*t));
+    
+    stepInserted(step);
+}
+
+void RenderGeometryMap::popMappingsToAncestor(const RenderLayerModelObject* ancestorRenderer)
+{
+    ASSERT(m_mapping.size());
+
+    while (m_mapping.size() && m_mapping.last().m_renderer != ancestorRenderer) {
+        stepRemoved(m_mapping.last());
+        m_mapping.removeLast();
+    }
+}
+
+void RenderGeometryMap::popMappingsToAncestor(const RenderLayer* ancestorLayer)
+{
+    const RenderLayerModelObject* ancestorRenderer = ancestorLayer ? ancestorLayer->renderer() : 0;
+    popMappingsToAncestor(ancestorRenderer);
+}
+
+void RenderGeometryMap::stepInserted(const RenderGeometryMapStep& step)
+{
+    // RenderView's offset, is only applied when we have fixed-positions.
+    if (!step.m_renderer->isRenderView())
+        m_accumulatedOffset += step.m_offset;
+
+    if (step.m_isNonUniform)
+        ++m_nonUniformStepsCount;
+
+    if (step.m_transform)
+        ++m_transformedStepsCount;
+    
+    if (step.m_isFixedPosition)
+        ++m_fixedStepsCount;
+}
+
+void RenderGeometryMap::stepRemoved(const RenderGeometryMapStep& step)
+{
+    // RenderView's offset, is only applied when we have fixed-positions.
+    if (!step.m_renderer->isRenderView())
+        m_accumulatedOffset -= step.m_offset;
+
+    if (step.m_isNonUniform) {
+        ASSERT(m_nonUniformStepsCount);
+        --m_nonUniformStepsCount;
+    }
+
+    if (step.m_transform) {
+        ASSERT(m_transformedStepsCount);
+        --m_transformedStepsCount;
+    }
+
+    if (step.m_isFixedPosition) {
+        ASSERT(m_fixedStepsCount);
+        --m_fixedStepsCount;
+    }
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderGeometryMap.h b/Source/core/rendering/RenderGeometryMap.h
new file mode 100644
index 0000000..887b5c2
--- /dev/null
+++ b/Source/core/rendering/RenderGeometryMap.h
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2012 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 RenderGeometryMap_h
+#define RenderGeometryMap_h
+
+#include "core/platform/graphics/FloatPoint.h"
+#include "core/platform/graphics/FloatQuad.h"
+#include "core/platform/graphics/IntSize.h"
+#include "core/platform/graphics/LayoutSize.h"
+#include "core/platform/graphics/transforms/TransformationMatrix.h"
+#include "core/rendering/RenderObject.h"
+#include <wtf/OwnPtr.h>
+
+namespace WebCore {
+
+class RenderLayer;
+class RenderLayerModelObject;
+class RenderView;
+class TransformState;
+
+// Stores data about how to map from one renderer to its container.
+struct RenderGeometryMapStep {
+    RenderGeometryMapStep(const RenderGeometryMapStep& o)
+        : m_renderer(o.m_renderer)
+        , m_offset(o.m_offset)
+        , m_accumulatingTransform(o.m_accumulatingTransform)
+        , m_isNonUniform(o.m_isNonUniform)
+        , m_isFixedPosition(o.m_isFixedPosition)
+        , m_hasTransform(o.m_hasTransform)
+    {
+        ASSERT(!o.m_transform);
+    }
+    RenderGeometryMapStep(const RenderObject* renderer, bool accumulatingTransform, bool isNonUniform, bool isFixedPosition, bool hasTransform)
+        : m_renderer(renderer)
+        , m_accumulatingTransform(accumulatingTransform)
+        , m_isNonUniform(isNonUniform)
+        , m_isFixedPosition(isFixedPosition)
+        , m_hasTransform(hasTransform)
+    {
+    }
+    const RenderObject* m_renderer;
+    LayoutSize m_offset;
+    OwnPtr<TransformationMatrix> m_transform; // Includes offset if non-null.
+    bool m_accumulatingTransform;
+    bool m_isNonUniform; // Mapping depends on the input point, e.g. because of CSS columns.
+    bool m_isFixedPosition;
+    bool m_hasTransform;
+};
+
+// Can be used while walking the Renderer tree to cache data about offsets and transforms.
+class RenderGeometryMap {
+    WTF_MAKE_NONCOPYABLE(RenderGeometryMap);
+public:
+    RenderGeometryMap(MapCoordinatesFlags = UseTransforms);
+    ~RenderGeometryMap();
+
+    MapCoordinatesFlags mapCoordinatesFlags() const { return m_mapCoordinatesFlags; }
+
+    FloatPoint absolutePoint(const FloatPoint& p) const
+    {
+        return mapToContainer(p, 0);
+    }
+
+    FloatRect absoluteRect(const FloatRect& rect) const
+    {
+        return mapToContainer(rect, 0).boundingBox();
+    }
+
+    // Map to a container. Will assert that the container has been pushed onto this map.
+    // A null container maps through the RenderView (including its scale transform, if any).
+    // If the container is the RenderView, the scroll offset is applied, but not the scale.
+    FloatPoint mapToContainer(const FloatPoint&, const RenderLayerModelObject*) const;
+    FloatQuad mapToContainer(const FloatRect&, const RenderLayerModelObject*) const;
+    
+    // Called by code walking the renderer or layer trees.
+    void pushMappingsToAncestor(const RenderLayer*, const RenderLayer* ancestorLayer);
+    void popMappingsToAncestor(const RenderLayer*);
+    void pushMappingsToAncestor(const RenderObject*, const RenderLayerModelObject* ancestorRenderer);
+    void popMappingsToAncestor(const RenderLayerModelObject*);
+    
+    // The following methods should only be called by renderers inside a call to pushMappingsToAncestor().
+
+    // Push geometry info between this renderer and some ancestor. The ancestor must be its container() or some
+    // stacking context between the renderer and its container.
+    void push(const RenderObject*, const LayoutSize&, bool accumulatingTransform = false, bool isNonUniform = false, bool isFixedPosition = false, bool hasTransform = false);
+    void push(const RenderObject*, const TransformationMatrix&, bool accumulatingTransform = false, bool isNonUniform = false, bool isFixedPosition = false, bool hasTransform = false);
+
+    // RenderView gets special treatment, because it applies the scroll offset only for elements inside in fixed position.
+    void pushView(const RenderView*, const LayoutSize& scrollOffset, const TransformationMatrix* = 0);
+
+private:
+    void mapToContainer(TransformState&, const RenderLayerModelObject* container = 0) const;
+
+    void stepInserted(const RenderGeometryMapStep&);
+    void stepRemoved(const RenderGeometryMapStep&);
+    
+    bool hasNonUniformStep() const { return m_nonUniformStepsCount; }
+    bool hasTransformStep() const { return m_transformedStepsCount; }
+    bool hasFixedPositionStep() const { return m_fixedStepsCount; }
+
+    typedef Vector<RenderGeometryMapStep, 32> RenderGeometryMapSteps;
+
+    size_t m_insertionPosition;
+    int m_nonUniformStepsCount;
+    int m_transformedStepsCount;
+    int m_fixedStepsCount;
+    RenderGeometryMapSteps m_mapping;
+    LayoutSize m_accumulatedOffset;
+    MapCoordinatesFlags m_mapCoordinatesFlags;
+};
+
+} // namespace WebCore
+
+namespace WTF {
+// This is required for a struct with OwnPtr. We know RenderGeometryMapStep is simple enough that
+// initializing to 0 and moving with memcpy (and then not destructing the original) will work.
+template<> struct VectorTraits<WebCore::RenderGeometryMapStep> : SimpleClassVectorTraits { };
+}
+
+#endif // RenderGeometryMap_h
diff --git a/Source/core/rendering/RenderGrid.cpp b/Source/core/rendering/RenderGrid.cpp
new file mode 100644
index 0000000..3700d2a
--- /dev/null
+++ b/Source/core/rendering/RenderGrid.cpp
@@ -0,0 +1,872 @@
+/*
+ * Copyright (C) 2011 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 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 "core/rendering/RenderGrid.h"
+
+#include "core/platform/NotImplemented.h"
+#include "core/rendering/LayoutRepainter.h"
+#include "core/rendering/RenderLayer.h"
+#include "core/rendering/RenderView.h"
+
+namespace WebCore {
+
+static const int infinity = intMaxForLayoutUnit;
+
+class GridTrack {
+public:
+    GridTrack()
+        : m_usedBreadth(0)
+        , m_maxBreadth(0)
+    {
+    }
+
+    void growUsedBreadth(LayoutUnit growth)
+    {
+        ASSERT(growth >= 0);
+        m_usedBreadth += growth;
+    }
+    LayoutUnit usedBreadth() const { return m_usedBreadth; }
+
+    void growMaxBreadth(LayoutUnit growth)
+    {
+        if (m_maxBreadth == infinity)
+            m_maxBreadth = m_usedBreadth + growth;
+        else
+            m_maxBreadth += growth;
+    }
+    LayoutUnit maxBreadthIfNotInfinite() const
+    {
+        return (m_maxBreadth == infinity) ? m_usedBreadth : m_maxBreadth;
+    }
+
+    LayoutUnit m_usedBreadth;
+    LayoutUnit m_maxBreadth;
+};
+
+class RenderGrid::GridIterator {
+    WTF_MAKE_NONCOPYABLE(GridIterator);
+public:
+    // |direction| is the direction that is fixed to |fixedTrackIndex| so e.g
+    // GridIterator(m_grid, ForColumns, 1) will walk over the rows of the 2nd column.
+    GridIterator(const Vector<Vector<Vector<RenderBox*, 1> > >& grid, TrackSizingDirection direction, size_t fixedTrackIndex)
+        : m_grid(grid)
+        , m_direction(direction)
+        , m_rowIndex((direction == ForColumns) ? 0 : fixedTrackIndex)
+        , m_columnIndex((direction == ForColumns) ? fixedTrackIndex : 0)
+        , m_childIndex(0)
+    {
+        ASSERT(m_rowIndex < m_grid.size());
+        ASSERT(m_columnIndex < m_grid[0].size());
+    }
+
+    RenderBox* nextGridItem()
+    {
+        if (!m_grid.size())
+            return 0;
+
+        size_t& varyingTrackIndex = (m_direction == ForColumns) ? m_rowIndex : m_columnIndex;
+        const size_t endOfVaryingTrackIndex = (m_direction == ForColumns) ? m_grid.size() : m_grid[0].size();
+        for (; varyingTrackIndex < endOfVaryingTrackIndex; ++varyingTrackIndex) {
+            const Vector<RenderBox*>& children = m_grid[m_rowIndex][m_columnIndex];
+            if (m_childIndex < children.size())
+                return children[m_childIndex++];
+
+            m_childIndex = 0;
+        }
+        return 0;
+    }
+
+    PassOwnPtr<GridCoordinate> nextEmptyGridArea()
+    {
+        if (m_grid.isEmpty())
+            return nullptr;
+
+        size_t& varyingTrackIndex = (m_direction == ForColumns) ? m_rowIndex : m_columnIndex;
+        const size_t endOfVaryingTrackIndex = (m_direction == ForColumns) ? m_grid.size() : m_grid[0].size();
+        for (; varyingTrackIndex < endOfVaryingTrackIndex; ++varyingTrackIndex) {
+            const Vector<RenderBox*>& children = m_grid[m_rowIndex][m_columnIndex];
+            if (children.isEmpty()) {
+                OwnPtr<GridCoordinate> result = adoptPtr(new GridCoordinate(GridSpan(m_rowIndex, m_rowIndex), GridSpan(m_columnIndex, m_columnIndex)));
+                // Advance the iterator to avoid an infinite loop where we would return the same grid area over and over.
+                ++varyingTrackIndex;
+                return result.release();
+            }
+        }
+        return nullptr;
+    }
+
+private:
+    const Vector<Vector<Vector<RenderBox*, 1> > >& m_grid;
+    TrackSizingDirection m_direction;
+    size_t m_rowIndex;
+    size_t m_columnIndex;
+    size_t m_childIndex;
+};
+
+RenderGrid::RenderGrid(Element* element)
+    : RenderBlock(element)
+{
+    // All of our children must be block level.
+    setChildrenInline(false);
+}
+
+RenderGrid::~RenderGrid()
+{
+}
+
+void RenderGrid::layoutBlock(bool relayoutChildren, LayoutUnit)
+{
+    ASSERT(needsLayout());
+
+    if (!relayoutChildren && simplifiedLayout())
+        return;
+
+    // FIXME: Much of this method is boiler plate that matches RenderBox::layoutBlock and Render*FlexibleBox::layoutBlock.
+    // It would be nice to refactor some of the duplicate code.
+    LayoutRepainter repainter(*this, checkForRepaintDuringLayout());
+    LayoutStateMaintainer statePusher(view(), this, locationOffset(), hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode());
+
+    // Regions changing widths can force us to relayout our children.
+    RenderFlowThread* flowThread = flowThreadContainingBlock();
+    if (logicalWidthChangedInRegions(flowThread))
+        relayoutChildren = true;
+    if (updateRegionsAndExclusionsLogicalSize(flowThread))
+        relayoutChildren = true;
+
+    LayoutSize previousSize = size();
+
+    setLogicalHeight(0);
+    updateLogicalWidth();
+
+    layoutGridItems();
+
+    LayoutUnit oldClientAfterEdge = clientLogicalBottom();
+    updateLogicalHeight();
+
+    if (size() != previousSize)
+        relayoutChildren = true;
+
+    layoutPositionedObjects(relayoutChildren || isRoot());
+
+    computeRegionRangeForBlock(flowThread);
+
+    computeOverflow(oldClientAfterEdge);
+    statePusher.pop();
+
+    updateLayerTransform();
+
+    // Update our scroll information if we're overflow:auto/scroll/hidden now that we know if
+    // we overflow or not.
+    if (hasOverflowClip())
+        layer()->updateScrollInfoAfterLayout();
+
+    repainter.repaintAfterLayout();
+
+    setNeedsLayout(false);
+}
+
+void RenderGrid::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const
+{
+    const_cast<RenderGrid*>(this)->placeItemsOnGrid();
+
+    // FIXME: This is an inefficient way to fill our sizes as it will try every grid areas, when we would
+    // only want to account for fixed grid tracks and grid items. Also this will be incorrect if we have spanning
+    // grid items.
+    for (size_t i = 0; i < gridColumnCount(); ++i) {
+        const GridTrackSize& trackSize = gridTrackSize(ForColumns, i);
+        LayoutUnit minTrackBreadth = computePreferredTrackWidth(trackSize.minTrackBreadth(), i);
+        LayoutUnit maxTrackBreadth = computePreferredTrackWidth(trackSize.maxTrackBreadth(), i);
+        maxTrackBreadth = std::max(maxTrackBreadth, minTrackBreadth);
+
+        minLogicalWidth += minTrackBreadth;
+        maxLogicalWidth += maxTrackBreadth;
+
+        // FIXME: This should add in the scrollbarWidth (e.g. see RenderFlexibleBox).
+    }
+
+    const_cast<RenderGrid*>(this)->clearGrid();
+}
+
+void RenderGrid::computePreferredLogicalWidths()
+{
+    ASSERT(preferredLogicalWidthsDirty());
+
+    m_minPreferredLogicalWidth = 0;
+    m_maxPreferredLogicalWidth = 0;
+
+    // FIXME: We don't take our own logical width into account. Once we do, we need to make sure
+    // we apply (and test the interaction with) min-width / max-width.
+
+    computeIntrinsicLogicalWidths(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);
+
+    LayoutUnit borderAndPaddingInInlineDirection = borderAndPaddingLogicalWidth();
+    m_minPreferredLogicalWidth += borderAndPaddingInInlineDirection;
+    m_maxPreferredLogicalWidth += borderAndPaddingInInlineDirection;
+
+    setPreferredLogicalWidthsDirty(false);
+}
+
+LayoutUnit RenderGrid::computePreferredTrackWidth(const GridLength& gridLength, size_t trackIndex) const
+{
+    // FIXME: Implement support for <flex> (crbug.com/235258)
+    if (gridLength.isFlex())
+        return 0;
+
+    const Length& length = gridLength.length();
+
+    if (length.isFixed()) {
+        // Grid areas don't have borders, margins or paddings so we don't need to account for them.
+        return length.intValue();
+    }
+
+    if (length.isMinContent()) {
+        LayoutUnit minContentSize = 0;
+        GridIterator iterator(m_grid, ForColumns, trackIndex);
+        while (RenderBox* gridItem = iterator.nextGridItem()) {
+            // FIXME: We should include the child's fixed margins like RenderFlexibleBox.
+            minContentSize = std::max(minContentSize, gridItem->minPreferredLogicalWidth());
+        }
+        return minContentSize;
+    }
+
+    if (length.isMaxContent()) {
+        LayoutUnit maxContentSize = 0;
+        GridIterator iterator(m_grid, ForColumns, trackIndex);
+        while (RenderBox* gridItem = iterator.nextGridItem()) {
+            // FIXME: We should include the child's fixed margins like RenderFlexibleBox.
+            maxContentSize = std::max(maxContentSize, gridItem->maxPreferredLogicalWidth());
+        }
+        return maxContentSize;
+    }
+
+    // FIXME: css3-sizing mentions that we should resolve "definite sizes"
+    // (including <percentage> and calc()) but we don't do it elsewhere.
+    return 0;
+}
+
+void RenderGrid::computedUsedBreadthOfGridTracks(TrackSizingDirection direction, Vector<GridTrack>& columnTracks, Vector<GridTrack>& rowTracks)
+{
+    LayoutUnit availableLogicalSpace = (direction == ForColumns) ? availableLogicalWidth() : availableLogicalHeight(IncludeMarginBorderPadding);
+    Vector<GridTrack>& tracks = (direction == ForColumns) ? columnTracks : rowTracks;
+    for (size_t i = 0; i < tracks.size(); ++i) {
+        GridTrack& track = tracks[i];
+        const GridTrackSize& trackSize = gridTrackSize(direction, i);
+        const GridLength& minTrackBreadth = trackSize.minTrackBreadth();
+        const GridLength& maxTrackBreadth = trackSize.maxTrackBreadth();
+
+        track.m_usedBreadth = computeUsedBreadthOfMinLength(direction, minTrackBreadth);
+        track.m_maxBreadth = computeUsedBreadthOfMaxLength(direction, maxTrackBreadth);
+
+        track.m_maxBreadth = std::max(track.m_maxBreadth, track.m_usedBreadth);
+    }
+
+    // FIXME: We shouldn't call resolveContentBasedTrackSizingFunctions if we have no min-content / max-content tracks.
+    resolveContentBasedTrackSizingFunctions(direction, columnTracks, rowTracks, availableLogicalSpace);
+
+    if (availableLogicalSpace <= 0)
+        return;
+
+    const size_t tracksSize = tracks.size();
+    Vector<GridTrack*> tracksForDistribution(tracksSize);
+    for (size_t i = 0; i < tracksSize; ++i)
+        tracksForDistribution[i] = tracks.data() + i;
+
+    distributeSpaceToTracks(tracksForDistribution, 0, &GridTrack::usedBreadth, &GridTrack::growUsedBreadth, availableLogicalSpace);
+}
+
+LayoutUnit RenderGrid::computeUsedBreadthOfMinLength(TrackSizingDirection direction, const GridLength& gridLength) const
+{
+    if (gridLength.isFlex())
+        return 0;
+
+    const Length& trackLength = gridLength.length();
+    ASSERT(!trackLength.isAuto());
+    if (trackLength.isFixed() || trackLength.isPercent() || trackLength.isViewportPercentage())
+        return computeUsedBreadthOfSpecifiedLength(direction, trackLength);
+
+    ASSERT(trackLength.isMinContent() || trackLength.isMaxContent());
+    return 0;
+}
+
+LayoutUnit RenderGrid::computeUsedBreadthOfMaxLength(TrackSizingDirection direction, const GridLength& gridLength) const
+{
+    if (gridLength.isFlex()) {
+        // FIXME: We should return the UsedBreadth per the specification.
+        return 0;
+    }
+
+    const Length& trackLength = gridLength.length();
+    ASSERT(!trackLength.isAuto());
+    if (trackLength.isFixed() || trackLength.isPercent() || trackLength.isViewportPercentage()) {
+        LayoutUnit computedBreadth = computeUsedBreadthOfSpecifiedLength(direction, trackLength);
+        // FIXME: We should ASSERT that computedBreadth cannot return infinity but it's currently
+        // possible. See https://bugs.webkit.org/show_bug.cgi?id=107053
+        return computedBreadth;
+    }
+
+    ASSERT(trackLength.isMinContent() || trackLength.isMaxContent());
+    return infinity;
+}
+
+LayoutUnit RenderGrid::computeUsedBreadthOfSpecifiedLength(TrackSizingDirection direction, const Length& trackLength) const
+{
+    // FIXME: We still need to support calc() here (https://webkit.org/b/103761).
+    ASSERT(trackLength.isFixed() || trackLength.isPercent() || trackLength.isViewportPercentage());
+    // FIXME: The -1 here should be replaced by whatever the intrinsic height of the grid is.
+    return valueForLength(trackLength, direction == ForColumns ? logicalWidth() : computeContentLogicalHeight(style()->logicalHeight(), -1), view());
+}
+
+const GridTrackSize& RenderGrid::gridTrackSize(TrackSizingDirection direction, size_t i) const
+{
+    const Vector<GridTrackSize>& trackStyles = (direction == ForColumns) ? style()->gridColumns() : style()->gridRows();
+    if (i >= trackStyles.size())
+        return (direction == ForColumns) ? style()->gridAutoColumns() : style()->gridAutoRows();
+
+    return trackStyles[i];
+}
+
+size_t RenderGrid::explicitGridColumnCount() const
+{
+    return style()->gridColumns().size();
+}
+
+size_t RenderGrid::explicitGridRowCount() const
+{
+    return style()->gridRows().size();
+}
+
+size_t RenderGrid::maximumIndexInDirection(TrackSizingDirection direction) const
+{
+    size_t maximumIndex = std::max<size_t>(1, (direction == ForColumns) ? explicitGridColumnCount() : explicitGridRowCount());
+
+    for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
+        // This function bypasses the cache (cachedGridCoordinate()) as it is used to build it.
+        OwnPtr<GridSpan> positions = resolveGridPositionsFromStyle(child, direction);
+
+        // |positions| is NULL if we need to run the auto-placement algorithm. Our estimation ignores
+        // this case as the auto-placement algorithm will grow the grid as needed.
+        if (!positions)
+            continue;
+
+        maximumIndex = std::max(maximumIndex, positions->finalPositionIndex + 1);
+    }
+
+    return maximumIndex;
+}
+
+LayoutUnit RenderGrid::logicalContentHeightForChild(RenderBox* child, Vector<GridTrack>& columnTracks)
+{
+    // FIXME: We shouldn't force a layout every time this function is called but
+    // 1) Return computeLogicalHeight's value if it's available. Unfortunately computeLogicalHeight
+    // doesn't return if the logical height is available so would need to be changed.
+    // 2) Relayout if the column track's used breadth changed OR the logical height is unavailable.
+    if (!child->needsLayout())
+        child->setNeedsLayout(true, MarkOnlyThis);
+
+    child->setOverrideContainingBlockContentLogicalWidth(gridAreaBreadthForChild(child, ForColumns, columnTracks));
+    // If |child| has a percentage logical height, we shouldn't let it override its intrinsic height, which is
+    // what we are interested in here. Thus we need to set the override logical height to -1 (no possible resolution).
+    child->setOverrideContainingBlockContentLogicalHeight(-1);
+    child->layout();
+    return child->logicalHeight();
+}
+
+LayoutUnit RenderGrid::minContentForChild(RenderBox* child, TrackSizingDirection direction, Vector<GridTrack>& columnTracks)
+{
+    bool hasOrthogonalWritingMode = child->isHorizontalWritingMode() != isHorizontalWritingMode();
+    // FIXME: Properly support orthogonal writing mode.
+    if (hasOrthogonalWritingMode)
+        return 0;
+
+    if (direction == ForColumns) {
+        // FIXME: It's unclear if we should return the intrinsic width or the preferred width.
+        // See http://lists.w3.org/Archives/Public/www-style/2013Jan/0245.html
+        return child->minPreferredLogicalWidth();
+    }
+
+    return logicalContentHeightForChild(child, columnTracks);
+}
+
+LayoutUnit RenderGrid::maxContentForChild(RenderBox* child, TrackSizingDirection direction, Vector<GridTrack>& columnTracks)
+{
+    bool hasOrthogonalWritingMode = child->isHorizontalWritingMode() != isHorizontalWritingMode();
+    // FIXME: Properly support orthogonal writing mode.
+    if (hasOrthogonalWritingMode)
+        return LayoutUnit();
+
+    if (direction == ForColumns) {
+        // FIXME: It's unclear if we should return the intrinsic width or the preferred width.
+        // See http://lists.w3.org/Archives/Public/www-style/2013Jan/0245.html
+        return child->maxPreferredLogicalWidth();
+    }
+
+    return logicalContentHeightForChild(child, columnTracks);
+}
+
+void RenderGrid::resolveContentBasedTrackSizingFunctions(TrackSizingDirection direction, Vector<GridTrack>& columnTracks, Vector<GridTrack>& rowTracks, LayoutUnit& availableLogicalSpace)
+{
+    // FIXME: Split the grid tracks once we support fractions (step 1 of the algorithm).
+
+    Vector<GridTrack>& tracks = (direction == ForColumns) ? columnTracks : rowTracks;
+
+    // FIXME: Per step 2 of the specification, we should order the grid items by increasing span.
+    for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
+        resolveContentBasedTrackSizingFunctionsForItems(direction, columnTracks, rowTracks, child, &GridTrackSize::hasMinOrMaxContentMinTrackBreadth, &RenderGrid::minContentForChild, &GridTrack::usedBreadth, &GridTrack::growUsedBreadth);
+        resolveContentBasedTrackSizingFunctionsForItems(direction, columnTracks, rowTracks, child, &GridTrackSize::hasMaxContentMinTrackBreadth, &RenderGrid::maxContentForChild, &GridTrack::usedBreadth, &GridTrack::growUsedBreadth);
+        resolveContentBasedTrackSizingFunctionsForItems(direction, columnTracks, rowTracks, child, &GridTrackSize::hasMinOrMaxContentMaxTrackBreadth, &RenderGrid::minContentForChild, &GridTrack::maxBreadthIfNotInfinite, &GridTrack::growMaxBreadth);
+        resolveContentBasedTrackSizingFunctionsForItems(direction, columnTracks, rowTracks, child, &GridTrackSize::hasMaxContentMaxTrackBreadth, &RenderGrid::maxContentForChild, &GridTrack::maxBreadthIfNotInfinite, &GridTrack::growMaxBreadth);
+    }
+
+    for (size_t i = 0; i < tracks.size(); ++i) {
+        GridTrack& track = tracks[i];
+        if (track.m_maxBreadth == infinity)
+            track.m_maxBreadth = track.m_usedBreadth;
+
+        availableLogicalSpace -= track.m_usedBreadth;
+    }
+}
+
+void RenderGrid::resolveContentBasedTrackSizingFunctionsForItems(TrackSizingDirection direction, Vector<GridTrack>& columnTracks, Vector<GridTrack>& rowTracks, RenderBox* gridItem, FilterFunction filterFunction, SizingFunction sizingFunction, AccumulatorGetter trackGetter, AccumulatorGrowFunction trackGrowthFunction)
+{
+    const GridCoordinate coordinate = cachedGridCoordinate(gridItem);
+    const size_t initialTrackIndex = (direction == ForColumns) ? coordinate.columns.initialPositionIndex : coordinate.rows.initialPositionIndex;
+    const size_t finalTrackIndex = (direction == ForColumns) ? coordinate.columns.finalPositionIndex : coordinate.rows.finalPositionIndex;
+
+    Vector<GridTrack*> tracks;
+    for (size_t trackIndex = initialTrackIndex; trackIndex <= finalTrackIndex; ++trackIndex) {
+        const GridTrackSize& trackSize = gridTrackSize(direction, trackIndex);
+        if (!(trackSize.*filterFunction)())
+            continue;
+
+        GridTrack& track = (direction == ForColumns) ? columnTracks[trackIndex] : rowTracks[trackIndex];
+        tracks.append(&track);
+    }
+
+    LayoutUnit additionalBreadthSpace = (this->*sizingFunction)(gridItem, direction, columnTracks);
+    for (size_t trackIndexForSpace = initialTrackIndex; trackIndexForSpace <= finalTrackIndex; ++trackIndexForSpace) {
+        GridTrack& track = (direction == ForColumns) ? columnTracks[trackIndexForSpace] : rowTracks[trackIndexForSpace];
+        additionalBreadthSpace -= (track.*trackGetter)();
+    }
+
+    // FIXME: We should pass different values for |tracksForGrowthAboveMaxBreadth|.
+    distributeSpaceToTracks(tracks, &tracks, trackGetter, trackGrowthFunction, additionalBreadthSpace);
+}
+
+static bool sortByGridTrackGrowthPotential(const GridTrack* track1, const GridTrack* track2)
+{
+    return (track1->m_maxBreadth - track1->m_usedBreadth) < (track2->m_maxBreadth - track2->m_usedBreadth);
+}
+
+void RenderGrid::distributeSpaceToTracks(Vector<GridTrack*>& tracks, Vector<GridTrack*>* tracksForGrowthAboveMaxBreadth, AccumulatorGetter trackGetter, AccumulatorGrowFunction trackGrowthFunction, LayoutUnit& availableLogicalSpace)
+{
+    std::sort(tracks.begin(), tracks.end(), sortByGridTrackGrowthPotential);
+
+    size_t tracksSize = tracks.size();
+    Vector<LayoutUnit> updatedTrackBreadths(tracksSize);
+
+    for (size_t i = 0; i < tracksSize; ++i) {
+        GridTrack& track = *tracks[i];
+        LayoutUnit availableLogicalSpaceShare = availableLogicalSpace / (tracksSize - i);
+        LayoutUnit trackBreadth = (tracks[i]->*trackGetter)();
+        LayoutUnit growthShare = std::min(availableLogicalSpaceShare, track.m_maxBreadth - trackBreadth);
+        updatedTrackBreadths[i] = trackBreadth + growthShare;
+        availableLogicalSpace -= growthShare;
+    }
+
+    if (availableLogicalSpace > 0 && tracksForGrowthAboveMaxBreadth) {
+        tracksSize = tracksForGrowthAboveMaxBreadth->size();
+        for (size_t i = 0; i < tracksSize; ++i) {
+            LayoutUnit growthShare = availableLogicalSpace / (tracksSize - i);
+            updatedTrackBreadths[i] += growthShare;
+            availableLogicalSpace -= growthShare;
+        }
+    }
+
+    for (size_t i = 0; i < tracksSize; ++i) {
+        LayoutUnit growth = updatedTrackBreadths[i] - (tracks[i]->*trackGetter)();
+        if (growth >= 0)
+            (tracks[i]->*trackGrowthFunction)(growth);
+    }
+}
+
+#ifndef NDEBUG
+bool RenderGrid::tracksAreWiderThanMinTrackBreadth(TrackSizingDirection direction, const Vector<GridTrack>& tracks)
+{
+    for (size_t i = 0; i < tracks.size(); ++i) {
+        const GridTrackSize& trackSize = gridTrackSize(direction, i);
+        const GridLength& minTrackBreadth = trackSize.minTrackBreadth();
+        if (computeUsedBreadthOfMinLength(direction, minTrackBreadth) > tracks[i].m_usedBreadth)
+            return false;
+    }
+    return true;
+}
+#endif
+
+void RenderGrid::growGrid(TrackSizingDirection direction)
+{
+    if (direction == ForColumns) {
+        const size_t oldColumnSize = m_grid[0].size();
+        for (size_t row = 0; row < m_grid.size(); ++row)
+            m_grid[row].grow(oldColumnSize + 1);
+    } else {
+        const size_t oldRowSize = m_grid.size();
+        m_grid.grow(oldRowSize + 1);
+        m_grid[oldRowSize].grow(m_grid[0].size());
+    }
+}
+
+void RenderGrid::insertItemIntoGrid(RenderBox* child, const GridCoordinate& coordinate)
+{
+    m_grid[coordinate.rows.initialPositionIndex][coordinate.columns.initialPositionIndex].append(child);
+    m_gridItemCoordinate.set(child, coordinate);
+}
+
+void RenderGrid::insertItemIntoGrid(RenderBox* child, size_t rowTrack, size_t columnTrack)
+{
+    const GridSpan& rowSpan = resolveGridPositionsFromAutoPlacementPosition(child, ForRows, rowTrack);
+    const GridSpan& columnSpan = resolveGridPositionsFromAutoPlacementPosition(child, ForColumns, columnTrack);
+    insertItemIntoGrid(child, GridCoordinate(rowSpan, columnSpan));
+}
+
+void RenderGrid::placeItemsOnGrid()
+{
+    ASSERT(!gridWasPopulated());
+    ASSERT(m_gridItemCoordinate.isEmpty());
+
+    m_grid.grow(maximumIndexInDirection(ForRows));
+    size_t maximumColumnIndex = maximumIndexInDirection(ForColumns);
+    for (size_t i = 0; i < m_grid.size(); ++i)
+        m_grid[i].grow(maximumColumnIndex);
+
+    Vector<RenderBox*> autoMajorAxisAutoGridItems;
+    Vector<RenderBox*> specifiedMajorAxisAutoGridItems;
+    GridAutoFlow autoFlow = style()->gridAutoFlow();
+    for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
+        // FIXME: We never re-resolve positions if the grid is grown during auto-placement which may lead auto / <integer>
+        // positions to not match the author's intent. The specification is unclear on what should be done in this case.
+        OwnPtr<GridSpan> rowPositions = resolveGridPositionsFromStyle(child, ForRows);
+        OwnPtr<GridSpan> columnPositions = resolveGridPositionsFromStyle(child, ForColumns);
+        if (!rowPositions || !columnPositions) {
+            GridSpan* majorAxisPositions = (autoPlacementMajorAxisDirection() == ForColumns) ? columnPositions.get() : rowPositions.get();
+            if (!majorAxisPositions)
+                autoMajorAxisAutoGridItems.append(child);
+            else
+                specifiedMajorAxisAutoGridItems.append(child);
+            continue;
+        }
+        insertItemIntoGrid(child, GridCoordinate(*rowPositions, *columnPositions));
+    }
+
+    ASSERT(gridRowCount() >= style()->gridRows().size());
+    ASSERT(gridColumnCount() >= style()->gridColumns().size());
+
+    if (autoFlow == AutoFlowNone) {
+        // If we did collect some grid items, they won't be placed thus never laid out.
+        ASSERT(!autoMajorAxisAutoGridItems.size());
+        ASSERT(!specifiedMajorAxisAutoGridItems.size());
+        return;
+    }
+
+    placeSpecifiedMajorAxisItemsOnGrid(specifiedMajorAxisAutoGridItems);
+    placeAutoMajorAxisItemsOnGrid(autoMajorAxisAutoGridItems);
+}
+
+void RenderGrid::placeSpecifiedMajorAxisItemsOnGrid(Vector<RenderBox*> autoGridItems)
+{
+    for (size_t i = 0; i < autoGridItems.size(); ++i) {
+        OwnPtr<GridSpan> majorAxisPositions = resolveGridPositionsFromStyle(autoGridItems[i], autoPlacementMajorAxisDirection());
+        GridIterator iterator(m_grid, autoPlacementMajorAxisDirection(), majorAxisPositions->initialPositionIndex);
+        if (OwnPtr<GridCoordinate> emptyGridArea = iterator.nextEmptyGridArea()) {
+            insertItemIntoGrid(autoGridItems[i], emptyGridArea->rows.initialPositionIndex, emptyGridArea->columns.initialPositionIndex);
+            continue;
+        }
+
+        growGrid(autoPlacementMinorAxisDirection());
+        OwnPtr<GridCoordinate> emptyGridArea = iterator.nextEmptyGridArea();
+        ASSERT(emptyGridArea);
+        insertItemIntoGrid(autoGridItems[i], emptyGridArea->rows.initialPositionIndex, emptyGridArea->columns.initialPositionIndex);
+    }
+}
+
+void RenderGrid::placeAutoMajorAxisItemsOnGrid(Vector<RenderBox*> autoGridItems)
+{
+    for (size_t i = 0; i < autoGridItems.size(); ++i)
+        placeAutoMajorAxisItemOnGrid(autoGridItems[i]);
+}
+
+void RenderGrid::placeAutoMajorAxisItemOnGrid(RenderBox* gridItem)
+{
+    OwnPtr<GridSpan> minorAxisPositions = resolveGridPositionsFromStyle(gridItem, autoPlacementMinorAxisDirection());
+    ASSERT(!resolveGridPositionsFromStyle(gridItem, autoPlacementMajorAxisDirection()));
+    size_t minorAxisIndex = 0;
+    if (minorAxisPositions) {
+        minorAxisIndex = minorAxisPositions->initialPositionIndex;
+        GridIterator iterator(m_grid, autoPlacementMinorAxisDirection(), minorAxisIndex);
+        if (OwnPtr<GridCoordinate> emptyGridArea = iterator.nextEmptyGridArea()) {
+            insertItemIntoGrid(gridItem, emptyGridArea->rows.initialPositionIndex, emptyGridArea->columns.initialPositionIndex);
+            return;
+        }
+    } else {
+        const size_t endOfMajorAxis = (autoPlacementMajorAxisDirection() == ForColumns) ? gridColumnCount() : gridRowCount();
+        for (size_t majorAxisIndex = 0; majorAxisIndex < endOfMajorAxis; ++majorAxisIndex) {
+            GridIterator iterator(m_grid, autoPlacementMajorAxisDirection(), majorAxisIndex);
+            if (OwnPtr<GridCoordinate> emptyGridArea = iterator.nextEmptyGridArea()) {
+                insertItemIntoGrid(gridItem, emptyGridArea->rows.initialPositionIndex, emptyGridArea->columns.initialPositionIndex);
+                return;
+            }
+        }
+    }
+
+    // We didn't find an empty grid area so we need to create an extra major axis line and insert our gridItem in it.
+    const size_t columnIndex = (autoPlacementMajorAxisDirection() == ForColumns) ? m_grid[0].size() : minorAxisIndex;
+    const size_t rowIndex = (autoPlacementMajorAxisDirection() == ForColumns) ? minorAxisIndex : m_grid.size();
+    growGrid(autoPlacementMajorAxisDirection());
+    insertItemIntoGrid(gridItem, rowIndex, columnIndex);
+}
+
+RenderGrid::TrackSizingDirection RenderGrid::autoPlacementMajorAxisDirection() const
+{
+    GridAutoFlow flow = style()->gridAutoFlow();
+    ASSERT(flow != AutoFlowNone);
+    return (flow == AutoFlowColumn) ? ForColumns : ForRows;
+}
+
+RenderGrid::TrackSizingDirection RenderGrid::autoPlacementMinorAxisDirection() const
+{
+    GridAutoFlow flow = style()->gridAutoFlow();
+    ASSERT(flow != AutoFlowNone);
+    return (flow == AutoFlowColumn) ? ForRows : ForColumns;
+}
+
+void RenderGrid::clearGrid()
+{
+    m_grid.clear();
+    m_gridItemCoordinate.clear();
+}
+
+void RenderGrid::layoutGridItems()
+{
+    placeItemsOnGrid();
+
+    Vector<GridTrack> columnTracks(gridColumnCount());
+    Vector<GridTrack> rowTracks(gridRowCount());
+    computedUsedBreadthOfGridTracks(ForColumns, columnTracks, rowTracks);
+    ASSERT(tracksAreWiderThanMinTrackBreadth(ForColumns, columnTracks));
+    computedUsedBreadthOfGridTracks(ForRows, columnTracks, rowTracks);
+    ASSERT(tracksAreWiderThanMinTrackBreadth(ForRows, rowTracks));
+
+    for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
+        LayoutPoint childPosition = findChildLogicalPosition(child, columnTracks, rowTracks);
+
+        // Because the grid area cannot be styled, we don't need to adjust
+        // the grid breadth to account for 'box-sizing'.
+        LayoutUnit oldOverrideContainingBlockContentLogicalWidth = child->hasOverrideContainingBlockLogicalWidth() ? child->overrideContainingBlockContentLogicalWidth() : LayoutUnit();
+        LayoutUnit oldOverrideContainingBlockContentLogicalHeight = child->hasOverrideContainingBlockLogicalHeight() ? child->overrideContainingBlockContentLogicalHeight() : LayoutUnit();
+
+        // FIXME: For children in a content sized track, we clear the overrideContainingBlockContentLogicalHeight
+        // in minContentForChild / maxContentForChild which means that we will always relayout the child.
+        LayoutUnit overrideContainingBlockContentLogicalWidth = gridAreaBreadthForChild(child, ForColumns, columnTracks);
+        LayoutUnit overrideContainingBlockContentLogicalHeight = gridAreaBreadthForChild(child, ForRows, rowTracks);
+        if (oldOverrideContainingBlockContentLogicalWidth != overrideContainingBlockContentLogicalWidth || oldOverrideContainingBlockContentLogicalHeight != overrideContainingBlockContentLogicalHeight)
+            child->setNeedsLayout(true, MarkOnlyThis);
+
+        child->setOverrideContainingBlockContentLogicalWidth(overrideContainingBlockContentLogicalWidth);
+        child->setOverrideContainingBlockContentLogicalHeight(overrideContainingBlockContentLogicalHeight);
+
+        LayoutRect oldChildRect = child->frameRect();
+
+        // FIXME: Grid items should stretch to fill their cells. Once we
+        // implement grid-{column,row}-align, we can also shrink to fit. For
+        // now, just size as if we were a regular child.
+        child->layoutIfNeeded();
+
+        // FIXME: Handle border & padding on the grid element.
+        child->setLogicalLocation(childPosition);
+
+        // 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(oldChildRect);
+    }
+
+    for (size_t i = 0; i < rowTracks.size(); ++i)
+        setLogicalHeight(logicalHeight() + rowTracks[i].m_usedBreadth);
+
+    // FIXME: We should handle min / max logical height.
+
+    setLogicalHeight(logicalHeight() + borderAndPaddingLogicalHeight());
+    clearGrid();
+}
+
+RenderGrid::GridCoordinate RenderGrid::cachedGridCoordinate(const RenderBox* gridItem) const
+{
+    ASSERT(m_gridItemCoordinate.contains(gridItem));
+    return m_gridItemCoordinate.get(gridItem);
+}
+
+RenderGrid::GridSpan RenderGrid::resolveGridPositionsFromAutoPlacementPosition(const RenderBox*, TrackSizingDirection, size_t initialPosition) const
+{
+    // FIXME: We don't support spanning with auto positions yet. Once we do, this is wrong. Also we should make
+    // sure the grid can accomodate the new item as we only grow 1 position in a given direction.
+    return GridSpan(initialPosition, initialPosition);
+}
+
+PassOwnPtr<RenderGrid::GridSpan> RenderGrid::resolveGridPositionsFromStyle(const RenderBox* gridItem, TrackSizingDirection direction) const
+{
+    const GridPosition& initialPosition = (direction == ForColumns) ? gridItem->style()->gridStart() : gridItem->style()->gridBefore();
+    const GridPositionSide initialPositionSide = (direction == ForColumns) ? StartSide : BeforeSide;
+    const GridPosition& finalPosition = (direction == ForColumns) ? gridItem->style()->gridEnd() : gridItem->style()->gridAfter();
+    const GridPositionSide finalPositionSide = (direction == ForColumns) ? EndSide : AfterSide;
+
+    // We should NEVER see both spans as they should have been handled during style resolve.
+    ASSERT(!initialPosition.isSpan() || !finalPosition.isSpan());
+
+    if (initialPosition.isAuto() && finalPosition.isAuto()) {
+        if (style()->gridAutoFlow() == AutoFlowNone)
+            return adoptPtr(new GridSpan(0, 0));
+
+        // We can't get our grid positions without running the auto placement algorithm.
+        return nullptr;
+    }
+
+    if (initialPosition.shouldBeResolvedAgainstOppositePosition()) {
+        // Infer the position from the final position ('auto / 1' or 'span 2 / 3' case).
+        const size_t finalResolvedPosition = resolveGridPositionFromStyle(finalPosition, finalPositionSide);
+        return resolveGridPositionAgainstOppositePosition(finalResolvedPosition, initialPosition, initialPositionSide);
+    }
+
+    if (finalPosition.shouldBeResolvedAgainstOppositePosition()) {
+        // Infer our position from the initial position ('1 / auto' or '3 / span 2' case).
+        const size_t initialResolvedPosition = resolveGridPositionFromStyle(initialPosition, initialPositionSide);
+        return resolveGridPositionAgainstOppositePosition(initialResolvedPosition, finalPosition, finalPositionSide);
+    }
+
+    size_t resolvedInitialPosition = resolveGridPositionFromStyle(initialPosition, initialPositionSide);
+    size_t resolvedFinalPosition = resolveGridPositionFromStyle(finalPosition, finalPositionSide);
+
+    // If 'grid-after' specifies a line at or before that specified by 'grid-before', it computes to 'span 1'.
+    if (resolvedFinalPosition < resolvedInitialPosition)
+        resolvedFinalPosition = resolvedInitialPosition;
+
+    return adoptPtr(new GridSpan(resolvedInitialPosition, resolvedFinalPosition));
+}
+
+size_t RenderGrid::resolveGridPositionFromStyle(const GridPosition& position, GridPositionSide side) const
+{
+    // FIXME: Handle other values for grid-{row,column} like ranges or line names.
+    switch (position.type()) {
+    case IntegerPosition: {
+        if (position.isPositive()) {
+            if (side == EndSide || side == AfterSide)
+                return std::max(0, position.integerPosition() - 2);
+
+            return position.integerPosition() - 1;
+        }
+
+        size_t resolvedPosition = abs(position.integerPosition());
+        // FIXME: This returns one less than the expected result for side == StartSide or BeforeSide as we don't properly convert
+        // the grid line to its grid track. However this avoids the issue of growing the grid when inserting the item (e.g. -1 / auto).
+        const size_t endOfTrack = (side == StartSide || side == EndSide) ? explicitGridColumnCount() : explicitGridRowCount();
+
+        // Per http://lists.w3.org/Archives/Public/www-style/2013Mar/0589.html, we clamp negative value to the first line.
+        if (endOfTrack < resolvedPosition)
+            return 0;
+
+        return endOfTrack - resolvedPosition;
+    }
+    case AutoPosition:
+        // 'auto' depends on the opposite position for resolution (e.g. grid-row: auto / 1).
+        ASSERT_NOT_REACHED();
+        return 0;
+    case SpanPosition:
+        // FIXME: Handle span positions (crbug.com/229713).
+        ASSERT_NOT_REACHED();
+        return 0;
+    }
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
+PassOwnPtr<RenderGrid::GridSpan> RenderGrid::resolveGridPositionAgainstOppositePosition(size_t resolvedOppositePosition, const GridPosition& position, GridPositionSide side) const
+{
+    if (position.isAuto())
+        return GridSpan::create(resolvedOppositePosition, resolvedOppositePosition);
+
+    ASSERT(position.isSpan());
+    ASSERT(position.spanPosition() > 0);
+
+    // 'span 1' is contained inside a single grid track regardless of the direction.
+    // That's why the CSS span value is one more than the offset we apply.
+    size_t positionOffset = position.spanPosition() - 1;
+    if (side == StartSide || side == BeforeSide) {
+        size_t initialResolvedPosition = std::max<int>(0, resolvedOppositePosition - positionOffset);
+        return GridSpan::create(initialResolvedPosition, resolvedOppositePosition);
+    }
+
+    return GridSpan::create(resolvedOppositePosition, resolvedOppositePosition + positionOffset);
+}
+
+LayoutUnit RenderGrid::gridAreaBreadthForChild(const RenderBox* child, TrackSizingDirection direction, const Vector<GridTrack>& tracks) const
+{
+    const GridCoordinate& coordinate = cachedGridCoordinate(child);
+    const GridSpan& span = (direction == ForColumns) ? coordinate.columns : coordinate.rows;
+    LayoutUnit gridAreaBreadth = 0;
+    for (size_t trackIndex = span.initialPositionIndex; trackIndex <= span.finalPositionIndex; ++trackIndex)
+        gridAreaBreadth += tracks[trackIndex].m_usedBreadth;
+    return gridAreaBreadth;
+}
+
+LayoutPoint RenderGrid::findChildLogicalPosition(RenderBox* child, const Vector<GridTrack>& columnTracks, const Vector<GridTrack>& rowTracks)
+{
+    const GridCoordinate& coordinate = cachedGridCoordinate(child);
+
+    // The grid items should be inside the grid container's border box, that's why they need to be shifted.
+    LayoutPoint offset(borderAndPaddingStart(), borderAndPaddingBefore());
+    // FIXME: |columnTrack| and |rowTrack| should be smaller than our column / row count.
+    for (size_t i = 0; i < coordinate.columns.initialPositionIndex && i < columnTracks.size(); ++i)
+        offset.setX(offset.x() + columnTracks[i].m_usedBreadth);
+    for (size_t i = 0; i < coordinate.rows.initialPositionIndex && i < rowTracks.size(); ++i)
+        offset.setY(offset.y() + rowTracks[i].m_usedBreadth);
+
+    // FIXME: Handle margins on the grid item.
+    return offset;
+}
+
+const char* RenderGrid::renderName() const
+{
+    if (isFloating())
+        return "RenderGrid (floating)";
+    if (isOutOfFlowPositioned())
+        return "RenderGrid (positioned)";
+    if (isAnonymous())
+        return "RenderGrid (generated)";
+    if (isRelPositioned())
+        return "RenderGrid (relative positioned)";
+    return "RenderGrid";
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderGrid.h b/Source/core/rendering/RenderGrid.h
new file mode 100644
index 0000000..61b9825
--- /dev/null
+++ b/Source/core/rendering/RenderGrid.h
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2011 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 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 RenderGrid_h
+#define RenderGrid_h
+
+#include "core/rendering/RenderBlock.h"
+
+namespace WebCore {
+
+class GridTrack;
+
+class RenderGrid FINAL : public RenderBlock {
+public:
+    RenderGrid(Element*);
+    virtual ~RenderGrid();
+
+    virtual const char* renderName() const OVERRIDE;
+
+    virtual void layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeight = 0) OVERRIDE;
+
+    virtual bool avoidsFloats() const OVERRIDE { return true; }
+    virtual bool canCollapseAnonymousBlockChild() const OVERRIDE { return false; }
+
+private:
+    virtual bool isRenderGrid() const OVERRIDE { return true; }
+    virtual void computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const OVERRIDE;
+    virtual void computePreferredLogicalWidths() OVERRIDE;
+
+    LayoutUnit computePreferredTrackWidth(const GridLength&, size_t) const;
+
+    struct GridSpan {
+        static PassOwnPtr<GridSpan> create(size_t initialPosition, size_t finalPosition)
+        {
+            return adoptPtr(new GridSpan(initialPosition, finalPosition));
+        }
+
+        GridSpan(size_t initialPosition, size_t finalPosition)
+            : initialPositionIndex(initialPosition)
+            , finalPositionIndex(finalPosition)
+        {
+            ASSERT(initialPositionIndex <= finalPositionIndex);
+        }
+
+        size_t initialPositionIndex;
+        size_t finalPositionIndex;
+    };
+
+    struct GridCoordinate {
+        // HashMap requires a default constuctor.
+        GridCoordinate()
+            : columns(0, 0)
+            , rows(0, 0)
+        {
+        }
+
+        GridCoordinate(const GridSpan& r, const GridSpan& c)
+            : columns(c)
+            , rows(r)
+        {
+        }
+
+        GridSpan columns;
+        GridSpan rows;
+    };
+
+    class GridIterator;
+    enum TrackSizingDirection { ForColumns, ForRows };
+    void computedUsedBreadthOfGridTracks(TrackSizingDirection, Vector<GridTrack>& columnTracks, Vector<GridTrack>& rowTracks);
+    LayoutUnit computeUsedBreadthOfMinLength(TrackSizingDirection, const GridLength&) const;
+    LayoutUnit computeUsedBreadthOfMaxLength(TrackSizingDirection, const GridLength&) const;
+    LayoutUnit computeUsedBreadthOfSpecifiedLength(TrackSizingDirection, const Length&) const;
+    void resolveContentBasedTrackSizingFunctions(TrackSizingDirection, Vector<GridTrack>& columnTracks, Vector<GridTrack>& rowTracks, LayoutUnit& availableLogicalSpace);
+
+    void growGrid(TrackSizingDirection);
+    void insertItemIntoGrid(RenderBox*, size_t rowTrack, size_t columnTrack);
+    void insertItemIntoGrid(RenderBox*, const GridCoordinate&);
+    void placeItemsOnGrid();
+    void placeSpecifiedMajorAxisItemsOnGrid(Vector<RenderBox*>);
+    void placeAutoMajorAxisItemsOnGrid(Vector<RenderBox*>);
+    void placeAutoMajorAxisItemOnGrid(RenderBox*);
+    TrackSizingDirection autoPlacementMajorAxisDirection() const;
+    TrackSizingDirection autoPlacementMinorAxisDirection() const;
+
+    void layoutGridItems();
+    void clearGrid();
+
+    typedef LayoutUnit (RenderGrid::* SizingFunction)(RenderBox*, TrackSizingDirection, Vector<GridTrack>&);
+    typedef LayoutUnit (GridTrack::* AccumulatorGetter)() const;
+    typedef void (GridTrack::* AccumulatorGrowFunction)(LayoutUnit);
+    typedef bool (GridTrackSize::* FilterFunction)() const;
+    void resolveContentBasedTrackSizingFunctionsForItems(TrackSizingDirection, Vector<GridTrack>& columnTracks, Vector<GridTrack>& rowTracks, RenderBox*, FilterFunction, SizingFunction, AccumulatorGetter, AccumulatorGrowFunction);
+    void distributeSpaceToTracks(Vector<GridTrack*>&, Vector<GridTrack*>* tracksForGrowthAboveMaxBreadth, AccumulatorGetter, AccumulatorGrowFunction, LayoutUnit& availableLogicalSpace);
+
+    const GridTrackSize& gridTrackSize(TrackSizingDirection, size_t) const;
+    size_t explicitGridColumnCount() const;
+    size_t explicitGridRowCount() const;
+    size_t maximumIndexInDirection(TrackSizingDirection) const;
+
+    LayoutUnit logicalContentHeightForChild(RenderBox*, Vector<GridTrack>&);
+    LayoutUnit minContentForChild(RenderBox*, TrackSizingDirection, Vector<GridTrack>& columnTracks);
+    LayoutUnit maxContentForChild(RenderBox*, TrackSizingDirection, Vector<GridTrack>& columnTracks);
+    LayoutPoint findChildLogicalPosition(RenderBox*, const Vector<GridTrack>& columnTracks, const Vector<GridTrack>& rowTracks);
+    GridCoordinate cachedGridCoordinate(const RenderBox*) const;
+
+    GridSpan resolveGridPositionsFromAutoPlacementPosition(const RenderBox*, TrackSizingDirection, size_t) const;
+    PassOwnPtr<GridSpan> resolveGridPositionsFromStyle(const RenderBox*, TrackSizingDirection) const;
+    enum GridPositionSide {
+        StartSide,
+        EndSide,
+        BeforeSide,
+        AfterSide
+    };
+    size_t resolveGridPositionFromStyle(const GridPosition&, GridPositionSide) const;
+    PassOwnPtr<GridSpan> resolveGridPositionAgainstOppositePosition(size_t resolvedOppositePosition, const GridPosition&, GridPositionSide) const;
+
+    LayoutUnit gridAreaBreadthForChild(const RenderBox* child, TrackSizingDirection, const Vector<GridTrack>&) const;
+
+#ifndef NDEBUG
+    bool tracksAreWiderThanMinTrackBreadth(TrackSizingDirection, const Vector<GridTrack>&);
+    bool gridWasPopulated() const { return !m_grid.isEmpty() && !m_grid[0].isEmpty(); }
+#endif
+
+    size_t gridColumnCount() const
+    {
+        ASSERT(gridWasPopulated());
+        return m_grid[0].size();
+    }
+    size_t gridRowCount() const
+    {
+        ASSERT(gridWasPopulated());
+        return m_grid.size();
+    }
+
+    Vector<Vector<Vector<RenderBox*, 1> > > m_grid;
+    HashMap<const RenderBox*, GridCoordinate> m_gridItemCoordinate;
+};
+
+} // namespace WebCore
+
+#endif // RenderGrid_h
diff --git a/Source/core/rendering/RenderHTMLCanvas.cpp b/Source/core/rendering/RenderHTMLCanvas.cpp
new file mode 100644
index 0000000..ae72616
--- /dev/null
+++ b/Source/core/rendering/RenderHTMLCanvas.cpp
@@ -0,0 +1,101 @@
+/*
+ * 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 "core/rendering/RenderHTMLCanvas.h"
+
+#include "HTMLNames.h"
+#include "core/dom/Document.h"
+#include "core/html/HTMLCanvasElement.h"
+#include "core/html/canvas/CanvasRenderingContext.h"
+#include "core/page/Frame.h"
+#include "core/page/FrameView.h"
+#include "core/page/Page.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/rendering/PaintInfo.h"
+#include "core/rendering/RenderView.h"
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+RenderHTMLCanvas::RenderHTMLCanvas(HTMLCanvasElement* element)
+    : RenderReplaced(element, element->size())
+{
+    view()->frameView()->setIsVisuallyNonEmpty();
+}
+
+bool RenderHTMLCanvas::requiresLayer() const
+{
+    if (RenderReplaced::requiresLayer())
+        return true;
+    
+    HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(node());
+    return canvas && canvas->renderingContext() && canvas->renderingContext()->isAccelerated();
+}
+
+void RenderHTMLCanvas::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    LayoutRect rect = contentBoxRect();
+    rect.moveBy(paintOffset);
+
+    if (Frame* frame = this->frame()) {
+        if (Page* page = frame->page()) {
+            if (paintInfo.phase == PaintPhaseForeground)
+                page->addRelevantRepaintedObject(this, rect);
+        }
+    }
+
+    bool useLowQualityScale = style()->imageRendering() == ImageRenderingOptimizeContrast;
+    static_cast<HTMLCanvasElement*>(node())->paint(paintInfo.context, rect, useLowQualityScale);
+}
+
+void RenderHTMLCanvas::canvasSizeChanged()
+{
+    IntSize canvasSize = static_cast<HTMLCanvasElement*>(node())->size();
+    LayoutSize zoomedSize(canvasSize.width() * style()->effectiveZoom(), canvasSize.height() * style()->effectiveZoom());
+
+    if (zoomedSize == intrinsicSize())
+        return;
+
+    setIntrinsicSize(zoomedSize);
+
+    if (!parent())
+        return;
+
+    if (!preferredLogicalWidthsDirty())
+        setPreferredLogicalWidthsDirty(true);
+
+    LayoutSize oldSize = size();
+    updateLogicalWidth();
+    updateLogicalHeight();
+    if (oldSize == size())
+        return;
+
+    if (!selfNeedsLayout())
+        setNeedsLayout(true);
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderHTMLCanvas.h b/Source/core/rendering/RenderHTMLCanvas.h
new file mode 100644
index 0000000..ffc1f22
--- /dev/null
+++ b/Source/core/rendering/RenderHTMLCanvas.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2004, 2006, 2007, 2009 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 "core/rendering/RenderReplaced.h"
+
+namespace WebCore {
+
+class HTMLCanvasElement;
+
+class RenderHTMLCanvas FINAL : public RenderReplaced {
+public:
+    explicit RenderHTMLCanvas(HTMLCanvasElement*);
+
+    virtual bool isCanvas() const { return true; }
+    virtual bool requiresLayer() const;
+
+    void canvasSizeChanged();
+    
+private:
+    virtual const char* renderName() const { return "RenderHTMLCanvas"; }
+    virtual void paintReplaced(PaintInfo&, const LayoutPoint&);
+    virtual void intrinsicSizeChanged() { canvasSizeChanged(); }
+};
+
+inline RenderHTMLCanvas* toRenderHTMLCanvas(RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isCanvas());
+    return static_cast<RenderHTMLCanvas*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderHTMLCanvas(const RenderHTMLCanvas*);
+
+} // namespace WebCore
+
+#endif // RenderHTMLCanvas_h
diff --git a/Source/core/rendering/RenderIFrame.cpp b/Source/core/rendering/RenderIFrame.cpp
new file mode 100644
index 0000000..e0c72c5
--- /dev/null
+++ b/Source/core/rendering/RenderIFrame.cpp
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2010 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 "core/rendering/RenderIFrame.h"
+
+#include "HTMLNames.h"
+#include "core/html/HTMLIFrameElement.h"
+#include "core/page/Frame.h"
+#include "core/page/FrameView.h"
+#include "core/page/Page.h"
+#include "core/page/Settings.h"
+#include "core/rendering/RenderView.h"
+
+namespace WebCore {
+
+using namespace HTMLNames;
+    
+RenderIFrame::RenderIFrame(Element* element)
+    : RenderFrameBase(element)
+{
+}
+
+bool RenderIFrame::shouldComputeSizeAsReplaced() const
+{
+    // When we're seamless, we use normal block/box sizing code except when inline.
+    return !isSeamless();
+}
+
+bool RenderIFrame::isInlineBlockOrInlineTable() const
+{
+    return isSeamless() && isInline();
+}
+
+LayoutUnit RenderIFrame::minPreferredLogicalWidth() const
+{
+    if (!isSeamless())
+        return RenderFrameBase::minPreferredLogicalWidth();
+
+    RenderView* childRoot = contentRootRenderer();
+    if (!childRoot)
+        return 0;
+
+    return childRoot->minPreferredLogicalWidth() + borderAndPaddingLogicalWidth();
+}
+
+LayoutUnit RenderIFrame::maxPreferredLogicalWidth() const
+{
+    if (!isSeamless())
+        return RenderFrameBase::maxPreferredLogicalWidth();
+
+    RenderView* childRoot = contentRootRenderer();
+    if (!childRoot)
+        return 0;
+
+    return childRoot->maxPreferredLogicalWidth() + borderAndPaddingLogicalWidth();
+}
+
+bool RenderIFrame::isSeamless() const
+{
+    return node() && node()->hasTagName(iframeTag) && static_cast<HTMLIFrameElement*>(node())->shouldDisplaySeamlessly();
+}
+
+bool RenderIFrame::requiresLayer() const
+{
+    return RenderFrameBase::requiresLayer() || style()->resize() != RESIZE_NONE;
+}
+
+RenderView* RenderIFrame::contentRootRenderer() const
+{
+    // FIXME: Is this always a valid cast? What about plugins?
+    ASSERT(!widget() || widget()->isFrameView());
+    FrameView* childFrameView = toFrameView(widget());
+    return childFrameView ? childFrameView->frame()->contentRenderer() : 0;
+}
+
+bool RenderIFrame::flattenFrame() const
+{
+    if (!node() || !node()->hasTagName(iframeTag))
+        return false;
+
+    HTMLIFrameElement* element = static_cast<HTMLIFrameElement*>(node());
+    Frame* frame = element->document()->frame();
+
+    if (isSeamless())
+        return false; // Seamless iframes are already "flat", don't try to flatten them.
+
+    bool enabled = frame && frame->settings() && frame->settings()->frameFlatteningEnabled();
+
+    if (!enabled || !frame->page())
+        return false;
+
+    if (style()->width().isFixed() && style()->height().isFixed()) {
+        // Do not flatten iframes with scrolling="no".
+        if (element->scrollingMode() == ScrollbarAlwaysOff)
+            return false;
+        if (style()->width().value() <= 0 || style()->height().value() <= 0)
+            return false;
+    }
+
+    // Do not flatten offscreen inner frames during frame flattening, as flattening might make them visible.
+    IntRect boundingRect = absoluteBoundingBoxRectIgnoringTransforms();
+    return boundingRect.maxX() > 0 && boundingRect.maxY() > 0;
+}
+
+void RenderIFrame::layoutSeamlessly()
+{
+    updateLogicalWidth();
+    // FIXME: Containers set their height to 0 before laying out their kids (as we're doing here)
+    // however, this causes FrameView::layout() to add vertical scrollbars, incorrectly inflating
+    // the resulting contentHeight(). We'll need to make FrameView::layout() smarter.
+    setLogicalHeight(0);
+    updateWidgetPosition(); // Tell the Widget about our new width/height (it will also layout the child document).
+
+    // Laying out our kids is normally responsible for adjusting our height, so we set it here.
+    // Replaced elements normally do not respect padding, but seamless elements should: we'll add
+    // both padding and border to the child's logical height here.
+    FrameView* childFrameView = toFrameView(widget());
+    if (childFrameView) // Widget should never be null during layout(), but just in case.
+        setLogicalHeight(childFrameView->contentsHeight() + borderTop() + borderBottom() + paddingTop() + paddingBottom());
+    updateLogicalHeight();
+
+    updateWidgetPosition(); // Notify the Widget of our final height.
+
+    // Assert that the child document did a complete layout.
+    RenderView* childRoot = childFrameView ? childFrameView->frame()->contentRenderer() : 0;
+    ASSERT(!childFrameView || !childFrameView->layoutPending());
+    ASSERT_UNUSED(childRoot, !childRoot || !childRoot->needsLayout());
+}
+
+void RenderIFrame::layout()
+{
+    StackStats::LayoutCheckPoint layoutCheckPoint;
+    ASSERT(needsLayout());
+
+    if (isSeamless()) {
+        layoutSeamlessly();
+        // Do not return so as to share the layer and overflow updates below.
+    } else {
+        updateLogicalWidth();
+        // No kids to layout as a replaced element.
+        updateLogicalHeight();
+
+        if (flattenFrame())
+            layoutWithFlattening(style()->width().isFixed(), style()->height().isFixed());
+    }
+
+    m_overflow.clear();
+    addVisualEffectOverflow();
+    updateLayerTransform();
+
+    setNeedsLayout(false);
+}
+
+}
diff --git a/Source/core/rendering/RenderIFrame.h b/Source/core/rendering/RenderIFrame.h
new file mode 100644
index 0000000..7bc8089
--- /dev/null
+++ b/Source/core/rendering/RenderIFrame.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2010 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 RenderIFrame_h
+#define RenderIFrame_h
+
+#include "core/rendering/RenderFrameBase.h"
+
+namespace WebCore {
+
+class RenderView;
+
+class RenderIFrame FINAL : public RenderFrameBase {
+public:
+    explicit RenderIFrame(Element*);
+
+    bool flattenFrame() const;
+    bool isSeamless() const;
+
+private:
+    virtual LayoutUnit minPreferredLogicalWidth() const OVERRIDE;
+    virtual LayoutUnit maxPreferredLogicalWidth() const OVERRIDE;
+
+    virtual bool shouldComputeSizeAsReplaced() const OVERRIDE;
+    virtual bool isInlineBlockOrInlineTable() const OVERRIDE;
+
+    virtual void layout() OVERRIDE;
+
+    virtual bool isRenderIFrame() const OVERRIDE { return true; }
+
+    virtual const char* renderName() const OVERRIDE { return "RenderPartObject"; } // Lying for now to avoid breaking tests
+
+    virtual bool requiresLayer() const OVERRIDE;
+
+    void layoutSeamlessly();
+
+    RenderView* contentRootRenderer() const;
+};
+
+inline RenderIFrame* toRenderIFrame(RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isRenderIFrame());
+    return static_cast<RenderIFrame*>(object);
+}
+
+inline const RenderIFrame* toRenderIFrame(const RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isRenderIFrame());
+    return static_cast<const RenderIFrame*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderIFrame(const RenderIFrame*);
+
+
+} // namespace WebCore
+
+#endif // RenderIFrame_h
diff --git a/Source/core/rendering/RenderImage.cpp b/Source/core/rendering/RenderImage.cpp
new file mode 100644
index 0000000..df2aa0a
--- /dev/null
+++ b/Source/core/rendering/RenderImage.cpp
@@ -0,0 +1,584 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2000 Dirk Mueller (mueller@kde.org)
+ *           (C) 2006 Allan Sandfeld Jensen (kde@carewolf.com)
+ *           (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ * Copyright (C) Research In Motion Limited 2011-2012. 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 "core/rendering/RenderImage.h"
+
+#include "HTMLNames.h"
+#include "core/editing/FrameSelection.h"
+#include "core/html/HTMLAreaElement.h"
+#include "core/html/HTMLImageElement.h"
+#include "core/html/HTMLInputElement.h"
+#include "core/html/HTMLMapElement.h"
+#include "core/loader/cache/CachedImage.h"
+#include "core/page/Frame.h"
+#include "core/page/Page.h"
+#include "core/platform/graphics/BitmapImage.h"
+#include "core/platform/graphics/Font.h"
+#include "core/platform/graphics/FontCache.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/rendering/HitTestResult.h"
+#include "core/rendering/PaintInfo.h"
+#include "core/rendering/RenderView.h"
+#include "core/svg/graphics/SVGImage.h"
+#include <wtf/UnusedParam.h>
+
+using namespace std;
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+RenderImage::RenderImage(Element* element)
+    : RenderReplaced(element, IntSize())
+    , m_needsToSetSizeForAltText(false)
+    , m_didIncrementVisuallyNonEmptyPixelCount(false)
+    , m_isGeneratedContent(false)
+{
+    updateAltText();
+}
+
+RenderImage* RenderImage::createAnonymous(Document* document)
+{
+    RenderImage* image = new (document->renderArena()) RenderImage(0);
+    image->setDocumentForAnonymous(document);
+    return image;
+}
+
+RenderImage::~RenderImage()
+{
+    ASSERT(m_imageResource);
+    m_imageResource->shutdown();
+}
+
+void RenderImage::setImageResource(PassOwnPtr<RenderImageResource> imageResource)
+{
+    ASSERT(!m_imageResource);
+    m_imageResource = imageResource;
+    m_imageResource->initialize(this);
+}
+
+// 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 float maxAltTextWidth = 1024;
+static const int maxAltTextHeight = 256;
+
+IntSize RenderImage::imageSizeForError(CachedImage* newImage) const
+{
+    ASSERT_ARG(newImage, newImage);
+    ASSERT_ARG(newImage, newImage->imageForRenderer(this));
+
+    IntSize imageSize;
+    if (newImage->willPaintBrokenImage()) {
+        float deviceScaleFactor = WebCore::deviceScaleFactor(frame());
+        pair<Image*, float> brokenImageAndImageScaleFactor = newImage->brokenImage(deviceScaleFactor);
+        imageSize = brokenImageAndImageScaleFactor.first->size();
+        imageSize.scale(1 / brokenImageAndImageScaleFactor.second);
+    } else
+        imageSize = newImage->imageForRenderer(this)->size();
+
+    // 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.
+    return IntSize(paddingWidth + imageSize.width() * style()->effectiveZoom(), paddingHeight + imageSize.height() * style()->effectiveZoom());
+}
+
+// Sets the image height and width to fit the alt text.  Returns true if the
+// image size changed.
+bool RenderImage::setImageSizeForAltText(CachedImage* newImage /* = 0 */)
+{
+    IntSize imageSize;
+    if (newImage && newImage->imageForRenderer(this))
+        imageSize = imageSizeForError(newImage);
+    else if (!m_altText.isEmpty() || newImage) {
+        // If we'll be displaying either text or an image, add a little padding.
+        imageSize = IntSize(paddingWidth, paddingHeight);
+    }
+
+    // we have an alt and the user meant it (its not a text we invented)
+    if (!m_altText.isEmpty()) {
+        FontCachePurgePreventer fontCachePurgePreventer;
+
+        const Font& font = style()->font();
+        IntSize paddedTextSize(paddingWidth + min(ceilf(font.width(RenderBlock::constructTextRun(this, font, m_altText, style()))), maxAltTextWidth), paddingHeight + min(font.fontMetrics().height(), maxAltTextHeight));
+        imageSize = imageSize.expandedTo(paddedTextSize);
+    }
+
+    if (imageSize == intrinsicSize())
+        return false;
+
+    setIntrinsicSize(imageSize);
+    return true;
+}
+
+void RenderImage::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
+{
+    RenderReplaced::styleDidChange(diff, oldStyle);
+    if (m_needsToSetSizeForAltText) {
+        if (!m_altText.isEmpty() && setImageSizeForAltText(m_imageResource->cachedImage()))
+            imageDimensionsChanged(true /* imageSizeChanged */);
+        m_needsToSetSizeForAltText = false;
+    }
+}
+
+void RenderImage::imageChanged(WrappedImagePtr newImage, const IntRect* rect)
+{
+    if (documentBeingDestroyed())
+        return;
+
+    if (hasBoxDecorations() || hasMask())
+        RenderReplaced::imageChanged(newImage, rect);
+
+    if (!m_imageResource)
+        return;
+
+    if (newImage != m_imageResource->imagePtr() || !newImage)
+        return;
+    
+    if (!m_didIncrementVisuallyNonEmptyPixelCount) {
+        // At a zoom level of 1 the image is guaranteed to have an integer size.
+        view()->frameView()->incrementVisuallyNonEmptyPixelCount(flooredIntSize(m_imageResource->imageSize(1.0f)));
+        m_didIncrementVisuallyNonEmptyPixelCount = true;
+    }
+
+    bool imageSizeChanged = false;
+
+    // Set image dimensions, taking into account the size of the alt text.
+    if (m_imageResource->errorOccurred()) {
+        if (!m_altText.isEmpty() && document()->hasPendingStyleRecalc()) {
+            ASSERT(node());
+            if (node()) {
+                m_needsToSetSizeForAltText = true;
+                node()->setNeedsStyleRecalc(SyntheticStyleChange);
+            }
+            return;
+        }
+        imageSizeChanged = setImageSizeForAltText(m_imageResource->cachedImage());
+    }
+
+    imageDimensionsChanged(imageSizeChanged, rect);
+}
+
+bool RenderImage::updateIntrinsicSizeIfNeeded(const LayoutSize& newSize, bool imageSizeChanged)
+{
+    if (newSize == intrinsicSize() && !imageSizeChanged)
+        return false;
+    if (m_imageResource->errorOccurred())
+        return imageSizeChanged;
+    setIntrinsicSize(newSize);
+    return true;
+}
+
+void RenderImage::imageDimensionsChanged(bool imageSizeChanged, const IntRect* rect)
+{
+    bool intrinsicSizeChanged = updateIntrinsicSizeIfNeeded(m_imageResource->imageSize(style()->effectiveZoom()), imageSizeChanged);
+
+    // In the case of generated image content using :before/:after/content, we might not be
+    // in the render tree yet. In that case, we just need to update our intrinsic size.
+    // layout() will be called after we are inserted in the tree which will take care of
+    // what we are doing here.
+    if (!containingBlock())
+        return;
+
+    bool shouldRepaint = true;
+    if (intrinsicSizeChanged) {
+        if (!preferredLogicalWidthsDirty())
+            setPreferredLogicalWidthsDirty(true);
+
+        bool hasOverrideSize = hasOverrideHeight() || hasOverrideWidth();
+        if (!hasOverrideSize && !imageSizeChanged) {
+            LogicalExtentComputedValues computedValues;
+            computeLogicalWidthInRegion(computedValues);
+            LayoutUnit newWidth = computedValues.m_extent;
+            computeLogicalHeight(height(), 0, computedValues);
+            LayoutUnit newHeight = computedValues.m_extent;
+
+            imageSizeChanged = width() != newWidth || height() != newHeight;
+        }
+
+        // FIXME: We only need to recompute the containing block's preferred size
+        // if the containing block's size depends on the image's size (i.e., the container uses shrink-to-fit sizing).
+        // There's no easy way to detect that shrink-to-fit is needed, always force a layout.
+        bool containingBlockNeedsToRecomputePreferredSize =
+            style()->logicalWidth().isPercent()
+            || style()->logicalMaxWidth().isPercent()
+            || style()->logicalMinWidth().isPercent();
+
+        if (imageSizeChanged || hasOverrideSize || containingBlockNeedsToRecomputePreferredSize) {
+            shouldRepaint = false;
+            if (!selfNeedsLayout())
+                setNeedsLayout(true);
+        }
+    }
+
+    if (shouldRepaint) {
+        LayoutRect repaintRect;
+        if (rect) {
+            // The image changed rect is in source image coordinates (pre-zooming),
+            // so map from the bounds of the image to the contentsBox.
+            repaintRect = enclosingIntRect(mapRect(*rect, FloatRect(FloatPoint(), m_imageResource->imageSize(1.0f)), contentBoxRect()));
+            // Guard against too-large changed rects.
+            repaintRect.intersect(contentBoxRect());
+        } else
+            repaintRect = contentBoxRect();
+        
+        repaintRectangle(repaintRect);
+
+        // Tell any potential compositing layers that the image needs updating.
+        contentChanged(ImageChanged);
+    }
+}
+
+void RenderImage::notifyFinished(CachedResource* newImage)
+{
+    if (!m_imageResource)
+        return;
+    
+    if (documentBeingDestroyed())
+        return;
+
+    invalidateBackgroundObscurationStatus();
+
+    if (newImage == m_imageResource->cachedImage()) {
+        // tell any potential compositing layers
+        // that the image is done and they can reference it directly.
+        contentChanged(ImageChanged);
+    }
+}
+
+void RenderImage::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    LayoutUnit cWidth = contentWidth();
+    LayoutUnit cHeight = contentHeight();
+    LayoutUnit leftBorder = borderLeft();
+    LayoutUnit topBorder = borderTop();
+    LayoutUnit leftPad = paddingLeft();
+    LayoutUnit topPad = paddingTop();
+
+    GraphicsContext* context = paintInfo.context;
+
+    Page* page = 0;
+    if (Frame* frame = this->frame())
+        page = frame->page();
+
+    if (!m_imageResource->hasImage() || m_imageResource->errorOccurred()) {
+        if (paintInfo.phase == PaintPhaseSelection)
+            return;
+
+        if (page && paintInfo.phase == PaintPhaseForeground)
+            page->addRelevantUnpaintedObject(this, visualOverflowRect());
+
+        if (cWidth > 2 && cHeight > 2) {
+            const int borderWidth = 1;
+
+            // Draw an outline rect where the image should be.
+            context->setStrokeStyle(SolidStroke);
+            context->setStrokeColor(Color::lightGray, style()->colorSpace());
+            context->setFillColor(Color::transparent, style()->colorSpace());
+            context->drawRect(pixelSnappedIntRect(LayoutRect(paintOffset.x() + leftBorder + leftPad, paintOffset.y() + topBorder + topPad, cWidth, cHeight)));
+
+            bool errorPictureDrawn = false;
+            LayoutSize imageOffset;
+            // When calculating the usable dimensions, exclude the pixels of
+            // the ouline rect so the error image/alt text doesn't draw on it.
+            LayoutUnit usableWidth = cWidth - 2 * borderWidth;
+            LayoutUnit usableHeight = cHeight - 2 * borderWidth;
+
+            RefPtr<Image> image = m_imageResource->image();
+
+            if (m_imageResource->errorOccurred() && !image->isNull() && usableWidth >= image->width() && usableHeight >= image->height()) {
+                float deviceScaleFactor = WebCore::deviceScaleFactor(frame());
+                // Call brokenImage() explicitly to ensure we get the broken image icon at the appropriate resolution.
+                pair<Image*, float> brokenImageAndImageScaleFactor = m_imageResource->cachedImage()->brokenImage(deviceScaleFactor);
+                image = brokenImageAndImageScaleFactor.first;
+                IntSize imageSize = image->size();
+                imageSize.scale(1 / brokenImageAndImageScaleFactor.second);
+                // Center the error image, accounting for border and padding.
+                LayoutUnit centerX = (usableWidth - imageSize.width()) / 2;
+                if (centerX < 0)
+                    centerX = 0;
+                LayoutUnit centerY = (usableHeight - imageSize.height()) / 2;
+                if (centerY < 0)
+                    centerY = 0;
+                imageOffset = LayoutSize(leftBorder + leftPad + centerX + borderWidth, topBorder + topPad + centerY + borderWidth);
+                context->drawImage(image.get(), style()->colorSpace(), pixelSnappedIntRect(LayoutRect(paintOffset + imageOffset, imageSize)), CompositeSourceOver, shouldRespectImageOrientation());
+                errorPictureDrawn = true;
+            }
+
+            if (!m_altText.isEmpty()) {
+                String text = document()->displayStringModifiedByEncoding(m_altText);
+                context->setFillColor(style()->visitedDependentColor(CSSPropertyColor), style()->colorSpace());
+                const Font& font = style()->font();
+                const FontMetrics& fontMetrics = font.fontMetrics();
+                LayoutUnit ascent = fontMetrics.ascent();
+                LayoutPoint altTextOffset = paintOffset;
+                altTextOffset.move(leftBorder + leftPad + (paddingWidth / 2) - borderWidth, topBorder + topPad + ascent + (paddingHeight / 2) - borderWidth);
+
+                // Only draw the alt text if it'll fit within the content box,
+                // and only if it fits above the error image.
+                TextRun textRun = RenderBlock::constructTextRun(this, font, text, style());
+                LayoutUnit textWidth = font.width(textRun);
+                if (errorPictureDrawn) {
+                    if (usableWidth >= textWidth && fontMetrics.height() <= imageOffset.height())
+                        context->drawText(font, textRun, altTextOffset);
+                } else if (usableWidth >= textWidth && usableHeight >= fontMetrics.height())
+                    context->drawText(font, textRun, altTextOffset);
+            }
+        }
+    } else if (m_imageResource->hasImage() && cWidth > 0 && cHeight > 0) {
+        RefPtr<Image> img = m_imageResource->image(cWidth, cHeight);
+        if (!img || img->isNull()) {
+            if (page && paintInfo.phase == PaintPhaseForeground)
+                page->addRelevantUnpaintedObject(this, visualOverflowRect());
+            return;
+        }
+
+        LayoutSize contentSize(cWidth, cHeight);
+        LayoutPoint contentLocation = paintOffset;
+        contentLocation.move(leftBorder + leftPad, topBorder + topPad);
+        paintIntoRect(context, LayoutRect(contentLocation, contentSize));
+        
+        if (cachedImage() && page && paintInfo.phase == PaintPhaseForeground) {
+            // For now, count images as unpainted if they are still progressively loading. We may want 
+            // to refine this in the future to account for the portion of the image that has painted.
+            if (cachedImage()->isLoading())
+                page->addRelevantUnpaintedObject(this, LayoutRect(contentLocation, contentSize));
+            else
+                page->addRelevantRepaintedObject(this, LayoutRect(contentLocation, contentSize));
+        }
+    }
+}
+
+void RenderImage::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    RenderReplaced::paint(paintInfo, paintOffset);
+    
+    if (paintInfo.phase == PaintPhaseOutline)
+        paintAreaElementFocusRing(paintInfo);
+}
+    
+void RenderImage::paintAreaElementFocusRing(PaintInfo& paintInfo)
+{
+    Document* document = this->document();
+    
+    if (document->printing() || !document->frame()->selection()->isFocusedAndActive())
+        return;
+    
+    if (paintInfo.context->paintingDisabled() && !paintInfo.context->updatingControlTints())
+        return;
+
+    Node* focusedNode = document->focusedNode();
+    if (!focusedNode || !focusedNode->hasTagName(areaTag))
+        return;
+
+    HTMLAreaElement* areaElement = static_cast<HTMLAreaElement*>(focusedNode);
+    if (areaElement->imageElement() != node())
+        return;
+
+    // Even if the theme handles focus ring drawing for entire elements, it won't do it for
+    // an area within an image, so we don't call RenderTheme::supportsFocusRing here.
+
+    Path path = areaElement->computePath(this);
+    if (path.isEmpty())
+        return;
+
+    // FIXME: Do we need additional code to clip the path to the image's bounding box?
+
+    RenderStyle* areaElementStyle = areaElement->computedStyle();
+    unsigned short outlineWidth = areaElementStyle->outlineWidth();
+    if (!outlineWidth)
+        return;
+
+    paintInfo.context->drawFocusRing(path, outlineWidth,
+        areaElementStyle->outlineOffset(),
+        areaElementStyle->visitedDependentColor(CSSPropertyOutlineColor));
+}
+
+void RenderImage::areaElementFocusChanged(HTMLAreaElement* element)
+{
+    ASSERT_UNUSED(element, element->imageElement() == node());
+
+    // It would be more efficient to only repaint the focus ring rectangle
+    // for the passed-in area element. That would require adding functions
+    // to the area element class.
+    repaint();
+}
+
+void RenderImage::paintIntoRect(GraphicsContext* context, const LayoutRect& rect)
+{
+    IntRect alignedRect = pixelSnappedIntRect(rect);
+    if (!m_imageResource->hasImage() || m_imageResource->errorOccurred() || alignedRect.width() <= 0 || alignedRect.height() <= 0)
+        return;
+
+    RefPtr<Image> img = m_imageResource->image(alignedRect.width(), alignedRect.height());
+    if (!img || img->isNull())
+        return;
+
+    HTMLImageElement* imageElt = (node() && node()->hasTagName(imgTag)) ? static_cast<HTMLImageElement*>(node()) : 0;
+    CompositeOperator compositeOperator = imageElt ? imageElt->compositeOperator() : CompositeSourceOver;
+    Image* image = m_imageResource->image().get();
+    bool useLowQualityScaling = shouldPaintAtLowQuality(context, image, image, alignedRect.size());
+    context->drawImage(m_imageResource->image(alignedRect.width(), alignedRect.height()).get(), style()->colorSpace(), alignedRect, compositeOperator, shouldRespectImageOrientation(), useLowQualityScaling);
+}
+
+bool RenderImage::boxShadowShouldBeAppliedToBackground(BackgroundBleedAvoidance bleedAvoidance, InlineFlowBox*) const
+{
+    if (!RenderBoxModelObject::boxShadowShouldBeAppliedToBackground(bleedAvoidance))
+        return false;
+
+    return !const_cast<RenderImage*>(this)->backgroundIsKnownToBeObscured();
+}
+
+bool RenderImage::foregroundIsKnownToBeOpaqueInRect(const LayoutRect& localRect, unsigned maxDepthToTest) const
+{
+    UNUSED_PARAM(maxDepthToTest);
+    if (!m_imageResource->hasImage() || m_imageResource->errorOccurred())
+        return false;
+    if (m_imageResource->cachedImage() && !m_imageResource->cachedImage()->isLoaded())
+        return false;
+    if (!contentBoxRect().contains(localRect))
+        return false;
+    EFillBox backgroundClip = style()->backgroundClip();
+    // Background paints under borders.
+    if (backgroundClip == BorderFillBox && style()->hasBorder() && !borderObscuresBackground())
+        return false;
+    // Background shows in padding area.
+    if ((backgroundClip == BorderFillBox || backgroundClip == PaddingFillBox) && style()->hasPadding())
+        return false;
+    // Check for image with alpha.
+    return m_imageResource->cachedImage() && m_imageResource->cachedImage()->currentFrameKnownToBeOpaque(this);
+}
+
+bool RenderImage::computeBackgroundIsKnownToBeObscured()
+{
+    if (!hasBackground())
+        return false;
+    return foregroundIsKnownToBeOpaqueInRect(backgroundPaintedExtent(), 0);
+}
+
+LayoutUnit RenderImage::minimumReplacedHeight() const
+{
+    return m_imageResource->errorOccurred() ? intrinsicSize().height() : LayoutUnit();
+}
+
+HTMLMapElement* RenderImage::imageMap() const
+{
+    HTMLImageElement* i = node() && node()->hasTagName(imgTag) ? static_cast<HTMLImageElement*>(node()) : 0;
+    return i ? i->treeScope()->getImageMap(i->fastGetAttribute(usemapAttr)) : 0;
+}
+
+bool RenderImage::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
+{
+    HitTestResult tempResult(result.hitTestLocation());
+    bool inside = RenderReplaced::nodeAtPoint(request, tempResult, locationInContainer, accumulatedOffset, hitTestAction);
+
+    if (tempResult.innerNode() && node()) {
+        if (HTMLMapElement* map = imageMap()) {
+            LayoutRect contentBox = contentBoxRect();
+            float scaleFactor = 1 / style()->effectiveZoom();
+            LayoutPoint mapLocation = locationInContainer.point() - toLayoutSize(accumulatedOffset) - locationOffset() - toLayoutSize(contentBox.location());
+            mapLocation.scale(scaleFactor, scaleFactor);
+
+            if (map->mapMouseEvent(mapLocation, contentBox.size(), tempResult))
+                tempResult.setInnerNonSharedNode(node());
+        }
+    }
+
+    if (!inside && result.isRectBasedTest())
+        result.append(tempResult);
+    if (inside)
+        result = tempResult;
+    return inside;
+}
+
+void RenderImage::updateAltText()
+{
+    if (!node())
+        return;
+
+    if (node()->hasTagName(inputTag))
+        m_altText = static_cast<HTMLInputElement*>(node())->altText();
+    else if (node()->hasTagName(imgTag))
+        m_altText = static_cast<HTMLImageElement*>(node())->altText();
+}
+
+void RenderImage::layout()
+{
+    StackStats::LayoutCheckPoint layoutCheckPoint;
+    RenderReplaced::layout();
+
+    // Propagate container size to image resource.
+    IntSize containerSize(contentWidth(), contentHeight());
+    if (!containerSize.isEmpty())
+        m_imageResource->setContainerSizeForRenderer(containerSize);
+}
+
+void RenderImage::computeIntrinsicRatioInformation(FloatSize& intrinsicSize, double& intrinsicRatio, bool& isPercentageIntrinsicSize) const
+{
+    RenderReplaced::computeIntrinsicRatioInformation(intrinsicSize, intrinsicRatio, isPercentageIntrinsicSize);
+
+    // Our intrinsicSize is empty if we're rendering generated images with relative width/height. Figure out the right intrinsic size to use.
+    if (intrinsicSize.isEmpty() && (m_imageResource->imageHasRelativeWidth() || m_imageResource->imageHasRelativeHeight())) {
+        RenderObject* containingBlock = isOutOfFlowPositioned() ? container() : this->containingBlock();
+        if (containingBlock->isBox()) {
+            RenderBox* box = toRenderBox(containingBlock);
+            intrinsicSize.setWidth(box->availableLogicalWidth());
+            intrinsicSize.setHeight(box->availableLogicalHeight(IncludeMarginBorderPadding));
+        }
+    }
+    // Don't compute an intrinsic ratio to preserve historical WebKit behavior if we're painting alt text and/or a broken image.
+    if (m_imageResource && m_imageResource->errorOccurred()) {
+        intrinsicRatio = 1;
+        return;
+    }
+}
+
+bool RenderImage::needsPreferredWidthsRecalculation() const
+{
+    if (RenderReplaced::needsPreferredWidthsRecalculation())
+        return true;
+    return embeddedContentBox();
+}
+
+RenderBox* RenderImage::embeddedContentBox() const
+{
+    if (!m_imageResource)
+        return 0;
+
+#if ENABLE(SVG)
+    CachedImage* cachedImage = m_imageResource->cachedImage();
+    if (cachedImage && cachedImage->image() && cachedImage->image()->isSVGImage())
+        return static_cast<SVGImage*>(cachedImage->image())->embeddedContentBox();
+#endif
+
+    return 0;
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderImage.h b/Source/core/rendering/RenderImage.h
new file mode 100644
index 0000000..81c7cea
--- /dev/null
+++ b/Source/core/rendering/RenderImage.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2006 Allan Sandfeld Jensen (kde@carewolf.com) 
+ *           (C) 2006 Samuel Weinig (sam.weinig@gmail.com)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010, 2011 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 "core/rendering/RenderImageResource.h"
+#include "core/rendering/RenderReplaced.h"
+
+namespace WebCore {
+
+class HTMLAreaElement;
+class HTMLMapElement;
+
+class RenderImage : public RenderReplaced {
+public:
+    RenderImage(Element*);
+    virtual ~RenderImage();
+
+    static RenderImage* createAnonymous(Document*);
+
+    void setImageResource(PassOwnPtr<RenderImageResource>);
+
+    RenderImageResource* imageResource() { return m_imageResource.get(); }
+    const RenderImageResource* imageResource() const { return m_imageResource.get(); }
+    CachedImage* cachedImage() const { return m_imageResource ? m_imageResource->cachedImage() : 0; }
+
+    bool setImageSizeForAltText(CachedImage* newImage = 0);
+
+    void updateAltText();
+
+    HTMLMapElement* imageMap() const;
+    void areaElementFocusChanged(HTMLAreaElement*);
+
+    void highQualityRepaintTimerFired(Timer<RenderImage>*);
+
+    void setIsGeneratedContent(bool generated = true) { m_isGeneratedContent = generated; }
+
+    bool isGeneratedContent() const { return m_isGeneratedContent; }
+
+    String altText() const { return m_altText; }
+
+protected:
+    virtual bool needsPreferredWidthsRecalculation() const OVERRIDE FINAL;
+    virtual RenderBox* embeddedContentBox() const OVERRIDE FINAL;
+    virtual void computeIntrinsicRatioInformation(FloatSize& intrinsicSize, double& intrinsicRatio, bool& isPercentageIntrinsicSize) const OVERRIDE FINAL;
+
+    virtual void styleDidChange(StyleDifference, const RenderStyle*) OVERRIDE FINAL;
+
+    virtual void imageChanged(WrappedImagePtr, const IntRect* = 0);
+
+    void paintIntoRect(GraphicsContext*, const LayoutRect&);
+    virtual void paint(PaintInfo&, const LayoutPoint&) OVERRIDE FINAL;
+    virtual void layout();
+
+    virtual void intrinsicSizeChanged()
+    {
+        if (m_imageResource)
+            imageChanged(m_imageResource->imagePtr());
+    }
+
+private:
+    virtual const char* renderName() const { return "RenderImage"; }
+
+    virtual bool isImage() const { return true; }
+    virtual bool isRenderImage() const OVERRIDE FINAL { return true; }
+
+    virtual void paintReplaced(PaintInfo&, const LayoutPoint&);
+
+    virtual bool foregroundIsKnownToBeOpaqueInRect(const LayoutRect& localRect, unsigned maxDepthToTest) const OVERRIDE FINAL;
+    virtual bool computeBackgroundIsKnownToBeObscured() OVERRIDE FINAL;
+
+    virtual LayoutUnit minimumReplacedHeight() const OVERRIDE;
+
+    virtual void notifyFinished(CachedResource*) OVERRIDE FINAL;
+    virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE FINAL;
+
+    virtual bool boxShadowShouldBeAppliedToBackground(BackgroundBleedAvoidance, InlineFlowBox*) const OVERRIDE FINAL;
+
+    IntSize imageSizeForError(CachedImage*) const;
+    void imageDimensionsChanged(bool imageSizeChanged, const IntRect* = 0);
+    bool updateIntrinsicSizeIfNeeded(const LayoutSize&, bool imageSizeChanged);
+
+    void paintAreaElementFocusRing(PaintInfo&);
+
+    // Text to display as long as the image isn't available.
+    String m_altText;
+    OwnPtr<RenderImageResource> m_imageResource;
+    bool m_needsToSetSizeForAltText;
+    bool m_didIncrementVisuallyNonEmptyPixelCount;
+    bool m_isGeneratedContent;
+
+    friend class RenderImageScaleObserver;
+};
+
+inline RenderImage* toRenderImage(RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isRenderImage());
+    return static_cast<RenderImage*>(object);
+}
+
+inline const RenderImage* toRenderImage(const RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isRenderImage());
+    return static_cast<const RenderImage*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderImage(const RenderImage*);
+
+} // namespace WebCore
+
+#endif // RenderImage_h
diff --git a/Source/core/rendering/RenderImageResource.cpp b/Source/core/rendering/RenderImageResource.cpp
new file mode 100644
index 0000000..87b7788
--- /dev/null
+++ b/Source/core/rendering/RenderImageResource.cpp
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 1999 Lars Knoll <knoll@kde.org>
+ * Copyright (C) 1999 Antti Koivisto <koivisto@kde.org>
+ * Copyright (C) 2000 Dirk Mueller <mueller@kde.org>
+ * Copyright (C) 2006 Allan Sandfeld Jensen <kde@carewolf.com>
+ * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
+ * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com>
+ *
+ * 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 "core/rendering/RenderImageResource.h"
+
+#include "core/loader/cache/CachedImage.h"
+#include "core/platform/graphics/Image.h"
+#include "core/rendering/RenderImageResourceStyleImage.h"
+#include "core/rendering/RenderObject.h"
+
+namespace WebCore {
+
+RenderImageResource::RenderImageResource()
+    : m_renderer(0)
+    , m_cachedImage(0)
+{
+}
+
+RenderImageResource::~RenderImageResource()
+{
+}
+
+void RenderImageResource::initialize(RenderObject* renderer)
+{
+    ASSERT(!m_renderer);
+    ASSERT(renderer);
+    m_renderer = renderer;
+}
+
+void RenderImageResource::shutdown()
+{
+    ASSERT(m_renderer);
+
+    if (m_cachedImage)
+        m_cachedImage->removeClient(m_renderer);
+}
+
+void RenderImageResource::setCachedImage(CachedImage* newImage)
+{
+    ASSERT(m_renderer);
+
+    if (m_cachedImage == newImage)
+        return;
+
+    if (m_cachedImage)
+        m_cachedImage->removeClient(m_renderer);
+    m_cachedImage = newImage;
+    if (m_cachedImage) {
+        m_cachedImage->addClient(m_renderer);
+        if (m_cachedImage->errorOccurred())
+            m_renderer->imageChanged(m_cachedImage.get());
+    }
+}
+
+void RenderImageResource::resetAnimation()
+{
+    ASSERT(m_renderer);
+
+    if (!m_cachedImage)
+        return;
+
+    image()->resetAnimation();
+
+    if (!m_renderer->needsLayout())
+        m_renderer->repaint();
+}
+
+void RenderImageResource::setContainerSizeForRenderer(const IntSize& imageContainerSize)
+{
+    ASSERT(m_renderer);
+    if (m_cachedImage)
+        m_cachedImage->setContainerSizeForRenderer(m_renderer, imageContainerSize, m_renderer->style()->effectiveZoom());
+}
+
+Image* RenderImageResource::nullImage()
+{
+    return Image::nullImage();
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderImageResource.h b/Source/core/rendering/RenderImageResource.h
new file mode 100644
index 0000000..d908753
--- /dev/null
+++ b/Source/core/rendering/RenderImageResource.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 1999 Lars Knoll <knoll@kde.org>
+ * Copyright (C) 1999 Antti Koivisto <koivisto@kde.org>
+ * Copyright (C) 2006 Allan Sandfeld Jensen <kde@carewolf.com>
+ * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
+ * Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com>
+ *
+ * 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 RenderImageResource_h
+#define RenderImageResource_h
+
+#include "core/loader/cache/CachedImage.h"
+#include "core/loader/cache/CachedResourceHandle.h"
+#include "core/platform/graphics/Image.h"
+#include "core/platform/graphics/LayoutSize.h"
+#include "core/rendering/style/StyleImage.h"
+
+namespace WebCore {
+
+class RenderObject;
+
+class RenderImageResource {
+    WTF_MAKE_NONCOPYABLE(RenderImageResource); WTF_MAKE_FAST_ALLOCATED;
+public:
+    virtual ~RenderImageResource();
+
+    static PassOwnPtr<RenderImageResource> create()
+    {
+        return adoptPtr(new RenderImageResource);
+    }
+
+    virtual void initialize(RenderObject*);
+    virtual void shutdown();
+
+    void setCachedImage(CachedImage*);
+    CachedImage* cachedImage() const { return m_cachedImage.get(); }
+    virtual bool hasImage() const { return m_cachedImage; }
+
+    void resetAnimation();
+
+    virtual PassRefPtr<Image> image(int /* width */ = 0, int /* height */ = 0) const { return m_cachedImage ? m_cachedImage->imageForRenderer(m_renderer) : nullImage(); }
+    virtual bool errorOccurred() const { return m_cachedImage && m_cachedImage->errorOccurred(); }
+
+    virtual void setContainerSizeForRenderer(const IntSize&);
+    virtual bool usesImageContainerSize() const { return m_cachedImage ? m_cachedImage->usesImageContainerSize() : false; }
+    virtual bool imageHasRelativeWidth() const { return m_cachedImage ? m_cachedImage->imageHasRelativeWidth() : false; }
+    virtual bool imageHasRelativeHeight() const { return m_cachedImage ? m_cachedImage->imageHasRelativeHeight() : false; }
+
+    virtual LayoutSize imageSize(float multiplier) const { return m_cachedImage ? m_cachedImage->imageSizeForRenderer(m_renderer, multiplier) : LayoutSize(); }
+
+    virtual WrappedImagePtr imagePtr() const { return m_cachedImage.get(); }
+
+protected:
+    RenderImageResource();
+    RenderObject* m_renderer;
+    CachedResourceHandle<CachedImage> m_cachedImage;
+
+private:
+    static Image* nullImage();
+};
+
+} // namespace WebCore
+
+#endif // RenderImage_h
diff --git a/Source/core/rendering/RenderImageResourceStyleImage.cpp b/Source/core/rendering/RenderImageResourceStyleImage.cpp
new file mode 100644
index 0000000..4580e15
--- /dev/null
+++ b/Source/core/rendering/RenderImageResourceStyleImage.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 1999 Lars Knoll <knoll@kde.org>
+ * Copyright (C) 1999 Antti Koivisto <koivisto@kde.org>
+ * Copyright (C) 2000 Dirk Mueller <mueller@kde.org>
+ * Copyright (C) 2006 Allan Sandfeld Jensen <kde@carewolf.com>
+ * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
+ * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com>
+ *
+ * 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 "core/rendering/RenderImageResourceStyleImage.h"
+
+#include "core/loader/cache/CachedImage.h"
+#include "core/rendering/RenderObject.h"
+#include "core/rendering/style/StyleCachedImage.h"
+
+namespace WebCore {
+
+RenderImageResourceStyleImage::RenderImageResourceStyleImage(StyleImage* styleImage)
+    : m_styleImage(styleImage)
+{
+    ASSERT(m_styleImage);
+}
+
+RenderImageResourceStyleImage::~RenderImageResourceStyleImage()
+{
+}
+
+void RenderImageResourceStyleImage::initialize(RenderObject* renderer)
+{
+    RenderImageResource::initialize(renderer);
+
+    if (m_styleImage->isCachedImage())
+        m_cachedImage = static_cast<StyleCachedImage*>(m_styleImage.get())->cachedImage();
+
+    m_styleImage->addClient(m_renderer);
+}
+
+void RenderImageResourceStyleImage::shutdown()
+{
+    ASSERT(m_renderer);
+    m_styleImage->removeClient(m_renderer);
+    m_cachedImage = 0;
+}
+
+PassRefPtr<Image> RenderImageResourceStyleImage::image(int width, int height) const
+{
+    // Generated content may trigger calls to image() while we're still pending, don't assert but gracefully exit.
+    if (m_styleImage->isPendingImage())
+        return 0;
+    return m_styleImage->image(m_renderer, IntSize(width, height));
+}
+
+void RenderImageResourceStyleImage::setContainerSizeForRenderer(const IntSize& size)
+{
+    ASSERT(m_renderer);
+    m_styleImage->setContainerSizeForRenderer(m_renderer, size, m_renderer->style()->effectiveZoom());
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderImageResourceStyleImage.h b/Source/core/rendering/RenderImageResourceStyleImage.h
new file mode 100644
index 0000000..9593635
--- /dev/null
+++ b/Source/core/rendering/RenderImageResourceStyleImage.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 1999 Lars Knoll <knoll@kde.org>
+ * Copyright (C) 1999 Antti Koivisto <koivisto@kde.org>
+ * Copyright (C) 2006 Allan Sandfeld Jensen <kde@carewolf.com>
+ * Copyright (C) 2006 Samuel Weinig <sam.weinig@gmail.com>
+ * Copyright (C) 2004, 2005, 2006, 2007, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com>
+ *
+ * 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 RenderImageResourceStyleImage_h
+#define RenderImageResourceStyleImage_h
+
+#include "core/rendering/RenderImageResource.h"
+#include "core/rendering/style/StyleImage.h"
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class RenderObject;
+
+class RenderImageResourceStyleImage : public RenderImageResource {
+public:
+    virtual ~RenderImageResourceStyleImage();
+
+    static PassOwnPtr<RenderImageResource> create(StyleImage* styleImage)
+    {
+        return adoptPtr(new RenderImageResourceStyleImage(styleImage));
+    }
+    virtual void initialize(RenderObject*);
+    virtual void shutdown();
+
+    virtual bool hasImage() const { return true; }
+    virtual PassRefPtr<Image> image(int width = 0, int height = 0) const;
+    virtual bool errorOccurred() const { return m_styleImage->errorOccurred(); }
+
+    virtual void setContainerSizeForRenderer(const IntSize&);
+    virtual bool usesImageContainerSize() const { return m_styleImage->usesImageContainerSize(); }
+    virtual bool imageHasRelativeWidth() const { return m_styleImage->imageHasRelativeWidth(); }
+    virtual bool imageHasRelativeHeight() const { return m_styleImage->imageHasRelativeHeight(); }
+
+    virtual LayoutSize imageSize(float multiplier) const OVERRIDE { return m_styleImage->imageSize(m_renderer, multiplier); }
+
+    virtual WrappedImagePtr imagePtr() const { return m_styleImage->data(); }
+
+private:
+    RenderImageResourceStyleImage(StyleImage*);
+    RefPtr<StyleImage> m_styleImage;
+};
+
+} // namespace WebCore
+
+#endif // RenderImageStyleImage_h
diff --git a/Source/core/rendering/RenderInline.cpp b/Source/core/rendering/RenderInline.cpp
new file mode 100644
index 0000000..7d92f61
--- /dev/null
+++ b/Source/core/rendering/RenderInline.cpp
@@ -0,0 +1,1589 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 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 "core/rendering/RenderInline.h"
+
+#include "core/dom/WebCoreMemoryInstrumentation.h"
+#include "core/editing/VisiblePosition.h"
+#include "core/page/Chrome.h"
+#include "core/page/Frame.h"
+#include "core/page/Page.h"
+#include "core/platform/graphics/FloatQuad.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/platform/graphics/transforms/TransformState.h"
+#include "core/rendering/HitTestResult.h"
+#include "core/rendering/InlineTextBox.h"
+#include "core/rendering/RenderArena.h"
+#include "core/rendering/RenderBlock.h"
+#include "core/rendering/RenderFlowThread.h"
+#include "core/rendering/RenderGeometryMap.h"
+#include "core/rendering/RenderLayer.h"
+#include "core/rendering/RenderTheme.h"
+#include "core/rendering/RenderView.h"
+#include "core/rendering/style/StyleInheritedData.h"
+
+using namespace std;
+
+namespace WebCore {
+
+RenderInline::RenderInline(Element* element)
+    : RenderBoxModelObject(element)
+    , m_alwaysCreateLineBoxes(false)
+{
+    setChildrenInline(true);
+}
+
+RenderInline* RenderInline::createAnonymous(Document* document)
+{
+    RenderInline* renderer = new (document->renderArena()) RenderInline(0);
+    renderer->setDocumentForAnonymous(document);
+    return renderer;
+}
+
+void RenderInline::willBeDestroyed()
+{
+#if !ASSERT_DISABLED
+    // Make sure we do not retain "this" in the continuation outline table map of our containing blocks.
+    if (parent() && style()->visibility() == VISIBLE && hasOutline()) {
+        bool containingBlockPaintsContinuationOutline = continuation() || isInlineElementContinuation();
+        if (containingBlockPaintsContinuationOutline) {
+            if (RenderBlock* cb = containingBlock()) {
+                if (RenderBlock* cbCb = cb->containingBlock())
+                    ASSERT(!cbCb->paintsContinuationOutline(this));
+            }
+        }
+    }
+#endif
+
+    // 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.
+    children()->destroyLeftoverChildren();
+
+    // Destroy our continuation before anything other than anonymous children.
+    // The reason we don't destroy it before anonymous children is that they may
+    // have continuations of their own that are anonymous children of our continuation.
+    RenderBoxModelObject* continuation = this->continuation();
+    if (continuation) {
+        continuation->destroy();
+        setContinuation(0);
+    }
+    
+    if (!documentBeingDestroyed()) {
+        if (firstLineBox()) {
+            // We can't wait for RenderBoxModelObject::destroy to clear the selection,
+            // because by then we will have nuked the line boxes.
+            // FIXME: The FrameSelection 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 (firstLineBox()->parent()) {
+                for (InlineFlowBox* box = firstLineBox(); box; box = box->nextLineBox())
+                    box->remove();
+            }
+        } else if (parent()) 
+            parent()->dirtyLinesFromChangedChild(this);
+    }
+
+    m_lineBoxes.deleteLineBoxes(renderArena());
+
+    RenderBoxModelObject::willBeDestroyed();
+}
+
+RenderInline* RenderInline::inlineElementContinuation() const
+{
+    RenderBoxModelObject* continuation = this->continuation();
+    if (!continuation || continuation->isInline())
+        return toRenderInline(continuation);
+    return toRenderBlock(continuation)->inlineElementContinuation();
+}
+
+void RenderInline::updateFromStyle()
+{
+    RenderBoxModelObject::updateFromStyle();
+
+    setInline(true); // Needed for run-ins, since run-in is considered a block display type.
+
+    // FIXME: Support transforms and reflections on inline flows someday.
+    setHasTransform(false);
+    setHasReflection(false);    
+}
+
+static RenderObject* inFlowPositionedInlineAncestor(RenderObject* p)
+{
+    while (p && p->isRenderInline()) {
+        if (p->isInFlowPositioned())
+            return p;
+        p = p->parent();
+    }
+    return 0;
+}
+
+static void updateStyleOfAnonymousBlockContinuations(RenderObject* block, const RenderStyle* newStyle, const RenderStyle* oldStyle)
+{
+    for (;block && block->isAnonymousBlock(); block = block->nextSibling()) {
+        if (!toRenderBlock(block)->isAnonymousBlockContinuation() || block->style()->position() == newStyle->position())
+            continue;
+        // If we are no longer in-flow positioned but our descendant block(s) still have an in-flow positioned ancestor then
+        // their containing anonymous block should keep its in-flow positioning. 
+        RenderInline* cont = toRenderBlock(block)->inlineElementContinuation();
+        if (oldStyle->hasInFlowPosition() && inFlowPositionedInlineAncestor(cont))
+            continue;
+        RefPtr<RenderStyle> blockStyle = RenderStyle::createAnonymousStyleWithDisplay(block->style(), BLOCK);
+        blockStyle->setPosition(newStyle->position());
+        block->setStyle(blockStyle);
+    }
+}
+
+void RenderInline::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
+{
+    RenderBoxModelObject::styleDidChange(diff, oldStyle);
+
+    // 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.
+    RenderStyle* newStyle = style();
+    RenderInline* continuation = inlineElementContinuation();
+    for (RenderInline* currCont = continuation; currCont; currCont = currCont->inlineElementContinuation()) {
+        RenderBoxModelObject* nextCont = currCont->continuation();
+        currCont->setContinuation(0);
+        currCont->setStyle(newStyle);
+        currCont->setContinuation(nextCont);
+    }
+
+    // If an inline's in-flow positioning has changed then any descendant blocks will need to change their in-flow positioning accordingly.
+    // Do this by updating the position of the descendant blocks' containing anonymous blocks - there may be more than one.
+    if (continuation && oldStyle && newStyle->position() != oldStyle->position()
+        && (newStyle->hasInFlowPosition() || oldStyle->hasInFlowPosition())) {
+        // If any descendant blocks exist then they will be in the next anonymous block and its siblings.
+        RenderObject* block = containingBlock()->nextSibling();
+        ASSERT(block && block->isAnonymousBlock());
+        updateStyleOfAnonymousBlockContinuations(block, newStyle, oldStyle);
+    }
+
+    if (!m_alwaysCreateLineBoxes) {
+        bool alwaysCreateLineBoxes = hasSelfPaintingLayer() || hasBoxDecorations() || newStyle->hasPadding() || newStyle->hasMargin() || hasOutline();
+        if (oldStyle && alwaysCreateLineBoxes) {
+            dirtyLineBoxes(false);
+            setNeedsLayout(true);
+        }
+        m_alwaysCreateLineBoxes = alwaysCreateLineBoxes;
+    }
+}
+
+void RenderInline::updateAlwaysCreateLineBoxes(bool fullLayout)
+{
+    // Once we have been tainted once, just assume it will happen again. This way effects like hover highlighting that change the
+    // background color will only cause a layout on the first rollover.
+    if (m_alwaysCreateLineBoxes)
+        return;
+
+    RenderStyle* parentStyle = parent()->style();
+    RenderInline* parentRenderInline = parent()->isRenderInline() ? toRenderInline(parent()) : 0;
+    bool checkFonts = document()->inNoQuirksMode();
+    RenderFlowThread* flowThread = flowThreadContainingBlock();
+    bool alwaysCreateLineBoxes = (parentRenderInline && parentRenderInline->alwaysCreateLineBoxes())
+        || (parentRenderInline && parentStyle->verticalAlign() != BASELINE)
+        || style()->verticalAlign() != BASELINE
+        || style()->textEmphasisMark() != TextEmphasisMarkNone
+        || (checkFonts && (!parentStyle->font().fontMetrics().hasIdenticalAscentDescentAndLineGap(style()->font().fontMetrics())
+        || parentStyle->lineHeight() != style()->lineHeight()))
+        || (flowThread && flowThread->hasRegionsWithStyling());
+
+    if (!alwaysCreateLineBoxes && checkFonts && document()->styleSheetCollection()->usesFirstLineRules()) {
+        // Have to check the first line style as well.
+        parentStyle = parent()->style(true);
+        RenderStyle* childStyle = style(true);
+        alwaysCreateLineBoxes = !parentStyle->font().fontMetrics().hasIdenticalAscentDescentAndLineGap(childStyle->font().fontMetrics())
+        || childStyle->verticalAlign() != BASELINE
+        || parentStyle->lineHeight() != childStyle->lineHeight();
+    }
+
+    if (alwaysCreateLineBoxes) {
+        if (!fullLayout)
+            dirtyLineBoxes(false);
+        m_alwaysCreateLineBoxes = true;
+    }
+}
+
+LayoutRect RenderInline::localCaretRect(InlineBox* inlineBox, int, LayoutUnit* extraWidthToEndOfLine)
+{
+    if (firstChild()) {
+        // This condition is possible if the RenderInline is at an editing boundary,
+        // i.e. the VisiblePosition is:
+        //   <RenderInline editingBoundary=true>|<RenderText> </RenderText></RenderInline>
+        // FIXME: need to figure out how to make this return a valid rect, note that
+        // there are no line boxes created in the above case.
+        return LayoutRect();
+    }
+
+    ASSERT_UNUSED(inlineBox, !inlineBox);
+
+    if (extraWidthToEndOfLine)
+        *extraWidthToEndOfLine = 0;
+
+    LayoutRect caretRect = localCaretRectForEmptyElement(borderAndPaddingWidth(), 0);
+
+    if (InlineBox* firstBox = firstLineBox())
+        caretRect.moveBy(roundedLayoutPoint(firstBox->topLeft()));
+
+    return caretRect;
+}
+
+void RenderInline::addChild(RenderObject* newChild, RenderObject* beforeChild)
+{
+    if (continuation())
+        return addChildToContinuation(newChild, beforeChild);
+    return addChildIgnoringContinuation(newChild, beforeChild);
+}
+
+static RenderBoxModelObject* nextContinuation(RenderObject* renderer)
+{
+    if (renderer->isInline() && !renderer->isReplaced())
+        return toRenderInline(renderer)->continuation();
+    return toRenderBlock(renderer)->inlineElementContinuation();
+}
+
+RenderBoxModelObject* RenderInline::continuationBefore(RenderObject* beforeChild)
+{
+    if (beforeChild && beforeChild->parent() == this)
+        return this;
+
+    RenderBoxModelObject* curr = nextContinuation(this);
+    RenderBoxModelObject* nextToLast = this;
+    RenderBoxModelObject* last = this;
+    while (curr) {
+        if (beforeChild && beforeChild->parent() == curr) {
+            if (curr->firstChild() == beforeChild)
+                return last;
+            return curr;
+        }
+
+        nextToLast = last;
+        last = curr;
+        curr = nextContinuation(curr);
+    }
+
+    if (!beforeChild && !last->firstChild())
+        return nextToLast;
+    return last;
+}
+
+void RenderInline::addChildIgnoringContinuation(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->isFloatingOrOutOfFlowPositioned()) {
+        // 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::createAnonymousStyleWithDisplay(style(), BLOCK);
+        
+        // If inside an inline affected by in-flow positioning the block needs to be affected by it too.
+        // Giving the block a layer like this allows it to collect the x/y offsets from inline parents later.
+        if (RenderObject* positionedAncestor = inFlowPositionedInlineAncestor(this))
+            newStyle->setPosition(positionedAncestor->style()->position());
+
+        RenderBlock* newBox = RenderBlock::createAnonymous(document());
+        newBox->setStyle(newStyle.release());
+        RenderBoxModelObject* oldContinuation = continuation();
+        setContinuation(newBox);
+
+        splitFlow(beforeChild, newBox, newChild, oldContinuation);
+        return;
+    }
+
+    RenderBoxModelObject::addChild(newChild, beforeChild);
+
+    newChild->setNeedsLayoutAndPrefWidthsRecalc();
+}
+
+RenderInline* RenderInline::clone() const
+{
+    RenderInline* cloneInline = new (renderArena()) RenderInline(node());
+    cloneInline->setStyle(style());
+    cloneInline->setFlowThreadState(flowThreadState());
+    return cloneInline;
+}
+
+void RenderInline::splitInlines(RenderBlock* fromBlock, RenderBlock* toBlock,
+                                RenderBlock* middleBlock,
+                                RenderObject* beforeChild, RenderBoxModelObject* oldCont)
+{
+    // Create a clone of this inline.
+    RenderInline* cloneInline = clone();
+    cloneInline->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();
+        cloneInline->addChildIgnoringContinuation(children()->removeChildNode(this, tmp), 0);
+        tmp->setNeedsLayoutAndPrefWidthsRecalc();
+    }
+
+    // Hook |clone| up as the continuation of the middle block.
+    middleBlock->setContinuation(cloneInline);
+
+    // 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.
+    RenderBoxModelObject* curr = toRenderBoxModelObject(parent());
+    RenderBoxModelObject* 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) {
+        ASSERT(curr->isRenderInline());
+        if (splitDepth < cMaxSplitDepth) {
+            // Create a new clone.
+            RenderInline* cloneChild = cloneInline;
+            cloneInline = toRenderInline(curr)->clone();
+
+            // Insert our child clone as the first child.
+            cloneInline->addChildIgnoringContinuation(cloneChild, 0);
+
+            // Hook the clone up as a continuation of |curr|.
+            RenderInline* inlineCurr = toRenderInline(curr);
+            oldCont = inlineCurr->continuation();
+            inlineCurr->setContinuation(cloneInline);
+            cloneInline->setContinuation(oldCont);
+
+            // 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();
+                cloneInline->addChildIgnoringContinuation(inlineCurr->children()->removeChildNode(curr, tmp), 0);
+                tmp->setNeedsLayoutAndPrefWidthsRecalc();
+            }
+        }
+        
+        // Keep walking up the chain.
+        currChild = curr;
+        curr = toRenderBoxModelObject(curr->parent());
+        splitDepth++;
+    }
+
+    // Now we are at the block level. We need to put the clone into the toBlock.
+    toBlock->children()->appendChildNode(toBlock, cloneInline);
+
+    // 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->children()->appendChildNode(toBlock, fromBlock->children()->removeChildNode(fromBlock, tmp));
+    }
+}
+
+void RenderInline::splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox,
+                             RenderObject* newChild, RenderBoxModelObject* 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;
+        pre->removePositionedObjects(0);
+        pre->removeFloatingObjects();
+        block = block->containingBlock();
+    } else {
+        // No anonymous block available for use.  Make one.
+        pre = block->createAnonymousBlock();
+        madeNewBeforeBlock = true;
+    }
+
+    RenderBlock* post = toRenderBlock(pre->createAnonymousBoxWithSameTypeAs(block));
+
+    RenderObject* boxFirst = madeNewBeforeBlock ? block->firstChild() : pre->nextSibling();
+    if (madeNewBeforeBlock)
+        block->children()->insertChildNode(block, pre, boxFirst);
+    block->children()->insertChildNode(block, newBlockBox, boxFirst);
+    block->children()->insertChildNode(block, post, boxFirst);
+    block->setChildrenInline(false);
+    
+    if (madeNewBeforeBlock) {
+        RenderObject* o = boxFirst;
+        while (o) {
+            RenderObject* no = o;
+            o = no->nextSibling();
+            pre->children()->appendChildNode(pre, block->children()->removeChildNode(block, 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 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->addChild(newChild);
+
+    // 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::addChildToContinuation(RenderObject* newChild, RenderObject* beforeChild)
+{
+    RenderBoxModelObject* flow = continuationBefore(beforeChild);
+    ASSERT(!beforeChild || beforeChild->parent()->isRenderBlock() || beforeChild->parent()->isRenderInline());
+    RenderBoxModelObject* beforeChildParent = 0;
+    if (beforeChild)
+        beforeChildParent = toRenderBoxModelObject(beforeChild->parent());
+    else {
+        RenderBoxModelObject* cont = nextContinuation(flow);
+        if (cont)
+            beforeChildParent = cont;
+        else
+            beforeChildParent = flow;
+    }
+
+    if (newChild->isFloatingOrOutOfFlowPositioned())
+        return beforeChildParent->addChildIgnoringContinuation(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->addChildIgnoringContinuation(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->addChildIgnoringContinuation(newChild, beforeChild);
+        else if (flowInline == childInline)
+            return flow->addChildIgnoringContinuation(newChild, 0); // Just treat like an append.
+        else
+            return beforeChildParent->addChildIgnoringContinuation(newChild, beforeChild);
+    }
+}
+
+void RenderInline::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    m_lineBoxes.paint(this, paintInfo, paintOffset);
+}
+
+template<typename GeneratorContext>
+void RenderInline::generateLineBoxRects(GeneratorContext& yield) const
+{
+    if (!alwaysCreateLineBoxes())
+        generateCulledLineBoxRects(yield, this);
+    else if (InlineFlowBox* curr = firstLineBox()) {
+        for (; curr; curr = curr->nextLineBox())
+            yield(FloatRect(curr->topLeft(), curr->size()));
+    } else
+        yield(FloatRect());
+}
+
+template<typename GeneratorContext>
+void RenderInline::generateCulledLineBoxRects(GeneratorContext& yield, const RenderInline* container) const
+{
+    if (!culledInlineFirstLineBox()) {
+        yield(FloatRect());
+        return;
+    }
+
+    bool isHorizontal = style()->isHorizontalWritingMode();
+
+    for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
+        if (curr->isFloatingOrOutOfFlowPositioned())
+            continue;
+            
+        // We want to get the margin box in the inline direction, and then use our font ascent/descent in the block
+        // direction (aligned to the root box's baseline).
+        if (curr->isBox()) {
+            RenderBox* currBox = toRenderBox(curr);
+            if (currBox->inlineBoxWrapper()) {
+                RootInlineBox* rootBox = currBox->inlineBoxWrapper()->root();
+                int logicalTop = rootBox->logicalTop() + (rootBox->renderer()->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent() - container->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent());
+                int logicalHeight = container->style(rootBox->isFirstLineStyle())->font().fontMetrics().height();
+                if (isHorizontal)
+                    yield(FloatRect(currBox->inlineBoxWrapper()->x() - currBox->marginLeft(), logicalTop, currBox->width() + currBox->marginWidth(), logicalHeight));
+                else
+                    yield(FloatRect(logicalTop, currBox->inlineBoxWrapper()->y() - currBox->marginTop(), logicalHeight, currBox->height() + currBox->marginHeight()));
+            }
+        } else if (curr->isRenderInline()) {
+            // If the child doesn't need line boxes either, then we can recur.
+            RenderInline* currInline = toRenderInline(curr);
+            if (!currInline->alwaysCreateLineBoxes())
+                currInline->generateCulledLineBoxRects(yield, container);
+            else {
+                for (InlineFlowBox* childLine = currInline->firstLineBox(); childLine; childLine = childLine->nextLineBox()) {
+                    RootInlineBox* rootBox = childLine->root();
+                    int logicalTop = rootBox->logicalTop() + (rootBox->renderer()->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent() - container->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent());
+                    int logicalHeight = container->style(rootBox->isFirstLineStyle())->font().fontMetrics().height();
+                    if (isHorizontal)
+                        yield(FloatRect(childLine->x() - childLine->marginLogicalLeft(),
+                            logicalTop,
+                            childLine->logicalWidth() + childLine->marginLogicalLeft() + childLine->marginLogicalRight(),
+                            logicalHeight));
+                    else
+                        yield(FloatRect(logicalTop,
+                            childLine->y() - childLine->marginLogicalLeft(),
+                            logicalHeight,
+                            childLine->logicalWidth() + childLine->marginLogicalLeft() + childLine->marginLogicalRight()));
+                }
+            }
+        } else if (curr->isText()) {
+            RenderText* currText = toRenderText(curr);
+            for (InlineTextBox* childText = currText->firstTextBox(); childText; childText = childText->nextTextBox()) {
+                RootInlineBox* rootBox = childText->root();
+                int logicalTop = rootBox->logicalTop() + (rootBox->renderer()->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent() - container->style(rootBox->isFirstLineStyle())->font().fontMetrics().ascent());
+                int logicalHeight = container->style(rootBox->isFirstLineStyle())->font().fontMetrics().height();
+                if (isHorizontal)
+                    yield(FloatRect(childText->x(), logicalTop, childText->logicalWidth(), logicalHeight));
+                else
+                    yield(FloatRect(logicalTop, childText->y(), logicalHeight, childText->logicalWidth()));
+            }
+        }
+    }
+}
+
+namespace {
+
+class AbsoluteRectsGeneratorContext {
+public:
+    AbsoluteRectsGeneratorContext(Vector<IntRect>& rects, const LayoutPoint& accumulatedOffset)
+        : m_rects(rects)
+        , m_accumulatedOffset(accumulatedOffset) { }
+
+    void operator()(const FloatRect& rect)
+    {
+        IntRect intRect = enclosingIntRect(rect);
+        intRect.move(m_accumulatedOffset.x(), m_accumulatedOffset.y());
+        m_rects.append(intRect);
+    }
+private:
+    Vector<IntRect>& m_rects;
+    const LayoutPoint& m_accumulatedOffset;
+};
+
+} // unnamed namespace
+
+void RenderInline::absoluteRects(Vector<IntRect>& rects, const LayoutPoint& accumulatedOffset) const
+{
+    AbsoluteRectsGeneratorContext context(rects, accumulatedOffset);
+    generateLineBoxRects(context);
+
+    if (continuation()) {
+        if (continuation()->isBox()) {
+            RenderBox* box = toRenderBox(continuation());
+            continuation()->absoluteRects(rects, toLayoutPoint(accumulatedOffset - containingBlock()->location() + box->locationOffset()));
+        } else
+            continuation()->absoluteRects(rects, toLayoutPoint(accumulatedOffset - containingBlock()->location()));
+    }
+}
+
+
+namespace {
+
+class AbsoluteQuadsGeneratorContext {
+public:
+    AbsoluteQuadsGeneratorContext(const RenderInline* renderer, Vector<FloatQuad>& quads)
+        : m_quads(quads)
+        , m_geometryMap()
+    {
+        m_geometryMap.pushMappingsToAncestor(renderer, 0);
+    }
+
+    void operator()(const FloatRect& rect)
+    {
+        m_quads.append(m_geometryMap.absoluteRect(rect));
+    }
+private:
+    Vector<FloatQuad>& m_quads;
+    RenderGeometryMap m_geometryMap;
+};
+
+} // unnamed namespace
+
+void RenderInline::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed) const
+{
+    AbsoluteQuadsGeneratorContext context(this, quads);
+    generateLineBoxRects(context);
+
+    if (continuation())
+        continuation()->absoluteQuads(quads, wasFixed);
+}
+
+LayoutUnit RenderInline::offsetLeft() const
+{
+    LayoutPoint topLeft;
+    if (InlineBox* firstBox = firstLineBoxIncludingCulling())
+        topLeft = flooredLayoutPoint(firstBox->topLeft());
+    return adjustedPositionRelativeToOffsetParent(topLeft).x();
+}
+
+LayoutUnit RenderInline::offsetTop() const
+{
+    LayoutPoint topLeft;
+    if (InlineBox* firstBox = firstLineBoxIncludingCulling())
+        topLeft = flooredLayoutPoint(firstBox->topLeft());
+    return adjustedPositionRelativeToOffsetParent(topLeft).y();
+}
+
+static LayoutUnit computeMargin(const RenderInline* renderer, const Length& margin)
+{
+    if (margin.isAuto())
+        return 0;
+    if (margin.isFixed())
+        return margin.value();
+    if (margin.isPercent())
+        return minimumValueForLength(margin, max<LayoutUnit>(0, renderer->containingBlock()->availableLogicalWidth()));
+    if (margin.isViewportPercentage())
+        return valueForLength(margin, 0, renderer->view());
+    return 0;
+}
+
+LayoutUnit RenderInline::marginLeft() const
+{
+    return computeMargin(this, style()->marginLeft());
+}
+
+LayoutUnit RenderInline::marginRight() const
+{
+    return computeMargin(this, style()->marginRight());
+}
+
+LayoutUnit RenderInline::marginTop() const
+{
+    return computeMargin(this, style()->marginTop());
+}
+
+LayoutUnit RenderInline::marginBottom() const
+{
+    return computeMargin(this, style()->marginBottom());
+}
+
+LayoutUnit RenderInline::marginStart(const RenderStyle* otherStyle) const
+{
+    return computeMargin(this, style()->marginStartUsing(otherStyle ? otherStyle : style()));
+}
+
+LayoutUnit RenderInline::marginEnd(const RenderStyle* otherStyle) const
+{
+    return computeMargin(this, style()->marginEndUsing(otherStyle ? otherStyle : style()));
+}
+
+LayoutUnit RenderInline::marginBefore(const RenderStyle* otherStyle) const
+{
+    return computeMargin(this, style()->marginBeforeUsing(otherStyle ? otherStyle : style()));
+}
+
+LayoutUnit RenderInline::marginAfter(const RenderStyle* otherStyle) const
+{
+    return computeMargin(this, style()->marginAfterUsing(otherStyle ? otherStyle : style()));
+}
+
+const char* RenderInline::renderName() const
+{
+    if (isRelPositioned())
+        return "RenderInline (relative positioned)";
+    if (isStickyPositioned())
+        return "RenderInline (sticky positioned)";
+    // FIXME: Temporary hack while the new generated content system is being implemented.
+    if (isPseudoElement())
+        return "RenderInline (generated)";
+    if (isAnonymous())
+        return "RenderInline (generated)";
+    if (isRunIn())
+        return "RenderInline (run-in)";
+    return "RenderInline";
+}
+
+bool RenderInline::nodeAtPoint(const HitTestRequest& request, HitTestResult& result,
+                                const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
+{
+    return m_lineBoxes.hitTest(this, request, result, locationInContainer, accumulatedOffset, hitTestAction);
+}
+
+namespace {
+
+class HitTestCulledInlinesGeneratorContext {
+public:
+    HitTestCulledInlinesGeneratorContext(Region& region, const HitTestLocation& location) : m_intersected(false), m_region(region), m_location(location) { }
+    void operator()(const FloatRect& rect)
+    {
+        m_intersected = m_intersected || m_location.intersects(rect);
+        m_region.unite(enclosingIntRect(rect));
+    }
+    bool intersected() const { return m_intersected; }
+private:
+    bool m_intersected;
+    Region& m_region;
+    const HitTestLocation& m_location;
+};
+
+} // unnamed namespace
+
+bool RenderInline::hitTestCulledInline(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset)
+{
+    ASSERT(result.isRectBasedTest() && !alwaysCreateLineBoxes());
+    if (!visibleToHitTestRequest(request))
+        return false;
+
+    HitTestLocation tmpLocation(locationInContainer, -toLayoutSize(accumulatedOffset));
+
+    Region regionResult;
+    HitTestCulledInlinesGeneratorContext context(regionResult, tmpLocation);
+    generateCulledLineBoxRects(context, this);
+
+    if (context.intersected()) {
+        updateHitTestResult(result, tmpLocation.point());
+        // We can not use addNodeToRectBasedTestResult to determine if we fully enclose the hit-test area
+        // because it can only handle rectangular targets.
+        result.addNodeToRectBasedTestResult(node(), request, locationInContainer);
+        return regionResult.contains(enclosingIntRect(tmpLocation.boundingBox()));
+    }
+    return false;
+}
+
+VisiblePosition RenderInline::positionForPoint(const LayoutPoint& point)
+{
+    // FIXME: Does not deal with relative or sticky positioned inlines (should it?)
+    RenderBlock* cb = containingBlock();
+    if (firstLineBox()) {
+        // This inline actually has a line box.  We must have clicked in the border/padding of one of these boxes.  We
+        // should try to find a result by asking our containing block.
+        return cb->positionForPoint(point);
+    }
+
+    // Translate the coords from the pre-anonymous block to the post-anonymous block.
+    LayoutPoint parentBlockPoint = cb->location() + point;  
+    RenderBoxModelObject* c = continuation();
+    while (c) {
+        RenderBox* contBlock = c->isInline() ? c->containingBlock() : toRenderBlock(c);
+        if (c->isInline() || c->firstChild())
+            return c->positionForPoint(parentBlockPoint - contBlock->locationOffset());
+        c = toRenderBlock(c)->inlineElementContinuation();
+    }
+    
+    return RenderBoxModelObject::positionForPoint(point);
+}
+
+namespace {
+
+class LinesBoundingBoxGeneratorContext {
+public:
+    LinesBoundingBoxGeneratorContext(FloatRect& rect) : m_rect(rect) { }
+    void operator()(const FloatRect& rect)
+    {
+        m_rect.uniteIfNonZero(rect);
+    }
+private:
+    FloatRect& m_rect;
+};
+
+} // unnamed namespace
+
+IntRect RenderInline::linesBoundingBox() const
+{
+    if (!alwaysCreateLineBoxes()) {
+        ASSERT(!firstLineBox());
+        FloatRect floatResult;
+        LinesBoundingBoxGeneratorContext context(floatResult);
+        generateCulledLineBoxRects(context, this);
+        return enclosingIntRect(floatResult);
+    }
+
+    IntRect result;
+    
+    // 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 the width of the minimal left side and the maximal right side.
+        float logicalLeftSide = 0;
+        float logicalRightSide = 0;
+        for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) {
+            if (curr == firstLineBox() || curr->logicalLeft() < logicalLeftSide)
+                logicalLeftSide = curr->logicalLeft();
+            if (curr == firstLineBox() || curr->logicalRight() > logicalRightSide)
+                logicalRightSide = curr->logicalRight();
+        }
+        
+        bool isHorizontal = style()->isHorizontalWritingMode();
+        
+        float x = isHorizontal ? logicalLeftSide : firstLineBox()->x();
+        float y = isHorizontal ? firstLineBox()->y() : logicalLeftSide;
+        float width = isHorizontal ? logicalRightSide - logicalLeftSide : lastLineBox()->logicalBottom() - x;
+        float height = isHorizontal ? lastLineBox()->logicalBottom() - y : logicalRightSide - logicalLeftSide;
+        result = enclosingIntRect(FloatRect(x, y, width, height));
+    }
+
+    return result;
+}
+
+InlineBox* RenderInline::culledInlineFirstLineBox() const
+{
+    for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
+        if (curr->isFloatingOrOutOfFlowPositioned())
+            continue;
+            
+        // We want to get the margin box in the inline direction, and then use our font ascent/descent in the block
+        // direction (aligned to the root box's baseline).
+        if (curr->isBox())
+            return toRenderBox(curr)->inlineBoxWrapper();
+        if (curr->isRenderInline()) {
+            RenderInline* currInline = toRenderInline(curr);
+            InlineBox* result = currInline->firstLineBoxIncludingCulling();
+            if (result)
+                return result;
+        } else if (curr->isText()) {
+            RenderText* currText = toRenderText(curr);
+            if (currText->firstTextBox())
+                return currText->firstTextBox();
+        }
+    }
+    return 0;
+}
+
+InlineBox* RenderInline::culledInlineLastLineBox() const
+{
+    for (RenderObject* curr = lastChild(); curr; curr = curr->previousSibling()) {
+        if (curr->isFloatingOrOutOfFlowPositioned())
+            continue;
+            
+        // We want to get the margin box in the inline direction, and then use our font ascent/descent in the block
+        // direction (aligned to the root box's baseline).
+        if (curr->isBox())
+            return toRenderBox(curr)->inlineBoxWrapper();
+        if (curr->isRenderInline()) {
+            RenderInline* currInline = toRenderInline(curr);
+            InlineBox* result = currInline->lastLineBoxIncludingCulling();
+            if (result)
+                return result;
+        } else if (curr->isText()) {
+            RenderText* currText = toRenderText(curr);
+            if (currText->lastTextBox())
+                return currText->lastTextBox();
+        }
+    }
+    return 0;
+}
+
+LayoutRect RenderInline::culledInlineVisualOverflowBoundingBox() const
+{
+    FloatRect floatResult;
+    LinesBoundingBoxGeneratorContext context(floatResult);
+    generateCulledLineBoxRects(context, this);
+    LayoutRect result(enclosingLayoutRect(floatResult));
+    bool isHorizontal = style()->isHorizontalWritingMode();
+    for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
+        if (curr->isFloatingOrOutOfFlowPositioned())
+            continue;
+            
+        // For overflow we just have to propagate by hand and recompute it all.
+        if (curr->isBox()) {
+            RenderBox* currBox = toRenderBox(curr);
+            if (!currBox->hasSelfPaintingLayer() && currBox->inlineBoxWrapper()) {
+                LayoutRect logicalRect = currBox->logicalVisualOverflowRectForPropagation(style());
+                if (isHorizontal) {
+                    logicalRect.moveBy(currBox->location());
+                    result.uniteIfNonZero(logicalRect);
+                } else {
+                    logicalRect.moveBy(currBox->location());
+                    result.uniteIfNonZero(logicalRect.transposedRect());
+                }
+            }
+        } else if (curr->isRenderInline()) {
+            // If the child doesn't need line boxes either, then we can recur.
+            RenderInline* currInline = toRenderInline(curr);
+            if (!currInline->alwaysCreateLineBoxes())
+                result.uniteIfNonZero(currInline->culledInlineVisualOverflowBoundingBox());
+            else if (!currInline->hasSelfPaintingLayer())
+                result.uniteIfNonZero(currInline->linesVisualOverflowBoundingBox());
+        } else if (curr->isText()) {
+            // FIXME; Overflow from text boxes is lost. We will need to cache this information in
+            // InlineTextBoxes.
+            RenderText* currText = toRenderText(curr);
+            result.uniteIfNonZero(currText->linesVisualOverflowBoundingBox());
+        }
+    }
+    return result;
+}
+
+LayoutRect RenderInline::linesVisualOverflowBoundingBox() const
+{
+    if (!alwaysCreateLineBoxes())
+        return culledInlineVisualOverflowBoundingBox();
+
+    if (!firstLineBox() || !lastLineBox())
+        return LayoutRect();
+
+    // Return the width of the minimal left side and the maximal right side.
+    LayoutUnit logicalLeftSide = LayoutUnit::max();
+    LayoutUnit logicalRightSide = LayoutUnit::min();
+    for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) {
+        logicalLeftSide = min(logicalLeftSide, curr->logicalLeftVisualOverflow());
+        logicalRightSide = max(logicalRightSide, curr->logicalRightVisualOverflow());
+    }
+
+    RootInlineBox* firstRootBox = firstLineBox()->root();
+    RootInlineBox* lastRootBox = lastLineBox()->root();
+    
+    LayoutUnit logicalTop = firstLineBox()->logicalTopVisualOverflow(firstRootBox->lineTop());
+    LayoutUnit logicalWidth = logicalRightSide - logicalLeftSide;
+    LayoutUnit logicalHeight = lastLineBox()->logicalBottomVisualOverflow(lastRootBox->lineBottom()) - logicalTop;
+    
+    LayoutRect rect(logicalLeftSide, logicalTop, logicalWidth, logicalHeight);
+    if (!style()->isHorizontalWritingMode())
+        rect = rect.transposedRect();
+    return rect;
+}
+
+LayoutRect RenderInline::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const
+{
+    // Only run-ins are allowed in here during layout.
+    ASSERT(!view() || !view()->layoutStateEnabled() || isRunIn());
+
+    if (!firstLineBoxIncludingCulling() && !continuation())
+        return LayoutRect();
+
+    LayoutRect repaintRect(linesVisualOverflowBoundingBox());
+    bool hitRepaintContainer = false;
+
+    // We need to add in the in-flow position offsets of any inlines (including us) up to our
+    // containing block.
+    RenderBlock* cb = containingBlock();
+    for (const RenderObject* inlineFlow = this; inlineFlow && inlineFlow->isRenderInline() && inlineFlow != cb;
+         inlineFlow = inlineFlow->parent()) {
+         if (inlineFlow == repaintContainer) {
+            hitRepaintContainer = true;
+            break;
+        }
+        if (inlineFlow->style()->hasInFlowPosition() && inlineFlow->hasLayer())
+            repaintRect.move(toRenderInline(inlineFlow)->layer()->paintOffset());
+    }
+
+    LayoutUnit outlineSize = style()->outlineSize();
+    repaintRect.inflate(outlineSize);
+
+    if (hitRepaintContainer || !cb)
+        return repaintRect;
+
+    if (cb->hasColumns())
+        cb->adjustRectForColumns(repaintRect);
+
+    if (cb->hasOverflowClip())
+        cb->applyCachedClipAndScrollOffsetForRepaint(repaintRect);
+
+    cb->computeRectForRepaint(repaintContainer, repaintRect);
+
+    if (outlineSize) {
+        for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
+            if (!curr->isText())
+                repaintRect.unite(curr->rectWithOutlineForRepaint(repaintContainer, outlineSize));
+        }
+
+        if (continuation() && !continuation()->isInline() && continuation()->parent())
+            repaintRect.unite(continuation()->rectWithOutlineForRepaint(repaintContainer, outlineSize));
+    }
+
+    return repaintRect;
+}
+
+LayoutRect RenderInline::rectWithOutlineForRepaint(const RenderLayerModelObject* repaintContainer, LayoutUnit outlineWidth) const
+{
+    LayoutRect r(RenderBoxModelObject::rectWithOutlineForRepaint(repaintContainer, outlineWidth));
+    for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
+        if (!curr->isText())
+            r.unite(curr->rectWithOutlineForRepaint(repaintContainer, outlineWidth));
+    }
+    return r;
+}
+
+void RenderInline::computeRectForRepaint(const RenderLayerModelObject* repaintContainer, LayoutRect& rect, bool fixed) const
+{
+    if (RenderView* v = view()) {
+        // LayoutState is only valid for root-relative repainting
+        if (v->layoutStateEnabled() && !repaintContainer) {
+            LayoutState* layoutState = v->layoutState();
+            if (style()->hasInFlowPosition() && layer())
+                rect.move(layer()->paintOffset());
+            rect.move(layoutState->m_paintOffset);
+            if (layoutState->m_clipped)
+                rect.intersect(layoutState->m_clipRect);
+            return;
+        }
+    }
+
+    if (repaintContainer == this)
+        return;
+
+    bool containerSkipped;
+    RenderObject* o = container(repaintContainer, &containerSkipped);
+    if (!o)
+        return;
+
+    LayoutPoint topLeft = rect.location();
+
+    if (o->isBlockFlow() && !style()->hasOutOfFlowPosition()) {
+        RenderBlock* cb = toRenderBlock(o);
+        if (cb->hasColumns()) {
+            LayoutRect repaintRect(topLeft, rect.size());
+            cb->adjustRectForColumns(repaintRect);
+            topLeft = repaintRect.location();
+            rect = repaintRect;
+        }
+    }
+
+    if (style()->hasInFlowPosition() && layer()) {
+        // Apply the in-flow 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 or sticky position
+        // flag on the RenderObject has been cleared, so use the one on the style().
+        topLeft += layer()->paintOffset();
+    }
+    
+    // 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.
+    rect.setLocation(topLeft);
+    if (o->hasOverflowClip()) {
+        RenderBox* containerBox = toRenderBox(o);
+        containerBox->applyCachedClipAndScrollOffsetForRepaint(rect);
+        if (rect.isEmpty())
+            return;
+    }
+
+    if (containerSkipped) {
+        // If the repaintContainer is below o, then we need to map the rect into repaintContainer's coordinates.
+        LayoutSize containerOffset = repaintContainer->offsetFromAncestorContainer(o);
+        rect.move(-containerOffset);
+        return;
+    }
+    
+    o->computeRectForRepaint(repaintContainer, rect, fixed);
+}
+
+LayoutSize RenderInline::offsetFromContainer(RenderObject* container, const LayoutPoint& point, bool* offsetDependsOnPoint) const
+{
+    ASSERT(container == this->container());
+    
+    LayoutSize offset;    
+    if (isInFlowPositioned())
+        offset += offsetForInFlowPosition();
+
+    container->adjustForColumns(offset, point);
+
+    if (container->hasOverflowClip())
+        offset -= toRenderBox(container)->scrolledContentOffset();
+
+    if (offsetDependsOnPoint)
+        *offsetDependsOnPoint = container->hasColumns() || (container->isBox() && container->style()->isFlippedBlocksWritingMode());
+
+    return offset;
+}
+
+void RenderInline::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags mode, bool* wasFixed) const
+{
+    if (repaintContainer == this)
+        return;
+
+    if (RenderView *v = view()) {
+        if (v->layoutStateEnabled() && !repaintContainer) {
+            LayoutState* layoutState = v->layoutState();
+            LayoutSize offset = layoutState->m_paintOffset;
+            if (style()->hasInFlowPosition() && layer())
+                offset += layer()->paintOffset();
+            transformState.move(offset);
+            return;
+        }
+    }
+
+    bool containerSkipped;
+    RenderObject* o = container(repaintContainer, &containerSkipped);
+    if (!o)
+        return;
+
+    if (mode & ApplyContainerFlip && o->isBox()) {
+        if (o->style()->isFlippedBlocksWritingMode()) {
+            IntPoint centerPoint = roundedIntPoint(transformState.mappedPoint());
+            transformState.move(toRenderBox(o)->flipForWritingModeIncludingColumns(centerPoint) - centerPoint);
+        }
+        mode &= ~ApplyContainerFlip;
+    }
+
+    LayoutSize containerOffset = offsetFromContainer(o, roundedLayoutPoint(transformState.mappedPoint()));
+
+    bool preserve3D = mode & UseTransforms && (o->style()->preserves3D() || style()->preserves3D());
+    if (mode & UseTransforms && shouldUseTransformFromContainer(o)) {
+        TransformationMatrix t;
+        getTransformFromContainer(o, containerOffset, t);
+        transformState.applyTransform(t, preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
+    } else
+        transformState.move(containerOffset.width(), containerOffset.height(), preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
+
+    if (containerSkipped) {
+        // There can't be a transform between repaintContainer and o, because transforms create containers, so it should be safe
+        // to just subtract the delta between the repaintContainer and o.
+        LayoutSize containerOffset = repaintContainer->offsetFromAncestorContainer(o);
+        transformState.move(-containerOffset.width(), -containerOffset.height(), preserve3D ? TransformState::AccumulateTransform : TransformState::FlattenTransform);
+        return;
+    }
+
+    o->mapLocalToContainer(repaintContainer, transformState, mode, wasFixed);
+}
+
+const RenderObject* RenderInline::pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const
+{
+    ASSERT(ancestorToStopAt != this);
+
+    bool ancestorSkipped;
+    RenderObject* container = this->container(ancestorToStopAt, &ancestorSkipped);
+    if (!container)
+        return 0;
+
+    LayoutSize adjustmentForSkippedAncestor;
+    if (ancestorSkipped) {
+        // There can't be a transform between repaintContainer and o, because transforms create containers, so it should be safe
+        // to just subtract the delta between the ancestor and o.
+        adjustmentForSkippedAncestor = -ancestorToStopAt->offsetFromAncestorContainer(container);
+    }
+
+    bool offsetDependsOnPoint = false;
+    LayoutSize containerOffset = offsetFromContainer(container, LayoutPoint(), &offsetDependsOnPoint);
+
+    bool preserve3D = container->style()->preserves3D() || style()->preserves3D();
+    if (shouldUseTransformFromContainer(container)) {
+        TransformationMatrix t;
+        getTransformFromContainer(container, containerOffset, t);
+        t.translateRight(adjustmentForSkippedAncestor.width(), adjustmentForSkippedAncestor.height()); // FIXME: right?
+        geometryMap.push(this, t, preserve3D, offsetDependsOnPoint);
+    } else {
+        containerOffset += adjustmentForSkippedAncestor;
+        geometryMap.push(this, containerOffset, preserve3D, offsetDependsOnPoint);
+    }
+    
+    return ancestorSkipped ? ancestorToStopAt : container;
+}
+
+void RenderInline::updateDragState(bool dragOn)
+{
+    RenderBoxModelObject::updateDragState(dragOn);
+    if (continuation())
+        continuation()->updateDragState(dragOn);
+}
+
+void RenderInline::childBecameNonInline(RenderObject* child)
+{
+    // We have to split the parent flow.
+    RenderBlock* newBox = containingBlock()->createAnonymousBlock();
+    RenderBoxModelObject* oldContinuation = continuation();
+    setContinuation(newBox);
+    RenderObject* beforeChild = child->nextSibling();
+    children()->removeChildNode(this, child);
+    splitFlow(beforeChild, newBox, child, oldContinuation);
+}
+
+void RenderInline::updateHitTestResult(HitTestResult& result, const LayoutPoint& point)
+{
+    if (result.innerNode())
+        return;
+
+    Node* n = node();
+    LayoutPoint localPoint(point);
+    if (n) {
+        if (isInlineElementContinuation()) {
+            // 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.
+            RenderBlock* firstBlock = n->renderer()->containingBlock();
+            
+            // Get our containing block.
+            RenderBox* block = containingBlock();
+            localPoint.moveBy(block->location() - firstBlock->locationOffset());
+        }
+
+        result.setInnerNode(n);
+        if (!result.innerNonSharedNode())
+            result.setInnerNonSharedNode(n);
+        result.setLocalPoint(localPoint);
+    }
+}
+
+void RenderInline::dirtyLineBoxes(bool fullLayout)
+{
+    if (fullLayout) {
+        m_lineBoxes.deleteLineBoxes(renderArena());
+        return;
+    }
+
+    if (!alwaysCreateLineBoxes()) {
+        // We have to grovel into our children in order to dirty the appropriate lines.
+        for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
+            if (curr->isFloatingOrOutOfFlowPositioned())
+                continue;
+            if (curr->isBox() && !curr->needsLayout()) {
+                RenderBox* currBox = toRenderBox(curr);
+                if (currBox->inlineBoxWrapper())
+                    currBox->inlineBoxWrapper()->root()->markDirty();
+            } else if (!curr->selfNeedsLayout()) {
+                if (curr->isRenderInline()) {
+                    RenderInline* currInline = toRenderInline(curr);
+                    for (InlineFlowBox* childLine = currInline->firstLineBox(); childLine; childLine = childLine->nextLineBox())
+                        childLine->root()->markDirty();
+                } else if (curr->isText()) {
+                    RenderText* currText = toRenderText(curr);
+                    for (InlineTextBox* childText = currText->firstTextBox(); childText; childText = childText->nextTextBox())
+                        childText->root()->markDirty();
+                }
+            }
+        }
+    } else
+        m_lineBoxes.dirtyLineBoxes();
+}
+
+void RenderInline::deleteLineBoxTree()
+{
+    m_lineBoxes.deleteLineBoxTree(renderArena());
+}
+
+InlineFlowBox* RenderInline::createInlineFlowBox() 
+{
+    return new (renderArena()) InlineFlowBox(this);
+}
+
+InlineFlowBox* RenderInline::createAndAppendInlineFlowBox()
+{
+    setAlwaysCreateLineBoxes();
+    InlineFlowBox* flowBox = createInlineFlowBox();
+    m_lineBoxes.appendLineBox(flowBox);
+    return flowBox;
+}
+
+LayoutUnit RenderInline::lineHeight(bool firstLine, LineDirectionMode /*direction*/, LinePositionMode /*linePositionMode*/) const
+{
+    if (firstLine && document()->styleSheetCollection()->usesFirstLineRules()) {
+        RenderStyle* s = style(firstLine);
+        if (s != style())
+            return s->computedLineHeight(view());
+    }
+
+    return style()->computedLineHeight(view());
+}
+
+int RenderInline::baselinePosition(FontBaseline baselineType, bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const
+{
+    ASSERT(linePositionMode == PositionOnContainingLine);
+    const FontMetrics& fontMetrics = style(firstLine)->fontMetrics();
+    return fontMetrics.ascent(baselineType) + (lineHeight(firstLine, direction, linePositionMode) - fontMetrics.height()) / 2;
+}
+
+LayoutSize RenderInline::offsetForInFlowPositionedInline(const RenderBox* child) const
+{
+    // FIXME: This function isn't right with mixed writing modes.
+
+    ASSERT(isInFlowPositioned());
+    if (!isInFlowPositioned())
+        return LayoutSize();
+
+    // 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.
+
+    LayoutSize logicalOffset;
+    LayoutUnit inlinePosition;
+    LayoutUnit blockPosition;
+    if (firstLineBox()) {
+        inlinePosition = roundedLayoutUnit(firstLineBox()->logicalLeft());
+        blockPosition = firstLineBox()->logicalTop();
+    } else {
+        inlinePosition = layer()->staticInlinePosition();
+        blockPosition = layer()->staticBlockPosition();
+    }
+
+    if (!child->style()->hasStaticInlinePosition(style()->isHorizontalWritingMode()))
+        logicalOffset.setWidth(inlinePosition);
+
+    // 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 (!child->style()->isOriginalDisplayInlineType())
+        // Avoid adding in the left border/padding of the containing block twice.  Subtract it out.
+        logicalOffset.setWidth(inlinePosition - child->containingBlock()->borderAndPaddingLogicalLeft());
+
+    if (!child->style()->hasStaticBlockPosition(style()->isHorizontalWritingMode()))
+        logicalOffset.setHeight(blockPosition);
+
+    return style()->isHorizontalWritingMode() ? logicalOffset : logicalOffset.transposedSize();
+}
+
+void RenderInline::imageChanged(WrappedImagePtr, const IntRect*)
+{
+    if (!parent())
+        return;
+        
+    // FIXME: We can do better.
+    repaint();
+}
+
+void RenderInline::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint& additionalOffset, const RenderLayerModelObject* paintContainer)
+{
+    AbsoluteRectsGeneratorContext context(rects, additionalOffset);
+    generateLineBoxRects(context);
+
+    for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling()) {
+        if (!curr->isText() && !curr->isListMarker()) {
+            FloatPoint pos(additionalOffset);
+            // FIXME: This doesn't work correctly with transforms.
+            if (curr->hasLayer()) 
+                pos = curr->localToContainerPoint(FloatPoint(), paintContainer);
+            else if (curr->isBox())
+                pos.move(toRenderBox(curr)->locationOffset());
+            curr->addFocusRingRects(rects, flooredIntPoint(pos), paintContainer);
+        }
+    }
+
+    if (continuation()) {
+        if (continuation()->isInline())
+            continuation()->addFocusRingRects(rects, flooredLayoutPoint(additionalOffset + continuation()->containingBlock()->location() - containingBlock()->location()), paintContainer);
+        else
+            continuation()->addFocusRingRects(rects, flooredLayoutPoint(additionalOffset + toRenderBox(continuation())->location() - containingBlock()->location()), paintContainer);
+    }
+}
+
+void RenderInline::paintOutline(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    if (!hasOutline())
+        return;
+    
+    RenderStyle* styleToUse = style();
+    if (styleToUse->outlineStyleIsAuto() || hasOutlineAnnotation()) {
+        if (!theme()->supportsFocusRing(styleToUse)) {
+            // Only paint the focus ring by hand if the theme isn't able to draw the focus ring.
+            paintFocusRing(paintInfo, paintOffset, styleToUse);
+        }
+    }
+
+    GraphicsContext* graphicsContext = paintInfo.context;
+    if (graphicsContext->paintingDisabled())
+        return;
+
+    if (styleToUse->outlineStyleIsAuto() || styleToUse->outlineStyle() == BNONE)
+        return;
+
+    Vector<LayoutRect> rects;
+
+    rects.append(LayoutRect());
+    for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) {
+        RootInlineBox* root = curr->root();
+        LayoutUnit top = max<LayoutUnit>(root->lineTop(), curr->logicalTop());
+        LayoutUnit bottom = min<LayoutUnit>(root->lineBottom(), curr->logicalBottom());
+        rects.append(LayoutRect(curr->x(), top, curr->logicalWidth(), bottom - top));
+    }
+    rects.append(LayoutRect());
+
+    Color outlineColor = styleToUse->visitedDependentColor(CSSPropertyOutlineColor);
+    bool useTransparencyLayer = outlineColor.hasAlpha();
+    if (useTransparencyLayer) {
+        graphicsContext->beginTransparencyLayer(static_cast<float>(outlineColor.alpha()) / 255);
+        outlineColor = Color(outlineColor.red(), outlineColor.green(), outlineColor.blue());
+    }
+
+    for (unsigned i = 1; i < rects.size() - 1; i++)
+        paintOutlineForLine(graphicsContext, paintOffset, rects.at(i - 1), rects.at(i), rects.at(i + 1), outlineColor);
+
+    if (useTransparencyLayer)
+        graphicsContext->endTransparencyLayer();
+}
+
+void RenderInline::paintOutlineForLine(GraphicsContext* graphicsContext, const LayoutPoint& paintOffset,
+                                       const LayoutRect& lastline, const LayoutRect& thisline, const LayoutRect& nextline,
+                                       const Color outlineColor)
+{
+    RenderStyle* styleToUse = style();
+    int outlineWidth = styleToUse->outlineWidth();
+    EBorderStyle outlineStyle = styleToUse->outlineStyle();
+
+    bool antialias = shouldAntialiasLines(graphicsContext);
+
+    int offset = style()->outlineOffset();
+
+    LayoutRect box(LayoutPoint(paintOffset.x() + thisline.x() - offset, paintOffset.y() + thisline.y() - offset),
+        LayoutSize(thisline.width() + offset, thisline.height() + offset));
+
+    IntRect pixelSnappedBox = pixelSnappedIntRect(box);
+    IntRect pixelSnappedLastLine = pixelSnappedIntRect(paintOffset.x() + lastline.x(), 0, lastline.width(), 0);
+    IntRect pixelSnappedNextLine = pixelSnappedIntRect(paintOffset.x() + nextline.x(), 0, nextline.width(), 0);
+    
+    // left edge
+    drawLineForBoxSide(graphicsContext,
+        pixelSnappedBox.x() - outlineWidth,
+        pixelSnappedBox.y() - (lastline.isEmpty() || thisline.x() < lastline.x() || (lastline.maxX() - 1) <= thisline.x() ? outlineWidth : 0),
+        pixelSnappedBox.x(),
+        pixelSnappedBox.maxY() + (nextline.isEmpty() || thisline.x() <= nextline.x() || (nextline.maxX() - 1) <= thisline.x() ? outlineWidth : 0),
+        BSLeft,
+        outlineColor, outlineStyle,
+        (lastline.isEmpty() || thisline.x() < lastline.x() || (lastline.maxX() - 1) <= thisline.x() ? outlineWidth : -outlineWidth),
+        (nextline.isEmpty() || thisline.x() <= nextline.x() || (nextline.maxX() - 1) <= thisline.x() ? outlineWidth : -outlineWidth),
+        antialias);
+    
+    // right edge
+    drawLineForBoxSide(graphicsContext,
+        pixelSnappedBox.maxX(),
+        pixelSnappedBox.y() - (lastline.isEmpty() || lastline.maxX() < thisline.maxX() || (thisline.maxX() - 1) <= lastline.x() ? outlineWidth : 0),
+        pixelSnappedBox.maxX() + outlineWidth,
+        pixelSnappedBox.maxY() + (nextline.isEmpty() || nextline.maxX() <= thisline.maxX() || (thisline.maxX() - 1) <= nextline.x() ? outlineWidth : 0),
+        BSRight,
+        outlineColor, outlineStyle,
+        (lastline.isEmpty() || lastline.maxX() < thisline.maxX() || (thisline.maxX() - 1) <= lastline.x() ? outlineWidth : -outlineWidth),
+        (nextline.isEmpty() || nextline.maxX() <= thisline.maxX() || (thisline.maxX() - 1) <= nextline.x() ? outlineWidth : -outlineWidth),
+        antialias);
+    // upper edge
+    if (thisline.x() < lastline.x())
+        drawLineForBoxSide(graphicsContext,
+            pixelSnappedBox.x() - outlineWidth,
+            pixelSnappedBox.y() - outlineWidth,
+            min(pixelSnappedBox.maxX() + outlineWidth, (lastline.isEmpty() ? 1000000 : pixelSnappedLastLine.x())),
+            pixelSnappedBox.y(),
+            BSTop, outlineColor, outlineStyle,
+            outlineWidth,
+            (!lastline.isEmpty() && paintOffset.x() + lastline.x() + 1 < pixelSnappedBox.maxX() + outlineWidth) ? -outlineWidth : outlineWidth,
+            antialias);
+    
+    if (lastline.maxX() < thisline.maxX())
+        drawLineForBoxSide(graphicsContext,
+            max(lastline.isEmpty() ? -1000000 : pixelSnappedLastLine.maxX(), pixelSnappedBox.x() - outlineWidth),
+            pixelSnappedBox.y() - outlineWidth,
+            pixelSnappedBox.maxX() + outlineWidth,
+            pixelSnappedBox.y(),
+            BSTop, outlineColor, outlineStyle,
+            (!lastline.isEmpty() && pixelSnappedBox.x() - outlineWidth < paintOffset.x() + lastline.maxX()) ? -outlineWidth : outlineWidth,
+            outlineWidth, antialias);
+
+    if (thisline.x() == thisline.maxX())
+          drawLineForBoxSide(graphicsContext,
+            pixelSnappedBox.x() - outlineWidth,
+            pixelSnappedBox.y() - outlineWidth,
+            pixelSnappedBox.maxX() + outlineWidth,
+            pixelSnappedBox.y(),
+            BSTop, outlineColor, outlineStyle,
+            outlineWidth,
+            outlineWidth,
+            antialias);
+
+    // lower edge
+    if (thisline.x() < nextline.x())
+        drawLineForBoxSide(graphicsContext,
+            pixelSnappedBox.x() - outlineWidth,
+            pixelSnappedBox.maxY(),
+            min(pixelSnappedBox.maxX() + outlineWidth, !nextline.isEmpty() ? pixelSnappedNextLine.x() + 1 : 1000000),
+            pixelSnappedBox.maxY() + outlineWidth,
+            BSBottom, outlineColor, outlineStyle,
+            outlineWidth,
+            (!nextline.isEmpty() && paintOffset.x() + nextline.x() + 1 < pixelSnappedBox.maxX() + outlineWidth) ? -outlineWidth : outlineWidth,
+            antialias);
+    
+    if (nextline.maxX() < thisline.maxX())
+        drawLineForBoxSide(graphicsContext,
+            max(!nextline.isEmpty() ? pixelSnappedNextLine.maxX() : -1000000, pixelSnappedBox.x() - outlineWidth),
+            pixelSnappedBox.maxY(),
+            pixelSnappedBox.maxX() + outlineWidth,
+            pixelSnappedBox.maxY() + outlineWidth,
+            BSBottom, outlineColor, outlineStyle,
+            (!nextline.isEmpty() && pixelSnappedBox.x() - outlineWidth < paintOffset.x() + nextline.maxX()) ? -outlineWidth : outlineWidth,
+            outlineWidth, antialias);
+
+    if (thisline.x() == thisline.maxX())
+          drawLineForBoxSide(graphicsContext,
+            pixelSnappedBox.x() - outlineWidth,
+            pixelSnappedBox.maxY(),
+            pixelSnappedBox.maxX() + outlineWidth,
+            pixelSnappedBox.maxY() + outlineWidth,
+            BSBottom, outlineColor, outlineStyle,
+            outlineWidth,
+            outlineWidth,
+            antialias);
+}
+
+void RenderInline::addAnnotatedRegions(Vector<AnnotatedRegionValue>& regions)
+{
+    // Convert the style regions to absolute coordinates.
+    if (style()->visibility() != VISIBLE)
+        return;
+
+    if (style()->getDraggableRegionMode() == DraggableRegionNone)
+        return;
+
+    AnnotatedRegionValue region;
+    region.draggable = style()->getDraggableRegionMode() == DraggableRegionDrag;
+    region.bounds = linesBoundingBox();
+
+    RenderObject* container = containingBlock();
+    if (!container)
+        container = this;
+
+    FloatPoint absPos = container->localToAbsolute();
+    region.bounds.setX(absPos.x() + region.bounds.x());
+    region.bounds.setY(absPos.y() + region.bounds.y());
+    
+    regions.append(region);
+}
+
+void RenderInline::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, PlatformMemoryTypes::Rendering);
+    RenderBoxModelObject::reportMemoryUsage(memoryObjectInfo);
+    info.addMember(m_children, "children");
+    info.addMember(m_lineBoxes, "lineBoxes");
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderInline.h b/Source/core/rendering/RenderInline.h
new file mode 100644
index 0000000..be0def1
--- /dev/null
+++ b/Source/core/rendering/RenderInline.h
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 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 RenderInline_h
+#define RenderInline_h
+
+#include "core/rendering/InlineFlowBox.h"
+#include "core/rendering/RenderBoxModelObject.h"
+#include "core/rendering/RenderLineBoxList.h"
+
+namespace WebCore {
+
+class Position;
+
+class RenderInline : public RenderBoxModelObject {
+public:
+    explicit RenderInline(Element*);
+
+    static RenderInline* createAnonymous(Document*);
+
+    RenderObject* firstChild() const { ASSERT(children() == virtualChildren()); return children()->firstChild(); }
+    RenderObject* lastChild() const { ASSERT(children() == virtualChildren()); return children()->lastChild(); }
+
+    virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0);
+
+    Element* node() const { return toElement(RenderBoxModelObject::node()); }
+
+    virtual LayoutUnit marginLeft() const OVERRIDE FINAL;
+    virtual LayoutUnit marginRight() const OVERRIDE FINAL;
+    virtual LayoutUnit marginTop() const OVERRIDE FINAL;
+    virtual LayoutUnit marginBottom() const OVERRIDE FINAL;
+    virtual LayoutUnit marginBefore(const RenderStyle* otherStyle = 0) const OVERRIDE FINAL;
+    virtual LayoutUnit marginAfter(const RenderStyle* otherStyle = 0) const OVERRIDE FINAL;
+    virtual LayoutUnit marginStart(const RenderStyle* otherStyle = 0) const OVERRIDE FINAL;
+    virtual LayoutUnit marginEnd(const RenderStyle* otherStyle = 0) const OVERRIDE FINAL;
+
+    virtual void absoluteRects(Vector<IntRect>&, const LayoutPoint& accumulatedOffset) const OVERRIDE FINAL;
+    virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const;
+
+    virtual LayoutSize offsetFromContainer(RenderObject*, const LayoutPoint&, bool* offsetDependsOnPoint = 0) const OVERRIDE FINAL;
+
+    IntRect linesBoundingBox() const;
+    LayoutRect linesVisualOverflowBoundingBox() const;
+
+    InlineFlowBox* createAndAppendInlineFlowBox();
+
+    void dirtyLineBoxes(bool fullLayout);
+    void deleteLineBoxTree();
+
+    RenderLineBoxList* lineBoxes() { return &m_lineBoxes; }
+    const RenderLineBoxList* lineBoxes() const { return &m_lineBoxes; }
+
+    InlineFlowBox* firstLineBox() const { return m_lineBoxes.firstLineBox(); }
+    InlineFlowBox* lastLineBox() const { return m_lineBoxes.lastLineBox(); }
+    InlineBox* firstLineBoxIncludingCulling() const { return alwaysCreateLineBoxes() ? firstLineBox() : culledInlineFirstLineBox(); }
+    InlineBox* lastLineBoxIncludingCulling() const { return alwaysCreateLineBoxes() ? lastLineBox() : culledInlineLastLineBox(); }
+
+    virtual RenderBoxModelObject* virtualContinuation() const OVERRIDE FINAL { return continuation(); }
+    RenderInline* inlineElementContinuation() const;
+
+    virtual void updateDragState(bool dragOn) OVERRIDE FINAL;
+    
+    LayoutSize offsetForInFlowPositionedInline(const RenderBox* child) const;
+
+    virtual void addFocusRingRects(Vector<IntRect>&, const LayoutPoint& additionalOffset, const RenderLayerModelObject* paintContainer = 0) OVERRIDE FINAL;
+    void paintOutline(PaintInfo&, const LayoutPoint&);
+
+    using RenderBoxModelObject::continuation;
+    using RenderBoxModelObject::setContinuation;
+
+    bool alwaysCreateLineBoxes() const { return m_alwaysCreateLineBoxes; }
+    void setAlwaysCreateLineBoxes() { m_alwaysCreateLineBoxes = true; }
+    void updateAlwaysCreateLineBoxes(bool fullLayout);
+
+    virtual LayoutRect localCaretRect(InlineBox*, int, LayoutUnit* extraWidthToEndOfLine) OVERRIDE FINAL;
+
+    bool hitTestCulledInline(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset);
+
+    virtual void reportMemoryUsage(MemoryObjectInfo*) const OVERRIDE FINAL;
+
+protected:
+    virtual void willBeDestroyed();
+
+    virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE;
+
+private:
+    virtual RenderObjectChildList* virtualChildren() OVERRIDE FINAL { return children(); }
+    virtual const RenderObjectChildList* virtualChildren() const OVERRIDE FINAL { return children(); }
+    const RenderObjectChildList* children() const { return &m_children; }
+    RenderObjectChildList* children() { return &m_children; }
+
+    virtual const char* renderName() const;
+
+    virtual bool isRenderInline() const OVERRIDE FINAL { return true; }
+
+    LayoutRect culledInlineVisualOverflowBoundingBox() const;
+    InlineBox* culledInlineFirstLineBox() const;
+    InlineBox* culledInlineLastLineBox() const;
+
+    template<typename GeneratorContext>
+    void generateLineBoxRects(GeneratorContext& yield) const;
+    template<typename GeneratorContext>
+    void generateCulledLineBoxRects(GeneratorContext& yield, const RenderInline* container) const;
+
+    void addChildToContinuation(RenderObject* newChild, RenderObject* beforeChild);
+    virtual void addChildIgnoringContinuation(RenderObject* newChild, RenderObject* beforeChild = 0) OVERRIDE FINAL;
+
+    void splitInlines(RenderBlock* fromBlock, RenderBlock* toBlock, RenderBlock* middleBlock,
+                      RenderObject* beforeChild, RenderBoxModelObject* oldCont);
+    void splitFlow(RenderObject* beforeChild, RenderBlock* newBlockBox,
+                   RenderObject* newChild, RenderBoxModelObject* oldCont);
+
+    virtual void layout() OVERRIDE FINAL { ASSERT_NOT_REACHED(); } // Do nothing for layout()
+
+    virtual void paint(PaintInfo&, const LayoutPoint&) OVERRIDE FINAL;
+
+    virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE FINAL;
+
+    virtual bool requiresLayer() const { return isInFlowPositioned() || createsGroup() || hasClipPath(); }
+
+    virtual LayoutUnit offsetLeft() const OVERRIDE FINAL;
+    virtual LayoutUnit offsetTop() const OVERRIDE FINAL;
+    virtual LayoutUnit offsetWidth() const OVERRIDE FINAL { return linesBoundingBox().width(); }
+    virtual LayoutUnit offsetHeight() const OVERRIDE FINAL { return linesBoundingBox().height(); }
+
+    virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const OVERRIDE;
+    virtual LayoutRect rectWithOutlineForRepaint(const RenderLayerModelObject* repaintContainer, LayoutUnit outlineWidth) const OVERRIDE FINAL;
+    virtual void computeRectForRepaint(const RenderLayerModelObject* repaintContainer, LayoutRect&, bool fixed) const OVERRIDE FINAL;
+
+    virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = 0) const OVERRIDE;
+    virtual const RenderObject* pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap&) const OVERRIDE;
+
+    virtual VisiblePosition positionForPoint(const LayoutPoint&) OVERRIDE FINAL;
+
+    virtual LayoutRect frameRectForStickyPositioning() const OVERRIDE FINAL { return linesBoundingBox(); }
+
+    virtual IntRect borderBoundingBox() const OVERRIDE FINAL
+    {
+        IntRect boundingBox = linesBoundingBox();
+        return IntRect(0, 0, boundingBox.width(), boundingBox.height());
+    }
+
+    virtual InlineFlowBox* createInlineFlowBox(); // Subclassed by SVG and Ruby
+
+    virtual void dirtyLinesFromChangedChild(RenderObject* child) OVERRIDE FINAL { m_lineBoxes.dirtyLinesFromChangedChild(this, child); }
+
+    virtual LayoutUnit lineHeight(bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const OVERRIDE FINAL;
+    virtual int baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const OVERRIDE FINAL;
+    
+    virtual void childBecameNonInline(RenderObject* child) OVERRIDE FINAL;
+
+    virtual void updateHitTestResult(HitTestResult&, const LayoutPoint&) OVERRIDE FINAL;
+
+    virtual void imageChanged(WrappedImagePtr, const IntRect* = 0) OVERRIDE FINAL;
+
+    virtual void addAnnotatedRegions(Vector<AnnotatedRegionValue>&) OVERRIDE FINAL;
+    
+    virtual void updateFromStyle() OVERRIDE FINAL;
+    
+    RenderInline* clone() const;
+
+    void paintOutlineForLine(GraphicsContext*, const LayoutPoint&, const LayoutRect& prevLine, const LayoutRect& thisLine,
+                             const LayoutRect& nextLine, const Color);
+    RenderBoxModelObject* continuationBefore(RenderObject* beforeChild);
+
+    RenderObjectChildList m_children;
+    RenderLineBoxList m_lineBoxes;   // All of the line boxes created for this inline flow.  For example, <i>Hello<br>world.</i> will have two <i> line boxes.
+
+    bool m_alwaysCreateLineBoxes : 1;
+};
+
+inline RenderInline* toRenderInline(RenderObject* object)
+{ 
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isRenderInline());
+    return static_cast<RenderInline*>(object);
+}
+
+inline const RenderInline* toRenderInline(const RenderObject* object)
+{ 
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isRenderInline());
+    return static_cast<const RenderInline*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderInline(const RenderInline*);
+
+} // namespace WebCore
+
+#endif // RenderInline_h
diff --git a/Source/core/rendering/RenderInputSpeech.cpp b/Source/core/rendering/RenderInputSpeech.cpp
new file mode 100644
index 0000000..b632d65
--- /dev/null
+++ b/Source/core/rendering/RenderInputSpeech.cpp
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2010 Google 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:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+ * OWNER 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(INPUT_SPEECH)
+#include "core/rendering/RenderInputSpeech.h"
+
+#include "HTMLNames.h"
+#include "core/html/shadow/TextControlInnerElements.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/rendering/PaintInfo.h"
+#include "core/rendering/RenderBox.h"
+
+namespace WebCore {
+
+static const float defaultControlFontPixelSize = 13;
+static const float defaultSpeechButtonSize = 16;
+static const float minSpeechButtonSize = 8;
+static const float maxSpeechButtonSize = 40;
+
+void RenderInputSpeech::adjustInputFieldSpeechButtonStyle(StyleResolver*, RenderStyle* style, Element*)
+{
+    // Scale the button size based on the font size.
+    float fontScale = style->fontSize() / defaultControlFontPixelSize;
+    int speechButtonSize = lroundf(std::min(std::max(minSpeechButtonSize, defaultSpeechButtonSize * fontScale), maxSpeechButtonSize));
+    style->setWidth(Length(speechButtonSize, Fixed));
+    style->setHeight(Length(speechButtonSize, Fixed));
+}
+
+bool RenderInputSpeech::paintInputFieldSpeechButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
+{
+    Element* element = object->node()->isElementNode() ? toElement(object->node()) : 0;
+    if (!element || !element->isInputFieldSpeechButtonElement())
+        return false;
+
+    // Get the renderer of <input> element.
+    Node* input = object->node()->shadowHost();
+    if (!input->renderer()->isBox())
+        return false;
+    RenderBox* inputRenderBox = toRenderBox(input->renderer());
+    LayoutRect inputContentBox = inputRenderBox->contentBoxRect();
+
+    // Make sure the scaled button stays square and will fit in its parent's box.
+    LayoutUnit buttonSize = std::min(inputContentBox.width(), std::min<LayoutUnit>(inputContentBox.height(), rect.height()));
+    // Calculate button's coordinates relative to the input element.
+    // Center the button vertically.  Round up though, so if it has to be one pixel off-center, it will
+    // be one pixel closer to the bottom of the field.  This tends to look better with the text.
+    LayoutRect buttonRect(object->offsetFromAncestorContainer(inputRenderBox).width(),
+                          inputContentBox.y() + (inputContentBox.height() - buttonSize + 1) / 2,
+                          buttonSize, buttonSize);
+
+    // Compute an offset between the part renderer and the input renderer.
+    LayoutSize offsetFromInputRenderer = -(object->offsetFromAncestorContainer(inputRenderBox));
+    // Move the rect into partRenderer's coords.
+    buttonRect.move(offsetFromInputRenderer);
+    // Account for the local drawing offset.
+    buttonRect.moveBy(rect.location());
+
+    DEFINE_STATIC_LOCAL(RefPtr<Image>, imageStateNormal, (Image::loadPlatformResource("inputSpeech")));
+    DEFINE_STATIC_LOCAL(RefPtr<Image>, imageStateRecording, (Image::loadPlatformResource("inputSpeechRecording")));
+    DEFINE_STATIC_LOCAL(RefPtr<Image>, imageStateWaiting, (Image::loadPlatformResource("inputSpeechWaiting")));
+
+    InputFieldSpeechButtonElement* speechButton = toInputFieldSpeechButtonElement(element);
+    Image* image = imageStateNormal.get();
+    if (speechButton->state() == InputFieldSpeechButtonElement::Recording)
+        image = imageStateRecording.get();
+    else if (speechButton->state() == InputFieldSpeechButtonElement::Recognizing)
+        image = imageStateWaiting.get();
+    paintInfo.context->drawImage(image, object->style()->colorSpace(), pixelSnappedIntRect(buttonRect));
+
+    return false;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(INPUT_SPEECH)
diff --git a/Source/core/rendering/RenderInputSpeech.h b/Source/core/rendering/RenderInputSpeech.h
new file mode 100644
index 0000000..6735961
--- /dev/null
+++ b/Source/core/rendering/RenderInputSpeech.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2010 Google 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:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+ * OWNER 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 RenderInputSpeech_h
+#define RenderInputSpeech_h
+
+#if ENABLE(INPUT_SPEECH)
+
+namespace WebCore {
+
+struct PaintInfo;
+
+class Element;
+class IntRect;
+class RenderObject;
+class RenderStyle;
+class StyleResolver;
+
+class RenderInputSpeech {
+public:
+    static void adjustInputFieldSpeechButtonStyle(StyleResolver*, RenderStyle*, Element*);
+    static bool paintInputFieldSpeechButton(RenderObject*, const PaintInfo&, const IntRect&);
+};
+
+} // namespace WebCore
+
+#endif
+#endif // RenderInputSpeech_h
diff --git a/Source/core/rendering/RenderLayer.cpp b/Source/core/rendering/RenderLayer.cpp
new file mode 100644
index 0000000..b86a2ae
--- /dev/null
+++ b/Source/core/rendering/RenderLayer.cpp
@@ -0,0 +1,6445 @@
+/*
+ * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc. All rights reserved.
+ *
+ * Portions are Copyright (C) 1998 Netscape Communications Corporation.
+ *
+ * Other contributors:
+ *   Robert O'Callahan <roc+@cs.cmu.edu>
+ *   David Baron <dbaron@fas.harvard.edu>
+ *   Christian Biesinger <cbiesinger@web.de>
+ *   Randall Jesup <rjesup@wgate.com>
+ *   Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
+ *   Josh Soref <timeless@mac.com>
+ *   Boris Zbarsky <bzbarsky@mit.edu>
+ *
+ * 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 "core/rendering/RenderLayer.h"
+
+#include "CSSPropertyNames.h"
+#include "HTMLNames.h"
+#include "core/css/StylePropertySet.h"
+#include "core/css/StyleResolver.h"
+#include "core/dom/Document.h"
+#include "core/dom/DocumentEventQueue.h"
+#include "core/dom/OverflowEvent.h"
+#include "core/dom/ShadowRoot.h"
+#include "core/dom/WebCoreMemoryInstrumentation.h"
+#include "core/editing/FrameSelection.h"
+#include "core/html/HTMLFrameElement.h"
+#include "core/html/HTMLFrameOwnerElement.h"
+#include "core/loader/FrameLoader.h"
+#include "core/loader/FrameLoaderClient.h"
+#include "core/page/Chrome.h"
+#include "core/page/EventHandler.h"
+#include "core/page/FocusController.h"
+#include "core/page/Frame.h"
+#include "core/page/FrameTree.h"
+#include "core/page/FrameView.h"
+#include "core/page/Page.h"
+#include "core/page/Settings.h"
+#include "core/page/UseCounter.h"
+#include "core/page/animation/AnimationController.h"
+#include "core/page/scrolling/ScrollingCoordinator.h"
+#include "core/platform/FloatConversion.h"
+#include "core/platform/HistogramSupport.h"
+#include "core/platform/PlatformMouseEvent.h"
+#include "core/platform/ScrollAnimator.h"
+#include "core/platform/Scrollbar.h"
+#include "core/platform/ScrollbarTheme.h"
+#include "core/platform/graphics/FloatPoint3D.h"
+#include "core/platform/graphics/FloatRect.h"
+#include "core/platform/graphics/Gradient.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/platform/graphics/filters/custom/CustomFilterGlobalContext.h"
+#include "core/platform/graphics/filters/custom/CustomFilterOperation.h"
+#include "core/platform/graphics/filters/custom/CustomFilterValidatedProgram.h"
+#include "core/platform/graphics/filters/custom/ValidatedCustomFilterOperation.h"
+#include "core/platform/graphics/filters/FEColorMatrix.h"
+#include "core/platform/graphics/filters/FEMerge.h"
+#include "core/platform/graphics/filters/SourceGraphic.h"
+#include "core/platform/graphics/transforms/ScaleTransformOperation.h"
+#include "core/platform/graphics/transforms/TransformationMatrix.h"
+#include "core/platform/graphics/transforms/TranslateTransformOperation.h"
+#include "core/platform/text/TextStream.h"
+#include "core/rendering/ColumnInfo.h"
+#include "core/rendering/FilterEffectRenderer.h"
+#include "core/rendering/HitTestRequest.h"
+#include "core/rendering/HitTestResult.h"
+#include "core/rendering/HitTestingTransformState.h"
+#include "core/rendering/OverlapTestRequestClient.h"
+#include "core/rendering/RenderArena.h"
+#include "core/rendering/RenderFlowThread.h"
+#include "core/rendering/RenderGeometryMap.h"
+#include "core/rendering/RenderInline.h"
+#include "core/rendering/RenderLayerBacking.h"
+#include "core/rendering/RenderLayerCompositor.h"
+#include "core/rendering/RenderLazyBlock.h"
+#include "core/rendering/RenderMarquee.h"
+#include "core/rendering/RenderReplica.h"
+#include "core/rendering/RenderScrollbar.h"
+#include "core/rendering/RenderScrollbarPart.h"
+#include "core/rendering/RenderTheme.h"
+#include "core/rendering/RenderTreeAsText.h"
+#include "core/rendering/RenderView.h"
+#include "core/rendering/svg/RenderSVGResourceClipper.h"
+#include <wtf/MemoryInstrumentationVector.h>
+#include <wtf/StdLibExtras.h>
+#include <wtf/text/CString.h>
+#include <wtf/UnusedParam.h>
+
+#if ENABLE(SVG)
+#include "SVGNames.h"
+#endif
+
+#define MIN_INTERSECT_FOR_REVEAL 32
+
+using namespace std;
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+const int MinimumWidthWhileResizing = 100;
+const int MinimumHeightWhileResizing = 40;
+
+bool ClipRect::intersects(const HitTestLocation& hitTestLocation) const
+{
+    return hitTestLocation.intersects(m_rect);
+}
+
+RenderLayer::RenderLayer(RenderLayerModelObject* renderer)
+    : m_inResizeMode(false)
+    , m_scrollDimensionsDirty(true)
+    , m_normalFlowListDirty(true)
+    , m_hasSelfPaintingLayerDescendant(false)
+    , m_hasSelfPaintingLayerDescendantDirty(false)
+    , m_hasOutOfFlowPositionedDescendant(false)
+    , m_hasOutOfFlowPositionedDescendantDirty(true)
+    , m_needsCompositedScrolling(false)
+    , m_descendantsAreContiguousInStackingOrder(false)
+    , m_descendantsAreContiguousInStackingOrderDirty(true)
+    , m_isRootLayer(renderer->isRenderView())
+    , m_usedTransparency(false)
+    , m_paintingInsideReflection(false)
+    , m_inOverflowRelayout(false)
+    , m_repaintStatus(NeedsNormalRepaint)
+    , m_visibleContentStatusDirty(true)
+    , m_hasVisibleContent(false)
+    , m_visibleDescendantStatusDirty(false)
+    , m_hasVisibleDescendant(false)
+    , m_isPaginated(false)
+    , m_3DTransformedDescendantStatusDirty(true)
+    , m_has3DTransformedDescendant(false)
+    , m_containsDirtyOverlayScrollbars(false)
+    , m_updatingMarqueePosition(false)
+#if !ASSERT_DISABLED
+    , m_layerListMutationAllowed(true)
+#endif
+    , m_canSkipRepaintRectsUpdateOnScroll(renderer->isTableCell())
+    , m_hasFilterInfo(false)
+#if ENABLE(CSS_COMPOSITING)
+    , m_blendMode(BlendModeNormal)
+#endif
+    , m_renderer(renderer)
+    , m_parent(0)
+    , m_previous(0)
+    , m_next(0)
+    , m_first(0)
+    , m_last(0)
+    , m_staticInlinePosition(0)
+    , m_staticBlockPosition(0)
+    , m_reflection(0)
+    , m_scrollCorner(0)
+    , m_resizer(0)
+    , m_enclosingPaginationLayer(0)
+{
+    m_isNormalFlowOnly = shouldBeNormalFlowOnly();
+    m_isSelfPaintingLayer = shouldBeSelfPaintingLayer();
+
+    // Non-stacking containers should have empty z-order lists. As this is already the case,
+    // there is no need to dirty / recompute these lists.
+    m_zOrderListsDirty = isStackingContainer();
+
+    ScrollableArea::setConstrainsScrollingToContentEdge(false);
+
+    if (!renderer->firstChild() && renderer->style()) {
+        m_visibleContentStatusDirty = false;
+        m_hasVisibleContent = renderer->style()->visibility() == VISIBLE;
+    }
+
+    Node* node = renderer->node();
+    if (node && node->isElementNode()) {
+        // We save and restore only the scrollOffset as the other scroll values are recalculated.
+        Element* element = toElement(node);
+        m_scrollOffset = element->savedLayerScrollOffset();
+        if (!m_scrollOffset.isZero())
+            scrollAnimator()->setCurrentPosition(FloatPoint(m_scrollOffset.width(), m_scrollOffset.height()));
+        element->setSavedLayerScrollOffset(IntSize());
+    }
+}
+
+RenderLayer::~RenderLayer()
+{
+    if (inResizeMode() && !renderer()->documentBeingDestroyed()) {
+        if (Frame* frame = renderer()->frame())
+            frame->eventHandler()->resizeLayerDestroyed();
+    }
+
+    if (Frame* frame = renderer()->frame()) {
+        if (FrameView* frameView = frame->view())
+            frameView->removeScrollableArea(this);
+    }
+
+    if (!m_renderer->documentBeingDestroyed()) {
+        Node* node = m_renderer->node();
+        if (node && node->isElementNode())
+            toElement(node)->setSavedLayerScrollOffset(m_scrollOffset);
+    }
+
+    destroyScrollbar(HorizontalScrollbar);
+    destroyScrollbar(VerticalScrollbar);
+
+    if (renderer()->frame() && renderer()->frame()->page()) {
+        if (ScrollingCoordinator* scrollingCoordinator = renderer()->frame()->page()->scrollingCoordinator())
+            scrollingCoordinator->willDestroyScrollableArea(this);
+    }
+
+    if (m_reflection)
+        removeReflection();
+
+    removeFilterInfoIfNeeded();
+
+    // Child layers will be deleted by their corresponding render objects, so
+    // we don't need to delete them ourselves.
+
+    clearBacking(true);
+
+    if (m_scrollCorner)
+        m_scrollCorner->destroy();
+    if (m_resizer)
+        m_resizer->destroy();
+}
+
+#ifndef NDEBUG
+String RenderLayer::debugName() const
+{
+    String name = renderer()->debugName();
+    if (!isReflection())
+        return name;
+    return name + " (reflection)";
+}
+#endif
+
+RenderLayerCompositor* RenderLayer::compositor() const
+{
+    if (!renderer()->view())
+        return 0;
+    return renderer()->view()->compositor();
+}
+
+void RenderLayer::contentChanged(ContentChangeType changeType)
+{
+    // This can get called when video becomes accelerated, so the layers may change.
+    if ((changeType == CanvasChanged || changeType == VideoChanged || changeType == FullScreenChanged) && compositor()->updateLayerCompositingState(this))
+        compositor()->setCompositingLayersNeedRebuild();
+
+    if (m_backing)
+        m_backing->contentChanged(changeType);
+}
+
+bool RenderLayer::canRender3DTransforms() const
+{
+    return compositor()->canRender3DTransforms();
+}
+
+bool RenderLayer::paintsWithFilters() const
+{
+    // FIXME: Eventually there will be more factors than isComposited() to decide whether or not to render the filter
+    if (!renderer()->hasFilter())
+        return false;
+        
+    if (!isComposited())
+        return true;
+
+    if (!m_backing || !m_backing->canCompositeFilters())
+        return true;
+
+    return false;
+}
+    
+bool RenderLayer::requiresFullLayerImageForFilters() const 
+{
+    if (!paintsWithFilters())
+        return false;
+    FilterEffectRenderer* filter = filterRenderer();
+    return filter ? filter->hasFilterThatMovesPixels() : false;
+}
+
+LayoutPoint RenderLayer::computeOffsetFromRoot(bool& hasLayerOffset) const
+{
+    hasLayerOffset = true;
+
+    if (!parent())
+        return LayoutPoint();
+
+    // This is similar to root() but we check if an ancestor layer would
+    // prevent the optimization from working.
+    const RenderLayer* rootLayer = 0;
+    for (const RenderLayer* parentLayer = parent(); parentLayer; rootLayer = parentLayer, parentLayer = parentLayer->parent()) {
+        hasLayerOffset = parentLayer->canUseConvertToLayerCoords();
+        if (!hasLayerOffset)
+            return LayoutPoint();
+    }
+    ASSERT(rootLayer == root());
+
+    LayoutPoint offset;
+    parent()->convertToLayerCoords(rootLayer, offset);
+    return offset;
+}
+
+void RenderLayer::updateLayerPositionsAfterLayout(const RenderLayer* rootLayer, UpdateLayerPositionsFlags flags)
+{
+    RenderGeometryMap geometryMap(UseTransforms);
+    if (this != rootLayer)
+        geometryMap.pushMappingsToAncestor(parent(), 0);
+    updateLayerPositions(&geometryMap, flags);
+}
+
+void RenderLayer::updateLayerPositions(RenderGeometryMap* geometryMap, UpdateLayerPositionsFlags flags)
+{
+    updateLayerPosition(); // For relpositioned layers or non-positioned layers,
+                           // we need to keep in sync, since we may have shifted relative
+                           // to our parent layer.
+    if (geometryMap)
+        geometryMap->pushMappingsToAncestor(this, parent());
+
+    // Clear our cached clip rect information.
+    clearClipRects();
+    
+    if (hasOverflowControls()) {
+        LayoutPoint offsetFromRoot;
+        if (geometryMap)
+            offsetFromRoot = LayoutPoint(geometryMap->absolutePoint(FloatPoint()));
+        else {
+            // FIXME: It looks suspicious to call convertToLayerCoords here
+            // as canUseConvertToLayerCoords may be true for an ancestor layer.
+            convertToLayerCoords(root(), offsetFromRoot);
+        }
+        positionOverflowControls(toIntSize(roundedIntPoint(offsetFromRoot)));
+    }
+
+    updateDescendantDependentFlags();
+
+    if (flags & UpdatePagination)
+        updatePagination();
+    else {
+        m_isPaginated = false;
+        m_enclosingPaginationLayer = 0;
+    }
+
+    if (m_hasVisibleContent) {
+        RenderView* view = renderer()->view();
+        ASSERT(view);
+        // FIXME: LayoutState does not work with RenderLayers as there is not a 1-to-1
+        // mapping between them and the RenderObjects. It would be neat to enable
+        // LayoutState outside the layout() phase and use it here.
+        ASSERT(!view->layoutStateEnabled());
+
+        RenderLayerModelObject* repaintContainer = renderer()->containerForRepaint();
+        LayoutRect oldRepaintRect = m_repaintRect;
+        LayoutRect oldOutlineBox = m_outlineBox;
+        computeRepaintRects(repaintContainer, geometryMap);
+
+        // FIXME: Should ASSERT that value calculated for m_outlineBox using the cached offset is the same
+        // as the value not using the cached offset, but we can't due to https://bugs.webkit.org/show_bug.cgi?id=37048
+        if (flags & CheckForRepaint) {
+            if (view && !view->printing()) {
+                if (m_repaintStatus & NeedsFullRepaint) {
+                    renderer()->repaintUsingContainer(repaintContainer, pixelSnappedIntRect(oldRepaintRect));
+                    if (m_repaintRect != oldRepaintRect)
+                        renderer()->repaintUsingContainer(repaintContainer, pixelSnappedIntRect(m_repaintRect));
+                } else if (shouldRepaintAfterLayout())
+                    renderer()->repaintAfterLayoutIfNeeded(repaintContainer, oldRepaintRect, oldOutlineBox, &m_repaintRect, &m_outlineBox);
+            }
+        }
+    } else
+        clearRepaintRects();
+
+    m_repaintStatus = NeedsNormalRepaint;
+
+    // Go ahead and update the reflection's position and size.
+    if (m_reflection)
+        m_reflection->layout();
+
+    // Clear the IsCompositingUpdateRoot flag once we've found the first compositing layer in this update.
+    bool isUpdateRoot = (flags & IsCompositingUpdateRoot);
+    if (isComposited())
+        flags &= ~IsCompositingUpdateRoot;
+
+    if (useRegionBasedColumns() && renderer()->isInFlowRenderFlowThread()) {
+        updatePagination();
+        flags |= UpdatePagination;
+    }
+    
+    if (renderer()->hasColumns())
+        flags |= UpdatePagination;
+
+    for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
+        child->updateLayerPositions(geometryMap, flags);
+
+    if ((flags & UpdateCompositingLayers) && isComposited()) {
+        RenderLayerBacking::UpdateAfterLayoutFlags updateFlags = RenderLayerBacking::CompositingChildrenOnly;
+        if (flags & NeedsFullRepaintInBacking)
+            updateFlags |= RenderLayerBacking::NeedsFullRepaint;
+        if (isUpdateRoot)
+            updateFlags |= RenderLayerBacking::IsUpdateRoot;
+        backing()->updateAfterLayout(updateFlags);
+    }
+
+    // With all our children positioned, now update our marquee if we need to.
+    if (m_marquee) {
+        // FIXME: would like to use TemporaryChange<> but it doesn't work with bitfields.
+        bool oldUpdatingMarqueePosition = m_updatingMarqueePosition;
+        m_updatingMarqueePosition = true;
+        m_marquee->updateMarqueePosition();
+        m_updatingMarqueePosition = oldUpdatingMarqueePosition;
+    }
+
+    if (geometryMap)
+        geometryMap->popMappingsToAncestor(parent());
+}
+
+LayoutRect RenderLayer::repaintRectIncludingNonCompositingDescendants() const
+{
+    LayoutRect repaintRect = m_repaintRect;
+    for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
+        // Don't include repaint rects for composited child layers; they will paint themselves and have a different origin.
+        if (child->isComposited())
+            continue;
+
+        repaintRect.unite(child->repaintRectIncludingNonCompositingDescendants());
+    }
+    return repaintRect;
+}
+
+void RenderLayer::setAncestorChainHasSelfPaintingLayerDescendant()
+{
+    for (RenderLayer* layer = this; layer; layer = layer->parent()) {
+        if (!layer->m_hasSelfPaintingLayerDescendantDirty && layer->hasSelfPaintingLayerDescendant())
+            break;
+
+        layer->m_hasSelfPaintingLayerDescendantDirty = false;
+        layer->m_hasSelfPaintingLayerDescendant = true;
+    }
+}
+
+void RenderLayer::dirtyAncestorChainHasSelfPaintingLayerDescendantStatus()
+{
+    for (RenderLayer* layer = this; layer; layer = layer->parent()) {
+        layer->m_hasSelfPaintingLayerDescendantDirty = true;
+        // If we have reached a self-painting layer, we know our parent should have a self-painting descendant
+        // in this case, there is no need to dirty our ancestors further.
+        if (layer->isSelfPaintingLayer()) {
+            ASSERT(!parent() || parent()->m_hasSelfPaintingLayerDescendantDirty || parent()->hasSelfPaintingLayerDescendant());
+            break;
+        }
+    }
+}
+
+bool RenderLayer::acceleratedCompositingForOverflowScrollEnabled() const
+{
+    return renderer()->frame()
+        && renderer()->frame()->page()
+        && renderer()->frame()->page()->settings()->acceleratedCompositingForOverflowScrollEnabled();
+}
+
+// If we are a stacking container, then this function will determine if our
+// descendants for a contiguous block in stacking order. This is required in
+// order for an element to be safely promoted to a stacking container. It is safe
+// to become a stacking container if this change would not alter the stacking
+// order of layers on the page. That can only happen if a non-descendant appear
+// between us and our descendants in stacking order. Here's an example:
+//
+//                                 this
+//                                /  |  \.
+//                               A   B   C
+//                              /\   |   /\.
+//                             0 -8  D  2  7
+//                                   |
+//                                   5
+//
+// I've labeled our normal flow descendants A, B, C, and D, our stacking
+// container descendants with their z indices, and us with 'this' (we're a
+// stacking container and our zIndex doesn't matter here). These nodes appear in
+// three lists: posZOrder, negZOrder, and normal flow (keep in mind that normal
+// flow layers don't overlap). So if we arrange these lists in order we get our
+// stacking order:
+//
+//                     [-8], [A-D], [0, 2, 5, 7]--> pos z-order.
+//                       |     |
+//        Neg z-order. <-+     +--> Normal flow descendants.
+//
+// We can then assign new, 'stacking' order indices to these elements as follows:
+//
+//                     [-8], [A-D], [0, 2, 5, 7]
+// 'Stacking' indices:  -1     0     1  2  3  4
+//
+// Note that the normal flow descendants can share an index because they don't
+// stack/overlap. Now our problem becomes very simple: a layer can safely become
+// a stacking container if the stacking-order indices of it and its descendants
+// appear in a contiguous block in the list of stacking indices. This problem
+// can be solved very efficiently by calculating the min/max stacking indices in
+// the subtree, and the number stacking container descendants. Once we have this
+// information, we know that the subtree's indices form a contiguous block if:
+//
+//           maxStackIndex - minStackIndex == numSCDescendants
+//
+// So for node A in the example above we would have:
+//   maxStackIndex = 1
+//   minStackIndex = -1
+//   numSCDecendants = 2
+//
+// and so,
+//       maxStackIndex - minStackIndex == numSCDescendants
+//  ===>                      1 - (-1) == 2
+//  ===>                             2 == 2
+//
+//  Since this is true, A can safely become a stacking container.
+//  Now, for node C we have:
+//
+//   maxStackIndex = 4
+//   minStackIndex = 0 <-- because C has stacking index 0.
+//   numSCDecendants = 2
+//
+// and so,
+//       maxStackIndex - minStackIndex == numSCDescendants
+//  ===>                         4 - 0 == 2
+//  ===>                             4 == 2
+//
+// Since this is false, C cannot be safely promoted to a stacking container. This
+// happened because of the elements with z-index 5 and 0. Now if 5 had been a
+// child of C rather than D, and A had no child with Z index 0, we would have had:
+//
+//   maxStackIndex = 3
+//   minStackIndex = 0 <-- because C has stacking index 0.
+//   numSCDecendants = 3
+//
+// and so,
+//       maxStackIndex - minStackIndex == numSCDescendants
+//  ===>                         3 - 0 == 3
+//  ===>                             3 == 3
+//
+//  And we would conclude that C could be promoted.
+void RenderLayer::updateDescendantsAreContiguousInStackingOrder()
+{
+    if (!m_descendantsAreContiguousInStackingOrderDirty || !isStackingContext() || !acceleratedCompositingForOverflowScrollEnabled())
+        return;
+
+    ASSERT(!m_normalFlowListDirty);
+    ASSERT(!m_zOrderListsDirty);
+
+    OwnPtr<Vector<RenderLayer*> > posZOrderList;
+    OwnPtr<Vector<RenderLayer*> > negZOrderList;
+    rebuildZOrderLists(StopAtStackingContexts, posZOrderList, negZOrderList);
+
+    // Create a reverse lookup.
+    HashMap<const RenderLayer*, int> lookup;
+
+    if (negZOrderList) {
+        int stackingOrderIndex = -1;
+        size_t listSize = negZOrderList->size();
+        for (size_t i = 0; i < listSize; ++i) {
+            RenderLayer* currentLayer = negZOrderList->at(listSize - i - 1);
+            if (!currentLayer->isStackingContext())
+                continue;
+            lookup.set(currentLayer, stackingOrderIndex--);
+        }
+    }
+
+    if (posZOrderList) {
+        size_t listSize = posZOrderList->size();
+        int stackingOrderIndex = 1;
+        for (size_t i = 0; i < listSize; ++i) {
+            RenderLayer* currentLayer = posZOrderList->at(i);
+            if (!currentLayer->isStackingContext())
+                continue;
+            lookup.set(currentLayer, stackingOrderIndex++);
+        }
+    }
+
+    int minIndex = 0;
+    int maxIndex = 0;
+    int count = 0;
+    bool firstIteration = true;
+    updateDescendantsAreContiguousInStackingOrderRecursive(lookup, minIndex, maxIndex, count, firstIteration);
+
+    m_descendantsAreContiguousInStackingOrderDirty = false;
+}
+
+void RenderLayer::updateDescendantsAreContiguousInStackingOrderRecursive(const HashMap<const RenderLayer*, int>& lookup, int& minIndex, int& maxIndex, int& count, bool firstIteration)
+{
+    if (isStackingContext() && !firstIteration) {
+        if (lookup.contains(this)) {
+            minIndex = std::min(minIndex, lookup.get(this));
+            maxIndex = std::max(maxIndex, lookup.get(this));
+            count++;
+        }
+        return;
+    }
+
+    for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
+        int childMinIndex = 0;
+        int childMaxIndex = 0;
+        int childCount = 0;
+        child->updateDescendantsAreContiguousInStackingOrderRecursive(lookup, childMinIndex, childMaxIndex, childCount, false);
+        if (childCount) {
+            count += childCount;
+            minIndex = std::min(minIndex, childMinIndex);
+            maxIndex = std::max(maxIndex, childMaxIndex);
+        }
+    }
+
+    if (!isStackingContext()) {
+        bool newValue = maxIndex - minIndex == count;
+        bool didUpdate = newValue != m_descendantsAreContiguousInStackingOrder;
+        m_descendantsAreContiguousInStackingOrder = newValue;
+        if (didUpdate)
+            updateNeedsCompositedScrolling();
+    }
+}
+
+static inline bool isPositionedContainer(const RenderLayer* layer)
+{
+    // FIXME: This is not in sync with containingBlock.
+    // RenderObject::canContainFixedPositionedObject() should probably be used
+    // instead.
+    RenderLayerModelObject* layerRenderer = layer->renderer();
+    return layer->isRootLayer() || layerRenderer->isPositioned() || layer->hasTransform();
+}
+
+void RenderLayer::collectBeforePromotionZOrderList(RenderLayer* ancestorStackingContext, OwnPtr<Vector<RenderLayer*> >& posZOrderListBeforePromote, OwnPtr<Vector<RenderLayer*> >& negZOrderListBeforePromote)
+{
+    // FIXME: TemporaryChange should support bit fields.
+    bool oldNeedsCompositedScrolling = m_needsCompositedScrolling;
+    bool oldIsNormalFlowOnly = m_isNormalFlowOnly;
+
+    m_needsCompositedScrolling = false;
+    m_isNormalFlowOnly = shouldBeNormalFlowOnly();
+
+    ancestorStackingContext->rebuildZOrderLists(StopAtStackingContexts, posZOrderListBeforePromote, negZOrderListBeforePromote, 0);
+
+    m_needsCompositedScrolling = oldNeedsCompositedScrolling;
+    m_isNormalFlowOnly = oldIsNormalFlowOnly;
+
+    const RenderLayer* positionedAncestor = parent();
+    while (positionedAncestor && !isPositionedContainer(positionedAncestor) && !positionedAncestor->isStackingContext())
+        positionedAncestor = positionedAncestor->parent();
+    if (positionedAncestor && (!isPositionedContainer(positionedAncestor) || positionedAncestor->isStackingContext()))
+        positionedAncestor = 0;
+
+    if (!posZOrderListBeforePromote)
+        posZOrderListBeforePromote = adoptPtr(new Vector<RenderLayer*>());
+    else if (posZOrderListBeforePromote->find(this) != notFound)
+        return;
+
+    // The current layer will appear in the z-order lists after promotion, so
+    // for a meaningful comparison, we must insert it in the z-order lists
+    // before promotion if it does not appear there already.
+    if (!positionedAncestor) {
+        posZOrderListBeforePromote->prepend(this);
+        return;
+    }
+
+    for (size_t index = 0; index < posZOrderListBeforePromote->size(); index++) {
+        if (posZOrderListBeforePromote->at(index) == positionedAncestor) {
+            posZOrderListBeforePromote->insert(index + 1, this);
+            return;
+        }
+    }
+}
+
+void RenderLayer::collectAfterPromotionZOrderList(RenderLayer* ancestorStackingContext, OwnPtr<Vector<RenderLayer*> >& posZOrderListAfterPromote, OwnPtr<Vector<RenderLayer*> >& negZOrderListAfterPromote)
+{
+    // FIXME: TemporaryChange should support bit fields.
+    bool oldNeedsCompositedScrolling = m_needsCompositedScrolling;
+    bool oldIsNormalFlowOnly = m_isNormalFlowOnly;
+
+    m_isNormalFlowOnly = false;
+    m_needsCompositedScrolling = true;
+
+    ancestorStackingContext->rebuildZOrderLists(StopAtStackingContexts, posZOrderListAfterPromote, negZOrderListAfterPromote, this);
+
+    m_needsCompositedScrolling = oldNeedsCompositedScrolling;
+    m_isNormalFlowOnly = oldIsNormalFlowOnly;
+}
+
+// Compute what positive and negative z-order lists would look like before and
+// after promotion, so we can later ensure that proper stacking order is
+// preserved between the two sets of lists.
+//
+// A few examples:
+// c = currentLayer
+// - = negative z-order child of currentLayer
+// + = positive z-order child of currentLayer
+// a = positioned ancestor of currentLayer
+// x = any other RenderLayer in the list
+//
+// (a) xxxxx-----++a+++x
+// (b) xxx-----c++++++xx
+//
+// Normally the current layer would be painted in the normal flow list if it
+// doesn't already appear in the positive z-order list. However, in the case
+// that the layer has a positioned ancestor, it will paint directly after the
+// positioned ancestor. In example (a), the current layer would be painted in
+// the middle of its own positive z-order children, so promoting would cause a
+// change in paint order (since a promoted layer will paint all of its positive
+// z-order children strictly after it paints itself).
+//
+// In example (b), it is ok to promote the current layer only if it does not
+// have a background. If it has a background, the background gets painted before
+// the layer's negative z-order children, so again, a promotion would cause a
+// change in paint order (causing the background to get painted after the
+// negative z-order children instead of before).
+//
+void RenderLayer::computePaintOrderList(PaintOrderListType type, Vector<RefPtr<Node> >& list)
+{
+    OwnPtr<Vector<RenderLayer*> > posZOrderList;
+    OwnPtr<Vector<RenderLayer*> > negZOrderList;
+
+    RenderLayer* stackingContext = ancestorStackingContext();
+
+    if (!stackingContext)
+        return;
+
+    switch (type) {
+    case BeforePromote:
+        collectBeforePromotionZOrderList(stackingContext, posZOrderList, negZOrderList);
+        break;
+    case AfterPromote:
+        collectAfterPromotionZOrderList(stackingContext, posZOrderList, negZOrderList);
+        break;
+    }
+
+    if (negZOrderList) {
+        for (size_t index = 0; index < negZOrderList->size(); ++index)
+            list.append(negZOrderList->at(index)->renderer()->node());
+    }
+
+    if (posZOrderList) {
+        for (size_t index = 0; index < posZOrderList->size(); ++index)
+            list.append(posZOrderList->at(index)->renderer()->node());
+    }
+}
+
+void RenderLayer::computeRepaintRects(const RenderLayerModelObject* repaintContainer, const RenderGeometryMap* geometryMap)
+{
+    ASSERT(!m_visibleContentStatusDirty);
+
+    m_repaintRect = renderer()->clippedOverflowRectForRepaint(repaintContainer);
+    m_outlineBox = renderer()->outlineBoundsForRepaint(repaintContainer, geometryMap);
+}
+
+
+void RenderLayer::computeRepaintRectsIncludingDescendants()
+{
+    // FIXME: computeRepaintRects() has to walk up the parent chain for every layer to compute the rects.
+    // We should make this more efficient.
+    // FIXME: it's wrong to call this when layout is not up-to-date, which we do.
+    computeRepaintRects(renderer()->containerForRepaint());
+
+    for (RenderLayer* layer = firstChild(); layer; layer = layer->nextSibling())
+        layer->computeRepaintRectsIncludingDescendants();
+}
+
+void RenderLayer::clearRepaintRects()
+{
+    ASSERT(!m_hasVisibleContent);
+    ASSERT(!m_visibleContentStatusDirty);
+
+    m_repaintRect = IntRect();
+    m_outlineBox = IntRect();
+}
+
+void RenderLayer::updateLayerPositionsAfterDocumentScroll()
+{
+    ASSERT(this == renderer()->view()->layer());
+
+    RenderGeometryMap geometryMap(UseTransforms);
+    updateLayerPositionsAfterScroll(&geometryMap);
+}
+
+void RenderLayer::updateLayerPositionsAfterOverflowScroll()
+{
+    RenderGeometryMap geometryMap(UseTransforms);
+    RenderView* view = renderer()->view();
+    if (this != view->layer())
+        geometryMap.pushMappingsToAncestor(parent(), 0);
+
+    // FIXME: why is it OK to not check the ancestors of this layer in order to
+    // initialize the HasSeenViewportConstrainedAncestor and HasSeenAncestorWithOverflowClip flags?
+    updateLayerPositionsAfterScroll(&geometryMap, IsOverflowScroll);
+}
+
+void RenderLayer::updateLayerPositionsAfterScroll(RenderGeometryMap* geometryMap, UpdateLayerPositionsAfterScrollFlags flags)
+{
+    // FIXME: This shouldn't be needed, but there are some corner cases where
+    // these flags are still dirty. Update so that the check below is valid.
+    updateDescendantDependentFlags();
+
+    // If we have no visible content and no visible descendants, there is no point recomputing
+    // our rectangles as they will be empty. If our visibility changes, we are expected to
+    // recompute all our positions anyway.
+    if (!m_hasVisibleDescendant && !m_hasVisibleContent)
+        return;
+
+    bool positionChanged = updateLayerPosition();
+    if (positionChanged)
+        flags |= HasChangedAncestor;
+
+    if (geometryMap)
+        geometryMap->pushMappingsToAncestor(this, parent());
+
+    if (flags & HasChangedAncestor || flags & HasSeenViewportConstrainedAncestor || flags & IsOverflowScroll)
+        clearClipRects();
+
+    if (renderer()->style()->hasViewportConstrainedPosition())
+        flags |= HasSeenViewportConstrainedAncestor;
+
+    if (renderer()->hasOverflowClip())
+        flags |= HasSeenAncestorWithOverflowClip;
+
+    if (flags & HasSeenViewportConstrainedAncestor
+        || (flags & IsOverflowScroll && flags & HasSeenAncestorWithOverflowClip && !m_canSkipRepaintRectsUpdateOnScroll)) {
+        // FIXME: We could track the repaint container as we walk down the tree.
+        computeRepaintRects(renderer()->containerForRepaint(), geometryMap);
+    } else {
+        // Check that our cached rects are correct.
+        // FIXME: re-enable these assertions when the issue with table cells is resolved: https://bugs.webkit.org/show_bug.cgi?id=103432
+        // ASSERT(m_repaintRect == renderer()->clippedOverflowRectForRepaint(renderer()->containerForRepaint()));
+        // ASSERT(m_outlineBox == renderer()->outlineBoundsForRepaint(renderer()->containerForRepaint(), geometryMap));
+    }
+    
+    for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
+        child->updateLayerPositionsAfterScroll(geometryMap, flags);
+
+    // We don't update our reflection as scrolling is a translation which does not change the size()
+    // of an object, thus RenderReplica will still repaint itself properly as the layer position was
+    // updated above.
+
+    if (m_marquee) {
+        bool oldUpdatingMarqueePosition = m_updatingMarqueePosition;
+        m_updatingMarqueePosition = true;
+        m_marquee->updateMarqueePosition();
+        m_updatingMarqueePosition = oldUpdatingMarqueePosition;
+    }
+
+    if (geometryMap)
+        geometryMap->popMappingsToAncestor(parent());
+}
+
+void RenderLayer::positionNewlyCreatedOverflowControls()
+{
+    if (!backing()->hasUnpositionedOverflowControlsLayers())
+        return;
+
+    RenderGeometryMap geometryMap(UseTransforms);
+    RenderView* view = renderer()->view();
+    if (this != view->layer() && parent())
+        geometryMap.pushMappingsToAncestor(parent(), 0);
+
+    LayoutPoint offsetFromRoot = LayoutPoint(geometryMap.absolutePoint(FloatPoint()));
+    positionOverflowControls(toIntSize(roundedIntPoint(offsetFromRoot)));
+}
+
+#if ENABLE(CSS_COMPOSITING)
+void RenderLayer::updateBlendMode()
+{
+    BlendMode newBlendMode = renderer()->style()->blendMode();
+    if (newBlendMode != m_blendMode) {
+        m_blendMode = newBlendMode;
+        if (backing())
+            backing()->setBlendMode(newBlendMode);
+    }
+}
+#endif
+
+void RenderLayer::updateTransform()
+{
+    // hasTransform() on the renderer is also true when there is transform-style: preserve-3d or perspective set,
+    // so check style too.
+    bool hasTransform = renderer()->hasTransform() && renderer()->style()->hasTransform();
+    bool had3DTransform = has3DTransform();
+
+    bool hadTransform = m_transform;
+    if (hasTransform != hadTransform) {
+        if (hasTransform)
+            m_transform = adoptPtr(new TransformationMatrix);
+        else
+            m_transform.clear();
+        
+        // Layers with transforms act as clip rects roots, so clear the cached clip rects here.
+        clearClipRectsIncludingDescendants();
+    }
+    
+    if (hasTransform) {
+        RenderBox* box = renderBox();
+        ASSERT(box);
+        m_transform->makeIdentity();
+        box->style()->applyTransform(*m_transform, box->pixelSnappedBorderBoxRect().size(), RenderStyle::IncludeTransformOrigin);
+        makeMatrixRenderable(*m_transform, canRender3DTransforms());
+    }
+
+    if (had3DTransform != has3DTransform())
+        dirty3DTransformedDescendantStatus();
+}
+
+TransformationMatrix RenderLayer::currentTransform(RenderStyle::ApplyTransformOrigin applyOrigin) const
+{
+    if (!m_transform)
+        return TransformationMatrix();
+
+    if (renderer()->style()->isRunningAcceleratedAnimation()) {
+        TransformationMatrix currTransform;
+        RefPtr<RenderStyle> style = renderer()->animation()->getAnimatedStyleForRenderer(renderer());
+        style->applyTransform(currTransform, renderBox()->pixelSnappedBorderBoxRect().size(), applyOrigin);
+        makeMatrixRenderable(currTransform, canRender3DTransforms());
+        return currTransform;
+    }
+
+    // m_transform includes transform-origin, so we need to recompute the transform here.
+    if (applyOrigin == RenderStyle::ExcludeTransformOrigin) {
+        RenderBox* box = renderBox();
+        TransformationMatrix currTransform;
+        box->style()->applyTransform(currTransform, box->pixelSnappedBorderBoxRect().size(), RenderStyle::ExcludeTransformOrigin);
+        makeMatrixRenderable(currTransform, canRender3DTransforms());
+        return currTransform;
+    }
+
+    return *m_transform;
+}
+
+TransformationMatrix RenderLayer::renderableTransform(PaintBehavior paintBehavior) const
+{
+    if (!m_transform)
+        return TransformationMatrix();
+    
+    if (paintBehavior & PaintBehaviorFlattenCompositingLayers) {
+        TransformationMatrix matrix = *m_transform;
+        makeMatrixRenderable(matrix, false /* flatten 3d */);
+        return matrix;
+    }
+
+    return *m_transform;
+}
+
+static bool checkContainingBlockChainForPagination(RenderLayerModelObject* renderer, RenderBox* ancestorColumnsRenderer)
+{
+    RenderView* view = renderer->view();
+    RenderLayerModelObject* prevBlock = renderer;
+    RenderBlock* containingBlock;
+    for (containingBlock = renderer->containingBlock();
+         containingBlock && containingBlock != view && containingBlock != ancestorColumnsRenderer;
+         containingBlock = containingBlock->containingBlock())
+        prevBlock = containingBlock;
+    
+    // If the columns block wasn't in our containing block chain, then we aren't paginated by it.
+    if (containingBlock != ancestorColumnsRenderer)
+        return false;
+        
+    // If the previous block is absolutely positioned, then we can't be paginated by the columns block.
+    if (prevBlock->isOutOfFlowPositioned())
+        return false;
+        
+    // Otherwise we are paginated by the columns block.
+    return true;
+}
+
+bool RenderLayer::useRegionBasedColumns() const
+{
+    const Settings* settings = renderer()->document()->settings();
+    return settings && settings->regionBasedColumnsEnabled();
+}
+
+void RenderLayer::updatePagination()
+{
+    m_isPaginated = false;
+    m_enclosingPaginationLayer = 0;
+
+    if (isComposited() || !parent())
+        return; // FIXME: We will have to deal with paginated compositing layers someday.
+                // FIXME: For now the RenderView can't be paginated.  Eventually printing will move to a model where it is though.
+
+    // The main difference between the paginated booleans for the old column code and the new column code
+    // is that each paginated layer has to paint on its own with the new code. There is no
+    // recurring into child layers. This means that the m_isPaginated bits for the new column code can't just be set on
+    // "roots" that get split and paint all their descendants. Instead each layer has to be checked individually and
+    // genuinely know if it is going to have to split itself up when painting only its contents (and not any other descendant
+    // layers). We track an enclosingPaginationLayer instead of using a simple bit, since we want to be able to get back
+    // to that layer easily.
+    bool regionBasedColumnsUsed = useRegionBasedColumns();
+    if (regionBasedColumnsUsed && renderer()->isInFlowRenderFlowThread()) {
+        m_enclosingPaginationLayer = this;
+        return;
+    }
+
+    if (isNormalFlowOnly()) {
+        if (regionBasedColumnsUsed) {
+            // Content inside a transform is not considered to be paginated, since we simply
+            // paint the transform multiple times in each column, so we don't have to use
+            // fragments for the transformed content.
+            m_enclosingPaginationLayer = parent()->enclosingPaginationLayer();
+            if (m_enclosingPaginationLayer && m_enclosingPaginationLayer->hasTransform())
+                m_enclosingPaginationLayer = 0;
+        } else
+            m_isPaginated = parent()->renderer()->hasColumns();
+        return;
+    }
+
+    // For the new columns code, we want to walk up our containing block chain looking for an enclosing layer. Once
+    // we find one, then we just check its pagination status.
+    if (regionBasedColumnsUsed) {
+        RenderView* view = renderer()->view();
+        RenderBlock* containingBlock;
+        for (containingBlock = renderer()->containingBlock();
+             containingBlock && containingBlock != view;
+             containingBlock = containingBlock->containingBlock()) {
+            if (containingBlock->hasLayer()) {
+                // Content inside a transform is not considered to be paginated, since we simply
+                // paint the transform multiple times in each column, so we don't have to use
+                // fragments for the transformed content.
+                m_enclosingPaginationLayer = containingBlock->layer()->enclosingPaginationLayer();
+                if (m_enclosingPaginationLayer && m_enclosingPaginationLayer->hasTransform())
+                    m_enclosingPaginationLayer = 0;
+                return;
+            }
+        }
+        return;
+    }
+
+    // If we're not normal flow, then we need to look for a multi-column object between us and our stacking container.
+    RenderLayer* ancestorStackingContainer = this->ancestorStackingContainer();
+    for (RenderLayer* curr = parent(); curr; curr = curr->parent()) {
+        if (curr->renderer()->hasColumns()) {
+            m_isPaginated = checkContainingBlockChainForPagination(renderer(), curr->renderBox());
+            return;
+        }
+        if (curr == ancestorStackingContainer)
+            return;
+    }
+}
+
+bool RenderLayer::canBeStackingContainer() const
+{
+    if (isStackingContext() || !ancestorStackingContainer())
+        return true;
+
+    return m_descendantsAreContiguousInStackingOrder;
+}
+
+void RenderLayer::setHasVisibleContent()
+{ 
+    if (m_hasVisibleContent && !m_visibleContentStatusDirty) {
+        ASSERT(!parent() || parent()->hasVisibleDescendant());
+        return;
+    }
+
+    m_visibleContentStatusDirty = false; 
+    m_hasVisibleContent = true;
+    computeRepaintRects(renderer()->containerForRepaint());
+    if (!isNormalFlowOnly()) {
+        // We don't collect invisible layers in z-order lists if we are not in compositing mode.
+        // As we became visible, we need to dirty our stacking containers ancestors to be properly
+        // collected. FIXME: When compositing, we could skip this dirtying phase.
+        for (RenderLayer* sc = ancestorStackingContainer(); sc; sc = sc->ancestorStackingContainer()) {
+            sc->dirtyZOrderLists();
+            if (sc->hasVisibleContent())
+                break;
+        }
+    }
+
+    if (parent())
+        parent()->setAncestorChainHasVisibleDescendant();
+}
+
+void RenderLayer::dirtyVisibleContentStatus() 
+{ 
+    m_visibleContentStatusDirty = true; 
+    if (parent())
+        parent()->dirtyAncestorChainVisibleDescendantStatus();
+}
+
+void RenderLayer::dirtyAncestorChainVisibleDescendantStatus()
+{
+    for (RenderLayer* layer = this; layer; layer = layer->parent()) {
+        if (layer->m_visibleDescendantStatusDirty)
+            break;
+
+        layer->m_visibleDescendantStatusDirty = true;
+    }
+}
+
+void RenderLayer::setAncestorChainHasVisibleDescendant()
+{
+    for (RenderLayer* layer = this; layer; layer = layer->parent()) {
+        if (!layer->m_visibleDescendantStatusDirty && layer->hasVisibleDescendant())
+            break;
+
+        layer->m_hasVisibleDescendant = true;
+        layer->m_visibleDescendantStatusDirty = false;
+    }
+}
+
+void RenderLayer::updateDescendantDependentFlags(HashSet<const RenderObject*>* outOfFlowDescendantContainingBlocks)
+{
+    if (m_visibleDescendantStatusDirty || m_hasSelfPaintingLayerDescendantDirty || m_hasOutOfFlowPositionedDescendantDirty) {
+        const bool hadVisibleDescendant = m_hasVisibleDescendant;
+        const bool hadOutOfFlowPositionedDescendant = m_hasOutOfFlowPositionedDescendant;
+
+        m_hasVisibleDescendant = false;
+        m_hasSelfPaintingLayerDescendant = false;
+        m_hasOutOfFlowPositionedDescendant = false;
+
+        HashSet<const RenderObject*> childOutOfFlowDescendantContainingBlocks;
+        for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
+            childOutOfFlowDescendantContainingBlocks.clear();
+            child->updateDescendantDependentFlags(&childOutOfFlowDescendantContainingBlocks);
+
+            bool childIsOutOfFlowPositioned = child->renderer() && child->renderer()->isOutOfFlowPositioned();
+            if (childIsOutOfFlowPositioned)
+                childOutOfFlowDescendantContainingBlocks.add(child->renderer()->containingBlock());
+
+            if (outOfFlowDescendantContainingBlocks) {
+                HashSet<const RenderObject*>::const_iterator it = childOutOfFlowDescendantContainingBlocks.begin();
+                for (; it != childOutOfFlowDescendantContainingBlocks.end(); ++it)
+                    outOfFlowDescendantContainingBlocks->add(*it);
+            }
+
+            bool hasVisibleDescendant = child->m_hasVisibleContent || child->m_hasVisibleDescendant;
+            bool hasSelfPaintingLayerDescendant = child->isSelfPaintingLayer() || child->hasSelfPaintingLayerDescendant();
+            bool hasOutOfFlowPositionedDescendant = hasVisibleDescendant && (!childOutOfFlowDescendantContainingBlocks.isEmpty() || child->hasOutOfFlowPositionedDescendant());
+
+            m_hasVisibleDescendant |= hasVisibleDescendant;
+            m_hasSelfPaintingLayerDescendant |= hasSelfPaintingLayerDescendant;
+            m_hasOutOfFlowPositionedDescendant |= hasOutOfFlowPositionedDescendant;
+
+            if (m_hasVisibleDescendant && m_hasSelfPaintingLayerDescendant && m_hasOutOfFlowPositionedDescendant)
+                break;
+        }
+
+        if (outOfFlowDescendantContainingBlocks && renderer())
+            outOfFlowDescendantContainingBlocks->remove(renderer());
+
+        m_visibleDescendantStatusDirty = false;
+        m_hasSelfPaintingLayerDescendantDirty = false;
+        m_hasOutOfFlowPositionedDescendantDirty = false;
+
+        if (m_hasVisibleDescendant != hadVisibleDescendant || m_hasOutOfFlowPositionedDescendant != hadOutOfFlowPositionedDescendant)
+            updateNeedsCompositedScrolling();
+    }
+
+    if (m_visibleContentStatusDirty) {
+        const bool hadVisibleContent = m_hasVisibleContent;
+        if (renderer()->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 = renderer()->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 == renderer())
+                            r = 0;
+                    } while (r && !r->nextSibling());
+                    if (r)
+                        r = r->nextSibling();
+                }
+            }
+        }    
+        m_visibleContentStatusDirty = false; 
+        if (hadVisibleContent != m_hasVisibleContent)
+            updateNeedsCompositedScrolling();
+    }
+}
+
+void RenderLayer::dirty3DTransformedDescendantStatus()
+{
+    RenderLayer* curr = ancestorStackingContainer();
+    if (curr)
+        curr->m_3DTransformedDescendantStatusDirty = true;
+        
+    // This propagates up through preserve-3d hierarchies to the enclosing flattening layer.
+    // Note that preserves3D() creates stacking context, so we can just run up the stacking containers.
+    while (curr && curr->preserves3D()) {
+        curr->m_3DTransformedDescendantStatusDirty = true;
+        curr = curr->ancestorStackingContainer();
+    }
+}
+
+// Return true if this layer or any preserve-3d descendants have 3d.
+bool RenderLayer::update3DTransformedDescendantStatus()
+{
+    if (m_3DTransformedDescendantStatusDirty) {
+        m_has3DTransformedDescendant = false;
+
+        updateZOrderLists();
+
+        // Transformed or preserve-3d descendants can only be in the z-order lists, not
+        // in the normal flow list, so we only need to check those.
+        if (Vector<RenderLayer*>* positiveZOrderList = posZOrderList()) {
+            for (unsigned i = 0; i < positiveZOrderList->size(); ++i)
+                m_has3DTransformedDescendant |= positiveZOrderList->at(i)->update3DTransformedDescendantStatus();
+        }
+
+        // Now check our negative z-index children.
+        if (Vector<RenderLayer*>* negativeZOrderList = negZOrderList()) {
+            for (unsigned i = 0; i < negativeZOrderList->size(); ++i)
+                m_has3DTransformedDescendant |= negativeZOrderList->at(i)->update3DTransformedDescendantStatus();
+        }
+        
+        m_3DTransformedDescendantStatusDirty = false;
+    }
+    
+    // If we live in a 3d hierarchy, then the layer at the root of that hierarchy needs
+    // the m_has3DTransformedDescendant set.
+    if (preserves3D())
+        return has3DTransform() || m_has3DTransformedDescendant;
+
+    return has3DTransform();
+}
+
+bool RenderLayer::updateLayerPosition()
+{
+    LayoutPoint localPoint;
+    LayoutSize inlineBoundingBoxOffset; // We don't put this into the RenderLayer x/y for inlines, so we need to subtract it out when done.
+    if (renderer()->isInline() && renderer()->isRenderInline()) {
+        RenderInline* inlineFlow = toRenderInline(renderer());
+        IntRect lineBox = inlineFlow->linesBoundingBox();
+        setSize(lineBox.size());
+        inlineBoundingBoxOffset = toSize(lineBox.location());
+        localPoint += inlineBoundingBoxOffset;
+    } else if (RenderBox* box = renderBox()) {
+        // FIXME: Is snapping the size really needed here for the RenderBox case?
+        setSize(pixelSnappedIntSize(box->size(), box->location()));
+        localPoint += box->topLeftLocationOffset();
+    }
+
+    if (!renderer()->isOutOfFlowPositioned() && renderer()->parent()) {
+        // We must adjust our position by walking up the render tree looking for the
+        // nearest enclosing object with a layer.
+        RenderObject* curr = renderer()->parent();
+        while (curr && !curr->hasLayer()) {
+            if (curr->isBox() && !curr->isTableRow()) {
+                // Rows and cells share the same coordinate space (that of the section).
+                // Omit them when computing our xpos/ypos.
+                localPoint += toRenderBox(curr)->topLeftLocationOffset();
+            }
+            curr = curr->parent();
+        }
+        if (curr->isBox() && curr->isTableRow()) {
+            // Put ourselves into the row coordinate space.
+            localPoint -= toRenderBox(curr)->topLeftLocationOffset();
+        }
+    }
+    
+    // Subtract our parent's scroll offset.
+    if (renderer()->isOutOfFlowPositioned() && enclosingPositionedAncestor()) {
+        RenderLayer* positionedParent = enclosingPositionedAncestor();
+
+        // For positioned layers, we subtract out the enclosing positioned layer's scroll offset.
+        if (positionedParent->renderer()->hasOverflowClip()) {
+            LayoutSize offset = positionedParent->scrolledContentOffset();
+            localPoint -= offset;
+        }
+        
+        if (renderer()->isOutOfFlowPositioned() && positionedParent->renderer()->isInFlowPositioned() && positionedParent->renderer()->isRenderInline()) {
+            LayoutSize offset = toRenderInline(positionedParent->renderer())->offsetForInFlowPositionedInline(toRenderBox(renderer()));
+            localPoint += offset;
+        }
+    } else if (parent()) {
+        if (isComposited()) {
+            // FIXME: Composited layers ignore pagination, so about the best we can do is make sure they're offset into the appropriate column.
+            // They won't split across columns properly.
+            LayoutSize columnOffset;
+            if (!parent()->renderer()->hasColumns() && parent()->renderer()->isRoot() && renderer()->view()->hasColumns())
+                renderer()->view()->adjustForColumns(columnOffset, localPoint);
+            else
+                parent()->renderer()->adjustForColumns(columnOffset, localPoint);
+
+            localPoint += columnOffset;
+        }
+
+        if (parent()->renderer()->hasOverflowClip()) {
+            IntSize scrollOffset = parent()->scrolledContentOffset();
+            localPoint -= scrollOffset;
+        }
+    }
+    
+    bool positionOrOffsetChanged = false;
+    if (renderer()->hasPaintOffset()) {
+        LayoutSize newOffset = toRenderBoxModelObject(renderer())->paintOffset();
+        positionOrOffsetChanged = newOffset != m_paintOffset;
+        m_paintOffset = newOffset;
+        localPoint.move(m_paintOffset);
+    } else {
+        m_paintOffset = LayoutSize();
+    }
+
+    // FIXME: We'd really like to just get rid of the concept of a layer rectangle and rely on the renderers.
+    localPoint -= inlineBoundingBoxOffset;
+    
+    positionOrOffsetChanged |= location() != localPoint;
+    setLocation(localPoint);
+    return positionOrOffsetChanged;
+}
+
+TransformationMatrix RenderLayer::perspectiveTransform() const
+{
+    if (!renderer()->hasTransform())
+        return TransformationMatrix();
+
+    RenderStyle* style = renderer()->style();
+    if (!style->hasPerspective())
+        return TransformationMatrix();
+
+    // Maybe fetch the perspective from the backing?
+    const IntRect borderBox = toRenderBox(renderer())->pixelSnappedBorderBoxRect();
+    const float boxWidth = borderBox.width();
+    const float boxHeight = borderBox.height();
+
+    float perspectiveOriginX = floatValueForLength(style->perspectiveOriginX(), boxWidth);
+    float perspectiveOriginY = floatValueForLength(style->perspectiveOriginY(), boxHeight);
+
+    // A perspective origin of 0,0 makes the vanishing point in the center of the element.
+    // We want it to be in the top-left, so subtract half the height and width.
+    perspectiveOriginX -= boxWidth / 2.0f;
+    perspectiveOriginY -= boxHeight / 2.0f;
+    
+    TransformationMatrix t;
+    t.translate(perspectiveOriginX, perspectiveOriginY);
+    t.applyPerspective(style->perspective());
+    t.translate(-perspectiveOriginX, -perspectiveOriginY);
+    
+    return t;
+}
+
+FloatPoint RenderLayer::perspectiveOrigin() const
+{
+    if (!renderer()->hasTransform())
+        return FloatPoint();
+
+    const LayoutRect borderBox = toRenderBox(renderer())->borderBoxRect();
+    RenderStyle* style = renderer()->style();
+
+    return FloatPoint(floatValueForLength(style->perspectiveOriginX(), borderBox.width()),
+                      floatValueForLength(style->perspectiveOriginY(), borderBox.height()));
+}
+
+RenderLayer* RenderLayer::ancestorStackingContainer() const
+{
+    RenderLayer* ancestor = parent();
+    while (ancestor && !ancestor->isStackingContainer())
+        ancestor = ancestor->parent();
+    return ancestor;
+}
+
+RenderLayer* RenderLayer::ancestorStackingContext() const
+{
+    RenderLayer* ancestor = parent();
+    while (ancestor && !ancestor->isStackingContext())
+        ancestor = ancestor->parent();
+    return ancestor;
+}
+
+static inline bool isFixedPositionedContainer(RenderLayer* layer)
+{
+    return layer->isRootLayer() || layer->hasTransform();
+}
+
+RenderLayer* RenderLayer::enclosingPositionedAncestor() const
+{
+    RenderLayer* curr = parent();
+    while (curr && !isPositionedContainer(curr))
+        curr = curr->parent();
+
+    return curr;
+}
+
+RenderLayer* RenderLayer::enclosingScrollableLayer() const
+{
+    for (RenderObject* nextRenderer = renderer()->parent(); nextRenderer; nextRenderer = nextRenderer->parent()) {
+        if (nextRenderer->isBox() && toRenderBox(nextRenderer)->canBeScrolledAndHasScrollableArea())
+            return nextRenderer->enclosingLayer();
+    }
+
+    return 0;
+}
+
+IntRect RenderLayer::scrollableAreaBoundingBox() const
+{
+    return renderer()->absoluteBoundingBoxRect();
+}
+
+RenderLayer* RenderLayer::enclosingTransformedAncestor() const
+{
+    RenderLayer* curr = parent();
+    while (curr && !curr->isRootLayer() && !curr->transform())
+        curr = curr->parent();
+
+    return curr;
+}
+
+static inline const RenderLayer* compositingContainer(const RenderLayer* layer)
+{
+    return layer->isNormalFlowOnly() ? layer->parent() : layer->ancestorStackingContainer();
+}
+
+inline bool RenderLayer::shouldRepaintAfterLayout() const
+{
+    if (m_repaintStatus == NeedsNormalRepaint)
+        return true;
+
+    // Composited layers that were moved during a positioned movement only
+    // layout, don't need to be repainted. They just need to be recomposited.
+    ASSERT(m_repaintStatus == NeedsFullRepaintForPositionedMovementLayout);
+    return !isComposited();
+}
+
+RenderLayer* RenderLayer::enclosingCompositingLayer(bool includeSelf) const
+{
+    if (includeSelf && isComposited())
+        return const_cast<RenderLayer*>(this);
+
+    for (const RenderLayer* curr = compositingContainer(this); curr; curr = compositingContainer(curr)) {
+        if (curr->isComposited())
+            return const_cast<RenderLayer*>(curr);
+    }
+         
+    return 0;
+}
+
+RenderLayer* RenderLayer::enclosingCompositingLayerForRepaint(bool includeSelf) const
+{
+    if (includeSelf && isComposited() && !backing()->paintsIntoCompositedAncestor())
+        return const_cast<RenderLayer*>(this);
+
+    for (const RenderLayer* curr = compositingContainer(this); curr; curr = compositingContainer(curr)) {
+        if (curr->isComposited() && !curr->backing()->paintsIntoCompositedAncestor())
+            return const_cast<RenderLayer*>(curr);
+    }
+         
+    return 0;
+}
+
+RenderLayer* RenderLayer::enclosingFilterLayer(bool includeSelf) const
+{
+    const RenderLayer* curr = includeSelf ? this : parent();
+    for (; curr; curr = curr->parent()) {
+        if (curr->requiresFullLayerImageForFilters())
+            return const_cast<RenderLayer*>(curr);
+    }
+    
+    return 0;
+}
+
+RenderLayer* RenderLayer::enclosingFilterRepaintLayer() const
+{
+    for (const RenderLayer* curr = this; curr; curr = curr->parent()) {
+        if ((curr != this && curr->requiresFullLayerImageForFilters()) || curr->isComposited() || curr->isRootLayer())
+            return const_cast<RenderLayer*>(curr);
+    }
+    return 0;
+}
+
+void RenderLayer::setFilterBackendNeedsRepaintingInRect(const LayoutRect& rect)
+{
+    if (rect.isEmpty())
+        return;
+    
+    LayoutRect rectForRepaint = rect;
+    renderer()->style()->filterOutsets().expandRect(rectForRepaint);
+
+    RenderLayerFilterInfo* filterInfo = this->filterInfo();
+    ASSERT(filterInfo);
+    filterInfo->expandDirtySourceRect(rectForRepaint);
+
+    ASSERT(filterInfo->renderer());
+    if (filterInfo->renderer()->hasCustomShaderFilter()) {
+        // If we have at least one custom shader, we need to update the whole bounding box of the layer, because the
+        // shader can address any ouput pixel.
+        // Note: This is only for output rect, so there's no need to expand the dirty source rect.
+        rectForRepaint.unite(calculateLayerBounds(this));
+    }
+    
+    RenderLayer* parentLayer = enclosingFilterRepaintLayer();
+    ASSERT(parentLayer);
+    FloatQuad repaintQuad(rectForRepaint);
+    LayoutRect parentLayerRect = renderer()->localToContainerQuad(repaintQuad, parentLayer->renderer()).enclosingBoundingBox();
+    
+    if (parentLayer->isComposited()) {
+        if (!parentLayer->backing()->paintsIntoWindow()) {
+            parentLayer->setBackingNeedsRepaintInRect(parentLayerRect);
+            return;
+        }
+        // If the painting goes to window, redirect the painting to the parent RenderView.
+        parentLayer = renderer()->view()->layer();
+        parentLayerRect = renderer()->localToContainerQuad(repaintQuad, parentLayer->renderer()).enclosingBoundingBox();
+    }
+
+    if (parentLayer->paintsWithFilters()) {
+        parentLayer->setFilterBackendNeedsRepaintingInRect(parentLayerRect);
+        return;        
+    }
+    
+    if (parentLayer->isRootLayer()) {
+        RenderView* view = toRenderView(parentLayer->renderer());
+        view->repaintViewRectangle(parentLayerRect);
+        return;
+    }
+    
+    ASSERT_NOT_REACHED();
+}
+
+bool RenderLayer::hasAncestorWithFilterOutsets() const
+{
+    for (const RenderLayer* curr = this; curr; curr = curr->parent()) {
+        RenderLayerModelObject* renderer = curr->renderer();
+        if (renderer->style()->hasFilterOutsets())
+            return true;
+    }
+    return false;
+}
+    
+RenderLayer* RenderLayer::clippingRootForPainting() const
+{
+    if (isComposited())
+        return const_cast<RenderLayer*>(this);
+
+    const RenderLayer* current = this;
+    while (current) {
+        if (current->isRootLayer())
+            return const_cast<RenderLayer*>(current);
+
+        current = compositingContainer(current);
+        ASSERT(current);
+        if (current->transform()
+            || (current->isComposited() && !current->backing()->paintsIntoCompositedAncestor())
+        )
+            return const_cast<RenderLayer*>(current);
+    }
+
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
+LayoutPoint RenderLayer::absoluteToContents(const LayoutPoint& absolutePoint) const
+{
+    // We don't use convertToLayerCoords because it doesn't know about transforms
+    return roundedLayoutPoint(renderer()->absoluteToLocal(absolutePoint, UseTransforms));
+}
+
+bool RenderLayer::cannotBlitToWindow() const
+{
+    if (isTransparent() || hasReflection() || hasTransform())
+        return true;
+    if (!parent())
+        return false;
+    return parent()->cannotBlitToWindow();
+}
+
+bool RenderLayer::isTransparent() const
+{
+#if ENABLE(SVG)
+    if (renderer()->node() && renderer()->node()->namespaceURI() == SVGNames::svgNamespaceURI)
+        return false;
+#endif
+    return renderer()->isTransparent() || renderer()->hasMask();
+}
+
+RenderLayer* RenderLayer::transparentPaintingAncestor()
+{
+    if (isComposited())
+        return 0;
+
+    for (RenderLayer* curr = parent(); curr; curr = curr->parent()) {
+        if (curr->isComposited())
+            return 0;
+        if (curr->isTransparent())
+            return curr;
+    }
+    return 0;
+}
+
+enum TransparencyClipBoxBehavior {
+    PaintingTransparencyClipBox,
+    HitTestingTransparencyClipBox
+};
+
+enum TransparencyClipBoxMode {
+    DescendantsOfTransparencyClipBox,
+    RootOfTransparencyClipBox
+};
+
+static LayoutRect transparencyClipBox(const RenderLayer*, const RenderLayer* rootLayer, TransparencyClipBoxBehavior, TransparencyClipBoxMode, PaintBehavior = 0);
+
+static void expandClipRectForDescendantsAndReflection(LayoutRect& clipRect, const RenderLayer* layer, const RenderLayer* rootLayer,
+    TransparencyClipBoxBehavior transparencyBehavior, PaintBehavior paintBehavior)
+{
+    // 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 (!layer->renderer()->hasMask()) {
+        // Note: we don't have to walk z-order lists since transparent elements always establish
+        // a stacking container. This means we can just walk the layer tree directly.
+        for (RenderLayer* curr = layer->firstChild(); curr; curr = curr->nextSibling()) {
+            if (!layer->reflection() || layer->reflectionLayer() != curr)
+                clipRect.unite(transparencyClipBox(curr, rootLayer, transparencyBehavior, DescendantsOfTransparencyClipBox, paintBehavior));
+        }
+    }
+
+    // If we have a reflection, then we need to account for that when we push the clip.  Reflect our entire
+    // current transparencyClipBox to catch all child layers.
+    // FIXME: Accelerated compositing will eventually want to do something smart here to avoid incorporating this
+    // size into the parent layer.
+    if (layer->renderer()->hasReflection()) {
+        LayoutPoint delta;
+        layer->convertToLayerCoords(rootLayer, delta);
+        clipRect.move(-delta.x(), -delta.y());
+        clipRect.unite(layer->renderBox()->reflectedRect(clipRect));
+        clipRect.moveBy(delta);
+    }
+}
+
+static LayoutRect transparencyClipBox(const RenderLayer* layer, const RenderLayer* rootLayer, TransparencyClipBoxBehavior transparencyBehavior,
+    TransparencyClipBoxMode transparencyMode, PaintBehavior paintBehavior)
+{
+    // 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.
+    
+    if (rootLayer != layer && ((transparencyBehavior == PaintingTransparencyClipBox && layer->paintsWithTransform(paintBehavior))
+        || (transparencyBehavior == HitTestingTransparencyClipBox && layer->hasTransform()))) {
+        // 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.
+        const RenderLayer* paginationLayer = transparencyMode == DescendantsOfTransparencyClipBox ? layer->enclosingPaginationLayer() : 0;
+        const RenderLayer* rootLayerForTransform = paginationLayer ? paginationLayer : rootLayer;
+        LayoutPoint delta;
+        layer->convertToLayerCoords(rootLayerForTransform, delta);
+
+        TransformationMatrix transform;
+        transform.translate(delta.x(), delta.y());
+        transform = transform * *layer->transform();
+
+        // We don't use fragment boxes when collecting a transformed layer's bounding box, since it always
+        // paints unfragmented.
+        LayoutRect clipRect = layer->boundingBox(layer);
+        expandClipRectForDescendantsAndReflection(clipRect, layer, layer, transparencyBehavior, paintBehavior);
+        layer->renderer()->style()->filterOutsets().expandRect(clipRect);
+        LayoutRect result = transform.mapRect(clipRect);
+        if (!paginationLayer)
+            return result;
+        
+        // We have to break up the transformed extent across our columns.
+        // Split our box up into the actual fragment boxes that render in the columns/pages and unite those together to
+        // get our true bounding box.
+        RenderFlowThread* enclosingFlowThread = toRenderFlowThread(paginationLayer->renderer());
+        result = enclosingFlowThread->fragmentsBoundingBox(result);
+        
+        LayoutPoint rootLayerDelta;
+        paginationLayer->convertToLayerCoords(rootLayer, rootLayerDelta);
+        result.moveBy(rootLayerDelta);
+        return result;
+    }
+    
+    LayoutRect clipRect = layer->boundingBox(rootLayer, RenderLayer::UseFragmentBoxes);
+    expandClipRectForDescendantsAndReflection(clipRect, layer, rootLayer, transparencyBehavior, paintBehavior);
+    layer->renderer()->style()->filterOutsets().expandRect(clipRect);
+    return clipRect;
+}
+
+LayoutRect RenderLayer::paintingExtent(const RenderLayer* rootLayer, const LayoutRect& paintDirtyRect, PaintBehavior paintBehavior)
+{
+    return intersection(transparencyClipBox(this, rootLayer, PaintingTransparencyClipBox, RootOfTransparencyClipBox, paintBehavior), paintDirtyRect);
+}
+
+void RenderLayer::beginTransparencyLayers(GraphicsContext* context, const RenderLayer* rootLayer, const LayoutRect& paintDirtyRect, PaintBehavior paintBehavior)
+{
+    if (context->paintingDisabled() || (paintsWithTransparency(paintBehavior) && m_usedTransparency))
+        return;
+    
+    RenderLayer* ancestor = transparentPaintingAncestor();
+    if (ancestor)
+        ancestor->beginTransparencyLayers(context, rootLayer, paintDirtyRect, paintBehavior);
+    
+    if (paintsWithTransparency(paintBehavior)) {
+        m_usedTransparency = true;
+        context->save();
+        LayoutRect clipRect = paintingExtent(rootLayer, paintDirtyRect, paintBehavior);
+        context->clip(clipRect);
+        context->beginTransparencyLayer(renderer()->opacity());
+#ifdef REVEAL_TRANSPARENCY_LAYERS
+        context->setFillColor(Color(0.0f, 0.0f, 0.5f, 0.2f), ColorSpaceDeviceRGB);
+        context->fillRect(clipRect);
+#endif
+    }
+}
+
+void* RenderLayer::operator new(size_t sz, RenderArena* renderArena)
+{
+    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);
+        ASSERT(prevSibling != child);
+    } else
+        setFirstChild(child);
+
+    if (beforeChild) {
+        beforeChild->setPreviousSibling(child);
+        child->setNextSibling(beforeChild);
+        ASSERT(beforeChild != child);
+    } else
+        setLastChild(child);
+
+    child->setParent(this);
+
+    if (child->isNormalFlowOnly())
+        dirtyNormalFlowList();
+
+    if (!child->isNormalFlowOnly() || child->firstChild()) {
+        // Dirty the z-order list in which we are contained. The ancestorStackingContainer() 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->dirtyStackingContainerZOrderLists();
+
+        // Adding an out of flow positioned descendant can only affect
+        // the opt-in decision for layers beneath and including our
+        // containing block.
+        RenderObject* containingBlock = child->renderer()->containingBlock();
+        for (RenderLayer* layer = child; layer; layer = layer->parent()) {
+            layer->updateNeedsCompositedScrolling();
+            if (layer->renderer() == containingBlock)
+                break;
+        }
+    }
+
+    child->updateDescendantDependentFlags();
+    if (child->m_hasVisibleContent || child->m_hasVisibleDescendant)
+        setAncestorChainHasVisibleDescendant();
+
+    if (child->isSelfPaintingLayer() || child->hasSelfPaintingLayerDescendant())
+        setAncestorChainHasSelfPaintingLayerDescendant();
+
+    if (child->renderer() && (child->renderer()->isOutOfFlowPositioned() || child->hasOutOfFlowPositionedDescendant()))
+        setAncestorChainHasOutOfFlowPositionedDescendant(child->renderer()->containingBlock());
+
+    compositor()->layerWasAdded(this, child);
+}
+
+RenderLayer* RenderLayer::removeChild(RenderLayer* oldChild)
+{
+    if (!renderer()->documentBeingDestroyed())
+        compositor()->layerWillBeRemoved(this, 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->isNormalFlowOnly())
+        dirtyNormalFlowList();
+    if (!oldChild->isNormalFlowOnly() || 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 |stackingContainer| value.
+        oldChild->dirtyStackingContainerZOrderLists();
+
+        // This could affect whether or not a layer has an out of flow
+        // positioned descendant so we need to schedule some updates.
+        // Removing an out of flow positioned descendant can only affect
+        // the opt-in decision for layers beneath and including the old child's
+        // containing block.
+        RenderObject* containingBlock = oldChild->renderer()->containingBlock();
+        for (RenderLayer* layer = this; layer; layer = layer->parent()) {
+            layer->updateNeedsCompositedScrolling();
+            if (layer->renderer() == containingBlock)
+                break;
+        }
+    }
+
+    if ((oldChild->renderer() && oldChild->renderer()->isOutOfFlowPositioned()) || oldChild->hasOutOfFlowPositionedDescendant())
+        dirtyAncestorChainHasOutOfFlowPositionedDescendantStatus();
+
+    oldChild->setPreviousSibling(0);
+    oldChild->setNextSibling(0);
+    oldChild->setParent(0);
+
+    oldChild->updateDescendantDependentFlags();
+    if (oldChild->m_hasVisibleContent || oldChild->m_hasVisibleDescendant)
+        dirtyAncestorChainVisibleDescendantStatus();
+
+    if (oldChild->isSelfPaintingLayer() || oldChild->hasSelfPaintingLayerDescendant())
+        dirtyAncestorChainHasSelfPaintingLayerDescendantStatus();
+
+    return oldChild;
+}
+
+void RenderLayer::removeOnlyThisLayer()
+{
+    if (!m_parent)
+        return;
+
+    // Mark that we are about to lose our layer. This makes render tree
+    // walks ignore this layer while we're removing it.
+    m_renderer->setHasLayer(false);
+
+    compositor()->layerWillBeRemoved(m_parent, this);
+
+    // Dirty the clip rects.
+    clearClipRectsIncludingDescendants();
+
+    RenderLayer* nextSib = nextSibling();
+
+    // Remove the child reflection layer before moving other child layers.
+    // The reflection layer should not be moved to the parent.
+    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);
+        m_parent->addChild(current, nextSib);
+        current->setRepaintStatus(NeedsFullRepaint);
+        // updateLayerPositions depends on hasLayer() already being false for proper layout.
+        ASSERT(!renderer()->hasLayer());
+        current->updateLayerPositions(0); // FIXME: use geometry map.
+        current = next;
+    }
+
+    // Remove us from the parent.
+    m_parent->removeChild(this);
+    m_renderer->destroyLayer();
+}
+
+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();
+        ASSERT(parentLayer);
+        RenderLayer* beforeChild = parentLayer->reflectionLayer() != this ? renderer()->parent()->findNextLayer(parentLayer, renderer()) : 0;
+        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.
+    clearClipRectsIncludingDescendants();
+}
+
+void RenderLayer::convertToPixelSnappedLayerCoords(const RenderLayer* ancestorLayer, IntPoint& roundedLocation) const
+{
+    LayoutPoint location = roundedLocation;
+    convertToLayerCoords(ancestorLayer, location);
+    roundedLocation = roundedIntPoint(location);
+}
+
+void RenderLayer::convertToPixelSnappedLayerCoords(const RenderLayer* ancestorLayer, IntRect& roundedRect) const
+{
+    LayoutRect rect = roundedRect;
+    convertToLayerCoords(ancestorLayer, rect);
+    roundedRect = pixelSnappedIntRect(rect);
+}
+
+// Returns the layer reached on the walk up towards the ancestor.
+static inline const RenderLayer* accumulateOffsetTowardsAncestor(const RenderLayer* layer, const RenderLayer* ancestorLayer, LayoutPoint& location)
+{
+    ASSERT(ancestorLayer != layer);
+
+    const RenderLayerModelObject* renderer = layer->renderer();
+    EPosition position = renderer->style()->position();
+
+    // FIXME: Special casing RenderFlowThread so much for fixed positioning here is not great.
+    RenderFlowThread* fixedFlowThreadContainer = position == FixedPosition ? renderer->flowThreadContainingBlock() : 0;
+    if (fixedFlowThreadContainer && !fixedFlowThreadContainer->isOutOfFlowPositioned())
+        fixedFlowThreadContainer = 0;
+
+    // FIXME: Positioning of out-of-flow(fixed, absolute) elements collected in a RenderFlowThread
+    // may need to be revisited in a future patch.
+    // If the fixed renderer is inside a RenderFlowThread, we should not compute location using localToAbsolute,
+    // since localToAbsolute maps the coordinates from named flow to regions coordinates and regions can be
+    // positioned in a completely different place in the viewport (RenderView).
+    if (position == FixedPosition && !fixedFlowThreadContainer && (!ancestorLayer || ancestorLayer == renderer->view()->layer())) {
+        // If the fixed layer's container is the root, just add in the offset of the view. We can obtain this by calling
+        // localToAbsolute() on the RenderView.
+        FloatPoint absPos = renderer->localToAbsolute(FloatPoint(), IsFixed);
+        location += LayoutSize(absPos.x(), absPos.y());
+        return ancestorLayer;
+    }
+
+    // For the fixed positioned elements inside a render flow thread, we should also skip the code path below
+    // Otherwise, for the case of ancestorLayer == rootLayer and fixed positioned element child of a transformed
+    // element in render flow thread, we will hit the fixed positioned container before hitting the ancestor layer.
+    if (position == FixedPosition && !fixedFlowThreadContainer) {
+        // For a fixed layers, we need to walk up to the root to see if there's a fixed position container
+        // (e.g. a transformed layer). It's an error to call convertToLayerCoords() across a layer with a transform,
+        // so we should always find the ancestor at or before we find the fixed position container.
+        RenderLayer* fixedPositionContainerLayer = 0;
+        bool foundAncestor = false;
+        for (RenderLayer* currLayer = layer->parent(); currLayer; currLayer = currLayer->parent()) {
+            if (currLayer == ancestorLayer)
+                foundAncestor = true;
+
+            if (isFixedPositionedContainer(currLayer)) {
+                fixedPositionContainerLayer = currLayer;
+                ASSERT_UNUSED(foundAncestor, foundAncestor);
+                break;
+            }
+        }
+        
+        ASSERT(fixedPositionContainerLayer); // We should have hit the RenderView's layer at least.
+
+        if (fixedPositionContainerLayer != ancestorLayer) {
+            LayoutPoint fixedContainerCoords;
+            layer->convertToLayerCoords(fixedPositionContainerLayer, fixedContainerCoords);
+
+            LayoutPoint ancestorCoords;
+            ancestorLayer->convertToLayerCoords(fixedPositionContainerLayer, ancestorCoords);
+
+            location += (fixedContainerCoords - ancestorCoords);
+            return ancestorLayer;
+        }
+    }
+    
+    RenderLayer* parentLayer;
+    if (position == AbsolutePosition || position == FixedPosition) {
+        // Do what enclosingPositionedAncestor() does, but check for ancestorLayer along the way.
+        parentLayer = layer->parent();
+        bool foundAncestorFirst = false;
+        while (parentLayer) {
+            // RenderFlowThread is a positioned container, child of RenderView, positioned at (0,0).
+            // This implies that, for out-of-flow positioned elements inside a RenderFlowThread,
+            // we are bailing out before reaching root layer.
+            if (isPositionedContainer(parentLayer))
+                break;
+
+            if (parentLayer == ancestorLayer) {
+                foundAncestorFirst = true;
+                break;
+            }
+
+            parentLayer = parentLayer->parent();
+        }
+
+        // We should not reach RenderView layer past the RenderFlowThread layer for any
+        // children of the RenderFlowThread.
+        if (renderer->flowThreadContainingBlock() && !layer->isOutOfFlowRenderFlowThread())
+            ASSERT(parentLayer != renderer->view()->layer());
+
+        if (foundAncestorFirst) {
+            // Found ancestorLayer before the abs. positioned container, so compute offset of both relative
+            // to enclosingPositionedAncestor and subtract.
+            RenderLayer* positionedAncestor = parentLayer->enclosingPositionedAncestor();
+
+            LayoutPoint thisCoords;
+            layer->convertToLayerCoords(positionedAncestor, thisCoords);
+            
+            LayoutPoint ancestorCoords;
+            ancestorLayer->convertToLayerCoords(positionedAncestor, ancestorCoords);
+
+            location += (thisCoords - ancestorCoords);
+            return ancestorLayer;
+        }
+    } else
+        parentLayer = layer->parent();
+    
+    if (!parentLayer)
+        return 0;
+
+    location += toSize(layer->location());
+    return parentLayer;
+}
+
+void RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, LayoutPoint& location) const
+{
+    if (ancestorLayer == this)
+        return;
+
+    const RenderLayer* currLayer = this;
+    while (currLayer && currLayer != ancestorLayer)
+        currLayer = accumulateOffsetTowardsAncestor(currLayer, ancestorLayer, location);
+}
+
+void RenderLayer::convertToLayerCoords(const RenderLayer* ancestorLayer, LayoutRect& rect) const
+{
+    LayoutPoint delta;
+    convertToLayerCoords(ancestorLayer, delta);
+    rect.move(-delta.x(), -delta.y());
+}
+
+bool RenderLayer::usesCompositedScrolling() const
+{
+    return isComposited() && backing()->scrollingLayer();
+}
+
+bool RenderLayer::needsCompositedScrolling() const
+{
+    return m_needsCompositedScrolling;
+}
+
+void RenderLayer::updateNeedsCompositedScrolling()
+{
+    bool needsCompositedScrolling = false;
+
+    FrameView* frameView = renderer()->view()->frameView();
+    if (frameView && frameView->containsScrollableArea(this)) {
+        updateDescendantDependentFlags();
+
+        bool forceUseCompositedScrolling = acceleratedCompositingForOverflowScrollEnabled()
+            && canBeStackingContainer()
+            && !hasOutOfFlowPositionedDescendant();
+
+#if ENABLE(ACCELERATED_OVERFLOW_SCROLLING)
+        needsCompositedScrolling = forceUseCompositedScrolling || renderer()->style()->useTouchOverflowScrolling();
+#else
+        needsCompositedScrolling = forceUseCompositedScrolling;
+#endif
+        // We gather a boolean value for use with Google UMA histograms to
+        // quantify the actual effects of a set of patches attempting to
+        // relax composited scrolling requirements, thereby increasing the
+        // number of composited overflow divs.
+        if (acceleratedCompositingForOverflowScrollEnabled())
+            HistogramSupport::histogramEnumeration("Renderer.NeedsCompositedScrolling", needsCompositedScrolling, 2);
+    }
+
+    if (m_needsCompositedScrolling == needsCompositedScrolling)
+        return;
+
+    m_needsCompositedScrolling = needsCompositedScrolling;
+
+    updateIsNormalFlowOnly();
+    updateSelfPaintingLayer();
+
+    if (isStackingContainer())
+        dirtyZOrderLists();
+    else
+        clearZOrderLists();
+
+    dirtyStackingContainerZOrderLists();
+
+    compositor()->setShouldReevaluateCompositingAfterLayout();
+    compositor()->setCompositingLayersNeedRebuild();
+}
+
+static inline int adjustedScrollDelta(int beginningDelta) {
+    // This implemention matches Firefox's.
+    // http://mxr.mozilla.org/firefox/source/toolkit/content/widgets/browser.xml#856.
+    const int speedReducer = 12;
+
+    int adjustedDelta = beginningDelta / speedReducer;
+    if (adjustedDelta > 1)
+        adjustedDelta = static_cast<int>(adjustedDelta * sqrt(static_cast<double>(adjustedDelta))) - 1;
+    else if (adjustedDelta < -1)
+        adjustedDelta = static_cast<int>(adjustedDelta * sqrt(static_cast<double>(-adjustedDelta))) + 1;
+
+    return adjustedDelta;
+}
+
+static inline IntSize adjustedScrollDelta(const IntSize& delta)
+{
+    return IntSize(adjustedScrollDelta(delta.width()), adjustedScrollDelta(delta.height()));
+}
+
+void RenderLayer::panScrollFromPoint(const IntPoint& sourcePoint)
+{
+    Frame* frame = renderer()->frame();
+    if (!frame)
+        return;
+    
+    IntPoint lastKnownMousePosition = frame->eventHandler()->lastKnownMousePosition();
+    
+    // We need to check if the last known mouse position is out of the window. When the mouse is out of the window, the position is incoherent
+    static IntPoint previousMousePosition;
+    if (lastKnownMousePosition.x() < 0 || lastKnownMousePosition.y() < 0)
+        lastKnownMousePosition = previousMousePosition;
+    else
+        previousMousePosition = lastKnownMousePosition;
+
+    IntSize delta = lastKnownMousePosition - sourcePoint;
+
+    if (abs(delta.width()) <= ScrollView::noPanScrollRadius) // at the center we let the space for the icon
+        delta.setWidth(0);
+    if (abs(delta.height()) <= ScrollView::noPanScrollRadius)
+        delta.setHeight(0);
+
+    scrollByRecursively(adjustedScrollDelta(delta), ScrollOffsetClamped);
+}
+
+void RenderLayer::scrollByRecursively(const IntSize& delta, ScrollOffsetClamping clamp)
+{
+    if (delta.isZero())
+        return;
+
+    bool restrictedByLineClamp = false;
+    if (renderer()->parent())
+        restrictedByLineClamp = !renderer()->parent()->style()->lineClamp().isNone();
+
+    if (renderer()->hasOverflowClip() && !restrictedByLineClamp) {
+        IntSize newScrollOffset = scrollOffset() + delta;
+        scrollToOffset(newScrollOffset, clamp);
+
+        // If this layer can't do the scroll we ask the next layer up that can scroll to try
+        IntSize remainingScrollOffset = newScrollOffset - scrollOffset();
+        if (!remainingScrollOffset.isZero() && renderer()->parent()) {
+            if (RenderLayer* scrollableLayer = enclosingScrollableLayer())
+                scrollableLayer->scrollByRecursively(remainingScrollOffset);
+
+            Frame* frame = renderer()->frame();
+            if (frame)
+                frame->eventHandler()->updateAutoscrollRenderer();
+        }
+    } else if (renderer()->view()->frameView()) {
+        // If we are here, we were called on a renderer that can be programmatically scrolled, but doesn't
+        // have an overflow clip. Which means that it is a document node that can be scrolled.
+        renderer()->view()->frameView()->scrollBy(delta);
+
+        // FIXME: If we didn't scroll the whole way, do we want to try looking at the frames ownerElement? 
+        // https://bugs.webkit.org/show_bug.cgi?id=28237
+    }
+}
+
+IntSize RenderLayer::clampScrollOffset(const IntSize& scrollOffset) const
+{
+    RenderBox* box = renderBox();
+    ASSERT(box);
+
+    int maxX = scrollWidth() - box->pixelSnappedClientWidth();
+    int maxY = scrollHeight() - box->pixelSnappedClientHeight();
+
+    int x = max(min(scrollOffset.width(), maxX), 0);
+    int y = max(min(scrollOffset.height(), maxY), 0);
+    return IntSize(x, y);
+}
+
+void RenderLayer::scrollToOffset(const IntSize& scrollOffset, ScrollOffsetClamping clamp)
+{
+    IntSize newScrollOffset = clamp == ScrollOffsetClamped ? clampScrollOffset(scrollOffset) : scrollOffset;
+    if (newScrollOffset != this->scrollOffset())
+        scrollToOffsetWithoutAnimation(IntPoint(newScrollOffset));
+}
+
+void RenderLayer::scrollTo(int x, int y)
+{
+    RenderBox* box = renderBox();
+    if (!box)
+        return;
+
+    if (box->style()->overflowX() != OMARQUEE) {
+        // Ensure that the dimensions will be computed if they need to be (for overflow:hidden blocks).
+        if (m_scrollDimensionsDirty)
+            computeScrollDimensions();
+    }
+    
+    // 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.).
+    IntSize newScrollOffset = IntSize(x - scrollOrigin().x(), y - scrollOrigin().y());
+    if (m_scrollOffset == newScrollOffset)
+        return;
+    m_scrollOffset = newScrollOffset;
+
+    Frame* frame = renderer()->frame();
+    InspectorInstrumentation::willScrollLayer(frame);
+
+    RenderView* view = renderer()->view();
+    
+    // We should have a RenderView if we're trying to scroll.
+    ASSERT(view);
+
+    // Update the positions of our child layers (if needed as only fixed layers should be impacted by a scroll).
+    // We don't update compositing layers, because we need to do a deep update from the compositing ancestor.
+    bool inLayout = view ? view->frameView()->isInLayout() : false;
+    if (!inLayout) {
+        // If we're in the middle of layout, we'll just update layers once layout has finished.
+        updateLayerPositionsAfterOverflowScroll();
+        if (view) {
+            // Update regions, scrolling may change the clip of a particular region.
+            view->frameView()->updateAnnotatedRegions();
+
+            view->updateWidgetPositions();
+
+            view->markLazyBlocksForLayout();
+        }
+
+        if (!m_updatingMarqueePosition) {
+            // Avoid updating compositing layers if, higher on the stack, we're already updating layer
+            // positions. Updating layer positions requires a full walk of up-to-date RenderLayers, and
+            // in this case we're still updating their positions; we'll update compositing layers later
+            // when that completes.
+            updateCompositingLayersAfterScroll();
+        }
+    }
+
+    RenderLayerModelObject* repaintContainer = renderer()->containerForRepaint();
+    if (frame) {
+        // The caret rect needs to be invalidated after scrolling
+        frame->selection()->setCaretRectNeedsUpdate();
+
+        FloatQuad quadForFakeMouseMoveEvent = FloatQuad(m_repaintRect);
+        if (repaintContainer)
+            quadForFakeMouseMoveEvent = repaintContainer->localToAbsoluteQuad(quadForFakeMouseMoveEvent);
+        frame->eventHandler()->dispatchFakeMouseMoveEventSoonInQuad(quadForFakeMouseMoveEvent);
+    }
+
+    bool requiresRepaint = true;
+
+    if (compositor()->inCompositingMode() && usesCompositedScrolling())
+        requiresRepaint = false;
+
+    // Just schedule a full repaint of our object.
+    if (view && requiresRepaint)
+        renderer()->repaintUsingContainer(repaintContainer, pixelSnappedIntRect(m_repaintRect));
+
+    // Schedule the scroll DOM event.
+    if (renderer()->node())
+        renderer()->node()->document()->eventQueue()->enqueueOrDispatchScrollEvent(renderer()->node(), DocumentEventQueue::ScrollEventElementTarget);
+
+    InspectorInstrumentation::didScrollLayer(frame);
+}
+
+static inline bool frameElementAndViewPermitScroll(HTMLFrameElement* frameElement, FrameView* frameView) 
+{
+    // If scrollbars aren't explicitly forbidden, permit scrolling.
+    if (frameElement && frameElement->scrollingMode() != ScrollbarAlwaysOff)
+        return true;
+
+    // If scrollbars are forbidden, user initiated scrolls should obviously be ignored.
+    if (frameView->wasScrolledByUser())
+        return false;
+
+    // Forbid autoscrolls when scrollbars are off, but permits other programmatic scrolls,
+    // like navigation to an anchor.
+    return !frameView->frame()->eventHandler()->autoscrollInProgress();
+}
+
+void RenderLayer::scrollRectToVisible(const LayoutRect& rect, const ScrollAlignment& alignX, const ScrollAlignment& alignY)
+{
+    RenderLayer* parentLayer = 0;
+    LayoutRect newRect = rect;
+
+    // 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 renderer().
+    FrameView* frameView = renderer()->document()->view();
+    if (frameView)
+        frameView->pauseScheduledEvents();
+
+    bool restrictedByLineClamp = false;
+    if (renderer()->parent()) {
+        parentLayer = renderer()->parent()->enclosingLayer();
+        restrictedByLineClamp = !renderer()->parent()->style()->lineClamp().isNone();
+    }
+
+    if (renderer()->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.
+        RenderBox* box = renderBox();
+        ASSERT(box);
+        LayoutRect localExposeRect(box->absoluteToLocalQuad(FloatQuad(FloatRect(rect)), UseTransforms).boundingBox());
+        LayoutRect layerBounds(0, 0, box->clientWidth(), box->clientHeight());
+        LayoutRect r = getRectToExpose(layerBounds, localExposeRect, alignX, alignY);
+
+        IntSize clampedScrollOffset = clampScrollOffset(scrollOffset() + toIntSize(roundedIntRect(r).location()));
+        if (clampedScrollOffset != scrollOffset()) {
+            IntSize oldScrollOffset = scrollOffset();
+            scrollToOffset(clampedScrollOffset);
+            IntSize scrollOffsetDifference = scrollOffset() - oldScrollOffset;
+            localExposeRect.move(-scrollOffsetDifference);
+            newRect = LayoutRect(box->localToAbsoluteQuad(FloatQuad(FloatRect(localExposeRect)), UseTransforms).boundingBox());
+        }
+    } else if (!parentLayer && renderer()->isBox() && renderBox()->canBeProgramaticallyScrolled()) {
+        if (frameView) {
+            Element* ownerElement = 0;
+            if (renderer()->document())
+                ownerElement = renderer()->document()->ownerElement();
+
+            if (ownerElement && ownerElement->renderer()) {
+                HTMLFrameElement* frameElement = 0;
+
+                if (ownerElement->hasTagName(frameTag) || ownerElement->hasTagName(iframeTag))
+                    frameElement = static_cast<HTMLFrameElement*>(ownerElement);
+
+                if (frameElementAndViewPermitScroll(frameElement, frameView)) {
+                    LayoutRect viewRect = frameView->visibleContentRect();
+                    LayoutRect exposeRect = getRectToExpose(viewRect, rect, alignX, alignY);
+
+                    int xOffset = roundToInt(exposeRect.x());
+                    int yOffset = roundToInt(exposeRect.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));
+                    if (frameView->safeToPropagateScrollToParent()) {
+                        parentLayer = ownerElement->renderer()->enclosingLayer();
+                        // FIXME: This doesn't correctly convert the rect to
+                        // absolute coordinates in the parent.
+                        newRect.setX(rect.x() - frameView->scrollX() + frameView->x());
+                        newRect.setY(rect.y() - frameView->scrollY() + frameView->y());
+                    } else
+                        parentLayer = 0;
+                }
+            } else {
+                LayoutRect viewRect = frameView->visibleContentRect();
+                LayoutRect r = getRectToExpose(viewRect, rect, alignX, alignY);
+                frameView->setScrollPosition(roundedIntPoint(r.location()));
+            }
+        }
+    }
+    
+    if (parentLayer)
+        parentLayer->scrollRectToVisible(newRect, alignX, alignY);
+
+    if (frameView)
+        frameView->resumeScheduledEvents();
+}
+
+void RenderLayer::updateCompositingLayersAfterScroll()
+{
+    if (compositor()->inCompositingMode()) {
+        // Our stacking container is guaranteed to contain all of our descendants that may need
+        // repositioning, so update compositing layers from there.
+        if (RenderLayer* compositingAncestor = ancestorStackingContainer()->enclosingCompositingLayer()) {
+            if (usesCompositedScrolling())
+                compositor()->updateCompositingLayers(CompositingUpdateOnCompositedScroll, compositingAncestor);
+            else
+                compositor()->updateCompositingLayers(CompositingUpdateOnScroll, compositingAncestor);
+        }
+    }
+}
+
+LayoutRect RenderLayer::getRectToExpose(const LayoutRect &visibleRect, const LayoutRect &exposeRect, const ScrollAlignment& alignX, const ScrollAlignment& alignY)
+{
+    // Determine the appropriate X behavior.
+    ScrollBehavior scrollX;
+    LayoutRect exposeRectX(exposeRect.x(), visibleRect.y(), exposeRect.width(), visibleRect.height());
+    LayoutUnit 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 = ScrollAlignment::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 = ScrollAlignment::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 = ScrollAlignment::getPartialBehavior(alignX);
+    else
+        scrollX = ScrollAlignment::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.maxX() > visibleRect.maxX() && exposeRect.width() < visibleRect.width())
+        scrollX = alignRight;
+
+    // Given the X behavior, compute the X coordinate.
+    LayoutUnit x;
+    if (scrollX == noScroll) 
+        x = visibleRect.x();
+    else if (scrollX == alignRight)
+        x = exposeRect.maxX() - 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;
+    LayoutRect exposeRectY(visibleRect.x(), exposeRect.y(), visibleRect.width(), exposeRect.height());
+    LayoutUnit intersectHeight = intersection(visibleRect, exposeRectY).height();
+    if (intersectHeight == exposeRect.height())
+        // If the rectangle is fully visible, use the specified visible behavior.
+        scrollY = ScrollAlignment::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 = ScrollAlignment::getVisibleBehavior(alignY);
+        if (scrollY == alignCenter)
+            scrollY = noScroll;
+    } else if (intersectHeight > 0)
+        // If the rectangle is partially visible, use the specified partial behavior
+        scrollY = ScrollAlignment::getPartialBehavior(alignY);
+    else
+        scrollY = ScrollAlignment::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.maxY() > visibleRect.maxY() && exposeRect.height() < visibleRect.height())
+        scrollY = alignBottom;
+
+    // Given the Y behavior, compute the Y coordinate.
+    LayoutUnit y;
+    if (scrollY == noScroll) 
+        y = visibleRect.y();
+    else if (scrollY == alignBottom)
+        y = exposeRect.maxY() - visibleRect.height();
+    else if (scrollY == alignCenter)
+        y = exposeRect.y() + (exposeRect.height() - visibleRect.height()) / 2;
+    else
+        y = exposeRect.y();
+
+    return LayoutRect(LayoutPoint(x, y), visibleRect.size());
+}
+
+void RenderLayer::autoscroll(const IntPoint& position)
+{
+    Frame* frame = renderer()->frame();
+    if (!frame)
+        return;
+
+    FrameView* frameView = frame->view();
+    if (!frameView)
+        return;
+
+    IntPoint currentDocumentPosition = frameView->windowToContents(position);
+    scrollRectToVisible(LayoutRect(currentDocumentPosition, LayoutSize(1, 1)), ScrollAlignment::alignToEdgeIfNeeded, ScrollAlignment::alignToEdgeIfNeeded);
+}
+
+bool RenderLayer::canResize() const
+{
+    if (!renderer())
+        return false;
+    // We need a special case for <iframe> because they never have
+    // hasOverflowClip(). However, they do "implicitly" clip their contents, so
+    // we want to allow resizing them also.
+    return (renderer()->hasOverflowClip() || renderer()->isRenderIFrame()) && renderer()->style()->resize() != RESIZE_NONE;
+}
+
+void RenderLayer::resize(const PlatformMouseEvent& evt, const LayoutSize& oldOffset)
+{
+    // FIXME: This should be possible on generated content but is not right now.
+    if (!inResizeMode() || !canResize() || !renderer()->node())
+        return;
+
+    ASSERT(renderer()->node()->isElementNode());
+    Element* element = toElement(renderer()->node());
+    RenderBox* renderer = toRenderBox(element->renderer());
+
+    Document* document = element->document();
+    if (!document->frame()->eventHandler()->mousePressed())
+        return;
+
+    float zoomFactor = renderer->style()->effectiveZoom();
+
+    LayoutSize newOffset = offsetFromResizeCorner(document->view()->windowToContents(evt.position()));
+    newOffset.setWidth(newOffset.width() / zoomFactor);
+    newOffset.setHeight(newOffset.height() / zoomFactor);
+    
+    LayoutSize currentSize = LayoutSize(renderer->width() / zoomFactor, renderer->height() / zoomFactor);
+    LayoutSize minimumSize = element->minimumSizeForResizing().shrunkTo(currentSize);
+    element->setMinimumSizeForResizing(minimumSize);
+    
+    LayoutSize adjustedOldOffset = LayoutSize(oldOffset.width() / zoomFactor, oldOffset.height() / zoomFactor);
+    if (renderer->style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft()) {
+        newOffset.setWidth(-newOffset.width());
+        adjustedOldOffset.setWidth(-adjustedOldOffset.width());
+    }
+    
+    LayoutSize difference = (currentSize + newOffset - adjustedOldOffset).expandedTo(minimumSize) - currentSize;
+
+    ASSERT_WITH_SECURITY_IMPLICATION(element->isStyledElement());
+    StyledElement* styledElement = static_cast<StyledElement*>(element);
+    bool isBoxSizingBorder = renderer->style()->boxSizing() == BORDER_BOX;
+
+    EResize resize = renderer->style()->resize();
+    if (resize != RESIZE_VERTICAL && difference.width()) {
+        if (element->isFormControlElement()) {
+            // Make implicit margins from the theme explicit (see <http://bugs.webkit.org/show_bug.cgi?id=9547>).
+            styledElement->setInlineStyleProperty(CSSPropertyMarginLeft, String::number(renderer->marginLeft() / zoomFactor) + "px", false);
+            styledElement->setInlineStyleProperty(CSSPropertyMarginRight, String::number(renderer->marginRight() / zoomFactor) + "px", false);
+        }
+        LayoutUnit baseWidth = renderer->width() - (isBoxSizingBorder ? LayoutUnit() : renderer->borderAndPaddingWidth());
+        baseWidth = baseWidth / zoomFactor;
+        styledElement->setInlineStyleProperty(CSSPropertyWidth, String::number(roundToInt(baseWidth + difference.width())) + "px", false);
+    }
+
+    if (resize != RESIZE_HORIZONTAL && difference.height()) {
+        if (element->isFormControlElement()) {
+            // Make implicit margins from the theme explicit (see <http://bugs.webkit.org/show_bug.cgi?id=9547>).
+            styledElement->setInlineStyleProperty(CSSPropertyMarginTop, String::number(renderer->marginTop() / zoomFactor) + "px", false);
+            styledElement->setInlineStyleProperty(CSSPropertyMarginBottom, String::number(renderer->marginBottom() / zoomFactor) + "px", false);
+        }
+        LayoutUnit baseHeight = renderer->height() - (isBoxSizingBorder ? LayoutUnit() : renderer->borderAndPaddingHeight());
+        baseHeight = baseHeight / zoomFactor;
+        styledElement->setInlineStyleProperty(CSSPropertyHeight, String::number(roundToInt(baseHeight + difference.height())) + "px", false);
+    }
+
+    document->updateLayout();
+
+    // FIXME (Radar 4118564): We should also autoscroll the window as necessary to keep the point under the cursor in view.
+}
+
+int RenderLayer::scrollSize(ScrollbarOrientation orientation) const
+{
+    Scrollbar* scrollbar = ((orientation == HorizontalScrollbar) ? m_hBar : m_vBar).get();
+    return scrollbar ? (scrollbar->totalSize() - scrollbar->visibleSize()) : 0;
+}
+
+void RenderLayer::setScrollOffset(const IntPoint& offset)
+{
+    scrollTo(offset.x(), offset.y());
+}
+
+int RenderLayer::scrollPosition(Scrollbar* scrollbar) const
+{
+    if (scrollbar->orientation() == HorizontalScrollbar)
+        return scrollXOffset();
+    if (scrollbar->orientation() == VerticalScrollbar)
+        return scrollYOffset();
+    return 0;
+}
+
+IntPoint RenderLayer::scrollPosition() const
+{
+    return IntPoint(m_scrollOffset);
+}
+
+IntPoint RenderLayer::minimumScrollPosition() const
+{
+    return -scrollOrigin();
+}
+
+IntPoint RenderLayer::maximumScrollPosition() const
+{
+    // FIXME: m_scrollSize may not be up-to-date if m_scrollDimensionsDirty is true.
+    return -scrollOrigin() + roundedIntSize(m_scrollSize) - visibleContentRect(IncludeScrollbars).size();
+}
+
+IntRect RenderLayer::visibleContentRect(VisibleContentRectIncludesScrollbars scrollbarInclusion) const
+{
+    int verticalScrollbarWidth = 0;
+    int horizontalScrollbarHeight = 0;
+    if (scrollbarInclusion == IncludeScrollbars) {
+        verticalScrollbarWidth = (verticalScrollbar() && !verticalScrollbar()->isOverlayScrollbar()) ? verticalScrollbar()->width() : 0;
+        horizontalScrollbarHeight = (horizontalScrollbar() && !horizontalScrollbar()->isOverlayScrollbar()) ? horizontalScrollbar()->height() : 0;
+    }
+    
+    return IntRect(IntPoint(scrollXOffset(), scrollYOffset()),
+                   IntSize(max(0, m_layerSize.width() - verticalScrollbarWidth), 
+                           max(0, m_layerSize.height() - horizontalScrollbarHeight)));
+}
+
+IntSize RenderLayer::overhangAmount() const
+{
+    return IntSize();
+}
+
+bool RenderLayer::isActive() const
+{
+    Page* page = renderer()->frame()->page();
+    return page && page->focusController()->isActive();
+}
+
+static int cornerStart(const RenderLayer* layer, int minX, int maxX, int thickness)
+{
+    if (layer->renderer()->style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft())
+        return minX + layer->renderer()->style()->borderLeftWidth();
+    return maxX - thickness - layer->renderer()->style()->borderRightWidth();
+}
+
+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::theme()->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(cornerStart(layer, bounds.x(), bounds.maxX(), horizontalThickness),
+                   bounds.maxY() - verticalThickness - layer->renderer()->style()->borderBottomWidth(),
+                   horizontalThickness, verticalThickness);
+}
+
+IntRect RenderLayer::scrollCornerRect() const
+{
+    // 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 = horizontalScrollbar();
+    bool hasVerticalBar = verticalScrollbar();
+    bool hasResizer = renderer()->style()->resize() != RESIZE_NONE;
+    if ((hasHorizontalBar && hasVerticalBar) || (hasResizer && (hasHorizontalBar || hasVerticalBar)))
+        return cornerRect(this, renderBox()->pixelSnappedBorderBoxRect());
+    return IntRect();
+}
+
+static IntRect resizerCornerRect(const RenderLayer* layer, const IntRect& bounds)
+{
+    ASSERT(layer->renderer()->isBox());
+    if (layer->renderer()->style()->resize() == RESIZE_NONE)
+        return IntRect();
+    return cornerRect(layer, bounds);
+}
+
+IntRect RenderLayer::scrollCornerAndResizerRect() const
+{
+    RenderBox* box = renderBox();
+    if (!box)
+        return IntRect();
+    IntRect scrollCornerAndResizer = scrollCornerRect();
+    if (scrollCornerAndResizer.isEmpty())
+        scrollCornerAndResizer = resizerCornerRect(this, box->pixelSnappedBorderBoxRect());
+    return scrollCornerAndResizer;
+}
+
+bool RenderLayer::isScrollCornerVisible() const
+{
+    ASSERT(renderer()->isBox());
+    return !scrollCornerRect().isEmpty();
+}
+
+IntRect RenderLayer::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntRect& scrollbarRect) const
+{
+    RenderView* view = renderer()->view();
+    if (!view)
+        return scrollbarRect;
+
+    IntRect rect = scrollbarRect;
+    rect.move(scrollbarOffset(scrollbar));
+
+    return view->frameView()->convertFromRenderer(renderer(), rect);
+}
+
+IntRect RenderLayer::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntRect& parentRect) const
+{
+    RenderView* view = renderer()->view();
+    if (!view)
+        return parentRect;
+
+    IntRect rect = view->frameView()->convertToRenderer(renderer(), parentRect);
+    rect.move(-scrollbarOffset(scrollbar));
+    return rect;
+}
+
+IntPoint RenderLayer::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntPoint& scrollbarPoint) const
+{
+    RenderView* view = renderer()->view();
+    if (!view)
+        return scrollbarPoint;
+
+    IntPoint point = scrollbarPoint;
+    point.move(scrollbarOffset(scrollbar));
+    return view->frameView()->convertFromRenderer(renderer(), point);
+}
+
+IntPoint RenderLayer::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntPoint& parentPoint) const
+{
+    RenderView* view = renderer()->view();
+    if (!view)
+        return parentPoint;
+
+    IntPoint point = view->frameView()->convertToRenderer(renderer(), parentPoint);
+
+    point.move(-scrollbarOffset(scrollbar));
+    return point;
+}
+
+IntSize RenderLayer::contentsSize() const
+{
+    return IntSize(scrollWidth(), scrollHeight());
+}
+
+int RenderLayer::visibleHeight() const
+{
+    return m_layerSize.height();
+}
+
+int RenderLayer::visibleWidth() const
+{
+    return m_layerSize.width();
+}
+
+bool RenderLayer::shouldSuspendScrollAnimations() const
+{
+    RenderView* view = renderer()->view();
+    if (!view)
+        return true;
+    return view->frameView()->shouldSuspendScrollAnimations();
+}
+
+bool RenderLayer::scrollbarsCanBeActive() const
+{
+    RenderView* view = renderer()->view();
+    if (!view)
+        return false;
+    return view->frameView()->scrollbarsCanBeActive();
+}
+
+IntPoint RenderLayer::lastKnownMousePosition() const
+{
+    return renderer()->frame() ? renderer()->frame()->eventHandler()->lastKnownMousePosition() : IntPoint();
+}
+
+IntRect RenderLayer::rectForHorizontalScrollbar(const IntRect& borderBoxRect) const
+{
+    if (!m_hBar)
+        return IntRect();
+
+    const RenderBox* box = renderBox();
+    const IntRect& scrollCorner = scrollCornerRect();
+
+    return IntRect(horizontalScrollbarStart(borderBoxRect.x()),
+        borderBoxRect.maxY() - box->borderBottom() - m_hBar->height(),
+        borderBoxRect.width() - (box->borderLeft() + box->borderRight()) - scrollCorner.width(),
+        m_hBar->height());
+}
+
+IntRect RenderLayer::rectForVerticalScrollbar(const IntRect& borderBoxRect) const
+{
+    if (!m_vBar)
+        return IntRect();
+
+    const RenderBox* box = renderBox();
+    const IntRect& scrollCorner = scrollCornerRect();
+
+    return IntRect(verticalScrollbarStart(borderBoxRect.x(), borderBoxRect.maxX()),
+        borderBoxRect.y() + box->borderTop(),
+        m_vBar->width(),
+        borderBoxRect.height() - (box->borderTop() + box->borderBottom()) - scrollCorner.height());
+}
+
+LayoutUnit RenderLayer::verticalScrollbarStart(int minX, int maxX) const
+{
+    const RenderBox* box = renderBox();
+    if (renderer()->style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft())
+        return minX + box->borderLeft();
+    return maxX - box->borderRight() - m_vBar->width();
+}
+
+LayoutUnit RenderLayer::horizontalScrollbarStart(int minX) const
+{
+    const RenderBox* box = renderBox();
+    int x = minX + box->borderLeft();
+    if (renderer()->style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft())
+        x += m_vBar ? m_vBar->width() : resizerCornerRect(this, box->pixelSnappedBorderBoxRect()).width();
+    return x;
+}
+
+IntSize RenderLayer::scrollbarOffset(const Scrollbar* scrollbar) const
+{
+    RenderBox* box = renderBox();
+
+    if (scrollbar == m_vBar.get())
+        return IntSize(verticalScrollbarStart(0, box->width()), box->borderTop());
+
+    if (scrollbar == m_hBar.get())
+        return IntSize(horizontalScrollbarStart(0), box->height() - box->borderBottom() - scrollbar->height());
+    
+    ASSERT_NOT_REACHED();
+    return IntSize();
+}
+
+void RenderLayer::invalidateScrollbarRect(Scrollbar* scrollbar, const IntRect& rect)
+{
+    if (scrollbar == m_vBar.get()) {
+        if (GraphicsLayer* layer = layerForVerticalScrollbar()) {
+            layer->setNeedsDisplayInRect(rect);
+            return;
+        }
+    } else {
+        if (GraphicsLayer* layer = layerForHorizontalScrollbar()) {
+            layer->setNeedsDisplayInRect(rect);
+            return;
+        }
+    }
+
+    IntRect scrollRect = rect;
+    RenderBox* box = renderBox();
+    ASSERT(box);
+    // If we are not yet inserted into the tree, there is no need to repaint.
+    if (!box->parent())
+        return;
+
+    if (scrollbar == m_vBar.get())
+        scrollRect.move(verticalScrollbarStart(0, box->width()), box->borderTop());
+    else
+        scrollRect.move(horizontalScrollbarStart(0), box->height() - box->borderBottom() - scrollbar->height());
+    renderer()->repaintRectangle(scrollRect);
+}
+
+void RenderLayer::invalidateScrollCornerRect(const IntRect& rect)
+{
+    if (GraphicsLayer* layer = layerForScrollCorner()) {
+        layer->setNeedsDisplayInRect(rect);
+        return;
+    }
+
+    if (m_scrollCorner)
+        m_scrollCorner->repaintRectangle(rect);
+    if (m_resizer)
+        m_resizer->repaintRectangle(rect);
+}
+
+static inline RenderObject* rendererForScrollbar(RenderObject* renderer)
+{
+    if (Node* node = renderer->node()) {
+        if (ShadowRoot* shadowRoot = node->containingShadowRoot()) {
+            if (shadowRoot->type() == ShadowRoot::UserAgentShadowRoot)
+                return shadowRoot->host()->renderer();
+        }
+    }
+
+    return renderer;
+}
+
+PassRefPtr<Scrollbar> RenderLayer::createScrollbar(ScrollbarOrientation orientation)
+{
+    RefPtr<Scrollbar> widget;
+    RenderObject* actualRenderer = rendererForScrollbar(renderer());
+    bool hasCustomScrollbarStyle = actualRenderer->isBox() && actualRenderer->style()->hasPseudoStyle(SCROLLBAR);
+    if (hasCustomScrollbarStyle)
+        widget = RenderScrollbar::createCustomScrollbar(this, orientation, actualRenderer->node());
+    else {
+        widget = Scrollbar::createNativeScrollbar(this, orientation, RegularScrollbar);
+        if (orientation == HorizontalScrollbar)
+            didAddHorizontalScrollbar(widget.get());
+        else 
+            didAddVerticalScrollbar(widget.get());
+    }
+    renderer()->document()->view()->addChild(widget.get());        
+    return widget.release();
+}
+
+void RenderLayer::destroyScrollbar(ScrollbarOrientation orientation)
+{
+    RefPtr<Scrollbar>& scrollbar = orientation == HorizontalScrollbar ? m_hBar : m_vBar;
+    if (!scrollbar)
+        return;
+
+    if (!scrollbar->isCustomScrollbar()) {
+        if (orientation == HorizontalScrollbar)
+            willRemoveHorizontalScrollbar(scrollbar.get());
+        else
+            willRemoveVerticalScrollbar(scrollbar.get());
+    }
+
+    scrollbar->removeFromParent();
+    scrollbar->disconnectFromScrollableArea();
+    scrollbar = 0;
+}
+
+bool RenderLayer::scrollsOverflow() const
+{
+    if (!renderer()->isBox())
+        return false;
+
+    return toRenderBox(renderer())->scrollsOverflow();
+}
+
+void RenderLayer::setHasHorizontalScrollbar(bool hasScrollbar)
+{
+    if (hasScrollbar == hasHorizontalScrollbar())
+        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();
+
+    // Force an update since we know the scrollbars have changed things.
+    if (renderer()->document()->hasAnnotatedRegions())
+        renderer()->document()->setAnnotatedRegionsDirty(true);
+}
+
+void RenderLayer::setHasVerticalScrollbar(bool hasScrollbar)
+{
+    if (hasScrollbar == hasVerticalScrollbar())
+        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();
+
+    // Force an update since we know the scrollbars have changed things.
+    if (renderer()->document()->hasAnnotatedRegions())
+        renderer()->document()->setAnnotatedRegionsDirty(true);
+}
+
+ScrollableArea* RenderLayer::enclosingScrollableArea() const
+{
+    if (RenderLayer* scrollableLayer = enclosingScrollableLayer())
+        return scrollableLayer;
+
+    // FIXME: We should return the frame view here (or possibly an ancestor frame view,
+    // if the frame view isn't scrollable.
+    return 0;
+}
+
+int RenderLayer::verticalScrollbarWidth(OverlayScrollbarSizeRelevancy relevancy) const
+{
+    if (!m_vBar || (m_vBar->isOverlayScrollbar() && (relevancy == IgnoreOverlayScrollbarSize || !m_vBar->shouldParticipateInHitTesting())))
+        return 0;
+    return m_vBar->width();
+}
+
+int RenderLayer::horizontalScrollbarHeight(OverlayScrollbarSizeRelevancy relevancy) const
+{
+    if (!m_hBar || (m_hBar->isOverlayScrollbar() && (relevancy == IgnoreOverlayScrollbarSize || !m_hBar->shouldParticipateInHitTesting())))
+        return 0;
+    return m_hBar->height();
+}
+
+IntSize RenderLayer::offsetFromResizeCorner(const IntPoint& absolutePoint) const
+{
+    // Currently the resize corner is either the bottom right corner or the bottom left corner.
+    // FIXME: This assumes the location is 0, 0. Is this guaranteed to always be the case?
+    IntSize elementSize = size();
+    if (renderer()->style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft())
+        elementSize.setWidth(0);
+    IntPoint resizerPoint = IntPoint(elementSize);
+    IntPoint localPoint = roundedIntPoint(absoluteToContents(absolutePoint));
+    return localPoint - resizerPoint;
+}
+
+bool RenderLayer::hasOverflowControls() const
+{
+    return m_hBar || m_vBar || m_scrollCorner || renderer()->style()->resize() != RESIZE_NONE;
+}
+
+void RenderLayer::positionOverflowControls(const IntSize& offsetFromRoot)
+{
+    if (!m_hBar && !m_vBar && !canResize())
+        return;
+    
+    RenderBox* box = renderBox();
+    if (!box)
+        return;
+
+    const IntRect borderBox = box->pixelSnappedBorderBoxRect();
+    const IntRect& scrollCorner = scrollCornerRect();
+    IntRect absBounds(borderBox.location() + offsetFromRoot, borderBox.size());
+    if (m_vBar) {
+        IntRect vBarRect = rectForVerticalScrollbar(borderBox);
+        vBarRect.move(offsetFromRoot);
+        m_vBar->setFrameRect(vBarRect);
+    }
+    
+    if (m_hBar) {
+        IntRect hBarRect = rectForHorizontalScrollbar(borderBox);
+        hBarRect.move(offsetFromRoot);
+        m_hBar->setFrameRect(hBarRect);
+    }
+    
+    if (m_scrollCorner)
+        m_scrollCorner->setFrameRect(scrollCorner);
+    if (m_resizer)
+        m_resizer->setFrameRect(resizerCornerRect(this, borderBox));
+
+    if (isComposited())
+        backing()->positionOverflowControlsLayers(offsetFromRoot);
+}
+
+int RenderLayer::scrollWidth() const
+{
+    ASSERT(renderBox());
+    if (m_scrollDimensionsDirty)
+        const_cast<RenderLayer*>(this)->computeScrollDimensions();
+    return snapSizeToPixel(m_scrollSize.width(), renderBox()->clientLeft() + renderBox()->x());
+}
+
+int RenderLayer::scrollHeight() const
+{
+    ASSERT(renderBox());
+    if (m_scrollDimensionsDirty)
+        const_cast<RenderLayer*>(this)->computeScrollDimensions();
+    return snapSizeToPixel(m_scrollSize.height(), renderBox()->clientTop() + renderBox()->y());
+}
+
+LayoutUnit RenderLayer::overflowTop() const
+{
+    RenderBox* box = renderBox();
+    LayoutRect overflowRect(box->layoutOverflowRect());
+    box->flipForWritingMode(overflowRect);
+    return overflowRect.y();
+}
+
+LayoutUnit RenderLayer::overflowBottom() const
+{
+    RenderBox* box = renderBox();
+    LayoutRect overflowRect(box->layoutOverflowRect());
+    box->flipForWritingMode(overflowRect);
+    return overflowRect.maxY();
+}
+
+LayoutUnit RenderLayer::overflowLeft() const
+{
+    RenderBox* box = renderBox();
+    LayoutRect overflowRect(box->layoutOverflowRect());
+    box->flipForWritingMode(overflowRect);
+    return overflowRect.x();
+}
+
+LayoutUnit RenderLayer::overflowRight() const
+{
+    RenderBox* box = renderBox();
+    LayoutRect overflowRect(box->layoutOverflowRect());
+    box->flipForWritingMode(overflowRect);
+    return overflowRect.maxX();
+}
+
+void RenderLayer::computeScrollDimensions()
+{
+    RenderBox* box = renderBox();
+    ASSERT(box);
+
+    m_scrollDimensionsDirty = false;
+
+    m_scrollSize.setWidth(overflowRight() - overflowLeft());
+    m_scrollSize.setHeight(overflowBottom() - overflowTop());
+
+    int scrollableLeftOverflow = overflowLeft() - box->borderLeft();
+    int scrollableTopOverflow = overflowTop() - box->borderTop();
+    setScrollOrigin(IntPoint(-scrollableLeftOverflow, -scrollableTopOverflow));
+}
+
+bool RenderLayer::hasScrollableHorizontalOverflow() const
+{
+    return hasHorizontalOverflow() && renderBox()->scrollsOverflowX();
+}
+
+bool RenderLayer::hasScrollableVerticalOverflow() const
+{
+    return hasVerticalOverflow() && renderBox()->scrollsOverflowY();
+}
+
+bool RenderLayer::hasHorizontalOverflow() const
+{
+    ASSERT(!m_scrollDimensionsDirty);
+
+    return scrollWidth() > renderBox()->pixelSnappedClientWidth();
+}
+
+bool RenderLayer::hasVerticalOverflow() const
+{
+    ASSERT(!m_scrollDimensionsDirty);
+
+    return scrollHeight() > renderBox()->pixelSnappedClientHeight();
+}
+
+void RenderLayer::updateScrollbarsAfterLayout()
+{
+    RenderBox* box = renderBox();
+    ASSERT(box);
+
+    // List box parts handle the scrollbars by themselves so we have nothing to do.
+    if (box->style()->appearance() == ListboxPart)
+        return;
+
+    bool hasHorizontalOverflow = this->hasHorizontalOverflow();
+    bool hasVerticalOverflow = this->hasVerticalOverflow();
+
+    // overflow:scroll should just enable/disable.
+    if (renderer()->style()->overflowX() == OSCROLL)
+        m_hBar->setEnabled(hasHorizontalOverflow);
+    if (renderer()->style()->overflowY() == OSCROLL)
+        m_vBar->setEnabled(hasVerticalOverflow);
+
+    // overflow:auto may need to lay out again if scrollbars got added/removed.
+    bool autoHorizontalScrollBarChanged = box->hasAutoHorizontalScrollbar() && (hasHorizontalScrollbar() != hasHorizontalOverflow);
+    bool autoVerticalScrollBarChanged = box->hasAutoVerticalScrollbar() && (hasVerticalScrollbar() != hasVerticalOverflow);
+
+    if (autoHorizontalScrollBarChanged || autoVerticalScrollBarChanged) {
+        if (box->hasAutoHorizontalScrollbar())
+            setHasHorizontalScrollbar(hasHorizontalOverflow);
+        if (box->hasAutoVerticalScrollbar())
+            setHasVerticalScrollbar(hasVerticalOverflow);
+
+        updateSelfPaintingLayer();
+
+        // Force an update since we know the scrollbars have changed things.
+        if (renderer()->document()->hasAnnotatedRegions())
+            renderer()->document()->setAnnotatedRegionsDirty(true);
+
+        renderer()->repaint();
+
+        if (renderer()->style()->overflowX() == OAUTO || renderer()->style()->overflowY() == OAUTO) {
+            if (!m_inOverflowRelayout) {
+                // Our proprietary overflow: overlay value doesn't trigger a layout.
+                m_inOverflowRelayout = true;
+                renderer()->setNeedsLayout(true, MarkOnlyThis);
+                if (renderer()->isRenderBlock()) {
+                    RenderBlock* block = toRenderBlock(renderer());
+                    block->scrollbarsChanged(autoHorizontalScrollBarChanged, autoVerticalScrollBarChanged);
+                    block->layoutBlock(true);
+                } else
+                    renderer()->layout();
+                m_inOverflowRelayout = false;
+            }
+        }
+    }
+
+    // Set up the range (and page step/line step).
+    if (m_hBar) {
+        int clientWidth = box->pixelSnappedClientWidth();
+        int pageStep = max(max<int>(clientWidth * Scrollbar::minFractionToStepWhenPaging(), clientWidth - Scrollbar::maxOverlapBetweenPages()), 1);
+        m_hBar->setSteps(Scrollbar::pixelsPerLineStep(), pageStep);
+        m_hBar->setProportion(clientWidth, m_scrollSize.width());
+    }
+    if (m_vBar) {
+        int clientHeight = box->pixelSnappedClientHeight();
+        int pageStep = max(max<int>(clientHeight * Scrollbar::minFractionToStepWhenPaging(), clientHeight - Scrollbar::maxOverlapBetweenPages()), 1);
+        m_vBar->setSteps(Scrollbar::pixelsPerLineStep(), pageStep);
+        m_vBar->setProportion(clientHeight, m_scrollSize.height());
+    }
+
+    updateScrollableAreaSet(hasScrollableHorizontalOverflow() || hasScrollableVerticalOverflow());
+}
+
+void RenderLayer::updateScrollInfoAfterLayout()
+{
+    RenderBox* box = renderBox();
+    if (!box)
+        return;
+
+    m_scrollDimensionsDirty = true;
+    IntSize originalScrollOffset = scrollOffset();
+
+    computeScrollDimensions();
+
+    if (box->style()->overflowX() != OMARQUEE) {
+        // Layout may cause us to be at 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).
+        IntSize clampedScrollOffset = clampScrollOffset(scrollOffset());
+        if (clampedScrollOffset != scrollOffset())
+            scrollToOffset(clampedScrollOffset);
+    }
+
+    updateScrollbarsAfterLayout();
+
+    if (originalScrollOffset != scrollOffset())
+        scrollToOffsetWithoutAnimation(IntPoint(scrollOffset()));
+
+    // Composited scrolling may need to be enabled or disabled if the amount of overflow changed.
+    if (renderer()->view() && compositor()->updateLayerCompositingState(this))
+        compositor()->setCompositingLayersNeedRebuild();
+}
+
+bool RenderLayer::overflowControlsIntersectRect(const IntRect& localRect) const
+{
+    const IntRect borderBox = renderBox()->pixelSnappedBorderBoxRect();
+
+    if (rectForHorizontalScrollbar(borderBox).intersects(localRect))
+        return true;
+
+    if (rectForVerticalScrollbar(borderBox).intersects(localRect))
+        return true;
+
+    if (scrollCornerRect().intersects(localRect))
+        return true;
+    
+    if (resizerCornerRect(this, borderBox).intersects(localRect))
+        return true;
+
+    return false;
+}
+
+void RenderLayer::paintOverflowControls(GraphicsContext* context, const IntPoint& paintOffset, const IntRect& damageRect, bool paintingOverlayControls)
+{
+    // Don't do anything if we have no overflow.
+    if (!renderer()->hasOverflowClip())
+        return;
+
+    // Overlay scrollbars paint in a second pass through the layer tree so that they will paint
+    // on top of everything else. If this is the normal painting pass, paintingOverlayControls
+    // will be false, and we should just tell the root layer that there are overlay scrollbars
+    // that need to be painted. That will cause the second pass through the layer tree to run,
+    // and we'll paint the scrollbars then. In the meantime, cache tx and ty so that the 
+    // second pass doesn't need to re-enter the RenderTree to get it right.
+    if (hasOverlayScrollbars() && !paintingOverlayControls) {
+        m_cachedOverlayScrollbarOffset = paintOffset;
+        // It's not necessary to do the second pass if the scrollbars paint into layers.
+        if ((m_hBar && layerForHorizontalScrollbar()) || (m_vBar && layerForVerticalScrollbar()))
+            return;
+        IntRect localDamgeRect = damageRect;
+        localDamgeRect.moveBy(-paintOffset);
+        if (!overflowControlsIntersectRect(localDamgeRect))
+            return;
+
+        RenderView* renderView = renderer()->view();
+
+        RenderLayer* paintingRoot = 0;
+        paintingRoot = enclosingCompositingLayer();
+        if (!paintingRoot)
+            paintingRoot = renderView->layer();
+
+        paintingRoot->setContainsDirtyOverlayScrollbars(true);
+        return;
+    }
+
+    // This check is required to avoid painting custom CSS scrollbars twice.
+    if (paintingOverlayControls && !hasOverlayScrollbars())
+        return;
+
+    IntPoint adjustedPaintOffset = paintOffset;
+    if (paintingOverlayControls)
+        adjustedPaintOffset = m_cachedOverlayScrollbarOffset;
+
+    // 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(toIntSize(adjustedPaintOffset));
+
+    // Now that we're sure the scrollbars are in the right place, paint them.
+    if (m_hBar && !layerForHorizontalScrollbar())
+        m_hBar->paint(context, damageRect);
+    if (m_vBar && !layerForVerticalScrollbar())
+        m_vBar->paint(context, damageRect);
+
+    if (layerForScrollCorner())
+        return;
+
+    // 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, adjustedPaintOffset, damageRect);
+    
+    // Paint our resizer last, since it sits on top of the scroll corner.
+    paintResizer(context, adjustedPaintOffset, damageRect);
+}
+
+void RenderLayer::paintScrollCorner(GraphicsContext* context, const IntPoint& paintOffset, const IntRect& damageRect)
+{
+    RenderBox* box = renderBox();
+    ASSERT(box);
+
+    IntRect absRect = scrollCornerRect();
+    absRect.moveBy(paintOffset);
+    if (!absRect.intersects(damageRect))
+        return;
+
+    if (context->updatingControlTints()) {
+        updateScrollCornerStyle();
+        return;
+    }
+
+    if (m_scrollCorner) {
+        m_scrollCorner->paintIntoRect(context, paintOffset, absRect);
+        return;
+    }
+
+    // We don't want to paint white if we have overlay scrollbars, since we need
+    // to see what is behind it.
+    if (!hasOverlayScrollbars())
+        context->fillRect(absRect, Color::white, box->style()->colorSpace());
+}
+
+void RenderLayer::drawPlatformResizerImage(GraphicsContext* context, IntRect resizerCornerRect)
+{
+    float deviceScaleFactor = WebCore::deviceScaleFactor(renderer()->frame());
+
+    RefPtr<Image> resizeCornerImage;
+    IntSize cornerResizerSize;
+    if (deviceScaleFactor >= 2) {
+        DEFINE_STATIC_LOCAL(Image*, resizeCornerImageHiRes, (Image::loadPlatformResource("textAreaResizeCorner@2x").leakRef()));
+        resizeCornerImage = resizeCornerImageHiRes;
+        cornerResizerSize = resizeCornerImage->size();
+        cornerResizerSize.scale(0.5f);
+    } else {
+        DEFINE_STATIC_LOCAL(Image*, resizeCornerImageLoRes, (Image::loadPlatformResource("textAreaResizeCorner").leakRef()));
+        resizeCornerImage = resizeCornerImageLoRes;
+        cornerResizerSize = resizeCornerImage->size();
+    }
+
+    if (renderer()->style()->shouldPlaceBlockDirectionScrollbarOnLogicalLeft()) {
+        context->save();
+        context->translate(resizerCornerRect.x() + cornerResizerSize.width(), resizerCornerRect.y() + resizerCornerRect.height() - cornerResizerSize.height());
+        context->scale(FloatSize(-1.0, 1.0));
+        context->drawImage(resizeCornerImage.get(), renderer()->style()->colorSpace(), IntRect(IntPoint(), cornerResizerSize));
+        context->restore();
+        return;
+    }
+    IntRect imageRect(resizerCornerRect.maxXMaxYCorner() - cornerResizerSize, cornerResizerSize);
+    context->drawImage(resizeCornerImage.get(), renderer()->style()->colorSpace(), imageRect);
+}
+
+void RenderLayer::paintResizer(GraphicsContext* context, const IntPoint& paintOffset, const IntRect& damageRect)
+{
+    if (renderer()->style()->resize() == RESIZE_NONE)
+        return;
+
+    RenderBox* box = renderBox();
+    ASSERT(box);
+
+    IntRect absRect = resizerCornerRect(this, box->pixelSnappedBorderBoxRect());
+    absRect.moveBy(paintOffset);
+    if (!absRect.intersects(damageRect))
+        return;
+
+    if (context->updatingControlTints()) {
+        updateResizerStyle();
+        return;
+    }
+    
+    if (m_resizer) {
+        m_resizer->paintIntoRect(context, paintOffset, absRect);
+        return;
+    }
+
+    drawPlatformResizerImage(context, absRect);
+
+    // 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 (!hasOverlayScrollbars() && (m_vBar || m_hBar)) {
+        GraphicsContextStateSaver stateSaver(*context);
+        context->clip(absRect);
+        IntRect largerCorner = absRect;
+        largerCorner.setSize(IntSize(largerCorner.width() + 1, largerCorner.height() + 1));
+        context->setStrokeColor(Color(makeRGB(217, 217, 217)), ColorSpaceDeviceRGB);
+        context->setStrokeThickness(1.0f);
+        context->setFillColor(Color::transparent, ColorSpaceDeviceRGB);
+        context->drawRect(largerCorner);
+    }
+}
+
+bool RenderLayer::isPointInResizeControl(const IntPoint& absolutePoint) const
+{
+    if (!canResize())
+        return false;
+    
+    RenderBox* box = renderBox();
+    ASSERT(box);
+
+    IntPoint localPoint = roundedIntPoint(absoluteToContents(absolutePoint));
+
+    IntRect localBounds(0, 0, box->pixelSnappedWidth(), box->pixelSnappedHeight());
+    return resizerCornerRect(this, localBounds).contains(localPoint);
+}
+
+bool RenderLayer::hitTestOverflowControls(HitTestResult& result, const IntPoint& localPoint)
+{
+    if (!m_hBar && !m_vBar && !canResize())
+        return false;
+
+    RenderBox* box = renderBox();
+    ASSERT(box);
+    
+    IntRect resizeControlRect;
+    if (renderer()->style()->resize() != RESIZE_NONE) {
+        resizeControlRect = resizerCornerRect(this, box->pixelSnappedBorderBoxRect());
+        if (resizeControlRect.contains(localPoint))
+            return true;
+    }
+
+    int resizeControlSize = max(resizeControlRect.height(), 0);
+
+    // FIXME: We should hit test the m_scrollCorner and pass it back through the result.
+
+    if (m_vBar && m_vBar->shouldParticipateInHitTesting()) {
+        LayoutRect vBarRect(verticalScrollbarStart(0, box->width()),
+                            box->borderTop(),
+                            m_vBar->width(),
+                            box->height() - (box->borderTop() + box->borderBottom()) - (m_hBar ? m_hBar->height() : resizeControlSize));
+        if (vBarRect.contains(localPoint)) {
+            result.setScrollbar(m_vBar.get());
+            return true;
+        }
+    }
+
+    resizeControlSize = max(resizeControlRect.width(), 0);
+    if (m_hBar && m_hBar->shouldParticipateInHitTesting()) {
+        LayoutRect hBarRect(horizontalScrollbarStart(0),
+                            box->height() - box->borderBottom() - m_hBar->height(),
+                            box->width() - (box->borderLeft() + box->borderRight()) - (m_vBar ? m_vBar->width() : resizeControlSize),
+                            m_hBar->height());
+        if (hBarRect.contains(localPoint)) {
+            result.setScrollbar(m_hBar.get());
+            return true;
+        }
+    }
+
+    return false;
+}
+
+bool RenderLayer::scroll(ScrollDirection direction, ScrollGranularity granularity, float multiplier)
+{
+    return ScrollableArea::scroll(direction, granularity, multiplier);
+}
+
+void RenderLayer::paint(GraphicsContext* context, const LayoutRect& damageRect, PaintBehavior paintBehavior, RenderObject* paintingRoot, RenderRegion* region, PaintLayerFlags paintFlags)
+{
+    OverlapTestRequestMap overlapTestRequests;
+
+    LayerPaintingInfo paintingInfo(this, enclosingIntRect(damageRect), paintBehavior, LayoutSize(), paintingRoot, region, &overlapTestRequests);
+    paintLayer(context, paintingInfo, paintFlags);
+
+    OverlapTestRequestMap::iterator end = overlapTestRequests.end();
+    for (OverlapTestRequestMap::iterator it = overlapTestRequests.begin(); it != end; ++it)
+        it->key->setOverlapTestResult(false);
+}
+
+void RenderLayer::paintOverlayScrollbars(GraphicsContext* context, const LayoutRect& damageRect, PaintBehavior paintBehavior, RenderObject* paintingRoot)
+{
+    if (!m_containsDirtyOverlayScrollbars)
+        return;
+
+    LayerPaintingInfo paintingInfo(this, enclosingIntRect(damageRect), paintBehavior, LayoutSize(), paintingRoot);
+    paintLayer(context, paintingInfo, PaintLayerPaintingOverlayScrollbars);
+
+    m_containsDirtyOverlayScrollbars = false;
+}
+
+#ifndef DISABLE_ROUNDED_CORNER_CLIPPING
+static bool inContainingBlockChain(RenderLayer* startLayer, RenderLayer* endLayer)
+{
+    if (startLayer == endLayer)
+        return true;
+    
+    RenderView* view = startLayer->renderer()->view();
+    for (RenderBlock* currentBlock = startLayer->renderer()->containingBlock(); currentBlock && currentBlock != view; currentBlock = currentBlock->containingBlock()) {
+        if (currentBlock->layer() == endLayer)
+            return true;
+    }
+    
+    return false;
+}
+#endif
+
+void RenderLayer::clipToRect(RenderLayer* rootLayer, GraphicsContext* context, const LayoutRect& paintDirtyRect, const ClipRect& clipRect,
+                             BorderRadiusClippingRule rule)
+{
+    if (clipRect.rect() == paintDirtyRect)
+        return;
+    context->save();
+    context->clip(pixelSnappedIntRect(clipRect.rect()));
+    
+    if (!clipRect.hasRadius())
+        return;
+
+#ifndef DISABLE_ROUNDED_CORNER_CLIPPING
+    // If the clip rect has been tainted by a border radius, then we have to walk up our layer chain applying the clips from
+    // any layers with overflow. The condition for being able to apply these clips is that the overflow object be in our
+    // containing block chain so we check that also.
+    for (RenderLayer* layer = rule == IncludeSelfForBorderRadius ? this : parent(); layer; layer = layer->parent()) {
+        if (layer->renderer()->hasOverflowClip() && layer->renderer()->style()->hasBorderRadius() && inContainingBlockChain(this, layer)) {
+                LayoutPoint delta;
+                layer->convertToLayerCoords(rootLayer, delta);
+                context->clipRoundedRect(layer->renderer()->style()->getRoundedInnerBorderFor(LayoutRect(delta, layer->size())));
+        }
+
+        if (layer == rootLayer)
+            break;
+    }
+#endif
+}
+
+void RenderLayer::restoreClip(GraphicsContext* context, const LayoutRect& paintDirtyRect, const ClipRect& clipRect)
+{
+    if (clipRect.rect() == paintDirtyRect)
+        return;
+    context->restore();
+}
+
+static void performOverlapTests(OverlapTestRequestMap& overlapTestRequests, const RenderLayer* rootLayer, const RenderLayer* layer)
+{
+    Vector<OverlapTestRequestClient*> overlappedRequestClients;
+    OverlapTestRequestMap::iterator end = overlapTestRequests.end();
+    LayoutRect boundingBox = layer->boundingBox(rootLayer);
+    for (OverlapTestRequestMap::iterator it = overlapTestRequests.begin(); it != end; ++it) {
+        if (!boundingBox.intersects(it->value))
+            continue;
+
+        it->key->setOverlapTestResult(true);
+        overlappedRequestClients.append(it->key);
+    }
+    for (size_t i = 0; i < overlappedRequestClients.size(); ++i)
+        overlapTestRequests.remove(overlappedRequestClients[i]);
+}
+
+static bool shouldDoSoftwarePaint(const RenderLayer* layer, bool paintingReflection)
+{
+    return paintingReflection && !layer->has3DTransform();
+}
+    
+static inline bool shouldSuppressPaintingLayer(RenderLayer* layer)
+{
+    // Avoid painting descendants of the root layer 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 (layer->renderer()->document()->didLayoutWithPendingStylesheets() && !layer->isRootLayer() && !layer->renderer()->isRoot())
+        return true;
+
+    return false;
+}
+
+void RenderLayer::paintLayer(GraphicsContext* context, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags)
+{
+    if (isComposited()) {
+        // The updatingControlTints() painting pass goes through compositing layers,
+        // but we need to ensure that we don't cache clip rects computed with the wrong root in this case.
+        if (context->updatingControlTints() || (paintingInfo.paintBehavior & PaintBehaviorFlattenCompositingLayers))
+            paintFlags |= PaintLayerTemporaryClipRects;
+        else if (!backing()->paintsIntoWindow()
+            && !backing()->paintsIntoCompositedAncestor()
+            && !shouldDoSoftwarePaint(this, paintFlags & PaintLayerPaintingReflection)) {
+            // If this RenderLayer should paint into its backing, that will be done via RenderLayerBacking::paintIntoLayer().
+            return;
+        }
+    } else if (viewportConstrainedNotCompositedReason() == NotCompositedForBoundsOutOfView) {
+        // Don't paint out-of-view viewport constrained layers (when doing prepainting) because they will never be visible
+        // unless their position or viewport size is changed.
+        return;
+    }
+
+    // Non self-painting leaf layers don't need to be painted as their renderer() should properly paint itself.
+    if (!isSelfPaintingLayer() && !hasSelfPaintingLayerDescendant())
+        return;
+
+    if (shouldSuppressPaintingLayer(this))
+        return;
+    
+    // If this layer is totally invisible then there is nothing to paint.
+    if (!renderer()->opacity())
+        return;
+
+    if (paintsWithTransparency(paintingInfo.paintBehavior))
+        paintFlags |= PaintLayerHaveTransparency;
+
+    // PaintLayerAppliedTransform is used in RenderReplica, to avoid applying the transform twice.
+    if (paintsWithTransform(paintingInfo.paintBehavior) && !(paintFlags & PaintLayerAppliedTransform)) {
+        TransformationMatrix layerTransform = renderableTransform(paintingInfo.paintBehavior);
+        // If the transform can't be inverted, then don't paint anything.
+        if (!layerTransform.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, assuming there is a parent
+        if (paintFlags & PaintLayerHaveTransparency) {
+            if (parent())
+                parent()->beginTransparencyLayers(context, paintingInfo.rootLayer, paintingInfo.paintDirtyRect, paintingInfo.paintBehavior);
+            else
+                beginTransparencyLayers(context, paintingInfo.rootLayer, paintingInfo.paintDirtyRect, paintingInfo.paintBehavior);
+        }
+
+        if (enclosingPaginationLayer()) {
+            paintTransformedLayerIntoFragments(context, paintingInfo, paintFlags);
+            return;
+        }
+
+        // Make sure the parent's clip rects have been calculated.
+        ClipRect clipRect = paintingInfo.paintDirtyRect;
+        if (parent()) {
+            ClipRectsContext clipRectsContext(paintingInfo.rootLayer, paintingInfo.region, (paintFlags & PaintLayerTemporaryClipRects) ? TemporaryClipRects : PaintingClipRects,
+                IgnoreOverlayScrollbarSize, (paintFlags & PaintLayerPaintingOverflowContents) ? IgnoreOverflowClip : RespectOverflowClip);
+            clipRect = backgroundClipRect(clipRectsContext);
+            clipRect.intersect(paintingInfo.paintDirtyRect);
+        
+            // Push the parent coordinate space's clip.
+            parent()->clipToRect(paintingInfo.rootLayer, context, paintingInfo.paintDirtyRect, clipRect);
+        }
+
+        paintLayerByApplyingTransform(context, paintingInfo, paintFlags);
+
+        // Restore the clip.
+        if (parent())
+            parent()->restoreClip(context, paintingInfo.paintDirtyRect, clipRect);
+
+        return;
+    }
+    
+    paintLayerContentsAndReflection(context, paintingInfo, paintFlags);
+}
+
+void RenderLayer::paintLayerContentsAndReflection(GraphicsContext* context, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags)
+{
+    ASSERT(isSelfPaintingLayer() || hasSelfPaintingLayerDescendant());
+
+    PaintLayerFlags localPaintFlags = paintFlags & ~(PaintLayerAppliedTransform);
+
+    // Paint the reflection first if we have one.
+    if (m_reflection && !m_paintingInsideReflection) {
+        // Mark that we are now inside replica painting.
+        m_paintingInsideReflection = true;
+        reflectionLayer()->paintLayer(context, paintingInfo, localPaintFlags | PaintLayerPaintingReflection);
+        m_paintingInsideReflection = false;
+    }
+
+    localPaintFlags |= PaintLayerPaintingCompositingAllPhases;
+    paintLayerContents(context, paintingInfo, localPaintFlags);
+}
+
+void RenderLayer::paintLayerContents(GraphicsContext* context, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags)
+{
+    ASSERT(isSelfPaintingLayer() || hasSelfPaintingLayerDescendant());
+
+    PaintLayerFlags localPaintFlags = paintFlags & ~(PaintLayerAppliedTransform);
+    bool haveTransparency = localPaintFlags & PaintLayerHaveTransparency;
+    bool isSelfPaintingLayer = this->isSelfPaintingLayer();
+    bool isPaintingOverlayScrollbars = paintFlags & PaintLayerPaintingOverlayScrollbars;
+    bool isPaintingScrollingContent = paintFlags & PaintLayerPaintingCompositingScrollingPhase;
+    bool isPaintingCompositedForeground = paintFlags & PaintLayerPaintingCompositingForegroundPhase;
+    bool isPaintingCompositedBackground = paintFlags & PaintLayerPaintingCompositingBackgroundPhase;
+    bool isPaintingOverflowContents = paintFlags & PaintLayerPaintingOverflowContents;
+    // Outline always needs to be painted even if we have no visible content. Also,
+    // the outline is painted in the background phase during composited scrolling.
+    // If it were painted in the foreground phase, it would move with the scrolled
+    // content. When not composited scrolling, the outline is painted in the
+    // foreground phase. Since scrolled contents are moved by repainting in this
+    // case, the outline won't get 'dragged along'.
+    bool shouldPaintOutline = isSelfPaintingLayer && !isPaintingOverlayScrollbars
+        && ((isPaintingScrollingContent && isPaintingCompositedBackground)
+        || (!isPaintingScrollingContent && isPaintingCompositedForeground));
+    bool shouldPaintContent = m_hasVisibleContent && isSelfPaintingLayer && !isPaintingOverlayScrollbars;
+
+    GraphicsContext* transparencyLayerContext = context;
+    
+    if (localPaintFlags & PaintLayerPaintingRootBackgroundOnly && !renderer()->isRenderView() && !renderer()->isRoot())
+        return;
+
+    // Ensure our lists are up-to-date.
+    updateLayerListsIfNeeded();
+
+    LayoutPoint offsetFromRoot;
+    convertToLayerCoords(paintingInfo.rootLayer, offsetFromRoot);
+
+    IntRect rootRelativeBounds;
+    bool rootRelativeBoundsComputed = false;
+
+    bool didQuantizeFonts = true;
+    bool scrollingOnMainThread = true;
+    Frame* frame = renderer()->frame();
+
+    // FIXME: We shouldn't have to disable subpixel quantization for overflow clips or subframes once we scroll those
+    // things on the scrolling thread.
+    bool needToAdjustSubpixelQuantization = scrollingOnMainThread || (renderer()->hasOverflowClip() && !usesCompositedScrolling()) || (frame && frame->ownerElement());
+    if (needToAdjustSubpixelQuantization) {
+        didQuantizeFonts = context->shouldSubpixelQuantizeFonts();
+        context->setShouldSubpixelQuantizeFonts(false);
+    }
+
+    // Apply clip-path to context.
+    bool hasClipPath = false;
+    RenderStyle* style = renderer()->style();
+    if (renderer()->hasClipPath() && !context->paintingDisabled() && style) {
+        ASSERT(style->clipPath());
+        if (style->clipPath()->getOperationType() == ClipPathOperation::SHAPE) {
+            hasClipPath = true;
+            context->save();
+            ShapeClipPathOperation* clipPath = static_cast<ShapeClipPathOperation*>(style->clipPath());
+
+            if (!rootRelativeBoundsComputed) {
+                rootRelativeBounds = calculateLayerBounds(paintingInfo.rootLayer, &offsetFromRoot, 0);
+                rootRelativeBoundsComputed = true;
+            }
+
+            context->clipPath(clipPath->path(rootRelativeBounds), clipPath->windRule());
+        }
+#if ENABLE(SVG)
+        else if (style->clipPath()->getOperationType() == ClipPathOperation::REFERENCE) {
+            ReferenceClipPathOperation* referenceClipPathOperation = static_cast<ReferenceClipPathOperation*>(style->clipPath());
+            Document* document = renderer()->document();
+            // FIXME: It doesn't work with forward or external SVG references (https://bugs.webkit.org/show_bug.cgi?id=90405)
+            Element* element = document ? document->getElementById(referenceClipPathOperation->fragment()) : 0;
+            if (element && element->hasTagName(SVGNames::clipPathTag) && element->renderer()) {
+                if (!rootRelativeBoundsComputed) {
+                    rootRelativeBounds = calculateLayerBounds(paintingInfo.rootLayer, &offsetFromRoot, 0);
+                    rootRelativeBoundsComputed = true;
+                }
+
+                // FIXME: This should use a safer cast such as toRenderSVGResourceContainer().
+                static_cast<RenderSVGResourceClipper*>(element->renderer())->applyClippingToContext(renderer(), rootRelativeBounds, paintingInfo.paintDirtyRect, context);
+            }
+        }
+#endif
+    }
+
+    LayerPaintingInfo localPaintingInfo(paintingInfo);
+    FilterEffectRendererHelper filterPainter(filterRenderer() && paintsWithFilters());
+    if (filterPainter.haveFilterEffect() && !context->paintingDisabled()) {
+        RenderLayerFilterInfo* filterInfo = this->filterInfo();
+        ASSERT(filterInfo);
+        LayoutRect filterRepaintRect = filterInfo->dirtySourceRect();
+        filterRepaintRect.move(offsetFromRoot.x(), offsetFromRoot.y());
+
+        if (!rootRelativeBoundsComputed) {
+            rootRelativeBounds = calculateLayerBounds(paintingInfo.rootLayer, &offsetFromRoot, 0);
+            rootRelativeBoundsComputed = true;
+        }
+
+        if (filterPainter.prepareFilterEffect(this, rootRelativeBounds, paintingInfo.paintDirtyRect, filterRepaintRect)) {
+            // Now we know for sure, that the source image will be updated, so we can revert our tracking repaint rect back to zero.
+            filterInfo->resetDirtySourceRect();
+
+            // Rewire the old context to a memory buffer, so that we can capture the contents of the layer.
+            // NOTE: We saved the old context in the "transparencyLayerContext" local variable, to be able to start a transparency layer
+            // on the original context and avoid duplicating "beginFilterEffect" after each transparency layer call. Also, note that 
+            // beginTransparencyLayers will only create a single lazy transparency layer, even though it is called twice in this method.
+            context = filterPainter.beginFilterEffect(context);
+
+            // Check that we didn't fail to allocate the graphics context for the offscreen buffer.
+            if (filterPainter.hasStartedFilterEffect()) {
+                localPaintingInfo.paintDirtyRect = filterPainter.repaintRect();
+                // If the filter needs the full source image, we need to avoid using the clip rectangles.
+                // Otherwise, if for example this layer has overflow:hidden, a drop shadow will not compute correctly.
+                // Note that we will still apply the clipping on the final rendering of the filter.
+                localPaintingInfo.clipToDirtyRect = !filterRenderer()->hasFilterThatMovesPixels();
+            }
+        }
+    }
+
+    if (filterPainter.hasStartedFilterEffect() && haveTransparency) {
+        // If we have a filter and transparency, we have to eagerly start a transparency layer here, rather than risk a child layer lazily starts one with the wrong context.
+        beginTransparencyLayers(transparencyLayerContext, localPaintingInfo.rootLayer, paintingInfo.paintDirtyRect, localPaintingInfo.paintBehavior);
+    }
+
+    // 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 descend through the renderers.
+    RenderObject* paintingRootForRenderer = 0;
+    if (localPaintingInfo.paintingRoot && !renderer()->isDescendantOf(localPaintingInfo.paintingRoot))
+        paintingRootForRenderer = localPaintingInfo.paintingRoot;
+
+    if (localPaintingInfo.overlapTestRequests && isSelfPaintingLayer)
+        performOverlapTests(*localPaintingInfo.overlapTestRequests, localPaintingInfo.rootLayer, this);
+
+    bool forceBlackText = localPaintingInfo.paintBehavior & PaintBehaviorForceBlackText;
+    bool selectionOnly  = localPaintingInfo.paintBehavior & PaintBehaviorSelectionOnly;
+    
+    PaintBehavior paintBehavior = PaintBehaviorNormal;
+    if (localPaintFlags & PaintLayerPaintingSkipRootBackground)
+        paintBehavior |= PaintBehaviorSkipRootBackground;
+    else if (localPaintFlags & PaintLayerPaintingRootBackgroundOnly)
+        paintBehavior |= PaintBehaviorRootBackgroundOnly;
+
+    LayerFragments layerFragments;
+    if (shouldPaintContent || shouldPaintOutline || isPaintingOverlayScrollbars) {
+        // Collect the fragments. This will compute the clip rectangles and paint offsets for each layer fragment, as well as whether or not the content of each
+        // fragment should paint.
+        collectFragments(layerFragments, localPaintingInfo.rootLayer, localPaintingInfo.region, localPaintingInfo.paintDirtyRect,
+            (localPaintFlags & PaintLayerTemporaryClipRects) ? TemporaryClipRects : PaintingClipRects, IgnoreOverlayScrollbarSize,
+            (isPaintingOverflowContents) ? IgnoreOverflowClip : RespectOverflowClip, &offsetFromRoot);
+        updatePaintingInfoForFragments(layerFragments, localPaintingInfo, localPaintFlags, shouldPaintContent, &offsetFromRoot);
+    }
+    
+    if (isPaintingCompositedBackground) {
+        // Paint only the backgrounds for all of the fragments of the layer.
+        if (shouldPaintContent && !selectionOnly)
+            paintBackgroundForFragments(layerFragments, context, transparencyLayerContext, paintingInfo.paintDirtyRect, haveTransparency,
+                localPaintingInfo, paintBehavior, paintingRootForRenderer);
+    }
+
+    // Now walk the sorted list of children with negative z-indices.
+    if ((isPaintingScrollingContent && isPaintingOverflowContents) || (!isPaintingScrollingContent && isPaintingCompositedBackground))
+        paintList(negZOrderList(), context, localPaintingInfo, localPaintFlags);
+    
+    if (isPaintingCompositedForeground) {
+        if (shouldPaintContent)
+            paintForegroundForFragments(layerFragments, context, transparencyLayerContext, paintingInfo.paintDirtyRect, haveTransparency,
+                localPaintingInfo, paintBehavior, paintingRootForRenderer, selectionOnly, forceBlackText);
+    }
+
+    if (shouldPaintOutline)
+        paintOutlineForFragments(layerFragments, context, localPaintingInfo, paintBehavior, paintingRootForRenderer);
+
+    if (isPaintingCompositedForeground) {
+        // Paint any child layers that have overflow.
+        paintList(m_normalFlowList.get(), context, localPaintingInfo, localPaintFlags);
+    
+        // Now walk the sorted list of children with positive z-indices.
+        paintList(posZOrderList(), context, localPaintingInfo, localPaintFlags);
+    }
+
+    if (isPaintingOverlayScrollbars)
+        paintOverflowControlsForFragments(layerFragments, context, localPaintingInfo);
+
+    if (filterPainter.hasStartedFilterEffect()) {
+        // Apply the correct clipping (ie. overflow: hidden).
+        // FIXME: It is incorrect to just clip to the damageRect here once multiple fragments are involved.
+        ClipRect backgroundRect = layerFragments.isEmpty() ? ClipRect() : layerFragments[0].backgroundRect;
+        clipToRect(localPaintingInfo.rootLayer, transparencyLayerContext, localPaintingInfo.paintDirtyRect, backgroundRect);
+        context = filterPainter.applyFilterEffect();
+        restoreClip(transparencyLayerContext, localPaintingInfo.paintDirtyRect, backgroundRect);
+    }
+    
+    // Make sure that we now use the original transparency context.
+    ASSERT(transparencyLayerContext == context);
+
+    if ((localPaintFlags & PaintLayerPaintingCompositingMaskPhase) && shouldPaintContent && renderer()->hasMask() && !selectionOnly) {
+        // Paint the mask for the fragments.
+        paintMaskForFragments(layerFragments, context, localPaintingInfo, paintingRootForRenderer);
+    }
+
+    // End our transparency layer
+    if (haveTransparency && m_usedTransparency && !m_paintingInsideReflection) {
+        context->endTransparencyLayer();
+        context->restore();
+        m_usedTransparency = false;
+    }
+
+    // Re-set this to whatever it was before we painted the layer.
+    if (needToAdjustSubpixelQuantization)
+        context->setShouldSubpixelQuantizeFonts(didQuantizeFonts);
+
+    if (hasClipPath)
+        context->restore();
+}
+
+void RenderLayer::paintLayerByApplyingTransform(GraphicsContext* context, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags, const LayoutPoint& translationOffset)
+{
+    // This involves subtracting out the position of the layer in our current coordinate space, but preserving
+    // the accumulated error for sub-pixel layout.
+    LayoutPoint delta;
+    convertToLayerCoords(paintingInfo.rootLayer, delta);
+    delta.moveBy(translationOffset);
+    TransformationMatrix transform(renderableTransform(paintingInfo.paintBehavior));
+    IntPoint roundedDelta = roundedIntPoint(delta);
+    transform.translateRight(roundedDelta.x(), roundedDelta.y());
+    LayoutSize adjustedSubPixelAccumulation = paintingInfo.subPixelAccumulation + (delta - roundedDelta);
+
+    // Apply the transform.
+    GraphicsContextStateSaver stateSaver(*context);
+    context->concatCTM(transform.toAffineTransform());
+
+    // Now do a paint with the root layer shifted to be us.
+    LayerPaintingInfo transformedPaintingInfo(this, enclosingIntRect(transform.inverse().mapRect(paintingInfo.paintDirtyRect)), paintingInfo.paintBehavior,
+        adjustedSubPixelAccumulation, paintingInfo.paintingRoot, paintingInfo.region, paintingInfo.overlapTestRequests);
+    paintLayerContentsAndReflection(context, transformedPaintingInfo, paintFlags);
+}
+
+void RenderLayer::paintList(Vector<RenderLayer*>* list, GraphicsContext* context, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags)
+{
+    if (!list)
+        return;
+
+    if (!hasSelfPaintingLayerDescendant())
+        return;
+
+#if !ASSERT_DISABLED
+    LayerListMutationDetector mutationChecker(this);
+#endif
+
+    for (size_t i = 0; i < list->size(); ++i) {
+        RenderLayer* childLayer = list->at(i);
+        if (!childLayer->isPaginated())
+            childLayer->paintLayer(context, paintingInfo, paintFlags);
+        else
+            paintPaginatedChildLayer(childLayer, context, paintingInfo, paintFlags);
+    }
+}
+
+void RenderLayer::collectFragments(LayerFragments& fragments, const RenderLayer* rootLayer, RenderRegion* region, const LayoutRect& dirtyRect,
+    ClipRectsType clipRectsType, OverlayScrollbarSizeRelevancy inOverlayScrollbarSizeRelevancy, ShouldRespectOverflowClip respectOverflowClip, const LayoutPoint* offsetFromRoot,
+    const LayoutRect* layerBoundingBox)
+{
+    if (!enclosingPaginationLayer() || hasTransform()) {
+        // For unpaginated layers, there is only one fragment.
+        LayerFragment fragment;
+        ClipRectsContext clipRectsContext(rootLayer, region, clipRectsType, inOverlayScrollbarSizeRelevancy, respectOverflowClip);
+        calculateRects(clipRectsContext, dirtyRect, fragment.layerBounds, fragment.backgroundRect, fragment.foregroundRect, fragment.outlineRect, offsetFromRoot);
+        fragments.append(fragment);
+        return;
+    }
+    
+    // Compute our offset within the enclosing pagination layer.
+    LayoutPoint offsetWithinPaginatedLayer;
+    convertToLayerCoords(enclosingPaginationLayer(), offsetWithinPaginatedLayer);
+    
+    // Calculate clip rects relative to the enclosingPaginationLayer. The purpose of this call is to determine our bounds clipped to intermediate
+    // layers between us and the pagination context. It's important to minimize the number of fragments we need to create and this helps with that.
+    ClipRectsContext paginationClipRectsContext(enclosingPaginationLayer(), region, clipRectsType, inOverlayScrollbarSizeRelevancy, respectOverflowClip);
+    LayoutRect layerBoundsInFlowThread;
+    ClipRect backgroundRectInFlowThread;
+    ClipRect foregroundRectInFlowThread;
+    ClipRect outlineRectInFlowThread;
+    calculateRects(paginationClipRectsContext, PaintInfo::infiniteRect(), layerBoundsInFlowThread, backgroundRectInFlowThread, foregroundRectInFlowThread,
+        outlineRectInFlowThread, &offsetWithinPaginatedLayer);
+    
+    // Take our bounding box within the flow thread and clip it.
+    LayoutRect layerBoundingBoxInFlowThread = layerBoundingBox ? *layerBoundingBox : boundingBox(enclosingPaginationLayer(), 0, &offsetWithinPaginatedLayer);
+    layerBoundingBoxInFlowThread.intersect(backgroundRectInFlowThread.rect());
+
+    // Shift the dirty rect into flow thread coordinates.
+    LayoutPoint offsetOfPaginationLayerFromRoot;
+    enclosingPaginationLayer()->convertToLayerCoords(rootLayer, offsetOfPaginationLayerFromRoot);
+    LayoutRect dirtyRectInFlowThread(dirtyRect);
+    dirtyRectInFlowThread.moveBy(-offsetOfPaginationLayerFromRoot);
+
+    // Tell the flow thread to collect the fragments. We pass enough information to create a minimal number of fragments based off the pages/columns
+    // that intersect the actual dirtyRect as well as the pages/columns that intersect our layer's bounding box.
+    RenderFlowThread* enclosingFlowThread = toRenderFlowThread(enclosingPaginationLayer()->renderer());
+    enclosingFlowThread->collectLayerFragments(fragments, layerBoundingBoxInFlowThread, dirtyRectInFlowThread);
+    
+    if (fragments.isEmpty())
+        return;
+    
+    // Get the parent clip rects of the pagination layer, since we need to intersect with that when painting column contents.
+    ClipRect ancestorClipRect = dirtyRect;
+    if (enclosingPaginationLayer()->parent()) {
+        ClipRectsContext clipRectsContext(rootLayer, region, clipRectsType, inOverlayScrollbarSizeRelevancy, respectOverflowClip);
+        ancestorClipRect = enclosingPaginationLayer()->backgroundClipRect(clipRectsContext);
+        ancestorClipRect.intersect(dirtyRect);
+    }
+
+    for (size_t i = 0; i < fragments.size(); ++i) {
+        LayerFragment& fragment = fragments.at(i);
+        
+        // Set our four rects with all clipping applied that was internal to the flow thread.
+        fragment.setRects(layerBoundsInFlowThread, backgroundRectInFlowThread, foregroundRectInFlowThread, outlineRectInFlowThread);
+        
+        // Shift to the root-relative physical position used when painting the flow thread in this fragment.
+        fragment.moveBy(fragment.paginationOffset + offsetOfPaginationLayerFromRoot);
+
+        // Intersect the fragment with our ancestor's background clip so that e.g., columns in an overflow:hidden block are
+        // properly clipped by the overflow.
+        fragment.intersect(ancestorClipRect.rect());
+        
+        // Now intersect with our pagination clip. This will typically mean we're just intersecting the dirty rect with the column
+        // clip, so the column clip ends up being all we apply.
+        fragment.intersect(fragment.paginationClip);
+    }
+}
+
+void RenderLayer::updatePaintingInfoForFragments(LayerFragments& fragments, const LayerPaintingInfo& localPaintingInfo, PaintLayerFlags localPaintFlags,
+    bool shouldPaintContent, const LayoutPoint* offsetFromRoot)
+{
+    ASSERT(offsetFromRoot);
+    for (size_t i = 0; i < fragments.size(); ++i) {
+        LayerFragment& fragment = fragments.at(i);
+        fragment.shouldPaintContent = shouldPaintContent;
+        if (this != localPaintingInfo.rootLayer || !(localPaintFlags & PaintLayerPaintingOverflowContents)) {
+            LayoutPoint newOffsetFromRoot = *offsetFromRoot + fragment.paginationOffset;
+            fragment.shouldPaintContent &= intersectsDamageRect(fragment.layerBounds, fragment.backgroundRect.rect(), localPaintingInfo.rootLayer, &newOffsetFromRoot);
+        }
+    }
+}
+
+void RenderLayer::paintTransformedLayerIntoFragments(GraphicsContext* context, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags)
+{
+    LayerFragments enclosingPaginationFragments;
+    LayoutPoint offsetOfPaginationLayerFromRoot;
+    LayoutRect transformedExtent = transparencyClipBox(this, enclosingPaginationLayer(), PaintingTransparencyClipBox, RootOfTransparencyClipBox, paintingInfo.paintBehavior);
+    enclosingPaginationLayer()->collectFragments(enclosingPaginationFragments, paintingInfo.rootLayer, paintingInfo.region, paintingInfo.paintDirtyRect,
+        (paintFlags & PaintLayerTemporaryClipRects) ? TemporaryClipRects : PaintingClipRects, IgnoreOverlayScrollbarSize,
+        (paintFlags & PaintLayerPaintingOverflowContents) ? IgnoreOverflowClip : RespectOverflowClip, &offsetOfPaginationLayerFromRoot, &transformedExtent);
+    
+    for (size_t i = 0; i < enclosingPaginationFragments.size(); ++i) {
+        const LayerFragment& fragment = enclosingPaginationFragments.at(i);
+        
+        // Apply the page/column clip for this fragment, as well as any clips established by layers in between us and
+        // the enclosing pagination layer.
+        LayoutRect clipRect = fragment.backgroundRect.rect();
+        
+        // Now compute the clips within a given fragment
+        if (parent() != enclosingPaginationLayer()) {
+            enclosingPaginationLayer()->convertToLayerCoords(paintingInfo.rootLayer, offsetOfPaginationLayerFromRoot);
+    
+            ClipRectsContext clipRectsContext(enclosingPaginationLayer(), paintingInfo.region, (paintFlags & PaintLayerTemporaryClipRects) ? TemporaryClipRects : PaintingClipRects,
+                IgnoreOverlayScrollbarSize, (paintFlags & PaintLayerPaintingOverflowContents) ? IgnoreOverflowClip : RespectOverflowClip);
+            LayoutRect parentClipRect = backgroundClipRect(clipRectsContext).rect();
+            parentClipRect.moveBy(fragment.paginationOffset + offsetOfPaginationLayerFromRoot);
+            clipRect.intersect(parentClipRect);
+        }
+
+        parent()->clipToRect(paintingInfo.rootLayer, context, paintingInfo.paintDirtyRect, clipRect);
+        paintLayerByApplyingTransform(context, paintingInfo, paintFlags, fragment.paginationOffset);
+        parent()->restoreClip(context, paintingInfo.paintDirtyRect, clipRect);
+    }
+}
+
+void RenderLayer::paintBackgroundForFragments(const LayerFragments& layerFragments, GraphicsContext* context, GraphicsContext* transparencyLayerContext,
+    const LayoutRect& transparencyPaintDirtyRect, bool haveTransparency, const LayerPaintingInfo& localPaintingInfo, PaintBehavior paintBehavior,
+    RenderObject* paintingRootForRenderer)
+{
+    for (size_t i = 0; i < layerFragments.size(); ++i) {
+        const LayerFragment& fragment = layerFragments.at(i);
+        if (!fragment.shouldPaintContent)
+            continue;
+
+        // Begin transparency layers lazily now that we know we have to paint something.
+        if (haveTransparency)
+            beginTransparencyLayers(transparencyLayerContext, localPaintingInfo.rootLayer, transparencyPaintDirtyRect, localPaintingInfo.paintBehavior);
+    
+        if (localPaintingInfo.clipToDirtyRect) {
+            // Paint our background first, before painting any child layers.
+            // Establish the clip used to paint our background.
+            clipToRect(localPaintingInfo.rootLayer, context, localPaintingInfo.paintDirtyRect, fragment.backgroundRect, DoNotIncludeSelfForBorderRadius); // Background painting will handle clipping to self.
+        }
+        
+        // Paint the background.
+        // FIXME: Eventually we will collect the region from the fragment itself instead of just from the paint info.
+        PaintInfo paintInfo(context, pixelSnappedIntRect(fragment.backgroundRect.rect()), PaintPhaseBlockBackground, paintBehavior, paintingRootForRenderer, localPaintingInfo.region, 0, 0, localPaintingInfo.rootLayer->renderer());
+        renderer()->paint(paintInfo, toPoint(fragment.layerBounds.location() - renderBoxLocation() + localPaintingInfo.subPixelAccumulation));
+
+        if (localPaintingInfo.clipToDirtyRect)
+            restoreClip(context, localPaintingInfo.paintDirtyRect, fragment.backgroundRect);
+    }
+}
+
+void RenderLayer::paintForegroundForFragments(const LayerFragments& layerFragments, GraphicsContext* context, GraphicsContext* transparencyLayerContext,
+    const LayoutRect& transparencyPaintDirtyRect, bool haveTransparency, const LayerPaintingInfo& localPaintingInfo, PaintBehavior paintBehavior,
+    RenderObject* paintingRootForRenderer, bool selectionOnly, bool forceBlackText)
+{
+    // Begin transparency if we have something to paint.
+    if (haveTransparency) {
+        for (size_t i = 0; i < layerFragments.size(); ++i) {
+            const LayerFragment& fragment = layerFragments.at(i);
+            if (fragment.shouldPaintContent && !fragment.foregroundRect.isEmpty()) {
+                beginTransparencyLayers(transparencyLayerContext, localPaintingInfo.rootLayer, transparencyPaintDirtyRect, localPaintingInfo.paintBehavior);
+                break;
+            }
+        }
+    }
+    
+    PaintBehavior localPaintBehavior = forceBlackText ? (PaintBehavior)PaintBehaviorForceBlackText : paintBehavior;
+
+    // Optimize clipping for the single fragment case.
+    bool shouldClip = localPaintingInfo.clipToDirtyRect && layerFragments.size() == 1 && layerFragments[0].shouldPaintContent && !layerFragments[0].foregroundRect.isEmpty();
+    if (shouldClip)
+        clipToRect(localPaintingInfo.rootLayer, context, localPaintingInfo.paintDirtyRect, layerFragments[0].foregroundRect);
+    
+    // We have to loop through every fragment multiple times, since we have to repaint in each specific phase in order for
+    // interleaving of the fragments to work properly.
+    paintForegroundForFragmentsWithPhase(selectionOnly ? PaintPhaseSelection : PaintPhaseChildBlockBackgrounds, layerFragments,
+        context, localPaintingInfo, localPaintBehavior, paintingRootForRenderer);
+    
+    if (!selectionOnly) {
+        paintForegroundForFragmentsWithPhase(PaintPhaseFloat, layerFragments, context, localPaintingInfo, localPaintBehavior, paintingRootForRenderer);
+        paintForegroundForFragmentsWithPhase(PaintPhaseForeground, layerFragments, context, localPaintingInfo, localPaintBehavior, paintingRootForRenderer);
+        paintForegroundForFragmentsWithPhase(PaintPhaseChildOutlines, layerFragments, context, localPaintingInfo, localPaintBehavior, paintingRootForRenderer);
+    }
+    
+    if (shouldClip)
+        restoreClip(context, localPaintingInfo.paintDirtyRect, layerFragments[0].foregroundRect);
+}
+
+void RenderLayer::paintForegroundForFragmentsWithPhase(PaintPhase phase, const LayerFragments& layerFragments, GraphicsContext* context,
+    const LayerPaintingInfo& localPaintingInfo, PaintBehavior paintBehavior, RenderObject* paintingRootForRenderer)
+{
+    bool shouldClip = localPaintingInfo.clipToDirtyRect && layerFragments.size() > 1;
+
+    for (size_t i = 0; i < layerFragments.size(); ++i) {
+        const LayerFragment& fragment = layerFragments.at(i);
+        if (!fragment.shouldPaintContent || fragment.foregroundRect.isEmpty())
+            continue;
+        
+        if (shouldClip)
+            clipToRect(localPaintingInfo.rootLayer, context, localPaintingInfo.paintDirtyRect, fragment.foregroundRect);
+    
+        PaintInfo paintInfo(context, pixelSnappedIntRect(fragment.foregroundRect.rect()), phase, paintBehavior, paintingRootForRenderer, localPaintingInfo.region, 0, 0, localPaintingInfo.rootLayer->renderer());
+        if (phase == PaintPhaseForeground)
+            paintInfo.overlapTestRequests = localPaintingInfo.overlapTestRequests;
+        renderer()->paint(paintInfo, toPoint(fragment.layerBounds.location() - renderBoxLocation() + localPaintingInfo.subPixelAccumulation));
+        
+        if (shouldClip)
+            restoreClip(context, localPaintingInfo.paintDirtyRect, fragment.foregroundRect);
+    }
+}
+
+void RenderLayer::paintOutlineForFragments(const LayerFragments& layerFragments, GraphicsContext* context, const LayerPaintingInfo& localPaintingInfo,
+    PaintBehavior paintBehavior, RenderObject* paintingRootForRenderer)
+{
+    for (size_t i = 0; i < layerFragments.size(); ++i) {
+        const LayerFragment& fragment = layerFragments.at(i);
+        if (fragment.outlineRect.isEmpty())
+            continue;
+    
+        // Paint our own outline
+        PaintInfo paintInfo(context, pixelSnappedIntRect(fragment.outlineRect.rect()), PaintPhaseSelfOutline, paintBehavior, paintingRootForRenderer, localPaintingInfo.region, 0, 0, localPaintingInfo.rootLayer->renderer());
+        clipToRect(localPaintingInfo.rootLayer, context, localPaintingInfo.paintDirtyRect, fragment.outlineRect, DoNotIncludeSelfForBorderRadius);
+        renderer()->paint(paintInfo, toPoint(fragment.layerBounds.location() - renderBoxLocation() + localPaintingInfo.subPixelAccumulation));
+        restoreClip(context, localPaintingInfo.paintDirtyRect, fragment.outlineRect);
+    }
+}
+
+void RenderLayer::paintMaskForFragments(const LayerFragments& layerFragments, GraphicsContext* context, const LayerPaintingInfo& localPaintingInfo,
+    RenderObject* paintingRootForRenderer)
+{
+    for (size_t i = 0; i < layerFragments.size(); ++i) {
+        const LayerFragment& fragment = layerFragments.at(i);
+        if (!fragment.shouldPaintContent)
+            continue;
+
+        if (localPaintingInfo.clipToDirtyRect)
+            clipToRect(localPaintingInfo.rootLayer, context, localPaintingInfo.paintDirtyRect, fragment.backgroundRect, DoNotIncludeSelfForBorderRadius); // Mask painting will handle clipping to self.
+        
+        // Paint the mask.
+        // FIXME: Eventually we will collect the region from the fragment itself instead of just from the paint info.
+        PaintInfo paintInfo(context, pixelSnappedIntRect(fragment.backgroundRect.rect()), PaintPhaseMask, PaintBehaviorNormal, paintingRootForRenderer, localPaintingInfo.region, 0, 0, localPaintingInfo.rootLayer->renderer());
+        renderer()->paint(paintInfo, toPoint(fragment.layerBounds.location() - renderBoxLocation() + localPaintingInfo.subPixelAccumulation));
+        
+        if (localPaintingInfo.clipToDirtyRect)
+            restoreClip(context, localPaintingInfo.paintDirtyRect, fragment.backgroundRect);
+    }
+}
+
+void RenderLayer::paintOverflowControlsForFragments(const LayerFragments& layerFragments, GraphicsContext* context, const LayerPaintingInfo& localPaintingInfo)
+{
+    for (size_t i = 0; i < layerFragments.size(); ++i) {
+        const LayerFragment& fragment = layerFragments.at(i);
+        clipToRect(localPaintingInfo.rootLayer, context, localPaintingInfo.paintDirtyRect, fragment.backgroundRect);
+        paintOverflowControls(context, roundedIntPoint(toPoint(fragment.layerBounds.location() - renderBoxLocation() + localPaintingInfo.subPixelAccumulation)),
+            pixelSnappedIntRect(fragment.backgroundRect.rect()), true);
+        restoreClip(context, localPaintingInfo.paintDirtyRect, fragment.backgroundRect);
+    }
+}
+
+void RenderLayer::paintPaginatedChildLayer(RenderLayer* childLayer, GraphicsContext* context, const LayerPaintingInfo& paintingInfo, PaintLayerFlags paintFlags)
+{
+    // We need to do multiple passes, breaking up our child layer into strips.
+    Vector<RenderLayer*> columnLayers;
+    RenderLayer* ancestorLayer = isNormalFlowOnly() ? parent() : ancestorStackingContainer();
+    for (RenderLayer* curr = childLayer->parent(); curr; curr = curr->parent()) {
+        if (curr->renderer()->hasColumns() && checkContainingBlockChainForPagination(childLayer->renderer(), curr->renderBox()))
+            columnLayers.append(curr);
+        if (curr == ancestorLayer)
+            break;
+    }
+
+    // It is possible for paintLayer() to be called after the child layer ceases to be paginated but before
+    // updateLayerPositions() is called and resets the isPaginated() flag, see <rdar://problem/10098679>.
+    // If this is the case, just bail out, since the upcoming call to updateLayerPositions() will repaint the layer.
+    if (!columnLayers.size())
+        return;
+
+    paintChildLayerIntoColumns(childLayer, context, paintingInfo, paintFlags, columnLayers, columnLayers.size() - 1);
+}
+
+void RenderLayer::paintChildLayerIntoColumns(RenderLayer* childLayer, GraphicsContext* context, const LayerPaintingInfo& paintingInfo,
+    PaintLayerFlags paintFlags, const Vector<RenderLayer*>& columnLayers, size_t colIndex)
+{
+    RenderBlock* columnBlock = toRenderBlock(columnLayers[colIndex]->renderer());
+
+    ASSERT(columnBlock && columnBlock->hasColumns());
+    if (!columnBlock || !columnBlock->hasColumns())
+        return;
+    
+    LayoutPoint layerOffset;
+    // FIXME: It looks suspicious to call convertToLayerCoords here
+    // as canUseConvertToLayerCoords is true for this layer.
+    columnBlock->layer()->convertToLayerCoords(paintingInfo.rootLayer, layerOffset);
+    
+    bool isHorizontal = columnBlock->style()->isHorizontalWritingMode();
+
+    ColumnInfo* colInfo = columnBlock->columnInfo();
+    unsigned colCount = columnBlock->columnCount(colInfo);
+    LayoutUnit currLogicalTopOffset = 0;
+    for (unsigned i = 0; i < colCount; i++) {
+        // For each rect, we clip to the rect, and then we adjust our coords.
+        LayoutRect colRect = columnBlock->columnRectAt(colInfo, i);
+        columnBlock->flipForWritingMode(colRect);
+        LayoutUnit logicalLeftOffset = (isHorizontal ? colRect.x() : colRect.y()) - columnBlock->logicalLeftOffsetForContent();
+        LayoutSize offset;
+        if (isHorizontal) {
+            if (colInfo->progressionAxis() == ColumnInfo::InlineAxis)
+                offset = LayoutSize(logicalLeftOffset, currLogicalTopOffset);
+            else
+                offset = LayoutSize(0, colRect.y() + currLogicalTopOffset - columnBlock->borderTop() - columnBlock->paddingTop());
+        } else {
+            if (colInfo->progressionAxis() == ColumnInfo::InlineAxis)
+                offset = LayoutSize(currLogicalTopOffset, logicalLeftOffset);
+            else
+                offset = LayoutSize(colRect.x() + currLogicalTopOffset - columnBlock->borderLeft() - columnBlock->paddingLeft(), 0);
+        }
+
+        colRect.moveBy(layerOffset);
+
+        LayoutRect localDirtyRect(paintingInfo.paintDirtyRect);
+        localDirtyRect.intersect(colRect);
+        
+        if (!localDirtyRect.isEmpty()) {
+            GraphicsContextStateSaver stateSaver(*context);
+            
+            // Each strip pushes a clip, since column boxes are specified as being
+            // like overflow:hidden.
+            context->clip(pixelSnappedIntRect(colRect));
+
+            if (!colIndex) {
+                // Apply a translation transform to change where the layer paints.
+                TransformationMatrix oldTransform;
+                bool oldHasTransform = childLayer->transform();
+                if (oldHasTransform)
+                    oldTransform = *childLayer->transform();
+                TransformationMatrix newTransform(oldTransform);
+                newTransform.translateRight(roundToInt(offset.width()), roundToInt(offset.height()));
+                
+                childLayer->m_transform = adoptPtr(new TransformationMatrix(newTransform));
+                
+                LayerPaintingInfo localPaintingInfo(paintingInfo);
+                localPaintingInfo.paintDirtyRect = localDirtyRect;
+                childLayer->paintLayer(context, localPaintingInfo, paintFlags);
+
+                if (oldHasTransform)
+                    childLayer->m_transform = adoptPtr(new TransformationMatrix(oldTransform));
+                else
+                    childLayer->m_transform.clear();
+            } else {
+                // 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.
+                LayoutPoint childOffset;
+                columnLayers[colIndex - 1]->convertToLayerCoords(paintingInfo.rootLayer, childOffset);
+                TransformationMatrix transform;
+                transform.translateRight(roundToInt(childOffset.x() + offset.width()), roundToInt(childOffset.y() + offset.height()));
+                
+                // Apply the transform.
+                context->concatCTM(transform.toAffineTransform());
+
+                // Now do a paint with the root layer shifted to be the next multicol block.
+                LayerPaintingInfo columnPaintingInfo(paintingInfo);
+                columnPaintingInfo.rootLayer = columnLayers[colIndex - 1];
+                columnPaintingInfo.paintDirtyRect = transform.inverse().mapRect(localDirtyRect);
+                paintChildLayerIntoColumns(childLayer, context, columnPaintingInfo, paintFlags, columnLayers, colIndex - 1);
+            }
+        }
+
+        // Move to the next position.
+        LayoutUnit blockDelta = isHorizontal ? colRect.height() : colRect.width();
+        if (columnBlock->style()->isFlippedBlocksWritingMode())
+            currLogicalTopOffset += blockDelta;
+        else
+            currLogicalTopOffset -= blockDelta;
+    }
+}
+
+static inline LayoutRect frameVisibleRect(RenderObject* renderer)
+{
+    FrameView* frameView = renderer->document()->view();
+    if (!frameView)
+        return LayoutRect();
+
+    return frameView->visibleContentRect();
+}
+
+bool RenderLayer::hitTest(const HitTestRequest& request, HitTestResult& result)
+{
+    return hitTest(request, result.hitTestLocation(), result);
+}
+
+bool RenderLayer::hitTest(const HitTestRequest& request, const HitTestLocation& hitTestLocation, HitTestResult& result)
+{
+    ASSERT(isSelfPaintingLayer() || hasSelfPaintingLayerDescendant());
+
+    renderer()->document()->updateLayout();
+    
+    LayoutRect hitTestArea = isOutOfFlowRenderFlowThread() ? toRenderFlowThread(renderer())->borderBoxRect() : renderer()->view()->documentRect();
+    if (!request.ignoreClipping())
+        hitTestArea.intersect(frameVisibleRect(renderer()));
+
+    RenderLayer* insideLayer = hitTestLayer(this, 0, request, result, hitTestArea, hitTestLocation, false);
+    if (!insideLayer) {
+        // 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.isChildFrameHitTest() && (request.active() || request.release()) && isRootLayer()) {
+            renderer()->updateHitTestResult(result, toRenderView(renderer())->flipForWritingMode(hitTestLocation.point()));
+            insideLayer = this;
+        }
+    }
+
+    // Now determine if the result is inside an anchor - if the urlElement isn't already set.
+    Node* node = result.innerNode();
+    if (node && !result.URLElement())
+        result.setURLElement(toElement(node->enclosingLinkEventParentOrSelf()));
+
+    // 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->node())
+            return e;
+    }
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
+bool RenderLayer::isInTopLayer() const
+{
+    Node* node = renderer()->node();
+    return node && node->isElementNode() && toElement(node)->isInTopLayer();
+}
+
+bool RenderLayer::isInTopLayerSubtree() const
+{
+    for (const RenderLayer* layer = this; layer; layer = layer->parent()) {
+        if (layer->isInTopLayer())
+            return true;
+    }
+    return false;
+}
+
+// Compute the z-offset of the point in the transformState.
+// This is effectively projecting a ray normal to the plane of ancestor, finding where that
+// ray intersects target, and computing the z delta between those two points.
+static double computeZOffset(const HitTestingTransformState& transformState)
+{
+    // We got an affine transform, so no z-offset
+    if (transformState.m_accumulatedTransform.isAffine())
+        return 0;
+
+    // Flatten the point into the target plane
+    FloatPoint targetPoint = transformState.mappedPoint();
+    
+    // Now map the point back through the transform, which computes Z.
+    FloatPoint3D backmappedPoint = transformState.m_accumulatedTransform.mapPoint(FloatPoint3D(targetPoint));
+    return backmappedPoint.z();
+}
+
+PassRefPtr<HitTestingTransformState> RenderLayer::createLocalTransformState(RenderLayer* rootLayer, RenderLayer* containerLayer,
+                                        const LayoutRect& hitTestRect, const HitTestLocation& hitTestLocation,
+                                        const HitTestingTransformState* containerTransformState,
+                                        const LayoutPoint& translationOffset) const
+{
+    RefPtr<HitTestingTransformState> transformState;
+    LayoutPoint offset;
+    if (containerTransformState) {
+        // If we're already computing transform state, then it's relative to the container (which we know is non-null).
+        transformState = HitTestingTransformState::create(*containerTransformState);
+        convertToLayerCoords(containerLayer, offset);
+    } else {
+        // If this is the first time we need to make transform state, then base it off of hitTestLocation,
+        // which is relative to rootLayer.
+        transformState = HitTestingTransformState::create(hitTestLocation.transformedPoint(), hitTestLocation.transformedRect(), FloatQuad(hitTestRect));
+        convertToLayerCoords(rootLayer, offset);
+    }
+    offset.moveBy(translationOffset);
+
+    RenderObject* containerRenderer = containerLayer ? containerLayer->renderer() : 0;
+    if (renderer()->shouldUseTransformFromContainer(containerRenderer)) {
+        TransformationMatrix containerTransform;
+        renderer()->getTransformFromContainer(containerRenderer, toLayoutSize(offset), containerTransform);
+        transformState->applyTransform(containerTransform, HitTestingTransformState::AccumulateTransform);
+    } else {
+        transformState->translate(offset.x(), offset.y(), HitTestingTransformState::AccumulateTransform);
+    }
+    
+    return transformState;
+}
+
+
+static bool isHitCandidate(const RenderLayer* hitLayer, bool canDepthSort, double* zOffset, const HitTestingTransformState* transformState)
+{
+    if (!hitLayer)
+        return false;
+
+    // The hit layer is depth-sorting with other layers, so just say that it was hit.
+    if (canDepthSort)
+        return true;
+    
+    // We need to look at z-depth to decide if this layer was hit.
+    if (zOffset) {
+        ASSERT(transformState);
+        // This is actually computing our z, but that's OK because the hitLayer is coplanar with us.
+        double childZOffset = computeZOffset(*transformState);
+        if (childZOffset > *zOffset) {
+            *zOffset = childZOffset;
+            return true;
+        }
+        return false;
+    }
+
+    return true;
+}
+
+// hitTestLocation and hitTestRect are relative to rootLayer.
+// A 'flattening' layer is one preserves3D() == false.
+// transformState.m_accumulatedTransform holds the transform from the containing flattening layer.
+// transformState.m_lastPlanarPoint is the hitTestLocation in the plane of the containing flattening layer.
+// transformState.m_lastPlanarQuad is the hitTestRect as a quad in the plane of the containing flattening layer.
+// 
+// If zOffset is non-null (which indicates that the caller wants z offset information), 
+//  *zOffset on return is the z offset of the hit point relative to the containing flattening layer.
+RenderLayer* RenderLayer::hitTestLayer(RenderLayer* rootLayer, RenderLayer* containerLayer, const HitTestRequest& request, HitTestResult& result,
+                                       const LayoutRect& hitTestRect, const HitTestLocation& hitTestLocation, bool appliedTransform,
+                                       const HitTestingTransformState* transformState, double* zOffset)
+{
+    if (!isSelfPaintingLayer() && !hasSelfPaintingLayerDescendant())
+        return 0;
+
+    // The natural thing would be to keep HitTestingTransformState on the stack, but it's big, so we heap-allocate.
+
+    // Apply a transform if we have one.
+    if (transform() && !appliedTransform) {
+        if (enclosingPaginationLayer())
+            return hitTestTransformedLayerInFragments(rootLayer, containerLayer, request, result, hitTestRect, hitTestLocation, transformState, zOffset);
+
+        // Make sure the parent's clip rects have been calculated.
+        if (parent()) {
+            ClipRectsContext clipRectsContext(rootLayer, hitTestLocation.region(), RootRelativeClipRects, IncludeOverlayScrollbarSize);
+            ClipRect clipRect = backgroundClipRect(clipRectsContext);
+            // Go ahead and test the enclosing clip now.
+            if (!clipRect.intersects(hitTestLocation))
+                return 0;
+        }
+
+        return hitTestLayerByApplyingTransform(rootLayer, containerLayer, request, result, hitTestRect, hitTestLocation, transformState, zOffset);
+    }
+
+    // Ensure our lists and 3d status are up-to-date.
+    updateLayerListsIfNeeded();
+    update3DTransformedDescendantStatus();
+
+    RefPtr<HitTestingTransformState> localTransformState;
+    if (appliedTransform) {
+        // We computed the correct state in the caller (above code), so just reference it.
+        ASSERT(transformState);
+        localTransformState = const_cast<HitTestingTransformState*>(transformState);
+    } else if (transformState || m_has3DTransformedDescendant || preserves3D()) {
+        // We need transform state for the first time, or to offset the container state, so create it here.
+        localTransformState = createLocalTransformState(rootLayer, containerLayer, hitTestRect, hitTestLocation, transformState);
+    }
+
+    // Check for hit test on backface if backface-visibility is 'hidden'
+    if (localTransformState && renderer()->style()->backfaceVisibility() == BackfaceVisibilityHidden) {
+        TransformationMatrix invertedMatrix = localTransformState->m_accumulatedTransform.inverse();
+        // If the z-vector of the matrix is negative, the back is facing towards the viewer.
+        if (invertedMatrix.m33() < 0)
+            return 0;
+    }
+
+    RefPtr<HitTestingTransformState> unflattenedTransformState = localTransformState;
+    if (localTransformState && !preserves3D()) {
+        // Keep a copy of the pre-flattening state, for computing z-offsets for the container
+        unflattenedTransformState = HitTestingTransformState::create(*localTransformState);
+        // This layer is flattening, so flatten the state passed to descendants.
+        localTransformState->flatten();
+    }
+
+    // The following are used for keeping track of the z-depth of the hit point of 3d-transformed
+    // descendants.
+    double localZOffset = -numeric_limits<double>::infinity();
+    double* zOffsetForDescendantsPtr = 0;
+    double* zOffsetForContentsPtr = 0;
+    
+    bool depthSortDescendants = false;
+    if (preserves3D()) {
+        depthSortDescendants = true;
+        // Our layers can depth-test with our container, so share the z depth pointer with the container, if it passed one down.
+        zOffsetForDescendantsPtr = zOffset ? zOffset : &localZOffset;
+        zOffsetForContentsPtr = zOffset ? zOffset : &localZOffset;
+    } else if (m_has3DTransformedDescendant) {
+        // Flattening layer with 3d children; use a local zOffset pointer to depth-test children and foreground.
+        depthSortDescendants = true;
+        zOffsetForDescendantsPtr = zOffset ? zOffset : &localZOffset;
+        zOffsetForContentsPtr = zOffset ? zOffset : &localZOffset;
+    } else if (zOffset) {
+        zOffsetForDescendantsPtr = 0;
+        // Container needs us to give back a z offset for the hit layer.
+        zOffsetForContentsPtr = zOffset;
+    }
+
+    // This variable tracks which layer the mouse ends up being inside.
+    RenderLayer* candidateLayer = 0;
+
+    // Begin by walking our list of positive layers from highest z-index down to the lowest z-index.
+    RenderLayer* hitLayer = hitTestList(posZOrderList(), rootLayer, request, result, hitTestRect, hitTestLocation,
+                                        localTransformState.get(), zOffsetForDescendantsPtr, zOffset, unflattenedTransformState.get(), depthSortDescendants);
+    if (hitLayer) {
+        if (!depthSortDescendants)
+            return hitLayer;
+        candidateLayer = hitLayer;
+    }
+
+    // Now check our overflow objects.
+    hitLayer = hitTestList(m_normalFlowList.get(), rootLayer, request, result, hitTestRect, hitTestLocation,
+                           localTransformState.get(), zOffsetForDescendantsPtr, zOffset, unflattenedTransformState.get(), depthSortDescendants);
+    if (hitLayer) {
+        if (!depthSortDescendants)
+            return hitLayer;
+        candidateLayer = hitLayer;
+    }
+
+    // Collect the fragments. This will compute the clip rectangles for each layer fragment.
+    LayerFragments layerFragments;
+    collectFragments(layerFragments, rootLayer, hitTestLocation.region(), hitTestRect, RootRelativeClipRects, IncludeOverlayScrollbarSize);
+
+    if (canResize() && hitTestResizerInFragments(layerFragments, hitTestLocation)) {
+        renderer()->updateHitTestResult(result, hitTestLocation.point());
+        return this;
+    }
+
+    // Next we want to see if the mouse pos is inside the child RenderObjects of the layer. Check
+    // every fragment in reverse order.
+    if (isSelfPaintingLayer()) {
+        // Hit test with a temporary HitTestResult, because we only want to commit to 'result' if we know we're frontmost.
+        HitTestResult tempResult(result.hitTestLocation());
+        bool insideFragmentForegroundRect = false;
+        if (hitTestContentsForFragments(layerFragments, request, tempResult, hitTestLocation, HitTestDescendants, insideFragmentForegroundRect)
+            && isHitCandidate(this, false, zOffsetForContentsPtr, unflattenedTransformState.get())) {
+            if (result.isRectBasedTest())
+                result.append(tempResult);
+            else
+                result = tempResult;
+            if (!depthSortDescendants)
+                return this;
+            // Foreground can depth-sort with descendant layers, so keep this as a candidate.
+            candidateLayer = this;
+        } else if (insideFragmentForegroundRect && result.isRectBasedTest())
+            result.append(tempResult);
+    }
+
+    // Now check our negative z-index children.
+    hitLayer = hitTestList(negZOrderList(), rootLayer, request, result, hitTestRect, hitTestLocation,
+        localTransformState.get(), zOffsetForDescendantsPtr, zOffset, unflattenedTransformState.get(), depthSortDescendants);
+    if (hitLayer) {
+        if (!depthSortDescendants)
+            return hitLayer;
+        candidateLayer = hitLayer;
+    }
+
+    // If we found a layer, return. Child layers, and foreground always render in front of background.
+    if (candidateLayer)
+        return candidateLayer;
+
+    if (isSelfPaintingLayer()) {
+        HitTestResult tempResult(result.hitTestLocation());
+        bool insideFragmentBackgroundRect = false;
+        if (hitTestContentsForFragments(layerFragments, request, tempResult, hitTestLocation, HitTestSelf, insideFragmentBackgroundRect)
+            && isHitCandidate(this, false, zOffsetForContentsPtr, unflattenedTransformState.get())) {
+            if (result.isRectBasedTest())
+                result.append(tempResult);
+            else
+                result = tempResult;
+            return this;
+        }
+        if (insideFragmentBackgroundRect && result.isRectBasedTest())
+            result.append(tempResult);
+    }
+
+    return 0;
+}
+
+bool RenderLayer::hitTestContentsForFragments(const LayerFragments& layerFragments, const HitTestRequest& request, HitTestResult& result,
+    const HitTestLocation& hitTestLocation, HitTestFilter hitTestFilter, bool& insideClipRect) const
+{
+    if (layerFragments.isEmpty())
+        return false;
+
+    for (int i = layerFragments.size() - 1; i >= 0; --i) {
+        const LayerFragment& fragment = layerFragments.at(i);
+        if ((hitTestFilter == HitTestSelf && !fragment.backgroundRect.intersects(hitTestLocation))
+            || (hitTestFilter == HitTestDescendants && !fragment.foregroundRect.intersects(hitTestLocation)))
+            continue;
+        insideClipRect = true;
+        if (hitTestContents(request, result, fragment.layerBounds, hitTestLocation, hitTestFilter))
+            return true;
+    }
+    
+    return false;
+}
+
+bool RenderLayer::hitTestResizerInFragments(const LayerFragments& layerFragments, const HitTestLocation& hitTestLocation) const
+{
+    if (layerFragments.isEmpty())
+        return false;
+
+    for (int i = layerFragments.size() - 1; i >= 0; --i) {
+        const LayerFragment& fragment = layerFragments.at(i);
+        if (fragment.backgroundRect.intersects(hitTestLocation) && resizerCornerRect(this, pixelSnappedIntRect(fragment.layerBounds)).contains(hitTestLocation.roundedPoint()))
+            return true;
+    }
+    
+    return false;
+}
+
+RenderLayer* RenderLayer::hitTestTransformedLayerInFragments(RenderLayer* rootLayer, RenderLayer* containerLayer, const HitTestRequest& request, HitTestResult& result,
+    const LayoutRect& hitTestRect, const HitTestLocation& hitTestLocation, const HitTestingTransformState* transformState, double* zOffset)
+{
+    LayerFragments enclosingPaginationFragments;
+    LayoutPoint offsetOfPaginationLayerFromRoot;
+    LayoutRect transformedExtent = transparencyClipBox(this, enclosingPaginationLayer(), HitTestingTransparencyClipBox, RootOfTransparencyClipBox);
+    enclosingPaginationLayer()->collectFragments(enclosingPaginationFragments, rootLayer, hitTestLocation.region(), hitTestRect,
+        RootRelativeClipRects, IncludeOverlayScrollbarSize, RespectOverflowClip, &offsetOfPaginationLayerFromRoot, &transformedExtent);
+
+    for (int i = enclosingPaginationFragments.size() - 1; i >= 0; --i) {
+        const LayerFragment& fragment = enclosingPaginationFragments.at(i);
+        
+        // Apply the page/column clip for this fragment, as well as any clips established by layers in between us and
+        // the enclosing pagination layer.
+        LayoutRect clipRect = fragment.backgroundRect.rect();
+        
+        // Now compute the clips within a given fragment
+        if (parent() != enclosingPaginationLayer()) {
+            enclosingPaginationLayer()->convertToLayerCoords(rootLayer, offsetOfPaginationLayerFromRoot);
+    
+            ClipRectsContext clipRectsContext(enclosingPaginationLayer(), hitTestLocation.region(), RootRelativeClipRects, IncludeOverlayScrollbarSize);
+            LayoutRect parentClipRect = backgroundClipRect(clipRectsContext).rect();
+            parentClipRect.moveBy(fragment.paginationOffset + offsetOfPaginationLayerFromRoot);
+            clipRect.intersect(parentClipRect);
+        }
+        
+        if (!hitTestLocation.intersects(clipRect))
+            continue;
+
+        RenderLayer* hitLayer = hitTestLayerByApplyingTransform(rootLayer, containerLayer, request, result, hitTestRect, hitTestLocation,
+            transformState, zOffset, fragment.paginationOffset);
+        if (hitLayer)
+            return hitLayer;
+    }
+    
+    return 0;
+}
+
+RenderLayer* RenderLayer::hitTestLayerByApplyingTransform(RenderLayer* rootLayer, RenderLayer* containerLayer, const HitTestRequest& request, HitTestResult& result,
+    const LayoutRect& hitTestRect, const HitTestLocation& hitTestLocation, const HitTestingTransformState* transformState, double* zOffset,
+    const LayoutPoint& translationOffset)
+{
+    // Create a transform state to accumulate this transform.
+    RefPtr<HitTestingTransformState> newTransformState = createLocalTransformState(rootLayer, containerLayer, hitTestRect, hitTestLocation, transformState, translationOffset);
+
+    // If the transform can't be inverted, then don't hit test this layer at all.
+    if (!newTransformState->m_accumulatedTransform.isInvertible())
+        return 0;
+
+    // Compute the point and the hit test rect in the coords of this layer by using the values
+    // from the transformState, which store the point and quad in the coords of the last flattened
+    // layer, and the accumulated transform which lets up map through preserve-3d layers.
+    //
+    // We can't just map hitTestLocation and hitTestRect because they may have been flattened (losing z)
+    // by our container.
+    FloatPoint localPoint = newTransformState->mappedPoint();
+    FloatQuad localPointQuad = newTransformState->mappedQuad();
+    LayoutRect localHitTestRect = newTransformState->boundsOfMappedArea();
+    HitTestLocation newHitTestLocation;
+    if (hitTestLocation.isRectBasedTest())
+        newHitTestLocation = HitTestLocation(localPoint, localPointQuad);
+    else
+        newHitTestLocation = HitTestLocation(localPoint);
+
+    // Now do a hit test with the root layer shifted to be us.
+    return hitTestLayer(this, containerLayer, request, result, localHitTestRect, newHitTestLocation, true, newTransformState.get(), zOffset);
+}
+
+bool RenderLayer::hitTestContents(const HitTestRequest& request, HitTestResult& result, const LayoutRect& layerBounds, const HitTestLocation& hitTestLocation, HitTestFilter hitTestFilter) const
+{
+    ASSERT(isSelfPaintingLayer() || hasSelfPaintingLayerDescendant());
+
+    if (!renderer()->hitTest(request, result, hitTestLocation, toLayoutPoint(layerBounds.location() - renderBoxLocation()), hitTestFilter)) {
+        // It's wrong to set innerNode, but then claim that you didn't hit anything, unless it is
+        // a rect-based test.
+        ASSERT(!result.innerNode() || (result.isRectBasedTest() && result.rectBasedTestResult().size()));
+        return false;
+    }
+
+    // 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 true;
+}
+
+RenderLayer* RenderLayer::hitTestList(Vector<RenderLayer*>* list, RenderLayer* rootLayer,
+                                      const HitTestRequest& request, HitTestResult& result,
+                                      const LayoutRect& hitTestRect, const HitTestLocation& hitTestLocation,
+                                      const HitTestingTransformState* transformState, 
+                                      double* zOffsetForDescendants, double* zOffset,
+                                      const HitTestingTransformState* unflattenedTransformState,
+                                      bool depthSortDescendants)
+{
+    if (!list)
+        return 0;
+
+    if (!hasSelfPaintingLayerDescendant())
+        return 0;
+
+    RenderLayer* resultLayer = 0;
+    for (int i = list->size() - 1; i >= 0; --i) {
+        RenderLayer* childLayer = list->at(i);
+        RenderLayer* hitLayer = 0;
+        HitTestResult tempResult(result.hitTestLocation());
+        if (childLayer->isPaginated())
+            hitLayer = hitTestPaginatedChildLayer(childLayer, rootLayer, request, tempResult, hitTestRect, hitTestLocation, transformState, zOffsetForDescendants);
+        else
+            hitLayer = childLayer->hitTestLayer(rootLayer, this, request, tempResult, hitTestRect, hitTestLocation, false, transformState, zOffsetForDescendants);
+
+        // If it a rect-based test, we can safely append the temporary result since it might had hit
+        // nodes but not necesserily had hitLayer set.
+        if (result.isRectBasedTest())
+            result.append(tempResult);
+
+        if (isHitCandidate(hitLayer, depthSortDescendants, zOffset, unflattenedTransformState)) {
+            resultLayer = hitLayer;
+            if (!result.isRectBasedTest())
+                result = tempResult;
+            if (!depthSortDescendants)
+                break;
+        }
+    }
+
+    return resultLayer;
+}
+
+RenderLayer* RenderLayer::hitTestPaginatedChildLayer(RenderLayer* childLayer, RenderLayer* rootLayer, const HitTestRequest& request, HitTestResult& result,
+                                                     const LayoutRect& hitTestRect, const HitTestLocation& hitTestLocation, const HitTestingTransformState* transformState, double* zOffset)
+{
+    Vector<RenderLayer*> columnLayers;
+    RenderLayer* ancestorLayer = isNormalFlowOnly() ? parent() : ancestorStackingContainer();
+    for (RenderLayer* curr = childLayer->parent(); curr; curr = curr->parent()) {
+        if (curr->renderer()->hasColumns() && checkContainingBlockChainForPagination(childLayer->renderer(), curr->renderBox()))
+            columnLayers.append(curr);
+        if (curr == ancestorLayer)
+            break;
+    }
+
+    ASSERT(columnLayers.size());
+    return hitTestChildLayerColumns(childLayer, rootLayer, request, result, hitTestRect, hitTestLocation, transformState, zOffset,
+                                    columnLayers, columnLayers.size() - 1);
+}
+
+RenderLayer* RenderLayer::hitTestChildLayerColumns(RenderLayer* childLayer, RenderLayer* rootLayer, const HitTestRequest& request, HitTestResult& result,
+                                                   const LayoutRect& hitTestRect, const HitTestLocation& hitTestLocation, const HitTestingTransformState* transformState, double* zOffset,
+                                                   const Vector<RenderLayer*>& columnLayers, size_t columnIndex)
+{
+    RenderBlock* columnBlock = toRenderBlock(columnLayers[columnIndex]->renderer());
+
+    ASSERT(columnBlock && columnBlock->hasColumns());
+    if (!columnBlock || !columnBlock->hasColumns())
+        return 0;
+
+    LayoutPoint layerOffset;
+    columnBlock->layer()->convertToLayerCoords(rootLayer, layerOffset);
+
+    ColumnInfo* colInfo = columnBlock->columnInfo();
+    int colCount = columnBlock->columnCount(colInfo);
+
+    // We have to go backwards from the last column to the first.
+    bool isHorizontal = columnBlock->style()->isHorizontalWritingMode();
+    LayoutUnit logicalLeft = columnBlock->logicalLeftOffsetForContent();
+    LayoutUnit currLogicalTopOffset = 0;
+    int i;
+    for (i = 0; i < colCount; i++) {
+        LayoutRect colRect = columnBlock->columnRectAt(colInfo, i);
+        LayoutUnit blockDelta =  (isHorizontal ? colRect.height() : colRect.width());
+        if (columnBlock->style()->isFlippedBlocksWritingMode())
+            currLogicalTopOffset += blockDelta;
+        else
+            currLogicalTopOffset -= blockDelta;
+    }
+    for (i = colCount - 1; i >= 0; i--) {
+        // For each rect, we clip to the rect, and then we adjust our coords.
+        LayoutRect colRect = columnBlock->columnRectAt(colInfo, i);
+        columnBlock->flipForWritingMode(colRect);
+        LayoutUnit currLogicalLeftOffset = (isHorizontal ? colRect.x() : colRect.y()) - logicalLeft;
+        LayoutUnit blockDelta =  (isHorizontal ? colRect.height() : colRect.width());
+        if (columnBlock->style()->isFlippedBlocksWritingMode())
+            currLogicalTopOffset -= blockDelta;
+        else
+            currLogicalTopOffset += blockDelta;
+
+        LayoutSize offset;
+        if (isHorizontal) {
+            if (colInfo->progressionAxis() == ColumnInfo::InlineAxis)
+                offset = LayoutSize(currLogicalLeftOffset, currLogicalTopOffset);
+            else
+                offset = LayoutSize(0, colRect.y() + currLogicalTopOffset - columnBlock->borderTop() - columnBlock->paddingTop());
+        } else {
+            if (colInfo->progressionAxis() == ColumnInfo::InlineAxis)
+                offset = LayoutSize(currLogicalTopOffset, currLogicalLeftOffset);
+            else
+                offset = LayoutSize(colRect.x() + currLogicalTopOffset - columnBlock->borderLeft() - columnBlock->paddingLeft(), 0);
+        }
+
+        colRect.moveBy(layerOffset);
+
+        LayoutRect localClipRect(hitTestRect);
+        localClipRect.intersect(colRect);
+
+        if (!localClipRect.isEmpty() && hitTestLocation.intersects(localClipRect)) {
+            RenderLayer* hitLayer = 0;
+            if (!columnIndex) {
+                // Apply a translation transform to change where the layer paints.
+                TransformationMatrix oldTransform;
+                bool oldHasTransform = childLayer->transform();
+                if (oldHasTransform)
+                    oldTransform = *childLayer->transform();
+                TransformationMatrix newTransform(oldTransform);
+                newTransform.translateRight(offset.width(), offset.height());
+
+                childLayer->m_transform = adoptPtr(new TransformationMatrix(newTransform));
+                hitLayer = childLayer->hitTestLayer(rootLayer, columnLayers[0], request, result, localClipRect, hitTestLocation, false, transformState, zOffset);
+                if (oldHasTransform)
+                    childLayer->m_transform = adoptPtr(new TransformationMatrix(oldTransform));
+                else
+                    childLayer->m_transform.clear();
+            } else {
+                // Adjust the transform such that the renderer's upper left corner will be at (0,0) in user space.
+                // This involves subtracting out the position of the layer in our current coordinate space.
+                RenderLayer* nextLayer = columnLayers[columnIndex - 1];
+                RefPtr<HitTestingTransformState> newTransformState = nextLayer->createLocalTransformState(rootLayer, nextLayer, localClipRect, hitTestLocation, transformState);
+                newTransformState->translate(offset.width(), offset.height(), HitTestingTransformState::AccumulateTransform);
+                FloatPoint localPoint = newTransformState->mappedPoint();
+                FloatQuad localPointQuad = newTransformState->mappedQuad();
+                LayoutRect localHitTestRect = newTransformState->mappedArea().enclosingBoundingBox();
+                HitTestLocation newHitTestLocation;
+                if (hitTestLocation.isRectBasedTest())
+                    newHitTestLocation = HitTestLocation(localPoint, localPointQuad);
+                else
+                    newHitTestLocation = HitTestLocation(localPoint);
+                newTransformState->flatten();
+
+                hitLayer = hitTestChildLayerColumns(childLayer, columnLayers[columnIndex - 1], request, result, localHitTestRect, newHitTestLocation,
+                                                    newTransformState.get(), zOffset, columnLayers, columnIndex - 1);
+            }
+
+            if (hitLayer)
+                return hitLayer;
+        }
+    }
+
+    return 0;
+}
+
+void RenderLayer::updateClipRects(const ClipRectsContext& clipRectsContext)
+{
+    ClipRectsType clipRectsType = clipRectsContext.clipRectsType;
+    ASSERT(clipRectsType < NumCachedClipRectsTypes);
+    if (m_clipRectsCache && m_clipRectsCache->getClipRects(clipRectsType, clipRectsContext.respectOverflowClip)) {
+        ASSERT(clipRectsContext.rootLayer == m_clipRectsCache->m_clipRectsRoot[clipRectsType]);
+        ASSERT(m_clipRectsCache->m_scrollbarRelevancy[clipRectsType] == clipRectsContext.overlayScrollbarSizeRelevancy);
+        
+#ifdef CHECK_CACHED_CLIP_RECTS
+        // This code is useful to check cached clip rects, but is too expensive to leave enabled in debug builds by default.
+        ClipRectsContext tempContext(clipRectsContext);
+        tempContext.clipRectsType = TemporaryClipRects;
+        ClipRects clipRects;
+        calculateClipRects(tempContext, clipRects);
+        ASSERT(clipRects == *m_clipRectsCache->getClipRects(clipRectsType, clipRectsContext.respectOverflowClip).get());
+#endif
+        return; // We have the correct cached value.
+    }
+    
+    // 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 = clipRectsContext.rootLayer != this ? parent() : 0;
+    if (parentLayer)
+        parentLayer->updateClipRects(clipRectsContext);
+
+    ClipRects clipRects;
+    calculateClipRects(clipRectsContext, clipRects);
+
+    if (!m_clipRectsCache)
+        m_clipRectsCache = adoptPtr(new ClipRectsCache);
+
+    if (parentLayer && parentLayer->clipRects(clipRectsContext) && clipRects == *parentLayer->clipRects(clipRectsContext))
+        m_clipRectsCache->setClipRects(clipRectsType, clipRectsContext.respectOverflowClip, parentLayer->clipRects(clipRectsContext));
+    else
+        m_clipRectsCache->setClipRects(clipRectsType, clipRectsContext.respectOverflowClip, ClipRects::create(clipRects));
+
+#ifndef NDEBUG
+    m_clipRectsCache->m_clipRectsRoot[clipRectsType] = clipRectsContext.rootLayer;
+    m_clipRectsCache->m_scrollbarRelevancy[clipRectsType] = clipRectsContext.overlayScrollbarSizeRelevancy;
+#endif
+}
+
+void RenderLayer::calculateClipRects(const ClipRectsContext& clipRectsContext, ClipRects& clipRects) const
+{
+    if (!parent()) {
+        // The root layer's clip rect is always infinite.
+        clipRects.reset(PaintInfo::infiniteRect());
+        return;
+    }
+    
+    ClipRectsType clipRectsType = clipRectsContext.clipRectsType;
+    bool useCached = clipRectsType != TemporaryClipRects;
+
+    // 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 = clipRectsContext.rootLayer != this ? parent() : 0;
+    
+    // Ensure that our parent's clip has been calculated so that we can examine the values.
+    if (parentLayer) {
+        if (useCached && parentLayer->clipRects(clipRectsContext))
+            clipRects = *parentLayer->clipRects(clipRectsContext);
+        else {
+            ClipRectsContext parentContext(clipRectsContext);
+            parentContext.overlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize; // FIXME: why?
+            parentLayer->calculateClipRects(parentContext, clipRects);
+        }
+    } else
+        clipRects.reset(PaintInfo::infiniteRect());
+
+    // 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 (renderer()->style()->position() == FixedPosition) {
+        clipRects.setPosClipRect(clipRects.fixedClipRect());
+        clipRects.setOverflowClipRect(clipRects.fixedClipRect());
+        clipRects.setFixed(true);
+    } else if (renderer()->style()->hasPaintOffset())
+        clipRects.setPosClipRect(clipRects.overflowClipRect());
+    else if (renderer()->style()->position() == AbsolutePosition)
+        clipRects.setOverflowClipRect(clipRects.posClipRect());
+    
+    // Update the clip rects that will be passed to child layers.
+    if ((renderer()->hasOverflowClip() && (clipRectsContext.respectOverflowClip == RespectOverflowClip || this != clipRectsContext.rootLayer)) || renderer()->hasClip()) {
+        // This layer establishes a clip of some kind.
+
+        // This offset cannot use convertToLayerCoords, because sometimes our rootLayer may be across
+        // some transformed layer boundary, for example, in the RenderLayerCompositor overlapMap, where
+        // clipRects are needed in view space.
+        LayoutPoint offset;
+        offset = roundedLayoutPoint(renderer()->localToContainerPoint(FloatPoint(), clipRectsContext.rootLayer->renderer()));
+        RenderView* view = renderer()->view();
+        ASSERT(view);
+        if (view && clipRects.fixed() && clipRectsContext.rootLayer->renderer() == view) {
+            offset -= view->frameView()->scrollOffsetForFixedPosition();
+        }
+        
+        if (renderer()->hasOverflowClip()) {
+            ClipRect newOverflowClip = toRenderBox(renderer())->overflowClipRect(offset, clipRectsContext.region, clipRectsContext.overlayScrollbarSizeRelevancy);
+            if (renderer()->style()->hasBorderRadius())
+                newOverflowClip.setHasRadius(true);
+            clipRects.setOverflowClipRect(intersection(newOverflowClip, clipRects.overflowClipRect()));
+            if (renderer()->isPositioned())
+                clipRects.setPosClipRect(intersection(newOverflowClip, clipRects.posClipRect()));
+        }
+        if (renderer()->hasClip()) {
+            LayoutRect newPosClip = toRenderBox(renderer())->clipRect(offset, clipRectsContext.region);
+            clipRects.setPosClipRect(intersection(newPosClip, clipRects.posClipRect()));
+            clipRects.setOverflowClipRect(intersection(newPosClip, clipRects.overflowClipRect()));
+            clipRects.setFixedClipRect(intersection(newPosClip, clipRects.fixedClipRect()));
+        }
+    }
+}
+
+void RenderLayer::parentClipRects(const ClipRectsContext& clipRectsContext, ClipRects& clipRects) const
+{
+    ASSERT(parent());
+    if (clipRectsContext.clipRectsType == TemporaryClipRects) {
+        parent()->calculateClipRects(clipRectsContext, clipRects);
+        return;
+    }
+
+    parent()->updateClipRects(clipRectsContext);
+    clipRects = *parent()->clipRects(clipRectsContext);
+}
+
+static inline ClipRect backgroundClipRectForPosition(const ClipRects& parentRects, EPosition position)
+{
+    if (position == FixedPosition)
+        return parentRects.fixedClipRect();
+
+    if (position == AbsolutePosition)
+        return parentRects.posClipRect();
+
+    return parentRects.overflowClipRect();
+}
+
+ClipRect RenderLayer::backgroundClipRect(const ClipRectsContext& clipRectsContext) const
+{
+    ASSERT(parent());
+    
+    ClipRects parentRects;
+
+    // If we cross into a different pagination context, then we can't rely on the cache.
+    // Just switch over to using TemporaryClipRects.
+    if (clipRectsContext.clipRectsType != TemporaryClipRects && parent()->enclosingPaginationLayer() != enclosingPaginationLayer()) {
+        ClipRectsContext tempContext(clipRectsContext);
+        tempContext.clipRectsType = TemporaryClipRects;
+        parentClipRects(tempContext, parentRects);
+    } else
+        parentClipRects(clipRectsContext, parentRects);
+    
+    ClipRect backgroundClipRect = backgroundClipRectForPosition(parentRects, renderer()->style()->position());
+    RenderView* view = renderer()->view();
+    ASSERT(view);
+
+    // Note: infinite clipRects should not be scrolled here, otherwise they will accidentally no longer be considered infinite.
+    if (parentRects.fixed() && clipRectsContext.rootLayer->renderer() == view && backgroundClipRect != PaintInfo::infiniteRect())
+        backgroundClipRect.move(view->frameView()->scrollOffsetForFixedPosition());
+
+    return backgroundClipRect;
+}
+
+void RenderLayer::calculateRects(const ClipRectsContext& clipRectsContext, const LayoutRect& paintDirtyRect, LayoutRect& layerBounds,
+    ClipRect& backgroundRect, ClipRect& foregroundRect, ClipRect& outlineRect, const LayoutPoint* offsetFromRoot) const
+{
+    if (clipRectsContext.rootLayer != this && parent()) {
+        backgroundRect = backgroundClipRect(clipRectsContext);
+        backgroundRect.intersect(paintDirtyRect);
+    } else
+        backgroundRect = paintDirtyRect;
+
+    foregroundRect = backgroundRect;
+    outlineRect = backgroundRect;
+    
+    LayoutPoint offset;
+    if (offsetFromRoot)
+        offset = *offsetFromRoot;
+    else
+        convertToLayerCoords(clipRectsContext.rootLayer, offset);
+    layerBounds = LayoutRect(offset, size());
+
+    // Update the clip rects that will be passed to child layers.
+    if (renderer()->hasClipOrOverflowClip()) {
+        // This layer establishes a clip of some kind.
+        if (renderer()->hasOverflowClip() && (this != clipRectsContext.rootLayer || clipRectsContext.respectOverflowClip == RespectOverflowClip)) {
+            foregroundRect.intersect(toRenderBox(renderer())->overflowClipRect(offset, clipRectsContext.region, clipRectsContext.overlayScrollbarSizeRelevancy));
+            if (renderer()->style()->hasBorderRadius())
+                foregroundRect.setHasRadius(true);
+        }
+
+        if (renderer()->hasClip()) {
+            // Clip applies to *us* as well, so go ahead and update the damageRect.
+            LayoutRect newPosClip = toRenderBox(renderer())->clipRect(offset, clipRectsContext.region);
+            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 including our visual overflow,
+        // since any visual overflow like box-shadow or border-outset is not clipped by overflow:auto/hidden.
+        if (renderBox()->hasVisualOverflow()) {
+            // FIXME: Does not do the right thing with CSS regions yet, since we don't yet factor in the
+            // individual region boxes as overflow.
+            LayoutRect layerBoundsWithVisualOverflow = renderBox()->visualOverflowRect();
+            renderBox()->flipForWritingMode(layerBoundsWithVisualOverflow); // Layers are in physical coordinates, so the overflow has to be flipped.
+            layerBoundsWithVisualOverflow.moveBy(offset);
+            if (this != clipRectsContext.rootLayer || clipRectsContext.respectOverflowClip == RespectOverflowClip)
+                backgroundRect.intersect(layerBoundsWithVisualOverflow);
+        } else {
+            // Shift the bounds to be for our region only.
+            LayoutRect bounds = renderBox()->borderBoxRectInRegion(clipRectsContext.region);
+            bounds.moveBy(offset);
+            if (this != clipRectsContext.rootLayer || clipRectsContext.respectOverflowClip == RespectOverflowClip)
+                backgroundRect.intersect(bounds);
+        }
+    }
+}
+
+LayoutRect RenderLayer::childrenClipRect() const
+{
+    // FIXME: border-radius not accounted for.
+    // FIXME: Regions not accounted for.
+    RenderView* renderView = renderer()->view();
+    RenderLayer* clippingRootLayer = clippingRootForPainting();
+    LayoutRect layerBounds;
+    ClipRect backgroundRect, foregroundRect, outlineRect;
+    ClipRectsContext clipRectsContext(clippingRootLayer, 0, TemporaryClipRects);
+    // Need to use temporary clip rects, because the value of 'dontClipToOverflow' may be different from the painting path (<rdar://problem/11844909>).
+    calculateRects(clipRectsContext, renderView->unscaledDocumentRect(), layerBounds, backgroundRect, foregroundRect, outlineRect);
+    return clippingRootLayer->renderer()->localToAbsoluteQuad(FloatQuad(foregroundRect.rect())).enclosingBoundingBox();
+}
+
+LayoutRect RenderLayer::selfClipRect() const
+{
+    // FIXME: border-radius not accounted for.
+    // FIXME: Regions not accounted for.
+    RenderView* renderView = renderer()->view();
+    RenderLayer* clippingRootLayer = clippingRootForPainting();
+    LayoutRect layerBounds;
+    ClipRect backgroundRect, foregroundRect, outlineRect;
+    ClipRectsContext clipRectsContext(clippingRootLayer, 0, PaintingClipRects);
+    calculateRects(clipRectsContext, renderView->documentRect(), layerBounds, backgroundRect, foregroundRect, outlineRect);
+    return clippingRootLayer->renderer()->localToAbsoluteQuad(FloatQuad(backgroundRect.rect())).enclosingBoundingBox();
+}
+
+LayoutRect RenderLayer::localClipRect() const
+{
+    // FIXME: border-radius not accounted for.
+    // FIXME: Regions not accounted for.
+    RenderLayer* clippingRootLayer = clippingRootForPainting();
+    LayoutRect layerBounds;
+    ClipRect backgroundRect, foregroundRect, outlineRect;
+    ClipRectsContext clipRectsContext(clippingRootLayer, 0, PaintingClipRects);
+    calculateRects(clipRectsContext, PaintInfo::infiniteRect(), layerBounds, backgroundRect, foregroundRect, outlineRect);
+
+    LayoutRect clipRect = backgroundRect.rect();
+    if (clipRect == PaintInfo::infiniteRect())
+        return clipRect;
+
+    LayoutPoint clippingRootOffset;
+    convertToLayerCoords(clippingRootLayer, clippingRootOffset);
+    clipRect.moveBy(-clippingRootOffset);
+
+    return clipRect;
+}
+
+void RenderLayer::addBlockSelectionGapsBounds(const LayoutRect& bounds)
+{
+    m_blockSelectionGapsBounds.unite(enclosingIntRect(bounds));
+}
+
+void RenderLayer::clearBlockSelectionGapsBounds()
+{
+    m_blockSelectionGapsBounds = IntRect();
+    for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
+        child->clearBlockSelectionGapsBounds();
+}
+
+void RenderLayer::repaintBlockSelectionGaps()
+{
+    for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
+        child->repaintBlockSelectionGaps();
+
+    if (m_blockSelectionGapsBounds.isEmpty())
+        return;
+
+    LayoutRect rect = m_blockSelectionGapsBounds;
+    rect.move(-scrolledContentOffset());
+    if (renderer()->hasOverflowClip() && !usesCompositedScrolling())
+        rect.intersect(toRenderBox(renderer())->overflowClipRect(LayoutPoint(), 0)); // FIXME: Regions not accounted for.
+    if (renderer()->hasClip())
+        rect.intersect(toRenderBox(renderer())->clipRect(LayoutPoint(), 0)); // FIXME: Regions not accounted for.
+    if (!rect.isEmpty())
+        renderer()->repaintRectangle(rect);
+}
+
+bool RenderLayer::intersectsDamageRect(const LayoutRect& layerBounds, const LayoutRect& damageRect, const RenderLayer* rootLayer, const LayoutPoint* offsetFromRoot) 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 (isRootLayer() || 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()->isRenderInline()) {
+        LayoutRect 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, 0, offsetFromRoot).intersects(damageRect);
+}
+
+LayoutRect RenderLayer::localBoundingBox(CalculateLayerBoundsFlags flags) 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
+    // 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.
+    LayoutRect result;
+    if (renderer()->isInline() && renderer()->isRenderInline())
+        result = toRenderInline(renderer())->linesVisualOverflowBoundingBox();
+    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()) {
+                LayoutRect bbox = toRenderBox(child)->borderBoxRect();
+                result.unite(bbox);
+                LayoutRect overflowRect = renderBox()->visualOverflowRect();
+                if (bbox != overflowRect)
+                    result.unite(overflowRect);
+            }
+        }
+    } else {
+        RenderBox* box = renderBox();
+        ASSERT(box);
+        if (!(flags & DontConstrainForMask) && box->hasMask()) {
+            result = box->maskClipRect();
+            box->flipForWritingMode(result); // The mask clip rect is in physical coordinates, so we have to flip, since localBoundingBox is not.
+        } else {
+            LayoutRect bbox = box->borderBoxRect();
+            result = bbox;
+            LayoutRect overflowRect = box->visualOverflowRect();
+            if (bbox != overflowRect)
+                result.unite(overflowRect);
+        }
+    }
+
+    RenderView* view = renderer()->view();
+    ASSERT(view);
+    if (view)
+        result.inflate(view->maximalOutlineSize()); // Used to apply a fudge factor to dirty-rect checks on blocks/tables.
+
+    return result;
+}
+
+LayoutRect RenderLayer::boundingBox(const RenderLayer* ancestorLayer, CalculateLayerBoundsFlags flags, const LayoutPoint* offsetFromRoot) const
+{    
+    LayoutRect result = localBoundingBox(flags);
+    if (renderer()->isBox())
+        renderBox()->flipForWritingMode(result);
+    else
+        renderer()->containingBlock()->flipForWritingMode(result);
+
+    if (enclosingPaginationLayer() && (flags & UseFragmentBoxes)) {
+        // Split our box up into the actual fragment boxes that render in the columns/pages and unite those together to
+        // get our true bounding box.
+        LayoutPoint offsetWithinPaginationLayer;
+        convertToLayerCoords(enclosingPaginationLayer(), offsetWithinPaginationLayer);        
+        result.moveBy(offsetWithinPaginationLayer);
+
+        RenderFlowThread* enclosingFlowThread = toRenderFlowThread(enclosingPaginationLayer()->renderer());
+        result = enclosingFlowThread->fragmentsBoundingBox(result);
+        
+        LayoutPoint delta;
+        if (offsetFromRoot)
+            delta = *offsetFromRoot;
+        else
+            enclosingPaginationLayer()->convertToLayerCoords(ancestorLayer, delta);
+        result.moveBy(delta);
+        return result;
+    }
+
+    LayoutPoint delta;
+    if (offsetFromRoot)
+        delta = *offsetFromRoot;
+    else
+        convertToLayerCoords(ancestorLayer, delta);
+    
+    result.moveBy(delta);
+    return result;
+}
+
+IntRect RenderLayer::absoluteBoundingBox() const
+{
+    return pixelSnappedIntRect(boundingBox(root()));
+}
+
+IntRect RenderLayer::calculateLayerBounds(const RenderLayer* ancestorLayer, const LayoutPoint* offsetFromRoot, CalculateLayerBoundsFlags flags) const
+{
+    if (!isSelfPaintingLayer())
+        return IntRect();
+
+    // FIXME: This could be improved to do a check like hasVisibleNonCompositingDescendantLayers() (bug 92580).
+    if ((flags & ExcludeHiddenDescendants) && this != ancestorLayer && !hasVisibleContent() && !hasVisibleDescendant())
+        return IntRect();
+
+    RenderLayerModelObject* renderer = this->renderer();
+
+    if (isRootLayer()) {
+        // The root layer is always just the size of the document.
+        return renderer->view()->unscaledDocumentRect();
+    }
+
+    LayoutRect boundingBoxRect = localBoundingBox(flags);
+
+    if (renderer->isBox())
+        toRenderBox(renderer)->flipForWritingMode(boundingBoxRect);
+    else
+        renderer->containingBlock()->flipForWritingMode(boundingBoxRect);
+
+    if (renderer->isRoot()) {
+        // If the root layer becomes composited (e.g. because some descendant with negative z-index is composited),
+        // then it has to be big enough to cover the viewport in order to display the background. This is akin
+        // to the code in RenderBox::paintRootBoxFillLayers().
+        if (FrameView* frameView = renderer->view()->frameView()) {
+            LayoutUnit contentsWidth = frameView->contentsWidth();
+            LayoutUnit contentsHeight = frameView->contentsHeight();
+        
+            boundingBoxRect.setWidth(max(boundingBoxRect.width(), contentsWidth - boundingBoxRect.x()));
+            boundingBoxRect.setHeight(max(boundingBoxRect.height(), contentsHeight - boundingBoxRect.y()));
+        }
+    }
+
+    LayoutRect unionBounds = boundingBoxRect;
+
+    if (flags & UseLocalClipRectIfPossible) {
+        LayoutRect localClipRect = this->localClipRect();
+        if (localClipRect != PaintInfo::infiniteRect()) {
+            if ((flags & IncludeSelfTransform) && paintsWithTransform(PaintBehaviorNormal))
+                localClipRect = transform()->mapRect(localClipRect);
+
+            LayoutPoint ancestorRelOffset;
+            convertToLayerCoords(ancestorLayer, ancestorRelOffset);
+            localClipRect.moveBy(ancestorRelOffset);
+            return pixelSnappedIntRect(localClipRect);
+        }
+    }
+
+    // FIXME: should probably just pass 'flags' down to descendants.
+    CalculateLayerBoundsFlags descendantFlags = DefaultCalculateLayerBoundsFlags | (flags & ExcludeHiddenDescendants) | (flags & IncludeCompositedDescendants);
+
+    const_cast<RenderLayer*>(this)->updateLayerListsIfNeeded();
+
+    if (RenderLayer* reflection = reflectionLayer()) {
+        if (!reflection->isComposited()) {
+            IntRect childUnionBounds = reflection->calculateLayerBounds(this, 0, descendantFlags);
+            unionBounds.unite(childUnionBounds);
+        }
+    }
+    
+    ASSERT(isStackingContainer() || (!posZOrderList() || !posZOrderList()->size()));
+
+#if !ASSERT_DISABLED
+    LayerListMutationDetector mutationChecker(const_cast<RenderLayer*>(this));
+#endif
+
+    if (Vector<RenderLayer*>* negZOrderList = this->negZOrderList()) {
+        size_t listSize = negZOrderList->size();
+        for (size_t i = 0; i < listSize; ++i) {
+            RenderLayer* curLayer = negZOrderList->at(i);
+            if (flags & IncludeCompositedDescendants || !curLayer->isComposited()) {
+                IntRect childUnionBounds = curLayer->calculateLayerBounds(this, 0, descendantFlags);
+                unionBounds.unite(childUnionBounds);
+            }
+        }
+    }
+
+    if (Vector<RenderLayer*>* posZOrderList = this->posZOrderList()) {
+        size_t listSize = posZOrderList->size();
+        for (size_t i = 0; i < listSize; ++i) {
+            RenderLayer* curLayer = posZOrderList->at(i);
+            if (flags & IncludeCompositedDescendants || !curLayer->isComposited()) {
+                IntRect childUnionBounds = curLayer->calculateLayerBounds(this, 0, descendantFlags);
+                unionBounds.unite(childUnionBounds);
+            }
+        }
+    }
+
+    if (Vector<RenderLayer*>* normalFlowList = this->normalFlowList()) {
+        size_t listSize = normalFlowList->size();
+        for (size_t i = 0; i < listSize; ++i) {
+            RenderLayer* curLayer = normalFlowList->at(i);
+            if (flags & IncludeCompositedDescendants || !curLayer->isComposited()) {
+                IntRect curAbsBounds = curLayer->calculateLayerBounds(this, 0, descendantFlags);
+                unionBounds.unite(curAbsBounds);
+            }
+        }
+    }
+
+    // FIXME: We can optimize the size of the composited layers, by not enlarging
+    // filtered areas with the outsets if we know that the filter is going to render in hardware.
+    // https://bugs.webkit.org/show_bug.cgi?id=81239
+    if (flags & IncludeLayerFilterOutsets)
+        renderer->style()->filterOutsets().expandRect(unionBounds);
+
+    if ((flags & IncludeSelfTransform) && paintsWithTransform(PaintBehaviorNormal)) {
+        TransformationMatrix* affineTrans = transform();
+        boundingBoxRect = affineTrans->mapRect(boundingBoxRect);
+        unionBounds = affineTrans->mapRect(unionBounds);
+    }
+
+    LayoutPoint ancestorRelOffset;
+    if (offsetFromRoot)
+        ancestorRelOffset = *offsetFromRoot;
+    else
+        convertToLayerCoords(ancestorLayer, ancestorRelOffset);
+    unionBounds.moveBy(ancestorRelOffset);
+    
+    return pixelSnappedIntRect(unionBounds);
+}
+
+void RenderLayer::clearClipRectsIncludingDescendants(ClipRectsType typeToClear)
+{
+    // FIXME: it's not clear how this layer not having clip rects guarantees that no descendants have any.
+    if (!m_clipRectsCache)
+        return;
+
+    clearClipRects(typeToClear);
+    
+    for (RenderLayer* l = firstChild(); l; l = l->nextSibling())
+        l->clearClipRectsIncludingDescendants(typeToClear);
+}
+
+void RenderLayer::clearClipRects(ClipRectsType typeToClear)
+{
+    if (typeToClear == AllClipRectTypes)
+        m_clipRectsCache = nullptr;
+    else {
+        ASSERT(typeToClear < NumCachedClipRectsTypes);
+        RefPtr<ClipRects> dummy;
+        m_clipRectsCache->setClipRects(typeToClear, RespectOverflowClip, dummy);
+        m_clipRectsCache->setClipRects(typeToClear, IgnoreOverflowClip, dummy);
+    }
+}
+
+RenderLayerBacking* RenderLayer::ensureBacking()
+{
+    if (!m_backing) {
+        m_backing = adoptPtr(new RenderLayerBacking(this));
+        compositor()->layerBecameComposited(this);
+
+        updateOrRemoveFilterEffectRenderer();
+#if ENABLE(CSS_COMPOSITING)
+        backing()->setBlendMode(m_blendMode);
+#endif
+    }
+    return m_backing.get();
+}
+
+void RenderLayer::clearBacking(bool layerBeingDestroyed)
+{
+    if (m_backing && !renderer()->documentBeingDestroyed())
+        compositor()->layerBecameNonComposited(this);
+    m_backing.clear();
+
+    if (!layerBeingDestroyed)
+        updateOrRemoveFilterEffectRenderer();
+}
+
+bool RenderLayer::hasCompositedMask() const
+{
+    return m_backing && m_backing->hasMaskLayer();
+}
+
+GraphicsLayer* RenderLayer::layerForScrolling() const
+{
+    return m_backing ? m_backing->scrollingContentsLayer() : 0;
+}
+
+GraphicsLayer* RenderLayer::layerForHorizontalScrollbar() const
+{
+    return m_backing ? m_backing->layerForHorizontalScrollbar() : 0;
+}
+
+GraphicsLayer* RenderLayer::layerForVerticalScrollbar() const
+{
+    return m_backing ? m_backing->layerForVerticalScrollbar() : 0;
+}
+
+GraphicsLayer* RenderLayer::layerForScrollCorner() const
+{
+    return m_backing ? m_backing->layerForScrollCorner() : 0;
+}
+
+bool RenderLayer::paintsWithTransform(PaintBehavior paintBehavior) const
+{
+    bool paintsToWindow = !isComposited() || backing()->paintsIntoWindow();
+    return transform() && ((paintBehavior & PaintBehaviorFlattenCompositingLayers) || paintsToWindow);
+}
+
+bool RenderLayer::backgroundIsKnownToBeOpaqueInRect(const LayoutRect& localRect) const
+{
+    if (!isSelfPaintingLayer() && !hasSelfPaintingLayerDescendant())
+        return false;
+
+    if (paintsWithTransparency(PaintBehaviorNormal))
+        return false;
+
+    if (paintsWithFilters() && renderer()->style()->filter().hasFilterThatAffectsOpacity())
+        return false;
+
+    // FIXME: Handle simple transforms.
+    if (paintsWithTransform(PaintBehaviorNormal))
+        return false;
+
+    // FIXME: Remove this check.
+    // This function should not be called when layer-lists are dirty.
+    // It is somehow getting triggered during style update.
+    if (m_zOrderListsDirty || m_normalFlowListDirty)
+        return false;
+
+    // FIXME: We currently only check the immediate renderer,
+    // which will miss many cases.
+    return renderer()->backgroundIsKnownToBeOpaqueInRect(localRect)
+        || listBackgroundIsKnownToBeOpaqueInRect(posZOrderList(), localRect)
+        || listBackgroundIsKnownToBeOpaqueInRect(negZOrderList(), localRect)
+        || listBackgroundIsKnownToBeOpaqueInRect(normalFlowList(), localRect);
+}
+
+bool RenderLayer::listBackgroundIsKnownToBeOpaqueInRect(const Vector<RenderLayer*>* list, const LayoutRect& localRect) const
+{
+    if (!list || list->isEmpty())
+        return false;
+
+    for (Vector<RenderLayer*>::const_reverse_iterator iter = list->rbegin(); iter != list->rend(); ++iter) {
+        const RenderLayer* childLayer = *iter;
+        if (childLayer->isComposited())
+            continue;
+
+        if (!childLayer->canUseConvertToLayerCoords())
+            continue;
+
+        LayoutPoint childOffset;
+        LayoutRect childLocalRect(localRect);
+        childLayer->convertToLayerCoords(this, childOffset);
+        childLocalRect.moveBy(-childOffset);
+
+        if (childLayer->backgroundIsKnownToBeOpaqueInRect(childLocalRect))
+            return true;
+    }
+    return false;
+}
+
+void RenderLayer::setParent(RenderLayer* parent)
+{
+    if (parent == m_parent)
+        return;
+
+    if (m_parent && !renderer()->documentBeingDestroyed())
+        compositor()->layerWillBeRemoved(m_parent, this);
+
+    m_parent = parent;
+
+    if (m_parent && !renderer()->documentBeingDestroyed())
+        compositor()->layerWasAdded(m_parent, this);
+}
+
+// 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()
+{
+    ASSERT(m_layerListMutationAllowed);
+    ASSERT(isStackingContainer());
+
+    if (m_posZOrderList)
+        m_posZOrderList->clear();
+    if (m_negZOrderList)
+        m_negZOrderList->clear();
+    m_zOrderListsDirty = true;
+
+    m_descendantsAreContiguousInStackingOrderDirty = true;
+
+    if (!renderer()->documentBeingDestroyed()) {
+        compositor()->setCompositingLayersNeedRebuild();
+        if (acceleratedCompositingForOverflowScrollEnabled())
+            compositor()->setShouldReevaluateCompositingAfterLayout();
+    }
+}
+
+void RenderLayer::dirtyStackingContainerZOrderLists()
+{
+    RenderLayer* stackingContainer = this->ancestorStackingContainer();
+    if (stackingContainer)
+        stackingContainer->dirtyZOrderLists();
+
+    // Any change that could affect our stacking container's z-order list could
+    // cause other RenderLayers in our stacking context to either opt in or out
+    // of composited scrolling. It is important that we make our stacking
+    // context aware of these z-order changes so the appropriate updating can
+    // happen.
+    RenderLayer* stackingContext = this->ancestorStackingContext();
+    if (stackingContext && stackingContext != stackingContainer)
+        stackingContext->dirtyZOrderLists();
+}
+
+void RenderLayer::dirtyNormalFlowList()
+{
+    ASSERT(m_layerListMutationAllowed);
+
+    if (m_normalFlowList)
+        m_normalFlowList->clear();
+    m_normalFlowListDirty = true;
+
+    if (!renderer()->documentBeingDestroyed()) {
+        compositor()->setCompositingLayersNeedRebuild();
+        if (acceleratedCompositingForOverflowScrollEnabled())
+            compositor()->setShouldReevaluateCompositingAfterLayout();
+    }
+}
+
+void RenderLayer::rebuildZOrderLists()
+{
+    ASSERT(m_layerListMutationAllowed);
+    ASSERT(isDirtyStackingContainer());
+    rebuildZOrderLists(StopAtStackingContainers, m_posZOrderList, m_negZOrderList);
+    m_zOrderListsDirty = false;
+}
+
+void RenderLayer::rebuildZOrderLists(CollectLayersBehavior behavior, OwnPtr<Vector<RenderLayer*> >& posZOrderList, OwnPtr<Vector<RenderLayer*> >& negZOrderList, const RenderLayer* layerToForceAsStackingContainer)
+{
+    bool includeHiddenLayers = compositor()->inCompositingMode();
+    for (RenderLayer* child = firstChild(); child; child = child->nextSibling())
+        if (!m_reflection || reflectionLayer() != child)
+            child->collectLayers(includeHiddenLayers, behavior, posZOrderList, negZOrderList, layerToForceAsStackingContainer);
+
+    // Sort the two lists.
+    if (posZOrderList)
+        std::stable_sort(posZOrderList->begin(), posZOrderList->end(), compareZIndex);
+
+    if (negZOrderList)
+        std::stable_sort(negZOrderList->begin(), negZOrderList->end(), compareZIndex);
+
+    // Append layers for top layer elements after normal layer collection, to ensure they are on top regardless of z-indexes.
+    // The renderers of top layer elements are children of the view, sorted in top layer stacking order.
+    if (isRootLayer()) {
+        RenderObject* view = renderer()->view();
+        for (RenderObject* child = view->firstChild(); child; child = child->nextSibling()) {
+            Element* childElement = (child->node() && child->node()->isElementNode()) ? toElement(child->node()) : 0;
+            if (childElement && childElement->isInTopLayer()) {
+                RenderLayer* layer = toRenderLayerModelObject(child)->layer();
+                posZOrderList->append(layer);
+            }
+        }
+    }
+}
+
+void RenderLayer::updateNormalFlowList()
+{
+    if (!m_normalFlowListDirty)
+        return;
+
+    ASSERT(m_layerListMutationAllowed);
+
+    for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
+        // Ignore non-overflow layers and reflections.
+        if (child->isNormalFlowOnly() && (!m_reflection || reflectionLayer() != child)) {
+            if (!m_normalFlowList)
+                m_normalFlowList = adoptPtr(new Vector<RenderLayer*>);
+            m_normalFlowList->append(child);
+        }
+    }
+    
+    m_normalFlowListDirty = false;
+}
+
+void RenderLayer::collectLayers(bool includeHiddenLayers, CollectLayersBehavior behavior, OwnPtr<Vector<RenderLayer*> >& posBuffer, OwnPtr<Vector<RenderLayer*> >& negBuffer, const RenderLayer* layerToForceAsStackingContainer)
+{
+    if (isInTopLayer())
+        return;
+
+    updateDescendantDependentFlags();
+
+    bool isStacking = false;
+
+    switch (behavior) {
+        case StopAtStackingContexts:
+            isStacking = (this == layerToForceAsStackingContainer) || isStackingContext();
+            break;
+
+        case StopAtStackingContainers:
+            isStacking = (this == layerToForceAsStackingContainer) || isStackingContainer();
+            break;
+    }
+
+    // Overflow layers are just painted by their enclosing layers, so they don't get put in zorder lists.
+    bool includeHiddenLayer = includeHiddenLayers || (m_hasVisibleContent || (m_hasVisibleDescendant && isStacking));
+    if (includeHiddenLayer && !isNormalFlowOnly() && !isOutOfFlowRenderFlowThread()) {
+        // Determine which buffer the child should be in.
+        OwnPtr<Vector<RenderLayer*> >& buffer = (zIndex() >= 0) ? posBuffer : negBuffer;
+
+        // Create the buffer if it doesn't exist yet.
+        if (!buffer)
+            buffer = adoptPtr(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/container.
+    if ((includeHiddenLayers || m_hasVisibleDescendant) && !isStacking) {
+        for (RenderLayer* child = firstChild(); child; child = child->nextSibling()) {
+            // Ignore reflections.
+            if (!m_reflection || reflectionLayer() != child)
+                child->collectLayers(includeHiddenLayers, behavior, posBuffer, negBuffer, layerToForceAsStackingContainer);
+        }
+    }
+}
+
+void RenderLayer::updateLayerListsIfNeeded()
+{
+    bool shouldUpdateDescendantsAreContiguousInStackingOrder = acceleratedCompositingForOverflowScrollEnabled() && isStackingContext() && (m_zOrderListsDirty || m_normalFlowListDirty) && m_descendantsAreContiguousInStackingOrderDirty;
+    updateZOrderLists();
+    updateNormalFlowList();
+
+    if (RenderLayer* reflectionLayer = this->reflectionLayer()) {
+        reflectionLayer->updateZOrderLists();
+        reflectionLayer->updateNormalFlowList();
+    }
+
+    if (shouldUpdateDescendantsAreContiguousInStackingOrder) {
+        updateDescendantsAreContiguousInStackingOrder();
+        // The above function can cause us to update m_needsCompositedScrolling
+        // and dirty our layer lists. Refresh them if necessary.
+        updateZOrderLists();
+        updateNormalFlowList();
+    }
+}
+
+void RenderLayer::repaintIncludingDescendants()
+{
+    renderer()->repaint();
+    for (RenderLayer* curr = firstChild(); curr; curr = curr->nextSibling())
+        curr->repaintIncludingDescendants();
+}
+
+void RenderLayer::setBackingNeedsRepaint()
+{
+    ASSERT(isComposited());
+    if (backing()->paintsIntoWindow()) {
+        // If we're trying to repaint the placeholder document layer, propagate the
+        // repaint to the native view system.
+        RenderView* view = renderer()->view();
+        if (view)
+            view->repaintViewRectangle(absoluteBoundingBox());
+    } else
+        backing()->setContentsNeedDisplay();
+}
+
+void RenderLayer::setBackingNeedsRepaintInRect(const LayoutRect& r)
+{
+    // https://bugs.webkit.org/show_bug.cgi?id=61159 describes an unreproducible crash here,
+    // so assert but check that the layer is composited.
+    ASSERT(isComposited());
+    if (!isComposited() || backing()->paintsIntoWindow()) {
+        // If we're trying to repaint the placeholder document layer, propagate the
+        // repaint to the native view system.
+        LayoutRect absRect(r);
+        LayoutPoint delta;
+        convertToLayerCoords(root(), delta);
+        absRect.moveBy(delta);
+
+        RenderView* view = renderer()->view();
+        if (view)
+            view->repaintViewRectangle(absRect);
+    } else
+        backing()->setContentsNeedDisplayInRect(pixelSnappedIntRect(r));
+}
+
+// Since we're only painting non-composited layers, we know that they all share the same repaintContainer.
+void RenderLayer::repaintIncludingNonCompositingDescendants(RenderLayerModelObject* repaintContainer)
+{
+    renderer()->repaintUsingContainer(repaintContainer, pixelSnappedIntRect(renderer()->clippedOverflowRectForRepaint(repaintContainer)));
+
+    for (RenderLayer* curr = firstChild(); curr; curr = curr->nextSibling()) {
+        if (!curr->isComposited())
+            curr->repaintIncludingNonCompositingDescendants(repaintContainer);
+    }
+}
+
+bool RenderLayer::shouldBeNormalFlowOnly() const
+{
+    return (renderer()->hasOverflowClip()
+                || renderer()->hasReflection()
+                || renderer()->hasMask()
+                || renderer()->isCanvas()
+                || renderer()->isVideo()
+                || renderer()->isEmbeddedObject()
+                || renderer()->isRenderIFrame()
+                || (renderer()->style()->specifiesColumns() && !isRootLayer()))
+            && !renderer()->isPositioned()
+            && !renderer()->hasTransform()
+            && !renderer()->hasClipPath()
+            && !renderer()->hasFilter()
+#if ENABLE(CSS_COMPOSITING)
+            && !renderer()->hasBlendMode()
+#endif
+            && !isTransparent()
+            && !needsCompositedScrolling()
+            && !renderer()->isFloatingWithShapeOutside()
+            ;
+}
+
+void RenderLayer::updateIsNormalFlowOnly()
+{
+    bool isNormalFlowOnly = shouldBeNormalFlowOnly();
+    if (isNormalFlowOnly == m_isNormalFlowOnly)
+        return;
+
+    m_isNormalFlowOnly = isNormalFlowOnly;
+    if (RenderLayer* p = parent())
+        p->dirtyNormalFlowList();
+    dirtyStackingContainerZOrderLists();
+}
+
+bool RenderLayer::shouldBeSelfPaintingLayer() const
+{
+    return !isNormalFlowOnly()
+        || hasOverlayScrollbars()
+        || needsCompositedScrolling()
+        || renderer()->hasReflection()
+        || renderer()->hasMask()
+        || renderer()->isTableRow()
+        || renderer()->isCanvas()
+        || renderer()->isVideo()
+        || renderer()->isEmbeddedObject()
+        || renderer()->isRenderIFrame();
+}
+
+void RenderLayer::updateSelfPaintingLayer()
+{
+    bool isSelfPaintingLayer = shouldBeSelfPaintingLayer();
+    if (m_isSelfPaintingLayer == isSelfPaintingLayer)
+        return;
+
+    m_isSelfPaintingLayer = isSelfPaintingLayer;
+    if (!parent())
+        return;
+    if (isSelfPaintingLayer)
+        parent()->setAncestorChainHasSelfPaintingLayerDescendant();
+    else
+        parent()->dirtyAncestorChainHasSelfPaintingLayerDescendantStatus();
+}
+
+bool RenderLayer::hasNonEmptyChildRenderers() const
+{
+    // Some HTML can cause whitespace text nodes to have renderers, like:
+    // <div>
+    // <img src=...>
+    // </div>
+    // so test for 0x0 RenderTexts here
+    for (RenderObject* child = renderer()->firstChild(); child; child = child->nextSibling()) {
+        if (!child->hasLayer()) {
+            if (child->isRenderInline() || !child->isBox())
+                return true;
+        
+            if (toRenderBox(child)->width() > 0 || toRenderBox(child)->height() > 0)
+                return true;
+        }
+    }
+    return false;
+}
+
+static bool hasBoxDecorations(const RenderStyle* style)
+{
+    return style->hasBorder() || style->hasBorderRadius() || style->hasOutline() || style->hasAppearance() || style->boxShadow() || style->hasFilter();
+}
+
+bool RenderLayer::hasBoxDecorationsOrBackground() const
+{
+    return hasBoxDecorations(renderer()->style()) || renderer()->hasBackground();
+}
+
+bool RenderLayer::hasVisibleBoxDecorations() const
+{
+    if (!hasVisibleContent())
+        return false;
+
+    return hasBoxDecorationsOrBackground() || hasOverflowControls();
+}
+
+bool RenderLayer::isVisuallyNonEmpty() const
+{
+    ASSERT(!m_visibleDescendantStatusDirty);
+
+    if (hasVisibleContent() && hasNonEmptyChildRenderers())
+        return true;
+
+    if (renderer()->isReplaced() || renderer()->hasMask())
+        return true;
+
+    if (hasVisibleBoxDecorations())
+        return true;
+
+    return false;
+}
+
+void RenderLayer::updateVisibilityAfterStyleChange(const RenderStyle* oldStyle)
+{
+    EVisibility oldVisibility = oldStyle ? oldStyle->visibility() : VISIBLE;
+    if (oldVisibility == renderer()->style()->visibility() || !renderer()->isOutOfFlowPositioned())
+        return;
+
+    if (renderer()->style()->visibility() == VISIBLE)
+        setAncestorChainHasOutOfFlowPositionedDescendant(renderer()->containingBlock());
+    else
+        dirtyAncestorChainHasOutOfFlowPositionedDescendantStatus();
+}
+
+void RenderLayer::updateStackingContextsAfterStyleChange(const RenderStyle* oldStyle)
+{
+    bool wasStackingContext = oldStyle ? isStackingContext(oldStyle) : false;
+    EVisibility oldVisibility = oldStyle ? oldStyle->visibility() : VISIBLE;
+    int oldZIndex = oldStyle ? oldStyle->zIndex() : 0;
+
+    // FIXME: RenderLayer already handles visibility changes through our visiblity dirty bits. This logic could
+    // likely be folded along with the rest.
+    bool isStackingContext = this->isStackingContext();
+    if (isStackingContext == wasStackingContext && oldVisibility == renderer()->style()->visibility() && oldZIndex == renderer()->style()->zIndex())
+        return;
+
+    dirtyStackingContainerZOrderLists();
+
+    if (isStackingContainer())
+        dirtyZOrderLists();
+    else
+        clearZOrderLists();
+
+    updateNeedsCompositedScrolling();
+}
+
+static bool overflowRequiresScrollbar(EOverflow overflow)
+{
+    return overflow == OSCROLL;
+}
+
+static bool overflowDefinesAutomaticScrollbar(EOverflow overflow)
+{
+    return overflow == OAUTO || overflow == OOVERLAY;
+}
+
+void RenderLayer::updateScrollbarsAfterStyleChange(const RenderStyle* oldStyle)
+{
+    // Overflow are a box concept.
+    RenderBox* box = renderBox();
+    if (!box)
+        return;
+
+    // List box parts handle the scrollbars by themselves so we have nothing to do.
+    if (box->style()->appearance() == ListboxPart)
+        return;
+
+    EOverflow overflowX = box->style()->overflowX();
+    EOverflow overflowY = box->style()->overflowY();
+
+    // To avoid doing a relayout in updateScrollbarsAfterLayout, we try to keep any automatic scrollbar that was already present.
+    bool needsHorizontalScrollbar = (hasHorizontalScrollbar() && overflowDefinesAutomaticScrollbar(overflowX)) || overflowRequiresScrollbar(overflowX);
+    bool needsVerticalScrollbar = (hasVerticalScrollbar() && overflowDefinesAutomaticScrollbar(overflowY)) || overflowRequiresScrollbar(overflowY);
+    setHasHorizontalScrollbar(needsHorizontalScrollbar);
+    setHasVerticalScrollbar(needsVerticalScrollbar);
+
+    // With overflow: scroll, scrollbars are always visible but may be disabled.
+    // When switching to another value, we need to re-enable them (see bug 11985).
+    if (needsHorizontalScrollbar && oldStyle && oldStyle->overflowX() == OSCROLL && overflowX != OSCROLL) {
+        ASSERT(hasHorizontalScrollbar());
+        m_hBar->setEnabled(true);
+    }
+
+    if (needsVerticalScrollbar && oldStyle && oldStyle->overflowY() == OSCROLL && overflowY != OSCROLL) {
+        ASSERT(hasVerticalScrollbar());
+        m_vBar->setEnabled(true);
+    }
+
+    if (!m_scrollDimensionsDirty)
+        updateScrollableAreaSet(hasScrollableHorizontalOverflow() || hasScrollableVerticalOverflow());
+}
+
+void RenderLayer::setAncestorChainHasOutOfFlowPositionedDescendant(RenderObject* containingBlock)
+{
+    for (RenderLayer* layer = this; layer; layer = layer->parent()) {
+        if (!layer->m_hasOutOfFlowPositionedDescendantDirty && layer->hasOutOfFlowPositionedDescendant())
+            break;
+
+        layer->m_hasOutOfFlowPositionedDescendantDirty = false;
+        layer->m_hasOutOfFlowPositionedDescendant = true;
+        layer->updateNeedsCompositedScrolling();
+
+        if (layer->renderer() && layer->renderer() == containingBlock)
+            break;
+    }
+}
+
+void RenderLayer::dirtyAncestorChainHasOutOfFlowPositionedDescendantStatus()
+{
+    if (m_hasOutOfFlowPositionedDescendant) {
+        m_hasOutOfFlowPositionedDescendantDirty = true;
+        // FIXME It would be nice to avoid this when we clean up render layer
+        // updating. We shouldn't have to update the composited scrolling state
+        // nearly as frequently if all the updates happen in a single, well
+        // defined phase.
+        updateNeedsCompositedScrolling();
+    }
+
+    if (parent())
+        parent()->dirtyAncestorChainHasOutOfFlowPositionedDescendantStatus();
+}
+
+void RenderLayer::updateOutOfFlowPositioned(const RenderStyle* oldStyle)
+{
+    bool wasOutOfFlowPositioned = oldStyle && (oldStyle->position() == AbsolutePosition || oldStyle->position() == FixedPosition);
+    bool isOutOfFlowPositioned = renderer()->isOutOfFlowPositioned();
+    if (parent() && isOutOfFlowPositioned != wasOutOfFlowPositioned) {
+        if (isOutOfFlowPositioned)
+            parent()->setAncestorChainHasOutOfFlowPositionedDescendant(renderer()->containingBlock());
+        else
+            parent()->dirtyAncestorChainHasOutOfFlowPositionedDescendantStatus();
+    }
+}
+
+static bool hasOrHadFilters(const RenderStyle* oldStyle, const RenderStyle* newStyle)
+{
+    ASSERT(newStyle);
+    return (oldStyle && oldStyle->hasFilter()) || newStyle->hasFilter();
+}
+
+inline bool RenderLayer::needsCompositingLayersRebuiltForClip(const RenderStyle* oldStyle, const RenderStyle* newStyle) const
+{
+    ASSERT(newStyle);
+    return oldStyle && (oldStyle->clip() != newStyle->clip() || oldStyle->hasClip() != newStyle->hasClip());
+}
+
+inline bool RenderLayer::needsCompositingLayersRebuiltForOverflow(const RenderStyle* oldStyle, const RenderStyle* newStyle) const
+{
+    ASSERT(newStyle);
+    return !isComposited() && oldStyle && (oldStyle->overflowX() != newStyle->overflowX()) && ancestorStackingContainer()->hasCompositingDescendant();
+}
+
+inline bool RenderLayer::needsCompositingLayersRebuiltForFilters(const RenderStyle* oldStyle, const RenderStyle* newStyle, bool didPaintWithFilters) const
+{
+    if (!hasOrHadFilters(oldStyle, newStyle))
+        return false;
+
+    if (renderer()->animation()->isRunningAcceleratedAnimationOnRenderer(renderer(), CSSPropertyWebkitFilter)) {
+        // When the compositor is performing the filter animation, we shouldn't touch the compositing layers.
+        // All of the layers above us should have been promoted to compositing layers already.
+        return false;
+    }
+
+    FilterOutsets newOutsets = newStyle->filterOutsets();
+    if (oldStyle && (oldStyle->filterOutsets() != newOutsets)) {
+        // When filter outsets change, we need to:
+        // (1) Recompute the overlap map to promote the correct layers to composited layers.
+        // (2) Update the composited layer bounds (and child GraphicsLayer positions) on platforms
+        //     whose compositors can't compute their own filter outsets.
+        return true;
+    }
+
+#if HAVE(COMPOSITOR_FILTER_OUTSETS)
+    if ((didPaintWithFilters != paintsWithFilters()) && !newOutsets.isZero()) {
+        // When the layer used to paint filters in software and now paints filters in the
+        // compositor, the compositing layer bounds need to change from including filter outsets to
+        // excluding filter outsets, on platforms whose compositors compute their own outsets.
+        // Similarly for the reverse change from compositor-painted to software-painted filters.
+        return true;
+    }
+#endif
+
+    return false;
+}
+
+void RenderLayer::updateFilters(const RenderStyle* oldStyle, const RenderStyle* newStyle)
+{
+    if (!hasOrHadFilters(oldStyle, newStyle))
+        return;
+
+    updateOrRemoveFilterClients();
+    // During an accelerated animation, both WebKit and the compositor animate properties.
+    // However, WebKit shouldn't ask the compositor to update its filters if the compositor is performing the animation.
+    bool shouldUpdateFilters = isComposited() && !renderer()->animation()->isRunningAcceleratedAnimationOnRenderer(renderer(), CSSPropertyWebkitFilter);
+    if (shouldUpdateFilters)
+        backing()->updateFilters(renderer()->style());
+    updateOrRemoveFilterEffectRenderer();
+    // FIXME: Accelerated SVG reference filters still rely on FilterEffectRenderer to build the filter graph.
+    // Thus, we have to call updateFilters again, after we have a FilterEffectRenderer.
+    // FilterEffectRenderer is intended to render software filters and shouldn't be needed for accelerated filters.
+    // We should extract the SVG graph building functionality out of FilterEffectRenderer, and it should happen in RenderLayer::computeFilterOperations.
+    // https://bugs.webkit.org/show_bug.cgi?id=114051
+    if (shouldUpdateFilters && newStyle->filter().hasReferenceFilter())
+        backing()->updateFilters(renderer()->style());
+}
+
+void RenderLayer::styleChanged(StyleDifference, const RenderStyle* oldStyle)
+{
+    updateIsNormalFlowOnly();
+
+    if (renderer()->style()->overflowX() == OMARQUEE && renderer()->style()->marqueeBehavior() != MNONE && renderer()->isBox()) {
+        if (!m_marquee)
+            m_marquee = adoptPtr(new RenderMarquee(this));
+        UseCounter::count(renderer()->document(), renderer()->isHTMLMarquee() ? UseCounter::HTMLMarqueeElement : UseCounter::CSSOverflowMarquee);
+        m_marquee->updateMarqueeStyle();
+    }
+    else if (m_marquee) {
+        m_marquee.clear();
+    }
+
+    updateScrollbarsAfterStyleChange(oldStyle);
+    updateStackingContextsAfterStyleChange(oldStyle);
+    updateVisibilityAfterStyleChange(oldStyle);
+    // Overlay scrollbars can make this layer self-painting so we need
+    // to recompute the bit once scrollbars have been updated.
+    updateSelfPaintingLayer();
+    updateOutOfFlowPositioned(oldStyle);
+
+    if (!hasReflection() && m_reflection)
+        removeReflection();
+    else if (hasReflection()) {
+        if (!m_reflection)
+            createReflection();
+        UseCounter::count(renderer()->document(), UseCounter::Reflection);
+        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();
+
+    updateDescendantDependentFlags();
+    updateTransform();
+#if ENABLE(CSS_COMPOSITING)
+    updateBlendMode();
+#endif
+
+    bool didPaintWithFilters = false;
+
+    if (paintsWithFilters())
+        didPaintWithFilters = true;
+    updateFilters(oldStyle, renderer()->style());
+
+    const RenderStyle* newStyle = renderer()->style();
+    if (compositor()->updateLayerCompositingState(this)
+        || needsCompositingLayersRebuiltForClip(oldStyle, newStyle)
+        || needsCompositingLayersRebuiltForOverflow(oldStyle, newStyle)
+        || needsCompositingLayersRebuiltForFilters(oldStyle, newStyle, didPaintWithFilters))
+        compositor()->setCompositingLayersNeedRebuild();
+    else if (isComposited())
+        backing()->updateGraphicsLayerGeometry();
+}
+
+void RenderLayer::updateScrollableAreaSet(bool hasOverflow)
+{
+    Frame* frame = renderer()->frame();
+    if (!frame)
+        return;
+
+    FrameView* frameView = frame->view();
+    if (!frameView)
+        return;
+
+    bool isVisibleToHitTest = renderer()->visibleToHitTesting();
+    if (HTMLFrameOwnerElement* owner = frame->ownerElement())
+        isVisibleToHitTest &= owner->renderer() && owner->renderer()->visibleToHitTesting();
+
+    bool updatedScrollableAreaSet = false;
+    if (hasOverflow && isVisibleToHitTest)
+        updatedScrollableAreaSet = frameView->addScrollableArea(this);
+    else
+        updatedScrollableAreaSet = frameView->removeScrollableArea(this);
+
+    if (updatedScrollableAreaSet)
+        updateNeedsCompositedScrolling();
+}
+
+void RenderLayer::updateScrollCornerStyle()
+{
+    RenderObject* actualRenderer = rendererForScrollbar(renderer());
+    RefPtr<RenderStyle> corner = renderer()->hasOverflowClip() ? actualRenderer->getUncachedPseudoStyle(PseudoStyleRequest(SCROLLBAR_CORNER), actualRenderer->style()) : PassRefPtr<RenderStyle>(0);
+    if (corner) {
+        if (!m_scrollCorner) {
+            m_scrollCorner = RenderScrollbarPart::createAnonymous(renderer()->document());
+            m_scrollCorner->setParent(renderer());
+        }
+        m_scrollCorner->setStyle(corner.release());
+    } else if (m_scrollCorner) {
+        m_scrollCorner->destroy();
+        m_scrollCorner = 0;
+    }
+}
+
+void RenderLayer::updateResizerStyle()
+{
+    RenderObject* actualRenderer = rendererForScrollbar(renderer());
+    RefPtr<RenderStyle> resizer = renderer()->hasOverflowClip() ? actualRenderer->getUncachedPseudoStyle(PseudoStyleRequest(RESIZER), actualRenderer->style()) : PassRefPtr<RenderStyle>(0);
+    if (resizer) {
+        if (!m_resizer) {
+            m_resizer = RenderScrollbarPart::createAnonymous(renderer()->document());
+            m_resizer->setParent(renderer());
+        }
+        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 = RenderReplica::createAnonymous(renderer()->document());
+    m_reflection->setParent(renderer()); // We create a 1-way connection.
+}
+
+void RenderLayer::removeReflection()
+{
+    if (!m_reflection->documentBeingDestroyed())
+        m_reflection->removeLayers(this);
+
+    m_reflection->setParent(0);
+    m_reflection->destroy();
+    m_reflection = 0;
+}
+
+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());
+}
+
+bool RenderLayer::isCSSCustomFilterEnabled() const
+{
+    // We only want to enable shaders if WebGL is also enabled on this platform.
+    const Settings* settings = renderer()->document()->settings();
+    return settings && settings->isCSSCustomFilterEnabled() && settings->webGLEnabled();
+}
+
+FilterOperations RenderLayer::computeFilterOperations(const RenderStyle* style)
+{
+    const FilterOperations& filters = style->filter();
+    if (!filters.hasCustomFilter())
+        return filters;
+
+    if (!isCSSCustomFilterEnabled()) {
+        // CSS Custom filters should not parse at all in this case, but there might be
+        // remaining styles that were parsed when the flag was enabled. Reproduces in DumpRenderTree
+        // because it resets the flag while the previous test is still loaded.
+        return FilterOperations();
+    }
+
+    FilterOperations outputFilters;
+    for (size_t i = 0; i < filters.size(); ++i) {
+        RefPtr<FilterOperation> filterOperation = filters.operations().at(i);
+        if (filterOperation->getOperationType() == FilterOperation::CUSTOM) {
+            // We have to wait until the program of CSS Shaders is loaded before setting it on the layer.
+            // Note that we will handle the loading of the shaders and repainting of the layer in updateOrRemoveFilterClients.
+            const CustomFilterOperation* customOperation = static_cast<const CustomFilterOperation*>(filterOperation.get());
+            RefPtr<CustomFilterProgram> program = customOperation->program();
+            if (!program->isLoaded())
+                continue;
+            
+            CustomFilterGlobalContext* globalContext = renderer()->view()->customFilterGlobalContext();
+            RefPtr<CustomFilterValidatedProgram> validatedProgram = globalContext->getValidatedProgram(program->programInfo());
+            if (!validatedProgram->isInitialized())
+                continue;
+
+            RefPtr<ValidatedCustomFilterOperation> validatedOperation = ValidatedCustomFilterOperation::create(validatedProgram.release(), 
+                customOperation->parameters(), customOperation->meshRows(), customOperation->meshColumns(), customOperation->meshType());
+            outputFilters.operations().append(validatedOperation.release());
+            continue;
+        }
+        outputFilters.operations().append(filterOperation.release());
+    }
+    return outputFilters;
+}
+
+void RenderLayer::updateOrRemoveFilterClients()
+{
+    if (!hasFilter()) {
+        removeFilterInfoIfNeeded();
+        return;
+    }
+
+    if (renderer()->style()->filter().hasCustomFilter())
+        ensureFilterInfo()->updateCustomFilterClients(renderer()->style()->filter());
+    else if (hasFilterInfo())
+        filterInfo()->removeCustomFilterClients();
+
+#if ENABLE(SVG)
+    if (renderer()->style()->filter().hasReferenceFilter())
+        ensureFilterInfo()->updateReferenceFilterClients(renderer()->style()->filter());
+    else if (hasFilterInfo())
+        filterInfo()->removeReferenceFilterClients();
+#endif
+}
+
+void RenderLayer::updateOrRemoveFilterEffectRenderer()
+{
+    // FilterEffectRenderer is only used to render the filters in software mode,
+    // so we always need to run updateOrRemoveFilterEffectRenderer after the composited
+    // mode might have changed for this layer.
+    if (!paintsWithFilters()) {
+        // Don't delete the whole filter info here, because we might use it
+        // for loading CSS shader files.
+        if (RenderLayerFilterInfo* filterInfo = this->filterInfo())
+            filterInfo->setRenderer(0);
+
+        // FIXME: Accelerated SVG reference filters shouldn't rely on FilterEffectRenderer to build the filter graph.
+        // https://bugs.webkit.org/show_bug.cgi?id=114051
+
+        // Early-return only if we *don't* have reference filters.
+        // For reference filters, we still want the FilterEffect graph built
+        // for us, even if we're composited.
+        if (!renderer()->style()->filter().hasReferenceFilter())
+            return;
+    }
+    
+    RenderLayerFilterInfo* filterInfo = ensureFilterInfo();
+    if (!filterInfo->renderer()) {
+        RefPtr<FilterEffectRenderer> filterRenderer = FilterEffectRenderer::create();
+        RenderingMode renderingMode = renderer()->frame()->page()->settings()->acceleratedFiltersEnabled() ? Accelerated : Unaccelerated;
+        filterRenderer->setRenderingMode(renderingMode);
+        filterInfo->setRenderer(filterRenderer.release());
+        
+        // We can optimize away code paths in other places if we know that there are no software filters.
+        renderer()->document()->view()->setHasSoftwareFilters(true);
+    }
+
+    // If the filter fails to build, remove it from the layer. It will still attempt to
+    // go through regular processing (e.g. compositing), but never apply anything.
+    if (!filterInfo->renderer()->build(renderer(), computeFilterOperations(renderer()->style())))
+        filterInfo->setRenderer(0);
+}
+
+void RenderLayer::filterNeedsRepaint()
+{
+    renderer()->node()->setNeedsStyleRecalc(SyntheticStyleChange);
+    if (renderer()->view())
+        renderer()->repaint();
+}
+
+void RenderLayer::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::Rendering);
+    ScrollableArea::reportMemoryUsage(memoryObjectInfo);
+    info.addWeakPointer(m_renderer);
+    info.addWeakPointer(m_parent);
+    info.addWeakPointer(m_previous);
+    info.addWeakPointer(m_next);
+    info.addWeakPointer(m_first);
+    info.addWeakPointer(m_last);
+    info.addMember(m_hBar, "hBar");
+    info.addMember(m_vBar, "vBar");
+    info.addMember(m_posZOrderList, "posZOrderList");
+    info.addMember(m_negZOrderList, "negZOrderList");
+    info.addMember(m_normalFlowList, "normalFlowList");
+    info.addMember(m_clipRectsCache, "clipRectsCache");
+    info.addMember(m_marquee, "marquee");
+    info.addMember(m_transform, "transform");
+    info.addWeakPointer(m_reflection);
+    info.addWeakPointer(m_scrollCorner);
+    info.addWeakPointer(m_resizer);
+    info.addMember(m_backing, "backing");
+    info.setCustomAllocation(true);
+}
+
+} // namespace WebCore
+
+#ifndef NDEBUG
+void showLayerTree(const WebCore::RenderLayer* layer)
+{
+    if (!layer)
+        return;
+
+    if (WebCore::Frame* frame = layer->renderer()->frame()) {
+        WTF::String output = externalRepresentation(frame, WebCore::RenderAsTextShowAllLayers | WebCore::RenderAsTextShowLayerNesting | WebCore::RenderAsTextShowCompositedLayers | WebCore::RenderAsTextShowAddresses | WebCore::RenderAsTextShowIDAndClass | WebCore::RenderAsTextDontUpdateLayout | WebCore::RenderAsTextShowLayoutState);
+        fprintf(stderr, "%s\n", output.utf8().data());
+    }
+}
+
+void showLayerTree(const WebCore::RenderObject* renderer)
+{
+    if (!renderer)
+        return;
+    showLayerTree(renderer->enclosingLayer());
+}
+#endif
diff --git a/Source/core/rendering/RenderLayer.h b/Source/core/rendering/RenderLayer.h
new file mode 100644
index 0000000..eebc9b1
--- /dev/null
+++ b/Source/core/rendering/RenderLayer.h
@@ -0,0 +1,1321 @@
+/*
+ * Copyright (C) 2003, 2009, 2012 Apple Inc. All rights reserved.
+ *
+ * Portions are Copyright (C) 1998 Netscape Communications Corporation.
+ *
+ * Other contributors:
+ *   Robert O'Callahan <roc+@cs.cmu.edu>
+ *   David Baron <dbaron@fas.harvard.edu>
+ *   Christian Biesinger <cbiesinger@web.de>
+ *   Randall Jesup <rjesup@wgate.com>
+ *   Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
+ *   Josh Soref <timeless@mac.com>
+ *   Boris Zbarsky <bzbarsky@mit.edu>
+ *
+ * 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 "core/platform/ScrollableArea.h"
+#include "core/rendering/PaintInfo.h"
+#include "core/rendering/RenderBox.h"
+#include <wtf/OwnPtr.h>
+
+#include "core/rendering/RenderLayerFilterInfo.h"
+
+namespace WebCore {
+
+class FilterEffectRenderer;
+class FilterOperations;
+class HitTestRequest;
+class HitTestResult;
+class HitTestingTransformState;
+class RenderFlowThread;
+class RenderGeometryMap;
+class RenderLayerBacking;
+class RenderLayerCompositor;
+class RenderMarquee;
+class RenderReplica;
+class RenderScrollbarPart;
+class RenderStyle;
+class RenderView;
+class Scrollbar;
+class TransformationMatrix;
+
+enum BorderRadiusClippingRule { IncludeSelfForBorderRadius, DoNotIncludeSelfForBorderRadius };
+
+enum RepaintStatus {
+    NeedsNormalRepaint = 0,
+    NeedsFullRepaint = 1 << 0,
+    NeedsFullRepaintForPositionedMovementLayout = 1 << 1
+};
+
+class ClipRect {
+public:
+    ClipRect()
+    : m_hasRadius(false)
+    { }
+    
+    ClipRect(const LayoutRect& rect)
+    : m_rect(rect)
+    , m_hasRadius(false)
+    { }
+    
+    const LayoutRect& rect() const { return m_rect; }
+    void setRect(const LayoutRect& rect) { m_rect = rect; }
+
+    bool hasRadius() const { return m_hasRadius; }
+    void setHasRadius(bool hasRadius) { m_hasRadius = hasRadius; }
+
+    bool operator==(const ClipRect& other) const { return rect() == other.rect() && hasRadius() == other.hasRadius(); }
+    bool operator!=(const ClipRect& other) const { return rect() != other.rect() || hasRadius() != other.hasRadius(); }
+    bool operator!=(const LayoutRect& otherRect) const { return rect() != otherRect; }
+
+    void intersect(const LayoutRect& other) { m_rect.intersect(other); }
+    void intersect(const ClipRect& other)
+    {
+        m_rect.intersect(other.rect());
+        if (other.hasRadius())
+            m_hasRadius = true;
+    }
+    void move(LayoutUnit x, LayoutUnit y) { m_rect.move(x, y); }
+    void move(const LayoutSize& size) { m_rect.move(size); }
+    void moveBy(const LayoutPoint& point) { m_rect.moveBy(point); }
+
+    bool isEmpty() const { return m_rect.isEmpty(); }
+    bool intersects(const LayoutRect& rect) const { return m_rect.intersects(rect); }
+    bool intersects(const HitTestLocation&) const;
+
+private:
+    LayoutRect m_rect;
+    bool m_hasRadius;
+};
+
+inline ClipRect intersection(const ClipRect& a, const ClipRect& b)
+{
+    ClipRect c = a;
+    c.intersect(b);
+    return c;
+}
+
+class ClipRects {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    static PassRefPtr<ClipRects> create()
+    {
+        return adoptRef(new ClipRects);
+    }
+
+    static PassRefPtr<ClipRects> create(const ClipRects& other)
+    {
+        return adoptRef(new ClipRects(other));
+    }
+
+    ClipRects()
+        : m_refCnt(1)
+        , m_fixed(false)
+    {
+    }
+
+    void reset(const LayoutRect& r)
+    {
+        m_overflowClipRect = r;
+        m_fixedClipRect = r;
+        m_posClipRect = r;
+        m_fixed = false;
+    }
+    
+    const ClipRect& overflowClipRect() const { return m_overflowClipRect; }
+    void setOverflowClipRect(const ClipRect& r) { m_overflowClipRect = r; }
+
+    const ClipRect& fixedClipRect() const { return m_fixedClipRect; }
+    void setFixedClipRect(const ClipRect&r) { m_fixedClipRect = r; }
+
+    const ClipRect& posClipRect() const { return m_posClipRect; }
+    void setPosClipRect(const ClipRect& r) { m_posClipRect = r; }
+
+    bool fixed() const { return m_fixed; }
+    void setFixed(bool fixed) { m_fixed = fixed; }
+
+    void ref() { m_refCnt++; }
+    void deref()
+    {
+        if (!--m_refCnt)
+            delete this;
+    }
+
+    bool operator==(const ClipRects& other) const
+    {
+        return m_overflowClipRect == other.overflowClipRect() &&
+               m_fixedClipRect == other.fixedClipRect() &&
+               m_posClipRect == other.posClipRect() &&
+               m_fixed == other.fixed();
+    }
+
+    ClipRects& operator=(const ClipRects& other)
+    {
+        m_overflowClipRect = other.overflowClipRect();
+        m_fixedClipRect = other.fixedClipRect();
+        m_posClipRect = other.posClipRect();
+        m_fixed = other.fixed();
+        return *this;
+    }
+
+private:
+    ClipRects(const LayoutRect& r)
+        : m_overflowClipRect(r)
+        , m_fixedClipRect(r)
+        , m_posClipRect(r)
+        , m_refCnt(1)
+        , m_fixed(false)
+    {
+    }
+
+    ClipRects(const ClipRects& other)
+        : m_overflowClipRect(other.overflowClipRect())
+        , m_fixedClipRect(other.fixedClipRect())
+        , m_posClipRect(other.posClipRect())
+        , m_refCnt(1)
+        , m_fixed(other.fixed())
+    {
+    }
+
+    ClipRect m_overflowClipRect;
+    ClipRect m_fixedClipRect;
+    ClipRect m_posClipRect;
+    unsigned m_refCnt : 31;
+    bool m_fixed : 1;
+};
+
+enum ClipRectsType {
+    PaintingClipRects, // Relative to painting ancestor. Used for painting.
+    RootRelativeClipRects, // Relative to the ancestor treated as the root (e.g. transformed layer). Used for hit testing.
+    AbsoluteClipRects, // Relative to the RenderView's layer. Used for compositing overlap testing.
+    NumCachedClipRectsTypes,
+    AllClipRectTypes,
+    TemporaryClipRects
+};
+
+enum ShouldRespectOverflowClip {
+    IgnoreOverflowClip,
+    RespectOverflowClip
+};
+
+struct ClipRectsCache {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    ClipRectsCache()
+    {
+#ifndef NDEBUG
+        for (int i = 0; i < NumCachedClipRectsTypes; ++i) {
+            m_clipRectsRoot[i] = 0;
+            m_scrollbarRelevancy[i] = IgnoreOverlayScrollbarSize;
+        }
+#endif
+    }
+
+    PassRefPtr<ClipRects> getClipRects(ClipRectsType clipRectsType, ShouldRespectOverflowClip respectOverflow) { return m_clipRects[getIndex(clipRectsType, respectOverflow)]; }
+    void setClipRects(ClipRectsType clipRectsType, ShouldRespectOverflowClip respectOverflow, PassRefPtr<ClipRects> clipRects) { m_clipRects[getIndex(clipRectsType, respectOverflow)] = clipRects; }
+
+#ifndef NDEBUG
+    const RenderLayer* m_clipRectsRoot[NumCachedClipRectsTypes];
+    OverlayScrollbarSizeRelevancy m_scrollbarRelevancy[NumCachedClipRectsTypes];
+#endif
+
+private:
+    int getIndex(ClipRectsType clipRectsType, ShouldRespectOverflowClip respectOverflow)
+    {
+        int index = static_cast<int>(clipRectsType);
+        if (respectOverflow == RespectOverflowClip)
+            index += static_cast<int>(NumCachedClipRectsTypes);
+        return index;
+    }
+
+    RefPtr<ClipRects> m_clipRects[NumCachedClipRectsTypes * 2];
+};
+
+struct LayerFragment {
+public:
+    LayerFragment()
+        : shouldPaintContent(false)
+    { }
+
+    void setRects(const LayoutRect& bounds, const ClipRect& background, const ClipRect& foreground, const ClipRect& outline)
+    {
+        layerBounds = bounds;
+        backgroundRect = background;
+        foregroundRect = foreground;
+        outlineRect = outline;
+    }
+    
+    void moveBy(const LayoutPoint& offset)
+    {
+        layerBounds.moveBy(offset);
+        backgroundRect.moveBy(offset);
+        foregroundRect.moveBy(offset);
+        outlineRect.moveBy(offset);
+        paginationClip.moveBy(offset);
+    }
+    
+    void intersect(const LayoutRect& rect)
+    {
+        backgroundRect.intersect(rect);
+        foregroundRect.intersect(rect);
+        outlineRect.intersect(rect);
+    }
+    
+    bool shouldPaintContent;
+    LayoutRect layerBounds;
+    ClipRect backgroundRect;
+    ClipRect foregroundRect;
+    ClipRect outlineRect;
+    
+    // Unique to paginated fragments. The physical translation to apply to shift the layer when painting/hit-testing.
+    LayoutPoint paginationOffset;
+    
+    // Also unique to paginated fragments. An additional clip that applies to the layer. It is in layer-local
+    // (physical) coordinates.
+    LayoutRect paginationClip;
+};
+
+typedef Vector<LayerFragment, 1> LayerFragments;
+
+class RenderLayer : public ScrollableArea {
+public:
+    friend class RenderReplica;
+
+    RenderLayer(RenderLayerModelObject*);
+    ~RenderLayer();
+
+#ifndef NDEBUG
+    String debugName() const;
+#endif
+
+    RenderLayerModelObject* renderer() const { return m_renderer; }
+    RenderBox* renderBox() const { return m_renderer && m_renderer->isBox() ? toRenderBox(m_renderer) : 0; }
+    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();
+
+    // Indicate that the layer contents need to be repainted. Only has an effect
+    // if layer compositing is being used,
+    void setBackingNeedsRepaint();
+    void setBackingNeedsRepaintInRect(const LayoutRect&); // r is in the coordinate space of the layer's render object
+    void repaintIncludingNonCompositingDescendants(RenderLayerModelObject* repaintContainer);
+
+    void styleChanged(StyleDifference, const RenderStyle* oldStyle);
+
+    RenderMarquee* marquee() const { return m_marquee.get(); }
+
+    bool isNormalFlowOnly() const { return m_isNormalFlowOnly; }
+    bool isSelfPaintingLayer() const { return m_isSelfPaintingLayer; }
+
+    bool cannotBlitToWindow() const;
+
+    bool isTransparent() const;
+    RenderLayer* transparentPaintingAncestor();
+    void beginTransparencyLayers(GraphicsContext*, const RenderLayer* rootLayer, const LayoutRect& paintDirtyRect, PaintBehavior);
+
+    bool hasReflection() const { return renderer()->hasReflection(); }
+    bool isReflection() const { return renderer()->isReplica(); }
+    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;
+    }
+    
+    const LayoutPoint& location() const { return m_topLeft; }
+    void setLocation(const LayoutPoint& p) { m_topLeft = p; }
+
+    const IntSize& size() const { return m_layerSize; }
+    void setSize(const IntSize& size) { m_layerSize = size; }
+
+    LayoutRect rect() const { return LayoutRect(location(), size()); }
+
+    int scrollWidth() const;
+    int scrollHeight() const;
+
+    void panScrollFromPoint(const IntPoint&);
+
+    enum ScrollOffsetClamping {
+        ScrollOffsetUnclamped,
+        ScrollOffsetClamped
+    };
+
+    // Scrolling methods for layers that can scroll their overflow.
+    void scrollByRecursively(const IntSize&, ScrollOffsetClamping = ScrollOffsetUnclamped);
+    void scrollToOffset(const IntSize&, ScrollOffsetClamping = ScrollOffsetUnclamped);
+    void scrollToXOffset(int x, ScrollOffsetClamping clamp = ScrollOffsetUnclamped) { scrollToOffset(IntSize(x, scrollYOffset()), clamp); }
+    void scrollToYOffset(int y, ScrollOffsetClamping clamp = ScrollOffsetUnclamped) { scrollToOffset(IntSize(scrollXOffset(), y), clamp); }
+
+    int scrollXOffset() const { return m_scrollOffset.width() + scrollOrigin().x(); }
+    int scrollYOffset() const { return m_scrollOffset.height() + scrollOrigin().y(); }
+    IntSize scrollOffset() const { return IntSize(scrollXOffset(), scrollYOffset()); }
+
+    void scrollRectToVisible(const LayoutRect&, const ScrollAlignment& alignX, const ScrollAlignment& alignY);
+
+    LayoutRect getRectToExpose(const LayoutRect& visibleRect, const LayoutRect& exposeRect, const ScrollAlignment& alignX, const ScrollAlignment& alignY);
+
+    bool scrollsOverflow() const;
+    bool hasScrollbars() const { return m_hBar || m_vBar; }
+    void setHasHorizontalScrollbar(bool);
+    void setHasVerticalScrollbar(bool);
+
+    PassRefPtr<Scrollbar> createScrollbar(ScrollbarOrientation);
+    void destroyScrollbar(ScrollbarOrientation);
+
+    bool hasHorizontalScrollbar() const { return horizontalScrollbar(); }
+    bool hasVerticalScrollbar() const { return verticalScrollbar(); }
+
+    // ScrollableArea overrides
+    virtual Scrollbar* horizontalScrollbar() const { return m_hBar.get(); }
+    virtual Scrollbar* verticalScrollbar() const { return m_vBar.get(); }
+    virtual ScrollableArea* enclosingScrollableArea() const;
+
+    int verticalScrollbarWidth(OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize) const;
+    int horizontalScrollbarHeight(OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize) const;
+
+    bool hasOverflowControls() const;
+    bool isPointInResizeControl(const IntPoint& absolutePoint) const;
+    bool hitTestOverflowControls(HitTestResult&, const IntPoint& localPoint);
+    IntSize offsetFromResizeCorner(const IntPoint& absolutePoint) const;
+
+    void paintOverflowControls(GraphicsContext*, const IntPoint&, const IntRect& damageRect, bool paintingOverlayControls = false);
+    void paintScrollCorner(GraphicsContext*, const IntPoint&, const IntRect& damageRect);
+    void paintResizer(GraphicsContext*, const IntPoint&, const IntRect& damageRect);
+
+    void updateScrollInfoAfterLayout();
+
+    bool scroll(ScrollDirection, ScrollGranularity, float multiplier = 1);
+    void autoscroll(const IntPoint&);
+
+    bool canResize() const;
+    void resize(const PlatformMouseEvent&, const LayoutSize&);
+    bool inResizeMode() const { return m_inResizeMode; }
+    void setInResizeMode(bool b) { m_inResizeMode = b; }
+
+    bool isRootLayer() const { return m_isRootLayer; }
+
+    RenderLayerCompositor* compositor() const;
+    
+    // Notification from the renderer that its content changed (e.g. current frame of image changed).
+    // Allows updates of layer content without repainting.
+    void contentChanged(ContentChangeType);
+
+    bool canRender3DTransforms() const;
+
+    enum UpdateLayerPositionsFlag {
+        CheckForRepaint = 1 << 0,
+        NeedsFullRepaintInBacking = 1 << 1,
+        IsCompositingUpdateRoot = 1 << 2,
+        UpdateCompositingLayers = 1 << 3,
+        UpdatePagination = 1 << 4
+    };
+    typedef unsigned UpdateLayerPositionsFlags;
+    static const UpdateLayerPositionsFlags defaultFlags = CheckForRepaint | IsCompositingUpdateRoot | UpdateCompositingLayers;
+
+    void updateLayerPositionsAfterLayout(const RenderLayer* rootLayer, UpdateLayerPositionsFlags);
+
+    void updateLayerPositionsAfterOverflowScroll();
+    void updateLayerPositionsAfterDocumentScroll();
+
+    void positionNewlyCreatedOverflowControls();
+
+    bool isPaginated() const { return m_isPaginated; }
+    RenderLayer* enclosingPaginationLayer() const { return m_enclosingPaginationLayer; }
+
+    void updateTransform();
+    
+#if ENABLE(CSS_COMPOSITING)
+    void updateBlendMode();
+#endif
+
+    const LayoutSize& paintOffset() const { return m_paintOffset; }
+
+    void clearClipRectsIncludingDescendants(ClipRectsType typeToClear = AllClipRectTypes);
+    void clearClipRects(ClipRectsType typeToClear = AllClipRectTypes);
+
+    void addBlockSelectionGapsBounds(const LayoutRect&);
+    void clearBlockSelectionGapsBounds();
+    void repaintBlockSelectionGaps();
+
+    // A stacking context is a layer that has a non-auto z-index.
+    bool isStackingContext() const { return isStackingContext(renderer()->style()); }
+
+    // A stacking container can have z-order lists. All stacking contexts are
+    // stacking containers, but the converse is not true. Layers that use
+    // composited scrolling are stacking containers, but they may not
+    // necessarily be stacking contexts.
+    bool isStackingContainer() const { return isStackingContext() || needsCompositedScrolling(); }
+
+    RenderLayer* ancestorStackingContainer() const;
+    RenderLayer* ancestorStackingContext() const;
+
+    // Gets the enclosing stacking container for this layer, possibly the layer
+    // itself, if it is a stacking container.
+    RenderLayer* enclosingStackingContainer() { return isStackingContainer() ? this : ancestorStackingContainer(); }
+
+    void dirtyZOrderLists();
+    void dirtyStackingContainerZOrderLists();
+
+    Vector<RenderLayer*>* posZOrderList() const
+    {
+        ASSERT(!m_zOrderListsDirty);
+        ASSERT(isStackingContainer() || !m_posZOrderList);
+        return m_posZOrderList.get();
+    }
+
+    bool hasNegativeZOrderList() const { return negZOrderList() && negZOrderList()->size(); }
+
+    Vector<RenderLayer*>* negZOrderList() const
+    {
+        ASSERT(!m_zOrderListsDirty);
+        ASSERT(isStackingContainer() || !m_negZOrderList);
+        return m_negZOrderList.get();
+    }
+
+    void dirtyNormalFlowList();
+    Vector<RenderLayer*>* normalFlowList() const { ASSERT(!m_normalFlowListDirty); return m_normalFlowList.get(); }
+
+    // Update our normal and z-index lists.
+    void updateLayerListsIfNeeded();
+
+    // FIXME: We should ASSERT(!m_visibleContentStatusDirty) here, but see https://bugs.webkit.org/show_bug.cgi?id=71044
+    // ditto for hasVisibleDescendant(), see https://bugs.webkit.org/show_bug.cgi?id=71277
+    bool hasVisibleContent() const { return m_hasVisibleContent; }
+    bool hasVisibleDescendant() const { return m_hasVisibleDescendant; }
+
+    void setHasVisibleContent();
+    void dirtyVisibleContentStatus();
+
+    bool hasBoxDecorationsOrBackground() const;
+    bool hasVisibleBoxDecorations() const;
+    // Returns true if this layer has visible content (ignoring any child layers).
+    bool isVisuallyNonEmpty() const;
+    // True if this layer container renderers that paint.
+    bool hasNonEmptyChildRenderers() const;
+
+    // FIXME: We should ASSERT(!m_hasSelfPaintingLayerDescendantDirty); here but we hit the same bugs as visible content above.
+    // Part of the issue is with subtree relayout: we don't check if our ancestors have some descendant flags dirty, missing some updates.
+    bool hasSelfPaintingLayerDescendant() const { return m_hasSelfPaintingLayerDescendant; }
+
+    // This returns true if we have an out of flow positioned descendant whose
+    // containing block is not a descendant of ours. If this is true, we cannot
+    // automatically opt into composited scrolling since this out of flow
+    // positioned descendant would become clipped by us, possibly altering the 
+    // rendering of the page.
+    // FIXME: We should ASSERT(!m_hasOutOfFlowPositionedDescendantDirty); here but we may hit the same bugs as visible content above.
+    bool hasOutOfFlowPositionedDescendant() const { return m_hasOutOfFlowPositionedDescendant; }
+
+    // Gets the nearest enclosing positioned ancestor layer (also includes
+    // the <html> layer and the root layer).
+    RenderLayer* enclosingPositionedAncestor() const;
+
+    // Returns the nearest enclosing layer that is scrollable.
+    RenderLayer* enclosingScrollableLayer() const;
+
+    // The layer relative to which clipping rects for this layer are computed.
+    RenderLayer* clippingRootForPainting() const;
+
+    // Enclosing compositing layer; if includeSelf is true, may return this.
+    RenderLayer* enclosingCompositingLayer(bool includeSelf = true) const;
+    RenderLayer* enclosingCompositingLayerForRepaint(bool includeSelf = true) const;
+    // Ancestor compositing layer, excluding this.
+    RenderLayer* ancestorCompositingLayer() const { return enclosingCompositingLayer(false); }
+
+    RenderLayer* enclosingFilterLayer(bool includeSelf = true) const;
+    RenderLayer* enclosingFilterRepaintLayer() const;
+    void setFilterBackendNeedsRepaintingInRect(const LayoutRect&);
+    bool hasAncestorWithFilterOutsets() const;
+
+    bool canUseConvertToLayerCoords() const
+    {
+        // These RenderObject have an impact on their layers' without them knowing about it.
+        return !renderer()->hasColumns() && !renderer()->hasTransform()
+#if ENABLE(SVG)
+            && !renderer()->isSVGRoot()
+#endif
+            ;
+    }
+
+    void convertToPixelSnappedLayerCoords(const RenderLayer* ancestorLayer, IntPoint& location) const;
+    void convertToPixelSnappedLayerCoords(const RenderLayer* ancestorLayer, IntRect&) const;
+    void convertToLayerCoords(const RenderLayer* ancestorLayer, LayoutPoint& location) const;
+    void convertToLayerCoords(const RenderLayer* ancestorLayer, LayoutRect&) const;
+
+    int zIndex() const { return renderer()->style()->zIndex(); }
+
+    enum PaintLayerFlag {
+        PaintLayerHaveTransparency = 1,
+        PaintLayerAppliedTransform = 1 << 1,
+        PaintLayerTemporaryClipRects = 1 << 2,
+        PaintLayerPaintingReflection = 1 << 3,
+        PaintLayerPaintingOverlayScrollbars = 1 << 4,
+        PaintLayerPaintingCompositingBackgroundPhase = 1 << 5,
+        PaintLayerPaintingCompositingForegroundPhase = 1 << 6,
+        PaintLayerPaintingCompositingMaskPhase = 1 << 7,
+        PaintLayerPaintingCompositingScrollingPhase = 1 << 8,
+        PaintLayerPaintingOverflowContents = 1 << 9,
+        PaintLayerPaintingRootBackgroundOnly = 1 << 10,
+        PaintLayerPaintingSkipRootBackground = 1 << 11,
+        PaintLayerPaintingCompositingAllPhases = (PaintLayerPaintingCompositingBackgroundPhase | PaintLayerPaintingCompositingForegroundPhase | PaintLayerPaintingCompositingMaskPhase)
+    };
+    
+    typedef unsigned PaintLayerFlags;
+
+    // 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 LayoutRect& damageRect, PaintBehavior = PaintBehaviorNormal, RenderObject* paintingRoot = 0,
+        RenderRegion* = 0, PaintLayerFlags = 0);
+    bool hitTest(const HitTestRequest&, HitTestResult&);
+    bool hitTest(const HitTestRequest&, const HitTestLocation&, HitTestResult&);
+    void paintOverlayScrollbars(GraphicsContext*, const LayoutRect& damageRect, PaintBehavior, RenderObject* paintingRoot = 0);
+
+    struct ClipRectsContext {
+        ClipRectsContext(const RenderLayer* inRootLayer, RenderRegion* inRegion, ClipRectsType inClipRectsType, OverlayScrollbarSizeRelevancy inOverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize, ShouldRespectOverflowClip inRespectOverflowClip = RespectOverflowClip)
+            : rootLayer(inRootLayer)
+            , region(inRegion)
+            , clipRectsType(inClipRectsType)
+            , overlayScrollbarSizeRelevancy(inOverlayScrollbarSizeRelevancy)
+            , respectOverflowClip(inRespectOverflowClip)
+        { }
+        const RenderLayer* rootLayer;
+        RenderRegion* region;
+        ClipRectsType clipRectsType;
+        OverlayScrollbarSizeRelevancy overlayScrollbarSizeRelevancy;
+        ShouldRespectOverflowClip respectOverflowClip;
+    };
+
+    // This method figures out our layerBounds in coordinates relative to
+    // |rootLayer}.  It also computes our background and foreground clip rects
+    // for painting/event handling.
+    // Pass offsetFromRoot if known.
+    void calculateRects(const ClipRectsContext&, const LayoutRect& paintDirtyRect, LayoutRect& layerBounds,
+        ClipRect& backgroundRect, ClipRect& foregroundRect, ClipRect& outlineRect, const LayoutPoint* offsetFromRoot = 0) const;
+
+    // Compute and cache clip rects computed with the given layer as the root
+    void updateClipRects(const ClipRectsContext&);
+    // Compute and return the clip rects. If useCached is true, will used previously computed clip rects on ancestors
+    // (rather than computing them all from scratch up the parent chain).
+    void calculateClipRects(const ClipRectsContext&, ClipRects&) const;
+
+    ClipRects* clipRects(const ClipRectsContext& context) const
+    {
+        ASSERT(context.clipRectsType < NumCachedClipRectsTypes);
+        return m_clipRectsCache ? m_clipRectsCache->getClipRects(context.clipRectsType, context.respectOverflowClip).get() : 0;
+    }
+
+    LayoutRect childrenClipRect() const; // Returns the foreground clip rect of the layer in the document's coordinate space.
+    LayoutRect selfClipRect() const; // Returns the background clip rect of the layer in the document's coordinate space.
+    LayoutRect localClipRect() const; // Returns the background clip rect of the layer in the local coordinate space.
+
+    // Pass offsetFromRoot if known.
+    bool intersectsDamageRect(const LayoutRect& layerBounds, const LayoutRect& damageRect, const RenderLayer* rootLayer, const LayoutPoint* offsetFromRoot = 0) const;
+
+    enum CalculateLayerBoundsFlag {
+        IncludeSelfTransform = 1 << 0,
+        UseLocalClipRectIfPossible = 1 << 1,
+        IncludeLayerFilterOutsets = 1 << 2,
+        ExcludeHiddenDescendants = 1 << 3,
+        DontConstrainForMask = 1 << 4,
+        IncludeCompositedDescendants = 1 << 5,
+        UseFragmentBoxes = 1 << 6,
+        DefaultCalculateLayerBoundsFlags =  IncludeSelfTransform | UseLocalClipRectIfPossible | IncludeLayerFilterOutsets | UseFragmentBoxes
+    };
+    typedef unsigned CalculateLayerBoundsFlags;
+
+    // Bounding box relative to some ancestor layer. Pass offsetFromRoot if known.
+    LayoutRect boundingBox(const RenderLayer* rootLayer, CalculateLayerBoundsFlags = 0, const LayoutPoint* offsetFromRoot = 0) const;
+    // Bounding box in the coordinates of this layer.
+    LayoutRect localBoundingBox(CalculateLayerBoundsFlags = 0) const;
+    // Pixel snapped bounding box relative to the root.
+    IntRect absoluteBoundingBox() const;
+
+    // Bounds used for layer overlap testing in RenderLayerCompositor.
+    LayoutRect overlapBounds() const { return overlapBoundsIncludeChildren() ? calculateLayerBounds(this) : localBoundingBox(); }
+
+    // If true, this layer's children are included in its bounds for overlap testing.
+    // We can't rely on the children's positions if this layer has a filter that could have moved the children's pixels around.
+    bool overlapBoundsIncludeChildren() const { return hasFilter() && renderer()->style()->filter().hasFilterThatMovesPixels(); }
+
+    // Can pass offsetFromRoot if known.
+    IntRect calculateLayerBounds(const RenderLayer* ancestorLayer, const LayoutPoint* offsetFromRoot = 0, CalculateLayerBoundsFlags = DefaultCalculateLayerBoundsFlags) const;
+    
+    // WARNING: This method returns the offset for the parent as this is what updateLayerPositions expects.
+    LayoutPoint computeOffsetFromRoot(bool& hasLayerOffset) const;
+
+    // Return a cached repaint rect, computed relative to the layer renderer's containerForRepaint.
+    LayoutRect repaintRect() const { return m_repaintRect; }
+    LayoutRect repaintRectIncludingNonCompositingDescendants() const;
+
+    void setRepaintStatus(RepaintStatus status) { m_repaintStatus = status; }
+
+    LayoutUnit staticInlinePosition() const { return m_staticInlinePosition; }
+    LayoutUnit staticBlockPosition() const { return m_staticBlockPosition; }
+   
+    void setStaticInlinePosition(LayoutUnit position) { m_staticInlinePosition = position; }
+    void setStaticBlockPosition(LayoutUnit position) { m_staticBlockPosition = position; }
+
+    bool hasTransform() const { return renderer()->hasTransform(); }
+    // Note that this transform has the transform-origin baked in.
+    TransformationMatrix* transform() const { return m_transform.get(); }
+    // currentTransform computes a transform which takes accelerated animations into account. The
+    // resulting transform has transform-origin baked in. If the layer does not have a transform,
+    // returns the identity matrix.
+    TransformationMatrix currentTransform(RenderStyle::ApplyTransformOrigin = RenderStyle::IncludeTransformOrigin) const;
+    TransformationMatrix renderableTransform(PaintBehavior) const;
+    
+    // Get the perspective transform, which is applied to transformed sublayers.
+    // Returns true if the layer has a -webkit-perspective.
+    // Note that this transform has the perspective-origin baked in.
+    TransformationMatrix perspectiveTransform() const;
+    FloatPoint perspectiveOrigin() const;
+    bool preserves3D() const { return renderer()->style()->transformStyle3D() == TransformStyle3DPreserve3D; }
+    bool has3DTransform() const { return m_transform && !m_transform->isAffine(); }
+
+    virtual void filterNeedsRepaint();
+    bool hasFilter() const { return renderer()->hasFilter(); }
+
+#if ENABLE(CSS_COMPOSITING)
+    bool hasBlendMode() const { return renderer()->hasBlendMode(); }
+#else
+    bool hasBlendMode() const { return false; }
+#endif
+
+    // Overloaded new operator. Derived classes must override operator new
+    // in order to allocate out of the RenderArena.
+    void* operator new(size_t, RenderArena*);
+
+    // Overridden to prevent the normal delete from being called.
+    void operator delete(void*, size_t);
+
+    bool isComposited() const { return m_backing != 0; }
+    bool hasCompositedMask() const;
+    RenderLayerBacking* backing() const { return m_backing.get(); }
+    RenderLayerBacking* ensureBacking();
+    void clearBacking(bool layerBeingDestroyed = false);
+    virtual GraphicsLayer* layerForScrolling() const;
+    virtual GraphicsLayer* layerForHorizontalScrollbar() const;
+    virtual GraphicsLayer* layerForVerticalScrollbar() const;
+    virtual GraphicsLayer* layerForScrollCorner() const;
+    virtual bool usesCompositedScrolling() const OVERRIDE;
+    bool needsCompositedScrolling() const;
+    bool needsCompositingLayersRebuiltForClip(const RenderStyle* oldStyle, const RenderStyle* newStyle) const;
+    bool needsCompositingLayersRebuiltForOverflow(const RenderStyle* oldStyle, const RenderStyle* newStyle) const;
+    bool needsCompositingLayersRebuiltForFilters(const RenderStyle* oldStyle, const RenderStyle* newStyle, bool didPaintWithFilters) const;
+
+    bool paintsWithTransparency(PaintBehavior paintBehavior) const
+    {
+        return isTransparent() && ((paintBehavior & PaintBehaviorFlattenCompositingLayers) || !isComposited());
+    }
+
+    bool paintsWithTransform(PaintBehavior) const;
+
+    // Returns true if background phase is painted opaque in the given rect.
+    // The query rect is given in local coordinates.
+    bool backgroundIsKnownToBeOpaqueInRect(const LayoutRect&) const;
+
+    bool containsDirtyOverlayScrollbars() const { return m_containsDirtyOverlayScrollbars; }
+    void setContainsDirtyOverlayScrollbars(bool dirtyScrollbars) { m_containsDirtyOverlayScrollbars = dirtyScrollbars; }
+
+    bool isCSSCustomFilterEnabled() const;
+
+    FilterOperations computeFilterOperations(const RenderStyle*);
+    bool paintsWithFilters() const;
+    bool requiresFullLayerImageForFilters() const;
+    FilterEffectRenderer* filterRenderer() const 
+    {
+        RenderLayerFilterInfo* filterInfo = this->filterInfo();
+        return filterInfo ? filterInfo->renderer() : 0;
+    }
+    
+    RenderLayerFilterInfo* filterInfo() const { return hasFilterInfo() ? RenderLayerFilterInfo::filterInfoForRenderLayer(this) : 0; }
+    RenderLayerFilterInfo* ensureFilterInfo() { return RenderLayerFilterInfo::createFilterInfoForRenderLayerIfNeeded(this); }
+    void removeFilterInfoIfNeeded() 
+    {
+        if (hasFilterInfo())
+            RenderLayerFilterInfo::removeFilterInfoForRenderLayer(this); 
+    }
+    
+    bool hasFilterInfo() const { return m_hasFilterInfo; }
+    void setHasFilterInfo(bool hasFilterInfo) { m_hasFilterInfo = hasFilterInfo; }
+
+    void updateFilters(const RenderStyle* oldStyle, const RenderStyle* newStyle);
+
+#if !ASSERT_DISABLED
+    bool layerListMutationAllowed() const { return m_layerListMutationAllowed; }
+    void setLayerListMutationAllowed(bool flag) { m_layerListMutationAllowed = flag; }
+#endif
+
+    Node* enclosingElement() const;
+
+    bool isInTopLayer() const;
+    bool isInTopLayerSubtree() const;
+
+    virtual void reportMemoryUsage(MemoryObjectInfo*) const OVERRIDE;
+
+    enum ViewportConstrainedNotCompositedReason {
+        NoNotCompositedReason,
+        NotCompositedForBoundsOutOfView,
+        NotCompositedForNonViewContainer,
+        NotCompositedForNoVisibleContent,
+        NotCompositedForUnscrollableAncestors,
+    };
+
+    void setViewportConstrainedNotCompositedReason(ViewportConstrainedNotCompositedReason reason) { m_compositingProperties.viewportConstrainedNotCompositedReason = reason; }
+    ViewportConstrainedNotCompositedReason viewportConstrainedNotCompositedReason() const { return static_cast<ViewportConstrainedNotCompositedReason>(m_compositingProperties.viewportConstrainedNotCompositedReason); }
+
+    bool isOutOfFlowRenderFlowThread() const { return renderer()->isOutOfFlowRenderFlowThread(); }
+
+    enum PaintOrderListType {BeforePromote, AfterPromote};
+    void computePaintOrderList(PaintOrderListType type, Vector<RefPtr<Node> >&);
+
+private:
+    enum CollectLayersBehavior { StopAtStackingContexts, StopAtStackingContainers };
+
+    void updateZOrderLists();
+    void rebuildZOrderLists();
+    // See the comment for collectLayers for information about the layerToForceAsStackingContainer parameter.
+    void rebuildZOrderLists(CollectLayersBehavior, OwnPtr<Vector<RenderLayer*> >&, OwnPtr<Vector<RenderLayer*> >&, const RenderLayer* layerToForceAsStackingContainer = 0);
+    void clearZOrderLists();
+
+    void updateNormalFlowList();
+
+    bool isStackingContext(const RenderStyle* style) const { return !style->hasAutoZIndex() || isRootLayer(); }
+
+    bool isDirtyStackingContainer() const { return m_zOrderListsDirty && isStackingContainer(); }
+
+    void setAncestorChainHasSelfPaintingLayerDescendant();
+    void dirtyAncestorChainHasSelfPaintingLayerDescendantStatus();
+
+    bool acceleratedCompositingForOverflowScrollEnabled() const;
+    void updateDescendantsAreContiguousInStackingOrder();
+    void updateDescendantsAreContiguousInStackingOrderRecursive(const HashMap<const RenderLayer*, int>&, int& minIndex, int& maxIndex, int& count, bool firstIteration);
+    void collectBeforePromotionZOrderList(RenderLayer* ancestorStackingContext, OwnPtr<Vector<RenderLayer*> >& posZOrderListBeforePromote, OwnPtr<Vector<RenderLayer*> >& negZOrderListBeforePromote);
+    void collectAfterPromotionZOrderList(RenderLayer* ancestorStackingContext, OwnPtr<Vector<RenderLayer*> >& posZOrderListAfterPromote, OwnPtr<Vector<RenderLayer*> >& negZOrderListAfterPromote);
+
+    void computeRepaintRects(const RenderLayerModelObject* repaintContainer, const RenderGeometryMap* = 0);
+    void computeRepaintRectsIncludingDescendants();
+    void clearRepaintRects();
+
+    void clipToRect(RenderLayer* rootLayer, GraphicsContext*, const LayoutRect& paintDirtyRect, const ClipRect&,
+                    BorderRadiusClippingRule = IncludeSelfForBorderRadius);
+    void restoreClip(GraphicsContext*, const LayoutRect& paintDirtyRect, const ClipRect&);
+
+    bool shouldRepaintAfterLayout() const;
+
+    void updateSelfPaintingLayer();
+    void updateIsNormalFlowOnly();
+    void updateVisibilityAfterStyleChange(const RenderStyle* oldStyle);
+    void updateStackingContextsAfterStyleChange(const RenderStyle* oldStyle);
+
+    void updateScrollbarsAfterStyleChange(const RenderStyle* oldStyle);
+    void updateScrollbarsAfterLayout();
+
+    void setAncestorChainHasOutOfFlowPositionedDescendant(RenderObject* containingBlock);
+    void dirtyAncestorChainHasOutOfFlowPositionedDescendantStatus();
+    void updateOutOfFlowPositioned(const RenderStyle* oldStyle);
+
+    void updateNeedsCompositedScrolling();
+
+    // Returns true if the position changed.
+    bool updateLayerPosition();
+
+    void updateLayerPositions(RenderGeometryMap* = 0, UpdateLayerPositionsFlags = defaultFlags);
+
+    enum UpdateLayerPositionsAfterScrollFlag {
+        NoFlag = 0,
+        IsOverflowScroll = 1 << 0,
+        HasSeenViewportConstrainedAncestor = 1 << 1,
+        HasSeenAncestorWithOverflowClip = 1 << 2,
+        HasChangedAncestor = 1 << 3
+    };
+    typedef unsigned UpdateLayerPositionsAfterScrollFlags;
+    void updateLayerPositionsAfterScroll(RenderGeometryMap*, UpdateLayerPositionsAfterScrollFlags = NoFlag);
+
+    friend IntSize RenderBox::scrolledContentOffset() const;
+    IntSize scrolledContentOffset() const { return m_scrollOffset; }
+
+    IntSize clampScrollOffset(const IntSize&) const;
+
+    // The normal operator new is disallowed on all render objects.
+    void* operator new(size_t) throw();
+
+    void setNextSibling(RenderLayer* next) { m_next = next; }
+    void setPreviousSibling(RenderLayer* prev) { m_previous = prev; }
+    void setParent(RenderLayer* parent);
+    void setFirstChild(RenderLayer* first) { m_first = first; }
+    void setLastChild(RenderLayer* last) { m_last = last; }
+
+    LayoutPoint renderBoxLocation() const { return renderer()->isBox() ? toRenderBox(renderer())->location() : LayoutPoint(); }
+
+    // layerToForceAsStackingContainer allows us to build pre-promotion and
+    // post-promotion layer lists, by allowing us to treat a layer as if it is a
+    // stacking context, without adding a new member to RenderLayer or modifying
+    // the style (which could cause extra allocations).
+    void collectLayers(bool includeHiddenLayers, CollectLayersBehavior, OwnPtr<Vector<RenderLayer*> >&, OwnPtr<Vector<RenderLayer*> >&, const RenderLayer* layerToForceAsStackingContainer = 0);
+
+    struct LayerPaintingInfo {
+        LayerPaintingInfo(RenderLayer* inRootLayer, const LayoutRect& inDirtyRect, PaintBehavior inPaintBehavior, const LayoutSize& inSubPixelAccumulation, RenderObject* inPaintingRoot = 0, RenderRegion*inRegion = 0, OverlapTestRequestMap* inOverlapTestRequests = 0)
+            : rootLayer(inRootLayer)
+            , paintingRoot(inPaintingRoot)
+            , paintDirtyRect(inDirtyRect)
+            , subPixelAccumulation(inSubPixelAccumulation)
+            , region(inRegion)
+            , overlapTestRequests(inOverlapTestRequests)
+            , paintBehavior(inPaintBehavior)
+            , clipToDirtyRect(true)
+        { }
+        RenderLayer* rootLayer;
+        RenderObject* paintingRoot; // only paint descendants of this object
+        LayoutRect paintDirtyRect; // relative to rootLayer;
+        LayoutSize subPixelAccumulation;
+        RenderRegion* region; // May be null.
+        OverlapTestRequestMap* overlapTestRequests; // May be null.
+        PaintBehavior paintBehavior;
+        bool clipToDirtyRect;
+    };
+        
+    void paintLayer(GraphicsContext*, const LayerPaintingInfo&, PaintLayerFlags);
+    void paintLayerContentsAndReflection(GraphicsContext*, const LayerPaintingInfo&, PaintLayerFlags);
+    void paintLayerByApplyingTransform(GraphicsContext*, const LayerPaintingInfo&, PaintLayerFlags, const LayoutPoint& translationOffset = LayoutPoint());
+    void paintLayerContents(GraphicsContext*, const LayerPaintingInfo&, PaintLayerFlags);
+    void paintList(Vector<RenderLayer*>*, GraphicsContext*, const LayerPaintingInfo&, PaintLayerFlags);
+    void paintPaginatedChildLayer(RenderLayer* childLayer, GraphicsContext*, const LayerPaintingInfo&, PaintLayerFlags);
+    void paintChildLayerIntoColumns(RenderLayer* childLayer, GraphicsContext*, const LayerPaintingInfo&, PaintLayerFlags, const Vector<RenderLayer*>& columnLayers, size_t columnIndex);
+
+    void collectFragments(LayerFragments&, const RenderLayer* rootLayer, RenderRegion*, const LayoutRect& dirtyRect,
+        ClipRectsType, OverlayScrollbarSizeRelevancy inOverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize,
+        ShouldRespectOverflowClip = RespectOverflowClip, const LayoutPoint* offsetFromRoot = 0, const LayoutRect* layerBoundingBox = 0);
+    void updatePaintingInfoForFragments(LayerFragments&, const LayerPaintingInfo&, PaintLayerFlags, bool shouldPaintContent, const LayoutPoint* offsetFromRoot);
+    void paintBackgroundForFragments(const LayerFragments&, GraphicsContext*, GraphicsContext* transparencyLayerContext,
+        const LayoutRect& transparencyPaintDirtyRect, bool haveTransparency, const LayerPaintingInfo&, PaintBehavior, RenderObject* paintingRootForRenderer);
+    void paintForegroundForFragments(const LayerFragments&, GraphicsContext*, GraphicsContext* transparencyLayerContext,
+        const LayoutRect& transparencyPaintDirtyRect, bool haveTransparency, const LayerPaintingInfo&, PaintBehavior, RenderObject* paintingRootForRenderer,
+        bool selectionOnly, bool forceBlackText);
+    void paintForegroundForFragmentsWithPhase(PaintPhase, const LayerFragments&, GraphicsContext*, const LayerPaintingInfo&, PaintBehavior, RenderObject* paintingRootForRenderer);
+    void paintOutlineForFragments(const LayerFragments&, GraphicsContext*, const LayerPaintingInfo&, PaintBehavior, RenderObject* paintingRootForRenderer);
+    void paintOverflowControlsForFragments(const LayerFragments&, GraphicsContext*, const LayerPaintingInfo&);
+    void paintMaskForFragments(const LayerFragments&, GraphicsContext*, const LayerPaintingInfo&, RenderObject* paintingRootForRenderer);
+    void paintTransformedLayerIntoFragments(GraphicsContext*, const LayerPaintingInfo&, PaintLayerFlags);
+
+    RenderLayer* hitTestLayer(RenderLayer* rootLayer, RenderLayer* containerLayer, const HitTestRequest& request, HitTestResult& result,
+                              const LayoutRect& hitTestRect, const HitTestLocation&, bool appliedTransform,
+                              const HitTestingTransformState* transformState = 0, double* zOffset = 0);
+    RenderLayer* hitTestLayerByApplyingTransform(RenderLayer* rootLayer, RenderLayer* containerLayer, const HitTestRequest&, HitTestResult&,
+        const LayoutRect& hitTestRect, const HitTestLocation&, const HitTestingTransformState* = 0, double* zOffset = 0,
+        const LayoutPoint& translationOffset = LayoutPoint());
+    RenderLayer* hitTestList(Vector<RenderLayer*>*, RenderLayer* rootLayer, const HitTestRequest& request, HitTestResult& result,
+                             const LayoutRect& hitTestRect, const HitTestLocation&,
+                             const HitTestingTransformState* transformState, double* zOffsetForDescendants, double* zOffset,
+                             const HitTestingTransformState* unflattenedTransformState, bool depthSortDescendants);
+    RenderLayer* hitTestPaginatedChildLayer(RenderLayer* childLayer, RenderLayer* rootLayer, const HitTestRequest& request, HitTestResult& result,
+                                            const LayoutRect& hitTestRect, const HitTestLocation&,
+                                            const HitTestingTransformState* transformState, double* zOffset);
+    RenderLayer* hitTestChildLayerColumns(RenderLayer* childLayer, RenderLayer* rootLayer, const HitTestRequest& request, HitTestResult& result,
+                                          const LayoutRect& hitTestRect, const HitTestLocation&,
+                                          const HitTestingTransformState* transformState, double* zOffset,
+                                          const Vector<RenderLayer*>& columnLayers, size_t columnIndex);
+
+    PassRefPtr<HitTestingTransformState> createLocalTransformState(RenderLayer* rootLayer, RenderLayer* containerLayer,
+                            const LayoutRect& hitTestRect, const HitTestLocation&,
+                            const HitTestingTransformState* containerTransformState,
+                            const LayoutPoint& translationOffset = LayoutPoint()) const;
+    
+    bool hitTestContents(const HitTestRequest&, HitTestResult&, const LayoutRect& layerBounds, const HitTestLocation&, HitTestFilter) const;
+    bool hitTestContentsForFragments(const LayerFragments&, const HitTestRequest&, HitTestResult&, const HitTestLocation&, HitTestFilter, bool& insideClipRect) const;
+    bool hitTestResizerInFragments(const LayerFragments&, const HitTestLocation&) const;
+    RenderLayer* hitTestTransformedLayerInFragments(RenderLayer* rootLayer, RenderLayer* containerLayer, const HitTestRequest&, HitTestResult&,
+        const LayoutRect& hitTestRect, const HitTestLocation&, const HitTestingTransformState* = 0, double* zOffset = 0);
+
+    bool listBackgroundIsKnownToBeOpaqueInRect(const Vector<RenderLayer*>*, const LayoutRect&) const;
+
+    void computeScrollDimensions();
+    bool hasHorizontalOverflow() const;
+    bool hasVerticalOverflow() const;
+    bool hasScrollableHorizontalOverflow() const;
+    bool hasScrollableVerticalOverflow() const;
+
+    bool shouldBeNormalFlowOnly() const;
+
+    bool shouldBeSelfPaintingLayer() const;
+
+    int scrollPosition(Scrollbar*) const;
+    
+    // ScrollableArea interface
+    virtual void invalidateScrollbarRect(Scrollbar*, const IntRect&);
+    virtual void invalidateScrollCornerRect(const IntRect&);
+    virtual bool isActive() const;
+    virtual bool isScrollCornerVisible() const;
+    virtual IntRect scrollCornerRect() const;
+    virtual IntRect convertFromScrollbarToContainingView(const Scrollbar*, const IntRect&) const;
+    virtual IntRect convertFromContainingViewToScrollbar(const Scrollbar*, const IntRect&) const;
+    virtual IntPoint convertFromScrollbarToContainingView(const Scrollbar*, const IntPoint&) const;
+    virtual IntPoint convertFromContainingViewToScrollbar(const Scrollbar*, const IntPoint&) const;
+    virtual int scrollSize(ScrollbarOrientation) const;
+    virtual void setScrollOffset(const IntPoint&);
+    virtual IntPoint scrollPosition() const;
+    virtual IntPoint minimumScrollPosition() const;
+    virtual IntPoint maximumScrollPosition() const;
+    virtual IntRect visibleContentRect(VisibleContentRectIncludesScrollbars) const;
+    virtual int visibleHeight() const;
+    virtual int visibleWidth() const;
+    virtual IntSize contentsSize() const;
+    virtual IntSize overhangAmount() const;
+    virtual IntPoint lastKnownMousePosition() const;
+    virtual bool shouldSuspendScrollAnimations() const;
+    virtual bool scrollbarsCanBeActive() const;
+    virtual IntRect scrollableAreaBoundingBox() const OVERRIDE;
+
+    // Rectangle encompassing the scroll corner and resizer rect.
+    IntRect scrollCornerAndResizerRect() const;
+
+    // NOTE: This should only be called by the overriden setScrollOffset from ScrollableArea.
+    void scrollTo(int, int);
+    void updateCompositingLayersAfterScroll();
+
+    IntSize scrollbarOffset(const Scrollbar*) const;
+    
+    void updateScrollableAreaSet(bool hasOverflow);
+
+    void dirtyAncestorChainVisibleDescendantStatus();
+    void setAncestorChainHasVisibleDescendant();
+
+    void updateDescendantDependentFlags(HashSet<const RenderObject*>* outOfFlowDescendantContainingBlocks = 0);
+
+    // This flag is computed by RenderLayerCompositor, which knows more about 3d hierarchies than we do.
+    void setHas3DTransformedDescendant(bool b) { m_has3DTransformedDescendant = b; }
+    bool has3DTransformedDescendant() const { return m_has3DTransformedDescendant; }
+    
+    void dirty3DTransformedDescendantStatus();
+    // Both updates the status, and returns true if descendants of this have 3d.
+    bool update3DTransformedDescendantStatus();
+
+    void createReflection();
+    void removeReflection();
+
+    void updateReflectionStyle();
+    bool paintingInsideReflection() const { return m_paintingInsideReflection; }
+    void setPaintingInsideReflection(bool b) { m_paintingInsideReflection = b; }
+
+    void updateOrRemoveFilterClients();
+    void updateOrRemoveFilterEffectRenderer();
+
+    void parentClipRects(const ClipRectsContext&, ClipRects&) const;
+    ClipRect backgroundClipRect(const ClipRectsContext&) const;
+
+    LayoutRect paintingExtent(const RenderLayer* rootLayer, const LayoutRect& paintDirtyRect, PaintBehavior);
+
+    RenderLayer* enclosingTransformedAncestor() const;
+
+    // Convert a point in absolute coords into layer coords, taking transforms into account
+    LayoutPoint absoluteToContents(const LayoutPoint&) const;
+
+    void positionOverflowControls(const IntSize&);
+    void updateScrollCornerStyle();
+    void updateResizerStyle();
+
+    void drawPlatformResizerImage(GraphicsContext*, IntRect resizerCornerRect);
+
+    void updatePagination();
+    
+    // FIXME: Temporary. Remove when new columns come online.
+    bool useRegionBasedColumns() const;
+    
+    bool hasCompositingDescendant() const { return m_compositingProperties.hasCompositingDescendant; }
+    void setHasCompositingDescendant(bool b)  { m_compositingProperties.hasCompositingDescendant = b; }
+    
+    enum IndirectCompositingReason {
+        NoIndirectCompositingReason,
+        IndirectCompositingForStacking,
+        IndirectCompositingForOverlap,
+        IndirectCompositingForBackgroundLayer,
+        IndirectCompositingForGraphicalEffect, // opacity, mask, filter, transform etc.
+        IndirectCompositingForPerspective,
+        IndirectCompositingForPreserve3D
+    };
+    
+    void setIndirectCompositingReason(IndirectCompositingReason reason) { m_compositingProperties.indirectCompositingReason = reason; }
+    IndirectCompositingReason indirectCompositingReason() const { return static_cast<IndirectCompositingReason>(m_compositingProperties.indirectCompositingReason); }
+    bool mustCompositeForIndirectReasons() const { return m_compositingProperties.indirectCompositingReason; }
+
+    // Returns true if z ordering would not change if this layer were a stacking container.
+    bool canBeStackingContainer() const;
+
+    friend class RenderLayerBacking;
+    friend class RenderLayerCompositor;
+    friend class RenderLayerModelObject;
+
+    // Only safe to call from RenderBoxModelObject::destroyLayer(RenderArena*)
+    void destroy(RenderArena*);
+
+    LayoutUnit overflowTop() const;
+    LayoutUnit overflowBottom() const;
+    LayoutUnit overflowLeft() const;
+    LayoutUnit overflowRight() const;
+
+    IntRect rectForHorizontalScrollbar(const IntRect& borderBoxRect) const;
+    IntRect rectForVerticalScrollbar(const IntRect& borderBoxRect) const;
+
+    LayoutUnit verticalScrollbarStart(int minX, int maxX) const;
+    LayoutUnit horizontalScrollbarStart(int minX) const;
+
+    bool overflowControlsIntersectRect(const IntRect& localRect) const;
+
+protected:
+    // The bitfields are up here so they will fall into the padding from ScrollableArea on 64-bit.
+
+    // Keeps track of whether the layer is currently resizing, so events can cause resizing to start and stop.
+    bool m_inResizeMode : 1;
+
+    bool m_scrollDimensionsDirty : 1;
+    bool m_zOrderListsDirty : 1;
+    bool m_normalFlowListDirty: 1;
+    bool m_isNormalFlowOnly : 1;
+
+    bool m_isSelfPaintingLayer : 1;
+
+    // If have no self-painting descendants, we don't have to walk our children during painting. This can lead to
+    // significant savings, especially if the tree has lots of non-self-painting layers grouped together (e.g. table cells).
+    bool m_hasSelfPaintingLayerDescendant : 1;
+    bool m_hasSelfPaintingLayerDescendantDirty : 1;
+
+    // If we have no out of flow positioned descendants and no non-descendant
+    // appears between our descendants in stacking order, then we may become a
+    // stacking context.
+    bool m_hasOutOfFlowPositionedDescendant : 1;
+    bool m_hasOutOfFlowPositionedDescendantDirty : 1;
+
+    bool m_needsCompositedScrolling : 1;
+
+    // If this is true, then no non-descendant appears between any of our
+    // descendants in stacking order. This is one of the requirements of being
+    // able to safely become a stacking context.
+    bool m_descendantsAreContiguousInStackingOrder : 1;
+    bool m_descendantsAreContiguousInStackingOrderDirty : 1;
+
+    const bool m_isRootLayer : 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;
+    unsigned m_repaintStatus : 2; // RepaintStatus
+
+    bool m_visibleContentStatusDirty : 1;
+    bool m_hasVisibleContent : 1;
+    bool m_visibleDescendantStatusDirty : 1;
+    bool m_hasVisibleDescendant : 1;
+
+    bool m_isPaginated : 1; // If we think this layer is split by a multi-column ancestor, then this bit will be set.
+
+    bool m_3DTransformedDescendantStatusDirty : 1;
+    bool m_has3DTransformedDescendant : 1;  // Set on a stacking context layer that has 3D descendants anywhere
+                                            // in a preserves3D hierarchy. Hint to do 3D-aware hit testing.
+
+    bool m_containsDirtyOverlayScrollbars : 1;
+    bool m_updatingMarqueePosition : 1;
+
+#if !ASSERT_DISABLED
+    bool m_layerListMutationAllowed : 1;
+#endif
+    // This is an optimization added for <table>.
+    // Currently cells do not need to update their repaint rectangles when scrolling. This also
+    // saves a lot of time when scrolling on a table.
+    const bool m_canSkipRepaintRectsUpdateOnScroll : 1;
+
+    bool m_hasFilterInfo : 1;
+
+#if ENABLE(CSS_COMPOSITING)
+    BlendMode m_blendMode;
+#endif
+
+    RenderLayerModelObject* m_renderer;
+
+    RenderLayer* m_parent;
+    RenderLayer* m_previous;
+    RenderLayer* m_next;
+    RenderLayer* m_first;
+    RenderLayer* m_last;
+
+    LayoutRect m_repaintRect; // Cached repaint rects. Used by layout.
+    LayoutRect m_outlineBox;
+
+    // Paint time offset only, it is used for properly paint relative / sticky positioned elements and exclusion boxes on floats.
+    LayoutSize m_paintOffset;
+
+    // Our (x,y) coordinates are in our parent layer's coordinate space.
+    LayoutPoint m_topLeft;
+
+    // The layer's width/height
+    IntSize m_layerSize;
+
+    // This is the (scroll) offset from scrollOrigin().
+    IntSize m_scrollOffset;
+
+    // The width/height of our scrolled area.
+    LayoutSize m_scrollSize;
+
+    // For layers with overflow, we have a pair of scrollbars.
+    RefPtr<Scrollbar> m_hBar;
+    RefPtr<Scrollbar> m_vBar;
+
+    // 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.
+    OwnPtr<Vector<RenderLayer*> > m_posZOrderList;
+    OwnPtr<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.
+    OwnPtr<Vector<RenderLayer*> > m_normalFlowList;
+
+    OwnPtr<ClipRectsCache> m_clipRectsCache;
+    
+    IntPoint m_cachedOverlayScrollbarOffset;
+
+    OwnPtr<RenderMarquee> m_marquee; // Used by layers with overflow:marquee
+    
+    // Cached normal flow values for absolute positioned elements with static left/top values.
+    LayoutUnit m_staticInlinePosition;
+    LayoutUnit m_staticBlockPosition;
+
+    OwnPtr<TransformationMatrix> 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;
+
+    // Pointer to the enclosing RenderLayer that caused us to be paginated. It is 0 if we are not paginated.
+    RenderLayer* m_enclosingPaginationLayer;
+
+    // Properties that are computed while updating compositing layers. These values may be dirty/invalid if
+    // compositing status is not up-to-date before using them.
+    struct CompositingProperties {
+        CompositingProperties()
+            : hasCompositingDescendant(false)
+            , indirectCompositingReason(NoIndirectCompositingReason)
+            , viewportConstrainedNotCompositedReason(NoNotCompositedReason)
+        { }
+
+        // Used only while determining what layers should be composited. Applies to the tree of z-order lists.
+        bool hasCompositingDescendant : 1;
+
+        // Used only while determining what layers should be composited.
+        unsigned indirectCompositingReason : 3;
+
+        // The reason, if any exists, that a fixed-position layer is chosen not to be composited.
+        unsigned viewportConstrainedNotCompositedReason : 2;
+    };
+
+    CompositingProperties m_compositingProperties;
+
+private:
+    IntRect m_blockSelectionGapsBounds;
+
+    OwnPtr<RenderLayerBacking> m_backing;
+};
+
+inline void RenderLayer::clearZOrderLists()
+{
+    ASSERT(!isStackingContainer());
+
+    m_posZOrderList.clear();
+    m_negZOrderList.clear();
+}
+
+inline void RenderLayer::updateZOrderLists()
+{
+    if (!m_zOrderListsDirty)
+        return;
+
+    if (!isStackingContainer()) {
+        clearZOrderLists();
+        m_zOrderListsDirty = false;
+        return;
+    }
+
+    rebuildZOrderLists();
+}
+
+#if !ASSERT_DISABLED
+class LayerListMutationDetector {
+public:
+    LayerListMutationDetector(RenderLayer* layer)
+        : m_layer(layer)
+        , m_previousMutationAllowedState(layer->layerListMutationAllowed())
+    {
+        m_layer->setLayerListMutationAllowed(false);
+    }
+    
+    ~LayerListMutationDetector()
+    {
+        m_layer->setLayerListMutationAllowed(m_previousMutationAllowedState);
+    }
+
+private:
+    RenderLayer* m_layer;
+    bool m_previousMutationAllowedState;
+};
+#endif
+
+
+} // namespace WebCore
+
+#ifndef NDEBUG
+// Outside the WebCore namespace for ease of invocation from gdb.
+void showLayerTree(const WebCore::RenderLayer*);
+void showLayerTree(const WebCore::RenderObject*);
+#endif
+
+#endif // RenderLayer_h
diff --git a/Source/core/rendering/RenderLayerBacking.cpp b/Source/core/rendering/RenderLayerBacking.cpp
new file mode 100644
index 0000000..ac13c24
--- /dev/null
+++ b/Source/core/rendering/RenderLayerBacking.cpp
@@ -0,0 +1,1987 @@
+/*
+ * Copyright (C) 2009, 2010, 2011 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 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 "core/rendering/RenderLayerBacking.h"
+
+#include "CSSPropertyNames.h"
+#include "HTMLNames.h"
+#include "core/css/StyleResolver.h"
+#include "core/dom/WebCoreMemoryInstrumentation.h"
+#include "core/html/HTMLCanvasElement.h"
+#include "core/html/HTMLIFrameElement.h"
+#include "core/html/HTMLMediaElement.h"
+#include "core/html/canvas/CanvasRenderingContext.h"
+#include "core/inspector/InspectorInstrumentation.h"
+#include "core/loader/cache/CachedImage.h"
+#include "core/page/Chrome.h"
+#include "core/page/FrameView.h"
+#include "core/page/Settings.h"
+#include "core/page/animation/AnimationController.h"
+#include "core/page/scrolling/ScrollingCoordinator.h"
+#include "core/platform/graphics/FontCache.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/platform/graphics/GraphicsLayer.h"
+#include "core/plugins/PluginView.h"
+#include "core/rendering/RenderApplet.h"
+#include "core/rendering/RenderEmbeddedObject.h"
+#include "core/rendering/RenderIFrame.h"
+#include "core/rendering/RenderImage.h"
+#include "core/rendering/RenderLayerCompositor.h"
+#include "core/rendering/RenderVideo.h"
+#include "core/rendering/RenderView.h"
+#include "core/rendering/style/KeyframeList.h"
+#include <wtf/CurrentTime.h>
+#include <wtf/text/StringBuilder.h>
+
+#include "core/platform/graphics/filters/custom/CustomFilterOperation.h"
+#include "core/rendering/FilterEffectRenderer.h"
+
+#include "core/platform/graphics/GraphicsContext3D.h"
+
+using namespace std;
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+static bool hasBoxDecorationsOrBackgroundImage(const RenderStyle*);
+static IntRect clipBox(RenderBox* renderer);
+
+static inline bool isAcceleratedCanvas(RenderObject* renderer)
+{
+    if (renderer->isCanvas()) {
+        HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(renderer->node());
+        if (CanvasRenderingContext* context = canvas->renderingContext())
+            return context->isAccelerated();
+    }
+    return false;
+}
+
+// Get the scrolling coordinator in a way that works inside RenderLayerBacking's destructor.
+static ScrollingCoordinator* scrollingCoordinatorFromLayer(RenderLayer* layer)
+{
+    Page* page = layer->renderer()->frame()->page();
+    if (!page)
+        return 0;
+
+    return page->scrollingCoordinator();
+}
+
+RenderLayerBacking::RenderLayerBacking(RenderLayer* layer)
+    : m_owningLayer(layer)
+    , m_artificiallyInflatedBounds(false)
+    , m_boundsConstrainedByClipping(false)
+    , m_isMainFrameRenderViewLayer(false)
+    , m_requiresOwnBackingStore(true)
+    , m_canCompositeFilters(false)
+    , m_backgroundLayerPaintsFixedRootBackground(false)
+{
+    if (layer->isRootLayer()) {
+        Frame* frame = toRenderView(renderer())->frameView()->frame();
+        Page* page = frame ? frame->page() : 0;
+        if (page && frame && page->mainFrame() == frame) {
+            m_isMainFrameRenderViewLayer = true;
+        }
+    }
+    
+    createPrimaryGraphicsLayer();
+}
+
+RenderLayerBacking::~RenderLayerBacking()
+{
+    updateClippingLayers(false, false);
+    updateOverflowControlsLayers(false, false, false);
+    updateForegroundLayer(false);
+    updateBackgroundLayer(false);
+    updateMaskLayer(false);
+    updateScrollingLayers(false);
+    destroyGraphicsLayers();
+}
+
+PassOwnPtr<GraphicsLayer> RenderLayerBacking::createGraphicsLayer(const String& name)
+{
+    GraphicsLayerFactory* graphicsLayerFactory = 0;
+    if (Page* page = renderer()->frame()->page())
+        graphicsLayerFactory = page->chrome()->client()->graphicsLayerFactory();
+
+    OwnPtr<GraphicsLayer> graphicsLayer = GraphicsLayer::create(graphicsLayerFactory, this);
+
+#ifndef NDEBUG
+    graphicsLayer->setName(name);
+#else
+    UNUSED_PARAM(name);
+#endif
+    graphicsLayer->setMaintainsPixelAlignment(compositor()->keepLayersPixelAligned());
+    
+    return graphicsLayer.release();
+}
+
+void RenderLayerBacking::updateDebugIndicators(bool showBorder, bool showRepaintCounter)
+{
+    m_graphicsLayer->setShowDebugBorder(showBorder);
+    m_graphicsLayer->setShowRepaintCounter(showRepaintCounter);
+    
+    if (m_ancestorClippingLayer)
+        m_ancestorClippingLayer->setShowDebugBorder(showBorder);
+
+    if (m_foregroundLayer) {
+        m_foregroundLayer->setShowDebugBorder(showBorder);
+        m_foregroundLayer->setShowRepaintCounter(showRepaintCounter);
+    }
+    
+    if (m_contentsContainmentLayer)
+        m_contentsContainmentLayer->setShowDebugBorder(showBorder);
+    
+    if (m_backgroundLayer) {
+        m_backgroundLayer->setShowDebugBorder(showBorder);
+        m_backgroundLayer->setShowRepaintCounter(showRepaintCounter);
+    }
+
+    if (m_maskLayer) {
+        m_maskLayer->setShowDebugBorder(showBorder);
+        m_maskLayer->setShowRepaintCounter(showRepaintCounter);
+    }
+
+    if (m_layerForHorizontalScrollbar)
+        m_layerForHorizontalScrollbar->setShowDebugBorder(showBorder);
+
+    if (m_layerForVerticalScrollbar)
+        m_layerForVerticalScrollbar->setShowDebugBorder(showBorder);
+
+    if (m_layerForScrollCorner)
+        m_layerForScrollCorner->setShowDebugBorder(showBorder);
+
+    if (m_scrollingLayer)
+        m_scrollingLayer->setShowDebugBorder(showBorder);
+
+    if (m_scrollingContentsLayer) {
+        m_scrollingContentsLayer->setShowDebugBorder(showBorder);
+        m_scrollingContentsLayer->setShowRepaintCounter(showRepaintCounter);
+    }
+}
+
+void RenderLayerBacking::createPrimaryGraphicsLayer()
+{
+    String layerName;
+#ifndef NDEBUG
+    layerName = m_owningLayer->debugName();
+#endif
+    
+    m_graphicsLayer = createGraphicsLayer(layerName);
+
+    if (m_isMainFrameRenderViewLayer) {
+        m_graphicsLayer->setContentsOpaque(true);
+        m_graphicsLayer->setAppliesPageScale();
+    }
+
+    updateOpacity(renderer()->style());
+    updateTransform(renderer()->style());
+    updateFilters(renderer()->style());
+#if ENABLE(CSS_COMPOSITING)
+    updateLayerBlendMode(renderer()->style());
+#endif
+}
+
+void RenderLayerBacking::destroyGraphicsLayers()
+{
+    if (m_graphicsLayer)
+        m_graphicsLayer->removeFromParent();
+
+    m_ancestorClippingLayer = nullptr;
+    m_contentsContainmentLayer = nullptr;
+    m_graphicsLayer = nullptr;
+    m_foregroundLayer = nullptr;
+    m_backgroundLayer = nullptr;
+    m_childContainmentLayer = nullptr;
+    m_maskLayer = nullptr;
+
+    m_scrollingLayer = nullptr;
+    m_scrollingContentsLayer = nullptr;
+}
+
+void RenderLayerBacking::updateOpacity(const RenderStyle* style)
+{
+    m_graphicsLayer->setOpacity(compositingOpacity(style->opacity()));
+}
+
+void RenderLayerBacking::updateTransform(const RenderStyle* style)
+{
+    // FIXME: This could use m_owningLayer->transform(), but that currently has transform-origin
+    // baked into it, and we don't want that.
+    TransformationMatrix t;
+    if (m_owningLayer->hasTransform()) {
+        style->applyTransform(t, toRenderBox(renderer())->pixelSnappedBorderBoxRect().size(), RenderStyle::ExcludeTransformOrigin);
+        makeMatrixRenderable(t, compositor()->canRender3DTransforms());
+    }
+    
+    if (m_contentsContainmentLayer) {
+        m_contentsContainmentLayer->setTransform(t);
+        m_graphicsLayer->setTransform(TransformationMatrix());
+    } else
+        m_graphicsLayer->setTransform(t);
+}
+
+void RenderLayerBacking::updateFilters(const RenderStyle* style)
+{
+    bool didCompositeFilters = m_canCompositeFilters;
+    m_canCompositeFilters = m_graphicsLayer->setFilters(owningLayer()->computeFilterOperations(style));
+    if (didCompositeFilters != m_canCompositeFilters) {
+        //
+        // If filters used to be painted in software and are now painted in the compositor, we need to:
+        // (1) Remove the FilterEffectRenderer, which was used for painting filters in software.
+        // (2) Repaint the layer contents to remove the software-applied filter because the compositor will apply it.
+        //
+        // Similarly, if filters used to be painted in the compositor and are now painted in software, we need to:
+        // (1) Create a FilterEffectRenderer.
+        // (2) Repaint the layer contents to apply a software filter because the compositor won't apply it.
+        //
+        m_owningLayer->updateOrRemoveFilterEffectRenderer();
+        setContentsNeedDisplay();
+    }
+}
+
+#if ENABLE(CSS_COMPOSITING)
+void RenderLayerBacking::updateLayerBlendMode(const RenderStyle*)
+{
+}
+#endif
+
+static bool hasNonZeroTransformOrigin(const RenderObject* renderer)
+{
+    RenderStyle* style = renderer->style();
+    return (style->transformOriginX().type() == Fixed && style->transformOriginX().value())
+        || (style->transformOriginY().type() == Fixed && style->transformOriginY().value());
+}
+
+static bool layerOrAncestorIsTransformedOrUsingCompositedScrolling(RenderLayer* layer)
+{
+    for (RenderLayer* curr = layer; curr; curr = curr->parent()) {
+        if (curr->hasTransform() || curr->needsCompositedScrolling())
+            return true;
+    }
+    
+    return false;
+}
+
+bool RenderLayerBacking::shouldClipCompositedBounds() const
+{
+    // Scrollbar layers use this layer for relative positioning, so don't clip.
+    if (layerForHorizontalScrollbar() || layerForVerticalScrollbar())
+        return false;
+
+    if (layerOrAncestorIsTransformedOrUsingCompositedScrolling(m_owningLayer))
+        return false;
+
+    return true;
+}
+
+void RenderLayerBacking::updateCompositedBounds()
+{
+    IntRect layerBounds = compositor()->calculateCompositedBounds(m_owningLayer, m_owningLayer);
+
+    // Clip to the size of the document or enclosing overflow-scroll layer.
+    // If this or an ancestor is transformed, we can't currently compute the correct rect to intersect with.
+    // We'd need RenderObject::convertContainerToLocalQuad(), which doesn't yet exist.
+    if (shouldClipCompositedBounds()) {
+        RenderView* view = m_owningLayer->renderer()->view();
+        RenderLayer* rootLayer = view->layer();
+
+        LayoutRect clippingBounds;
+        if (renderer()->style()->position() == FixedPosition && renderer()->container() == view)
+            clippingBounds = view->frameView()->viewportConstrainedVisibleContentRect();
+        else
+            clippingBounds = view->unscaledDocumentRect();
+
+        if (m_owningLayer != rootLayer)
+            clippingBounds.intersect(m_owningLayer->backgroundClipRect(RenderLayer::ClipRectsContext(rootLayer, 0, AbsoluteClipRects)).rect()); // FIXME: Incorrect for CSS regions.
+
+        LayoutPoint delta;
+        m_owningLayer->convertToLayerCoords(rootLayer, delta);
+        clippingBounds.move(-delta.x(), -delta.y());
+
+        layerBounds.intersect(pixelSnappedIntRect(clippingBounds));
+        m_boundsConstrainedByClipping = true;
+    } else
+        m_boundsConstrainedByClipping = false;
+    
+    // If the element has a transform-origin that has fixed lengths, and the renderer has zero size,
+    // then we need to ensure that the compositing layer has non-zero size so that we can apply
+    // the transform-origin via the GraphicsLayer anchorPoint (which is expressed as a fractional value).
+    if (layerBounds.isEmpty() && hasNonZeroTransformOrigin(renderer())) {
+        layerBounds.setWidth(1);
+        layerBounds.setHeight(1);
+        m_artificiallyInflatedBounds = true;
+    } else
+        m_artificiallyInflatedBounds = false;
+
+    setCompositedBounds(layerBounds);
+}
+
+void RenderLayerBacking::updateAfterWidgetResize()
+{
+    if (renderer()->isRenderPart()) {
+        if (RenderLayerCompositor* innerCompositor = RenderLayerCompositor::frameContentsCompositor(toRenderPart(renderer()))) {
+            innerCompositor->frameViewDidChangeSize();
+            innerCompositor->frameViewDidChangeLocation(contentsBox().location());
+        }
+    }
+}
+
+void RenderLayerBacking::updateAfterLayout(UpdateAfterLayoutFlags flags)
+{
+    RenderLayerCompositor* layerCompositor = compositor();
+    if (!layerCompositor->compositingLayersNeedRebuild()) {
+        // Calling updateGraphicsLayerGeometry() here gives incorrect results, because the
+        // position of this layer's GraphicsLayer depends on the position of our compositing
+        // ancestor's GraphicsLayer. That cannot be determined until all the descendant 
+        // RenderLayers of that ancestor have been processed via updateLayerPositions().
+        //
+        // The solution is to update compositing children of this layer here,
+        // via updateCompositingChildrenGeometry().
+        updateCompositedBounds();
+        layerCompositor->updateCompositingDescendantGeometry(m_owningLayer, m_owningLayer, flags & CompositingChildrenOnly);
+        
+        if (flags & IsUpdateRoot) {
+            updateGraphicsLayerGeometry();
+            layerCompositor->updateRootLayerPosition();
+            RenderLayer* stackingContainer = m_owningLayer->enclosingStackingContainer();
+            if (!layerCompositor->compositingLayersNeedRebuild() && stackingContainer && (stackingContainer != m_owningLayer))
+                layerCompositor->updateCompositingDescendantGeometry(stackingContainer, stackingContainer, flags & CompositingChildrenOnly);
+        }
+    }
+    
+    if (flags & NeedsFullRepaint && !paintsIntoWindow() && !paintsIntoCompositedAncestor())
+        setContentsNeedDisplay();
+}
+
+bool RenderLayerBacking::updateGraphicsLayerConfiguration()
+{
+    RenderLayerCompositor* compositor = this->compositor();
+    RenderObject* renderer = this->renderer();
+
+    m_owningLayer->updateDescendantDependentFlags();
+    m_owningLayer->updateZOrderLists();
+
+    bool layerConfigChanged = false;
+    setBackgroundLayerPaintsFixedRootBackground(compositor->needsFixedRootBackgroundLayer(m_owningLayer));
+    
+    // The background layer is currently only used for fixed root backgrounds.
+    if (updateBackgroundLayer(m_backgroundLayerPaintsFixedRootBackground))
+        layerConfigChanged = true;
+
+    if (updateForegroundLayer(compositor->needsContentsCompositingLayer(m_owningLayer)))
+        layerConfigChanged = true;
+    
+    bool needsDescendentsClippingLayer = compositor->clipsCompositingDescendants(m_owningLayer);
+
+    // Our scrolling layer will clip.
+    if (m_owningLayer->needsCompositedScrolling())
+        needsDescendentsClippingLayer = false;
+
+    if (updateClippingLayers(compositor->clippedByAncestor(m_owningLayer), needsDescendentsClippingLayer))
+        layerConfigChanged = true;
+
+    if (updateOverflowControlsLayers(requiresHorizontalScrollbarLayer(), requiresVerticalScrollbarLayer(), requiresScrollCornerLayer()))
+        layerConfigChanged = true;
+
+    if (updateScrollingLayers(m_owningLayer->needsCompositedScrolling()))
+        layerConfigChanged = true;
+
+    if (layerConfigChanged)
+        updateInternalHierarchy();
+
+    if (updateMaskLayer(renderer->hasMask()))
+        m_graphicsLayer->setMaskLayer(m_maskLayer.get());
+
+    if (m_owningLayer->hasReflection()) {
+        if (m_owningLayer->reflectionLayer()->backing()) {
+            GraphicsLayer* reflectionLayer = m_owningLayer->reflectionLayer()->backing()->graphicsLayer();
+            m_graphicsLayer->setReplicatedByLayer(reflectionLayer);
+        }
+    } else
+        m_graphicsLayer->setReplicatedByLayer(0);
+
+    updateBackgroundColor(isSimpleContainerCompositingLayer());
+    updateRootLayerConfiguration();
+    
+    if (isDirectlyCompositedImage())
+        updateImageContents();
+
+    if (renderer->isEmbeddedObject() && toRenderEmbeddedObject(renderer)->allowsAcceleratedCompositing()) {
+        PluginView* pluginView = toPluginView(toRenderWidget(renderer)->widget());
+        m_graphicsLayer->setContentsToMedia(pluginView->platformLayer());
+    } else if (renderer->isVideo()) {
+        HTMLMediaElement* mediaElement = toMediaElement(renderer->node());
+        m_graphicsLayer->setContentsToMedia(mediaElement->platformLayer());
+    } else if (isAcceleratedCanvas(renderer)) {
+        HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(renderer->node());
+        if (CanvasRenderingContext* context = canvas->renderingContext())
+            m_graphicsLayer->setContentsToCanvas(context->platformLayer());
+        layerConfigChanged = true;
+    }
+    if (renderer->isRenderPart())
+        layerConfigChanged = RenderLayerCompositor::parentFrameContentLayers(toRenderPart(renderer));
+
+    return layerConfigChanged;
+}
+
+static IntRect clipBox(RenderBox* renderer)
+{
+    LayoutRect result = PaintInfo::infiniteRect();
+    if (renderer->hasOverflowClip())
+        result = renderer->overflowClipRect(LayoutPoint(), 0); // FIXME: Incorrect for CSS regions.
+
+    if (renderer->hasClip())
+        result.intersect(renderer->clipRect(LayoutPoint(), 0)); // FIXME: Incorrect for CSS regions.
+
+    return pixelSnappedIntRect(result);
+}
+
+void RenderLayerBacking::updateGraphicsLayerGeometry()
+{
+    // If we haven't built z-order lists yet, wait until later.
+    if (m_owningLayer->isStackingContainer() && m_owningLayer->m_zOrderListsDirty)
+        return;
+
+    // Set transform property, if it is not animating. We have to do this here because the transform
+    // is affected by the layer dimensions.
+    if (!renderer()->animation()->isRunningAcceleratedAnimationOnRenderer(renderer(), CSSPropertyWebkitTransform))
+        updateTransform(renderer()->style());
+
+    // Set opacity, if it is not animating.
+    if (!renderer()->animation()->isRunningAcceleratedAnimationOnRenderer(renderer(), CSSPropertyOpacity))
+        updateOpacity(renderer()->style());
+
+#if ENABLE(CSS_COMPOSITING)
+    updateLayerBlendMode(renderer()->style());
+#endif
+
+    bool isSimpleContainer = isSimpleContainerCompositingLayer();
+    
+    m_owningLayer->updateDescendantDependentFlags();
+
+    // m_graphicsLayer is the corresponding GraphicsLayer for this RenderLayer and its non-compositing
+    // descendants. So, the visibility flag for m_graphicsLayer should be true if there are any
+    // non-compositing visible layers.
+    m_graphicsLayer->setContentsVisible(m_owningLayer->hasVisibleContent() || hasVisibleNonCompositingDescendantLayers());
+
+    RenderStyle* style = renderer()->style();
+    // FIXME: reflections should force transform-style to be flat in the style: https://bugs.webkit.org/show_bug.cgi?id=106959
+    bool preserves3D = style->transformStyle3D() == TransformStyle3DPreserve3D && !renderer()->hasReflection();
+    m_graphicsLayer->setPreserves3D(preserves3D);
+    m_graphicsLayer->setBackfaceVisibility(style->backfaceVisibility() == BackfaceVisibilityVisible);
+
+    RenderLayer* compAncestor = m_owningLayer->ancestorCompositingLayer();
+    
+    // We compute everything relative to the enclosing compositing layer.
+    IntRect ancestorCompositingBounds;
+    if (compAncestor) {
+        ASSERT(compAncestor->backing());
+        ancestorCompositingBounds = pixelSnappedIntRect(compAncestor->backing()->compositedBounds());
+    }
+
+    IntRect localCompositingBounds = pixelSnappedIntRect(compositedBounds());
+
+    IntRect relativeCompositingBounds(localCompositingBounds);
+    IntPoint delta;
+    m_owningLayer->convertToPixelSnappedLayerCoords(compAncestor, delta);
+    relativeCompositingBounds.moveBy(delta);
+
+    IntPoint graphicsLayerParentLocation;
+    if (compAncestor && compAncestor->backing()->hasClippingLayer()) {
+        // If the compositing ancestor has a layer to clip children, we parent in that, and therefore
+        // position relative to it.
+        IntRect clippingBox = clipBox(toRenderBox(compAncestor->renderer()));
+        graphicsLayerParentLocation = clippingBox.location();
+    } else if (compAncestor)
+        graphicsLayerParentLocation = ancestorCompositingBounds.location();
+    else
+        graphicsLayerParentLocation = renderer()->view()->documentRect().location();
+
+    if (compAncestor && compAncestor->needsCompositedScrolling()) {
+        RenderBox* renderBox = toRenderBox(compAncestor->renderer());
+        IntSize scrollOffset = compAncestor->scrolledContentOffset();
+        IntPoint scrollOrigin(renderBox->borderLeft(), renderBox->borderTop());
+        graphicsLayerParentLocation = scrollOrigin - scrollOffset;
+    }
+    
+    if (compAncestor && m_ancestorClippingLayer) {
+        // Call calculateRects to get the backgroundRect which is what is used to clip the contents of this
+        // layer. Note that we call it with temporaryClipRects = true because normally when computing clip rects
+        // for a compositing layer, rootLayer is the layer itself.
+        RenderLayer::ClipRectsContext clipRectsContext(compAncestor, 0, TemporaryClipRects, IgnoreOverlayScrollbarSize, IgnoreOverflowClip);
+        IntRect parentClipRect = pixelSnappedIntRect(m_owningLayer->backgroundClipRect(clipRectsContext).rect()); // FIXME: Incorrect for CSS regions.
+        ASSERT(parentClipRect != PaintInfo::infiniteRect());
+        m_ancestorClippingLayer->setPosition(FloatPoint(parentClipRect.location() - graphicsLayerParentLocation));
+        m_ancestorClippingLayer->setSize(parentClipRect.size());
+
+        // backgroundRect is relative to compAncestor, so subtract deltaX/deltaY to get back to local coords.
+        m_ancestorClippingLayer->setOffsetFromRenderer(parentClipRect.location() - delta);
+
+        // The primary layer is then parented in, and positioned relative to this clipping layer.
+        graphicsLayerParentLocation = parentClipRect.location();
+    }
+
+    FloatSize contentsSize = relativeCompositingBounds.size();
+    
+    if (m_contentsContainmentLayer) {
+        m_contentsContainmentLayer->setPreserves3D(preserves3D);
+        m_contentsContainmentLayer->setPosition(FloatPoint(relativeCompositingBounds.location() - graphicsLayerParentLocation));
+        // Use the same size as m_graphicsLayer so transforms behave correctly.
+        m_contentsContainmentLayer->setSize(contentsSize);
+        graphicsLayerParentLocation = relativeCompositingBounds.location();
+    }
+
+    m_graphicsLayer->setPosition(FloatPoint(relativeCompositingBounds.location() - graphicsLayerParentLocation));
+    m_graphicsLayer->setOffsetFromRenderer(toIntSize(localCompositingBounds.location()));
+    
+    FloatSize oldSize = m_graphicsLayer->size();
+    if (oldSize != contentsSize) {
+        m_graphicsLayer->setSize(contentsSize);
+        // Usually invalidation will happen via layout etc, but if we've affected the layer
+        // size by constraining relative to a clipping ancestor or the viewport, we
+        // have to invalidate to avoid showing stretched content.
+        if (m_boundsConstrainedByClipping)
+            m_graphicsLayer->setNeedsDisplay();
+    }
+    if (!m_isMainFrameRenderViewLayer) {
+        // For non-root layers, background is always painted by the primary graphics layer.
+        ASSERT(!m_backgroundLayer);
+        m_graphicsLayer->setContentsOpaque(m_owningLayer->backgroundIsKnownToBeOpaqueInRect(localCompositingBounds));
+    }
+
+    // If we have a layer that clips children, position it.
+    IntRect clippingBox;
+    if (GraphicsLayer* clipLayer = clippingLayer()) {
+        clippingBox = clipBox(toRenderBox(renderer()));
+        clipLayer->setPosition(FloatPoint(clippingBox.location() - localCompositingBounds.location()));
+        clipLayer->setSize(clippingBox.size());
+        clipLayer->setOffsetFromRenderer(toIntSize(clippingBox.location()));
+    }
+    
+    if (m_maskLayer) {
+        if (m_maskLayer->size() != m_graphicsLayer->size()) {
+            m_maskLayer->setSize(m_graphicsLayer->size());
+            m_maskLayer->setNeedsDisplay();
+        }
+        m_maskLayer->setPosition(FloatPoint());
+        m_maskLayer->setOffsetFromRenderer(m_graphicsLayer->offsetFromRenderer());
+    }
+    
+    if (m_owningLayer->hasTransform()) {
+        const IntRect borderBox = toRenderBox(renderer())->pixelSnappedBorderBoxRect();
+
+        // Get layout bounds in the coords of compAncestor to match relativeCompositingBounds.
+        IntRect layerBounds = IntRect(delta, borderBox.size());
+
+        // Update properties that depend on layer dimensions
+        FloatPoint3D transformOrigin = computeTransformOrigin(borderBox);
+        // Compute the anchor point, which is in the center of the renderer box unless transform-origin is set.
+        FloatPoint3D anchor(relativeCompositingBounds.width()  != 0.0f ? ((layerBounds.x() - relativeCompositingBounds.x()) + transformOrigin.x()) / relativeCompositingBounds.width()  : 0.5f,
+                            relativeCompositingBounds.height() != 0.0f ? ((layerBounds.y() - relativeCompositingBounds.y()) + transformOrigin.y()) / relativeCompositingBounds.height() : 0.5f,
+                            transformOrigin.z());
+        if (m_contentsContainmentLayer)
+            m_contentsContainmentLayer->setAnchorPoint(anchor);
+        else
+            m_graphicsLayer->setAnchorPoint(anchor);
+
+        RenderStyle* style = renderer()->style();
+        GraphicsLayer* clipLayer = clippingLayer();
+        if (style->hasPerspective()) {
+            TransformationMatrix t = owningLayer()->perspectiveTransform();
+            
+            if (clipLayer) {
+                clipLayer->setChildrenTransform(t);
+                m_graphicsLayer->setChildrenTransform(TransformationMatrix());
+            }
+            else
+                m_graphicsLayer->setChildrenTransform(t);
+        } else {
+            if (clipLayer)
+                clipLayer->setChildrenTransform(TransformationMatrix());
+            else
+                m_graphicsLayer->setChildrenTransform(TransformationMatrix());
+        }
+    } else {
+        m_graphicsLayer->setAnchorPoint(FloatPoint3D(0.5f, 0.5f, 0));
+        if (m_contentsContainmentLayer)
+            m_contentsContainmentLayer->setAnchorPoint(FloatPoint3D(0.5f, 0.5f, 0));
+    }
+
+    if (m_foregroundLayer) {
+        FloatPoint foregroundPosition;
+        FloatSize foregroundSize = contentsSize;
+        IntSize foregroundOffset = m_graphicsLayer->offsetFromRenderer();
+        if (hasClippingLayer()) {
+            // If we have a clipping layer (which clips descendants), then the foreground layer is a child of it,
+            // so that it gets correctly sorted with children. In that case, position relative to the clipping layer.
+            foregroundSize = FloatSize(clippingBox.size());
+            foregroundOffset = toIntSize(clippingBox.location());
+        }
+
+        m_foregroundLayer->setPosition(foregroundPosition);
+        if (foregroundSize != m_foregroundLayer->size()) {
+            m_foregroundLayer->setSize(foregroundSize);
+            m_foregroundLayer->setNeedsDisplay();
+        }
+        m_foregroundLayer->setOffsetFromRenderer(foregroundOffset);
+    }
+
+    if (m_backgroundLayer) {
+        FloatPoint backgroundPosition;
+        FloatSize backgroundSize = contentsSize;
+        if (backgroundLayerPaintsFixedRootBackground()) {
+            FrameView* frameView = toRenderView(renderer())->frameView();
+            backgroundPosition = IntPoint(frameView->scrollOffsetForFixedPosition());
+            backgroundSize = frameView->visibleContentRect().size();
+        }
+        m_backgroundLayer->setPosition(backgroundPosition);
+        if (backgroundSize != m_backgroundLayer->size()) {
+            m_backgroundLayer->setSize(backgroundSize);
+            m_backgroundLayer->setNeedsDisplay();
+        }
+        m_backgroundLayer->setOffsetFromRenderer(m_graphicsLayer->offsetFromRenderer());
+    }
+
+    if (m_owningLayer->reflectionLayer() && m_owningLayer->reflectionLayer()->isComposited()) {
+        RenderLayerBacking* reflectionBacking = m_owningLayer->reflectionLayer()->backing();
+        reflectionBacking->updateGraphicsLayerGeometry();
+        
+        // The reflection layer has the bounds of m_owningLayer->reflectionLayer(),
+        // but the reflected layer is the bounds of this layer, so we need to position it appropriately.
+        FloatRect layerBounds = compositedBounds();
+        FloatRect reflectionLayerBounds = reflectionBacking->compositedBounds();
+        reflectionBacking->graphicsLayer()->setReplicatedLayerPosition(FloatPoint(layerBounds.location() - reflectionLayerBounds.location()));
+    }
+
+    if (m_scrollingLayer) {
+        ASSERT(m_scrollingContentsLayer);
+        RenderBox* renderBox = toRenderBox(renderer());
+        IntRect paddingBox(renderBox->borderLeft(), renderBox->borderTop(), renderBox->width() - renderBox->borderLeft() - renderBox->borderRight(), renderBox->height() - renderBox->borderTop() - renderBox->borderBottom());
+        IntSize scrollOffset = m_owningLayer->scrollOffset();
+
+        m_scrollingLayer->setPosition(FloatPoint(paddingBox.location() - localCompositingBounds.location()));
+
+        m_scrollingLayer->setSize(paddingBox.size());
+        m_scrollingContentsLayer->setPosition(FloatPoint(-scrollOffset.width(), -scrollOffset.height()));
+
+        IntSize oldScrollingLayerOffset = m_scrollingLayer->offsetFromRenderer();
+        m_scrollingLayer->setOffsetFromRenderer(-toIntSize(paddingBox.location()));
+
+        bool paddingBoxOffsetChanged = oldScrollingLayerOffset != m_scrollingLayer->offsetFromRenderer();
+
+        IntSize scrollSize(m_owningLayer->scrollWidth(), m_owningLayer->scrollHeight());
+        if (scrollSize != m_scrollingContentsLayer->size() || paddingBoxOffsetChanged)
+            m_scrollingContentsLayer->setNeedsDisplay();
+
+        IntSize scrollingContentsOffset = toIntSize(paddingBox.location() - scrollOffset);
+        if (scrollingContentsOffset != m_scrollingContentsLayer->offsetFromRenderer() || scrollSize != m_scrollingContentsLayer->size())
+            compositor()->scrollingLayerDidChange(m_owningLayer);
+
+        m_scrollingContentsLayer->setSize(scrollSize);
+        // FIXME: The paint offset and the scroll offset should really be separate concepts.
+        m_scrollingContentsLayer->setOffsetFromRenderer(scrollingContentsOffset, GraphicsLayer::DontSetNeedsDisplay);
+
+        if (m_foregroundLayer) {
+            if (m_foregroundLayer->size() != m_scrollingContentsLayer->size())
+                m_foregroundLayer->setSize(m_scrollingContentsLayer->size());
+            m_foregroundLayer->setNeedsDisplay();
+            m_foregroundLayer->setOffsetFromRenderer(m_scrollingContentsLayer->offsetFromRenderer());
+        }
+    }
+
+    // If this layer was created just for clipping or to apply perspective, it doesn't need its own backing store.
+    setRequiresOwnBackingStore(compositor()->requiresOwnBackingStore(m_owningLayer, compAncestor));
+
+    updateContentsRect(isSimpleContainer);
+    updateBackgroundColor(isSimpleContainer);
+    updateDrawsContent(isSimpleContainer);
+    updateAfterWidgetResize();
+    registerScrollingLayers();
+}
+
+void RenderLayerBacking::registerScrollingLayers()
+{
+    // Register fixed position layers and their containers with the scrolling coordinator.
+    ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer);
+    if (!scrollingCoordinator)
+        return;
+
+    compositor()->updateViewportConstraintStatus(m_owningLayer);
+
+    scrollingCoordinator->updateLayerPositionConstraint(m_owningLayer);
+
+    // Page scale is applied as a transform on the root render view layer. Because the scroll
+    // layer is further up in the hierarchy, we need to avoid marking the root render view
+    // layer as a container.
+    bool isContainer = m_owningLayer->hasTransform() && !m_owningLayer->isRootLayer();
+    scrollingCoordinator->setLayerIsContainerForFixedPositionLayers(childForSuperlayers(), isContainer);
+}
+
+void RenderLayerBacking::updateInternalHierarchy()
+{
+    // m_foregroundLayer has to be inserted in the correct order with child layers,
+    // so it's not inserted here.
+    if (m_ancestorClippingLayer)
+        m_ancestorClippingLayer->removeAllChildren();
+    
+    if (m_contentsContainmentLayer) {
+        m_contentsContainmentLayer->removeAllChildren();
+        if (m_ancestorClippingLayer)
+            m_ancestorClippingLayer->addChild(m_contentsContainmentLayer.get());
+    }
+    
+    if (m_backgroundLayer)
+        m_contentsContainmentLayer->addChild(m_backgroundLayer.get());
+
+    m_graphicsLayer->removeFromParent();
+    if (m_contentsContainmentLayer)
+        m_contentsContainmentLayer->addChild(m_graphicsLayer.get());
+    else if (m_ancestorClippingLayer)
+        m_ancestorClippingLayer->addChild(m_graphicsLayer.get());
+
+    if (m_childContainmentLayer) {
+        m_childContainmentLayer->removeFromParent();
+        m_graphicsLayer->addChild(m_childContainmentLayer.get());
+    }
+
+    if (m_scrollingLayer) {
+        GraphicsLayer* superlayer = m_childContainmentLayer ? m_childContainmentLayer.get() : m_graphicsLayer.get();
+        m_scrollingLayer->removeFromParent();
+        superlayer->addChild(m_scrollingLayer.get());
+    }
+
+    // The clip for child layers does not include space for overflow controls, so they exist as
+    // siblings of the clipping layer if we have one. Normal children of this layer are set as
+    // children of the clipping layer.
+    if (m_layerForHorizontalScrollbar) {
+        m_layerForHorizontalScrollbar->removeFromParent();
+        m_graphicsLayer->addChild(m_layerForHorizontalScrollbar.get());
+    }
+    if (m_layerForVerticalScrollbar) {
+        m_layerForVerticalScrollbar->removeFromParent();
+        m_graphicsLayer->addChild(m_layerForVerticalScrollbar.get());
+    }
+    if (m_layerForScrollCorner) {
+        m_layerForScrollCorner->removeFromParent();
+        m_graphicsLayer->addChild(m_layerForScrollCorner.get());
+    }
+}
+
+void RenderLayerBacking::updateContentsRect(bool isSimpleContainer)
+{
+    IntRect contentsRect;
+    if (isSimpleContainer && renderer()->hasBackground())
+        contentsRect = backgroundBox();
+    else
+        contentsRect = contentsBox();
+
+    m_graphicsLayer->setContentsRect(contentsRect);
+}
+
+void RenderLayerBacking::updateDrawsContent()
+{
+    updateDrawsContent(isSimpleContainerCompositingLayer());
+}
+
+void RenderLayerBacking::updateDrawsContent(bool isSimpleContainer)
+{
+    if (m_scrollingLayer) {
+        // We don't have to consider overflow controls, because we know that the scrollbars are drawn elsewhere.
+        // m_graphicsLayer only needs backing store if the non-scrolling parts (background, outlines, borders, shadows etc) need to paint.
+        // m_scrollingLayer never has backing store.
+        // m_scrollingContentsLayer only needs backing store if the scrolled contents need to paint.
+        bool hasNonScrollingPaintedContent = m_owningLayer->hasVisibleContent() && m_owningLayer->hasBoxDecorationsOrBackground();
+        m_graphicsLayer->setDrawsContent(hasNonScrollingPaintedContent);
+
+        bool hasScrollingPaintedContent = m_owningLayer->hasVisibleContent() && (renderer()->hasBackground() || paintsChildren());
+        m_scrollingContentsLayer->setDrawsContent(hasScrollingPaintedContent);
+        return;
+    }
+
+    bool hasPaintedContent = !isSimpleContainer && containsPaintedContent();
+
+    // FIXME: we could refine this to only allocate backing for one of these layers if possible.
+    m_graphicsLayer->setDrawsContent(hasPaintedContent);
+    if (m_foregroundLayer)
+        m_foregroundLayer->setDrawsContent(hasPaintedContent);
+
+    if (m_backgroundLayer)
+        m_backgroundLayer->setDrawsContent(hasPaintedContent);
+}
+
+// Return true if the layers changed.
+bool RenderLayerBacking::updateClippingLayers(bool needsAncestorClip, bool needsDescendantClip)
+{
+    bool layersChanged = false;
+
+    if (needsAncestorClip) {
+        if (!m_ancestorClippingLayer) {
+            m_ancestorClippingLayer = createGraphicsLayer("Ancestor clipping Layer");
+            m_ancestorClippingLayer->setMasksToBounds(true);
+            layersChanged = true;
+        }
+    } else if (m_ancestorClippingLayer) {
+        m_ancestorClippingLayer->removeFromParent();
+        m_ancestorClippingLayer = nullptr;
+        layersChanged = true;
+    }
+    
+    if (needsDescendantClip) {
+        if (!m_childContainmentLayer) {
+            m_childContainmentLayer = createGraphicsLayer("Child clipping Layer");
+            m_childContainmentLayer->setMasksToBounds(true);
+            layersChanged = true;
+        }
+    } else if (hasClippingLayer()) {
+        m_childContainmentLayer->removeFromParent();
+        m_childContainmentLayer = nullptr;
+        layersChanged = true;
+    }
+    
+    return layersChanged;
+}
+
+void RenderLayerBacking::setBackgroundLayerPaintsFixedRootBackground(bool backgroundLayerPaintsFixedRootBackground)
+{
+    m_backgroundLayerPaintsFixedRootBackground = backgroundLayerPaintsFixedRootBackground;
+}
+
+bool RenderLayerBacking::updateOverflowControlsLayers(bool needsHorizontalScrollbarLayer, bool needsVerticalScrollbarLayer, bool needsScrollCornerLayer)
+{
+    bool horizontalScrollbarLayerChanged = false;
+    if (needsHorizontalScrollbarLayer) {
+        if (!m_layerForHorizontalScrollbar) {
+            m_layerForHorizontalScrollbar = createGraphicsLayer("horizontal scrollbar");
+            horizontalScrollbarLayerChanged = true;
+        }
+    } else if (m_layerForHorizontalScrollbar) {
+        m_layerForHorizontalScrollbar = nullptr;
+        horizontalScrollbarLayerChanged = true;
+    }
+
+    bool verticalScrollbarLayerChanged = false;
+    if (needsVerticalScrollbarLayer) {
+        if (!m_layerForVerticalScrollbar) {
+            m_layerForVerticalScrollbar = createGraphicsLayer("vertical scrollbar");
+            verticalScrollbarLayerChanged = true;
+        }
+    } else if (m_layerForVerticalScrollbar) {
+        m_layerForVerticalScrollbar = nullptr;
+        verticalScrollbarLayerChanged = true;
+    }
+
+    bool scrollCornerLayerChanged = false;
+    if (needsScrollCornerLayer) {
+        if (!m_layerForScrollCorner) {
+            m_layerForScrollCorner = createGraphicsLayer("scroll corner");
+            scrollCornerLayerChanged = true;
+        }
+    } else if (m_layerForScrollCorner) {
+        m_layerForScrollCorner = nullptr;
+        scrollCornerLayerChanged = true;
+    }
+
+    if (ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer)) {
+        if (horizontalScrollbarLayerChanged)
+            scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_owningLayer, HorizontalScrollbar);
+        if (verticalScrollbarLayerChanged)
+            scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_owningLayer, VerticalScrollbar);
+    }
+
+    return horizontalScrollbarLayerChanged || verticalScrollbarLayerChanged || scrollCornerLayerChanged;
+}
+
+void RenderLayerBacking::positionOverflowControlsLayers(const IntSize& offsetFromRoot)
+{
+    IntSize offsetFromRenderer = m_graphicsLayer->offsetFromRenderer();
+    if (GraphicsLayer* layer = layerForHorizontalScrollbar()) {
+        Scrollbar* hBar = m_owningLayer->horizontalScrollbar();
+        if (hBar) {
+            layer->setPosition(hBar->frameRect().location() - offsetFromRoot - offsetFromRenderer);
+            layer->setSize(hBar->frameRect().size());
+            if (layer->hasContentsLayer())
+                layer->setContentsRect(IntRect(IntPoint(), hBar->frameRect().size()));
+        }
+        layer->setDrawsContent(hBar && !layer->hasContentsLayer());
+    }
+    
+    if (GraphicsLayer* layer = layerForVerticalScrollbar()) {
+        Scrollbar* vBar = m_owningLayer->verticalScrollbar();
+        if (vBar) {
+            layer->setPosition(vBar->frameRect().location() - offsetFromRoot - offsetFromRenderer);
+            layer->setSize(vBar->frameRect().size());
+            if (layer->hasContentsLayer())
+                layer->setContentsRect(IntRect(IntPoint(), vBar->frameRect().size()));
+        }
+        layer->setDrawsContent(vBar && !layer->hasContentsLayer());
+    }
+
+    if (GraphicsLayer* layer = layerForScrollCorner()) {
+        const LayoutRect& scrollCornerAndResizer = m_owningLayer->scrollCornerAndResizerRect();
+        layer->setPosition(scrollCornerAndResizer.location() - offsetFromRenderer);
+        layer->setSize(scrollCornerAndResizer.size());
+        layer->setDrawsContent(!scrollCornerAndResizer.isEmpty());
+    }
+}
+
+bool RenderLayerBacking::hasUnpositionedOverflowControlsLayers() const
+{
+    if (GraphicsLayer* layer = layerForHorizontalScrollbar())
+        if (!layer->drawsContent())
+            return true;
+
+    if (GraphicsLayer* layer = layerForVerticalScrollbar())
+        if (!layer->drawsContent())
+            return true;
+
+    if (GraphicsLayer* layer = layerForScrollCorner())
+        if (!layer->drawsContent())
+            return true;
+
+    return false;
+}
+
+bool RenderLayerBacking::updateForegroundLayer(bool needsForegroundLayer)
+{
+    bool layerChanged = false;
+    if (needsForegroundLayer) {
+        if (!m_foregroundLayer) {
+            String layerName;
+#ifndef NDEBUG
+            layerName = m_owningLayer->debugName() + " (foreground)";
+#endif
+            m_foregroundLayer = createGraphicsLayer(layerName);
+            m_foregroundLayer->setDrawsContent(true);
+            m_foregroundLayer->setPaintingPhase(GraphicsLayerPaintForeground);
+            layerChanged = true;
+        }
+    } else if (m_foregroundLayer) {
+        m_foregroundLayer->removeFromParent();
+        m_foregroundLayer = nullptr;
+        layerChanged = true;
+    }
+
+    if (layerChanged)
+        m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer());
+
+    return layerChanged;
+}
+
+bool RenderLayerBacking::updateBackgroundLayer(bool needsBackgroundLayer)
+{
+    bool layerChanged = false;
+    if (needsBackgroundLayer) {
+        if (!m_backgroundLayer) {
+            String layerName;
+#ifndef NDEBUG
+            layerName = m_owningLayer->debugName() + " (background)";
+#endif
+            m_backgroundLayer = createGraphicsLayer(layerName);
+            m_backgroundLayer->setDrawsContent(true);
+            m_backgroundLayer->setAnchorPoint(FloatPoint3D());
+            m_backgroundLayer->setPaintingPhase(GraphicsLayerPaintBackground);
+            layerChanged = true;
+        }
+        
+        if (!m_contentsContainmentLayer) {
+            String layerName;
+#ifndef NDEBUG
+            layerName = m_owningLayer->debugName() + " (contents containment)";
+#endif
+            m_contentsContainmentLayer = createGraphicsLayer(layerName);
+            m_contentsContainmentLayer->setAppliesPageScale(true);
+            m_graphicsLayer->setAppliesPageScale(false);
+            layerChanged = true;
+        }
+    } else {
+        if (m_backgroundLayer) {
+            m_backgroundLayer->removeFromParent();
+            m_backgroundLayer = nullptr;
+            layerChanged = true;
+        }
+        if (m_contentsContainmentLayer) {
+            m_contentsContainmentLayer->removeFromParent();
+            m_contentsContainmentLayer = nullptr;
+            layerChanged = true;
+            m_graphicsLayer->setAppliesPageScale(true);
+        }
+    }
+    
+    return layerChanged;
+}
+
+bool RenderLayerBacking::updateMaskLayer(bool needsMaskLayer)
+{
+    bool layerChanged = false;
+    if (needsMaskLayer) {
+        if (!m_maskLayer) {
+            m_maskLayer = createGraphicsLayer("Mask");
+            m_maskLayer->setDrawsContent(true);
+            m_maskLayer->setPaintingPhase(GraphicsLayerPaintMask);
+            layerChanged = true;
+        }
+    } else if (m_maskLayer) {
+        m_maskLayer = nullptr;
+        layerChanged = true;
+    }
+
+    if (layerChanged)
+        m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer());
+
+    return layerChanged;
+}
+
+bool RenderLayerBacking::updateScrollingLayers(bool needsScrollingLayers)
+{
+    ScrollingCoordinator* scrollingCoordinator = scrollingCoordinatorFromLayer(m_owningLayer);
+
+    bool layerChanged = false;
+    if (needsScrollingLayers) {
+        if (!m_scrollingLayer) {
+            // Outer layer which corresponds with the scroll view.
+            m_scrollingLayer = createGraphicsLayer("Scrolling container");
+            m_scrollingLayer->setDrawsContent(false);
+            m_scrollingLayer->setMasksToBounds(true);
+
+            // Inner layer which renders the content that scrolls.
+            m_scrollingContentsLayer = createGraphicsLayer("Scrolled Contents");
+            m_scrollingContentsLayer->setDrawsContent(true);
+            GraphicsLayerPaintingPhase paintPhase = GraphicsLayerPaintOverflowContents | GraphicsLayerPaintCompositedScroll;
+            if (!m_foregroundLayer)
+                paintPhase |= GraphicsLayerPaintForeground;
+            m_scrollingContentsLayer->setPaintingPhase(paintPhase);
+            m_scrollingLayer->addChild(m_scrollingContentsLayer.get());
+
+            layerChanged = true;
+            if (scrollingCoordinator)
+                scrollingCoordinator->scrollableAreaScrollLayerDidChange(m_owningLayer);
+        }
+    } else if (m_scrollingLayer) {
+        m_scrollingLayer = nullptr;
+        m_scrollingContentsLayer = nullptr;
+        layerChanged = true;
+        if (scrollingCoordinator)
+            scrollingCoordinator->scrollableAreaScrollLayerDidChange(m_owningLayer);
+    }
+
+    if (layerChanged) {
+        updateInternalHierarchy();
+        m_graphicsLayer->setPaintingPhase(paintingPhaseForPrimaryLayer());
+        m_graphicsLayer->setNeedsDisplay();
+        if (renderer()->view())
+            compositor()->scrollingLayerDidChange(m_owningLayer);
+    }
+
+    return layerChanged;
+}
+
+GraphicsLayerPaintingPhase RenderLayerBacking::paintingPhaseForPrimaryLayer() const
+{
+    unsigned phase = 0;
+    if (!m_backgroundLayer)
+        phase |= GraphicsLayerPaintBackground;
+    if (!m_foregroundLayer)
+        phase |= GraphicsLayerPaintForeground;
+    if (!m_maskLayer)
+        phase |= GraphicsLayerPaintMask;
+
+    if (m_scrollingContentsLayer) {
+        phase &= ~GraphicsLayerPaintForeground;
+        phase |= GraphicsLayerPaintCompositedScroll;
+    }
+
+    return static_cast<GraphicsLayerPaintingPhase>(phase);
+}
+
+float RenderLayerBacking::compositingOpacity(float rendererOpacity) const
+{
+    float finalOpacity = rendererOpacity;
+    
+    for (RenderLayer* curr = m_owningLayer->parent(); curr; curr = curr->parent()) {
+        // We only care about parents that are stacking contexts.
+        // Recall that opacity creates stacking context.
+        if (!curr->isStackingContainer())
+            continue;
+        
+        // If we found a compositing layer, we want to compute opacity
+        // relative to it. So we can break here.
+        if (curr->isComposited())
+            break;
+        
+        finalOpacity *= curr->renderer()->opacity();
+    }
+
+    return finalOpacity;
+}
+
+static bool hasBoxDecorations(const RenderStyle* style)
+{
+    return style->hasBorder() || style->hasBorderRadius() || style->hasOutline() || style->hasAppearance() || style->boxShadow() || style->hasFilter();
+}
+
+static bool hasBoxDecorationsOrBackgroundImage(const RenderStyle* style)
+{
+    return hasBoxDecorations(style) || style->hasBackgroundImage();
+}
+
+Color RenderLayerBacking::rendererBackgroundColor() const
+{
+    RenderObject* backgroundRenderer = renderer();
+    if (backgroundRenderer->isRoot())
+        backgroundRenderer = backgroundRenderer->rendererForRootBackground();
+
+    return backgroundRenderer->style()->visitedDependentColor(CSSPropertyBackgroundColor);
+}
+
+void RenderLayerBacking::updateBackgroundColor(bool isSimpleContainer)
+{
+    Color backgroundColor = rendererBackgroundColor();
+    if (isSimpleContainer) {
+        m_graphicsLayer->setContentsToSolidColor(backgroundColor);
+        m_graphicsLayer->setBackgroundColor(Color());
+    } else {
+        // An unset (invalid) color will remove the solid color.
+        m_graphicsLayer->setContentsToSolidColor(Color());
+        m_graphicsLayer->setBackgroundColor(backgroundColor);
+    }
+}
+
+void RenderLayerBacking::updateRootLayerConfiguration()
+{
+}
+
+static bool supportsDirectBoxDecorationsComposition(const RenderObject* renderer)
+{
+    if (!GraphicsLayer::supportsBackgroundColorContent())
+        return false;
+
+    if (renderer->hasClip())
+        return false;
+
+    if (hasBoxDecorationsOrBackgroundImage(renderer->style()))
+        return false;
+
+    // FIXME: we should be able to allow backgroundComposite; However since this is not a common use case it has been deferred for now.
+    if (renderer->style()->backgroundComposite() != CompositeSourceOver)
+        return false;
+
+    if (renderer->style()->backgroundClip() == TextFillBox)
+        return false;
+
+    return true;
+}
+
+bool RenderLayerBacking::paintsBoxDecorations() const
+{
+    if (!m_owningLayer->hasVisibleBoxDecorations())
+        return false;
+
+    if (!supportsDirectBoxDecorationsComposition(renderer()))
+        return true;
+
+    return false;
+}
+
+bool RenderLayerBacking::paintsChildren() const
+{
+    if (m_owningLayer->hasVisibleContent() && m_owningLayer->hasNonEmptyChildRenderers())
+        return true;
+        
+    if (hasVisibleNonCompositingDescendantLayers())
+        return true;
+
+    return false;
+}
+
+static bool isCompositedPlugin(RenderObject* renderer)
+{
+    return renderer->isEmbeddedObject() && toRenderEmbeddedObject(renderer)->allowsAcceleratedCompositing();
+}
+
+// A "simple container layer" is a RenderLayer which has no visible content to render.
+// It may have no children, or all its children may be themselves composited.
+// This is a useful optimization, because it allows us to avoid allocating backing store.
+bool RenderLayerBacking::isSimpleContainerCompositingLayer() const
+{
+    RenderObject* renderObject = renderer();
+    if (renderObject->hasMask()) // masks require special treatment
+        return false;
+
+    if (renderObject->isReplaced() && !isCompositedPlugin(renderObject))
+        return false;
+    
+    if (paintsBoxDecorations() || paintsChildren())
+        return false;
+
+    if (renderObject->isRenderRegion())
+        return false;
+
+    if (renderObject->node() && renderObject->node()->isDocumentNode()) {
+        // Look to see if the root object has a non-simple background
+        RenderObject* rootObject = renderObject->document()->documentElement() ? renderObject->document()->documentElement()->renderer() : 0;
+        if (!rootObject)
+            return false;
+        
+        RenderStyle* style = rootObject->style();
+        
+        // Reject anything that has a border, a border-radius or outline,
+        // or is not a simple background (no background, or solid color).
+        if (hasBoxDecorationsOrBackgroundImage(style))
+            return false;
+        
+        // Now look at the body's renderer.
+        HTMLElement* body = renderObject->document()->body();
+        RenderObject* bodyObject = (body && body->hasLocalName(bodyTag)) ? body->renderer() : 0;
+        if (!bodyObject)
+            return false;
+        
+        style = bodyObject->style();
+        
+        if (hasBoxDecorationsOrBackgroundImage(style))
+            return false;
+    }
+
+    return true;
+}
+
+static bool hasVisibleNonCompositingDescendant(RenderLayer* parent)
+{
+    // FIXME: We shouldn't be called with a stale z-order lists. See bug 85512.
+    parent->updateLayerListsIfNeeded();
+
+#if !ASSERT_DISABLED
+    LayerListMutationDetector mutationChecker(parent);
+#endif
+
+    if (Vector<RenderLayer*>* normalFlowList = parent->normalFlowList()) {
+        size_t listSize = normalFlowList->size();
+        for (size_t i = 0; i < listSize; ++i) {
+            RenderLayer* curLayer = normalFlowList->at(i);
+            if (!curLayer->isComposited()
+                && (curLayer->hasVisibleContent() || hasVisibleNonCompositingDescendant(curLayer)))
+                return true;
+        }
+    }
+
+    if (parent->isStackingContainer()) {
+        if (!parent->hasVisibleDescendant())
+            return false;
+
+        // Use the m_hasCompositingDescendant bit to optimize?
+        if (Vector<RenderLayer*>* negZOrderList = parent->negZOrderList()) {
+            size_t listSize = negZOrderList->size();
+            for (size_t i = 0; i < listSize; ++i) {
+                RenderLayer* curLayer = negZOrderList->at(i);
+                if (!curLayer->isComposited()
+                    && (curLayer->hasVisibleContent() || hasVisibleNonCompositingDescendant(curLayer)))
+                    return true;
+            }
+        }
+
+        if (Vector<RenderLayer*>* posZOrderList = parent->posZOrderList()) {
+            size_t listSize = posZOrderList->size();
+            for (size_t i = 0; i < listSize; ++i) {
+                RenderLayer* curLayer = posZOrderList->at(i);
+                if (!curLayer->isComposited()
+                    && (curLayer->hasVisibleContent() || hasVisibleNonCompositingDescendant(curLayer)))
+                    return true;
+            }
+        }
+    }
+
+    return false;
+}
+
+// Conservative test for having no rendered children.
+bool RenderLayerBacking::hasVisibleNonCompositingDescendantLayers() const
+{
+    return hasVisibleNonCompositingDescendant(m_owningLayer);
+}
+
+bool RenderLayerBacking::containsPaintedContent() const
+{
+    if (isSimpleContainerCompositingLayer() || paintsIntoWindow() || paintsIntoCompositedAncestor() || m_artificiallyInflatedBounds || m_owningLayer->isReflection())
+        return false;
+
+    if (isDirectlyCompositedImage())
+        return false;
+
+    // FIXME: we could optimize cases where the image, video or canvas is known to fill the border box entirely,
+    // and set background color on the layer in that case, instead of allocating backing store and painting.
+    if (renderer()->isVideo() && toRenderVideo(renderer())->shouldDisplayVideo())
+        return m_owningLayer->hasBoxDecorationsOrBackground();
+
+    if (isAcceleratedCanvas(renderer()))
+        return m_owningLayer->hasBoxDecorationsOrBackground();
+
+    return true;
+}
+
+// An image can be directly compositing if it's the sole content of the layer, and has no box decorations
+// that require painting. Direct compositing saves backing store.
+bool RenderLayerBacking::isDirectlyCompositedImage() const
+{
+    RenderObject* renderObject = renderer();
+    
+    if (!renderObject->isImage() || m_owningLayer->hasBoxDecorationsOrBackground() || renderObject->hasClip())
+        return false;
+
+    RenderImage* imageRenderer = toRenderImage(renderObject);
+    if (CachedImage* cachedImage = imageRenderer->cachedImage()) {
+        if (!cachedImage->hasImage())
+            return false;
+
+        Image* image = cachedImage->imageForRenderer(imageRenderer);
+        if (!image->isBitmapImage())
+            return false;
+
+        return m_graphicsLayer->shouldDirectlyCompositeImage(image);
+    }
+
+    return false;
+}
+
+void RenderLayerBacking::contentChanged(ContentChangeType changeType)
+{
+    if ((changeType == ImageChanged) && isDirectlyCompositedImage()) {
+        updateImageContents();
+        return;
+    }
+
+    if ((changeType == MaskImageChanged) && m_maskLayer) {
+        // The composited layer bounds relies on box->maskClipRect(), which changes
+        // when the mask image becomes available.
+        updateAfterLayout(CompositingChildrenOnly | IsUpdateRoot);
+    }
+
+    if ((changeType == CanvasChanged || changeType == CanvasPixelsChanged) && isAcceleratedCanvas(renderer())) {
+        m_graphicsLayer->setContentsNeedsDisplay();
+        return;
+    }
+}
+
+void RenderLayerBacking::updateImageContents()
+{
+    ASSERT(renderer()->isImage());
+    RenderImage* imageRenderer = toRenderImage(renderer());
+
+    CachedImage* cachedImage = imageRenderer->cachedImage();
+    if (!cachedImage)
+        return;
+
+    Image* image = cachedImage->imageForRenderer(imageRenderer);
+    if (!image)
+        return;
+
+    // We have to wait until the image is fully loaded before setting it on the layer.
+    if (!cachedImage->isLoaded())
+        return;
+
+    // This is a no-op if the layer doesn't have an inner layer for the image.
+    m_graphicsLayer->setContentsToImage(image);
+    bool isSimpleContainer = false;
+    updateDrawsContent(isSimpleContainer);
+    
+    // Image animation is "lazy", in that it automatically stops unless someone is drawing
+    // the image. So we have to kick the animation each time; this has the downside that the
+    // image will keep animating, even if its layer is not visible.
+    image->startAnimation();
+}
+
+FloatPoint3D RenderLayerBacking::computeTransformOrigin(const IntRect& borderBox) const
+{
+    RenderStyle* style = renderer()->style();
+
+    FloatPoint3D origin;
+    origin.setX(floatValueForLength(style->transformOriginX(), borderBox.width()));
+    origin.setY(floatValueForLength(style->transformOriginY(), borderBox.height()));
+    origin.setZ(style->transformOriginZ());
+
+    return origin;
+}
+
+FloatPoint RenderLayerBacking::computePerspectiveOrigin(const IntRect& borderBox) const
+{
+    RenderStyle* style = renderer()->style();
+
+    float boxWidth = borderBox.width();
+    float boxHeight = borderBox.height();
+
+    FloatPoint origin;
+    origin.setX(floatValueForLength(style->perspectiveOriginX(), boxWidth));
+    origin.setY(floatValueForLength(style->perspectiveOriginY(), boxHeight));
+
+    return origin;
+}
+
+// Return the offset from the top-left of this compositing layer at which the renderer's contents are painted.
+IntSize RenderLayerBacking::contentOffsetInCompostingLayer() const
+{
+    return IntSize(-m_compositedBounds.x(), -m_compositedBounds.y());
+}
+
+IntRect RenderLayerBacking::contentsBox() const
+{
+    if (!renderer()->isBox())
+        return IntRect();
+
+    IntRect contentsRect;
+    if (renderer()->isVideo()) {
+        RenderVideo* videoRenderer = toRenderVideo(renderer());
+        contentsRect = videoRenderer->videoBox();
+    } else
+        contentsRect = pixelSnappedIntRect(toRenderBox(renderer())->contentBoxRect());
+
+    contentsRect.move(contentOffsetInCompostingLayer());
+    return contentsRect;
+}
+
+static LayoutRect backgroundRectForBox(const RenderBox* box)
+{
+    EFillBox clip = box->style()->backgroundClip();
+    switch (clip) {
+    case BorderFillBox:
+        return box->borderBoxRect();
+    case PaddingFillBox:
+        return box->paddingBoxRect();
+    case ContentFillBox:
+        return box->contentBoxRect();
+    case TextFillBox:
+        break;
+    }
+
+    ASSERT_NOT_REACHED();
+    return LayoutRect();
+}
+
+IntRect RenderLayerBacking::backgroundBox() const
+{
+    if (!renderer()->isBox())
+        return IntRect();
+
+    IntRect pixelSnappedBackgroundBox = pixelSnappedIntRect(backgroundRectForBox(toRenderBox(renderer())));
+    pixelSnappedBackgroundBox.move(contentOffsetInCompostingLayer());
+    return pixelSnappedBackgroundBox;
+}
+
+GraphicsLayer* RenderLayerBacking::parentForSublayers() const
+{
+    if (m_scrollingContentsLayer)
+        return m_scrollingContentsLayer.get();
+
+    return m_childContainmentLayer ? m_childContainmentLayer.get() : m_graphicsLayer.get();
+}
+
+GraphicsLayer* RenderLayerBacking::childForSuperlayers() const
+{
+    if (m_ancestorClippingLayer)
+        return m_ancestorClippingLayer.get();
+
+    if (m_contentsContainmentLayer)
+        return m_contentsContainmentLayer.get();
+    
+    return m_graphicsLayer.get();
+}
+
+bool RenderLayerBacking::paintsIntoWindow() const
+{
+    if (m_owningLayer->isRootLayer()) {
+        return compositor()->rootLayerAttachment() != RenderLayerCompositor::RootLayerAttachedViaEnclosingFrame;
+    }
+    
+    return false;
+}
+
+void RenderLayerBacking::setRequiresOwnBackingStore(bool requiresOwnBacking)
+{
+    if (requiresOwnBacking == m_requiresOwnBackingStore)
+        return;
+    
+    m_requiresOwnBackingStore = requiresOwnBacking;
+
+    // This affects the answer to paintsIntoCompositedAncestor(), which in turn affects
+    // cached clip rects, so when it changes we have to clear clip rects on descendants.
+    m_owningLayer->clearClipRectsIncludingDescendants(PaintingClipRects);
+    m_owningLayer->computeRepaintRectsIncludingDescendants();
+    
+    compositor()->repaintInCompositedAncestor(m_owningLayer, compositedBounds());
+}
+
+#if ENABLE(CSS_COMPOSITING)
+void RenderLayerBacking::setBlendMode(BlendMode)
+{
+}
+#endif
+
+void RenderLayerBacking::setContentsNeedDisplay()
+{
+    ASSERT(!paintsIntoCompositedAncestor());
+    
+    if (m_graphicsLayer && m_graphicsLayer->drawsContent())
+        m_graphicsLayer->setNeedsDisplay();
+    
+    if (m_foregroundLayer && m_foregroundLayer->drawsContent())
+        m_foregroundLayer->setNeedsDisplay();
+
+    if (m_backgroundLayer && m_backgroundLayer->drawsContent())
+        m_backgroundLayer->setNeedsDisplay();
+
+    if (m_maskLayer && m_maskLayer->drawsContent())
+        m_maskLayer->setNeedsDisplay();
+
+    if (m_scrollingContentsLayer && m_scrollingContentsLayer->drawsContent())
+        m_scrollingContentsLayer->setNeedsDisplay();
+}
+
+// r is in the coordinate space of the layer's render object
+void RenderLayerBacking::setContentsNeedDisplayInRect(const IntRect& r)
+{
+    ASSERT(!paintsIntoCompositedAncestor());
+
+    if (m_graphicsLayer && m_graphicsLayer->drawsContent()) {
+        IntRect layerDirtyRect = r;
+        layerDirtyRect.move(-m_graphicsLayer->offsetFromRenderer());
+        m_graphicsLayer->setNeedsDisplayInRect(layerDirtyRect);
+    }
+
+    if (m_foregroundLayer && m_foregroundLayer->drawsContent()) {
+        IntRect layerDirtyRect = r;
+        layerDirtyRect.move(-m_foregroundLayer->offsetFromRenderer());
+        m_foregroundLayer->setNeedsDisplayInRect(layerDirtyRect);
+    }
+
+    // FIXME: need to split out repaints for the background.
+    if (m_backgroundLayer && m_backgroundLayer->drawsContent()) {
+        IntRect layerDirtyRect = r;
+        layerDirtyRect.move(-m_backgroundLayer->offsetFromRenderer());
+        m_backgroundLayer->setNeedsDisplayInRect(layerDirtyRect);
+    }
+
+    if (m_maskLayer && m_maskLayer->drawsContent()) {
+        IntRect layerDirtyRect = r;
+        layerDirtyRect.move(-m_maskLayer->offsetFromRenderer());
+        m_maskLayer->setNeedsDisplayInRect(layerDirtyRect);
+    }
+
+    if (m_scrollingContentsLayer && m_scrollingContentsLayer->drawsContent()) {
+        IntRect layerDirtyRect = r;
+        layerDirtyRect.move(-m_scrollingContentsLayer->offsetFromRenderer());
+        m_scrollingContentsLayer->setNeedsDisplayInRect(layerDirtyRect);
+    }
+}
+
+void RenderLayerBacking::paintIntoLayer(const GraphicsLayer* graphicsLayer, GraphicsContext* context,
+                    const IntRect& paintDirtyRect, // In the coords of rootLayer.
+                    PaintBehavior paintBehavior, GraphicsLayerPaintingPhase paintingPhase)
+{
+    if (paintsIntoWindow() || paintsIntoCompositedAncestor()) {
+        ASSERT_NOT_REACHED();
+        return;
+    }
+
+    FontCachePurgePreventer fontCachePurgePreventer;
+    
+    RenderLayer::PaintLayerFlags paintFlags = 0;
+    if (paintingPhase & GraphicsLayerPaintBackground)
+        paintFlags |= RenderLayer::PaintLayerPaintingCompositingBackgroundPhase;
+    if (paintingPhase & GraphicsLayerPaintForeground)
+        paintFlags |= RenderLayer::PaintLayerPaintingCompositingForegroundPhase;
+    if (paintingPhase & GraphicsLayerPaintMask)
+        paintFlags |= RenderLayer::PaintLayerPaintingCompositingMaskPhase;
+    if (paintingPhase & GraphicsLayerPaintOverflowContents)
+        paintFlags |= RenderLayer::PaintLayerPaintingOverflowContents;
+    if (paintingPhase & GraphicsLayerPaintCompositedScroll)
+        paintFlags |= RenderLayer::PaintLayerPaintingCompositingScrollingPhase;
+
+    if (graphicsLayer == m_backgroundLayer)
+        paintFlags |= (RenderLayer::PaintLayerPaintingRootBackgroundOnly | RenderLayer::PaintLayerPaintingCompositingForegroundPhase); // Need PaintLayerPaintingCompositingForegroundPhase to walk child layers.
+    else if (m_backgroundLayer)
+        paintFlags |= RenderLayer::PaintLayerPaintingSkipRootBackground;
+    
+    // FIXME: GraphicsLayers need a way to split for RenderRegions.
+    RenderLayer::LayerPaintingInfo paintingInfo(m_owningLayer, paintDirtyRect, paintBehavior, LayoutSize());
+    m_owningLayer->paintLayerContents(context, paintingInfo, paintFlags);
+
+    if (m_owningLayer->containsDirtyOverlayScrollbars())
+        m_owningLayer->paintLayerContents(context, paintingInfo, paintFlags | RenderLayer::PaintLayerPaintingOverlayScrollbars);
+
+    ASSERT(!m_owningLayer->m_usedTransparency);
+}
+
+static void paintScrollbar(Scrollbar* scrollbar, GraphicsContext& context, const IntRect& clip)
+{
+    if (!scrollbar)
+        return;
+
+    context.save();
+    const IntRect& scrollbarRect = scrollbar->frameRect();
+    context.translate(-scrollbarRect.x(), -scrollbarRect.y());
+    IntRect transformedClip = clip;
+    transformedClip.moveBy(scrollbarRect.location());
+    scrollbar->paint(&context, transformedClip);
+    context.restore();
+}
+
+// Up-call from compositing layer drawing callback.
+void RenderLayerBacking::paintContents(const GraphicsLayer* graphicsLayer, GraphicsContext& context, GraphicsLayerPaintingPhase paintingPhase, const IntRect& clip)
+{
+#ifndef NDEBUG
+    if (Page* page = renderer()->frame()->page())
+        page->setIsPainting(true);
+#endif
+
+    if (graphicsLayer == m_graphicsLayer.get()
+        || graphicsLayer == m_foregroundLayer.get()
+        || graphicsLayer == m_backgroundLayer.get()
+        || graphicsLayer == m_maskLayer.get()
+        || graphicsLayer == m_scrollingContentsLayer.get()) {
+        InspectorInstrumentation::willPaint(renderer());
+
+        // The dirtyRect is in the coords of the painting root.
+        IntRect dirtyRect = clip;
+        if (!(paintingPhase & GraphicsLayerPaintOverflowContents))
+            dirtyRect.intersect(compositedBounds());
+
+        // We have to use the same root as for hit testing, because both methods can compute and cache clipRects.
+        paintIntoLayer(graphicsLayer, &context, dirtyRect, PaintBehaviorNormal, paintingPhase);
+
+        InspectorInstrumentation::didPaint(renderer(), &context, clip);
+    } else if (graphicsLayer == layerForHorizontalScrollbar()) {
+        paintScrollbar(m_owningLayer->horizontalScrollbar(), context, clip);
+    } else if (graphicsLayer == layerForVerticalScrollbar()) {
+        paintScrollbar(m_owningLayer->verticalScrollbar(), context, clip);
+    } else if (graphicsLayer == layerForScrollCorner()) {
+        const IntRect& scrollCornerAndResizer = m_owningLayer->scrollCornerAndResizerRect();
+        context.save();
+        context.translate(-scrollCornerAndResizer.x(), -scrollCornerAndResizer.y());
+        IntRect transformedClip = clip;
+        transformedClip.moveBy(scrollCornerAndResizer.location());
+        m_owningLayer->paintScrollCorner(&context, IntPoint(), transformedClip);
+        m_owningLayer->paintResizer(&context, IntPoint(), transformedClip);
+        context.restore();
+    }
+#ifndef NDEBUG
+    if (Page* page = renderer()->frame()->page())
+        page->setIsPainting(false);
+#endif
+}
+
+float RenderLayerBacking::pageScaleFactor() const
+{
+    return compositor()->pageScaleFactor();
+}
+
+float RenderLayerBacking::deviceScaleFactor() const
+{
+    return compositor()->deviceScaleFactor();
+}
+
+void RenderLayerBacking::didCommitChangesForLayer(const GraphicsLayer* layer) const
+{
+}
+
+bool RenderLayerBacking::getCurrentTransform(const GraphicsLayer* graphicsLayer, TransformationMatrix& transform) const
+{
+    GraphicsLayer* transformedLayer = m_contentsContainmentLayer.get() ? m_contentsContainmentLayer.get() : m_graphicsLayer.get();
+    if (graphicsLayer != transformedLayer)
+        return false;
+
+    if (m_owningLayer->hasTransform()) {
+        transform = m_owningLayer->currentTransform(RenderStyle::ExcludeTransformOrigin);
+        return true;
+    }
+    return false;
+}
+
+bool RenderLayerBacking::isTrackingRepaints() const
+{
+    GraphicsLayerClient* client = compositor();
+    return client ? client->isTrackingRepaints() : false;
+}
+
+#ifndef NDEBUG
+void RenderLayerBacking::verifyNotPainting()
+{
+    ASSERT(!renderer()->frame()->page() || !renderer()->frame()->page()->isPainting());
+}
+#endif
+
+bool RenderLayerBacking::startAnimation(double timeOffset, const CSSAnimationData* anim, const KeyframeList& keyframes)
+{
+    bool hasOpacity = keyframes.containsProperty(CSSPropertyOpacity);
+    bool hasTransform = renderer()->isBox() && keyframes.containsProperty(CSSPropertyWebkitTransform);
+    bool hasFilter = keyframes.containsProperty(CSSPropertyWebkitFilter);
+
+    if (!hasOpacity && !hasTransform && !hasFilter)
+        return false;
+    
+    KeyframeValueList transformVector(AnimatedPropertyWebkitTransform);
+    KeyframeValueList opacityVector(AnimatedPropertyOpacity);
+    KeyframeValueList filterVector(AnimatedPropertyWebkitFilter);
+
+    size_t numKeyframes = keyframes.size();
+    for (size_t i = 0; i < numKeyframes; ++i) {
+        const KeyframeValue& currentKeyframe = keyframes[i];
+        const RenderStyle* keyframeStyle = currentKeyframe.style();
+        float key = currentKeyframe.key();
+
+        if (!keyframeStyle)
+            continue;
+            
+        // Get timing function.
+        RefPtr<TimingFunction> tf = keyframeStyle->hasAnimations() ? (*keyframeStyle->animations()).animation(0)->timingFunction() : 0;
+        
+        bool isFirstOrLastKeyframe = key == 0 || key == 1;
+        if ((hasTransform && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyWebkitTransform))
+            transformVector.insert(new TransformAnimationValue(key, &(keyframeStyle->transform()), tf));
+        
+        if ((hasOpacity && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyOpacity))
+            opacityVector.insert(new FloatAnimationValue(key, keyframeStyle->opacity(), tf));
+
+        if ((hasFilter && isFirstOrLastKeyframe) || currentKeyframe.containsProperty(CSSPropertyWebkitFilter))
+            filterVector.insert(new FilterAnimationValue(key, &(keyframeStyle->filter()), tf));
+    }
+
+    bool didAnimateTransform = false;
+    bool didAnimateOpacity = false;
+    bool didAnimateFilter = false;
+    
+    if (hasTransform && m_graphicsLayer->addAnimation(transformVector, toRenderBox(renderer())->pixelSnappedBorderBoxRect().size(), anim, keyframes.animationName(), timeOffset))
+        didAnimateTransform = true;
+
+    if (hasOpacity && m_graphicsLayer->addAnimation(opacityVector, IntSize(), anim, keyframes.animationName(), timeOffset))
+        didAnimateOpacity = true;
+
+    if (hasFilter && m_graphicsLayer->addAnimation(filterVector, IntSize(), anim, keyframes.animationName(), timeOffset))
+        didAnimateFilter = true;
+
+    return didAnimateTransform || didAnimateOpacity || didAnimateFilter;
+}
+
+void RenderLayerBacking::animationPaused(double timeOffset, const String& animationName)
+{
+    m_graphicsLayer->pauseAnimation(animationName, timeOffset);
+}
+
+void RenderLayerBacking::animationFinished(const String& animationName)
+{
+    m_graphicsLayer->removeAnimation(animationName);
+}
+
+bool RenderLayerBacking::startTransition(double timeOffset, CSSPropertyID property, const RenderStyle* fromStyle, const RenderStyle* toStyle)
+{
+    bool didAnimateOpacity = false;
+    bool didAnimateTransform = false;
+    bool didAnimateFilter = false;
+
+    ASSERT(property != CSSPropertyInvalid);
+
+    if (property == CSSPropertyOpacity) {
+        const CSSAnimationData* opacityAnim = toStyle->transitionForProperty(CSSPropertyOpacity);
+        if (opacityAnim && !opacityAnim->isEmptyOrZeroDuration()) {
+            KeyframeValueList opacityVector(AnimatedPropertyOpacity);
+            opacityVector.insert(new FloatAnimationValue(0, compositingOpacity(fromStyle->opacity())));
+            opacityVector.insert(new FloatAnimationValue(1, compositingOpacity(toStyle->opacity())));
+            // The boxSize param is only used for transform animations (which can only run on RenderBoxes), so we pass an empty size here.
+            if (m_graphicsLayer->addAnimation(opacityVector, IntSize(), opacityAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyOpacity), timeOffset)) {
+                // To ensure that the correct opacity is visible when the animation ends, also set the final opacity.
+                updateOpacity(toStyle);
+                didAnimateOpacity = true;
+            }
+        }
+    }
+
+    if (property == CSSPropertyWebkitTransform && m_owningLayer->hasTransform()) {
+        const CSSAnimationData* transformAnim = toStyle->transitionForProperty(CSSPropertyWebkitTransform);
+        if (transformAnim && !transformAnim->isEmptyOrZeroDuration()) {
+            KeyframeValueList transformVector(AnimatedPropertyWebkitTransform);
+            transformVector.insert(new TransformAnimationValue(0, &fromStyle->transform()));
+            transformVector.insert(new TransformAnimationValue(1, &toStyle->transform()));
+            if (m_graphicsLayer->addAnimation(transformVector, toRenderBox(renderer())->pixelSnappedBorderBoxRect().size(), transformAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyWebkitTransform), timeOffset)) {
+                // To ensure that the correct transform is visible when the animation ends, also set the final transform.
+                updateTransform(toStyle);
+                didAnimateTransform = true;
+            }
+        }
+    }
+
+    if (property == CSSPropertyWebkitFilter && m_owningLayer->hasFilter()) {
+        const CSSAnimationData* filterAnim = toStyle->transitionForProperty(CSSPropertyWebkitFilter);
+        if (filterAnim && !filterAnim->isEmptyOrZeroDuration()) {
+            KeyframeValueList filterVector(AnimatedPropertyWebkitFilter);
+            filterVector.insert(new FilterAnimationValue(0, &fromStyle->filter()));
+            filterVector.insert(new FilterAnimationValue(1, &toStyle->filter()));
+            if (m_graphicsLayer->addAnimation(filterVector, IntSize(), filterAnim, GraphicsLayer::animationNameForTransition(AnimatedPropertyWebkitFilter), timeOffset)) {
+                // To ensure that the correct filter is visible when the animation ends, also set the final filter.
+                updateFilters(toStyle);
+                didAnimateFilter = true;
+            }
+        }
+    }
+
+    return didAnimateOpacity || didAnimateTransform || didAnimateFilter;
+}
+
+void RenderLayerBacking::transitionPaused(double timeOffset, CSSPropertyID property)
+{
+    AnimatedPropertyID animatedProperty = cssToGraphicsLayerProperty(property);
+    if (animatedProperty != AnimatedPropertyInvalid)
+        m_graphicsLayer->pauseAnimation(GraphicsLayer::animationNameForTransition(animatedProperty), timeOffset);
+}
+
+void RenderLayerBacking::transitionFinished(CSSPropertyID property)
+{
+    AnimatedPropertyID animatedProperty = cssToGraphicsLayerProperty(property);
+    if (animatedProperty != AnimatedPropertyInvalid)
+        m_graphicsLayer->removeAnimation(GraphicsLayer::animationNameForTransition(animatedProperty));
+}
+
+void RenderLayerBacking::notifyAnimationStarted(const GraphicsLayer*, double time)
+{
+    renderer()->animation()->notifyAnimationStarted(renderer(), time);
+}
+
+// This is used for the 'freeze' API, for testing only.
+void RenderLayerBacking::suspendAnimations(double time)
+{
+    m_graphicsLayer->suspendAnimations(time);
+}
+
+void RenderLayerBacking::resumeAnimations()
+{
+    m_graphicsLayer->resumeAnimations();
+}
+
+IntRect RenderLayerBacking::compositedBounds() const
+{
+    return m_compositedBounds;
+}
+
+void RenderLayerBacking::setCompositedBounds(const IntRect& bounds)
+{
+    m_compositedBounds = bounds;
+}
+
+CSSPropertyID RenderLayerBacking::graphicsLayerToCSSProperty(AnimatedPropertyID property)
+{
+    CSSPropertyID cssProperty = CSSPropertyInvalid;
+    switch (property) {
+        case AnimatedPropertyWebkitTransform:
+            cssProperty = CSSPropertyWebkitTransform;
+            break;
+        case AnimatedPropertyOpacity:
+            cssProperty = CSSPropertyOpacity;
+            break;
+        case AnimatedPropertyBackgroundColor:
+            cssProperty = CSSPropertyBackgroundColor;
+            break;
+        case AnimatedPropertyWebkitFilter:
+            cssProperty = CSSPropertyWebkitFilter;
+            break;
+        case AnimatedPropertyInvalid:
+            ASSERT_NOT_REACHED();
+    }
+    return cssProperty;
+}
+
+AnimatedPropertyID RenderLayerBacking::cssToGraphicsLayerProperty(CSSPropertyID cssProperty)
+{
+    switch (cssProperty) {
+        case CSSPropertyWebkitTransform:
+            return AnimatedPropertyWebkitTransform;
+        case CSSPropertyOpacity:
+            return AnimatedPropertyOpacity;
+        case CSSPropertyBackgroundColor:
+            return AnimatedPropertyBackgroundColor;
+        case CSSPropertyWebkitFilter:
+            return AnimatedPropertyWebkitFilter;
+        default:
+            // It's fine if we see other css properties here; they are just not accelerated.
+            break;
+    }
+    return AnimatedPropertyInvalid;
+}
+
+CompositingLayerType RenderLayerBacking::compositingLayerType() const
+{
+    if (m_graphicsLayer->hasContentsLayer())
+        return MediaCompositingLayer;
+
+    if (m_graphicsLayer->drawsContent())
+        return NormalCompositingLayer;
+    
+    return ContainerCompositingLayer;
+}
+
+double RenderLayerBacking::backingStoreMemoryEstimate() const
+{
+    double backingMemory;
+    
+    // m_ancestorClippingLayer, m_contentsContainmentLayer and m_childContainmentLayer are just used for masking or containment, so have no backing.
+    backingMemory = m_graphicsLayer->backingStoreMemoryEstimate();
+    if (m_foregroundLayer)
+        backingMemory += m_foregroundLayer->backingStoreMemoryEstimate();
+    if (m_backgroundLayer)
+        backingMemory += m_backgroundLayer->backingStoreMemoryEstimate();
+    if (m_maskLayer)
+        backingMemory += m_maskLayer->backingStoreMemoryEstimate();
+
+    if (m_scrollingContentsLayer)
+        backingMemory += m_scrollingContentsLayer->backingStoreMemoryEstimate();
+
+    if (m_layerForHorizontalScrollbar)
+        backingMemory += m_layerForHorizontalScrollbar->backingStoreMemoryEstimate();
+
+    if (m_layerForVerticalScrollbar)
+        backingMemory += m_layerForVerticalScrollbar->backingStoreMemoryEstimate();
+
+    if (m_layerForScrollCorner)
+        backingMemory += m_layerForScrollCorner->backingStoreMemoryEstimate();
+    
+    return backingMemory;
+}
+
+void RenderLayerBacking::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, PlatformMemoryTypes::Rendering);
+    info.addWeakPointer(m_owningLayer);
+    info.addMember(m_ancestorClippingLayer, "ancestorClippingLayer");
+    info.addMember(m_contentsContainmentLayer, "contentsContainmentLayer");
+    info.addMember(m_graphicsLayer, "graphicsLayer");
+    info.addMember(m_foregroundLayer, "foregroundLayer");
+    info.addMember(m_backgroundLayer, "backgroundLayer");
+    info.addMember(m_childContainmentLayer, "childContainmentLayer");
+    info.addMember(m_maskLayer, "maskLayer");
+    info.addMember(m_layerForHorizontalScrollbar, "layerForHorizontalScrollbar");
+    info.addMember(m_layerForVerticalScrollbar, "layerForVerticalScrollbar");
+    info.addMember(m_layerForScrollCorner, "layerForScrollCorner");
+    info.addMember(m_scrollingLayer, "scrollingLayer");
+    info.addMember(m_scrollingContentsLayer, "scrollingContentsLayer");
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderLayerBacking.h b/Source/core/rendering/RenderLayerBacking.h
new file mode 100644
index 0000000..240380b
--- /dev/null
+++ b/Source/core/rendering/RenderLayerBacking.h
@@ -0,0 +1,282 @@
+/*
+ * Copyright (C) 2009, 2010, 2011 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 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 RenderLayerBacking_h
+#define RenderLayerBacking_h
+
+#include "core/platform/graphics/FloatPoint.h"
+#include "core/platform/graphics/FloatPoint3D.h"
+#include "core/platform/graphics/GraphicsLayer.h"
+#include "core/platform/graphics/GraphicsLayerClient.h"
+#include "core/platform/graphics/transforms/TransformationMatrix.h"
+#include "core/rendering/RenderLayer.h"
+
+namespace WebCore {
+
+class KeyframeList;
+class RenderLayerCompositor;
+
+enum CompositingLayerType {
+    NormalCompositingLayer, // non-tiled layer with backing store
+    MediaCompositingLayer, // layer that contains an image, video, webGL or plugin
+    ContainerCompositingLayer // layer with no backing store
+};
+
+// RenderLayerBacking controls the compositing behavior for a single RenderLayer.
+// It holds the various GraphicsLayers, and makes decisions about intra-layer rendering
+// optimizations.
+// 
+// There is one RenderLayerBacking for each RenderLayer that is composited.
+
+class RenderLayerBacking : public GraphicsLayerClient {
+    WTF_MAKE_NONCOPYABLE(RenderLayerBacking); WTF_MAKE_FAST_ALLOCATED;
+public:
+    explicit RenderLayerBacking(RenderLayer*);
+    ~RenderLayerBacking();
+
+    RenderLayer* owningLayer() const { return m_owningLayer; }
+
+    enum UpdateAfterLayoutFlag {
+        CompositingChildrenOnly = 1 << 0,
+        NeedsFullRepaint = 1 << 1,
+        IsUpdateRoot = 1 << 2
+    };
+    typedef unsigned UpdateAfterLayoutFlags;
+    void updateAfterLayout(UpdateAfterLayoutFlags);
+    
+    // Returns true if layer configuration changed.
+    bool updateGraphicsLayerConfiguration();
+    // Update graphics layer position and bounds.
+    void updateGraphicsLayerGeometry(); // make private
+    // Update contents and clipping structure.
+    void updateDrawsContent();
+    
+    GraphicsLayer* graphicsLayer() const { return m_graphicsLayer.get(); }
+
+    // Layer to clip children
+    bool hasClippingLayer() const { return m_childContainmentLayer; }
+    GraphicsLayer* clippingLayer() const { return m_childContainmentLayer.get(); }
+
+    // Layer to get clipped by ancestor
+    bool hasAncestorClippingLayer() const { return m_ancestorClippingLayer != 0; }
+    GraphicsLayer* ancestorClippingLayer() const { return m_ancestorClippingLayer.get(); }
+
+    GraphicsLayer* contentsContainmentLayer() const { return m_contentsContainmentLayer.get(); }
+
+    bool hasContentsLayer() const { return m_foregroundLayer != 0; }
+    GraphicsLayer* foregroundLayer() const { return m_foregroundLayer.get(); }
+
+    GraphicsLayer* backgroundLayer() const { return m_backgroundLayer.get(); }
+    bool backgroundLayerPaintsFixedRootBackground() const { return m_backgroundLayerPaintsFixedRootBackground; }
+    
+    bool hasScrollingLayer() const { return m_scrollingLayer; }
+    GraphicsLayer* scrollingLayer() const { return m_scrollingLayer.get(); }
+    GraphicsLayer* scrollingContentsLayer() const { return m_scrollingContentsLayer.get(); }
+
+    bool hasMaskLayer() const { return m_maskLayer != 0; }
+
+    GraphicsLayer* parentForSublayers() const;
+    GraphicsLayer* childForSuperlayers() const;
+
+    // RenderLayers with backing normally short-circuit paintLayer() because
+    // their content is rendered via callbacks from GraphicsLayer. However, the document
+    // layer is special, because it has a GraphicsLayer to act as a container for the GraphicsLayers
+    // for descendants, but its contents usually render into the window (in which case this returns true).
+    // This returns false for other layers, and when the document layer actually needs to paint into its backing store
+    // for some reason.
+    bool paintsIntoWindow() const;
+    
+    // Returns true for a composited layer that has no backing store of its own, so
+    // paints into some ancestor layer.
+    bool paintsIntoCompositedAncestor() const { return !m_requiresOwnBackingStore; }
+
+    void setRequiresOwnBackingStore(bool);
+
+    void setContentsNeedDisplay();
+    // r is in the coordinate space of the layer's render object
+    void setContentsNeedDisplayInRect(const IntRect&);
+
+    // Notification from the renderer that its content changed.
+    void contentChanged(ContentChangeType);
+
+    // Interface to start, finish, suspend and resume animations and transitions
+    bool startTransition(double, CSSPropertyID, const RenderStyle* fromStyle, const RenderStyle* toStyle);
+    void transitionPaused(double timeOffset, CSSPropertyID);
+    void transitionFinished(CSSPropertyID);
+
+    bool startAnimation(double timeOffset, const CSSAnimationData* anim, const KeyframeList& keyframes);
+    void animationPaused(double timeOffset, const String& name);
+    void animationFinished(const String& name);
+
+    void suspendAnimations(double time = 0);
+    void resumeAnimations();
+
+    IntRect compositedBounds() const;
+    void setCompositedBounds(const IntRect&);
+    void updateCompositedBounds();
+    
+    void updateAfterWidgetResize();
+    void positionOverflowControlsLayers(const IntSize& offsetFromRoot);
+    bool hasUnpositionedOverflowControlsLayers() const;
+
+    void updateDebugIndicators(bool showBorder, bool showRepaintCounter);
+
+    // GraphicsLayerClient interface
+    virtual void notifyAnimationStarted(const GraphicsLayer*, double startTime) OVERRIDE;
+
+    virtual void paintContents(const GraphicsLayer*, GraphicsContext&, GraphicsLayerPaintingPhase, const IntRect& clip) OVERRIDE;
+
+    virtual float deviceScaleFactor() const OVERRIDE;
+    virtual float pageScaleFactor() const OVERRIDE;
+    virtual void didCommitChangesForLayer(const GraphicsLayer*) const OVERRIDE;
+    virtual bool getCurrentTransform(const GraphicsLayer*, TransformationMatrix&) const OVERRIDE;
+
+    virtual bool isTrackingRepaints() const OVERRIDE;
+
+#ifndef NDEBUG
+    virtual void verifyNotPainting();
+#endif
+
+    IntRect contentsBox() const;
+    IntRect backgroundBox() const;
+    
+    // For informative purposes only.
+    CompositingLayerType compositingLayerType() const;
+    
+    GraphicsLayer* layerForHorizontalScrollbar() const { return m_layerForHorizontalScrollbar.get(); }
+    GraphicsLayer* layerForVerticalScrollbar() const { return m_layerForVerticalScrollbar.get(); }
+    GraphicsLayer* layerForScrollCorner() const { return m_layerForScrollCorner.get(); }
+
+    void updateFilters(const RenderStyle*);
+    bool canCompositeFilters() const { return m_canCompositeFilters; }
+
+    // Return an estimate of the backing store area (in pixels) allocated by this object's GraphicsLayers.
+    double backingStoreMemoryEstimate() const;
+
+#if ENABLE(CSS_COMPOSITING)
+    void setBlendMode(BlendMode);
+#endif
+    void reportMemoryUsage(MemoryObjectInfo*) const;
+
+private:
+    void createPrimaryGraphicsLayer();
+    void destroyGraphicsLayers();
+    
+    PassOwnPtr<GraphicsLayer> createGraphicsLayer(const String&);
+
+    RenderLayerModelObject* renderer() const { return m_owningLayer->renderer(); }
+    RenderLayerCompositor* compositor() const { return m_owningLayer->compositor(); }
+
+    void updateInternalHierarchy();
+    bool updateClippingLayers(bool needsAncestorClip, bool needsDescendantClip);
+    bool updateOverflowControlsLayers(bool needsHorizontalScrollbarLayer, bool needsVerticalScrollbarLayer, bool needsScrollCornerLayer);
+    bool updateForegroundLayer(bool needsForegroundLayer);
+    bool updateBackgroundLayer(bool needsBackgroundLayer);
+    bool updateMaskLayer(bool needsMaskLayer);
+    bool requiresHorizontalScrollbarLayer() const { return m_owningLayer->horizontalScrollbar(); }
+    bool requiresVerticalScrollbarLayer() const { return m_owningLayer->verticalScrollbar(); }
+    bool requiresScrollCornerLayer() const { return !m_owningLayer->scrollCornerAndResizerRect().isEmpty(); }
+    bool updateScrollingLayers(bool scrollingLayers);
+    void updateDrawsContent(bool isSimpleContainer);
+    void registerScrollingLayers();
+    
+    void updateRootLayerConfiguration();
+
+    void setBackgroundLayerPaintsFixedRootBackground(bool);
+
+    GraphicsLayerPaintingPhase paintingPhaseForPrimaryLayer() const;
+    
+    IntSize contentOffsetInCompostingLayer() const;
+    // Result is transform origin in pixels.
+    FloatPoint3D computeTransformOrigin(const IntRect& borderBox) const;
+    // Result is perspective origin in pixels.
+    FloatPoint computePerspectiveOrigin(const IntRect& borderBox) const;
+
+    void updateOpacity(const RenderStyle*);
+    void updateTransform(const RenderStyle*);
+#if ENABLE(CSS_COMPOSITING)
+    void updateLayerBlendMode(const RenderStyle*);
+#endif
+    // Return the opacity value that this layer should use for compositing.
+    float compositingOpacity(float rendererOpacity) const;
+    
+    bool isMainFrameRenderViewLayer() const;
+    
+    bool paintsBoxDecorations() const;
+    bool paintsChildren() const;
+
+    // Returns true if this compositing layer has no visible content.
+    bool isSimpleContainerCompositingLayer() const;
+    // Returns true if this layer has content that needs to be rendered by painting into the backing store.
+    bool containsPaintedContent() const;
+    // Returns true if the RenderLayer just contains an image that we can composite directly.
+    bool isDirectlyCompositedImage() const;
+    void updateImageContents();
+
+    Color rendererBackgroundColor() const;
+    void updateBackgroundColor(bool isSimpleContainer);
+    void updateContentsRect(bool isSimpleContainer);
+
+    bool hasVisibleNonCompositingDescendantLayers() const;
+
+    bool shouldClipCompositedBounds() const;
+
+    void paintIntoLayer(const GraphicsLayer*, GraphicsContext*, const IntRect& paintDirtyRect, PaintBehavior, GraphicsLayerPaintingPhase);
+
+    static CSSPropertyID graphicsLayerToCSSProperty(AnimatedPropertyID);
+    static AnimatedPropertyID cssToGraphicsLayerProperty(CSSPropertyID);
+
+    RenderLayer* m_owningLayer;
+
+    OwnPtr<GraphicsLayer> m_ancestorClippingLayer; // Only used if we are clipped by an ancestor which is not a stacking context.
+    OwnPtr<GraphicsLayer> m_contentsContainmentLayer; // Only used if we have a background layer; takes the transform.
+    OwnPtr<GraphicsLayer> m_graphicsLayer;
+    OwnPtr<GraphicsLayer> m_foregroundLayer; // Only used in cases where we need to draw the foreground separately.
+    OwnPtr<GraphicsLayer> m_backgroundLayer; // Only used in cases where we need to draw the background separately.
+    OwnPtr<GraphicsLayer> m_childContainmentLayer; // Only used if we have clipping on a stacking context with compositing children, or if the layer has a tile cache.
+    OwnPtr<GraphicsLayer> m_maskLayer; // Only used if we have a mask.
+
+    OwnPtr<GraphicsLayer> m_layerForHorizontalScrollbar;
+    OwnPtr<GraphicsLayer> m_layerForVerticalScrollbar;
+    OwnPtr<GraphicsLayer> m_layerForScrollCorner;
+
+    OwnPtr<GraphicsLayer> m_scrollingLayer; // Only used if the layer is using composited scrolling.
+    OwnPtr<GraphicsLayer> m_scrollingContentsLayer; // Only used if the layer is using composited scrolling.
+
+    uint64_t m_scrollLayerID;
+
+    IntRect m_compositedBounds;
+
+    bool m_artificiallyInflatedBounds; // bounds had to be made non-zero to make transform-origin work
+    bool m_boundsConstrainedByClipping;
+    bool m_isMainFrameRenderViewLayer;
+    bool m_requiresOwnBackingStore;
+    bool m_canCompositeFilters;
+    bool m_backgroundLayerPaintsFixedRootBackground;
+};
+
+} // namespace WebCore
+
+#endif // RenderLayerBacking_h
diff --git a/Source/core/rendering/RenderLayerCompositor.cpp b/Source/core/rendering/RenderLayerCompositor.cpp
new file mode 100644
index 0000000..6bf4e71
--- /dev/null
+++ b/Source/core/rendering/RenderLayerCompositor.cpp
@@ -0,0 +1,2794 @@
+/*
+ * Copyright (C) 2009, 2010 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 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 "core/rendering/RenderLayerCompositor.h"
+
+#include "CSSPropertyNames.h"
+#include "HTMLNames.h"
+#include "core/dom/NodeList.h"
+#include "core/dom/WebCoreMemoryInstrumentation.h"
+#include "core/html/HTMLCanvasElement.h"
+#include "core/html/HTMLIFrameElement.h"
+#include "core/html/canvas/CanvasRenderingContext.h"
+#include "core/inspector/InspectorInstrumentation.h"
+#include "core/page/Chrome.h"
+#include "core/page/ChromeClient.h"
+#include "core/page/Frame.h"
+#include "core/page/FrameView.h"
+#include "core/page/Page.h"
+#include "core/page/Settings.h"
+#include "core/page/animation/AnimationController.h"
+#include "core/page/scrolling/ScrollingConstraints.h"
+#include "core/page/scrolling/ScrollingCoordinator.h"
+#include "core/platform/HistogramSupport.h"
+#include "core/platform/Logging.h"
+#include "core/platform/ScrollbarTheme.h"
+#include "core/platform/chromium/TraceEvent.h"
+#include "core/platform/graphics/GraphicsLayer.h"
+#include "core/platform/graphics/transforms/TransformState.h"
+#include "core/rendering/HitTestResult.h"
+#include "core/rendering/RenderApplet.h"
+#include "core/rendering/RenderEmbeddedObject.h"
+#include "core/rendering/RenderFullScreen.h"
+#include "core/rendering/RenderGeometryMap.h"
+#include "core/rendering/RenderIFrame.h"
+#include "core/rendering/RenderLayerBacking.h"
+#include "core/rendering/RenderReplica.h"
+#include "core/rendering/RenderVideo.h"
+#include "core/rendering/RenderView.h"
+#include <wtf/MemoryInstrumentationHashMap.h>
+#include <wtf/TemporaryChange.h>
+
+#if !LOG_DISABLED
+#include <wtf/CurrentTime.h>
+#endif
+
+#ifndef NDEBUG
+#include "core/rendering/RenderTreeAsText.h"
+#endif
+
+#define WTF_USE_COMPOSITING_FOR_SMALL_CANVASES 1
+
+static const int canvasAreaThresholdRequiringCompositing = 50 * 100;
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+class OverlapMapContainer {
+public:
+    void add(const IntRect& bounds)
+    {
+        m_layerRects.append(bounds);
+        m_boundingBox.unite(bounds);
+    }
+
+    bool overlapsLayers(const IntRect& bounds) const
+    {
+        // Checking with the bounding box will quickly reject cases when
+        // layers are created for lists of items going in one direction and
+        // never overlap with each other.
+        if (!bounds.intersects(m_boundingBox))
+            return false;
+        for (unsigned i = 0; i < m_layerRects.size(); i++) {
+            if (m_layerRects[i].intersects(bounds))
+                return true;
+        }
+        return false;
+    }
+
+    void unite(const OverlapMapContainer& otherContainer)
+    {
+        m_layerRects.append(otherContainer.m_layerRects);
+        m_boundingBox.unite(otherContainer.m_boundingBox);
+    }
+private:
+    Vector<IntRect> m_layerRects;
+    IntRect m_boundingBox;
+};
+
+class RenderLayerCompositor::OverlapMap {
+    WTF_MAKE_NONCOPYABLE(OverlapMap);
+public:
+    OverlapMap()
+        : m_geometryMap(UseTransforms)
+    {
+        // Begin assuming the root layer will be composited so that there is
+        // something on the stack. The root layer should also never get an
+        // popCompositingContainer call.
+        pushCompositingContainer();
+    }
+
+    void add(const RenderLayer* layer, const IntRect& bounds)
+    {
+        // Layers do not contribute to overlap immediately--instead, they will
+        // contribute to overlap as soon as their composited ancestor has been
+        // recursively processed and popped off the stack.
+        ASSERT(m_overlapStack.size() >= 2);
+        m_overlapStack[m_overlapStack.size() - 2].add(bounds);
+        m_layers.add(layer);
+    }
+
+    bool contains(const RenderLayer* layer)
+    {
+        return m_layers.contains(layer);
+    }
+
+    bool overlapsLayers(const IntRect& bounds) const
+    {
+        return m_overlapStack.last().overlapsLayers(bounds);
+    }
+
+    bool isEmpty()
+    {
+        return m_layers.isEmpty();
+    }
+
+    void pushCompositingContainer()
+    {
+        m_overlapStack.append(OverlapMapContainer());
+    }
+
+    void popCompositingContainer()
+    {
+        m_overlapStack[m_overlapStack.size() - 2].unite(m_overlapStack.last());
+        m_overlapStack.removeLast();
+    }
+
+    RenderGeometryMap& geometryMap() { return m_geometryMap; }
+
+private:
+    Vector<OverlapMapContainer> m_overlapStack;
+    HashSet<const RenderLayer*> m_layers;
+    RenderGeometryMap m_geometryMap;
+};
+
+struct CompositingState {
+    CompositingState(RenderLayer* compAncestor, bool testOverlap)
+        : m_compositingAncestor(compAncestor)
+        , m_subtreeIsCompositing(false)
+        , m_testingOverlap(testOverlap)
+#ifndef NDEBUG
+        , m_depth(0)
+#endif
+    {
+    }
+    
+    CompositingState(const CompositingState& other)
+        : m_compositingAncestor(other.m_compositingAncestor)
+        , m_subtreeIsCompositing(other.m_subtreeIsCompositing)
+        , m_testingOverlap(other.m_testingOverlap)
+#ifndef NDEBUG
+        , m_depth(other.m_depth + 1)
+#endif
+    {
+    }
+    
+    RenderLayer* m_compositingAncestor;
+    bool m_subtreeIsCompositing;
+    bool m_testingOverlap;
+#ifndef NDEBUG
+    int m_depth;
+#endif
+};
+
+
+static inline bool compositingLogEnabled()
+{
+#if !LOG_DISABLED
+    return LogCompositing.state == WTFLogChannelOn;
+#else
+    return false;
+#endif
+}
+
+RenderLayerCompositor::RenderLayerCompositor(RenderView* renderView)
+    : m_renderView(renderView)
+    , m_hasAcceleratedCompositing(true)
+    , m_compositingTriggers(static_cast<ChromeClient::CompositingTriggerFlags>(ChromeClient::AllTriggers))
+    , m_compositedLayerCount(0)
+    , m_showDebugBorders(false)
+    , m_showRepaintCounter(false)
+    , m_reevaluateCompositingAfterLayout(false)
+    , m_compositing(false)
+    , m_compositingLayersNeedRebuild(false)
+    , m_forceCompositingMode(false)
+    , m_inPostLayoutUpdate(false)
+    , m_isTrackingRepaints(false)
+    , m_rootLayerAttachment(RootLayerUnattached)
+#if !LOG_DISABLED
+    , m_rootLayerUpdateCount(0)
+    , m_obligateCompositedLayerCount(0)
+    , m_secondaryCompositedLayerCount(0)
+    , m_obligatoryBackingStoreBytes(0)
+    , m_secondaryBackingStoreBytes(0)
+#endif
+{
+}
+
+RenderLayerCompositor::~RenderLayerCompositor()
+{
+    ASSERT(m_rootLayerAttachment == RootLayerUnattached);
+}
+
+void RenderLayerCompositor::enableCompositingMode(bool enable /* = true */)
+{
+    if (enable != m_compositing) {
+        m_compositing = enable;
+        
+        if (m_compositing) {
+            ensureRootLayer();
+            notifyIFramesOfCompositingChange();
+        } else
+            destroyRootLayer();
+    }
+}
+
+void RenderLayerCompositor::cacheAcceleratedCompositingFlags()
+{
+    bool hasAcceleratedCompositing = false;
+    bool showDebugBorders = false;
+    bool showRepaintCounter = false;
+    bool forceCompositingMode = false;
+
+    if (Settings* settings = m_renderView->document()->settings()) {
+        hasAcceleratedCompositing = settings->acceleratedCompositingEnabled();
+
+        // We allow the chrome to override the settings, in case the page is rendered
+        // on a chrome that doesn't allow accelerated compositing.
+        if (hasAcceleratedCompositing) {
+            if (Page* page = this->page()) {
+                ChromeClient* chromeClient = page->chrome()->client();
+                m_compositingTriggers = chromeClient->allowedCompositingTriggers();
+                hasAcceleratedCompositing = m_compositingTriggers;
+            }
+        }
+
+        showDebugBorders = settings->showDebugBorders();
+        showRepaintCounter = settings->showRepaintCounter();
+        forceCompositingMode = settings->forceCompositingMode() && hasAcceleratedCompositing;
+
+        if (forceCompositingMode && !isMainFrame())
+            forceCompositingMode = requiresCompositingForScrollableFrame();
+    }
+
+    if (hasAcceleratedCompositing != m_hasAcceleratedCompositing || showDebugBorders != m_showDebugBorders || showRepaintCounter != m_showRepaintCounter || forceCompositingMode != m_forceCompositingMode)
+        setCompositingLayersNeedRebuild();
+
+    bool debugBordersChanged = m_showDebugBorders != showDebugBorders;
+    m_hasAcceleratedCompositing = hasAcceleratedCompositing;
+    m_showDebugBorders = showDebugBorders;
+    m_showRepaintCounter = showRepaintCounter;
+    m_forceCompositingMode = forceCompositingMode;
+    
+    if (debugBordersChanged) {
+        if (m_layerForHorizontalScrollbar)
+            m_layerForHorizontalScrollbar->setShowDebugBorder(m_showDebugBorders);
+
+        if (m_layerForVerticalScrollbar)
+            m_layerForVerticalScrollbar->setShowDebugBorder(m_showDebugBorders);
+
+        if (m_layerForScrollCorner)
+            m_layerForScrollCorner->setShowDebugBorder(m_showDebugBorders);
+    }
+}
+
+bool RenderLayerCompositor::canRender3DTransforms() const
+{
+    return hasAcceleratedCompositing() && (m_compositingTriggers & ChromeClient::ThreeDTransformTrigger);
+}
+
+void RenderLayerCompositor::setCompositingLayersNeedRebuild(bool needRebuild)
+{
+    if (inCompositingMode())
+        m_compositingLayersNeedRebuild = needRebuild;
+}
+
+void RenderLayerCompositor::didChangeVisibleRect()
+{
+    GraphicsLayer* rootLayer = rootGraphicsLayer();
+    if (!rootLayer)
+        return;
+
+    FrameView* frameView = m_renderView ? m_renderView->frameView() : 0;
+    if (!frameView)
+        return;
+
+    IntRect visibleRect = m_clipLayer ? IntRect(IntPoint(), frameView->contentsSize()) : frameView->visibleContentRect();
+    if (rootLayer->visibleRectChangeRequiresFlush(visibleRect)) {
+        if (Page* page = this->page())
+            page->chrome()->client()->scheduleCompositingLayerFlush();
+    }
+}
+
+bool RenderLayerCompositor::hasAnyAdditionalCompositedLayers(const RenderLayer* rootLayer) const
+{
+    return m_compositedLayerCount > (rootLayer->isComposited() ? 1 : 0);
+}
+
+void RenderLayerCompositor::updateCompositingLayers(CompositingUpdateType updateType, RenderLayer* updateRoot)
+{
+    // Avoid updating the layers with old values. Compositing layers will be updated after the layout is finished.
+    if (m_renderView->needsLayout())
+        return;
+
+    if (m_forceCompositingMode && !m_compositing)
+        enableCompositingMode(true);
+
+    if (!m_reevaluateCompositingAfterLayout && !m_compositing)
+        return;
+
+    AnimationUpdateBlock animationUpdateBlock(m_renderView->frameView()->frame()->animation());
+
+    TemporaryChange<bool> postLayoutChange(m_inPostLayoutUpdate, true);
+    
+    bool checkForHierarchyUpdate = m_reevaluateCompositingAfterLayout;
+    bool needGeometryUpdate = false;
+
+    switch (updateType) {
+    case CompositingUpdateAfterStyleChange:
+    case CompositingUpdateAfterLayout:
+        checkForHierarchyUpdate = true;
+        break;
+    case CompositingUpdateOnScroll:
+        checkForHierarchyUpdate = true; // Overlap can change with scrolling, so need to check for hierarchy updates.
+        needGeometryUpdate = true;
+        break;
+    case CompositingUpdateOnCompositedScroll:
+        needGeometryUpdate = true;
+        break;
+    }
+
+    if (!checkForHierarchyUpdate && !needGeometryUpdate)
+        return;
+
+    bool needHierarchyUpdate = m_compositingLayersNeedRebuild;
+    bool isFullUpdate = !updateRoot;
+
+    // Only clear the flag if we're updating the entire hierarchy.
+    m_compositingLayersNeedRebuild = false;
+    updateRoot = rootRenderLayer();
+
+    if (isFullUpdate && updateType == CompositingUpdateAfterLayout)
+        m_reevaluateCompositingAfterLayout = false;
+
+#if !LOG_DISABLED
+    double startTime = 0;
+    if (compositingLogEnabled()) {
+        ++m_rootLayerUpdateCount;
+        startTime = currentTime();
+    }
+#endif
+
+    if (checkForHierarchyUpdate) {
+        // Go through the layers in presentation order, so that we can compute which RenderLayers need compositing layers.
+        // FIXME: we could maybe do this and the hierarchy udpate in one pass, but the parenting logic would be more complex.
+        CompositingState compState(updateRoot, true);
+        bool layersChanged = false;
+        bool saw3DTransform = false;
+        {
+            TRACE_EVENT0("blink_rendering", "RenderLayerCompositor::computeCompositingRequirements");
+            OverlapMap overlapTestRequestMap;
+            computeCompositingRequirements(0, updateRoot, &overlapTestRequestMap, compState, layersChanged, saw3DTransform);
+        }
+        needHierarchyUpdate |= layersChanged;
+    }
+
+#if !LOG_DISABLED
+    if (compositingLogEnabled() && isFullUpdate && (needHierarchyUpdate || needGeometryUpdate)) {
+        m_obligateCompositedLayerCount = 0;
+        m_secondaryCompositedLayerCount = 0;
+        m_obligatoryBackingStoreBytes = 0;
+        m_secondaryBackingStoreBytes = 0;
+
+        Frame* frame = m_renderView->frameView()->frame();
+        LOG(Compositing, "\nUpdate %d of %s.\n", m_rootLayerUpdateCount, isMainFrame() ? "main frame" : frame->tree()->uniqueName().string().utf8().data());
+    }
+#endif
+
+    if (needHierarchyUpdate) {
+        // Update the hierarchy of the compositing layers.
+        Vector<GraphicsLayer*> childList;
+        {
+            TRACE_EVENT0("blink_rendering", "RenderLayerCompositor::rebuildCompositingLayerTree");
+            rebuildCompositingLayerTree(updateRoot, childList, 0);
+        }
+
+        // Host the document layer in the RenderView's root layer.
+        if (isFullUpdate) {
+            // Even when childList is empty, don't drop out of compositing mode if there are
+            // composited layers that we didn't hit in our traversal (e.g. because of visibility:hidden).
+            if (childList.isEmpty() && !hasAnyAdditionalCompositedLayers(updateRoot))
+                destroyRootLayer();
+            else
+                m_rootContentLayer->setChildren(childList);
+        }
+    } else if (needGeometryUpdate) {
+        // We just need to do a geometry update. This is only used for position:fixed scrolling;
+        // most of the time, geometry is updated via RenderLayer::styleChanged().
+        updateLayerTreeGeometry(updateRoot, 0);
+    }
+    
+#if !LOG_DISABLED
+    if (compositingLogEnabled() && isFullUpdate && (needHierarchyUpdate || needGeometryUpdate)) {
+        double endTime = currentTime();
+        LOG(Compositing, "Total layers   primary   secondary   obligatory backing (KB)   secondary backing(KB)   total backing (KB)  update time (ms)\n");
+
+        LOG(Compositing, "%8d %11d %9d %20.2f %22.2f %22.2f %18.2f\n",
+            m_obligateCompositedLayerCount + m_secondaryCompositedLayerCount, m_obligateCompositedLayerCount,
+            m_secondaryCompositedLayerCount, m_obligatoryBackingStoreBytes / 1024, m_secondaryBackingStoreBytes / 1024, (m_obligatoryBackingStoreBytes + m_secondaryBackingStoreBytes) / 1024, 1000.0 * (endTime - startTime));
+    }
+#endif
+    ASSERT(updateRoot || !m_compositingLayersNeedRebuild);
+
+    if (!hasAcceleratedCompositing())
+        enableCompositingMode(false);
+
+    // Inform the inspector that the layer tree has changed.
+    InspectorInstrumentation::layerTreeDidChange(page());
+}
+
+void RenderLayerCompositor::layerBecameNonComposited(const RenderLayer* renderLayer)
+{
+    // Inform the inspector that the given RenderLayer was destroyed.
+    InspectorInstrumentation::renderLayerDestroyed(page(), renderLayer);
+
+    ASSERT(m_compositedLayerCount > 0);
+    --m_compositedLayerCount;
+}
+
+#if !LOG_DISABLED
+void RenderLayerCompositor::logLayerInfo(const RenderLayer* layer, int depth)
+{
+    if (!compositingLogEnabled())
+        return;
+        
+    RenderLayerBacking* backing = layer->backing();
+    if (requiresCompositingLayer(layer) || layer->isRootLayer()) {
+        ++m_obligateCompositedLayerCount;
+        m_obligatoryBackingStoreBytes += backing->backingStoreMemoryEstimate();
+    } else {
+        ++m_secondaryCompositedLayerCount;
+        m_secondaryBackingStoreBytes += backing->backingStoreMemoryEstimate();
+    }
+
+    String layerName;
+#ifndef NDEBUG
+    layerName = layer->debugName();
+#endif
+
+    LOG(Compositing, "%*p %dx%d %.2fKB (%s) %s\n", 12 + depth * 2, layer, backing->compositedBounds().width(), backing->compositedBounds().height(),
+        backing->backingStoreMemoryEstimate() / 1024,
+        logReasonsForCompositing(layer), layerName.utf8().data());
+}
+#endif
+
+bool RenderLayerCompositor::updateBacking(RenderLayer* layer, CompositingChangeRepaint shouldRepaint)
+{
+    bool layerChanged = false;
+    RenderLayer::ViewportConstrainedNotCompositedReason viewportConstrainedNotCompositedReason = RenderLayer::NoNotCompositedReason;
+
+    if (needsToBeComposited(layer, &viewportConstrainedNotCompositedReason)) {
+        enableCompositingMode();
+        
+        if (!layer->backing()) {
+            // If we need to repaint, do so before making backing
+            if (shouldRepaint == CompositingChangeRepaintNow)
+                repaintOnCompositingChange(layer);
+
+            layer->ensureBacking();
+
+            // At this time, the ScrollingCooridnator only supports the top-level frame.
+            if (layer->isRootLayer() && !isMainFrame()) {
+                if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
+                    scrollingCoordinator->frameViewRootLayerDidChange(m_renderView->frameView());
+            }
+
+            // This layer and all of its descendants have cached repaints rects that are relative to
+            // the repaint container, so change when compositing changes; we need to update them here.
+            if (layer->parent())
+                layer->computeRepaintRectsIncludingDescendants();
+
+            layerChanged = true;
+        }
+    } else {
+        if (layer->backing()) {
+            // If we're removing backing on a reflection, clear the source GraphicsLayer's pointer to
+            // its replica GraphicsLayer. In practice this should never happen because reflectee and reflection 
+            // are both either composited, or not composited.
+            if (layer->isReflection()) {
+                RenderLayer* sourceLayer = toRenderLayerModelObject(layer->renderer()->parent())->layer();
+                if (RenderLayerBacking* backing = sourceLayer->backing()) {
+                    ASSERT(backing->graphicsLayer()->replicaLayer() == layer->backing()->graphicsLayer());
+                    backing->graphicsLayer()->setReplicatedByLayer(0);
+                }
+            }
+
+            removeViewportConstrainedLayer(layer);
+            
+            layer->clearBacking();
+            layerChanged = true;
+
+            // This layer and all of its descendants have cached repaints rects that are relative to
+            // the repaint container, so change when compositing changes; we need to update them here.
+            layer->computeRepaintRectsIncludingDescendants();
+
+            // If we need to repaint, do so now that we've removed the backing
+            if (shouldRepaint == CompositingChangeRepaintNow)
+                repaintOnCompositingChange(layer);
+        }
+    }
+
+    if (layerChanged && layer->renderer()->isVideo()) {
+        // If it's a video, give the media player a chance to hook up to the layer.
+        RenderVideo* video = toRenderVideo(layer->renderer());
+        video->acceleratedRenderingStateChanged();
+    }
+
+    if (layerChanged && layer->renderer()->isRenderPart()) {
+        RenderLayerCompositor* innerCompositor = frameContentsCompositor(toRenderPart(layer->renderer()));
+        if (innerCompositor && innerCompositor->inCompositingMode())
+            innerCompositor->updateRootLayerAttachment();
+    }
+    
+    if (layerChanged)
+        layer->clearClipRectsIncludingDescendants(PaintingClipRects);
+
+    // If a fixed position layer gained/lost a backing or the reason not compositing it changed,
+    // the scrolling coordinator needs to recalculate whether it can do fast scrolling.
+    if (layer->renderer()->style()->position() == FixedPosition) {
+        if (layer->viewportConstrainedNotCompositedReason() != viewportConstrainedNotCompositedReason) {
+            layer->setViewportConstrainedNotCompositedReason(viewportConstrainedNotCompositedReason);
+            layerChanged = true;
+        }
+        if (layerChanged) {
+            if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
+                scrollingCoordinator->frameViewFixedObjectsDidChange(m_renderView->frameView());
+        }
+    }
+    
+    if (layer->backing())
+        layer->backing()->updateDebugIndicators(m_showDebugBorders, m_showRepaintCounter);
+
+    return layerChanged;
+}
+
+bool RenderLayerCompositor::updateLayerCompositingState(RenderLayer* layer, CompositingChangeRepaint shouldRepaint)
+{
+    bool layerChanged = updateBacking(layer, shouldRepaint);
+
+    // See if we need content or clipping layers. Methods called here should assume
+    // that the compositing state of descendant layers has not been updated yet.
+    if (layer->backing() && layer->backing()->updateGraphicsLayerConfiguration())
+        layerChanged = true;
+
+    return layerChanged;
+}
+
+void RenderLayerCompositor::repaintOnCompositingChange(RenderLayer* layer)
+{
+    // If the renderer is not attached yet, no need to repaint.
+    if (layer->renderer() != m_renderView && !layer->renderer()->parent())
+        return;
+
+    RenderLayerModelObject* repaintContainer = layer->renderer()->containerForRepaint();
+    if (!repaintContainer)
+        repaintContainer = m_renderView;
+
+    layer->repaintIncludingNonCompositingDescendants(repaintContainer);
+}
+
+// This method assumes that layout is up-to-date, unlike repaintOnCompositingChange().
+void RenderLayerCompositor::repaintInCompositedAncestor(RenderLayer* layer, const LayoutRect& rect)
+{
+    RenderLayer* compositedAncestor = layer->enclosingCompositingLayerForRepaint(false /*exclude self*/);
+    if (compositedAncestor) {
+        ASSERT(compositedAncestor->backing());
+
+        LayoutPoint offset;
+        layer->convertToLayerCoords(compositedAncestor, offset);
+
+        LayoutRect repaintRect = rect;
+        repaintRect.moveBy(offset);
+
+        compositedAncestor->setBackingNeedsRepaintInRect(repaintRect);
+    }
+}
+
+// The bounds of the GraphicsLayer created for a compositing layer is the union of the bounds of all the descendant
+// RenderLayers that are rendered by the composited RenderLayer.
+IntRect RenderLayerCompositor::calculateCompositedBounds(const RenderLayer* layer, const RenderLayer* ancestorLayer) const
+{
+    if (!canBeComposited(layer))
+        return IntRect();
+
+    RenderLayer::CalculateLayerBoundsFlags flags = RenderLayer::DefaultCalculateLayerBoundsFlags | RenderLayer::ExcludeHiddenDescendants | RenderLayer::DontConstrainForMask;
+#if HAVE(COMPOSITOR_FILTER_OUTSETS)
+    // If the compositor computes its own filter outsets, don't include them in the composited bounds.
+    if (!layer->paintsWithFilters())
+        flags &= ~RenderLayer::IncludeLayerFilterOutsets;
+#endif
+    return layer->calculateLayerBounds(ancestorLayer, 0, flags);
+}
+
+void RenderLayerCompositor::layerWasAdded(RenderLayer* /*parent*/, RenderLayer* /*child*/)
+{
+    setCompositingLayersNeedRebuild();
+}
+
+void RenderLayerCompositor::layerWillBeRemoved(RenderLayer* parent, RenderLayer* child)
+{
+    if (!child->isComposited() || parent->renderer()->documentBeingDestroyed())
+        return;
+
+    removeViewportConstrainedLayer(child);
+    repaintInCompositedAncestor(child, child->backing()->compositedBounds());
+
+    setCompositingParent(child, 0);
+    setCompositingLayersNeedRebuild();
+}
+
+RenderLayer* RenderLayerCompositor::enclosingNonStackingClippingLayer(const RenderLayer* layer) const
+{
+    for (RenderLayer* curr = layer->parent(); curr != 0; curr = curr->parent()) {
+        if (curr->isStackingContainer())
+            return 0;
+
+        if (curr->renderer()->hasClipOrOverflowClip())
+            return curr;
+    }
+    return 0;
+}
+
+void RenderLayerCompositor::addToOverlapMap(OverlapMap& overlapMap, RenderLayer* layer, IntRect& layerBounds, bool& boundsComputed)
+{
+    if (layer->isRootLayer())
+        return;
+
+    if (!boundsComputed) {
+        // FIXME: If this layer's overlap bounds include its children, we don't need to add its
+        // children's bounds to the overlap map.
+        layerBounds = enclosingIntRect(overlapMap.geometryMap().absoluteRect(layer->overlapBounds()));
+        // Empty rects never intersect, but we need them to for the purposes of overlap testing.
+        if (layerBounds.isEmpty())
+            layerBounds.setSize(IntSize(1, 1));
+        boundsComputed = true;
+    }
+
+    IntRect clipRect = pixelSnappedIntRect(layer->backgroundClipRect(RenderLayer::ClipRectsContext(rootRenderLayer(), 0, AbsoluteClipRects)).rect()); // FIXME: Incorrect for CSS regions.
+    clipRect.intersect(layerBounds);
+    overlapMap.add(layer, clipRect);
+}
+
+void RenderLayerCompositor::addToOverlapMapRecursive(OverlapMap& overlapMap, RenderLayer* layer, RenderLayer* ancestorLayer)
+{
+    if (!canBeComposited(layer) || overlapMap.contains(layer))
+        return;
+
+    // A null ancestorLayer is an indication that 'layer' has already been pushed.
+    if (ancestorLayer)
+        overlapMap.geometryMap().pushMappingsToAncestor(layer, ancestorLayer);
+    
+    IntRect bounds;
+    bool haveComputedBounds = false;
+    addToOverlapMap(overlapMap, layer, bounds, haveComputedBounds);
+
+#if !ASSERT_DISABLED
+    LayerListMutationDetector mutationChecker(layer);
+#endif
+
+    if (layer->isStackingContainer()) {
+        if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) {
+            size_t listSize = negZOrderList->size();
+            for (size_t i = 0; i < listSize; ++i) {
+                RenderLayer* curLayer = negZOrderList->at(i);
+                addToOverlapMapRecursive(overlapMap, curLayer, layer);
+            }
+        }
+    }
+
+    if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) {
+        size_t listSize = normalFlowList->size();
+        for (size_t i = 0; i < listSize; ++i) {
+            RenderLayer* curLayer = normalFlowList->at(i);
+            addToOverlapMapRecursive(overlapMap, curLayer, layer);
+        }
+    }
+
+    if (layer->isStackingContainer()) {
+        if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) {
+            size_t listSize = posZOrderList->size();
+            for (size_t i = 0; i < listSize; ++i) {
+                RenderLayer* curLayer = posZOrderList->at(i);
+                addToOverlapMapRecursive(overlapMap, curLayer, layer);
+            }
+        }
+    }
+    
+    if (ancestorLayer)
+        overlapMap.geometryMap().popMappingsToAncestor(ancestorLayer);
+}
+
+//  Recurse through the layers in z-index and overflow order (which is equivalent to painting order)
+//  For the z-order children of a compositing layer:
+//      If a child layers has a compositing layer, then all subsequent layers must
+//      be compositing in order to render above that layer.
+//
+//      If a child in the negative z-order list is compositing, then the layer itself
+//      must be compositing so that its contents render over that child.
+//      This implies that its positive z-index children must also be compositing.
+//
+void RenderLayerCompositor::computeCompositingRequirements(RenderLayer* ancestorLayer, RenderLayer* layer, OverlapMap* overlapMap, CompositingState& compositingState, bool& layersChanged, bool& descendantHas3DTransform)
+{
+    layer->updateLayerListsIfNeeded();
+    
+    if (overlapMap)
+        overlapMap->geometryMap().pushMappingsToAncestor(layer, ancestorLayer);
+    
+    // Clear the flag
+    layer->setHasCompositingDescendant(false);
+    
+    RenderLayer::IndirectCompositingReason compositingReason = compositingState.m_subtreeIsCompositing ? RenderLayer::IndirectCompositingForStacking : RenderLayer::NoIndirectCompositingReason;
+
+    bool haveComputedBounds = false;
+    IntRect absBounds;
+    // If we know for sure the layer is going to be composited, don't bother looking it up in the overlap map.
+    // Note that we are using requiresCompositingLayer instead of needsToBeComposited to avoid reading back the
+    // previous indirectCompositingReason through the call to needsToBeComposited.
+    if (overlapMap && !overlapMap->isEmpty() && compositingState.m_testingOverlap && !requiresCompositingLayer(layer)) {
+        // If we're testing for overlap, we only need to composite if we overlap something that is already composited.
+        absBounds = enclosingIntRect(overlapMap->geometryMap().absoluteRect(layer->overlapBounds()));
+
+        // Empty rects never intersect, but we need them to for the purposes of overlap testing.
+        if (absBounds.isEmpty())
+            absBounds.setSize(IntSize(1, 1));
+        haveComputedBounds = true;
+        compositingReason = overlapMap->overlapsLayers(absBounds) ? RenderLayer::IndirectCompositingForOverlap : RenderLayer::NoIndirectCompositingReason;
+    }
+
+    // Video is special. It's the only RenderLayer type that can both have
+    // RenderLayer children and whose children can't use its backing to render
+    // into. These children (the controls) always need to be promoted into their
+    // own layers to draw on top of the accelerated video.
+    if (compositingState.m_compositingAncestor && compositingState.m_compositingAncestor->renderer()->isVideo())
+        compositingReason = RenderLayer::IndirectCompositingForOverlap;
+
+    layer->setIndirectCompositingReason(compositingReason);
+
+    // The children of this layer don't need to composite, unless there is
+    // a compositing layer among them, so start by inheriting the compositing
+    // ancestor with m_subtreeIsCompositing set to false.
+    CompositingState childState(compositingState);
+    childState.m_subtreeIsCompositing = false;
+
+    bool willBeComposited = needsToBeComposited(layer);
+    if (willBeComposited) {
+        // Tell the parent it has compositing descendants.
+        compositingState.m_subtreeIsCompositing = true;
+        // This layer now acts as the ancestor for kids.
+        childState.m_compositingAncestor = layer;
+
+        if (overlapMap)
+            overlapMap->pushCompositingContainer();
+        // This layer is going to be composited, so children can safely ignore the fact that there's an 
+        // animation running behind this layer, meaning they can rely on the overlap map testing again.
+        childState.m_testingOverlap = true;
+    }
+
+#if !ASSERT_DISABLED
+    LayerListMutationDetector mutationChecker(layer);
+#endif
+
+    bool anyDescendantHas3DTransform = false;
+
+    if (layer->isStackingContainer()) {
+        if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) {
+            size_t listSize = negZOrderList->size();
+            for (size_t i = 0; i < listSize; ++i) {
+                RenderLayer* curLayer = negZOrderList->at(i);
+                computeCompositingRequirements(layer, curLayer, overlapMap, childState, layersChanged, anyDescendantHas3DTransform);
+
+                // If we have to make a layer for this child, make one now so we can have a contents layer
+                // (since we need to ensure that the -ve z-order child renders underneath our contents).
+                if (!willBeComposited && childState.m_subtreeIsCompositing) {
+                    // make layer compositing
+                    layer->setIndirectCompositingReason(RenderLayer::IndirectCompositingForBackgroundLayer);
+                    childState.m_compositingAncestor = layer;
+                    if (overlapMap)
+                        overlapMap->pushCompositingContainer();
+                    // This layer is going to be composited, so children can safely ignore the fact that there's an 
+                    // animation running behind this layer, meaning they can rely on the overlap map testing again
+                    childState.m_testingOverlap = true;
+                    willBeComposited = true;
+                }
+            }
+        }
+    }
+    
+    if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) {
+        size_t listSize = normalFlowList->size();
+        for (size_t i = 0; i < listSize; ++i) {
+            RenderLayer* curLayer = normalFlowList->at(i);
+            computeCompositingRequirements(layer, curLayer, overlapMap, childState, layersChanged, anyDescendantHas3DTransform);
+        }
+    }
+
+    if (layer->isStackingContainer()) {
+        if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) {
+            size_t listSize = posZOrderList->size();
+            for (size_t i = 0; i < listSize; ++i) {
+                RenderLayer* curLayer = posZOrderList->at(i);
+                computeCompositingRequirements(layer, curLayer, overlapMap, childState, layersChanged, anyDescendantHas3DTransform);
+            }
+        }
+    }
+    
+    // If we just entered compositing mode, the root will have become composited (as long as accelerated compositing is enabled).
+    if (layer->isRootLayer()) {
+        if (inCompositingMode() && m_hasAcceleratedCompositing)
+            willBeComposited = true;
+    }
+    
+    ASSERT(willBeComposited == needsToBeComposited(layer));
+
+    // All layers (even ones that aren't being composited) need to get added to
+    // the overlap map. Layers that do not composite will draw into their
+    // compositing ancestor's backing, and so are still considered for overlap.
+    if (overlapMap && childState.m_compositingAncestor && !childState.m_compositingAncestor->isRootLayer())
+        addToOverlapMap(*overlapMap, layer, absBounds, haveComputedBounds);
+
+    // Now check for reasons to become composited that depend on the state of descendant layers.
+    RenderLayer::IndirectCompositingReason indirectCompositingReason;
+    if (!willBeComposited && canBeComposited(layer)
+        && requiresCompositingForIndirectReason(layer->renderer(), childState.m_subtreeIsCompositing, anyDescendantHas3DTransform, indirectCompositingReason)) {
+        layer->setIndirectCompositingReason(indirectCompositingReason);
+        childState.m_compositingAncestor = layer;
+        if (overlapMap) {
+            overlapMap->pushCompositingContainer();
+            addToOverlapMapRecursive(*overlapMap, layer);
+        }
+        willBeComposited = true;
+    }
+    
+    ASSERT(willBeComposited == needsToBeComposited(layer));
+    if (layer->reflectionLayer()) {
+        // FIXME: Shouldn't we call computeCompositingRequirements to handle a reflection overlapping with another renderer?
+        layer->reflectionLayer()->setIndirectCompositingReason(willBeComposited ? RenderLayer::IndirectCompositingForStacking : RenderLayer::NoIndirectCompositingReason);
+    }
+
+    // Subsequent layers in the parent stacking context also need to composite.
+    if (childState.m_subtreeIsCompositing)
+        compositingState.m_subtreeIsCompositing = true;
+
+    // Set the flag to say that this SC has compositing children.
+    layer->setHasCompositingDescendant(childState.m_subtreeIsCompositing);
+
+    // setHasCompositingDescendant() may have changed the answer to needsToBeComposited() when clipping,
+    // so test that again.
+    bool isCompositedClippingLayer = canBeComposited(layer) && clipsCompositingDescendants(layer);
+
+    // Turn overlap testing off for later layers if it's already off, or if we have an animating transform.
+    // Note that if the layer clips its descendants, there's no reason to propagate the child animation to the parent layers. That's because
+    // we know for sure the animation is contained inside the clipping rectangle, which is already added to the overlap map.
+    if ((!childState.m_testingOverlap && !isCompositedClippingLayer) || isRunningAcceleratedTransformAnimation(layer->renderer()))
+        compositingState.m_testingOverlap = false;
+    
+    if (isCompositedClippingLayer) {
+        if (!willBeComposited) {
+            childState.m_compositingAncestor = layer;
+            if (overlapMap) {
+                overlapMap->pushCompositingContainer();
+                addToOverlapMapRecursive(*overlapMap, layer);
+            }
+            willBeComposited = true;
+         }
+    }
+
+    if (overlapMap && childState.m_compositingAncestor == layer && !layer->isRootLayer())
+        overlapMap->popCompositingContainer();
+
+    // If we're back at the root, and no other layers need to be composited, and the root layer itself doesn't need
+    // to be composited, then we can drop out of compositing mode altogether. However, don't drop out of compositing mode
+    // if there are composited layers that we didn't hit in our traversal (e.g. because of visibility:hidden).
+    if (layer->isRootLayer() && !childState.m_subtreeIsCompositing && !requiresCompositingLayer(layer) && !m_forceCompositingMode && !hasAnyAdditionalCompositedLayers(layer)) {
+        enableCompositingMode(false);
+        willBeComposited = false;
+    }
+    
+    // If the layer is going into compositing mode, repaint its old location.
+    ASSERT(willBeComposited == needsToBeComposited(layer));
+    if (!layer->isComposited() && willBeComposited)
+        repaintOnCompositingChange(layer);
+
+    // Update backing now, so that we can use isComposited() reliably during tree traversal in rebuildCompositingLayerTree().
+    if (updateBacking(layer, CompositingChangeRepaintNow))
+        layersChanged = true;
+
+    if (layer->reflectionLayer() && updateLayerCompositingState(layer->reflectionLayer(), CompositingChangeRepaintNow))
+        layersChanged = true;
+
+    descendantHas3DTransform |= anyDescendantHas3DTransform || layer->has3DTransform();
+
+    if (overlapMap)
+        overlapMap->geometryMap().popMappingsToAncestor(ancestorLayer);
+}
+
+void RenderLayerCompositor::setCompositingParent(RenderLayer* childLayer, RenderLayer* parentLayer)
+{
+    ASSERT(!parentLayer || childLayer->ancestorCompositingLayer() == parentLayer);
+    ASSERT(childLayer->isComposited());
+
+    // It's possible to be called with a parent that isn't yet composited when we're doing
+    // partial updates as required by painting or hit testing. Just bail in that case;
+    // we'll do a full layer update soon.
+    if (!parentLayer || !parentLayer->isComposited())
+        return;
+
+    if (parentLayer) {
+        GraphicsLayer* hostingLayer = parentLayer->backing()->parentForSublayers();
+        GraphicsLayer* hostedLayer = childLayer->backing()->childForSuperlayers();
+        
+        hostingLayer->addChild(hostedLayer);
+    } else
+        childLayer->backing()->childForSuperlayers()->removeFromParent();
+}
+
+void RenderLayerCompositor::removeCompositedChildren(RenderLayer* layer)
+{
+    ASSERT(layer->isComposited());
+
+    GraphicsLayer* hostingLayer = layer->backing()->parentForSublayers();
+    hostingLayer->removeAllChildren();
+}
+
+bool RenderLayerCompositor::canAccelerateVideoRendering(RenderVideo* o) const
+{
+    if (!m_hasAcceleratedCompositing)
+        return false;
+
+    return o->supportsAcceleratedRendering();
+}
+
+void RenderLayerCompositor::rebuildCompositingLayerTree(RenderLayer* layer, Vector<GraphicsLayer*>& childLayersOfEnclosingLayer, int depth)
+{
+    // Make the layer compositing if necessary, and set up clipping and content layers.
+    // Note that we can only do work here that is independent of whether the descendant layers
+    // have been processed. computeCompositingRequirements() will already have done the repaint if necessary.
+
+    // Used for gathering UMA data about the effect on memory usage of promoting all layers
+    // that have a webkit-transition on opacity or transform and intersect the viewport.
+    static double pixelsWithoutPromotingAllTransitions = 0.0;
+    static double pixelsAddedByPromotingAllTransitions = 0.0;
+
+    if (!depth) {
+        pixelsWithoutPromotingAllTransitions = 0.0;
+        pixelsAddedByPromotingAllTransitions = 0.0;
+    }
+
+    RenderLayerBacking* layerBacking = layer->backing();
+    if (layerBacking) {
+        // The compositing state of all our children has been updated already, so now
+        // we can compute and cache the composited bounds for this layer.
+        layerBacking->updateCompositedBounds();
+
+        if (RenderLayer* reflection = layer->reflectionLayer()) {
+            if (reflection->backing())
+                reflection->backing()->updateCompositedBounds();
+        }
+
+        if (layerBacking->updateGraphicsLayerConfiguration())
+            layerBacking->updateDebugIndicators(m_showDebugBorders, m_showRepaintCounter);
+        
+        layerBacking->updateGraphicsLayerGeometry();
+
+        if (!layer->parent())
+            updateRootLayerPosition();
+
+#if !LOG_DISABLED
+        logLayerInfo(layer, depth);
+#else
+        UNUSED_PARAM(depth);
+#endif
+        if (layerBacking->hasUnpositionedOverflowControlsLayers())
+            layer->positionNewlyCreatedOverflowControls();
+
+        pixelsWithoutPromotingAllTransitions += layer->size().height() * layer->size().width();
+    } else {
+        if ((layer->renderer()->style()->transitionForProperty(CSSPropertyOpacity) ||
+             layer->renderer()->style()->transitionForProperty(CSSPropertyWebkitTransform)) &&
+            m_renderView->viewRect().intersects(layer->absoluteBoundingBox()))
+            pixelsAddedByPromotingAllTransitions += layer->size().height() * layer->size().width();
+    }
+
+    // If this layer has backing, then we are collecting its children, otherwise appending
+    // to the compositing child list of an enclosing layer.
+    Vector<GraphicsLayer*> layerChildren;
+    Vector<GraphicsLayer*>& childList = layerBacking ? layerChildren : childLayersOfEnclosingLayer;
+
+#if !ASSERT_DISABLED
+    LayerListMutationDetector mutationChecker(layer);
+#endif
+
+    if (layer->isStackingContainer()) {
+        if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) {
+            size_t listSize = negZOrderList->size();
+            for (size_t i = 0; i < listSize; ++i) {
+                RenderLayer* curLayer = negZOrderList->at(i);
+                rebuildCompositingLayerTree(curLayer, childList, depth + 1);
+            }
+        }
+
+        // If a negative z-order child is compositing, we get a foreground layer which needs to get parented.
+        if (layerBacking && layerBacking->foregroundLayer())
+            childList.append(layerBacking->foregroundLayer());
+    }
+
+    if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) {
+        size_t listSize = normalFlowList->size();
+        for (size_t i = 0; i < listSize; ++i) {
+            RenderLayer* curLayer = normalFlowList->at(i);
+            rebuildCompositingLayerTree(curLayer, childList, depth + 1);
+        }
+    }
+    
+    if (layer->isStackingContainer()) {
+        if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) {
+            size_t listSize = posZOrderList->size();
+            for (size_t i = 0; i < listSize; ++i) {
+                RenderLayer* curLayer = posZOrderList->at(i);
+                rebuildCompositingLayerTree(curLayer, childList, depth + 1);
+            }
+        }
+    }
+    
+    if (layerBacking) {
+        bool parented = false;
+        if (layer->renderer()->isRenderPart())
+            parented = parentFrameContentLayers(toRenderPart(layer->renderer()));
+
+        if (!parented)
+            layerBacking->parentForSublayers()->setChildren(layerChildren);
+
+        // If the layer has a clipping layer the overflow controls layers will be siblings of the clipping layer.
+        // Otherwise, the overflow control layers are normal children.
+        if (!layerBacking->hasClippingLayer() && !layerBacking->hasScrollingLayer()) {
+            if (GraphicsLayer* overflowControlLayer = layerBacking->layerForHorizontalScrollbar()) {
+                overflowControlLayer->removeFromParent();
+                layerBacking->parentForSublayers()->addChild(overflowControlLayer);
+            }
+
+            if (GraphicsLayer* overflowControlLayer = layerBacking->layerForVerticalScrollbar()) {
+                overflowControlLayer->removeFromParent();
+                layerBacking->parentForSublayers()->addChild(overflowControlLayer);
+            }
+
+            if (GraphicsLayer* overflowControlLayer = layerBacking->layerForScrollCorner()) {
+                overflowControlLayer->removeFromParent();
+                layerBacking->parentForSublayers()->addChild(overflowControlLayer);
+            }
+        }
+
+        childLayersOfEnclosingLayer.append(layerBacking->childForSuperlayers());
+    }
+
+    if (!depth) {
+        int percentageIncreaseInPixels = static_cast<int>(pixelsAddedByPromotingAllTransitions / pixelsWithoutPromotingAllTransitions * 100);
+        HistogramSupport::histogramCustomCounts("Renderer.PixelIncreaseFromTransitions", percentageIncreaseInPixels, 0, 1000, 50);
+    }
+}
+
+void RenderLayerCompositor::frameViewDidChangeLocation(const IntPoint& contentsOffset)
+{
+    if (m_overflowControlsHostLayer)
+        m_overflowControlsHostLayer->setPosition(contentsOffset);
+}
+
+void RenderLayerCompositor::frameViewDidChangeSize()
+{
+    if (m_clipLayer) {
+        FrameView* frameView = m_renderView->frameView();
+        m_clipLayer->setSize(frameView->unscaledVisibleContentSize());
+
+        frameViewDidScroll();
+        updateOverflowControlsLayers();
+
+#if ENABLE(RUBBER_BANDING)
+        if (m_layerForOverhangAreas)
+            m_layerForOverhangAreas->setSize(frameView->frameRect().size());
+#endif
+    }
+}
+
+void RenderLayerCompositor::frameViewDidScroll()
+{
+    FrameView* frameView = m_renderView->frameView();
+    IntPoint scrollPosition = frameView->scrollPosition();
+
+    if (!m_scrollLayer)
+        return;
+
+    // If there's a scrolling coordinator that manages scrolling for this frame view,
+    // it will also manage updating the scroll layer position.
+    if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator()) {
+        if (scrollingCoordinator->coordinatesScrollingForFrameView(frameView))
+            return;
+        if (Settings* settings = m_renderView->document()->settings()) {
+            if (settings->compositedScrollingForFramesEnabled())
+                scrollingCoordinator->scrollableAreaScrollLayerDidChange(frameView);
+        }
+    }
+
+    m_scrollLayer->setPosition(FloatPoint(-scrollPosition.x(), -scrollPosition.y()));
+
+    if (GraphicsLayer* fixedBackgroundLayer = fixedRootBackgroundLayer())
+        fixedBackgroundLayer->setPosition(IntPoint(frameView->scrollOffsetForFixedPosition()));
+}
+
+void RenderLayerCompositor::frameViewDidLayout()
+{
+}
+
+void RenderLayerCompositor::rootFixedBackgroundsChanged()
+{
+    // FIXME: Implement when root fixed background layer is implemented.
+}
+
+void RenderLayerCompositor::scrollingLayerDidChange(RenderLayer* layer)
+{
+    if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
+        scrollingCoordinator->scrollableAreaScrollLayerDidChange(layer);
+}
+
+String RenderLayerCompositor::layerTreeAsText(LayerTreeFlags flags)
+{
+    updateCompositingLayers(CompositingUpdateAfterLayout);
+
+    if (!m_rootContentLayer)
+        return String();
+
+    LayerTreeAsTextBehavior layerTreeBehavior = LayerTreeAsTextBehaviorNormal;
+    if (flags & LayerTreeFlagsIncludeDebugInfo)
+        layerTreeBehavior |= LayerTreeAsTextDebug;
+    if (flags & LayerTreeFlagsIncludeVisibleRects)
+        layerTreeBehavior |= LayerTreeAsTextIncludeVisibleRects;
+    if (flags & LayerTreeFlagsIncludeRepaintRects)
+        layerTreeBehavior |= LayerTreeAsTextIncludeRepaintRects;
+    if (flags & LayerTreeFlagsIncludePaintingPhases)
+        layerTreeBehavior |= LayerTreeAsTextIncludePaintingPhases;
+
+    // We skip dumping the scroll and clip layers to keep layerTreeAsText output
+    // similar between platforms.
+    String layerTreeText = m_rootContentLayer->layerTreeAsText(layerTreeBehavior);
+
+    // The true root layer is not included in the dump, so if we want to report
+    // its repaint rects, they must be included here.
+    if (flags & LayerTreeFlagsIncludeRepaintRects) {
+        String layerTreeTextWithRootRepaintRects = m_renderView->frameView()->trackedRepaintRectsAsText();
+        layerTreeTextWithRootRepaintRects.append(layerTreeText);
+        return layerTreeTextWithRootRepaintRects;
+    }
+
+    return layerTreeText;
+}
+
+RenderLayerCompositor* RenderLayerCompositor::frameContentsCompositor(RenderPart* renderer)
+{
+    if (!renderer->node()->isFrameOwnerElement())
+        return 0;
+        
+    HTMLFrameOwnerElement* element = toFrameOwnerElement(renderer->node());
+    if (Document* contentDocument = element->contentDocument()) {
+        if (RenderView* view = contentDocument->renderView())
+            return view->compositor();
+    }
+    return 0;
+}
+
+bool RenderLayerCompositor::parentFrameContentLayers(RenderPart* renderer)
+{
+    RenderLayerCompositor* innerCompositor = frameContentsCompositor(renderer);
+    if (!innerCompositor || !innerCompositor->inCompositingMode() || innerCompositor->rootLayerAttachment() != RootLayerAttachedViaEnclosingFrame)
+        return false;
+    
+    RenderLayer* layer = renderer->layer();
+    if (!layer->isComposited())
+        return false;
+
+    RenderLayerBacking* backing = layer->backing();
+    GraphicsLayer* hostingLayer = backing->parentForSublayers();
+    GraphicsLayer* rootLayer = innerCompositor->rootGraphicsLayer();
+    if (hostingLayer->children().size() != 1 || hostingLayer->children()[0] != rootLayer) {
+        hostingLayer->removeAllChildren();
+        hostingLayer->addChild(rootLayer);
+    }
+    return true;
+}
+
+// This just updates layer geometry without changing the hierarchy.
+void RenderLayerCompositor::updateLayerTreeGeometry(RenderLayer* layer, int depth)
+{
+    if (RenderLayerBacking* layerBacking = layer->backing()) {
+        // The compositing state of all our children has been updated already, so now
+        // we can compute and cache the composited bounds for this layer.
+        layerBacking->updateCompositedBounds();
+
+        if (RenderLayer* reflection = layer->reflectionLayer()) {
+            if (reflection->backing())
+                reflection->backing()->updateCompositedBounds();
+        }
+
+        layerBacking->updateGraphicsLayerConfiguration();
+        layerBacking->updateGraphicsLayerGeometry();
+
+        if (!layer->parent())
+            updateRootLayerPosition();
+
+#if !LOG_DISABLED
+        logLayerInfo(layer, depth);
+#else
+        UNUSED_PARAM(depth);
+#endif
+    }
+
+#if !ASSERT_DISABLED
+    LayerListMutationDetector mutationChecker(layer);
+#endif
+
+    if (layer->isStackingContainer()) {
+        if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) {
+            size_t listSize = negZOrderList->size();
+            for (size_t i = 0; i < listSize; ++i)
+                updateLayerTreeGeometry(negZOrderList->at(i), depth + 1);
+        }
+    }
+
+    if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) {
+        size_t listSize = normalFlowList->size();
+        for (size_t i = 0; i < listSize; ++i)
+            updateLayerTreeGeometry(normalFlowList->at(i), depth + 1);
+    }
+    
+    if (layer->isStackingContainer()) {
+        if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) {
+            size_t listSize = posZOrderList->size();
+            for (size_t i = 0; i < listSize; ++i)
+                updateLayerTreeGeometry(posZOrderList->at(i), depth + 1);
+        }
+    }
+}
+
+// Recurs down the RenderLayer tree until its finds the compositing descendants of compositingAncestor and updates their geometry.
+void RenderLayerCompositor::updateCompositingDescendantGeometry(RenderLayer* compositingAncestor, RenderLayer* layer, bool compositedChildrenOnly)
+{
+    if (layer != compositingAncestor) {
+        if (RenderLayerBacking* layerBacking = layer->backing()) {
+            layerBacking->updateCompositedBounds();
+
+            if (RenderLayer* reflection = layer->reflectionLayer()) {
+                if (reflection->backing())
+                    reflection->backing()->updateCompositedBounds();
+            }
+
+            layerBacking->updateGraphicsLayerGeometry();
+            if (compositedChildrenOnly)
+                return;
+        }
+    }
+
+    if (layer->reflectionLayer())
+        updateCompositingDescendantGeometry(compositingAncestor, layer->reflectionLayer(), compositedChildrenOnly);
+
+    if (!layer->hasCompositingDescendant())
+        return;
+
+#if !ASSERT_DISABLED
+    LayerListMutationDetector mutationChecker(layer);
+#endif
+    
+    if (layer->isStackingContainer()) {
+        if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) {
+            size_t listSize = negZOrderList->size();
+            for (size_t i = 0; i < listSize; ++i)
+                updateCompositingDescendantGeometry(compositingAncestor, negZOrderList->at(i), compositedChildrenOnly);
+        }
+    }
+
+    if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) {
+        size_t listSize = normalFlowList->size();
+        for (size_t i = 0; i < listSize; ++i)
+            updateCompositingDescendantGeometry(compositingAncestor, normalFlowList->at(i), compositedChildrenOnly);
+    }
+    
+    if (layer->isStackingContainer()) {
+        if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) {
+            size_t listSize = posZOrderList->size();
+            for (size_t i = 0; i < listSize; ++i)
+                updateCompositingDescendantGeometry(compositingAncestor, posZOrderList->at(i), compositedChildrenOnly);
+        }
+    }
+}
+
+
+void RenderLayerCompositor::repaintCompositedLayers(const IntRect* absRect)
+{
+    recursiveRepaintLayer(rootRenderLayer(), absRect);
+}
+
+void RenderLayerCompositor::recursiveRepaintLayer(RenderLayer* layer, const IntRect* rect)
+{
+    // FIXME: This method does not work correctly with transforms.
+    if (layer->isComposited() && !layer->backing()->paintsIntoCompositedAncestor()) {
+        if (rect)
+            layer->setBackingNeedsRepaintInRect(*rect);
+        else
+            layer->setBackingNeedsRepaint();
+    }
+
+#if !ASSERT_DISABLED
+    LayerListMutationDetector mutationChecker(layer);
+#endif
+
+    if (layer->hasCompositingDescendant()) {
+        if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) {
+            size_t listSize = negZOrderList->size();
+            for (size_t i = 0; i < listSize; ++i) {
+                RenderLayer* curLayer = negZOrderList->at(i);
+                if (rect) {
+                    IntRect childRect(*rect);
+                    curLayer->convertToPixelSnappedLayerCoords(layer, childRect);
+                    recursiveRepaintLayer(curLayer, &childRect);
+                } else
+                    recursiveRepaintLayer(curLayer);
+            }
+        }
+
+        if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) {
+            size_t listSize = posZOrderList->size();
+            for (size_t i = 0; i < listSize; ++i) {
+                RenderLayer* curLayer = posZOrderList->at(i);
+                if (rect) {
+                    IntRect childRect(*rect);
+                    curLayer->convertToPixelSnappedLayerCoords(layer, childRect);
+                    recursiveRepaintLayer(curLayer, &childRect);
+                } else
+                    recursiveRepaintLayer(curLayer);
+            }
+        }
+    }
+    if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) {
+        size_t listSize = normalFlowList->size();
+        for (size_t i = 0; i < listSize; ++i) {
+            RenderLayer* curLayer = normalFlowList->at(i);
+            if (rect) {
+                IntRect childRect(*rect);
+                curLayer->convertToPixelSnappedLayerCoords(layer, childRect);
+                recursiveRepaintLayer(curLayer, &childRect);
+            } else
+                recursiveRepaintLayer(curLayer);
+        }
+    }
+}
+
+RenderLayer* RenderLayerCompositor::rootRenderLayer() const
+{
+    return m_renderView->layer();
+}
+
+GraphicsLayer* RenderLayerCompositor::rootGraphicsLayer() const
+{
+    if (m_overflowControlsHostLayer)
+        return m_overflowControlsHostLayer.get();
+    return m_rootContentLayer.get();
+}
+
+GraphicsLayer* RenderLayerCompositor::scrollLayer() const
+{
+    return m_scrollLayer.get();
+}
+
+void RenderLayerCompositor::setIsInWindow(bool isInWindow)
+{
+    if (!inCompositingMode())
+        return;
+
+    if (isInWindow) {
+        if (m_rootLayerAttachment != RootLayerUnattached)
+            return;
+
+        RootLayerAttachment attachment = isMainFrame() ? RootLayerAttachedViaChromeClient : RootLayerAttachedViaEnclosingFrame;
+        attachRootLayer(attachment);
+    } else {
+        if (m_rootLayerAttachment == RootLayerUnattached)
+            return;
+
+        detachRootLayer();
+    }
+}
+
+void RenderLayerCompositor::clearBackingForLayerIncludingDescendants(RenderLayer* layer)
+{
+    if (!layer)
+        return;
+
+    if (layer->isComposited()) {
+        removeViewportConstrainedLayer(layer);
+        layer->clearBacking();
+    }
+    
+    for (RenderLayer* currLayer = layer->firstChild(); currLayer; currLayer = currLayer->nextSibling())
+        clearBackingForLayerIncludingDescendants(currLayer);
+}
+
+void RenderLayerCompositor::clearBackingForAllLayers()
+{
+    clearBackingForLayerIncludingDescendants(m_renderView->layer());
+}
+
+void RenderLayerCompositor::updateRootLayerPosition()
+{
+    if (m_rootContentLayer) {
+        const IntRect& documentRect = m_renderView->documentRect();
+        m_rootContentLayer->setSize(documentRect.size());
+        m_rootContentLayer->setPosition(documentRect.location());
+    }
+    if (m_clipLayer) {
+        FrameView* frameView = m_renderView->frameView();
+        m_clipLayer->setSize(frameView->unscaledVisibleContentSize());
+    }
+
+#if ENABLE(RUBBER_BANDING)
+    if (m_contentShadowLayer) {
+        m_contentShadowLayer->setPosition(m_rootContentLayer->position());
+
+        FloatSize rootContentLayerSize = m_rootContentLayer->size();
+        if (m_contentShadowLayer->size() != rootContentLayerSize) {
+            m_contentShadowLayer->setSize(rootContentLayerSize);
+            ScrollbarTheme::theme()->setUpContentShadowLayer(m_contentShadowLayer.get());
+        }
+    }
+
+    updateLayerForTopOverhangArea(m_layerForTopOverhangArea);
+    updateLayerForBottomOverhangArea(m_layerForBottomOverhangArea);
+#endif
+}
+
+bool RenderLayerCompositor::has3DContent() const
+{
+    return layerHas3DContent(rootRenderLayer());
+}
+
+bool RenderLayerCompositor::needsToBeComposited(const RenderLayer* layer, RenderLayer::ViewportConstrainedNotCompositedReason* viewportConstrainedNotCompositedReason) const
+{
+    if (!canBeComposited(layer))
+        return false;
+
+    return requiresCompositingLayer(layer, viewportConstrainedNotCompositedReason) || layer->mustCompositeForIndirectReasons() || (inCompositingMode() && layer->isRootLayer());
+}
+
+// Note: this specifies whether the RL needs a compositing layer for intrinsic reasons.
+// Use needsToBeComposited() to determine if a RL actually needs a compositing layer.
+// static
+bool RenderLayerCompositor::requiresCompositingLayer(const RenderLayer* layer, RenderLayer::ViewportConstrainedNotCompositedReason* viewportConstrainedNotCompositedReason) const
+{
+    RenderObject* renderer = layer->renderer();
+    // The compositing state of a reflection should match that of its reflected layer.
+    if (layer->isReflection()) {
+        renderer = renderer->parent(); // The RenderReplica's parent is the object being reflected.
+        layer = toRenderLayerModelObject(renderer)->layer();
+    }
+    // The root layer always has a compositing layer, but it may not have backing.
+    return requiresCompositingForTransform(renderer)
+        || requiresCompositingForVideo(renderer)
+        || requiresCompositingForCanvas(renderer)
+        || requiresCompositingForPlugin(renderer)
+        || requiresCompositingForFrame(renderer)
+        || (canRender3DTransforms() && renderer->style()->backfaceVisibility() == BackfaceVisibilityHidden)
+        || clipsCompositingDescendants(layer)
+        || requiresCompositingForAnimation(renderer)
+        || requiresCompositingForFilters(renderer)
+        || requiresCompositingForPosition(renderer, layer, viewportConstrainedNotCompositedReason)
+        || requiresCompositingForOverflowScrolling(layer)
+        || requiresCompositingForBlending(renderer);
+}
+
+bool RenderLayerCompositor::canBeComposited(const RenderLayer* layer) const
+{
+    // FIXME: We disable accelerated compositing for elements in a RenderFlowThread as it doesn't work properly.
+    // See http://webkit.org/b/84900 to re-enable it.
+    return m_hasAcceleratedCompositing && layer->isSelfPaintingLayer() && layer->renderer()->flowThreadState() == RenderObject::NotInsideFlowThread;
+}
+
+bool RenderLayerCompositor::requiresOwnBackingStore(const RenderLayer* layer, const RenderLayer* compositingAncestorLayer) const
+{
+    RenderObject* renderer = layer->renderer();
+    if (compositingAncestorLayer
+        && !(compositingAncestorLayer->backing()->graphicsLayer()->drawsContent()
+            || compositingAncestorLayer->backing()->paintsIntoWindow()
+            || compositingAncestorLayer->backing()->paintsIntoCompositedAncestor()))
+        return true;
+
+    if (layer->isRootLayer()
+        || layer->transform() // note: excludes perspective and transformStyle3D.
+        || requiresCompositingForVideo(renderer)
+        || requiresCompositingForCanvas(renderer)
+        || requiresCompositingForPlugin(renderer)
+        || requiresCompositingForFrame(renderer)
+        || (canRender3DTransforms() && renderer->style()->backfaceVisibility() == BackfaceVisibilityHidden)
+        || requiresCompositingForAnimation(renderer)
+        || requiresCompositingForFilters(renderer)
+        || requiresCompositingForBlending(renderer)
+        || requiresCompositingForPosition(renderer, layer)
+        || requiresCompositingForOverflowScrolling(layer)
+        || renderer->isTransparent()
+        || renderer->hasMask()
+        || renderer->hasReflection()
+        || renderer->hasFilter())
+        return true;
+        
+    
+    if (layer->mustCompositeForIndirectReasons()) {
+        RenderLayer::IndirectCompositingReason reason = layer->indirectCompositingReason();
+        return reason == RenderLayer::IndirectCompositingForOverlap
+            || reason == RenderLayer::IndirectCompositingForStacking
+            || reason == RenderLayer::IndirectCompositingForBackgroundLayer
+            || reason == RenderLayer::IndirectCompositingForGraphicalEffect
+            || reason == RenderLayer::IndirectCompositingForPreserve3D; // preserve-3d has to create backing store to ensure that 3d-transformed elements intersect.
+    }
+    return false;
+}
+
+CompositingReasons RenderLayerCompositor::reasonsForCompositing(const RenderLayer* layer) const
+{
+    CompositingReasons reasons = CompositingReasonNone;
+
+    if (!layer || !layer->isComposited())
+        return reasons;
+
+    RenderObject* renderer = layer->renderer();
+    if (layer->isReflection()) {
+        renderer = renderer->parent();
+        layer = toRenderLayerModelObject(renderer)->layer();
+    }
+
+    if (requiresCompositingForTransform(renderer))
+        reasons |= CompositingReason3DTransform;
+
+    if (requiresCompositingForVideo(renderer))
+        reasons |= CompositingReasonVideo;
+
+    if (requiresCompositingForCanvas(renderer))
+        reasons |= CompositingReasonCanvas;
+
+    if (requiresCompositingForPlugin(renderer))
+        reasons |= CompositingReasonPlugin;
+
+    if (requiresCompositingForFrame(renderer))
+        reasons |= CompositingReasonIFrame;
+    
+    if ((canRender3DTransforms() && renderer->style()->backfaceVisibility() == BackfaceVisibilityHidden))
+        reasons |= CompositingReasonBackfaceVisibilityHidden;
+
+    if (clipsCompositingDescendants(layer))
+        reasons |= CompositingReasonClipsCompositingDescendants;
+
+    if (requiresCompositingForAnimation(renderer))
+        reasons |= CompositingReasonAnimation;
+
+    if (requiresCompositingForFilters(renderer))
+        reasons |= CompositingReasonFilters;
+
+    if (requiresCompositingForPosition(renderer, layer))
+        reasons |= renderer->style()->position() == FixedPosition ? CompositingReasonPositionFixed : CompositingReasonPositionSticky;
+
+    if (requiresCompositingForOverflowScrolling(layer))
+        reasons |= CompositingReasonOverflowScrollingTouch;
+
+    if (layer->indirectCompositingReason() == RenderLayer::IndirectCompositingForStacking)
+        reasons |= CompositingReasonStacking;
+    else if (layer->indirectCompositingReason() == RenderLayer::IndirectCompositingForOverlap)
+        reasons |= CompositingReasonOverlap;
+    else if (layer->indirectCompositingReason() == RenderLayer::IndirectCompositingForBackgroundLayer)
+        reasons |= CompositingReasonNegativeZIndexChildren;
+    else if (layer->indirectCompositingReason() == RenderLayer::IndirectCompositingForGraphicalEffect) {
+        if (layer->transform())
+            reasons |= CompositingReasonTransformWithCompositedDescendants;
+
+        if (renderer->isTransparent())
+            reasons |= CompositingReasonOpacityWithCompositedDescendants;
+
+        if (renderer->hasMask())
+            reasons |= CompositingReasonMaskWithCompositedDescendants;
+
+        if (renderer->hasReflection())
+            reasons |= CompositingReasonReflectionWithCompositedDescendants;
+
+        if (renderer->hasFilter())
+            reasons |= CompositingReasonFilterWithCompositedDescendants;
+            
+        if (renderer->hasBlendMode())
+            reasons |= CompositingReasonBlendingWithCompositedDescendants;
+    } else if (layer->indirectCompositingReason() == RenderLayer::IndirectCompositingForPerspective)
+        reasons |= CompositingReasonPerspective;
+    else if (layer->indirectCompositingReason() == RenderLayer::IndirectCompositingForPreserve3D)
+        reasons |= CompositingReasonPreserve3D;
+
+    if (inCompositingMode() && layer->isRootLayer())
+        reasons |= CompositingReasonRoot;
+
+    return reasons;
+}
+
+#if !LOG_DISABLED
+const char* RenderLayerCompositor::logReasonsForCompositing(const RenderLayer* layer)
+{
+    CompositingReasons reasons = reasonsForCompositing(layer);
+
+    if (reasons & CompositingReason3DTransform)
+        return "3D transform";
+
+    if (reasons & CompositingReasonVideo)
+        return "video";
+
+    if (reasons & CompositingReasonCanvas)
+        return "canvas";
+
+    if (reasons & CompositingReasonPlugin)
+        return "plugin";
+
+    if (reasons & CompositingReasonIFrame)
+        return "iframe";
+    
+    if (reasons & CompositingReasonBackfaceVisibilityHidden)
+        return "backface-visibility: hidden";
+
+    if (reasons & CompositingReasonClipsCompositingDescendants)
+        return "clips compositing descendants";
+
+    if (reasons & CompositingReasonAnimation)
+        return "animation";
+
+    if (reasons & CompositingReasonFilters)
+        return "filters";
+
+    if (reasons & CompositingReasonPositionFixed)
+        return "position: fixed";
+
+    if (reasons & CompositingReasonPositionSticky)
+        return "position: sticky";
+
+    if (reasons & CompositingReasonOverflowScrollingTouch)
+        return "-webkit-overflow-scrolling: touch";
+
+    if (reasons & CompositingReasonStacking)
+        return "stacking";
+
+    if (reasons & CompositingReasonOverlap)
+        return "overlap";
+
+    if (reasons & CompositingReasonNegativeZIndexChildren)
+        return "negative z-index children";
+
+    if (reasons & CompositingReasonTransformWithCompositedDescendants)
+        return "transform with composited descendants";
+
+    if (reasons & CompositingReasonOpacityWithCompositedDescendants)
+        return "opacity with composited descendants";
+
+    if (reasons & CompositingReasonMaskWithCompositedDescendants)
+        return "mask with composited descendants";
+
+    if (reasons & CompositingReasonReflectionWithCompositedDescendants)
+        return "reflection with composited descendants";
+
+    if (reasons & CompositingReasonFilterWithCompositedDescendants)
+        return "filter with composited descendants";
+            
+    if (reasons & CompositingReasonBlendingWithCompositedDescendants)
+        return "blending with composited descendants";
+
+    if (reasons & CompositingReasonPerspective)
+        return "perspective";
+
+    if (reasons & CompositingReasonPreserve3D)
+        return "preserve-3d";
+
+    if (reasons & CompositingReasonRoot)
+        return "root";
+
+    return "";
+}
+#endif
+
+// Return true if the given layer has some ancestor in the RenderLayer hierarchy that clips,
+// up to the enclosing compositing ancestor. This is required because compositing layers are parented
+// according to the z-order hierarchy, yet clipping goes down the renderer hierarchy.
+// Thus, a RenderLayer can be clipped by a RenderLayer that is an ancestor in the renderer hierarchy,
+// but a sibling in the z-order hierarchy.
+bool RenderLayerCompositor::clippedByAncestor(RenderLayer* layer) const
+{
+    if (!layer->isComposited() || !layer->parent())
+        return false;
+
+    RenderLayer* compositingAncestor = layer->ancestorCompositingLayer();
+    if (!compositingAncestor)
+        return false;
+
+    // If the compositingAncestor clips, that will be taken care of by clipsCompositingDescendants(),
+    // so we only care about clipping between its first child that is our ancestor (the computeClipRoot),
+    // and layer.
+    RenderLayer* computeClipRoot = 0;
+    RenderLayer* curr = layer;
+    while (curr) {
+        RenderLayer* next = curr->parent();
+        if (next == compositingAncestor) {
+            computeClipRoot = curr;
+            break;
+        }
+        curr = next;
+    }
+    
+    if (!computeClipRoot || computeClipRoot == layer)
+        return false;
+
+    return layer->backgroundClipRect(RenderLayer::ClipRectsContext(computeClipRoot, 0, TemporaryClipRects)).rect() != PaintInfo::infiniteRect(); // FIXME: Incorrect for CSS regions.
+}
+
+// Return true if the given layer is a stacking context and has compositing child
+// layers that it needs to clip. In this case we insert a clipping GraphicsLayer
+// into the hierarchy between this layer and its children in the z-order hierarchy.
+bool RenderLayerCompositor::clipsCompositingDescendants(const RenderLayer* layer) const
+{
+    return layer->hasCompositingDescendant() && layer->renderer()->hasClipOrOverflowClip();
+}
+
+bool RenderLayerCompositor::requiresCompositingForScrollableFrame() const
+{
+    // Need this done first to determine overflow.
+    ASSERT(!m_renderView->needsLayout());
+    if (isMainFrame())
+        return false;
+
+    if (!(m_compositingTriggers & ChromeClient::ScrollableInnerFrameTrigger))
+        return false;
+
+    FrameView* frameView = m_renderView->frameView();
+    return frameView->isScrollable();
+}
+
+bool RenderLayerCompositor::requiresCompositingForTransform(RenderObject* renderer) const
+{
+    if (!(m_compositingTriggers & ChromeClient::ThreeDTransformTrigger))
+        return false;
+
+    RenderStyle* style = renderer->style();
+    // Note that we ask the renderer if it has a transform, because the style may have transforms,
+    // but the renderer may be an inline that doesn't suppport them.
+    return renderer->hasTransform() && style->transform().has3DOperation();
+}
+
+bool RenderLayerCompositor::requiresCompositingForVideo(RenderObject* renderer) const
+{
+    if (!(m_compositingTriggers & ChromeClient::VideoTrigger))
+        return false;
+
+    if (renderer->isVideo()) {
+        RenderVideo* video = toRenderVideo(renderer);
+        return video->shouldDisplayVideo() && canAccelerateVideoRendering(video);
+    }
+    return false;
+}
+
+bool RenderLayerCompositor::requiresCompositingForCanvas(RenderObject* renderer) const
+{
+    if (!(m_compositingTriggers & ChromeClient::CanvasTrigger))
+        return false;
+
+    if (renderer->isCanvas()) {
+        HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(renderer->node());
+#if USE(COMPOSITING_FOR_SMALL_CANVASES)
+        bool isCanvasLargeEnoughToForceCompositing = true;
+#else
+        bool isCanvasLargeEnoughToForceCompositing = canvas->size().area() >= canvasAreaThresholdRequiringCompositing;
+#endif
+        return canvas->renderingContext() && canvas->renderingContext()->isAccelerated() && (canvas->renderingContext()->is3d() || isCanvasLargeEnoughToForceCompositing);
+    }
+    return false;
+}
+
+bool RenderLayerCompositor::requiresCompositingForPlugin(RenderObject* renderer) const
+{
+    if (!(m_compositingTriggers & ChromeClient::PluginTrigger))
+        return false;
+
+    bool composite = renderer->isEmbeddedObject() && toRenderEmbeddedObject(renderer)->allowsAcceleratedCompositing();
+    if (!composite)
+        return false;
+
+    m_reevaluateCompositingAfterLayout = true;
+    
+    RenderWidget* pluginRenderer = toRenderWidget(renderer);
+    // If we can't reliably know the size of the plugin yet, don't change compositing state.
+    if (pluginRenderer->needsLayout())
+        return pluginRenderer->hasLayer() && pluginRenderer->layer()->isComposited();
+
+    // Don't go into compositing mode if height or width are zero, or size is 1x1.
+    IntRect contentBox = pixelSnappedIntRect(pluginRenderer->contentBoxRect());
+    return contentBox.height() * contentBox.width() > 1;
+}
+
+bool RenderLayerCompositor::requiresCompositingForFrame(RenderObject* renderer) const
+{
+    if (!renderer->isRenderPart())
+        return false;
+    
+    RenderPart* frameRenderer = toRenderPart(renderer);
+
+    if (!frameRenderer->requiresAcceleratedCompositing())
+        return false;
+
+    m_reevaluateCompositingAfterLayout = true;
+
+    RenderLayerCompositor* innerCompositor = frameContentsCompositor(frameRenderer);
+    if (!innerCompositor)
+        return false;
+
+    // If we can't reliably know the size of the iframe yet, don't change compositing state.
+    if (renderer->needsLayout())
+        return frameRenderer->hasLayer() && frameRenderer->layer()->isComposited();
+    
+    // Don't go into compositing mode if height or width are zero.
+    IntRect contentBox = pixelSnappedIntRect(frameRenderer->contentBoxRect());
+    return contentBox.height() * contentBox.width() > 0;
+}
+
+bool RenderLayerCompositor::requiresCompositingForAnimation(RenderObject* renderer) const
+{
+    if (!(m_compositingTriggers & ChromeClient::AnimationTrigger))
+        return false;
+
+    if (AnimationController* animController = renderer->animation()) {
+        return (animController->isRunningAnimationOnRenderer(renderer, CSSPropertyOpacity) && inCompositingMode())
+            // <rdar://problem/10907251> - WebKit2 doesn't support CA animations of CI filters on Lion and below
+            || animController->isRunningAnimationOnRenderer(renderer, CSSPropertyWebkitFilter)
+            || animController->isRunningAnimationOnRenderer(renderer, CSSPropertyWebkitTransform);
+    }
+    return false;
+}
+
+bool RenderLayerCompositor::requiresCompositingForIndirectReason(RenderObject* renderer, bool hasCompositedDescendants, bool has3DTransformedDescendants, RenderLayer::IndirectCompositingReason& reason) const
+{
+    RenderLayer* layer = toRenderBoxModelObject(renderer)->layer();
+
+    // When a layer has composited descendants, some effects, like 2d transforms, filters, masks etc must be implemented
+    // via compositing so that they also apply to those composited descdendants.
+    if (hasCompositedDescendants && (layer->transform() || renderer->createsGroup() || renderer->hasReflection())) {
+        reason = RenderLayer::IndirectCompositingForGraphicalEffect;
+        return true;
+    }
+
+    // A layer with preserve-3d or perspective only needs to be composited if there are descendant layers that
+    // will be affected by the preserve-3d or perspective.
+    if (has3DTransformedDescendants) {
+        if (renderer->style()->transformStyle3D() == TransformStyle3DPreserve3D) {
+            reason = RenderLayer::IndirectCompositingForPreserve3D;
+            return true;
+        }
+    
+        if (renderer->style()->hasPerspective()) {
+            reason = RenderLayer::IndirectCompositingForPerspective;
+            return true;
+        }
+    }
+
+    reason = RenderLayer::NoIndirectCompositingReason;
+    return false;
+}
+
+bool RenderLayerCompositor::requiresCompositingForFilters(RenderObject* renderer) const
+{
+    if (!(m_compositingTriggers & ChromeClient::FilterTrigger))
+        return false;
+
+    return renderer->hasFilter();
+}
+
+bool RenderLayerCompositor::requiresCompositingForBlending(RenderObject* renderer) const
+{
+#if ENABLE(CSS_COMPOSITING)
+    return renderer->hasBlendMode();
+#else
+    UNUSED_PARAM(renderer);
+    return false;
+#endif
+}
+
+bool RenderLayerCompositor::requiresCompositingForPosition(RenderObject* renderer, const RenderLayer* layer, RenderLayer::ViewportConstrainedNotCompositedReason* viewportConstrainedNotCompositedReason) const
+{
+    // position:fixed elements that create their own stacking context (e.g. have an explicit z-index,
+    // opacity, transform) can get their own composited layer. A stacking context is required otherwise
+    // z-index and clipping will be broken.
+    if (!renderer->isPositioned())
+        return false;
+    
+    EPosition position = renderer->style()->position();
+    bool isFixed = renderer->isOutOfFlowPositioned() && position == FixedPosition;
+    if (isFixed && !layer->isStackingContainer())
+        return false;
+    
+    bool isSticky = renderer->isInFlowPositioned() && position == StickyPosition;
+    if (!isFixed && !isSticky)
+        return false;
+
+    // FIXME: acceleratedCompositingForFixedPositionEnabled should probably be renamed acceleratedCompositingForViewportConstrainedPositionEnabled().
+    if (Settings* settings = m_renderView->document()->settings()) {
+        if (!settings->acceleratedCompositingForFixedPositionEnabled())
+            return false;
+    }
+
+    if (isSticky)
+        return true;
+
+    RenderObject* container = renderer->container();
+    // If the renderer is not hooked up yet then we have to wait until it is.
+    if (!container) {
+        m_reevaluateCompositingAfterLayout = true;
+        return false;
+    }
+
+    // Don't promote fixed position elements that are descendants of a non-view container, e.g. transformed elements.
+    // They will stay fixed wrt the container rather than the enclosing frame.
+    if (container != m_renderView) {
+        if (viewportConstrainedNotCompositedReason)
+            *viewportConstrainedNotCompositedReason = RenderLayer::NotCompositedForNonViewContainer;
+        return false;
+    }
+    
+    // If the fixed-position element does not have any scrollable ancestor between it and
+    // its container, then we do not need to spend compositor resources for it. Start by
+    // assuming we can opt-out (i.e. no scrollable ancestor), and refine the answer below.
+    bool hasScrollableAncestor = false;
+
+    // The FrameView has the scrollbars associated with the top level viewport, so we have to
+    // check the FrameView in addition to the hierarchy of ancestors.
+    FrameView* frameView = m_renderView->frameView();
+    if (frameView && frameView->isScrollable())
+        hasScrollableAncestor = true;
+
+    RenderLayer* ancestor = layer->parent();
+    while (ancestor && !hasScrollableAncestor) {
+        if (frameView->containsScrollableArea(ancestor))
+            hasScrollableAncestor = true;
+        if (ancestor->renderer() == m_renderView)
+            break;
+        ancestor = ancestor->parent();
+    }
+
+    if (!hasScrollableAncestor) {
+        if (viewportConstrainedNotCompositedReason)
+            *viewportConstrainedNotCompositedReason = RenderLayer::NotCompositedForUnscrollableAncestors;
+        return false;
+    }
+
+    // Subsequent tests depend on layout. If we can't tell now, just keep things the way they are until layout is done.
+    if (!m_inPostLayoutUpdate) {
+        m_reevaluateCompositingAfterLayout = true;
+        return layer->isComposited();
+    }
+
+    bool paintsContent = layer->isVisuallyNonEmpty() || layer->hasVisibleDescendant();
+    if (!paintsContent) {
+        if (viewportConstrainedNotCompositedReason)
+            *viewportConstrainedNotCompositedReason = RenderLayer::NotCompositedForNoVisibleContent;
+        return false;
+    }
+
+    // Fixed position elements that are invisible in the current view don't get their own layer.
+    if (FrameView* frameView = m_renderView->frameView()) {
+        LayoutRect viewBounds = frameView->viewportConstrainedVisibleContentRect();
+        LayoutRect layerBounds = layer->calculateLayerBounds(rootRenderLayer(), 0, RenderLayer::DefaultCalculateLayerBoundsFlags
+            | RenderLayer::ExcludeHiddenDescendants | RenderLayer::DontConstrainForMask | RenderLayer::IncludeCompositedDescendants);
+        if (!viewBounds.intersects(enclosingIntRect(layerBounds))) {
+            if (viewportConstrainedNotCompositedReason)
+                *viewportConstrainedNotCompositedReason = RenderLayer::NotCompositedForBoundsOutOfView;
+            return false;
+        }
+    }
+    
+    return true;
+}
+
+bool RenderLayerCompositor::requiresCompositingForOverflowScrolling(const RenderLayer* layer) const
+{
+    return layer->needsCompositedScrolling();
+}
+
+bool RenderLayerCompositor::isRunningAcceleratedTransformAnimation(RenderObject* renderer) const
+{
+    if (!(m_compositingTriggers & ChromeClient::AnimationTrigger))
+        return false;
+
+    if (AnimationController* animController = renderer->animation())
+        return animController->isRunningAnimationOnRenderer(renderer, CSSPropertyWebkitTransform);
+
+    return false;
+}
+
+// If an element has negative z-index children, those children render in front of the 
+// layer background, so we need an extra 'contents' layer for the foreground of the layer
+// object.
+bool RenderLayerCompositor::needsContentsCompositingLayer(const RenderLayer* layer) const
+{
+    return layer->hasNegativeZOrderList();
+}
+
+static void paintScrollbar(Scrollbar* scrollbar, GraphicsContext& context, const IntRect& clip)
+{
+    if (!scrollbar)
+        return;
+
+    context.save();
+    const IntRect& scrollbarRect = scrollbar->frameRect();
+    context.translate(-scrollbarRect.x(), -scrollbarRect.y());
+    IntRect transformedClip = clip;
+    transformedClip.moveBy(scrollbarRect.location());
+    scrollbar->paint(&context, transformedClip);
+    context.restore();
+}
+
+void RenderLayerCompositor::paintContents(const GraphicsLayer* graphicsLayer, GraphicsContext& context, GraphicsLayerPaintingPhase, const IntRect& clip)
+{
+    if (graphicsLayer == layerForHorizontalScrollbar())
+        paintScrollbar(m_renderView->frameView()->horizontalScrollbar(), context, clip);
+    else if (graphicsLayer == layerForVerticalScrollbar())
+        paintScrollbar(m_renderView->frameView()->verticalScrollbar(), context, clip);
+    else if (graphicsLayer == layerForScrollCorner()) {
+        const IntRect& scrollCorner = m_renderView->frameView()->scrollCornerRect();
+        context.save();
+        context.translate(-scrollCorner.x(), -scrollCorner.y());
+        IntRect transformedClip = clip;
+        transformedClip.moveBy(scrollCorner.location());
+        m_renderView->frameView()->paintScrollCorner(&context, transformedClip);
+        context.restore();
+#if ENABLE(RUBBER_BANDING)
+    } else if (graphicsLayer == layerForOverhangAreas()) {
+        ScrollView* view = m_renderView->frameView();
+        view->calculateAndPaintOverhangAreas(&context, clip);
+#endif
+    }
+}
+
+bool RenderLayerCompositor::supportsFixedRootBackgroundCompositing() const
+{
+    return false;  // FIXME: Return true if this is supported when implemented.
+}
+
+bool RenderLayerCompositor::needsFixedRootBackgroundLayer(const RenderLayer* layer) const
+{
+    if (layer != m_renderView->layer())
+        return false;
+
+    return supportsFixedRootBackgroundCompositing() && m_renderView->rootBackgroundIsEntirelyFixed();
+}
+
+GraphicsLayer* RenderLayerCompositor::fixedRootBackgroundLayer() const
+{
+    // Get the fixed root background from the RenderView layer's backing.
+    RenderLayer* viewLayer = m_renderView->layer();
+    if (!viewLayer)
+        return 0;
+    
+    if (viewLayer->isComposited() && viewLayer->backing()->backgroundLayerPaintsFixedRootBackground())
+        return viewLayer->backing()->backgroundLayer();
+
+    return 0;
+}
+
+static void resetTrackedRepaintRectsRecursive(GraphicsLayer* graphicsLayer)
+{
+    if (!graphicsLayer)
+        return;
+
+    graphicsLayer->resetTrackedRepaints();
+
+    for (size_t i = 0; i < graphicsLayer->children().size(); ++i)
+        resetTrackedRepaintRectsRecursive(graphicsLayer->children()[i]);
+
+    if (GraphicsLayer* replicaLayer = graphicsLayer->replicaLayer())
+        resetTrackedRepaintRectsRecursive(replicaLayer);
+
+    if (GraphicsLayer* maskLayer = graphicsLayer->maskLayer())
+        resetTrackedRepaintRectsRecursive(maskLayer);
+}
+
+void RenderLayerCompositor::resetTrackedRepaintRects()
+{
+    if (GraphicsLayer* rootLayer = rootGraphicsLayer())
+        resetTrackedRepaintRectsRecursive(rootLayer);
+}
+
+void RenderLayerCompositor::setTracksRepaints(bool tracksRepaints)
+{
+    m_isTrackingRepaints = tracksRepaints;
+}
+
+bool RenderLayerCompositor::isTrackingRepaints() const
+{
+    return m_isTrackingRepaints;
+}
+
+float RenderLayerCompositor::deviceScaleFactor() const
+{
+    Page* page = this->page();
+    return page ? page->deviceScaleFactor() : 1;
+}
+
+float RenderLayerCompositor::pageScaleFactor() const
+{
+    Page* page = this->page();
+    return page ? page->pageScaleFactor() : 1;
+}
+
+void RenderLayerCompositor::didCommitChangesForLayer(const GraphicsLayer*) const
+{
+    // Nothing to do here yet.
+}
+
+bool RenderLayerCompositor::keepLayersPixelAligned() const
+{
+    // When scaling, attempt to align compositing layers to pixel boundaries.
+    return true;
+}
+
+static bool shouldCompositeOverflowControls(FrameView* view)
+{
+    if (Page* page = view->frame()->page()) {
+        if (ScrollingCoordinator* scrollingCoordinator = page->scrollingCoordinator())
+            if (scrollingCoordinator->coordinatesScrollingForFrameView(view))
+                return true;
+    }
+
+    return true;
+}
+
+bool RenderLayerCompositor::requiresHorizontalScrollbarLayer() const
+{
+    FrameView* view = m_renderView->frameView();
+    return shouldCompositeOverflowControls(view) && view->horizontalScrollbar();
+}
+
+bool RenderLayerCompositor::requiresVerticalScrollbarLayer() const
+{
+    FrameView* view = m_renderView->frameView();
+    return shouldCompositeOverflowControls(view) && view->verticalScrollbar();
+}
+
+bool RenderLayerCompositor::requiresScrollCornerLayer() const
+{
+    FrameView* view = m_renderView->frameView();
+    return shouldCompositeOverflowControls(view) && view->isScrollCornerVisible();
+}
+
+#if ENABLE(RUBBER_BANDING)
+bool RenderLayerCompositor::requiresOverhangAreasLayer() const
+{
+    // We don't want a layer if this is a subframe.
+    if (!isMainFrame())
+        return false;
+
+    // We do want a layer if we have a scrolling coordinator and can scroll.
+    if (scrollingCoordinator() && m_renderView->frameView()->hasOpaqueBackground() && !m_renderView->frameView()->prohibitsScrolling())
+        return true;
+
+    // Chromium always wants a layer.
+    return true;
+}
+
+bool RenderLayerCompositor::requiresContentShadowLayer() const
+{
+    // We don't want a layer if this is a subframe.
+    if (!isMainFrame())
+        return false;
+
+    return false;
+}
+
+GraphicsLayer* RenderLayerCompositor::updateLayerForTopOverhangArea(bool wantsLayer)
+{
+    if (!isMainFrame())
+        return 0;
+
+    if (!wantsLayer) {
+        if (m_layerForTopOverhangArea) {
+            m_layerForTopOverhangArea->removeFromParent();
+            m_layerForTopOverhangArea = nullptr;
+        }
+        return 0;
+    }
+
+    if (!m_layerForTopOverhangArea) {
+        m_layerForTopOverhangArea = GraphicsLayer::create(graphicsLayerFactory(), this);
+#ifndef NDEBUG
+        m_layerForTopOverhangArea->setName("top overhang area");
+#endif
+        m_scrollLayer->addChildBelow(m_layerForTopOverhangArea.get(), m_rootContentLayer.get());
+    }
+
+    return m_layerForTopOverhangArea.get();
+}
+
+GraphicsLayer* RenderLayerCompositor::updateLayerForBottomOverhangArea(bool wantsLayer)
+{
+    if (!isMainFrame())
+        return 0;
+
+    if (!wantsLayer) {
+        if (m_layerForBottomOverhangArea) {
+            m_layerForBottomOverhangArea->removeFromParent();
+            m_layerForBottomOverhangArea = nullptr;
+        }
+        return 0;
+    }
+
+    if (!m_layerForBottomOverhangArea) {
+        m_layerForBottomOverhangArea = GraphicsLayer::create(graphicsLayerFactory(), this);
+#ifndef NDEBUG
+        m_layerForBottomOverhangArea->setName("bottom overhang area");
+#endif
+        m_scrollLayer->addChildBelow(m_layerForBottomOverhangArea.get(), m_rootContentLayer.get());
+    }
+
+    m_layerForBottomOverhangArea->setPosition(FloatPoint(0, m_rootContentLayer->size().height()));
+    return m_layerForBottomOverhangArea.get();
+}
+
+#endif
+
+bool RenderLayerCompositor::viewHasTransparentBackground(Color* backgroundColor) const
+{
+    FrameView* frameView = m_renderView->frameView();
+    if (frameView->isTransparent()) {
+        if (backgroundColor)
+            *backgroundColor = Color(); // Return an invalid color.
+        return true;
+    }
+
+    Color documentBackgroundColor = frameView->documentBackgroundColor();
+    if (!documentBackgroundColor.isValid())
+        documentBackgroundColor = Color::white;
+
+    if (backgroundColor)
+        *backgroundColor = documentBackgroundColor;
+        
+    return documentBackgroundColor.hasAlpha();
+}
+
+void RenderLayerCompositor::updateOverflowControlsLayers()
+{
+#if ENABLE(RUBBER_BANDING)
+    if (requiresOverhangAreasLayer()) {
+        if (!m_layerForOverhangAreas) {
+            m_layerForOverhangAreas = GraphicsLayer::create(graphicsLayerFactory(), this);
+#ifndef NDEBUG
+            m_layerForOverhangAreas->setName("overhang areas");
+#endif
+            m_layerForOverhangAreas->setDrawsContent(false);
+            m_layerForOverhangAreas->setSize(m_renderView->frameView()->frameRect().size());
+
+            ScrollbarTheme::theme()->setUpOverhangAreasLayerContents(m_layerForOverhangAreas.get(), this->page()->chrome()->client()->underlayColor());
+
+            // We want the overhang areas layer to be positioned below the frame contents,
+            // so insert it below the clip layer.
+            m_overflowControlsHostLayer->addChildBelow(m_layerForOverhangAreas.get(), m_clipLayer.get());
+        }
+    } else if (m_layerForOverhangAreas) {
+        m_layerForOverhangAreas->removeFromParent();
+        m_layerForOverhangAreas = nullptr;
+    }
+
+    if (requiresContentShadowLayer()) {
+        if (!m_contentShadowLayer) {
+            m_contentShadowLayer = GraphicsLayer::create(graphicsLayerFactory(), this);
+#ifndef NDEBUG
+            m_contentShadowLayer->setName("content shadow");
+#endif
+            m_contentShadowLayer->setSize(m_rootContentLayer->size());
+            m_contentShadowLayer->setPosition(m_rootContentLayer->position());
+            ScrollbarTheme::theme()->setUpContentShadowLayer(m_contentShadowLayer.get());
+
+            m_scrollLayer->addChildBelow(m_contentShadowLayer.get(), m_rootContentLayer.get());
+        }
+    } else if (m_contentShadowLayer) {
+        m_contentShadowLayer->removeFromParent();
+        m_contentShadowLayer = nullptr;
+    }
+#endif
+
+    if (requiresHorizontalScrollbarLayer()) {
+        if (!m_layerForHorizontalScrollbar) {
+            m_layerForHorizontalScrollbar = GraphicsLayer::create(graphicsLayerFactory(), this);
+            m_layerForHorizontalScrollbar->setShowDebugBorder(m_showDebugBorders);
+#ifndef NDEBUG
+            m_layerForHorizontalScrollbar->setName("horizontal scrollbar");
+#endif
+            m_overflowControlsHostLayer->addChild(m_layerForHorizontalScrollbar.get());
+
+            if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
+                scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_renderView->frameView(), HorizontalScrollbar);
+        }
+    } else if (m_layerForHorizontalScrollbar) {
+        m_layerForHorizontalScrollbar->removeFromParent();
+        m_layerForHorizontalScrollbar = nullptr;
+
+        if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
+            scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_renderView->frameView(), HorizontalScrollbar);
+    }
+
+    if (requiresVerticalScrollbarLayer()) {
+        if (!m_layerForVerticalScrollbar) {
+            m_layerForVerticalScrollbar = GraphicsLayer::create(graphicsLayerFactory(), this);
+            m_layerForVerticalScrollbar->setShowDebugBorder(m_showDebugBorders);
+#ifndef NDEBUG
+            m_layerForVerticalScrollbar->setName("vertical scrollbar");
+#endif
+            m_overflowControlsHostLayer->addChild(m_layerForVerticalScrollbar.get());
+
+            if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
+                scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_renderView->frameView(), VerticalScrollbar);
+        }
+    } else if (m_layerForVerticalScrollbar) {
+        m_layerForVerticalScrollbar->removeFromParent();
+        m_layerForVerticalScrollbar = nullptr;
+
+        if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
+            scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_renderView->frameView(), VerticalScrollbar);
+    }
+
+    if (requiresScrollCornerLayer()) {
+        if (!m_layerForScrollCorner) {
+            m_layerForScrollCorner = GraphicsLayer::create(graphicsLayerFactory(), this);
+            m_layerForScrollCorner->setShowDebugBorder(m_showDebugBorders);
+#ifndef NDEBUG
+            m_layerForScrollCorner->setName("scroll corner");
+#endif
+            m_overflowControlsHostLayer->addChild(m_layerForScrollCorner.get());
+        }
+    } else if (m_layerForScrollCorner) {
+        m_layerForScrollCorner->removeFromParent();
+        m_layerForScrollCorner = nullptr;
+    }
+
+    m_renderView->frameView()->positionScrollbarLayers();
+}
+
+void RenderLayerCompositor::ensureRootLayer()
+{
+    RootLayerAttachment expectedAttachment = isMainFrame() ? RootLayerAttachedViaChromeClient : RootLayerAttachedViaEnclosingFrame;
+    if (expectedAttachment == m_rootLayerAttachment)
+         return;
+
+    if (!m_rootContentLayer) {
+        m_rootContentLayer = GraphicsLayer::create(graphicsLayerFactory(), this);
+#ifndef NDEBUG
+        m_rootContentLayer->setName("content root");
+#endif
+        IntRect overflowRect = m_renderView->pixelSnappedLayoutOverflowRect();
+        m_rootContentLayer->setSize(FloatSize(overflowRect.maxX(), overflowRect.maxY()));
+        m_rootContentLayer->setPosition(FloatPoint());
+
+        // Need to clip to prevent transformed content showing outside this frame
+        m_rootContentLayer->setMasksToBounds(true);
+    }
+
+    if (!m_overflowControlsHostLayer) {
+        ASSERT(!m_scrollLayer);
+        ASSERT(!m_clipLayer);
+
+        // Create a layer to host the clipping layer and the overflow controls layers.
+        m_overflowControlsHostLayer = GraphicsLayer::create(graphicsLayerFactory(), this);
+#ifndef NDEBUG
+        m_overflowControlsHostLayer->setName("overflow controls host");
+#endif
+
+        // Create a clipping layer if this is an iframe
+        m_clipLayer = GraphicsLayer::create(graphicsLayerFactory(), this);
+#ifndef NDEBUG
+        m_clipLayer->setName("frame clipping");
+#endif
+        m_clipLayer->setMasksToBounds(true);
+
+        m_scrollLayer = GraphicsLayer::create(graphicsLayerFactory(), this);
+#ifndef NDEBUG
+        m_scrollLayer->setName("frame scrolling");
+#endif
+        if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
+            scrollingCoordinator->setLayerIsContainerForFixedPositionLayers(m_scrollLayer.get(), true);
+
+        // Hook them up
+        m_overflowControlsHostLayer->addChild(m_clipLayer.get());
+        m_clipLayer->addChild(m_scrollLayer.get());
+        m_scrollLayer->addChild(m_rootContentLayer.get());
+
+        frameViewDidChangeSize();
+        frameViewDidScroll();
+    }
+
+    // Check to see if we have to change the attachment
+    if (m_rootLayerAttachment != RootLayerUnattached)
+        detachRootLayer();
+
+    attachRootLayer(expectedAttachment);
+}
+
+void RenderLayerCompositor::destroyRootLayer()
+{
+    if (!m_rootContentLayer)
+        return;
+
+    detachRootLayer();
+
+#if ENABLE(RUBBER_BANDING)
+    if (m_layerForOverhangAreas) {
+        m_layerForOverhangAreas->removeFromParent();
+        m_layerForOverhangAreas = nullptr;
+    }
+#endif
+
+    if (m_layerForHorizontalScrollbar) {
+        m_layerForHorizontalScrollbar->removeFromParent();
+        m_layerForHorizontalScrollbar = nullptr;
+        if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
+            scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_renderView->frameView(), HorizontalScrollbar);
+        if (Scrollbar* horizontalScrollbar = m_renderView->frameView()->verticalScrollbar())
+            m_renderView->frameView()->invalidateScrollbar(horizontalScrollbar, IntRect(IntPoint(0, 0), horizontalScrollbar->frameRect().size()));
+    }
+
+    if (m_layerForVerticalScrollbar) {
+        m_layerForVerticalScrollbar->removeFromParent();
+        m_layerForVerticalScrollbar = nullptr;
+        if (ScrollingCoordinator* scrollingCoordinator = this->scrollingCoordinator())
+            scrollingCoordinator->scrollableAreaScrollbarLayerDidChange(m_renderView->frameView(), VerticalScrollbar);
+        if (Scrollbar* verticalScrollbar = m_renderView->frameView()->verticalScrollbar())
+            m_renderView->frameView()->invalidateScrollbar(verticalScrollbar, IntRect(IntPoint(0, 0), verticalScrollbar->frameRect().size()));
+    }
+
+    if (m_layerForScrollCorner) {
+        m_layerForScrollCorner = nullptr;
+        m_renderView->frameView()->invalidateScrollCorner(m_renderView->frameView()->scrollCornerRect());
+    }
+
+    if (m_overflowControlsHostLayer) {
+        m_overflowControlsHostLayer = nullptr;
+        m_clipLayer = nullptr;
+        m_scrollLayer = nullptr;
+    }
+    ASSERT(!m_scrollLayer);
+    m_rootContentLayer = nullptr;
+}
+
+void RenderLayerCompositor::attachRootLayer(RootLayerAttachment attachment)
+{
+    if (!m_rootContentLayer)
+        return;
+
+    switch (attachment) {
+        case RootLayerUnattached:
+            ASSERT_NOT_REACHED();
+            break;
+        case RootLayerAttachedViaChromeClient: {
+            Frame* frame = m_renderView->frameView()->frame();
+            Page* page = frame ? frame->page() : 0;
+            if (!page)
+                return;
+
+            page->chrome()->client()->attachRootGraphicsLayer(frame, rootGraphicsLayer());
+            break;
+        }
+        case RootLayerAttachedViaEnclosingFrame: {
+            // The layer will get hooked up via RenderLayerBacking::updateGraphicsLayerConfiguration()
+            // for the frame's renderer in the parent document.
+            m_renderView->document()->ownerElement()->scheduleSetNeedsStyleRecalc(SyntheticStyleChange);
+            break;
+        }
+    }
+
+    m_rootLayerAttachment = attachment;
+    rootLayerAttachmentChanged();
+}
+
+void RenderLayerCompositor::detachRootLayer()
+{
+    if (!m_rootContentLayer || m_rootLayerAttachment == RootLayerUnattached)
+        return;
+
+    switch (m_rootLayerAttachment) {
+    case RootLayerAttachedViaEnclosingFrame: {
+        // The layer will get unhooked up via RenderLayerBacking::updateGraphicsLayerConfiguration()
+        // for the frame's renderer in the parent document.
+        if (m_overflowControlsHostLayer)
+            m_overflowControlsHostLayer->removeFromParent();
+        else
+            m_rootContentLayer->removeFromParent();
+
+        if (HTMLFrameOwnerElement* ownerElement = m_renderView->document()->ownerElement())
+            ownerElement->scheduleSetNeedsStyleRecalc(SyntheticStyleChange);
+        break;
+    }
+    case RootLayerAttachedViaChromeClient: {
+        Frame* frame = m_renderView->frameView()->frame();
+        Page* page = frame ? frame->page() : 0;
+        if (!page)
+            return;
+
+        page->chrome()->client()->attachRootGraphicsLayer(frame, 0);
+    }
+    break;
+    case RootLayerUnattached:
+        break;
+    }
+
+    m_rootLayerAttachment = RootLayerUnattached;
+    rootLayerAttachmentChanged();
+}
+
+void RenderLayerCompositor::updateRootLayerAttachment()
+{
+    ensureRootLayer();
+}
+
+bool RenderLayerCompositor::isMainFrame() const
+{
+    return !m_renderView->document()->ownerElement();
+}
+
+void RenderLayerCompositor::rootLayerAttachmentChanged()
+{
+    // The attachment can affect whether the RenderView layer's paintsIntoWindow() behavior,
+    // so call updateGraphicsLayerGeometry() to udpate that.
+    RenderLayer* layer = m_renderView->layer();
+    if (RenderLayerBacking* backing = layer ? layer->backing() : 0)
+        backing->updateDrawsContent();
+}
+
+// IFrames are special, because we hook compositing layers together across iframe boundaries
+// when both parent and iframe content are composited. So when this frame becomes composited, we have
+// to use a synthetic style change to get the iframes into RenderLayers in order to allow them to composite.
+void RenderLayerCompositor::notifyIFramesOfCompositingChange()
+{
+    Frame* frame = m_renderView->frameView() ? m_renderView->frameView()->frame() : 0;
+    if (!frame)
+        return;
+
+    for (Frame* child = frame->tree()->firstChild(); child; child = child->tree()->traverseNext(frame)) {
+        if (child->document() && child->document()->ownerElement())
+            child->document()->ownerElement()->scheduleSetNeedsStyleRecalc(SyntheticStyleChange);
+    }
+    
+    // Compositing also affects the answer to RenderIFrame::requiresAcceleratedCompositing(), so 
+    // we need to schedule a style recalc in our parent document.
+    if (HTMLFrameOwnerElement* ownerElement = m_renderView->document()->ownerElement())
+        ownerElement->scheduleSetNeedsStyleRecalc(SyntheticStyleChange);
+}
+
+bool RenderLayerCompositor::layerHas3DContent(const RenderLayer* layer) const
+{
+    const RenderStyle* style = layer->renderer()->style();
+
+    if (style && 
+        (style->transformStyle3D() == TransformStyle3DPreserve3D ||
+         style->hasPerspective() ||
+         style->transform().has3DOperation()))
+        return true;
+
+    const_cast<RenderLayer*>(layer)->updateLayerListsIfNeeded();
+
+#if !ASSERT_DISABLED
+    LayerListMutationDetector mutationChecker(const_cast<RenderLayer*>(layer));
+#endif
+
+    if (layer->isStackingContainer()) {
+        if (Vector<RenderLayer*>* negZOrderList = layer->negZOrderList()) {
+            size_t listSize = negZOrderList->size();
+            for (size_t i = 0; i < listSize; ++i) {
+                RenderLayer* curLayer = negZOrderList->at(i);
+                if (layerHas3DContent(curLayer))
+                    return true;
+            }
+        }
+
+        if (Vector<RenderLayer*>* posZOrderList = layer->posZOrderList()) {
+            size_t listSize = posZOrderList->size();
+            for (size_t i = 0; i < listSize; ++i) {
+                RenderLayer* curLayer = posZOrderList->at(i);
+                if (layerHas3DContent(curLayer))
+                    return true;
+            }
+        }
+    }
+
+    if (Vector<RenderLayer*>* normalFlowList = layer->normalFlowList()) {
+        size_t listSize = normalFlowList->size();
+        for (size_t i = 0; i < listSize; ++i) {
+            RenderLayer* curLayer = normalFlowList->at(i);
+            if (layerHas3DContent(curLayer))
+                return true;
+        }
+    }
+    return false;
+}
+
+void RenderLayerCompositor::deviceOrPageScaleFactorChanged()
+{
+    // Start at the RenderView's layer, since that's where the scale is applied.
+    RenderLayer* viewLayer = m_renderView->layer();
+    if (!viewLayer->isComposited())
+        return;
+
+    if (GraphicsLayer* rootLayer = viewLayer->backing()->childForSuperlayers())
+        rootLayer->noteDeviceOrPageScaleFactorChangedIncludingDescendants();
+}
+
+static bool isRootmostFixedOrStickyLayer(RenderLayer* layer)
+{
+    if (layer->renderer()->isStickyPositioned())
+        return true;
+
+    if (layer->renderer()->style()->position() != FixedPosition)
+        return false;
+
+    for (RenderLayer* stackingContainer = layer->ancestorStackingContainer(); stackingContainer; stackingContainer = stackingContainer->ancestorStackingContainer()) {
+        if (stackingContainer->isComposited() && stackingContainer->renderer()->style()->position() == FixedPosition)
+            return false;
+    }
+
+    return true;
+}
+
+void RenderLayerCompositor::updateViewportConstraintStatus(RenderLayer* layer)
+{
+    if (isRootmostFixedOrStickyLayer(layer))
+        addViewportConstrainedLayer(layer);
+    else
+        removeViewportConstrainedLayer(layer);
+}
+
+void RenderLayerCompositor::addViewportConstrainedLayer(RenderLayer* layer)
+{
+    m_viewportConstrainedLayers.add(layer);
+}
+
+void RenderLayerCompositor::removeViewportConstrainedLayer(RenderLayer* layer)
+{
+    if (!m_viewportConstrainedLayers.contains(layer))
+        return;
+
+    m_viewportConstrainedLayers.remove(layer);
+}
+
+FixedPositionViewportConstraints RenderLayerCompositor::computeFixedViewportConstraints(RenderLayer* layer) const
+{
+    ASSERT(layer->isComposited());
+
+    FrameView* frameView = m_renderView->frameView();
+    LayoutRect viewportRect = frameView->viewportConstrainedVisibleContentRect();
+
+    FixedPositionViewportConstraints constraints;
+
+    GraphicsLayer* graphicsLayer = layer->backing()->graphicsLayer();
+
+    constraints.setLayerPositionAtLastLayout(graphicsLayer->position());
+    constraints.setViewportRectAtLastLayout(viewportRect);
+
+    RenderStyle* style = layer->renderer()->style();
+    if (!style->left().isAuto())
+        constraints.addAnchorEdge(ViewportConstraints::AnchorEdgeLeft);
+
+    if (!style->right().isAuto())
+        constraints.addAnchorEdge(ViewportConstraints::AnchorEdgeRight);
+
+    if (!style->top().isAuto())
+        constraints.addAnchorEdge(ViewportConstraints::AnchorEdgeTop);
+
+    if (!style->bottom().isAuto())
+        constraints.addAnchorEdge(ViewportConstraints::AnchorEdgeBottom);
+
+    // If left and right are auto, use left.
+    if (style->left().isAuto() && style->right().isAuto())
+        constraints.addAnchorEdge(ViewportConstraints::AnchorEdgeLeft);
+
+    // If top and bottom are auto, use top.
+    if (style->top().isAuto() && style->bottom().isAuto())
+        constraints.addAnchorEdge(ViewportConstraints::AnchorEdgeTop);
+        
+    return constraints;
+}
+
+StickyPositionViewportConstraints RenderLayerCompositor::computeStickyViewportConstraints(RenderLayer* layer) const
+{
+    ASSERT(layer->isComposited());
+
+    FrameView* frameView = m_renderView->frameView();
+    LayoutRect viewportRect = frameView->viewportConstrainedVisibleContentRect();
+
+    StickyPositionViewportConstraints constraints;
+
+    RenderBoxModelObject* renderer = toRenderBoxModelObject(layer->renderer());
+
+    renderer->computeStickyPositionConstraints(constraints, viewportRect);
+
+    GraphicsLayer* graphicsLayer = layer->backing()->graphicsLayer();
+
+    constraints.setLayerPositionAtLastLayout(graphicsLayer->position());
+    constraints.setStickyOffsetAtLastLayout(renderer->stickyPositionOffset());
+
+    return constraints;
+}
+
+ScrollingCoordinator* RenderLayerCompositor::scrollingCoordinator() const
+{
+    if (Page* page = this->page())
+        return page->scrollingCoordinator();
+
+    return 0;
+}
+
+GraphicsLayerFactory* RenderLayerCompositor::graphicsLayerFactory() const
+{
+    if (Page* page = this->page())
+        return page->chrome()->client()->graphicsLayerFactory();
+
+    return 0;
+}
+
+Page* RenderLayerCompositor::page() const
+{
+    if (Frame* frame = m_renderView->frameView()->frame())
+        return frame->page();
+    
+    return 0;
+}
+
+void RenderLayerCompositor::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, PlatformMemoryTypes::Rendering);
+    info.addWeakPointer(m_renderView);
+    info.addMember(m_rootContentLayer, "rootContentLayer");
+    info.addMember(m_clipLayer, "clipLayer");
+    info.addMember(m_scrollLayer, "scrollLayer");
+    info.addMember(m_viewportConstrainedLayers, "viewportConstrainedLayers");
+    info.addMember(m_overflowControlsHostLayer, "overflowControlsHostLayer");
+    info.addMember(m_layerForHorizontalScrollbar, "layerForHorizontalScrollbar");
+    info.addMember(m_layerForVerticalScrollbar, "layerForVerticalScrollbar");
+    info.addMember(m_layerForScrollCorner, "layerForScrollCorner");
+#if ENABLE(RUBBER_BANDING)
+    info.addMember(m_layerForOverhangAreas, "layerForOverhangAreas");
+    info.addMember(m_contentShadowLayer, "contentShadowLayer");
+    info.addMember(m_layerForTopOverhangArea, "layerForTopOverhangArea");
+    info.addMember(m_layerForBottomOverhangArea, "layerForBottomOverhangArea");
+#endif
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderLayerCompositor.h b/Source/core/rendering/RenderLayerCompositor.h
new file mode 100644
index 0000000..a9579cb
--- /dev/null
+++ b/Source/core/rendering/RenderLayerCompositor.h
@@ -0,0 +1,391 @@
+/*
+ * Copyright (C) 2009 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 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 RenderLayerCompositor_h
+#define RenderLayerCompositor_h
+
+#include "core/page/ChromeClient.h"
+#include "core/page/Frame.h"
+#include "core/platform/graphics/GraphicsLayerClient.h"
+#include "core/rendering/RenderLayer.h"
+#include <wtf/HashMap.h>
+
+namespace WebCore {
+
+class FixedPositionViewportConstraints;
+class GraphicsLayer;
+class RenderEmbeddedObject;
+class RenderPart;
+class RenderVideo;
+class ScrollingCoordinator;
+class StickyPositionViewportConstraints;
+
+
+enum CompositingUpdateType {
+    CompositingUpdateAfterStyleChange,
+    CompositingUpdateAfterLayout,
+    CompositingUpdateOnScroll,
+    CompositingUpdateOnCompositedScroll
+};
+
+enum {
+    CompositingReasonNone                                   = 0,
+    CompositingReason3DTransform                            = 1 << 0,
+    CompositingReasonVideo                                  = 1 << 1,
+    CompositingReasonCanvas                                 = 1 << 2,
+    CompositingReasonPlugin                                 = 1 << 3,
+    CompositingReasonIFrame                                 = 1 << 4,
+    CompositingReasonBackfaceVisibilityHidden               = 1 << 5,
+    CompositingReasonClipsCompositingDescendants            = 1 << 6,
+    CompositingReasonAnimation                              = 1 << 7,
+    CompositingReasonFilters                                = 1 << 8,
+    CompositingReasonPositionFixed                          = 1 << 9,
+    CompositingReasonPositionSticky                         = 1 << 10,
+    CompositingReasonOverflowScrollingTouch                 = 1 << 11,
+    CompositingReasonStacking                               = 1 << 12,
+    CompositingReasonOverlap                                = 1 << 13,
+    CompositingReasonNegativeZIndexChildren                 = 1 << 14,
+    CompositingReasonTransformWithCompositedDescendants     = 1 << 15,
+    CompositingReasonOpacityWithCompositedDescendants       = 1 << 16,
+    CompositingReasonMaskWithCompositedDescendants          = 1 << 17,
+    CompositingReasonReflectionWithCompositedDescendants    = 1 << 18,
+    CompositingReasonFilterWithCompositedDescendants        = 1 << 19,
+    CompositingReasonBlendingWithCompositedDescendants      = 1 << 20,
+    CompositingReasonPerspective                            = 1 << 21,
+    CompositingReasonPreserve3D                             = 1 << 22,
+    CompositingReasonRoot                                   = 1 << 23
+};
+typedef unsigned CompositingReasons;
+
+// RenderLayerCompositor manages the hierarchy of
+// composited RenderLayers. It determines which RenderLayers
+// become compositing, and creates and maintains a hierarchy of
+// GraphicsLayers based on the RenderLayer painting order.
+// 
+// There is one RenderLayerCompositor per RenderView.
+
+class RenderLayerCompositor : public GraphicsLayerClient {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    explicit RenderLayerCompositor(RenderView*);
+    ~RenderLayerCompositor();
+
+    // Return true if this RenderView is in "compositing mode" (i.e. has one or more
+    // composited RenderLayers)
+    bool inCompositingMode() const { return m_compositing; }
+    // This will make a compositing layer at the root automatically, and hook up to
+    // the native view/window system.
+    void enableCompositingMode(bool enable = true);
+
+    bool inForcedCompositingMode() const { return m_forceCompositingMode; }
+
+    // Returns true if the accelerated compositing is enabled
+    bool hasAcceleratedCompositing() const { return m_hasAcceleratedCompositing; }
+
+    bool canRender3DTransforms() const;
+
+    // Copy the accelerated compositing related flags from Settings
+    void cacheAcceleratedCompositingFlags();
+
+    // Called when the layer hierarchy needs to be updated (compositing layers have been
+    // created, destroyed or re-parented).
+    void setCompositingLayersNeedRebuild(bool needRebuild = true);
+    bool compositingLayersNeedRebuild() const { return m_compositingLayersNeedRebuild; }
+
+    // Called when something outside WebKit affects the visible rect (e.g. delegated scrolling). Might schedule a layer flush.
+    void didChangeVisibleRect();
+    
+    // Rebuild the tree of compositing layers
+    void updateCompositingLayers(CompositingUpdateType, RenderLayer* updateRoot = 0);
+    
+    // Update the compositing state of the given layer. Returns true if that state changed.
+    enum CompositingChangeRepaint { CompositingChangeRepaintNow, CompositingChangeWillRepaintLater };
+    bool updateLayerCompositingState(RenderLayer*, CompositingChangeRepaint = CompositingChangeRepaintNow);
+
+    // Update the geometry for compositing children of compositingAncestor.
+    void updateCompositingDescendantGeometry(RenderLayer* compositingAncestor, RenderLayer*, bool compositedChildrenOnly);
+    
+    // Whether layer's backing needs a graphics layer to do clipping by an ancestor (non-stacking-context parent with overflow).
+    bool clippedByAncestor(RenderLayer*) const;
+    // Whether layer's backing needs a graphics layer to clip z-order children of the given layer.
+    bool clipsCompositingDescendants(const RenderLayer*) const;
+
+    // Whether the given layer needs an extra 'contents' layer.
+    bool needsContentsCompositingLayer(const RenderLayer*) const;
+
+    bool supportsFixedRootBackgroundCompositing() const;
+    bool needsFixedRootBackgroundLayer(const RenderLayer*) const;
+    GraphicsLayer* fixedRootBackgroundLayer() const;
+    
+    // Return the bounding box required for compositing layer and its childern, relative to ancestorLayer.
+    // If layerBoundingBox is not 0, on return it contains the bounding box of this layer only.
+    IntRect calculateCompositedBounds(const RenderLayer*, const RenderLayer* ancestorLayer) const;
+
+    // Repaint the appropriate layers when the given RenderLayer starts or stops being composited.
+    void repaintOnCompositingChange(RenderLayer*);
+    
+    void repaintInCompositedAncestor(RenderLayer*, const LayoutRect&);
+    
+    // Notify us that a layer has been added or removed
+    void layerWasAdded(RenderLayer* parent, RenderLayer* child);
+    void layerWillBeRemoved(RenderLayer* parent, RenderLayer* child);
+
+    // Get the nearest ancestor layer that has overflow or clip, but is not a stacking context
+    RenderLayer* enclosingNonStackingClippingLayer(const RenderLayer* layer) const;
+
+    // Repaint parts of all composited layers that intersect the given absolute rectangle (or the entire layer if the pointer is null).
+    void repaintCompositedLayers(const IntRect* = 0);
+
+    // Returns true if the given layer needs it own backing store.
+    bool requiresOwnBackingStore(const RenderLayer*, const RenderLayer* compositingAncestorLayer) const;
+
+    RenderLayer* rootRenderLayer() const;
+    GraphicsLayer* rootGraphicsLayer() const;
+    GraphicsLayer* scrollLayer() const;
+
+    enum RootLayerAttachment {
+        RootLayerUnattached,
+        RootLayerAttachedViaChromeClient,
+        RootLayerAttachedViaEnclosingFrame
+    };
+
+    RootLayerAttachment rootLayerAttachment() const { return m_rootLayerAttachment; }
+    void updateRootLayerAttachment();
+    void updateRootLayerPosition();
+    
+    void setIsInWindow(bool);
+
+    void clearBackingForAllLayers();
+    
+    void layerBecameComposited(const RenderLayer*) { ++m_compositedLayerCount; }
+    void layerBecameNonComposited(const RenderLayer*);
+
+    // Use by RenderVideo to ask if it should try to use accelerated compositing.
+    bool canAccelerateVideoRendering(RenderVideo*) const;
+
+    // Walk the tree looking for layers with 3d transforms. Useful in case you need
+    // to know if there is non-affine content, e.g. for drawing into an image.
+    bool has3DContent() const;
+    
+    static RenderLayerCompositor* frameContentsCompositor(RenderPart*);
+    // Return true if the layers changed.
+    static bool parentFrameContentLayers(RenderPart*);
+
+    // Update the geometry of the layers used for clipping and scrolling in frames.
+    void frameViewDidChangeLocation(const IntPoint& contentsOffset);
+    void frameViewDidChangeSize();
+    void frameViewDidScroll();
+    void frameViewDidLayout();
+    void rootFixedBackgroundsChanged();
+
+    void scrollingLayerDidChange(RenderLayer*);
+
+    String layerTreeAsText(LayerTreeFlags);
+
+    virtual float deviceScaleFactor() const OVERRIDE;
+    virtual float pageScaleFactor() const OVERRIDE;
+    virtual void didCommitChangesForLayer(const GraphicsLayer*) const OVERRIDE;
+
+    bool keepLayersPixelAligned() const;
+
+    void deviceOrPageScaleFactorChanged();
+
+    GraphicsLayer* layerForHorizontalScrollbar() const { return m_layerForHorizontalScrollbar.get(); }
+    GraphicsLayer* layerForVerticalScrollbar() const { return m_layerForVerticalScrollbar.get(); }
+    GraphicsLayer* layerForScrollCorner() const { return m_layerForScrollCorner.get(); }
+#if ENABLE(RUBBER_BANDING)
+    GraphicsLayer* layerForOverhangAreas() const { return m_layerForOverhangAreas.get(); }
+
+    GraphicsLayer* updateLayerForTopOverhangArea(bool wantsLayer);
+    GraphicsLayer* updateLayerForBottomOverhangArea(bool wantsLayer);
+#endif
+
+    void updateViewportConstraintStatus(RenderLayer*);
+    void removeViewportConstrainedLayer(RenderLayer*);
+
+    void resetTrackedRepaintRects();
+    void setTracksRepaints(bool);
+
+    void reportMemoryUsage(MemoryObjectInfo*) const;
+    void setShouldReevaluateCompositingAfterLayout() { m_reevaluateCompositingAfterLayout = true; }
+
+    bool viewHasTransparentBackground(Color* backgroundColor = 0) const;
+
+    CompositingReasons reasonsForCompositing(const RenderLayer*) const;
+    
+private:
+    class OverlapMap;
+
+    // GraphicsLayerClient implementation
+    virtual void notifyAnimationStarted(const GraphicsLayer*, double) OVERRIDE { }
+    virtual void paintContents(const GraphicsLayer*, GraphicsContext&, GraphicsLayerPaintingPhase, const IntRect&) OVERRIDE;
+
+    virtual bool isTrackingRepaints() const OVERRIDE;
+    
+    // Whether the given RL needs a compositing layer.
+    bool needsToBeComposited(const RenderLayer*, RenderLayer::ViewportConstrainedNotCompositedReason* = 0) const;
+    // Whether the layer has an intrinsic need for compositing layer.
+    bool requiresCompositingLayer(const RenderLayer*, RenderLayer::ViewportConstrainedNotCompositedReason* = 0) const;
+    // Whether the layer could ever be composited.
+    bool canBeComposited(const RenderLayer*) const;
+
+    // Make or destroy the backing for this layer; returns true if backing changed.
+    bool updateBacking(RenderLayer*, CompositingChangeRepaint shouldRepaint);
+
+    void clearBackingForLayerIncludingDescendants(RenderLayer*);
+
+    // Repaint the given rect (which is layer's coords), and regions of child layers that intersect that rect.
+    void recursiveRepaintLayer(RenderLayer*, const IntRect* = 0);
+
+    void addToOverlapMap(OverlapMap&, RenderLayer*, IntRect& layerBounds, bool& boundsComputed);
+    void addToOverlapMapRecursive(OverlapMap&, RenderLayer*, RenderLayer* ancestorLayer = 0);
+
+    // Returns true if any layer's compositing changed
+    void computeCompositingRequirements(RenderLayer* ancestorLayer, RenderLayer*, OverlapMap*, struct CompositingState&, bool& layersChanged, bool& descendantHas3DTransform);
+    
+    // Recurses down the tree, parenting descendant compositing layers and collecting an array of child layers for the current compositing layer.
+    void rebuildCompositingLayerTree(RenderLayer*, Vector<GraphicsLayer*>& childGraphicsLayersOfEnclosingLayer, int depth);
+
+    // Recurses down the tree, updating layer geometry only.
+    void updateLayerTreeGeometry(RenderLayer*, int depth);
+    
+    // Hook compositing layers together
+    void setCompositingParent(RenderLayer* childLayer, RenderLayer* parentLayer);
+    void removeCompositedChildren(RenderLayer*);
+
+    bool layerHas3DContent(const RenderLayer*) const;
+    bool isRunningAcceleratedTransformAnimation(RenderObject*) const;
+
+    bool hasAnyAdditionalCompositedLayers(const RenderLayer* rootLayer) const;
+
+    void ensureRootLayer();
+    void destroyRootLayer();
+
+    void attachRootLayer(RootLayerAttachment);
+    void detachRootLayer();
+
+    bool isMainFrame() const;
+    
+    void rootLayerAttachmentChanged();
+
+    void updateOverflowControlsLayers();
+
+    void notifyIFramesOfCompositingChange();
+
+    Page* page() const;
+    
+    GraphicsLayerFactory* graphicsLayerFactory() const;
+    ScrollingCoordinator* scrollingCoordinator() const;
+
+    // Whether a running transition or animation enforces the need for a compositing layer.
+    bool requiresCompositingForAnimation(RenderObject*) const;
+    bool requiresCompositingForTransform(RenderObject*) const;
+    bool requiresCompositingForVideo(RenderObject*) const;
+    bool requiresCompositingForCanvas(RenderObject*) const;
+    bool requiresCompositingForPlugin(RenderObject*) const;
+    bool requiresCompositingForFrame(RenderObject*) const;
+    bool requiresCompositingForFilters(RenderObject*) const;
+    bool requiresCompositingForBlending(RenderObject* renderer) const;
+    bool requiresCompositingForScrollableFrame() const;
+    bool requiresCompositingForPosition(RenderObject*, const RenderLayer*, RenderLayer::ViewportConstrainedNotCompositedReason* = 0) const;
+    bool requiresCompositingForOverflowScrolling(const RenderLayer*) const;
+    bool requiresCompositingForIndirectReason(RenderObject*, bool hasCompositedDescendants, bool has3DTransformedDescendants, RenderLayer::IndirectCompositingReason&) const;
+
+    void addViewportConstrainedLayer(RenderLayer*);
+
+    FixedPositionViewportConstraints computeFixedViewportConstraints(RenderLayer*) const;
+    StickyPositionViewportConstraints computeStickyViewportConstraints(RenderLayer*) const;
+
+    bool requiresHorizontalScrollbarLayer() const;
+    bool requiresVerticalScrollbarLayer() const;
+    bool requiresScrollCornerLayer() const;
+#if ENABLE(RUBBER_BANDING)
+    bool requiresOverhangAreasLayer() const;
+    bool requiresContentShadowLayer() const;
+#endif
+
+#if !LOG_DISABLED
+    const char* logReasonsForCompositing(const RenderLayer*);
+    void logLayerInfo(const RenderLayer*, int depth);
+#endif
+
+private:
+    RenderView* m_renderView;
+    OwnPtr<GraphicsLayer> m_rootContentLayer;
+
+    bool m_hasAcceleratedCompositing;
+    ChromeClient::CompositingTriggerFlags m_compositingTriggers;
+
+    int m_compositedLayerCount;
+    bool m_showDebugBorders;
+    bool m_showRepaintCounter;
+
+    // When true, we have to wait until layout has happened before we can decide whether to enter compositing mode,
+    // because only then do we know the final size of plugins and iframes.
+    mutable bool m_reevaluateCompositingAfterLayout;
+
+    bool m_compositing;
+    bool m_compositingLayersNeedRebuild;
+    bool m_forceCompositingMode;
+    bool m_inPostLayoutUpdate; // true when it's OK to trust layout information (e.g. layer sizes and positions)
+
+    bool m_isTrackingRepaints; // Used for testing.
+    
+    RootLayerAttachment m_rootLayerAttachment;
+
+    // Enclosing clipping layer for iframe content
+    OwnPtr<GraphicsLayer> m_clipLayer;
+    OwnPtr<GraphicsLayer> m_scrollLayer;
+
+    HashSet<RenderLayer*> m_viewportConstrainedLayers;
+    HashSet<RenderLayer*> m_viewportConstrainedLayersNeedingUpdate;
+
+    // Enclosing layer for overflow controls and the clipping layer
+    OwnPtr<GraphicsLayer> m_overflowControlsHostLayer;
+
+    // Layers for overflow controls
+    OwnPtr<GraphicsLayer> m_layerForHorizontalScrollbar;
+    OwnPtr<GraphicsLayer> m_layerForVerticalScrollbar;
+    OwnPtr<GraphicsLayer> m_layerForScrollCorner;
+#if ENABLE(RUBBER_BANDING)
+    OwnPtr<GraphicsLayer> m_layerForOverhangAreas;
+    OwnPtr<GraphicsLayer> m_contentShadowLayer;
+    OwnPtr<GraphicsLayer> m_layerForTopOverhangArea;
+    OwnPtr<GraphicsLayer> m_layerForBottomOverhangArea;
+#endif
+
+#if !LOG_DISABLED
+    int m_rootLayerUpdateCount;
+    int m_obligateCompositedLayerCount; // count of layer that have to be composited.
+    int m_secondaryCompositedLayerCount; // count of layers that have to be composited because of stacking or overlap.
+    double m_obligatoryBackingStoreBytes;
+    double m_secondaryBackingStoreBytes;
+#endif
+};
+
+
+} // namespace WebCore
+
+#endif // RenderLayerCompositor_h
diff --git a/Source/core/rendering/RenderLayerFilterInfo.cpp b/Source/core/rendering/RenderLayerFilterInfo.cpp
new file mode 100644
index 0000000..3a70961
--- /dev/null
+++ b/Source/core/rendering/RenderLayerFilterInfo.cpp
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2012 Adobe Systems Incorporated. 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 THE COPYRIGHT HOLDER "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 THE COPYRIGHT HOLDER 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 "core/rendering/RenderLayerFilterInfo.h"
+
+#include "core/rendering/FilterEffectRenderer.h"
+#include "core/rendering/RenderLayer.h"
+
+#if ENABLE(SVG)
+#include "core/loader/cache/CachedSVGDocument.h"
+#include "core/loader/cache/CachedSVGDocumentReference.h"
+#include "core/svg/SVGElement.h"
+#include "core/svg/SVGFilterPrimitiveStandardAttributes.h"
+#include "core/svg/graphics/filters/SVGFilter.h"
+#endif
+
+#include "core/platform/graphics/filters/custom/CustomFilterOperation.h"
+#include "core/platform/graphics/filters/custom/CustomFilterProgram.h"
+
+namespace WebCore {
+
+RenderLayerFilterInfoMap* RenderLayerFilterInfo::s_filterMap = 0;
+
+RenderLayerFilterInfo* RenderLayerFilterInfo::filterInfoForRenderLayer(const RenderLayer* layer)
+{
+    if (!s_filterMap)
+        return 0;
+    RenderLayerFilterInfoMap::iterator iter = s_filterMap->find(layer);
+    return (iter != s_filterMap->end()) ? iter->value : 0;
+}
+
+RenderLayerFilterInfo* RenderLayerFilterInfo::createFilterInfoForRenderLayerIfNeeded(RenderLayer* layer)
+{
+    if (!s_filterMap)
+        s_filterMap = new RenderLayerFilterInfoMap();
+    
+    RenderLayerFilterInfoMap::iterator iter = s_filterMap->find(layer);
+    if (iter != s_filterMap->end()) {
+        ASSERT(layer->hasFilterInfo());
+        return iter->value;
+    }
+    
+    RenderLayerFilterInfo* filter = new RenderLayerFilterInfo(layer);
+    s_filterMap->set(layer, filter);
+    layer->setHasFilterInfo(true);
+    return filter;
+}
+
+void RenderLayerFilterInfo::removeFilterInfoForRenderLayer(RenderLayer* layer)
+{
+    if (!s_filterMap)
+        return;
+    RenderLayerFilterInfo* filter = s_filterMap->take(layer);
+    if (s_filterMap->isEmpty()) {
+        delete s_filterMap;
+        s_filterMap = 0;
+    }
+    if (!filter) {
+        ASSERT(!layer->hasFilterInfo());
+        return;
+    }
+    layer->setHasFilterInfo(false);
+    delete filter;
+}
+
+RenderLayerFilterInfo::RenderLayerFilterInfo(RenderLayer* layer)
+    : m_layer(layer)
+{
+}
+
+RenderLayerFilterInfo::~RenderLayerFilterInfo()
+{
+    removeCustomFilterClients();
+#if ENABLE(SVG)
+    removeReferenceFilterClients();
+#endif
+}
+
+void RenderLayerFilterInfo::setRenderer(PassRefPtr<FilterEffectRenderer> renderer)
+{ 
+    m_renderer = renderer; 
+}
+
+#if ENABLE(SVG)
+void RenderLayerFilterInfo::notifyFinished(CachedResource*)
+{
+    RenderObject* renderer = m_layer->renderer();
+    renderer->node()->setNeedsStyleRecalc(SyntheticStyleChange);
+    renderer->repaint();
+}
+
+void RenderLayerFilterInfo::updateReferenceFilterClients(const FilterOperations& operations)
+{
+    removeReferenceFilterClients();
+    for (size_t i = 0; i < operations.size(); ++i) {
+        RefPtr<FilterOperation> filterOperation = operations.operations().at(i);
+        if (filterOperation->getOperationType() != FilterOperation::REFERENCE)
+            continue;
+        ReferenceFilterOperation* referenceFilterOperation = static_cast<ReferenceFilterOperation*>(filterOperation.get());
+        CachedSVGDocumentReference* documentReference = referenceFilterOperation->cachedSVGDocumentReference();
+        CachedSVGDocument* cachedSVGDocument = documentReference ? documentReference->document() : 0;
+
+        if (cachedSVGDocument) {
+            // Reference is external; wait for notifyFinished().
+            cachedSVGDocument->addClient(this);
+            m_externalSVGReferences.append(cachedSVGDocument);
+        } else {
+            // Reference is internal; add layer as a client so we can trigger
+            // filter repaint on SVG attribute change.
+            Element* filter = m_layer->renderer()->node()->document()->getElementById(referenceFilterOperation->fragment());
+            if (!filter || !filter->renderer() || !filter->renderer()->isSVGResourceFilter())
+                continue;
+            filter->renderer()->toRenderSVGResourceContainer()->addClientRenderLayer(m_layer);
+            m_internalSVGReferences.append(filter);
+        }
+    }
+}
+
+void RenderLayerFilterInfo::removeReferenceFilterClients()
+{
+    for (size_t i = 0; i < m_externalSVGReferences.size(); ++i)
+        m_externalSVGReferences.at(i)->removeClient(this);
+    m_externalSVGReferences.clear();
+    for (size_t i = 0; i < m_internalSVGReferences.size(); ++i) {
+        Element* filter = m_internalSVGReferences.at(i).get();
+        if (!filter->renderer())
+            continue;
+        filter->renderer()->toRenderSVGResourceContainer()->removeClientRenderLayer(m_layer);
+    }
+    m_internalSVGReferences.clear();
+}
+#endif
+
+void RenderLayerFilterInfo::notifyCustomFilterProgramLoaded(CustomFilterProgram*)
+{
+    RenderObject* renderer = m_layer->renderer();
+    renderer->node()->setNeedsStyleRecalc(SyntheticStyleChange);
+    renderer->repaint();
+}
+
+void RenderLayerFilterInfo::updateCustomFilterClients(const FilterOperations& operations)
+{
+    if (!operations.size()) {
+        removeCustomFilterClients();
+        return;
+    }
+    CustomFilterProgramList cachedCustomFilterPrograms;
+    for (size_t i = 0; i < operations.size(); ++i) {
+        const FilterOperation* filterOperation = operations.at(i);
+        if (filterOperation->getOperationType() != FilterOperation::CUSTOM)
+            continue;
+        const CustomFilterOperation* customFilterOperation = static_cast<const CustomFilterOperation*>(filterOperation);
+        RefPtr<CustomFilterProgram> program = customFilterOperation->program();
+        cachedCustomFilterPrograms.append(program);
+        program->addClient(this);
+    }
+    // Remove the old clients here, after we've added the new ones, so that we don't flicker if some shaders are unchanged.
+    removeCustomFilterClients();
+    m_cachedCustomFilterPrograms.swap(cachedCustomFilterPrograms);
+}
+
+void RenderLayerFilterInfo::removeCustomFilterClients()
+{
+    for (size_t i = 0; i < m_cachedCustomFilterPrograms.size(); ++i)
+        m_cachedCustomFilterPrograms.at(i)->removeClient(this);
+    m_cachedCustomFilterPrograms.clear();
+}
+
+} // namespace WebCore
+
diff --git a/Source/core/rendering/RenderLayerFilterInfo.h b/Source/core/rendering/RenderLayerFilterInfo.h
new file mode 100644
index 0000000..5fc7d9c
--- /dev/null
+++ b/Source/core/rendering/RenderLayerFilterInfo.h
@@ -0,0 +1,107 @@
+/*
+ * Copyright (C) 2012 Adobe Systems Incorporated. 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 THE COPYRIGHT HOLDER "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 THE COPYRIGHT HOLDER 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 RenderLayerFilterInfo_h
+#define RenderLayerFilterInfo_h
+
+#include "core/platform/graphics/LayoutRect.h"
+#include "core/platform/graphics/filters/FilterOperation.h"
+#include <wtf/HashMap.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefPtr.h>
+
+#include "core/platform/graphics/filters/custom/CustomFilterProgramClient.h"
+
+#if ENABLE(SVG)
+#include "core/dom/Element.h"
+#include "core/loader/cache/CachedSVGDocument.h"
+#endif
+
+namespace WebCore {
+
+class FilterEffectRenderer;
+class FilterOperations;
+class RenderLayer;
+class RenderLayerFilterInfo;
+
+typedef HashMap<const RenderLayer*, RenderLayerFilterInfo*> RenderLayerFilterInfoMap;
+    
+class RenderLayerFilterInfo
+    : public CustomFilterProgramClient
+#if ENABLE(SVG)
+    , public CachedSVGDocumentClient
+#endif
+{
+public:
+    static RenderLayerFilterInfo* filterInfoForRenderLayer(const RenderLayer*);
+    static RenderLayerFilterInfo* createFilterInfoForRenderLayerIfNeeded(RenderLayer*);
+    static void removeFilterInfoForRenderLayer(RenderLayer*);
+
+    const LayoutRect& dirtySourceRect() const { return m_dirtySourceRect; }
+    void expandDirtySourceRect(const LayoutRect& rect) { m_dirtySourceRect.unite(rect); }
+    void resetDirtySourceRect() { m_dirtySourceRect = LayoutRect(); }
+    
+    FilterEffectRenderer* renderer() const { return m_renderer.get(); }
+    void setRenderer(PassRefPtr<FilterEffectRenderer>);
+
+    // Implementation of the CustomFilterProgramClient interface.
+    virtual void notifyCustomFilterProgramLoaded(CustomFilterProgram*);
+
+    void updateCustomFilterClients(const FilterOperations&);
+    void removeCustomFilterClients();
+
+#if ENABLE(SVG)
+    void updateReferenceFilterClients(const FilterOperations&);
+    virtual void notifyFinished(CachedResource*);
+    void removeReferenceFilterClients();
+#endif
+
+private:
+    RenderLayerFilterInfo(RenderLayer*);
+    ~RenderLayerFilterInfo();
+    
+    RenderLayer* m_layer;
+    
+    RefPtr<FilterEffectRenderer> m_renderer;
+    LayoutRect m_dirtySourceRect;
+
+    typedef Vector<RefPtr<CustomFilterProgram> > CustomFilterProgramList;
+    CustomFilterProgramList m_cachedCustomFilterPrograms;
+    
+    static RenderLayerFilterInfoMap* s_filterMap;
+#if ENABLE(SVG)
+    Vector<RefPtr<Element> > m_internalSVGReferences;
+    Vector<CachedResourceHandle<CachedSVGDocument> > m_externalSVGReferences;
+#endif
+};
+
+} // namespace WebCore
+
+
+#endif // RenderLayerFilterInfo_h
diff --git a/Source/core/rendering/RenderLayerModelObject.cpp b/Source/core/rendering/RenderLayerModelObject.cpp
new file mode 100644
index 0000000..5adbabb
--- /dev/null
+++ b/Source/core/rendering/RenderLayerModelObject.cpp
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2005 Allan Sandfeld Jensen (kde@carewolf.com)
+ *           (C) 2005, 2006 Samuel Weinig (sam.weinig@gmail.com)
+ * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2010, 2012 Google 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 "core/rendering/RenderLayerModelObject.h"
+
+#include "core/dom/WebCoreMemoryInstrumentation.h"
+#include "core/rendering/RenderLayer.h"
+#include "core/rendering/RenderView.h"
+
+using namespace std;
+
+namespace WebCore {
+
+bool RenderLayerModelObject::s_wasFloating = false;
+bool RenderLayerModelObject::s_hadLayer = false;
+bool RenderLayerModelObject::s_hadTransform = false;
+bool RenderLayerModelObject::s_layerWasSelfPainting = false;
+
+RenderLayerModelObject::RenderLayerModelObject(ContainerNode* node)
+    : RenderObject(node)
+    , m_layer(0)
+{
+}
+
+RenderLayerModelObject::~RenderLayerModelObject()
+{
+    // Our layer should have been destroyed and cleared by now
+    ASSERT(!hasLayer());
+    ASSERT(!m_layer);
+}
+
+void RenderLayerModelObject::destroyLayer()
+{
+    ASSERT(!hasLayer()); // Callers should have already called setHasLayer(false)
+    ASSERT(m_layer);
+    m_layer->destroy(renderArena());
+    m_layer = 0;
+}
+
+void RenderLayerModelObject::ensureLayer()
+{
+    if (m_layer)
+        return;
+
+    m_layer = new (renderArena()) RenderLayer(this);
+    setHasLayer(true);
+    m_layer->insertOnlyThisLayer();
+}
+
+bool RenderLayerModelObject::hasSelfPaintingLayer() const
+{
+    return m_layer && m_layer->isSelfPaintingLayer();
+}
+
+void RenderLayerModelObject::willBeDestroyed()
+{
+    if (isPositioned()) {
+        // Don't use this->view() because the document's renderView has been set to 0 during destruction.
+        if (Frame* frame = this->frame()) {
+            if (FrameView* frameView = frame->view()) {
+                if (style()->hasViewportConstrainedPosition())
+                    frameView->removeViewportConstrainedObject(this);
+            }
+        }
+    }
+
+    // RenderObject::willBeDestroyed calls back to destroyLayer() for layer destruction
+    RenderObject::willBeDestroyed();
+}
+
+void RenderLayerModelObject::styleWillChange(StyleDifference diff, const RenderStyle* newStyle)
+{
+    s_wasFloating = isFloating();
+    s_hadLayer = hasLayer();
+    s_hadTransform = hasTransform();
+    if (s_hadLayer)
+        s_layerWasSelfPainting = layer()->isSelfPaintingLayer();
+
+    // If our z-index changes value or our visibility changes,
+    // we need to dirty our stacking context's z-order list.
+    RenderStyle* oldStyle = style();
+    if (oldStyle && newStyle) {
+        if (parent()) {
+            // 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 == StyleDifferenceRepaintLayer) {
+                layer()->repaintIncludingDescendants();
+                if (!(oldStyle->clip() == newStyle->clip()))
+                    layer()->clearClipRectsIncludingDescendants();
+            } else if (diff == StyleDifferenceRepaint || newStyle->outlineSize() < oldStyle->outlineSize())
+                repaint();
+        }
+
+        if (diff == StyleDifferenceLayout || diff == StyleDifferenceSimplifiedLayout) {
+            // When a layout hint happens, we go ahead and do a repaint of the layer, since the layer could
+            // end up being destroyed.
+            if (hasLayer()) {
+                if (oldStyle->position() != newStyle->position()
+                    || oldStyle->zIndex() != newStyle->zIndex()
+                    || oldStyle->hasAutoZIndex() != newStyle->hasAutoZIndex()
+                    || !(oldStyle->clip() == newStyle->clip())
+                    || oldStyle->hasClip() != newStyle->hasClip()
+                    || oldStyle->opacity() != newStyle->opacity()
+                    || oldStyle->transform() != newStyle->transform()
+                    || oldStyle->filter() != newStyle->filter()
+                    )
+                layer()->repaintIncludingDescendants();
+            } else if (newStyle->hasTransform() || newStyle->opacity() < 1 || newStyle->hasFilter()) {
+                // If we don't have a layer yet, but we are going to get one because of transform or opacity,
+                //  then we need to repaint the old position of the object.
+                repaint();
+            }
+        }
+    }
+
+    RenderObject::styleWillChange(diff, newStyle);
+}
+
+void RenderLayerModelObject::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
+{
+    RenderObject::styleDidChange(diff, oldStyle);
+    updateFromStyle();
+
+    if (requiresLayer()) {
+        if (!layer() && layerCreationAllowedForSubtree()) {
+            if (s_wasFloating && isFloating())
+                setChildNeedsLayout(true);
+            ensureLayer();
+            if (parent() && !needsLayout() && containingBlock()) {
+                layer()->setRepaintStatus(NeedsFullRepaint);
+                // There is only one layer to update, it is not worth using |cachedOffset| since
+                // we are not sure the value will be used.
+                layer()->updateLayerPositions(0);
+            }
+        }
+    } else if (layer() && layer()->parent()) {
+        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(); // calls destroyLayer() which clears m_layer
+        if (s_wasFloating && isFloating())
+            setChildNeedsLayout(true);
+        if (s_hadTransform)
+            setNeedsLayoutAndPrefWidthsRecalc();
+    }
+
+    if (layer()) {
+        layer()->styleChanged(diff, oldStyle);
+        if (s_hadLayer && layer()->isSelfPaintingLayer() != s_layerWasSelfPainting)
+            setChildNeedsLayout(true);
+    }
+
+    if (FrameView *frameView = view()->frameView()) {
+        bool newStyleIsViewportConstained = style()->hasViewportConstrainedPosition();
+        bool oldStyleIsViewportConstrained = oldStyle && oldStyle->hasViewportConstrainedPosition();
+        if (newStyleIsViewportConstained != oldStyleIsViewportConstrained) {
+            if (newStyleIsViewportConstained && layer())
+                frameView->addViewportConstrainedObject(this);
+            else
+                frameView->removeViewportConstrainedObject(this);
+        }
+    }
+}
+
+void RenderLayerModelObject::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, PlatformMemoryTypes::Rendering);
+    RenderObject::reportMemoryUsage(memoryObjectInfo);
+    info.addWeakPointer(m_layer);
+}
+
+} // namespace WebCore
+
diff --git a/Source/core/rendering/RenderLayerModelObject.h b/Source/core/rendering/RenderLayerModelObject.h
new file mode 100644
index 0000000..8483ae7
--- /dev/null
+++ b/Source/core/rendering/RenderLayerModelObject.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * Copyright (C) 2003, 2006, 2007, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2010, 2012 Google 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 RenderLayerModelObject_h
+#define RenderLayerModelObject_h
+
+#include "core/rendering/RenderObject.h"
+
+namespace WebCore {
+
+class RenderLayer;
+
+class RenderLayerModelObject : public RenderObject {
+public:
+    explicit RenderLayerModelObject(ContainerNode*);
+    virtual ~RenderLayerModelObject();
+
+    // Called by RenderObject::willBeDestroyed() and is the only way layers should ever be destroyed
+    void destroyLayer();
+
+    bool hasSelfPaintingLayer() const;
+    RenderLayer* layer() const { return m_layer; }
+
+    virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle) OVERRIDE;
+    virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE;
+    virtual void updateFromStyle() { }
+
+    virtual bool requiresLayer() const = 0;
+
+    // Returns true if the background is painted opaque in the given rect.
+    // The query rect is given in local coordinate system.
+    virtual bool backgroundIsKnownToBeOpaqueInRect(const LayoutRect&) const { return false; }
+
+    virtual void reportMemoryUsage(MemoryObjectInfo*) const OVERRIDE;
+
+    // This is null for anonymous renderers.
+    ContainerNode* node() const { return toContainerNode(RenderObject::node()); }
+
+protected:
+    void ensureLayer();
+
+    virtual void willBeDestroyed() OVERRIDE;
+
+private:
+    virtual bool isLayerModelObject() const OVERRIDE FINAL { return true; }
+
+    RenderLayer* m_layer;
+
+    // Used to store state between styleWillChange and styleDidChange
+    static bool s_wasFloating;
+    static bool s_hadLayer;
+    static bool s_hadTransform;
+    static bool s_layerWasSelfPainting;
+};
+
+inline RenderLayerModelObject* toRenderLayerModelObject(RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isLayerModelObject());
+    return static_cast<RenderLayerModelObject*>(object);
+}
+
+inline const RenderLayerModelObject* toRenderLayerModelObject(const RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isLayerModelObject());
+    return static_cast<const RenderLayerModelObject*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderLayerModelObject(const RenderLayerModelObject*);
+
+} // namespace WebCore
+
+#endif // RenderLayerModelObject_h
diff --git a/Source/core/rendering/RenderLazyBlock.cpp b/Source/core/rendering/RenderLazyBlock.cpp
new file mode 100644
index 0000000..3222d67
--- /dev/null
+++ b/Source/core/rendering/RenderLazyBlock.cpp
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 2013 Google 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:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+ * OWNER 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 "core/rendering/RenderLazyBlock.h"
+
+#include "core/dom/ClientRect.h"
+#include "core/rendering/LayoutRepainter.h"
+#include "core/rendering/RenderLayer.h"
+#include "core/rendering/RenderView.h"
+
+namespace WebCore {
+
+RenderLazyBlock::RenderLazyBlock(Element* element)
+    : RenderBlock(element)
+    , m_next(0)
+    , m_previous(0)
+    , m_firstVisibleChildBox(0)
+    , m_lastVisibleChildBox(0)
+    , m_attached(false)
+    , m_isNestedLayout(false)
+{
+    setChildrenInline(false); // All of our children must be block-level.
+}
+
+RenderLazyBlock::~RenderLazyBlock()
+{
+    ASSERT(!m_attached);
+}
+
+void RenderLazyBlock::willBeDestroyed()
+{
+    detachLazyBlock();
+    RenderBlock::willBeDestroyed();
+}
+
+void RenderLazyBlock::willBeRemovedFromTree()
+{
+    RenderBlock::willBeRemovedFromTree();
+    detachLazyBlock();
+}
+
+bool RenderLazyBlock::isNested() const
+{
+    for (RenderObject* ancestor = parent(); ancestor; ancestor = ancestor->parent()) {
+        if (ancestor->isRenderLazyBlock())
+            return true;
+    }
+    return false;
+}
+
+// FIXME: This method and detachLazyBlock are essentially identical to
+// RenderQuote::attachQuote and detachQuote. We should just have a
+// RenderTreeOrderedList that does this stuff internally.
+void RenderLazyBlock::attachLazyBlock()
+{
+    ASSERT(view());
+    ASSERT(!m_attached);
+    ASSERT(!m_next && !m_previous);
+    ASSERT(isRooted());
+
+    if (!view()->firstLazyBlock()) {
+        view()->setFirstLazyBlock(this);
+        m_attached = true;
+        return;
+    }
+
+    for (RenderObject* predecessor = previousInPreOrder(); predecessor; predecessor = predecessor->previousInPreOrder()) {
+        if (!predecessor->isRenderLazyBlock() || !toRenderLazyBlock(predecessor)->isAttached())
+            continue;
+        m_previous = toRenderLazyBlock(predecessor);
+        m_next = m_previous->m_next;
+        m_previous->m_next = this;
+        if (m_next)
+            m_next->m_previous = this;
+        break;
+    }
+
+    if (!m_previous) {
+        m_next = view()->firstLazyBlock();
+        view()->setFirstLazyBlock(this);
+        if (m_next)
+            m_next->m_previous = this;
+    }
+    m_attached = true;
+
+    ASSERT(!m_next || m_next->m_attached);
+    ASSERT(!m_next || m_next->m_previous == this);
+    ASSERT(!m_previous || m_previous->m_attached);
+    ASSERT(!m_previous || m_previous->m_next == this);
+}
+
+void RenderLazyBlock::detachLazyBlock()
+{
+    ASSERT(!m_next || m_next->m_attached);
+    ASSERT(!m_previous || m_previous->m_attached);
+    if (!m_attached)
+        return;
+    if (m_previous)
+        m_previous->m_next = m_next;
+    else if (view())
+        view()->setFirstLazyBlock(m_next);
+    if (m_next)
+        m_next->m_previous = m_previous;
+    m_attached = false;
+    m_next = 0;
+    m_previous = 0;
+}
+
+void RenderLazyBlock::paintChildren(PaintInfo& paintInfo, const LayoutPoint& paintOffset, PaintInfo& paintInfoForChild, bool usePrintRect)
+{
+    for (RenderBox* child = m_firstVisibleChildBox; child && child != m_lastVisibleChildBox; child = child->nextSiblingBox()) {
+        if (!paintChild(child, paintInfo, paintOffset, paintInfoForChild, usePrintRect))
+            return;
+    }
+}
+
+void RenderLazyBlock::layoutChildren(bool relayoutChildren)
+{
+    LayoutUnit afterEdge = borderAfter() + paddingAfter() + scrollbarLogicalHeight();
+    LayoutUnit height = borderBefore() + paddingBefore();
+    LayoutRect intersectRect = m_intersectRect;
+
+    // FIXME: If we already have m_firstVisibleChildBox we should start there
+    // and stop when we have enough to fill the viewport. This catches the most
+    // common cases of scrolling upward or downward.
+
+    m_firstVisibleChildBox = 0;
+    m_lastVisibleChildBox = 0;
+
+    // FIXME: This should approximate the height so we don't actually need to walk
+    // every child and can optimistically layout children until we fill the
+    // the expandedViewportRect.
+
+    setLogicalHeight(height);
+    int childCount = 0;
+    LayoutUnit heightOfChildren = 0;
+    for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
+        ++childCount;
+        updateBlockChildDirtyBitsBeforeLayout(relayoutChildren, child);
+
+        if (relayoutChildren)
+            child->setNeedsLayout(true, MarkOnlyThis);
+
+        if (child->style()->logicalHeight().isSpecified()) {
+            LogicalExtentComputedValues computedValues;
+            child->computeLogicalHeight(-1, height, computedValues);
+            child->setLogicalHeight(computedValues.m_extent);
+            heightOfChildren += computedValues.m_extent;
+        } else {
+            // FIXME: Enable guessing about height so we don't need to do layout
+            // on every non fixed height child.
+            setLogicalHeight(height);
+            setLogicalTopForChild(child, height);
+            if (heightOfChildren && child->needsLayout())
+                child->setLogicalHeight(heightOfChildren / childCount);
+            else
+                child->layoutIfNeeded();
+            heightOfChildren += child->logicalHeight();
+        }
+
+        intersectRect.setHeight(child->logicalHeight());
+
+        if (m_expandedViewportRect.intersects(enclosingIntRect(intersectRect))) {
+            if (!m_firstVisibleChildBox)
+                m_firstVisibleChildBox = child;
+            m_lastVisibleChildBox = child->nextSiblingBox();
+            setLogicalHeight(height);
+            setLogicalTopForChild(child, height);
+            child->layoutIfNeeded();
+            // FIXME: Track how far off our estimated height is from the actual height,
+            // and adjust the scrollbars accordingly.
+        }
+
+        intersectRect.setY(intersectRect.y() + child->logicalHeight());
+        height += child->logicalHeight();
+    }
+
+    setLogicalHeight(height + afterEdge);
+
+    updateLogicalHeight();
+}
+
+void RenderLazyBlock::layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeight)
+{
+    ASSERT(needsLayout());
+
+    if (!m_attached)
+        attachLazyBlock();
+
+    // FIXME: We should adjust the style to disallow columns too.
+    ASSERT(!hasColumns());
+
+    LayoutRepainter repainter(*this, checkForRepaintDuringLayout());
+    LayoutStateMaintainer statePusher(view(), this, locationOffset(), hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode());
+
+    // FIXME: The compositor can instead give us a list of rects it thinks
+    // are important.
+    IntRect expandedViewportRect = view()->frameView()->visibleContentRect(ScrollableArea::IncludeScrollbars);
+    expandedViewportRect.move(-4000, -4000);
+    expandedViewportRect.expand(8000, 8000);
+
+    // FIXME: We probably want a RenderGeometryMap instead since we need to handle
+    // rotation of the RenderLazyBlock and other transforms.
+    Vector<FloatQuad> quads;
+    enclosingBoxModelObject()->absoluteQuads(quads);
+    LayoutRect intersectRect = quads[0].enclosingBoundingBox();
+    if (hasOverflowClip())
+        intersectRect.move(-scrolledContentOffset());
+
+    // Avoid doing work inside the nested layout if we know everything is correct already.
+    if (!m_isNestedLayout || m_intersectRect != intersectRect || m_expandedViewportRect != expandedViewportRect) {
+        m_intersectRect = intersectRect;
+        m_expandedViewportRect = expandedViewportRect;
+        layoutChildren(relayoutChildren || updateLogicalWidthAndColumnWidth());
+    }
+
+    statePusher.pop();
+    updateLayerTransform();
+    updateScrollInfoAfterLayout();
+    repainter.repaintAfterLayout();
+
+    m_isNestedLayout = false;
+    setNeedsLayout(false);
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderLazyBlock.h b/Source/core/rendering/RenderLazyBlock.h
new file mode 100644
index 0000000..afdddf5
--- /dev/null
+++ b/Source/core/rendering/RenderLazyBlock.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2013 Google 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:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+ * OWNER 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 RenderLazyBlock_h
+#define RenderLazyBlock_h
+
+#include "core/rendering/RenderBlock.h"
+
+namespace WebCore {
+
+class RenderLazyBlock FINAL : public RenderBlock {
+public:
+    RenderLazyBlock(Element*);
+    virtual ~RenderLazyBlock();
+
+    bool isAttached() const { return m_attached; }
+    bool isNested() const;
+
+    void markForNestedLayout()
+    {
+        setNeedsLayout(true);
+        m_isNestedLayout = true;
+    }
+
+    RenderLazyBlock* next() const { return m_next; }
+    RenderLazyBlock* previous() const { return m_previous; }
+
+    RenderBox* firstVisibleChildBox() const { return m_firstVisibleChildBox; }
+    RenderBox* lastVisibleChildBox() const { return m_lastVisibleChildBox; }
+
+private:
+    virtual void paintChildren(PaintInfo& forSelf, const LayoutPoint&, PaintInfo& forChild, bool usePrintRect) OVERRIDE;
+
+    virtual bool isRenderLazyBlock() const OVERRIDE { return true; }
+    virtual void willBeDestroyed() OVERRIDE;
+    virtual void willBeRemovedFromTree() OVERRIDE;
+    virtual void layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeight) OVERRIDE;
+
+    void layoutChildren(bool relayoutChildren);
+
+    void attachLazyBlock();
+    void detachLazyBlock();
+
+    RenderLazyBlock* m_next;
+    RenderLazyBlock* m_previous;
+    RenderBox* m_firstVisibleChildBox;
+    RenderBox* m_lastVisibleChildBox;
+    bool m_attached;
+    bool m_isNestedLayout;
+    LayoutRect m_intersectRect;
+    IntRect m_expandedViewportRect;
+};
+
+inline RenderLazyBlock* toRenderLazyBlock(RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isRenderLazyBlock());
+    return static_cast<RenderLazyBlock*>(object);
+}
+
+inline const RenderLazyBlock* toRenderLazyBlock(const RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isRenderLazyBlock());
+    return static_cast<const RenderLazyBlock*>(object);
+}
+
+} // namespace WebCore
+
+#endif // RenderLazyBlock_h
diff --git a/Source/core/rendering/RenderLineBoxList.cpp b/Source/core/rendering/RenderLineBoxList.cpp
new file mode 100644
index 0000000..3e93272
--- /dev/null
+++ b/Source/core/rendering/RenderLineBoxList.cpp
@@ -0,0 +1,414 @@
+/*
+ * 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 "core/rendering/RenderLineBoxList.h"
+
+#include "core/rendering/HitTestResult.h"
+#include "core/rendering/InlineTextBox.h"
+#include "core/rendering/PaintInfo.h"
+#include "core/rendering/RenderArena.h"
+#include "core/rendering/RenderInline.h"
+#include "core/rendering/RenderView.h"
+#include "core/rendering/RootInlineBox.h"
+
+using namespace std;
+
+namespace WebCore {
+
+#ifndef NDEBUG
+RenderLineBoxList::~RenderLineBoxList()
+{
+    ASSERT(!m_firstLineBox);
+    ASSERT(!m_lastLineBox);
+}
+#endif
+
+void RenderLineBoxList::appendLineBox(InlineFlowBox* box)
+{
+    checkConsistency();
+    
+    if (!m_firstLineBox)
+        m_firstLineBox = m_lastLineBox = box;
+    else {
+        m_lastLineBox->setNextLineBox(box);
+        box->setPreviousLineBox(m_lastLineBox);
+        m_lastLineBox = box;
+    }
+
+    checkConsistency();
+}
+
+void RenderLineBoxList::deleteLineBoxTree(RenderArena* arena)
+{
+    InlineFlowBox* line = m_firstLineBox;
+    InlineFlowBox* nextLine;
+    while (line) {
+        nextLine = line->nextLineBox();
+        line->deleteLine(arena);
+        line = nextLine;
+    }
+    m_firstLineBox = m_lastLineBox = 0;
+}
+
+void RenderLineBoxList::extractLineBox(InlineFlowBox* box)
+{
+    checkConsistency();
+    
+    m_lastLineBox = box->prevLineBox();
+    if (box == m_firstLineBox)
+        m_firstLineBox = 0;
+    if (box->prevLineBox())
+        box->prevLineBox()->setNextLineBox(0);
+    box->setPreviousLineBox(0);
+    for (InlineFlowBox* curr = box; curr; curr = curr->nextLineBox())
+        curr->setExtracted();
+
+    checkConsistency();
+}
+
+void RenderLineBoxList::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->nextLineBox()) {
+        curr->setExtracted(false);
+        last = curr;
+    }
+    m_lastLineBox = last;
+
+    checkConsistency();
+}
+
+void RenderLineBoxList::removeLineBox(InlineFlowBox* box)
+{
+    checkConsistency();
+
+    if (box == m_firstLineBox)
+        m_firstLineBox = box->nextLineBox();
+    if (box == m_lastLineBox)
+        m_lastLineBox = box->prevLineBox();
+    if (box->nextLineBox())
+        box->nextLineBox()->setPreviousLineBox(box->prevLineBox());
+    if (box->prevLineBox())
+        box->prevLineBox()->setNextLineBox(box->nextLineBox());
+
+    checkConsistency();
+}
+
+void RenderLineBoxList::deleteLineBoxes(RenderArena* arena)
+{
+    if (m_firstLineBox) {
+        InlineFlowBox* next;
+        for (InlineFlowBox* curr = m_firstLineBox; curr; curr = next) {
+            next = curr->nextLineBox();
+            curr->destroy(arena);
+        }
+        m_firstLineBox = 0;
+        m_lastLineBox = 0;
+    }
+}
+
+void RenderLineBoxList::dirtyLineBoxes()
+{
+    for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextLineBox())
+        curr->dirtyLineBoxes();
+}
+
+bool RenderLineBoxList::rangeIntersectsRect(RenderBoxModelObject* renderer, LayoutUnit logicalTop, LayoutUnit logicalBottom, const LayoutRect& rect, const LayoutPoint& offset) const
+{
+    RenderBox* block;
+    if (renderer->isBox())
+        block = toRenderBox(renderer);
+    else
+        block = renderer->containingBlock();
+    LayoutUnit physicalStart = block->flipForWritingMode(logicalTop);
+    LayoutUnit physicalEnd = block->flipForWritingMode(logicalBottom);
+    LayoutUnit physicalExtent = absoluteValue(physicalEnd - physicalStart);
+    physicalStart = min(physicalStart, physicalEnd);
+    
+    if (renderer->style()->isHorizontalWritingMode()) {
+        physicalStart += offset.y();
+        if (physicalStart >= rect.maxY() || physicalStart + physicalExtent <= rect.y())
+            return false;
+    } else {
+        physicalStart += offset.x();
+        if (physicalStart >= rect.maxX() || physicalStart + physicalExtent <= rect.x())
+            return false;
+    }
+    
+    return true;
+}
+
+bool RenderLineBoxList::anyLineIntersectsRect(RenderBoxModelObject* renderer, const LayoutRect& rect, const LayoutPoint& offset, bool usePrintRect, LayoutUnit outlineSize) const
+{
+    // We can check the first box and last box and avoid painting/hit testing 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.
+    RootInlineBox* firstRootBox = firstLineBox()->root();
+    RootInlineBox* lastRootBox = lastLineBox()->root();
+    LayoutUnit firstLineTop = firstLineBox()->logicalTopVisualOverflow(firstRootBox->lineTop());
+    if (usePrintRect && !firstLineBox()->parent())
+        firstLineTop = min(firstLineTop, firstLineBox()->root()->lineTop());
+    LayoutUnit lastLineBottom = lastLineBox()->logicalBottomVisualOverflow(lastRootBox->lineBottom());
+    if (usePrintRect && !lastLineBox()->parent())
+        lastLineBottom = max(lastLineBottom, lastLineBox()->root()->lineBottom());
+    LayoutUnit logicalTop = firstLineTop - outlineSize;
+    LayoutUnit logicalBottom = outlineSize + lastLineBottom;
+    
+    return rangeIntersectsRect(renderer, logicalTop, logicalBottom, rect, offset);
+}
+
+bool RenderLineBoxList::lineIntersectsDirtyRect(RenderBoxModelObject* renderer, InlineFlowBox* box, const PaintInfo& paintInfo, const LayoutPoint& offset) const
+{
+    RootInlineBox* root = box->root();
+    LayoutUnit logicalTop = min<LayoutUnit>(box->logicalTopVisualOverflow(root->lineTop()), root->selectionTop()) - renderer->maximalOutlineSize(paintInfo.phase);
+    LayoutUnit logicalBottom = box->logicalBottomVisualOverflow(root->lineBottom()) + renderer->maximalOutlineSize(paintInfo.phase);
+    
+    return rangeIntersectsRect(renderer, logicalTop, logicalBottom, paintInfo.rect, offset);
+}
+
+void RenderLineBoxList::paint(RenderBoxModelObject* renderer, PaintInfo& paintInfo, const LayoutPoint& paintOffset) const
+{
+    // 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;
+
+    ASSERT(renderer->isRenderBlock() || (renderer->isRenderInline() && renderer->hasLayer())); // The only way an 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;
+
+    // FIXME: Paint-time pagination is obsolete and is now only used by embedded WebViews inside AppKit
+    // NSViews.  Do not add any more code for this.
+    RenderView* v = renderer->view();
+    bool usePrintRect = !v->printRect().isEmpty();
+    LayoutUnit outlineSize = renderer->maximalOutlineSize(paintInfo.phase);
+    if (!anyLineIntersectsRect(renderer, paintInfo.rect, paintOffset, usePrintRect, outlineSize))
+        return;
+
+    PaintInfo info(paintInfo);
+    ListHashSet<RenderInline*> 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.
+    for (InlineFlowBox* curr = firstLineBox(); curr; curr = curr->nextLineBox()) {
+        if (usePrintRect) {
+            // FIXME: This is the deprecated pagination model that is still needed
+            // for embedded views inside AppKit.  AppKit is incapable of paginating vertical
+            // text pages, so we don't have to deal with vertical lines at all here.
+            RootInlineBox* root = curr->root();
+            LayoutUnit topForPaginationCheck = curr->logicalTopVisualOverflow(root->lineTop());
+            LayoutUnit bottomForPaginationCheck = curr->logicalLeftVisualOverflow();
+            if (!curr->parent()) {
+                // We're a root box.  Use lineTop and lineBottom as well here.
+                topForPaginationCheck = min(topForPaginationCheck, root->lineTop());
+                bottomForPaginationCheck = max(bottomForPaginationCheck, root->lineBottom());
+            }
+            if (bottomForPaginationCheck - topForPaginationCheck <= v->printRect().height()) {
+                if (paintOffset.y() + bottomForPaginationCheck > v->printRect().maxY()) {
+                    if (RootInlineBox* nextRootBox = curr->root()->nextRootBox())
+                        bottomForPaginationCheck = min(bottomForPaginationCheck, min<LayoutUnit>(nextRootBox->logicalTopVisualOverflow(), nextRootBox->lineTop()));
+                }
+                if (paintOffset.y() + bottomForPaginationCheck > v->printRect().maxY()) {
+                    if (paintOffset.y() + topForPaginationCheck < v->truncatedAt())
+                        v->setBestTruncatedAt(paintOffset.y() + topForPaginationCheck, renderer);
+                    // If we were able to truncate, don't paint.
+                    if (paintOffset.y() + topForPaginationCheck >= v->truncatedAt())
+                        break;
+                }
+            }
+        }
+
+        if (lineIntersectsDirtyRect(renderer, curr, info, paintOffset)) {
+            RootInlineBox* root = curr->root();
+            curr->paint(info, paintOffset, root->lineTop(), root->lineBottom());
+        }
+    }
+
+    if (info.phase == PaintPhaseOutline || info.phase == PaintPhaseSelfOutline || info.phase == PaintPhaseChildOutlines) {
+        ListHashSet<RenderInline*>::iterator end = info.outlineObjects->end();
+        for (ListHashSet<RenderInline*>::iterator it = info.outlineObjects->begin(); it != end; ++it) {
+            RenderInline* flow = *it;
+            flow->paintOutline(info, paintOffset);
+        }
+        info.outlineObjects->clear();
+    }
+}
+
+bool RenderLineBoxList::hitTest(RenderBoxModelObject* renderer, const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction) const
+{
+    if (hitTestAction != HitTestForeground)
+        return false;
+
+    ASSERT(renderer->isRenderBlock() || (renderer->isRenderInline() && renderer->hasLayer())); // The only way an inline could hit test like this is if it has a layer.
+
+    // If we have no lines then we have no work to do.
+    if (!firstLineBox())
+        return false;
+
+    LayoutPoint point = locationInContainer.point();
+    LayoutRect rect = firstLineBox()->isHorizontal() ?
+        IntRect(point.x(), point.y() - locationInContainer.topPadding(), 1, locationInContainer.topPadding() + locationInContainer.bottomPadding() + 1) :
+        IntRect(point.x() - locationInContainer.leftPadding(), point.y(), locationInContainer.rightPadding() + locationInContainer.leftPadding() + 1, 1);
+
+    if (!anyLineIntersectsRect(renderer, rect, accumulatedOffset))
+        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->prevLineBox()) {
+        RootInlineBox* root = curr->root();
+        if (rangeIntersectsRect(renderer, curr->logicalTopVisualOverflow(root->lineTop()), curr->logicalBottomVisualOverflow(root->lineBottom()), rect, accumulatedOffset)) {
+            bool inside = curr->nodeAtPoint(request, result, locationInContainer, accumulatedOffset, root->lineTop(), root->lineBottom());
+            if (inside) {
+                renderer->updateHitTestResult(result, locationInContainer.point() - toLayoutSize(accumulatedOffset));
+                return true;
+            }
+        }
+    }
+
+    return false;
+}
+
+void RenderLineBoxList::dirtyLinesFromChangedChild(RenderObject* container, RenderObject* child)
+{
+    if (!container->parent() || (container->isRenderBlock() && (container->selfNeedsLayout() || !container->isBlockFlow())))
+        return;
+
+    RenderInline* inlineContainer = container->isRenderInline() ? toRenderInline(container) : 0;
+    InlineBox* firstBox = inlineContainer ? inlineContainer->firstLineBoxIncludingCulling() : firstLineBox();
+
+    // If we have no first line box, then just bail early.
+    if (!firstBox) {
+        // For an empty inline, go ahead and propagate the check up to our parent, unless the parent
+        // is already dirty.
+        if (container->isInline() && !container->ancestorLineBoxDirty()) {
+            container->parent()->dirtyLinesFromChangedChild(container);
+            container->setAncestorLineBoxDirty(); // Mark the container to avoid dirtying the same lines again across multiple destroy() calls of the same subtree.
+        }
+        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->isFloatingOrOutOfFlowPositioned())
+            continue;
+
+        if (curr->isReplaced()) {
+            InlineBox* wrapper = toRenderBox(curr)->inlineBoxWrapper();
+            if (wrapper)
+                box = wrapper->root();
+        } else if (curr->isText()) {
+            InlineTextBox* textBox = toRenderText(curr)->lastTextBox();
+            if (textBox)
+                box = textBox->root();
+        } else if (curr->isRenderInline()) {
+            InlineBox* lastSiblingBox = toRenderInline(curr)->lastLineBoxIncludingCulling();
+            if (lastSiblingBox)
+                box = lastSiblingBox->root();
+        }
+
+        if (box)
+            break;
+    }
+    if (!box) {
+        if (inlineContainer && !inlineContainer->alwaysCreateLineBoxes()) {
+            // https://bugs.webkit.org/show_bug.cgi?id=60778
+            // We may have just removed a <br> with no line box that was our first child. In this case
+            // we won't find a previous sibling, but firstBox can be pointing to a following sibling.
+            // This isn't good enough, since we won't locate the root line box that encloses the removed
+            // <br>. We have to just over-invalidate a bit and go up to our parent.
+            if (!inlineContainer->ancestorLineBoxDirty()) {
+                inlineContainer->parent()->dirtyLinesFromChangedChild(inlineContainer);
+                inlineContainer->setAncestorLineBoxDirty(); // Mark the container to avoid dirtying the same lines again across multiple destroy() calls of the same subtree.
+            }
+            return;
+        }
+        box = firstBox->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();
+        adjacentBox = box->nextRootBox();
+        // If |child| has been inserted before the first element in the linebox, but after collapsed leading
+        // space, the search for |child|'s linebox will go past the leading space to the previous linebox and select that
+        // one as |box|. If we hit that situation here, dirty the |box| actually containing the child too. 
+        bool insertedAfterLeadingSpace = box->lineBreakObj() == child->previousSibling();
+        if (adjacentBox && (adjacentBox->lineBreakObj() == child || child->isBR() || (curr && curr->isBR()) || insertedAfterLeadingSpace))
+            adjacentBox->markDirty();
+    }
+}
+
+#ifndef NDEBUG
+
+void RenderLineBoxList::checkConsistency() const
+{
+#ifdef CHECK_CONSISTENCY
+    const InlineFlowBox* prev = 0;
+    for (const InlineFlowBox* child = m_firstLineBox; child != 0; child = child->nextLineBox()) {
+        ASSERT(child->prevLineBox() == prev);
+        prev = child;
+    }
+    ASSERT(prev == m_lastLineBox);
+#endif
+}
+
+#endif
+
+}
diff --git a/Source/core/rendering/RenderLineBoxList.h b/Source/core/rendering/RenderLineBoxList.h
new file mode 100644
index 0000000..b773e3d
--- /dev/null
+++ b/Source/core/rendering/RenderLineBoxList.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (C) 2009 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 RenderLineBoxList_h
+#define RenderLineBoxList_h
+
+#include "core/rendering/RenderObject.h"
+
+namespace WebCore {
+
+class RenderLineBoxList {
+public:
+    RenderLineBoxList()
+        : m_firstLineBox(0)
+        , m_lastLineBox(0)
+    {
+    }
+
+#ifndef NDEBUG
+    ~RenderLineBoxList();
+#endif
+
+    InlineFlowBox* firstLineBox() const { return m_firstLineBox; }
+    InlineFlowBox* lastLineBox() const { return m_lastLineBox; }
+
+    void checkConsistency() const;
+
+    void appendLineBox(InlineFlowBox*);
+
+    void deleteLineBoxTree(RenderArena*);
+    void deleteLineBoxes(RenderArena*);
+
+    void extractLineBox(InlineFlowBox*);
+    void attachLineBox(InlineFlowBox*);
+    void removeLineBox(InlineFlowBox*);
+    
+    void dirtyLineBoxes();
+    void dirtyLinesFromChangedChild(RenderObject* parent, RenderObject* child);
+
+    void paint(RenderBoxModelObject*, PaintInfo&, const LayoutPoint&) const;
+    bool hitTest(RenderBoxModelObject*, const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) const;
+
+private:
+    bool anyLineIntersectsRect(RenderBoxModelObject*, const LayoutRect&, const LayoutPoint&, bool usePrintRect = false, LayoutUnit outlineSize = 0) const;
+    bool lineIntersectsDirtyRect(RenderBoxModelObject*, InlineFlowBox*, const PaintInfo&, const LayoutPoint&) const;
+    bool rangeIntersectsRect(RenderBoxModelObject*, LayoutUnit logicalTop, LayoutUnit logicalBottom, const LayoutRect&, const LayoutPoint&) const;
+
+    // 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;
+};
+
+
+#ifdef NDEBUG
+inline void RenderLineBoxList::checkConsistency() const
+{
+}
+#endif
+
+} // namespace WebCore
+
+#endif // RenderFlow_h
diff --git a/Source/core/rendering/RenderListBox.cpp b/Source/core/rendering/RenderListBox.cpp
new file mode 100644
index 0000000..15eed0c
--- /dev/null
+++ b/Source/core/rendering/RenderListBox.cpp
@@ -0,0 +1,888 @@
+/*
+ * Copyright (C) 2006, 2007, 2008, 2011 Apple Inc. All rights reserved.
+ *               2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ *
+ * 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 "core/rendering/RenderListBox.h"
+
+#include <math.h>
+#include "HTMLNames.h"
+#include "core/accessibility/AXObjectCache.h"
+#include "core/css/CSSFontSelector.h"
+#include "core/css/StyleResolver.h"
+#include "core/dom/Document.h"
+#include "core/dom/DocumentEventQueue.h"
+#include "core/dom/NodeRenderStyle.h"
+#include "core/editing/FrameSelection.h"
+#include "core/html/HTMLOptGroupElement.h"
+#include "core/html/HTMLOptionElement.h"
+#include "core/html/HTMLSelectElement.h"
+#include "core/page/EventHandler.h"
+#include "core/page/FocusController.h"
+#include "core/page/Frame.h"
+#include "core/page/FrameView.h"
+#include "core/page/Page.h"
+#include "core/page/SpatialNavigation.h"
+#include "core/platform/Scrollbar.h"
+#include "core/platform/ScrollbarTheme.h"
+#include "core/platform/graphics/FontCache.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/rendering/HitTestResult.h"
+#include "core/rendering/PaintInfo.h"
+#include "core/rendering/RenderLayer.h"
+#include "core/rendering/RenderScrollbar.h"
+#include "core/rendering/RenderText.h"
+#include "core/rendering/RenderTheme.h"
+#include "core/rendering/RenderView.h"
+
+using namespace std;
+
+namespace WebCore {
+
+using namespace HTMLNames;
+ 
+const int rowSpacing = 1;
+
+const int optionsSpacingHorizontal = 2;
+
+// The minSize constant was originally defined to render scrollbars correctly.
+// This might vary for different platforms.
+const int minSize = 4;
+
+// Default size when the multiple attribute is present but size attribute is absent.
+const int defaultSize = 4;
+
+// 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(Element* element)
+    : RenderBlock(element)
+    , m_optionsChanged(true)
+    , m_scrollToRevealSelectionAfterLayout(false)
+    , m_inAutoscroll(false)
+    , m_optionsWidth(0)
+    , m_indexOffset(0)
+{
+    ASSERT(element);
+    ASSERT(element->isHTMLElement());
+    ASSERT(element->hasTagName(HTMLNames::selectTag));
+
+    if (FrameView* frameView = frame()->view())
+        frameView->addScrollableArea(this);
+}
+
+RenderListBox::~RenderListBox()
+{
+    setHasVerticalScrollbar(false);
+
+    if (FrameView* frameView = frame()->view())
+        frameView->removeScrollableArea(this);
+}
+
+inline HTMLSelectElement* RenderListBox::selectElement() const
+{
+    return toHTMLSelectElement(node());
+}
+
+void RenderListBox::updateFromElement()
+{
+    FontCachePurgePreventer fontCachePurgePreventer;
+
+    if (m_optionsChanged) {
+        const Vector<HTMLElement*>& listItems = selectElement()->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 = toHTMLOptionElement(element)->textIndentedToRespectGroupLabel();
+            else if (element->hasTagName(optgroupTag)) {
+                text = static_cast<const HTMLOptGroupElement*>(element)->groupLabelText();
+                FontDescription d = itemFont.fontDescription();
+                d.setWeight(d.bolderWeight());
+                itemFont = Font(d, itemFont.letterSpacing(), itemFont.wordSpacing());
+                itemFont.update(document()->styleResolver()->fontSelector());
+            }
+
+            if (!text.isEmpty()) {
+                applyTextTransform(style(), text, ' ');
+                // FIXME: Why is this always LTR? Can't text direction affect the width?
+                TextRun textRun = constructTextRun(this, itemFont, text, style(), TextRun::AllowTrailingExpansion);
+                textRun.disableRoundingHacks();
+                float textWidth = itemFont.width(textRun);
+                width = max(width, textWidth);
+            }
+        }
+        m_optionsWidth = static_cast<int>(ceilf(width));
+        m_optionsChanged = false;
+        
+        setHasVerticalScrollbar(true);
+
+        setNeedsLayoutAndPrefWidthsRecalc();
+    }
+}
+
+bool RenderListBox::canBeReplacedWithInlineRunIn() const
+{
+    return false;
+}
+
+void RenderListBox::selectionChanged()
+{
+    repaint();
+    if (!m_inAutoscroll) {
+        if (m_optionsChanged || needsLayout())
+            m_scrollToRevealSelectionAfterLayout = true;
+        else
+            scrollToRevealSelection();
+    }
+    
+    if (AXObjectCache* cache = document()->existingAXObjectCache())
+        cache->selectedChildrenChanged(this);
+}
+
+void RenderListBox::layout()
+{
+    StackStats::LayoutCheckPoint layoutCheckPoint;
+    RenderBlock::layout();
+
+    if (m_vBar) {
+        bool enabled = numVisibleItems() < numItems();
+        m_vBar->setEnabled(enabled);
+        m_vBar->setSteps(1, max(1, numVisibleItems() - 1), itemHeight());
+        m_vBar->setProportion(numVisibleItems(), numItems());
+        if (!enabled) {
+            scrollToOffsetWithoutAnimation(VerticalScrollbar, 0);
+            m_indexOffset = 0;
+        }
+    }
+
+    if (m_scrollToRevealSelectionAfterLayout) {
+        LayoutStateDisabler layoutStateDisabler(view());
+        scrollToRevealSelection();
+    }
+}
+
+void RenderListBox::scrollToRevealSelection()
+{    
+    HTMLSelectElement* select = selectElement();
+
+    m_scrollToRevealSelectionAfterLayout = false;
+
+    int firstIndex = select->activeSelectionStartListIndex();
+    if (firstIndex >= 0 && !listIndexIsVisible(select->activeSelectionEndListIndex()))
+        scrollToRevealElementAtListIndex(firstIndex);
+}
+
+void RenderListBox::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const
+{
+    maxLogicalWidth = m_optionsWidth + 2 * optionsSpacingHorizontal;
+    if (m_vBar)
+        maxLogicalWidth += m_vBar->width();
+    if (!style()->width().isPercent())
+        minLogicalWidth = maxLogicalWidth;
+}
+
+void RenderListBox::computePreferredLogicalWidths()
+{
+    ASSERT(!m_optionsChanged);
+
+    m_minPreferredLogicalWidth = 0;
+    m_maxPreferredLogicalWidth = 0;
+
+    if (style()->width().isFixed() && style()->width().value() > 0)
+        m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = adjustContentBoxLogicalWidthForBoxSizing(style()->width().value());
+    else
+        computeIntrinsicLogicalWidths(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);
+
+    if (style()->minWidth().isFixed() && style()->minWidth().value() > 0) {
+        m_maxPreferredLogicalWidth = max(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->minWidth().value()));
+        m_minPreferredLogicalWidth = max(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->minWidth().value()));
+    }
+
+    if (style()->maxWidth().isFixed()) {
+        m_maxPreferredLogicalWidth = min(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->maxWidth().value()));
+        m_minPreferredLogicalWidth = min(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->maxWidth().value()));
+    }
+
+    LayoutUnit toAdd = borderAndPaddingWidth();
+    m_minPreferredLogicalWidth += toAdd;
+    m_maxPreferredLogicalWidth += toAdd;
+                                
+    setPreferredLogicalWidthsDirty(false);
+}
+
+int RenderListBox::size() const
+{
+    int specifiedSize = selectElement()->size();
+    if (specifiedSize > 1)
+        return max(minSize, specifiedSize);
+
+    return defaultSize;
+}
+
+int RenderListBox::numVisibleItems() const
+{
+    // Only count fully visible rows. But don't return 0 even if only part of a row shows.
+    return max<int>(1, (contentHeight() + rowSpacing) / itemHeight());
+}
+
+int RenderListBox::numItems() const
+{
+    return selectElement()->listItems().size();
+}
+
+LayoutUnit RenderListBox::listHeight() const
+{
+    return itemHeight() * numItems() - rowSpacing;
+}
+
+void RenderListBox::computeLogicalHeight(LayoutUnit, LayoutUnit logicalTop, LogicalExtentComputedValues& computedValues) const
+{
+    LayoutUnit height = itemHeight() * size() - rowSpacing + borderAndPaddingHeight();
+    RenderBox::computeLogicalHeight(height, logicalTop, computedValues);
+}
+
+int RenderListBox::baselinePosition(FontBaseline baselineType, bool firstLine, LineDirectionMode lineDirection, LinePositionMode linePositionMode) const
+{
+    return RenderBox::baselinePosition(baselineType, firstLine, lineDirection, linePositionMode) - baselineAdjustment;
+}
+
+LayoutRect RenderListBox::itemBoundingBoxRect(const LayoutPoint& additionalOffset, int index)
+{
+    return LayoutRect(additionalOffset.x() + borderLeft() + paddingLeft(),
+                   additionalOffset.y() + borderTop() + paddingTop() + itemHeight() * (index - m_indexOffset),
+                   contentWidth(), itemHeight());
+}
+    
+void RenderListBox::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    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, paintOffset, index);
+            index++;
+        }
+    }
+
+    // Paint the children.
+    RenderBlock::paintObject(paintInfo, paintOffset);
+
+    switch (paintInfo.phase) {
+    // Depending on whether we have overlay scrollbars they
+    // get rendered in the foreground or background phases
+    case PaintPhaseForeground:
+        if (m_vBar->isOverlayScrollbar())
+            paintScrollbar(paintInfo, paintOffset);
+        break;
+    case PaintPhaseBlockBackground:
+        if (!m_vBar->isOverlayScrollbar())
+            paintScrollbar(paintInfo, paintOffset);
+        break;
+    case PaintPhaseChildBlockBackground:
+    case PaintPhaseChildBlockBackgrounds: {
+        int index = m_indexOffset;
+        while (index < listItemsSize && index <= m_indexOffset + numVisibleItems()) {
+            paintItemBackground(paintInfo, paintOffset, index);
+            index++;
+        }
+        break;
+    }
+    default:
+        break;
+    }
+}
+
+void RenderListBox::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint& additionalOffset, const RenderLayerModelObject* paintContainer)
+{
+    if (!isSpatialNavigationEnabled(frame()))
+        return RenderBlock::addFocusRingRects(rects, additionalOffset, paintContainer);
+
+    HTMLSelectElement* select = selectElement();
+
+    // Focus the last selected item.
+    int selectedItem = select->activeSelectionEndListIndex();
+    if (selectedItem >= 0) {
+        rects.append(pixelSnappedIntRect(itemBoundingBoxRect(additionalOffset, selectedItem)));
+        return;
+    }
+
+    // No selected items, find the first non-disabled item.
+    int size = numItems();
+    const Vector<HTMLElement*>& listItems = select->listItems();
+    for (int i = 0; i < size; ++i) {
+        HTMLElement* element = listItems[i];
+        if (element->hasTagName(optionTag) && !element->isDisabledFormControl()) {
+            rects.append(pixelSnappedIntRect(itemBoundingBoxRect(additionalOffset, i)));
+            return;
+        }
+    }
+}
+
+void RenderListBox::paintScrollbar(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    if (m_vBar) {
+        IntRect scrollRect = pixelSnappedIntRect(paintOffset.x() + width() - borderRight() - m_vBar->width(),
+            paintOffset.y() + borderTop(),
+            m_vBar->width(),
+            height() - (borderTop() + borderBottom()));
+        m_vBar->setFrameRect(scrollRect);
+        m_vBar->paint(paintInfo.context, paintInfo.rect);
+    }
+}
+
+static LayoutSize itemOffsetForAlignment(TextRun textRun, RenderStyle* itemStyle, Font itemFont, LayoutRect itemBoudingBox)
+{
+    ETextAlign actualAlignment = itemStyle->textAlign();
+    // FIXME: Firefox doesn't respect JUSTIFY. Should we?
+    // FIXME: Handle TAEND here
+    if (actualAlignment == TASTART || actualAlignment == JUSTIFY)
+      actualAlignment = itemStyle->isLeftToRightDirection() ? LEFT : RIGHT;
+
+    LayoutSize offset = LayoutSize(0, itemFont.fontMetrics().ascent());
+    if (actualAlignment == RIGHT || actualAlignment == WEBKIT_RIGHT) {
+        float textWidth = itemFont.width(textRun);
+        offset.setWidth(itemBoudingBox.width() - textWidth - optionsSpacingHorizontal);
+    } else if (actualAlignment == CENTER || actualAlignment == WEBKIT_CENTER) {
+        float textWidth = itemFont.width(textRun);
+        offset.setWidth((itemBoudingBox.width() - textWidth) / 2);
+    } else
+        offset.setWidth(optionsSpacingHorizontal);
+    return offset;
+}
+
+void RenderListBox::paintItemForeground(PaintInfo& paintInfo, const LayoutPoint& paintOffset, int listIndex)
+{
+    FontCachePurgePreventer fontCachePurgePreventer;
+
+    HTMLSelectElement* select = selectElement();
+
+    const Vector<HTMLElement*>& listItems = select->listItems();
+    HTMLElement* element = listItems[listIndex];
+
+    RenderStyle* itemStyle = element->renderStyle();
+    if (!itemStyle)
+        itemStyle = style();
+
+    if (itemStyle->visibility() == HIDDEN)
+        return;
+
+    String itemText;
+    bool isOptionElement = element->hasTagName(optionTag);
+    if (isOptionElement)
+        itemText = toHTMLOptionElement(element)->textIndentedToRespectGroupLabel();
+    else if (element->hasTagName(optgroupTag))
+        itemText = static_cast<const HTMLOptGroupElement*>(element)->groupLabelText();
+    applyTextTransform(style(), itemText, ' ');
+
+    Color textColor = element->renderStyle() ? element->renderStyle()->visitedDependentColor(CSSPropertyColor) : style()->visitedDependentColor(CSSPropertyColor);
+    if (isOptionElement && toHTMLOptionElement(element)->selected()) {
+        if (frame()->selection()->isFocusedAndActive() && document()->focusedNode() == node())
+            textColor = theme()->activeListBoxSelectionForegroundColor();
+        // Honor the foreground color for disabled items
+        else if (!element->isDisabledFormControl() && !select->isDisabledFormControl())
+            textColor = theme()->inactiveListBoxSelectionForegroundColor();
+    }
+
+    ColorSpace colorSpace = itemStyle->colorSpace();
+    paintInfo.context->setFillColor(textColor, colorSpace);
+
+    TextRun textRun(itemText, 0, 0, TextRun::AllowTrailingExpansion, itemStyle->direction(), isOverride(itemStyle->unicodeBidi()), true, TextRun::NoRounding);
+    Font itemFont = style()->font();
+    LayoutRect r = itemBoundingBoxRect(paintOffset, listIndex);
+    r.move(itemOffsetForAlignment(textRun, itemStyle, itemFont, r));
+
+    if (element->hasTagName(optgroupTag)) {
+        FontDescription d = itemFont.fontDescription();
+        d.setWeight(d.bolderWeight());
+        itemFont = Font(d, itemFont.letterSpacing(), itemFont.wordSpacing());
+        itemFont.update(document()->styleResolver()->fontSelector());
+    }
+
+    // Draw the item text
+    paintInfo.context->drawBidiText(itemFont, textRun, roundedIntPoint(r.location()));
+}
+
+void RenderListBox::paintItemBackground(PaintInfo& paintInfo, const LayoutPoint& paintOffset, int listIndex)
+{
+    const Vector<HTMLElement*>& listItems = selectElement()->listItems();
+    HTMLElement* element = listItems[listIndex];
+
+    Color backColor;
+    if (element->hasTagName(optionTag) && toHTMLOptionElement(element)->selected()) {
+        if (frame()->selection()->isFocusedAndActive() && document()->focusedNode() == node())
+            backColor = theme()->activeListBoxSelectionBackgroundColor();
+        else
+            backColor = theme()->inactiveListBoxSelectionBackgroundColor();
+    } else
+        backColor = element->renderStyle() ? element->renderStyle()->visitedDependentColor(CSSPropertyBackgroundColor) : style()->visitedDependentColor(CSSPropertyBackgroundColor);
+
+    // Draw the background for this list box item
+    if (!element->renderStyle() || element->renderStyle()->visibility() != HIDDEN) {
+        ColorSpace colorSpace = element->renderStyle() ? element->renderStyle()->colorSpace() : style()->colorSpace();
+        LayoutRect itemRect = itemBoundingBoxRect(paintOffset, listIndex);
+        itemRect.intersect(controlClipRect(paintOffset));
+        paintInfo.context->fillRect(pixelSnappedIntRect(itemRect), backColor, colorSpace);
+    }
+}
+
+bool RenderListBox::isPointInOverflowControl(HitTestResult& result, const LayoutPoint& locationInContainer, const LayoutPoint& accumulatedOffset)
+{
+    if (!m_vBar || !m_vBar->shouldParticipateInHitTesting())
+        return false;
+
+    LayoutRect vertRect(accumulatedOffset.x() + width() - borderRight() - m_vBar->width(),
+                        accumulatedOffset.y() + borderTop(),
+                        m_vBar->width(),
+                        height() - borderTop() - borderBottom());
+
+    if (vertRect.contains(locationInContainer)) {
+        result.setScrollbar(m_vBar.get());
+        return true;
+    }
+    return false;
+}
+
+int RenderListBox::listIndexAtOffset(const LayoutSize& offset)
+{
+    if (!numItems())
+        return -1;
+
+    if (offset.height() < borderTop() + paddingTop() || offset.height() > height() - paddingBottom() - borderBottom())
+        return -1;
+
+    int scrollbarWidth = m_vBar ? m_vBar->width() : 0;
+    if (offset.width() < borderLeft() + paddingLeft() || offset.width() > width() - borderRight() - paddingRight() - scrollbarWidth)
+        return -1;
+
+    int newOffset = (offset.height() - 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;
+
+    // FIXME: This doesn't work correctly with transforms.
+    FloatPoint absOffset = localToAbsolute();
+
+    IntPoint lastKnownMousePosition = frame()->eventHandler()->lastKnownMousePosition();
+    // We need to check if the last known mouse position is out of the window. When the mouse is out of the window, the position is incoherent
+    static IntPoint previousMousePosition;
+    if (lastKnownMousePosition.y() < 0)
+        lastKnownMousePosition = previousMousePosition;
+    else
+        previousMousePosition = lastKnownMousePosition;
+
+    int yDelta = lastKnownMousePosition.y() - panStartMousePosition.y();
+
+    // If the point is too far from the center we limit the speed
+    yDelta = max<int>(min<int>(yDelta, maxSpeed), -maxSpeed);
+    
+    if (abs(yDelta) < iconRadius) // at the center we let the space for the icon
+        return;
+
+    if (yDelta > 0)
+        //offsetY = view()->viewHeight();
+        absOffset.move(0, listHeight());
+    else if (yDelta < 0)
+        yDelta--;
+
+    // Let's attenuate the speed
+    yDelta /= speedReducer;
+
+    IntPoint scrollPoint(0, 0);
+    scrollPoint.setY(absOffset.y() + yDelta);
+    int newOffset = scrollToward(scrollPoint);
+    if (newOffset < 0) 
+        return;
+
+    m_inAutoscroll = true;
+    HTMLSelectElement* select = selectElement();
+    select->updateListBoxSelection(!select->multiple());
+    m_inAutoscroll = false;
+}
+
+int RenderListBox::scrollToward(const IntPoint& destination)
+{
+    // FIXME: This doesn't work correctly with transforms.
+    FloatPoint absPos = localToAbsolute();
+    IntSize positionOffset = roundedIntSize(destination - absPos);
+
+    int rows = numVisibleItems();
+    int offset = m_indexOffset;
+    
+    if (positionOffset.height() < borderTop() + paddingTop() && scrollToRevealElementAtListIndex(offset - 1))
+        return offset - 1;
+    
+    if (positionOffset.height() > height() - paddingBottom() - borderBottom() && scrollToRevealElementAtListIndex(offset + rows))
+        return offset + rows - 1;
+    
+    return listIndexAtOffset(positionOffset);
+}
+
+void RenderListBox::autoscroll(const IntPoint&)
+{
+    IntPoint pos = frame()->view()->windowToContents(frame()->eventHandler()->lastKnownMousePosition());
+
+    int endIndex = scrollToward(pos);
+    if (endIndex >= 0) {
+        HTMLSelectElement* select = selectElement();
+        m_inAutoscroll = true;
+
+        if (!select->multiple())
+            select->setActiveSelectionAnchorIndex(endIndex);
+
+        select->setActiveSelectionEndIndex(endIndex);
+        select->updateListBoxSelection(!select->multiple());
+        m_inAutoscroll = false;
+    }
+}
+
+void RenderListBox::stopAutoscroll()
+{
+    selectElement()->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;
+
+    scrollToOffsetWithoutAnimation(VerticalScrollbar, newOffset);
+
+    return true;
+}
+
+bool RenderListBox::listIndexIsVisible(int index)
+{    
+    return index >= m_indexOffset && index < m_indexOffset + numVisibleItems();
+}
+
+bool RenderListBox::scroll(ScrollDirection direction, ScrollGranularity granularity, float multiplier, Node**)
+{
+    return ScrollableArea::scroll(direction, granularity, multiplier);
+}
+
+bool RenderListBox::logicalScroll(ScrollLogicalDirection direction, ScrollGranularity granularity, float multiplier, Node**)
+{
+    return ScrollableArea::scroll(logicalToPhysical(direction, style()->isHorizontalWritingMode(), style()->isFlippedBlocksWritingMode()), granularity, multiplier);
+}
+
+void RenderListBox::valueChanged(unsigned listIndex)
+{
+    HTMLSelectElement* element = selectElement();
+    element->setSelectedIndex(element->listToOptionIndex(listIndex));
+    element->dispatchFormControlChangeEvent();
+}
+
+int RenderListBox::scrollSize(ScrollbarOrientation orientation) const
+{
+    return ((orientation == VerticalScrollbar) && m_vBar) ? (m_vBar->totalSize() - m_vBar->visibleSize()) : 0;
+}
+
+int RenderListBox::scrollPosition(Scrollbar*) const
+{
+    return m_indexOffset;
+}
+
+void RenderListBox::setScrollOffset(const IntPoint& offset)
+{
+    scrollTo(offset.y());
+}
+
+void RenderListBox::scrollTo(int newOffset)
+{
+    if (newOffset == m_indexOffset)
+        return;
+
+    m_indexOffset = newOffset;
+    repaint();
+    node()->document()->eventQueue()->enqueueOrDispatchScrollEvent(node(), DocumentEventQueue::ScrollEventElementTarget);
+}
+
+LayoutUnit RenderListBox::itemHeight() const
+{
+    return style()->fontMetrics().height() + rowSpacing;
+}
+
+int RenderListBox::verticalScrollbarWidth() const
+{
+    return m_vBar && !m_vBar->isOverlayScrollbar() ? 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 pixelSnappedClientWidth();
+}
+
+int RenderListBox::scrollHeight() const
+{
+    return max(pixelSnappedClientHeight(), roundToInt(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;
+    
+    scrollToOffsetWithoutAnimation(VerticalScrollbar, index);
+}
+
+bool RenderListBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
+{
+    if (!RenderBlock::nodeAtPoint(request, result, locationInContainer, accumulatedOffset, hitTestAction))
+        return false;
+    const Vector<HTMLElement*>& listItems = selectElement()->listItems();
+    int size = numItems();
+    LayoutPoint adjustedLocation = accumulatedOffset + location();
+
+    for (int i = 0; i < size; ++i) {
+        if (itemBoundingBoxRect(adjustedLocation, i).contains(locationInContainer.point())) {
+            if (Element* node = listItems[i]) {
+                result.setInnerNode(node);
+                if (!result.innerNonSharedNode())
+                    result.setInnerNonSharedNode(node);
+                result.setLocalPoint(locationInContainer.point() - toLayoutSize(adjustedLocation));
+                break;
+            }
+        }
+    }
+
+    return true;
+}
+
+LayoutRect RenderListBox::controlClipRect(const LayoutPoint& additionalOffset) const
+{
+    LayoutRect clipRect = contentBoxRect();
+    clipRect.moveBy(additionalOffset);
+    return clipRect;
+}
+
+bool RenderListBox::isActive() const
+{
+    Page* page = 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);
+}
+
+IntRect RenderListBox::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntRect& scrollbarRect) const
+{
+    RenderView* view = this->view();
+    if (!view)
+        return scrollbarRect;
+
+    IntRect rect = scrollbarRect;
+
+    int scrollbarLeft = width() - borderRight() - scrollbar->width();
+    int scrollbarTop = borderTop();
+    rect.move(scrollbarLeft, scrollbarTop);
+
+    return view->frameView()->convertFromRenderer(this, rect);
+}
+
+IntRect RenderListBox::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntRect& parentRect) const
+{
+    RenderView* view = this->view();
+    if (!view)
+        return parentRect;
+
+    IntRect rect = view->frameView()->convertToRenderer(this, parentRect);
+
+    int scrollbarLeft = width() - borderRight() - scrollbar->width();
+    int scrollbarTop = borderTop();
+    rect.move(-scrollbarLeft, -scrollbarTop);
+    return rect;
+}
+
+IntPoint RenderListBox::convertFromScrollbarToContainingView(const Scrollbar* scrollbar, const IntPoint& scrollbarPoint) const
+{
+    RenderView* view = this->view();
+    if (!view)
+        return scrollbarPoint;
+
+    IntPoint point = scrollbarPoint;
+
+    int scrollbarLeft = width() - borderRight() - scrollbar->width();
+    int scrollbarTop = borderTop();
+    point.move(scrollbarLeft, scrollbarTop);
+
+    return view->frameView()->convertFromRenderer(this, point);
+}
+
+IntPoint RenderListBox::convertFromContainingViewToScrollbar(const Scrollbar* scrollbar, const IntPoint& parentPoint) const
+{
+    RenderView* view = this->view();
+    if (!view)
+        return parentPoint;
+
+    IntPoint point = view->frameView()->convertToRenderer(this, parentPoint);
+
+    int scrollbarLeft = width() - borderRight() - scrollbar->width();
+    int scrollbarTop = borderTop();
+    point.move(-scrollbarLeft, -scrollbarTop);
+    return point;
+}
+
+IntSize RenderListBox::contentsSize() const
+{
+    return IntSize(scrollWidth(), scrollHeight());
+}
+
+int RenderListBox::visibleHeight() const
+{
+    return height();
+}
+
+int RenderListBox::visibleWidth() const
+{
+    return width();
+}
+
+IntPoint RenderListBox::lastKnownMousePosition() const
+{
+    RenderView* view = this->view();
+    if (!view)
+        return IntPoint();
+    return view->frameView()->lastKnownMousePosition();
+}
+
+bool RenderListBox::shouldSuspendScrollAnimations() const
+{
+    RenderView* view = this->view();
+    if (!view)
+        return true;
+    return view->frameView()->shouldSuspendScrollAnimations();
+}
+
+bool RenderListBox::scrollbarsCanBeActive() const
+{
+    RenderView* view = this->view();
+    if (!view)
+        return false;
+    return view->frameView()->scrollbarsCanBeActive();
+}
+
+ScrollableArea* RenderListBox::enclosingScrollableArea() const
+{
+    // FIXME: Return a RenderLayer that's scrollable.
+    return 0;
+}
+
+IntRect RenderListBox::scrollableAreaBoundingBox() const
+{
+    return absoluteBoundingBoxRect();
+}
+
+PassRefPtr<Scrollbar> RenderListBox::createScrollbar()
+{
+    RefPtr<Scrollbar> widget;
+    bool hasCustomScrollbarStyle = style()->hasPseudoStyle(SCROLLBAR);
+    if (hasCustomScrollbarStyle)
+        widget = RenderScrollbar::createCustomScrollbar(this, VerticalScrollbar, this->node());
+    else {
+        widget = Scrollbar::createNativeScrollbar(this, VerticalScrollbar, theme()->scrollbarControlSizeForPart(ListboxPart));
+        didAddVerticalScrollbar(widget.get());
+    }
+    document()->view()->addChild(widget.get());        
+    return widget.release();
+}
+
+void RenderListBox::destroyScrollbar()
+{
+    if (!m_vBar)
+        return;
+
+    if (!m_vBar->isCustomScrollbar())
+        ScrollableArea::willRemoveVerticalScrollbar(m_vBar.get());
+    m_vBar->removeFromParent();
+    m_vBar->disconnectFromScrollableArea();
+    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();
+
+    // Force an update since we know the scrollbars have changed things.
+    if (document()->hasAnnotatedRegions())
+        document()->setAnnotatedRegionsDirty(true);
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderListBox.h b/Source/core/rendering/RenderListBox.h
new file mode 100644
index 0000000..43c47db
--- /dev/null
+++ b/Source/core/rendering/RenderListBox.h
@@ -0,0 +1,165 @@
+/*
+ * This file is part of the select element renderer in WebCore.
+ *
+ * Copyright (C) 2006, 2007, 2009 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 "core/platform/ScrollableArea.h"
+#include "core/rendering/RenderBlock.h"
+
+namespace WebCore {
+
+class HTMLSelectElement;
+
+class RenderListBox FINAL : public RenderBlock, private ScrollableArea {
+public:
+    explicit RenderListBox(Element*);
+    virtual ~RenderListBox();
+
+    void selectionChanged();
+
+    void setOptionsChanged(bool changed) { m_optionsChanged = changed; }
+
+    int listIndexAtOffset(const LayoutSize&);
+    LayoutRect itemBoundingBoxRect(const LayoutPoint&, int index);
+
+    bool scrollToRevealElementAtListIndex(int index);
+    bool listIndexIsVisible(int index);
+
+    int scrollToward(const IntPoint&); // Returns the new index or -1 if no scroll occurred
+
+    int size() const;
+
+private:
+    HTMLSelectElement* selectElement() const;
+
+    virtual const char* renderName() const { return "RenderListBox"; }
+
+    virtual bool isListBox() const { return true; }
+
+    virtual void updateFromElement();
+    virtual bool canBeReplacedWithInlineRunIn() const OVERRIDE;
+    virtual bool hasControlClip() const { return true; }
+    virtual void paintObject(PaintInfo&, const LayoutPoint&);
+    virtual LayoutRect controlClipRect(const LayoutPoint&) const;
+
+    virtual bool isPointInOverflowControl(HitTestResult&, const LayoutPoint& locationInContainer, const LayoutPoint& accumulatedOffset);
+
+    virtual bool scroll(ScrollDirection, ScrollGranularity, float multiplier = 1, Node** stopNode = 0);
+    virtual bool logicalScroll(ScrollLogicalDirection, ScrollGranularity, float multiplier = 1, Node** stopNode = 0);
+
+    virtual void computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const OVERRIDE;
+    virtual void computePreferredLogicalWidths() OVERRIDE;
+    virtual int baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const;
+    virtual void computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues&) const OVERRIDE;
+
+    virtual void layout();
+
+    virtual void addFocusRingRects(Vector<IntRect>&, const LayoutPoint& additionalOffset, const RenderLayerModelObject* paintContainer = 0) OVERRIDE;
+
+    virtual bool canBeProgramaticallyScrolled() const { return true; }
+    virtual void autoscroll(const IntPoint&);
+    virtual void stopAutoscroll();
+
+    virtual bool shouldPanScroll() const { return true; }
+    virtual void panScroll(const IntPoint&);
+
+    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);
+
+    virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
+
+    // ScrollableArea interface.
+    virtual int scrollSize(ScrollbarOrientation) const OVERRIDE;
+    virtual int scrollPosition(Scrollbar*) const OVERRIDE;
+    virtual void setScrollOffset(const IntPoint&) OVERRIDE;
+    virtual void invalidateScrollbarRect(Scrollbar*, const IntRect&) OVERRIDE;
+    virtual bool isActive() const OVERRIDE;
+    virtual bool isScrollCornerVisible() const OVERRIDE { return false; } // We don't support resize on list boxes yet. If we did these would have to change.
+    virtual IntRect scrollCornerRect() const OVERRIDE { return IntRect(); }
+    virtual void invalidateScrollCornerRect(const IntRect&) OVERRIDE { }
+    virtual IntRect convertFromScrollbarToContainingView(const Scrollbar*, const IntRect&) const OVERRIDE;
+    virtual IntRect convertFromContainingViewToScrollbar(const Scrollbar*, const IntRect&) const OVERRIDE;
+    virtual IntPoint convertFromScrollbarToContainingView(const Scrollbar*, const IntPoint&) const OVERRIDE;
+    virtual IntPoint convertFromContainingViewToScrollbar(const Scrollbar*, const IntPoint&) const OVERRIDE;
+    virtual Scrollbar* verticalScrollbar() const OVERRIDE { return m_vBar.get(); }
+    virtual IntSize contentsSize() const OVERRIDE;
+    virtual int visibleHeight() const OVERRIDE;
+    virtual int visibleWidth() const OVERRIDE;
+    virtual IntPoint lastKnownMousePosition() const OVERRIDE;
+    virtual bool shouldSuspendScrollAnimations() const OVERRIDE;
+    virtual bool scrollbarsCanBeActive() const OVERRIDE;
+
+    virtual ScrollableArea* enclosingScrollableArea() const OVERRIDE;
+    virtual IntRect scrollableAreaBoundingBox() const OVERRIDE;
+
+    // NOTE: This should only be called by the overriden setScrollOffset from ScrollableArea.
+    void scrollTo(int newOffset);
+
+    void setHasVerticalScrollbar(bool hasScrollbar);
+    PassRefPtr<Scrollbar> createScrollbar();
+    void destroyScrollbar();
+    
+    LayoutUnit itemHeight() const;
+    void valueChanged(unsigned listIndex);
+    int numVisibleItems() const;
+    int numItems() const;
+    LayoutUnit listHeight() const;
+    void paintScrollbar(PaintInfo&, const LayoutPoint&);
+    void paintItemForeground(PaintInfo&, const LayoutPoint&, int listIndex);
+    void paintItemBackground(PaintInfo&, const LayoutPoint&, int listIndex);
+    void scrollToRevealSelection();
+
+    bool m_optionsChanged;
+    bool m_scrollToRevealSelectionAfterLayout;
+    bool m_inAutoscroll;
+    int m_optionsWidth;
+    int m_indexOffset;
+
+    RefPtr<Scrollbar> m_vBar;
+};
+
+inline RenderListBox* toRenderListBox(RenderObject* object)
+{ 
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isListBox());
+    return static_cast<RenderListBox*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderListBox(const RenderListBox*);
+
+} // namepace WebCore
+
+#endif // RenderListBox_h
diff --git a/Source/core/rendering/RenderListItem.cpp b/Source/core/rendering/RenderListItem.cpp
new file mode 100644
index 0000000..fb565ec
--- /dev/null
+++ b/Source/core/rendering/RenderListItem.cpp
@@ -0,0 +1,515 @@
+/**
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Andrew Wellington (proton@wiretapped.net)
+ *
+ * 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 "core/rendering/RenderListItem.h"
+
+#include "HTMLNames.h"
+#include "core/dom/NodeTraversal.h"
+#include "core/html/HTMLOListElement.h"
+#include "core/loader/cache/CachedImage.h"
+#include "core/rendering/RenderListMarker.h"
+#include "core/rendering/RenderView.h"
+#include "core/rendering/style/StyleInheritedData.h"
+#include <wtf/StdLibExtras.h>
+#include <wtf/text/StringBuilder.h>
+
+using namespace std;
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+RenderListItem::RenderListItem(Element* element)
+    : RenderBlock(element)
+    , m_marker(0)
+    , m_hasExplicitValue(false)
+    , m_isValueUpToDate(false)
+    , m_notInList(false)
+{
+    setInline(false);
+}
+
+void RenderListItem::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
+{
+    RenderBlock::styleDidChange(diff, oldStyle);
+
+    if (style()->listStyleType() != NoneListStyle
+        || (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 = RenderListMarker::createAnonymous(this);
+        m_marker->setStyle(newStyle.release());
+    } else if (m_marker) {
+        m_marker->destroy();
+        m_marker = 0;
+    }
+}
+
+void RenderListItem::willBeDestroyed()
+{    
+    if (m_marker) {
+        m_marker->destroy();
+        m_marker = 0;
+    }
+    RenderBlock::willBeDestroyed();
+}
+
+void RenderListItem::insertedIntoTree()
+{
+    RenderBlock::insertedIntoTree();
+
+    updateListMarkerNumbers();
+}
+
+void RenderListItem::willBeRemovedFromTree()
+{
+    RenderBlock::willBeRemovedFromTree();
+
+    updateListMarkerNumbers();
+}
+
+static bool isList(const Node* node)
+{
+    return (node->hasTagName(ulTag) || node->hasTagName(olTag));
+}
+
+// Returns the enclosing list with respect to the DOM order.
+static Node* enclosingList(const RenderListItem* listItem)
+{
+    Node* listItemNode = listItem->node();
+    Node* firstNode = 0;
+    // We use parentNode because the enclosing list could be a ShadowRoot that's not Element.
+    for (Node* parent = listItemNode->parentNode(); parent; parent = parent->parentNode()) {
+        if (isList(parent))
+            return parent;
+        if (!firstNode)
+            firstNode = parent;
+    }
+
+    // If there's no actual <ul> or <ol> list element, then the first found
+    // node acts as our list for purposes of determining what other list items
+    // should be numbered as part of the same list.
+    return firstNode;
+}
+
+// Returns the next list item with respect to the DOM order.
+static RenderListItem* nextListItem(const Node* listNode, const RenderListItem* item = 0)
+{
+    if (!listNode)
+        return 0;
+
+    const Node* current = item ? item->node() : listNode;
+    current = ElementTraversal::nextIncludingPseudo(current, listNode);
+
+    while (current) {
+        if (isList(current)) {
+            // We've found a nested, independent list: nothing to do here.
+            current = ElementTraversal::nextIncludingPseudoSkippingChildren(current, listNode);
+            continue;
+        }
+
+        RenderObject* renderer = current->renderer();
+        if (renderer && renderer->isListItem())
+            return toRenderListItem(renderer);
+
+        // FIXME: Can this be optimized to skip the children of the elements without a renderer?
+        current = ElementTraversal::nextIncludingPseudo(current, listNode);
+    }
+
+    return 0;
+}
+
+// Returns the previous list item with respect to the DOM order.
+static RenderListItem* previousListItem(const Node* listNode, const RenderListItem* item)
+{
+    Node* current = item->node();
+    for (current = ElementTraversal::previousIncludingPseudo(current, listNode); current; current = ElementTraversal::previousIncludingPseudo(current, listNode)) {
+        RenderObject* renderer = current->renderer();
+        if (!renderer || (renderer && !renderer->isListItem()))
+            continue;
+        Node* otherList = enclosingList(toRenderListItem(renderer));
+        // This item is part of our current list, so it's what we're looking for.
+        if (listNode == otherList)
+            return toRenderListItem(renderer);
+        // We found ourself inside another list; lets skip the rest of it.
+        // Use nextIncludingPseudo() 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 previousIncludingPseudo() that will be done by the loop.
+        if (otherList)
+            current = ElementTraversal::nextIncludingPseudo(otherList);
+    }
+    return 0;
+}
+
+void RenderListItem::updateItemValuesForOrderedList(const HTMLOListElement* listNode)
+{
+    ASSERT(listNode);
+
+    for (RenderListItem* listItem = nextListItem(listNode); listItem; listItem = nextListItem(listNode, listItem))
+        listItem->updateValue();
+}
+
+unsigned RenderListItem::itemCountForOrderedList(const HTMLOListElement* listNode)
+{
+    ASSERT(listNode);
+
+    unsigned itemCount = 0;
+    for (RenderListItem* listItem = nextListItem(listNode); listItem; listItem = nextListItem(listNode, listItem))
+        itemCount++;
+
+    return itemCount;
+}
+
+inline int RenderListItem::calcValue() const
+{
+    if (m_hasExplicitValue)
+        return m_explicitValue;
+
+    Node* list = enclosingList(this);
+    HTMLOListElement* oListElement = (list && list->hasTagName(olTag)) ? static_cast<HTMLOListElement*>(list) : 0;
+    int valueStep = 1;
+    if (oListElement && oListElement->isReversed())
+        valueStep = -1;
+
+    // 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() + valueStep;
+
+    if (oListElement)
+        return oListElement->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;
+
+    bool inQuirksMode = curr->document()->inQuirksMode();
+    for (RenderObject* currChild = firstChild; currChild; currChild = currChild->nextSibling()) {
+        if (currChild == marker)
+            continue;
+
+        if (currChild->isInline() && (!currChild->isRenderInline() || curr->generatesLineBoxesForInlineChild(currChild)))
+            return curr;
+
+        if (currChild->isFloating() || currChild->isOutOfFlowPositioned())
+            continue;
+
+        if (currChild->isTable() || !currChild->isRenderBlock() || (currChild->isBox() && toRenderBox(currChild)->isWritingModeRoot()))
+            break;
+
+        if (curr->isListItem() && inQuirksMode && currChild->node() &&
+            (currChild->node()->hasTagName(ulTag)|| currChild->node()->hasTagName(olTag)))
+            break;
+
+        RenderObject* lineBox = getParentOfFirstLineBox(toRenderBlock(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->preferredLogicalWidthsDirty()) {
+            // Removing and adding the marker can trigger repainting in
+            // containers other than ourselves, so we need to disable LayoutState.
+            LayoutStateDisabler layoutStateDisabler(view());
+            updateFirstLetter();
+            m_marker->remove();
+            if (!lineBoxParent)
+                lineBoxParent = this;
+            lineBoxParent->addChild(m_marker, firstNonMarkerChild(lineBoxParent));
+            m_marker->updateMarginsAndContent();
+            // If markerPar is an anonymous block that has lost all its children, destroy it.
+            if (markerPar && markerPar->isAnonymousBlock() && !markerPar->firstChild() && !toRenderBlock(markerPar)->continuation())
+                markerPar->destroy();
+        }
+    }
+}
+
+void RenderListItem::layout()
+{
+    StackStats::LayoutCheckPoint layoutCheckPoint;
+    ASSERT(needsLayout()); 
+
+    updateMarkerLocation();    
+    RenderBlock::layout();
+}
+
+void RenderListItem::addOverflowFromChildren()
+{
+    RenderBlock::addOverflowFromChildren();
+    positionListMarker();
+}
+
+void RenderListItem::positionListMarker()
+{
+    if (m_marker && m_marker->parent()->isBox() && !m_marker->isInside() && m_marker->inlineBoxWrapper()) {
+        LayoutUnit markerOldLogicalLeft = m_marker->logicalLeft();
+        LayoutUnit blockOffset = 0;
+        LayoutUnit lineOffset = 0;
+        for (RenderBox* o = m_marker->parentBox(); o != this; o = o->parentBox()) {
+            blockOffset += o->logicalTop();
+            lineOffset += o->logicalLeft();
+        }
+
+        bool adjustOverflow = false;
+        LayoutUnit markerLogicalLeft;
+        RootInlineBox* root = m_marker->inlineBoxWrapper()->root();
+        bool hitSelfPaintingLayer = false;
+        
+        RootInlineBox* rootBox = m_marker->inlineBoxWrapper()->root();
+        LayoutUnit lineTop = rootBox->lineTop();
+        LayoutUnit lineBottom = rootBox->lineBottom();
+
+        // FIXME: Need to account for relative positioning in the layout overflow.
+        if (style()->isLeftToRightDirection()) {
+            LayoutUnit leftLineOffset = logicalLeftOffsetForLine(blockOffset, logicalLeftOffsetForLine(blockOffset, false), false);
+            markerLogicalLeft = leftLineOffset - lineOffset - paddingStart() - borderStart() + m_marker->marginStart();
+            m_marker->inlineBoxWrapper()->adjustLineDirectionPosition(markerLogicalLeft - markerOldLogicalLeft);
+            for (InlineFlowBox* box = m_marker->inlineBoxWrapper()->parent(); box; box = box->parent()) {
+                LayoutRect newLogicalVisualOverflowRect = box->logicalVisualOverflowRect(lineTop, lineBottom);
+                LayoutRect newLogicalLayoutOverflowRect = box->logicalLayoutOverflowRect(lineTop, lineBottom);
+                if (markerLogicalLeft < newLogicalVisualOverflowRect.x() && !hitSelfPaintingLayer) {
+                    newLogicalVisualOverflowRect.setWidth(newLogicalVisualOverflowRect.maxX() - markerLogicalLeft);
+                    newLogicalVisualOverflowRect.setX(markerLogicalLeft);
+                    if (box == root)
+                        adjustOverflow = true;
+                }
+                if (markerLogicalLeft < newLogicalLayoutOverflowRect.x()) {
+                    newLogicalLayoutOverflowRect.setWidth(newLogicalLayoutOverflowRect.maxX() - markerLogicalLeft);
+                    newLogicalLayoutOverflowRect.setX(markerLogicalLeft);
+                    if (box == root)
+                        adjustOverflow = true;
+                }
+                box->setOverflowFromLogicalRects(newLogicalLayoutOverflowRect, newLogicalVisualOverflowRect, lineTop, lineBottom);
+                if (box->boxModelObject()->hasSelfPaintingLayer())
+                    hitSelfPaintingLayer = true;
+            }
+        } else {
+            markerLogicalLeft = m_marker->logicalLeft() + paddingStart() + borderStart() + m_marker->marginEnd();
+            LayoutUnit rightLineOffset = logicalRightOffsetForLine(blockOffset, logicalRightOffsetForLine(blockOffset, false), false);
+            markerLogicalLeft = rightLineOffset - lineOffset + paddingStart() + borderStart() + m_marker->marginEnd();
+            m_marker->inlineBoxWrapper()->adjustLineDirectionPosition(markerLogicalLeft - markerOldLogicalLeft);
+            for (InlineFlowBox* box = m_marker->inlineBoxWrapper()->parent(); box; box = box->parent()) {
+                LayoutRect newLogicalVisualOverflowRect = box->logicalVisualOverflowRect(lineTop, lineBottom);
+                LayoutRect newLogicalLayoutOverflowRect = box->logicalLayoutOverflowRect(lineTop, lineBottom);
+                if (markerLogicalLeft + m_marker->logicalWidth() > newLogicalVisualOverflowRect.maxX() && !hitSelfPaintingLayer) {
+                    newLogicalVisualOverflowRect.setWidth(markerLogicalLeft + m_marker->logicalWidth() - newLogicalVisualOverflowRect.x());
+                    if (box == root)
+                        adjustOverflow = true;
+                }
+                if (markerLogicalLeft + m_marker->logicalWidth() > newLogicalLayoutOverflowRect.maxX()) {
+                    newLogicalLayoutOverflowRect.setWidth(markerLogicalLeft + m_marker->logicalWidth() - newLogicalLayoutOverflowRect.x());
+                    if (box == root)
+                        adjustOverflow = true;
+                }
+                box->setOverflowFromLogicalRects(newLogicalLayoutOverflowRect, newLogicalVisualOverflowRect, lineTop, lineBottom);
+                
+                if (box->boxModelObject()->hasSelfPaintingLayer())
+                    hitSelfPaintingLayer = true;
+            }
+        }
+
+        if (adjustOverflow) {
+            LayoutRect markerRect(markerLogicalLeft + lineOffset, blockOffset, m_marker->width(), m_marker->height());
+            if (!style()->isHorizontalWritingMode())
+                markerRect = markerRect.transposedRect();
+            RenderBox* o = m_marker;
+            bool propagateVisualOverflow = true;
+            bool propagateLayoutOverflow = true;
+            do {
+                o = o->parentBox();
+                if (o->hasOverflowClip())
+                    propagateVisualOverflow = false;
+                if (o->isRenderBlock()) {
+                    if (propagateVisualOverflow)
+                        toRenderBlock(o)->addVisualOverflow(markerRect);
+                    if (propagateLayoutOverflow)
+                        toRenderBlock(o)->addLayoutOverflow(markerRect);
+                }
+                if (o->hasOverflowClip())
+                    propagateLayoutOverflow = false;
+                if (o->hasSelfPaintingLayer())
+                    propagateVisualOverflow = false;
+                markerRect.moveBy(-o->location());
+            } while (o != this && propagateVisualOverflow && propagateLayoutOverflow);
+        }
+    }
+}
+
+void RenderListItem::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    if (!logicalHeight() && hasOverflowClip())
+        return;
+
+    RenderBlock::paint(paintInfo, paintOffset);
+}
+
+const String& RenderListItem::markerText() const
+{
+    if (m_marker)
+        return m_marker->text();
+    return nullAtom.string();
+}
+
+String RenderListItem::markerTextWithSuffix() const
+{
+    if (!m_marker)
+        return String();
+
+    // Append the suffix for the marker in the right place depending
+    // on the direction of the text (right-to-left or left-to-right).
+
+    const String& markerText = m_marker->text();
+    const String markerSuffix = m_marker->suffix();
+    StringBuilder result;
+
+    if (!m_marker->style()->isLeftToRightDirection())
+        result.append(markerSuffix);
+
+    result.append(markerText);
+
+    if (m_marker->style()->isLeftToRightDirection())
+        result.append(markerSuffix);
+
+    return result.toString();
+}
+
+void RenderListItem::explicitValueChanged()
+{
+    if (m_marker)
+        m_marker->setNeedsLayoutAndPrefWidthsRecalc();
+    Node* listNode = enclosingList(this);
+    for (RenderListItem* item = this; item; item = nextListItem(listNode, item))
+        item->updateValue();
+}
+
+void RenderListItem::setExplicitValue(int value)
+{
+    ASSERT(node());
+
+    if (m_hasExplicitValue && m_explicitValue == value)
+        return;
+    m_explicitValue = value;
+    m_value = value;
+    m_hasExplicitValue = true;
+    explicitValueChanged();
+}
+
+void RenderListItem::clearExplicitValue()
+{
+    ASSERT(node());
+
+    if (!m_hasExplicitValue)
+        return;
+    m_hasExplicitValue = false;
+    m_isValueUpToDate = false;
+    explicitValueChanged();
+}
+
+static RenderListItem* previousOrNextItem(bool isListReversed, Node* list, RenderListItem* item)
+{
+    return isListReversed ? previousListItem(list, item) : nextListItem(list, item);
+}
+
+void RenderListItem::updateListMarkerNumbers()
+{
+    Node* listNode = enclosingList(this);
+    // The list node can be the shadow root which has no renderer.
+    ASSERT(listNode);
+    if (!listNode)
+        return;
+
+    bool isListReversed = false;
+    HTMLOListElement* oListElement = (listNode && listNode->hasTagName(olTag)) ? static_cast<HTMLOListElement*>(listNode) : 0;
+    if (oListElement) {
+        oListElement->itemCountChanged();
+        isListReversed = oListElement->isReversed();
+    }
+    for (RenderListItem* item = previousOrNextItem(isListReversed, listNode, this); item; item = previousOrNextItem(isListReversed, listNode, item)) {
+        if (!item->m_isValueUpToDate) {
+            // If an item has been marked for update before, we can safely
+            // assume that all the following ones have too.
+            // This gives us the opportunity to stop here and avoid
+            // marking the same nodes again.
+            break;
+        }
+        item->updateValue();
+    }
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderListItem.h b/Source/core/rendering/RenderListItem.h
new file mode 100644
index 0000000..2a563f6
--- /dev/null
+++ b/Source/core/rendering/RenderListItem.h
@@ -0,0 +1,104 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2009 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 "core/rendering/RenderBlock.h"
+
+namespace WebCore {
+
+class HTMLOListElement;
+class RenderListMarker;
+
+class RenderListItem FINAL : public RenderBlock {
+public:
+    explicit RenderListItem(Element*);
+
+    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();
+
+    void setNotInList(bool notInList) { m_notInList = notInList; }
+    bool notInList() const { return m_notInList; }
+
+    const String& markerText() const;
+    String markerTextWithSuffix() const;
+
+    void updateListMarkerNumbers();
+
+    static void updateItemValuesForOrderedList(const HTMLOListElement*);
+    static unsigned itemCountForOrderedList(const HTMLOListElement*);
+
+private:
+    virtual const char* renderName() const { return "RenderListItem"; }
+
+    virtual bool isListItem() const { return true; }
+    
+    virtual void willBeDestroyed();
+
+    virtual void insertedIntoTree() OVERRIDE;
+    virtual void willBeRemovedFromTree() OVERRIDE;
+
+    virtual bool isEmpty() const;
+    virtual void paint(PaintInfo&, const LayoutPoint&);
+
+    virtual void layout();
+
+    void positionListMarker();
+
+    virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+
+    virtual bool requiresForcedStyleRecalcPropagation() const { return true; }
+
+    virtual void addOverflowFromChildren();
+
+    void updateMarkerLocation();
+    inline int calcValue() const;
+    void updateValueNow() const;
+    void explicitValueChanged();
+
+    int m_explicitValue;
+    RenderListMarker* m_marker;
+    mutable int m_value;
+
+    bool m_hasExplicitValue : 1;
+    mutable bool m_isValueUpToDate : 1;
+    bool m_notInList : 1;
+};
+
+inline RenderListItem* toRenderListItem(RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isListItem());
+    return static_cast<RenderListItem*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderListItem(const RenderListItem*);
+
+} // namespace WebCore
+
+#endif // RenderListItem_h
diff --git a/Source/core/rendering/RenderListMarker.cpp b/Source/core/rendering/RenderListMarker.cpp
new file mode 100644
index 0000000..68ed311
--- /dev/null
+++ b/Source/core/rendering/RenderListMarker.cpp
@@ -0,0 +1,1850 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Andrew Wellington (proton@wiretapped.net)
+ * Copyright (C) 2010 Daniel Bates (dbates@intudata.com)
+ *
+ * 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 "core/rendering/RenderListMarker.h"
+
+#include "core/dom/Document.h"
+#include "core/dom/WebCoreMemoryInstrumentation.h"
+#include "core/loader/cache/CachedImage.h"
+#include "core/platform/graphics/Font.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/rendering/RenderLayer.h"
+#include "core/rendering/RenderListItem.h"
+#include "core/rendering/RenderView.h"
+#include <wtf/text/StringBuilder.h>
+#include <wtf/unicode/CharacterNames.h>
+
+using namespace std;
+using namespace WTF;
+using namespace Unicode;
+
+namespace WebCore {
+
+const int cMarkerPadding = 7;
+
+enum SequenceType { NumericSequence, AlphabeticSequence };
+
+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.
+    ASSERT(number >= 1 && number <= 3999);
+
+    // Big enough to store largest roman number less than 3999 which
+    // is 3888 (MMMDCCCLXXXVIII)
+    const int lettersSize = 15;
+    LChar letters[lettersSize];
+
+    int length = 0;
+    const LChar ldigits[] = { 'i', 'v', 'x', 'l', 'c', 'd', 'm' };
+    const LChar udigits[] = { 'I', 'V', 'X', 'L', 'C', 'D', 'M' };
+    const LChar* 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);
+}
+
+// The typedef is needed because taking sizeof(number) in the const expression below doesn't work with some compilers.
+// This is likely the case because of the template.
+typedef int numberType;
+
+template <typename CharacterType>
+static inline String toAlphabeticOrNumeric(numberType number, const CharacterType* sequence, unsigned sequenceSize, SequenceType type)
+{
+    ASSERT(sequenceSize >= 2);
+
+    const int lettersSize = sizeof(numberType) * 8 + 1; // Binary is the worst case; requires one character per bit plus a minus sign.
+
+    CharacterType letters[lettersSize];
+
+    bool isNegativeNumber = false;
+    unsigned numberShadow = number;
+    if (type == AlphabeticSequence) {
+        ASSERT(number > 0);
+        --numberShadow;
+    } else if (number < 0) {
+        numberShadow = -number;
+        isNegativeNumber = true;
+    }
+    letters[lettersSize - 1] = sequence[numberShadow % sequenceSize];
+    int length = 1;
+
+    if (type == AlphabeticSequence) {
+        while ((numberShadow /= sequenceSize) > 0) {
+            --numberShadow;
+            letters[lettersSize - ++length] = sequence[numberShadow % sequenceSize];
+        }
+    } else {
+        while ((numberShadow /= sequenceSize) > 0)
+            letters[lettersSize - ++length] = sequence[numberShadow % sequenceSize];
+    }
+    if (isNegativeNumber)
+        letters[lettersSize - ++length] = hyphenMinus;
+
+    ASSERT(length <= lettersSize);
+    return String(&letters[lettersSize - length], length);
+}
+
+template <typename CharacterType>
+static String toSymbolic(int number, const CharacterType* symbols, unsigned symbolsSize)
+{
+    ASSERT(number > 0);
+    ASSERT(symbolsSize >= 1);
+    unsigned numberShadow = number;
+    --numberShadow;
+
+    // The asterisks list-style-type is the worst case; we show |numberShadow| asterisks.
+    StringBuilder letters;
+    letters.append(symbols[numberShadow % symbolsSize]);
+    unsigned numSymbols = numberShadow / symbolsSize;
+    while (numSymbols--)
+        letters.append(symbols[numberShadow % symbolsSize]);
+    return letters.toString();
+}
+
+template <typename CharacterType>
+static String toAlphabetic(int number, const CharacterType* alphabet, unsigned alphabetSize)
+{
+    return toAlphabeticOrNumeric(number, alphabet, alphabetSize, AlphabeticSequence);
+}
+
+template <typename CharacterType>
+static String toNumeric(int number, const CharacterType* numerals, unsigned numeralsSize)
+{
+    return toAlphabeticOrNumeric(number, numerals, numeralsSize, NumericSequence);
+}
+
+template <typename CharacterType, size_t size>
+static inline String toAlphabetic(int number, const CharacterType(&alphabet)[size])
+{
+    return toAlphabetic(number, alphabet, size);
+}
+
+template <typename CharacterType, size_t size>
+static inline String toNumeric(int number, const CharacterType(&alphabet)[size])
+{
+    return toNumeric(number, alphabet, size);
+}
+
+template <typename CharacterType, size_t size>
+static inline String toSymbolic(int number, const CharacterType(&alphabet)[size])
+{    
+    return toSymbolic(number, alphabet, size);
+}
+
+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.
+    ASSERT(number >= 0 && number <= 999999);
+
+    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++] = 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)
+{
+    ASSERT(number >= 1 && number <= 99999999);
+
+    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)
+{
+    ASSERT(number >= 1 && number <= 19999);
+
+    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])
+{
+    ASSERT(number >= 0);
+
+    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);
+}
+
+static EListStyleType effectiveListMarkerType(EListStyleType type, int value)
+{
+    // Note, the following switch statement has been explicitly grouped
+    // by list-style-type ordinal range.
+    switch (type) {
+    case ArabicIndic:
+    case Bengali:
+    case BinaryListStyle:
+    case Cambodian:
+    case Circle:
+    case DecimalLeadingZero:
+    case DecimalListStyle:
+    case Devanagari:
+    case Disc:
+    case Gujarati:
+    case Gurmukhi:
+    case Kannada:
+    case Khmer:
+    case Lao:
+    case LowerHexadecimal:
+    case Malayalam:
+    case Mongolian:
+    case Myanmar:
+    case NoneListStyle:
+    case Octal:
+    case Oriya:
+    case Persian:
+    case Square:
+    case Telugu:
+    case Thai:
+    case Tibetan:
+    case UpperHexadecimal:
+    case Urdu:
+        return type; // Can represent all ordinals.
+    case Armenian:
+        return (value < 1 || value > 99999999) ? DecimalListStyle : type;
+    case CJKIdeographic:
+        return (value < 0) ? DecimalListStyle : type;
+    case Georgian:
+        return (value < 1 || value > 19999) ? DecimalListStyle : type;
+    case Hebrew:
+        return (value < 0 || value > 999999) ? DecimalListStyle : type;
+    case LowerRoman:
+    case UpperRoman:
+        return (value < 1 || value > 3999) ? DecimalListStyle : type;
+    case Afar:
+    case Amharic:
+    case AmharicAbegede:
+    case Asterisks:
+    case CjkEarthlyBranch:
+    case CjkHeavenlyStem:
+    case Ethiopic:
+    case EthiopicAbegede:
+    case EthiopicAbegedeAmEt:
+    case EthiopicAbegedeGez:
+    case EthiopicAbegedeTiEr:
+    case EthiopicAbegedeTiEt:
+    case EthiopicHalehameAaEr:
+    case EthiopicHalehameAaEt:
+    case EthiopicHalehameAmEt:
+    case EthiopicHalehameGez:
+    case EthiopicHalehameOmEt:
+    case EthiopicHalehameSidEt:
+    case EthiopicHalehameSoEt:
+    case EthiopicHalehameTiEr:
+    case EthiopicHalehameTiEt:
+    case EthiopicHalehameTig:
+    case Footnotes:
+    case Hangul:
+    case HangulConsonant:
+    case Hiragana:
+    case HiraganaIroha:
+    case Katakana:
+    case KatakanaIroha:
+    case LowerAlpha:
+    case LowerArmenian:
+    case LowerGreek:
+    case LowerLatin:
+    case LowerNorwegian:
+    case Oromo:
+    case Sidama:
+    case Somali:
+    case Tigre:
+    case TigrinyaEr:
+    case TigrinyaErAbegede:
+    case TigrinyaEt:
+    case TigrinyaEtAbegede:
+    case UpperAlpha:
+    case UpperArmenian:
+    case UpperGreek:
+    case UpperLatin:
+    case UpperNorwegian:
+        return (value < 1) ? DecimalListStyle : type;
+    }
+
+    ASSERT_NOT_REACHED();
+    return type;
+}
+
+static UChar listMarkerSuffix(EListStyleType type, int value)
+{
+    // If the list-style-type cannot represent |value| because it's outside its
+    // ordinal range then we fall back to some list style that can represent |value|.
+    EListStyleType effectiveType = effectiveListMarkerType(type, value);
+
+    // Note, the following switch statement has been explicitly
+    // grouped by list-style-type suffix.
+    switch (effectiveType) {
+    case Asterisks:
+    case Circle:
+    case Disc:
+    case Footnotes:
+    case NoneListStyle:
+    case Square:
+        return ' ';
+    case Afar:
+    case Amharic:
+    case AmharicAbegede:
+    case Ethiopic:
+    case EthiopicAbegede:
+    case EthiopicAbegedeAmEt:
+    case EthiopicAbegedeGez:
+    case EthiopicAbegedeTiEr:
+    case EthiopicAbegedeTiEt:
+    case EthiopicHalehameAaEr:
+    case EthiopicHalehameAaEt:
+    case EthiopicHalehameAmEt:
+    case EthiopicHalehameGez:
+    case EthiopicHalehameOmEt:
+    case EthiopicHalehameSidEt:
+    case EthiopicHalehameSoEt:
+    case EthiopicHalehameTiEr:
+    case EthiopicHalehameTiEt:
+    case EthiopicHalehameTig:
+    case Oromo:
+    case Sidama:
+    case Somali:
+    case Tigre:
+    case TigrinyaEr:
+    case TigrinyaErAbegede:
+    case TigrinyaEt:
+    case TigrinyaEtAbegede:
+        return ethiopicPrefaceColon;
+    case Armenian:
+    case ArabicIndic:
+    case Bengali:
+    case BinaryListStyle:
+    case Cambodian:
+    case CJKIdeographic:
+    case CjkEarthlyBranch:
+    case CjkHeavenlyStem:
+    case DecimalLeadingZero:
+    case DecimalListStyle:
+    case Devanagari:
+    case Georgian:
+    case Gujarati:
+    case Gurmukhi:
+    case Hangul:
+    case HangulConsonant:
+    case Hebrew:
+    case Hiragana:
+    case HiraganaIroha:
+    case Kannada:
+    case Katakana:
+    case KatakanaIroha:
+    case Khmer:
+    case Lao:
+    case LowerAlpha:
+    case LowerArmenian:
+    case LowerGreek:
+    case LowerHexadecimal:
+    case LowerLatin:
+    case LowerNorwegian:
+    case LowerRoman:
+    case Malayalam:
+    case Mongolian:
+    case Myanmar:
+    case Octal:
+    case Oriya:
+    case Persian:
+    case Telugu:
+    case Thai:
+    case Tibetan:
+    case UpperAlpha:
+    case UpperArmenian:
+    case UpperGreek:
+    case UpperHexadecimal:
+    case UpperLatin:
+    case UpperNorwegian:
+    case UpperRoman:
+    case Urdu:
+        return '.';
+    }
+
+    ASSERT_NOT_REACHED();
+    return '.';
+}
+
+String listMarkerText(EListStyleType type, int value)
+{
+    // If the list-style-type, say hebrew, cannot represent |value| because it's outside
+    // its ordinal range then we fallback to some list style that can represent |value|.
+    switch (effectiveListMarkerType(type, value)) {
+        case NoneListStyle:
+            return "";
+
+        case Asterisks: {
+            static const LChar asterisksSymbols[1] = {
+                0x2A
+            };
+            return toSymbolic(value, asterisksSymbols);
+        }
+        // We use the same characters for text security.
+        // See RenderText::setInternalString.
+        case Circle:
+            return String(&whiteBullet, 1);
+        case Disc:
+            return String(&bullet, 1);
+        case Footnotes: {
+            static const UChar footnotesSymbols[4] = {
+                0x002A, 0x2051, 0x2020, 0x2021
+            };
+            return toSymbolic(value, footnotesSymbols);
+        }
+        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 DecimalListStyle:
+            return String::number(value);
+        case DecimalLeadingZero:
+            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 ArabicIndic: {
+            static const UChar arabicIndicNumerals[10] = {
+                0x0660, 0x0661, 0x0662, 0x0663, 0x0664, 0x0665, 0x0666, 0x0667, 0x0668, 0x0669
+            };
+            return toNumeric(value, arabicIndicNumerals);
+        }
+        case BinaryListStyle: {
+            static const LChar binaryNumerals[2] = {
+                '0', '1'
+            };
+            return toNumeric(value, binaryNumerals);
+        }
+        case Bengali: {
+            static const UChar bengaliNumerals[10] = {
+                0x09E6, 0x09E7, 0x09E8, 0x09E9, 0x09EA, 0x09EB, 0x09EC, 0x09ED, 0x09EE, 0x09EF
+            };
+            return toNumeric(value, bengaliNumerals);
+        }
+        case Cambodian:
+        case Khmer: {
+            static const UChar khmerNumerals[10] = {
+                0x17E0, 0x17E1, 0x17E2, 0x17E3, 0x17E4, 0x17E5, 0x17E6, 0x17E7, 0x17E8, 0x17E9
+            };
+            return toNumeric(value, khmerNumerals);
+        }
+        case Devanagari: {
+            static const UChar devanagariNumerals[10] = {
+                0x0966, 0x0967, 0x0968, 0x0969, 0x096A, 0x096B, 0x096C, 0x096D, 0x096E, 0x096F
+            };
+            return toNumeric(value, devanagariNumerals);
+        }
+        case Gujarati: {
+            static const UChar gujaratiNumerals[10] = {
+                0x0AE6, 0x0AE7, 0x0AE8, 0x0AE9, 0x0AEA, 0x0AEB, 0x0AEC, 0x0AED, 0x0AEE, 0x0AEF
+            };
+            return toNumeric(value, gujaratiNumerals);
+        }
+        case Gurmukhi: {
+            static const UChar gurmukhiNumerals[10] = {
+                0x0A66, 0x0A67, 0x0A68, 0x0A69, 0x0A6A, 0x0A6B, 0x0A6C, 0x0A6D, 0x0A6E, 0x0A6F
+            };
+            return toNumeric(value, gurmukhiNumerals);
+        }
+        case Kannada: {
+            static const UChar kannadaNumerals[10] = {
+                0x0CE6, 0x0CE7, 0x0CE8, 0x0CE9, 0x0CEA, 0x0CEB, 0x0CEC, 0x0CED, 0x0CEE, 0x0CEF
+            };
+            return toNumeric(value, kannadaNumerals);
+        }
+        case LowerHexadecimal: {
+            static const LChar lowerHexadecimalNumerals[16] = {
+                '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
+            };
+            return toNumeric(value, lowerHexadecimalNumerals);
+        }
+        case Lao: {
+            static const UChar laoNumerals[10] = {
+                0x0ED0, 0x0ED1, 0x0ED2, 0x0ED3, 0x0ED4, 0x0ED5, 0x0ED6, 0x0ED7, 0x0ED8, 0x0ED9
+            };
+            return toNumeric(value, laoNumerals);
+        }
+        case Malayalam: {
+            static const UChar malayalamNumerals[10] = {
+                0x0D66, 0x0D67, 0x0D68, 0x0D69, 0x0D6A, 0x0D6B, 0x0D6C, 0x0D6D, 0x0D6E, 0x0D6F
+            };
+            return toNumeric(value, malayalamNumerals);
+        }
+        case Mongolian: {
+            static const UChar mongolianNumerals[10] = {
+                0x1810, 0x1811, 0x1812, 0x1813, 0x1814, 0x1815, 0x1816, 0x1817, 0x1818, 0x1819
+            };
+            return toNumeric(value, mongolianNumerals);
+        }
+        case Myanmar: {
+            static const UChar myanmarNumerals[10] = {
+                0x1040, 0x1041, 0x1042, 0x1043, 0x1044, 0x1045, 0x1046, 0x1047, 0x1048, 0x1049
+            };
+            return toNumeric(value, myanmarNumerals);
+        }
+        case Octal: {
+            static const LChar octalNumerals[8] = {
+                '0', '1', '2', '3', '4', '5', '6', '7'
+            };
+            return toNumeric(value, octalNumerals);
+        }
+        case Oriya: {
+            static const UChar oriyaNumerals[10] = {
+                0x0B66, 0x0B67, 0x0B68, 0x0B69, 0x0B6A, 0x0B6B, 0x0B6C, 0x0B6D, 0x0B6E, 0x0B6F
+            };
+            return toNumeric(value, oriyaNumerals);
+        }
+        case Persian:
+        case Urdu: {
+            static const UChar urduNumerals[10] = {
+                0x06F0, 0x06F1, 0x06F2, 0x06F3, 0x06F4, 0x06F5, 0x06F6, 0x06F7, 0x06F8, 0x06F9
+            };
+            return toNumeric(value, urduNumerals);
+        }
+        case Telugu: {
+            static const UChar teluguNumerals[10] = {
+                0x0C66, 0x0C67, 0x0C68, 0x0C69, 0x0C6A, 0x0C6B, 0x0C6C, 0x0C6D, 0x0C6E, 0x0C6F
+            };
+            return toNumeric(value, teluguNumerals);
+        }
+        case Tibetan: {
+            static const UChar tibetanNumerals[10] = {
+                0x0F20, 0x0F21, 0x0F22, 0x0F23, 0x0F24, 0x0F25, 0x0F26, 0x0F27, 0x0F28, 0x0F29
+            };
+            return toNumeric(value, tibetanNumerals);
+        }
+        case Thai: {
+            static const UChar thaiNumerals[10] = {
+                0x0E50, 0x0E51, 0x0E52, 0x0E53, 0x0E54, 0x0E55, 0x0E56, 0x0E57, 0x0E58, 0x0E59
+            };
+            return toNumeric(value, thaiNumerals);
+        }
+        case UpperHexadecimal: {
+            static const LChar upperHexadecimalNumerals[16] = {
+                '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
+            };
+            return toNumeric(value, upperHexadecimalNumerals);
+        }
+
+        case LowerAlpha:
+        case LowerLatin: {
+            static const LChar 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);
+        }
+        case UpperAlpha:
+        case UpperLatin: {
+            static const LChar 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);
+        }
+        case LowerGreek: {
+            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);
+        }
+
+        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);
+        }
+        case HiraganaIroha: {
+            // 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);
+        }
+        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);
+        }
+        case KatakanaIroha: {
+            // 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);
+        }
+
+        case Afar:
+        case EthiopicHalehameAaEt:
+        case EthiopicHalehameAaEr: {
+            static const UChar ethiopicHalehameAaErAlphabet[18] = {
+                0x1200, 0x1208, 0x1210, 0x1218, 0x1228, 0x1230, 0x1260, 0x1270, 0x1290,
+                0x12A0, 0x12A8, 0x12C8, 0x12D0, 0x12E8, 0x12F0, 0x1308, 0x1338, 0x1348
+            };
+            return toAlphabetic(value, ethiopicHalehameAaErAlphabet);
+        }
+        case Amharic:
+        case EthiopicHalehameAmEt: {
+            static const UChar ethiopicHalehameAmEtAlphabet[33] = {
+                0x1200, 0x1208, 0x1210, 0x1218, 0x1220, 0x1228, 0x1230, 0x1238, 0x1240,
+                0x1260, 0x1270, 0x1278, 0x1280, 0x1290, 0x1298, 0x12A0, 0x12A8, 0x12B8,
+                0x12C8, 0x12D0, 0x12D8, 0x12E0, 0x12E8, 0x12F0, 0x1300, 0x1308, 0x1320,
+                0x1328, 0x1330, 0x1338, 0x1340, 0x1348, 0x1350
+            };
+            return toAlphabetic(value, ethiopicHalehameAmEtAlphabet);
+        }
+        case AmharicAbegede:
+        case EthiopicAbegedeAmEt: {
+            static const UChar ethiopicAbegedeAmEtAlphabet[33] = {
+                0x12A0, 0x1260, 0x1308, 0x12F0, 0x1300, 0x1200, 0x12C8, 0x12D8, 0x12E0,
+                0x1210, 0x1320, 0x1328, 0x12E8, 0x12A8, 0x12B8, 0x1208, 0x1218, 0x1290,
+                0x1298, 0x1220, 0x12D0, 0x1348, 0x1338, 0x1240, 0x1228, 0x1230, 0x1238,
+                0x1270, 0x1278, 0x1280, 0x1340, 0x1330, 0x1350
+            };
+            return toAlphabetic(value, ethiopicAbegedeAmEtAlphabet);
+        }
+        case CjkEarthlyBranch: {
+            static const UChar cjkEarthlyBranchAlphabet[12] = {
+                0x5B50, 0x4E11, 0x5BC5, 0x536F, 0x8FB0, 0x5DF3, 0x5348, 0x672A, 0x7533,
+                0x9149, 0x620C, 0x4EA5
+            };
+            return toAlphabetic(value, cjkEarthlyBranchAlphabet);
+        }
+        case CjkHeavenlyStem: {
+            static const UChar cjkHeavenlyStemAlphabet[10] = {
+                0x7532, 0x4E59, 0x4E19, 0x4E01, 0x620A, 0x5DF1, 0x5E9A, 0x8F9B, 0x58EC,
+                0x7678
+            };
+            return toAlphabetic(value, cjkHeavenlyStemAlphabet);
+        }
+        case Ethiopic:
+        case EthiopicHalehameGez: {
+            static const UChar ethiopicHalehameGezAlphabet[26] = {
+                0x1200, 0x1208, 0x1210, 0x1218, 0x1220, 0x1228, 0x1230, 0x1240, 0x1260,
+                0x1270, 0x1280, 0x1290, 0x12A0, 0x12A8, 0x12C8, 0x12D0, 0x12D8, 0x12E8,
+                0x12F0, 0x1308, 0x1320, 0x1330, 0x1338, 0x1340, 0x1348, 0x1350
+            };
+            return toAlphabetic(value, ethiopicHalehameGezAlphabet);
+        }
+        case EthiopicAbegede:
+        case EthiopicAbegedeGez: {
+            static const UChar ethiopicAbegedeGezAlphabet[26] = {
+                0x12A0, 0x1260, 0x1308, 0x12F0, 0x1200, 0x12C8, 0x12D8, 0x1210, 0x1320,
+                0x12E8, 0x12A8, 0x1208, 0x1218, 0x1290, 0x1220, 0x12D0, 0x1348, 0x1338,
+                0x1240, 0x1228, 0x1230, 0x1270, 0x1280, 0x1340, 0x1330, 0x1350
+            };
+            return toAlphabetic(value, ethiopicAbegedeGezAlphabet);
+        }
+        case HangulConsonant: {
+            static const UChar hangulConsonantAlphabet[14] = {
+                0x3131, 0x3134, 0x3137, 0x3139, 0x3141, 0x3142, 0x3145, 0x3147, 0x3148,
+                0x314A, 0x314B, 0x314C, 0x314D, 0x314E
+            };
+            return toAlphabetic(value, hangulConsonantAlphabet);
+        }
+        case Hangul: {
+            static const UChar hangulAlphabet[14] = {
+                0xAC00, 0xB098, 0xB2E4, 0xB77C, 0xB9C8, 0xBC14, 0xC0AC, 0xC544, 0xC790,
+                0xCC28, 0xCE74, 0xD0C0, 0xD30C, 0xD558
+            };
+            return toAlphabetic(value, hangulAlphabet);
+        }
+        case Oromo:
+        case EthiopicHalehameOmEt: {
+            static const UChar ethiopicHalehameOmEtAlphabet[25] = {
+                0x1200, 0x1208, 0x1218, 0x1228, 0x1230, 0x1238, 0x1240, 0x1260, 0x1270,
+                0x1278, 0x1290, 0x1298, 0x12A0, 0x12A8, 0x12C8, 0x12E8, 0x12F0, 0x12F8,
+                0x1300, 0x1308, 0x1320, 0x1328, 0x1338, 0x1330, 0x1348
+            };
+            return toAlphabetic(value, ethiopicHalehameOmEtAlphabet);
+        }
+        case Sidama:
+        case EthiopicHalehameSidEt: {
+            static const UChar ethiopicHalehameSidEtAlphabet[26] = {
+                0x1200, 0x1208, 0x1210, 0x1218, 0x1228, 0x1230, 0x1238, 0x1240, 0x1260,
+                0x1270, 0x1278, 0x1290, 0x1298, 0x12A0, 0x12A8, 0x12C8, 0x12E8, 0x12F0,
+                0x12F8, 0x1300, 0x1308, 0x1320, 0x1328, 0x1338, 0x1330, 0x1348
+            };
+            return toAlphabetic(value, ethiopicHalehameSidEtAlphabet);
+        }
+        case Somali:
+        case EthiopicHalehameSoEt: {
+            static const UChar ethiopicHalehameSoEtAlphabet[22] = {
+                0x1200, 0x1208, 0x1210, 0x1218, 0x1228, 0x1230, 0x1238, 0x1240, 0x1260,
+                0x1270, 0x1290, 0x12A0, 0x12A8, 0x12B8, 0x12C8, 0x12D0, 0x12E8, 0x12F0,
+                0x1300, 0x1308, 0x1338, 0x1348
+            };
+            return toAlphabetic(value, ethiopicHalehameSoEtAlphabet);
+        }
+        case Tigre:
+        case EthiopicHalehameTig: {
+            static const UChar ethiopicHalehameTigAlphabet[27] = {
+                0x1200, 0x1208, 0x1210, 0x1218, 0x1228, 0x1230, 0x1238, 0x1240, 0x1260,
+                0x1270, 0x1278, 0x1290, 0x12A0, 0x12A8, 0x12C8, 0x12D0, 0x12D8, 0x12E8,
+                0x12F0, 0x1300, 0x1308, 0x1320, 0x1328, 0x1338, 0x1330, 0x1348, 0x1350
+            };
+            return toAlphabetic(value, ethiopicHalehameTigAlphabet);
+        }
+        case TigrinyaEr:
+        case EthiopicHalehameTiEr: {
+            static const UChar ethiopicHalehameTiErAlphabet[31] = {
+                0x1200, 0x1208, 0x1210, 0x1218, 0x1228, 0x1230, 0x1238, 0x1240, 0x1250,
+                0x1260, 0x1270, 0x1278, 0x1290, 0x1298, 0x12A0, 0x12A8, 0x12B8, 0x12C8,
+                0x12D0, 0x12D8, 0x12E0, 0x12E8, 0x12F0, 0x1300, 0x1308, 0x1320, 0x1328,
+                0x1330, 0x1338, 0x1348, 0x1350
+            };
+            return toAlphabetic(value, ethiopicHalehameTiErAlphabet);
+        }
+        case TigrinyaErAbegede:
+        case EthiopicAbegedeTiEr: {
+            static const UChar ethiopicAbegedeTiErAlphabet[31] = {
+                0x12A0, 0x1260, 0x1308, 0x12F0, 0x1300, 0x1200, 0x12C8, 0x12D8, 0x12E0,
+                0x1210, 0x1320, 0x1328, 0x12E8, 0x12A8, 0x12B8, 0x1208, 0x1218, 0x1290,
+                0x1298, 0x12D0, 0x1348, 0x1338, 0x1240, 0x1250, 0x1228, 0x1230, 0x1238,
+                0x1270, 0x1278, 0x1330, 0x1350
+            };
+            return toAlphabetic(value, ethiopicAbegedeTiErAlphabet);
+        }
+        case TigrinyaEt:
+        case EthiopicHalehameTiEt: {
+            static const UChar ethiopicHalehameTiEtAlphabet[34] = {
+                0x1200, 0x1208, 0x1210, 0x1218, 0x1220, 0x1228, 0x1230, 0x1238, 0x1240,
+                0x1250, 0x1260, 0x1270, 0x1278, 0x1280, 0x1290, 0x1298, 0x12A0, 0x12A8,
+                0x12B8, 0x12C8, 0x12D0, 0x12D8, 0x12E0, 0x12E8, 0x12F0, 0x1300, 0x1308,
+                0x1320, 0x1328, 0x1330, 0x1338, 0x1340, 0x1348, 0x1350
+            };
+            return toAlphabetic(value, ethiopicHalehameTiEtAlphabet);
+        }
+        case TigrinyaEtAbegede:
+        case EthiopicAbegedeTiEt: {
+            static const UChar ethiopicAbegedeTiEtAlphabet[34] = {
+                0x12A0, 0x1260, 0x1308, 0x12F0, 0x1300, 0x1200, 0x12C8, 0x12D8, 0x12E0,
+                0x1210, 0x1320, 0x1328, 0x12E8, 0x12A8, 0x12B8, 0x1208, 0x1218, 0x1290,
+                0x1298, 0x1220, 0x12D0, 0x1348, 0x1338, 0x1240, 0x1250, 0x1228, 0x1230,
+                0x1238, 0x1270, 0x1278, 0x1280, 0x1340, 0x1330, 0x1350
+            };
+            return toAlphabetic(value, ethiopicAbegedeTiEtAlphabet);
+        }
+        case UpperGreek: {
+            static const UChar upperGreekAlphabet[24] = {
+                0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399,
+                0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, 0x03A0, 0x03A1, 0x03A3,
+                0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9
+            };
+            return toAlphabetic(value, upperGreekAlphabet);
+        }
+        case LowerNorwegian: {
+            static const LChar lowerNorwegianAlphabet[29] = {
+                0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
+                0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72,
+                0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0xE6,
+                0xF8, 0xE5
+            };
+            return toAlphabetic(value, lowerNorwegianAlphabet);
+        }
+        case UpperNorwegian: {
+            static const LChar upperNorwegianAlphabet[29] = {
+                0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
+                0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52,
+                0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0xC6,
+                0xD8, 0xC5
+            };
+            return toAlphabetic(value, upperNorwegianAlphabet);
+        }
+        case CJKIdeographic: {
+            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 LowerRoman:
+            return toRoman(value, false);
+        case UpperRoman:
+            return toRoman(value, true);
+
+        case Armenian:
+        case UpperArmenian:
+            // 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 LowerArmenian:
+            return toArmenian(value, false);
+        case Georgian:
+            return toGeorgian(value);
+        case Hebrew:
+            return toHebrew(value);
+    }
+
+    ASSERT_NOT_REACHED();
+    return "";
+}
+
+RenderListMarker::RenderListMarker(RenderListItem* item)
+    : RenderBox(0)
+    , m_listItem(item)
+{
+    // init RenderObject attributes
+    setInline(true);   // our object is Inline
+    setReplaced(true); // pretend to be replaced
+}
+
+RenderListMarker::~RenderListMarker()
+{
+    if (m_image)
+        m_image->removeClient(this);
+}
+
+RenderListMarker* RenderListMarker::createAnonymous(RenderListItem* item)
+{
+    Document* document = item->document();
+    RenderListMarker* renderer = new (document->renderArena()) RenderListMarker(item);
+    renderer->setDocumentForAnonymous(document);
+    return renderer;
+}
+
+void RenderListMarker::styleWillChange(StyleDifference diff, const RenderStyle* newStyle)
+{
+    if (style() && (newStyle->listStylePosition() != style()->listStylePosition() || newStyle->listStyleType() != style()->listStyleType()))
+        setNeedsLayoutAndPrefWidthsRecalc();
+    
+    RenderBox::styleWillChange(diff, newStyle);
+}
+
+void RenderListMarker::styleDidChange(StyleDifference 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()
+{
+    InlineBox* result = RenderBox::createInlineBox();
+    result->setIsText(isText());
+    return result;
+}
+
+bool RenderListMarker::isImage() const
+{
+    return m_image && !m_image->errorOccurred();
+}
+
+LayoutRect RenderListMarker::localSelectionRect()
+{
+    InlineBox* box = inlineBoxWrapper();
+    if (!box)
+        return LayoutRect(LayoutPoint(), size());
+    RootInlineBox* root = m_inlineBoxWrapper->root();
+    LayoutUnit newLogicalTop = root->block()->style()->isFlippedBlocksWritingMode() ? m_inlineBoxWrapper->logicalBottom() - root->selectionBottom() : root->selectionTop() - m_inlineBoxWrapper->logicalTop();
+    if (root->block()->style()->isHorizontalWritingMode())
+        return LayoutRect(0, newLogicalTop, width(), root->selectionHeight());
+    return LayoutRect(newLogicalTop, 0, root->selectionHeight(), height());
+}
+
+void RenderListMarker::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    if (paintInfo.phase != PaintPhaseForeground)
+        return;
+    
+    if (style()->visibility() != VISIBLE)
+        return;
+
+    LayoutPoint boxOrigin(paintOffset + location());
+    LayoutRect overflowRect(visualOverflowRect());
+    overflowRect.moveBy(boxOrigin);
+    overflowRect.inflate(maximalOutlineSize(paintInfo.phase));
+
+    if (!paintInfo.rect.intersects(pixelSnappedIntRect(overflowRect)))
+        return;
+
+    LayoutRect box(boxOrigin, size());
+    
+    IntRect marker = getRelativeMarkerRect();
+    marker.moveBy(roundedIntPoint(boxOrigin));
+
+    GraphicsContext* context = paintInfo.context;
+
+    if (isImage()) {
+        context->drawImage(m_image->image(this, marker.size()).get(), style()->colorSpace(), marker);
+        if (selectionState() != SelectionNone) {
+            LayoutRect selRect = localSelectionRect();
+            selRect.moveBy(boxOrigin);
+            context->fillRect(pixelSnappedIntRect(selRect), selectionBackgroundColor(), style()->colorSpace());
+        }
+        return;
+    }
+
+    if (selectionState() != SelectionNone) {
+        LayoutRect selRect = localSelectionRect();
+        selRect.moveBy(boxOrigin);
+        context->fillRect(pixelSnappedIntRect(selRect), selectionBackgroundColor(), style()->colorSpace());
+    }
+
+    const Color color(style()->visitedDependentColor(CSSPropertyColor));
+    context->setStrokeColor(color, style()->colorSpace());
+    context->setStrokeStyle(SolidStroke);
+    context->setStrokeThickness(1.0f);
+    context->setFillColor(color, style()->colorSpace());
+
+    EListStyleType type = style()->listStyleType();
+    switch (type) {
+        case Disc:
+            context->drawEllipse(marker);
+            return;
+        case Circle:
+            context->setFillColor(Color::transparent, ColorSpaceDeviceRGB);
+            context->drawEllipse(marker);
+            return;
+        case Square:
+            context->drawRect(marker);
+            return;
+        case NoneListStyle:
+            return;
+        case Afar:
+        case Amharic:
+        case AmharicAbegede:
+        case ArabicIndic:
+        case Armenian:
+        case BinaryListStyle:
+        case Bengali:
+        case Cambodian:
+        case CJKIdeographic:
+        case CjkEarthlyBranch:
+        case CjkHeavenlyStem:
+        case DecimalLeadingZero:
+        case DecimalListStyle:
+        case Devanagari:
+        case Ethiopic:
+        case EthiopicAbegede:
+        case EthiopicAbegedeAmEt:
+        case EthiopicAbegedeGez:
+        case EthiopicAbegedeTiEr:
+        case EthiopicAbegedeTiEt:
+        case EthiopicHalehameAaEr:
+        case EthiopicHalehameAaEt:
+        case EthiopicHalehameAmEt:
+        case EthiopicHalehameGez:
+        case EthiopicHalehameOmEt:
+        case EthiopicHalehameSidEt:
+        case EthiopicHalehameSoEt:
+        case EthiopicHalehameTiEr:
+        case EthiopicHalehameTiEt:
+        case EthiopicHalehameTig:
+        case Georgian:
+        case Gujarati:
+        case Gurmukhi:
+        case Hangul:
+        case HangulConsonant:
+        case Hebrew:
+        case Hiragana:
+        case HiraganaIroha:
+        case Kannada:
+        case Katakana:
+        case KatakanaIroha:
+        case Khmer:
+        case Lao:
+        case LowerAlpha:
+        case LowerArmenian:
+        case LowerGreek:
+        case LowerHexadecimal:
+        case LowerLatin:
+        case LowerNorwegian:
+        case LowerRoman:
+        case Malayalam:
+        case Mongolian:
+        case Myanmar:
+        case Octal:
+        case Oriya:
+        case Oromo:
+        case Persian:
+        case Sidama:
+        case Somali:
+        case Telugu:
+        case Thai:
+        case Tibetan:
+        case Tigre:
+        case TigrinyaEr:
+        case TigrinyaErAbegede:
+        case TigrinyaEt:
+        case TigrinyaEtAbegede:
+        case UpperAlpha:
+        case UpperArmenian:
+        case UpperGreek:
+        case UpperHexadecimal:
+        case UpperLatin:
+        case UpperNorwegian:
+        case UpperRoman:
+        case Urdu:
+        case Asterisks:
+        case Footnotes:
+            break;
+    }
+    if (m_text.isEmpty())
+        return;
+
+    const Font& font = style()->font();
+    TextRun textRun = RenderBlock::constructTextRun(this, font, m_text, style());
+
+    GraphicsContextStateSaver stateSaver(*context, false);
+    if (!style()->isHorizontalWritingMode()) {
+        marker.moveBy(roundedIntPoint(-boxOrigin));
+        marker = marker.transposedRect();
+        marker.moveBy(IntPoint(roundToInt(box.x()), roundToInt(box.y() - logicalHeight())));
+        stateSaver.save();
+        context->translate(marker.x(), marker.maxY());
+        context->rotate(static_cast<float>(deg2rad(90.)));
+        context->translate(-marker.x(), -marker.maxY());
+    }
+
+    IntPoint textOrigin = IntPoint(marker.x(), marker.y() + style()->fontMetrics().ascent());
+
+    if (type == Asterisks || type == Footnotes)
+        context->drawText(font, textRun, textOrigin);
+    else {
+        // 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;
+        StringBuilder reversedText;
+        if (textNeedsReversing) {
+            int length = m_text.length();
+            reversedText.reserveCapacity(length);
+            for (int i = length - 1; i >= 0; --i)
+                reversedText.append(m_text[i]);
+            textRun.setText(reversedText.characters(), length);
+        }
+
+        const UChar suffix = listMarkerSuffix(type, m_listItem->value());
+        if (style()->isLeftToRightDirection()) {
+            int width = font.width(textRun);
+            context->drawText(font, textRun, textOrigin);
+            UChar suffixSpace[2] = { suffix, ' ' };
+            context->drawText(font, RenderBlock::constructTextRun(this, font, suffixSpace, 2, style()), textOrigin + IntSize(width, 0));
+        } else {
+            UChar spaceSuffix[2] = { ' ', suffix };
+            TextRun spaceSuffixRun = RenderBlock::constructTextRun(this, font, spaceSuffix, 2, style());
+            int width = font.width(spaceSuffixRun);
+            context->drawText(font, spaceSuffixRun, textOrigin);
+            context->drawText(font, textRun, textOrigin + IntSize(width, 0));
+        }
+    }
+}
+
+void RenderListMarker::layout()
+{
+    StackStats::LayoutCheckPoint layoutCheckPoint;
+    ASSERT(needsLayout());
+ 
+    if (isImage()) {
+        updateMarginsAndContent();
+        setWidth(m_image->imageSize(this, style()->effectiveZoom()).width());
+        setHeight(m_image->imageSize(this, style()->effectiveZoom()).height());
+    } else {
+        setLogicalWidth(minPreferredLogicalWidth());
+        setLogicalHeight(style()->fontMetrics().height());
+    }
+
+    setMarginStart(0);
+    setMarginEnd(0);
+
+    Length startMargin = style()->marginStart();
+    Length endMargin = style()->marginEnd();
+    if (startMargin.isFixed())
+        setMarginStart(startMargin.value());
+    if (endMargin.isFixed())
+        setMarginEnd(endMargin.value());
+
+    setNeedsLayout(false);
+}
+
+void RenderListMarker::imageChanged(WrappedImagePtr o, const IntRect*)
+{
+    // 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 (width() != m_image->imageSize(this, style()->effectiveZoom()).width() || height() != m_image->imageSize(this, style()->effectiveZoom()).height() || m_image->errorOccurred())
+        setNeedsLayoutAndPrefWidthsRecalc();
+    else
+        repaint();
+}
+
+void RenderListMarker::updateMarginsAndContent()
+{
+    updateContent();
+    updateMargins();
+}
+
+void RenderListMarker::updateContent()
+{
+    // FIXME: This if-statement is just a performance optimization, but it's messy to use the preferredLogicalWidths dirty bit for this.
+    // It's unclear if this is a premature optimization.
+    if (!preferredLogicalWidthsDirty())
+        return;
+
+    m_text = "";
+
+    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 = style()->fontMetrics().ascent() / 2;
+        m_image->setContainerSizeForRenderer(this, IntSize(bulletWidth, bulletWidth), style()->effectiveZoom());
+        return;
+    }
+
+    EListStyleType type = style()->listStyleType();
+    switch (type) {
+    case NoneListStyle:
+        break;
+    case Circle:
+    case Disc:
+    case Square:
+        m_text = listMarkerText(type, 0); // value is ignored for these types
+        break;
+    case Asterisks:
+    case Footnotes:
+    case Afar:
+    case Amharic:
+    case AmharicAbegede:
+    case ArabicIndic:
+    case Armenian:
+    case BinaryListStyle:
+    case Bengali:
+    case Cambodian:
+    case CJKIdeographic:
+    case CjkEarthlyBranch:
+    case CjkHeavenlyStem:
+    case DecimalLeadingZero:
+    case DecimalListStyle:
+    case Devanagari:
+    case Ethiopic:
+    case EthiopicAbegede:
+    case EthiopicAbegedeAmEt:
+    case EthiopicAbegedeGez:
+    case EthiopicAbegedeTiEr:
+    case EthiopicAbegedeTiEt:
+    case EthiopicHalehameAaEr:
+    case EthiopicHalehameAaEt:
+    case EthiopicHalehameAmEt:
+    case EthiopicHalehameGez:
+    case EthiopicHalehameOmEt:
+    case EthiopicHalehameSidEt:
+    case EthiopicHalehameSoEt:
+    case EthiopicHalehameTiEr:
+    case EthiopicHalehameTiEt:
+    case EthiopicHalehameTig:
+    case Georgian:
+    case Gujarati:
+    case Gurmukhi:
+    case Hangul:
+    case HangulConsonant:
+    case Hebrew:
+    case Hiragana:
+    case HiraganaIroha:
+    case Kannada:
+    case Katakana:
+    case KatakanaIroha:
+    case Khmer:
+    case Lao:
+    case LowerAlpha:
+    case LowerArmenian:
+    case LowerGreek:
+    case LowerHexadecimal:
+    case LowerLatin:
+    case LowerNorwegian:
+    case LowerRoman:
+    case Malayalam:
+    case Mongolian:
+    case Myanmar:
+    case Octal:
+    case Oriya:
+    case Oromo:
+    case Persian:
+    case Sidama:
+    case Somali:
+    case Telugu:
+    case Thai:
+    case Tibetan:
+    case Tigre:
+    case TigrinyaEr:
+    case TigrinyaErAbegede:
+    case TigrinyaEt:
+    case TigrinyaEtAbegede:
+    case UpperAlpha:
+    case UpperArmenian:
+    case UpperGreek:
+    case UpperHexadecimal:
+    case UpperLatin:
+    case UpperNorwegian:
+    case UpperRoman:
+    case Urdu:
+        m_text = listMarkerText(type, m_listItem->value());
+        break;
+    }
+}
+
+void RenderListMarker::computePreferredLogicalWidths()
+{
+    ASSERT(preferredLogicalWidthsDirty());
+    updateContent();
+
+    if (isImage()) {
+        LayoutSize imageSize = m_image->imageSize(this, style()->effectiveZoom());
+        m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = style()->isHorizontalWritingMode() ? imageSize.width() : imageSize.height();
+        setPreferredLogicalWidthsDirty(false);
+        updateMargins();
+        return;
+    }
+
+    const Font& font = style()->font();
+
+    LayoutUnit logicalWidth = 0;
+    EListStyleType type = style()->listStyleType();
+    switch (type) {
+        case NoneListStyle:
+            break;
+        case Asterisks:
+        case Footnotes:
+            logicalWidth = font.width(m_text); // no suffix for these types
+            break;
+        case Circle:
+        case Disc:
+        case Square:
+            logicalWidth = (font.fontMetrics().ascent() * 2 / 3 + 1) / 2 + 2;
+            break;
+        case Afar:
+        case Amharic:
+        case AmharicAbegede:
+        case ArabicIndic:
+        case Armenian:
+        case BinaryListStyle:
+        case Bengali:
+        case Cambodian:
+        case CJKIdeographic:
+        case CjkEarthlyBranch:
+        case CjkHeavenlyStem:
+        case DecimalLeadingZero:
+        case DecimalListStyle:
+        case Devanagari:
+        case Ethiopic:
+        case EthiopicAbegede:
+        case EthiopicAbegedeAmEt:
+        case EthiopicAbegedeGez:
+        case EthiopicAbegedeTiEr:
+        case EthiopicAbegedeTiEt:
+        case EthiopicHalehameAaEr:
+        case EthiopicHalehameAaEt:
+        case EthiopicHalehameAmEt:
+        case EthiopicHalehameGez:
+        case EthiopicHalehameOmEt:
+        case EthiopicHalehameSidEt:
+        case EthiopicHalehameSoEt:
+        case EthiopicHalehameTiEr:
+        case EthiopicHalehameTiEt:
+        case EthiopicHalehameTig:
+        case Georgian:
+        case Gujarati:
+        case Gurmukhi:
+        case Hangul:
+        case HangulConsonant:
+        case Hebrew:
+        case Hiragana:
+        case HiraganaIroha:
+        case Kannada:
+        case Katakana:
+        case KatakanaIroha:
+        case Khmer:
+        case Lao:
+        case LowerAlpha:
+        case LowerArmenian:
+        case LowerGreek:
+        case LowerHexadecimal:
+        case LowerLatin:
+        case LowerNorwegian:
+        case LowerRoman:
+        case Malayalam:
+        case Mongolian:
+        case Myanmar:
+        case Octal:
+        case Oriya:
+        case Oromo:
+        case Persian:
+        case Sidama:
+        case Somali:
+        case Telugu:
+        case Thai:
+        case Tibetan:
+        case Tigre:
+        case TigrinyaEr:
+        case TigrinyaErAbegede:
+        case TigrinyaEt:
+        case TigrinyaEtAbegede:
+        case UpperAlpha:
+        case UpperArmenian:
+        case UpperGreek:
+        case UpperHexadecimal:
+        case UpperLatin:
+        case UpperNorwegian:
+        case UpperRoman:
+        case Urdu:
+            if (m_text.isEmpty())
+                logicalWidth = 0;
+            else {
+                LayoutUnit itemWidth = font.width(m_text);
+                UChar suffixSpace[2] = { listMarkerSuffix(type, m_listItem->value()), ' ' };
+                LayoutUnit suffixSpaceWidth = font.width(RenderBlock::constructTextRun(this, font, suffixSpace, 2, style()));
+                logicalWidth = itemWidth + suffixSpaceWidth;
+            }
+            break;
+    }
+
+    m_minPreferredLogicalWidth = logicalWidth;
+    m_maxPreferredLogicalWidth = logicalWidth;
+
+    setPreferredLogicalWidthsDirty(false);
+
+    updateMargins();
+}
+
+void RenderListMarker::updateMargins()
+{
+    const FontMetrics& fontMetrics = style()->fontMetrics();
+
+    LayoutUnit marginStart = 0;
+    LayoutUnit marginEnd = 0;
+
+    if (isInside()) {
+        if (isImage())
+            marginEnd = cMarkerPadding;
+        else switch (style()->listStyleType()) {
+            case Disc:
+            case Circle:
+            case Square:
+                marginStart = -1;
+                marginEnd = fontMetrics.ascent() - minPreferredLogicalWidth() + 1;
+                break;
+            default:
+                break;
+        }
+    } else {
+        if (style()->isLeftToRightDirection()) {
+            if (isImage())
+                marginStart = -minPreferredLogicalWidth() - cMarkerPadding;
+            else {
+                int offset = fontMetrics.ascent() * 2 / 3;
+                switch (style()->listStyleType()) {
+                    case Disc:
+                    case Circle:
+                    case Square:
+                        marginStart = -offset - cMarkerPadding - 1;
+                        break;
+                    case NoneListStyle:
+                        break;
+                    default:
+                        marginStart = m_text.isEmpty() ? LayoutUnit() : -minPreferredLogicalWidth() - offset / 2;
+                }
+            }
+            marginEnd = -marginStart - minPreferredLogicalWidth();
+        } else {
+            if (isImage())
+                marginEnd = cMarkerPadding;
+            else {
+                int offset = fontMetrics.ascent() * 2 / 3;
+                switch (style()->listStyleType()) {
+                    case Disc:
+                    case Circle:
+                    case Square:
+                        marginEnd = offset + cMarkerPadding + 1 - minPreferredLogicalWidth();
+                        break;
+                    case NoneListStyle:
+                        break;
+                    default:
+                        marginEnd = m_text.isEmpty() ? 0 : offset / 2;
+                }
+            }
+            marginStart = -marginEnd - minPreferredLogicalWidth();
+        }
+        
+    }
+
+    style()->setMarginStart(Length(marginStart, Fixed));
+    style()->setMarginEnd(Length(marginEnd, Fixed));
+}
+
+LayoutUnit RenderListMarker::lineHeight(bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const
+{
+    if (!isImage())
+        return m_listItem->lineHeight(firstLine, direction, PositionOfInteriorLineBoxes);
+    return RenderBox::lineHeight(firstLine, direction, linePositionMode);
+}
+
+int RenderListMarker::baselinePosition(FontBaseline baselineType, bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const
+{
+    ASSERT(linePositionMode == PositionOnContainingLine);
+    if (!isImage())
+        return m_listItem->baselinePosition(baselineType, firstLine, direction, PositionOfInteriorLineBoxes);
+    return RenderBox::baselinePosition(baselineType, firstLine, direction, linePositionMode);
+}
+
+String RenderListMarker::suffix() const
+{
+    EListStyleType type = style()->listStyleType();
+    const UChar suffix = listMarkerSuffix(type, m_listItem->value());
+
+    if (suffix == ' ')
+        return String(" ");
+
+    // If the suffix is not ' ', an extra space is needed
+    UChar data[2];
+    if (style()->isLeftToRightDirection()) {
+        data[0] = suffix;
+        data[1] = ' ';
+    } else {
+        data[0] = ' ';
+        data[1] = suffix;
+    }
+
+    return String(data, 2);
+}
+
+bool RenderListMarker::isInside() const
+{
+    return m_listItem->notInList() || style()->listStylePosition() == INSIDE;
+}
+
+IntRect RenderListMarker::getRelativeMarkerRect()
+{
+    if (isImage())
+        return IntRect(0, 0, m_image->imageSize(this, style()->effectiveZoom()).width(), m_image->imageSize(this, style()->effectiveZoom()).height());
+    
+    IntRect relativeRect;
+    EListStyleType type = style()->listStyleType();
+    switch (type) {
+        case Asterisks:
+        case Footnotes: {
+            const Font& font = style()->font();
+            relativeRect = IntRect(0, 0, font.width(m_text), font.fontMetrics().height());
+            break;
+        }
+        case Disc:
+        case Circle:
+        case Square: {
+            // FIXME: Are these particular rounding rules necessary?
+            const FontMetrics& fontMetrics = style()->fontMetrics();
+            int ascent = fontMetrics.ascent();
+            int bulletWidth = (ascent * 2 / 3 + 1) / 2;
+            relativeRect = IntRect(1, 3 * (ascent - ascent * 2 / 3) / 2, bulletWidth, bulletWidth);
+            break;
+        }
+        case NoneListStyle:
+            return IntRect();
+        case Afar:
+        case Amharic:
+        case AmharicAbegede:
+        case ArabicIndic:
+        case Armenian:
+        case BinaryListStyle:
+        case Bengali:
+        case Cambodian:
+        case CJKIdeographic:
+        case CjkEarthlyBranch:
+        case CjkHeavenlyStem:
+        case DecimalLeadingZero:
+        case DecimalListStyle:
+        case Devanagari:
+        case Ethiopic:
+        case EthiopicAbegede:
+        case EthiopicAbegedeAmEt:
+        case EthiopicAbegedeGez:
+        case EthiopicAbegedeTiEr:
+        case EthiopicAbegedeTiEt:
+        case EthiopicHalehameAaEr:
+        case EthiopicHalehameAaEt:
+        case EthiopicHalehameAmEt:
+        case EthiopicHalehameGez:
+        case EthiopicHalehameOmEt:
+        case EthiopicHalehameSidEt:
+        case EthiopicHalehameSoEt:
+        case EthiopicHalehameTiEr:
+        case EthiopicHalehameTiEt:
+        case EthiopicHalehameTig:
+        case Georgian:
+        case Gujarati:
+        case Gurmukhi:
+        case Hangul:
+        case HangulConsonant:
+        case Hebrew:
+        case Hiragana:
+        case HiraganaIroha:
+        case Kannada:
+        case Katakana:
+        case KatakanaIroha:
+        case Khmer:
+        case Lao:
+        case LowerAlpha:
+        case LowerArmenian:
+        case LowerGreek:
+        case LowerHexadecimal:
+        case LowerLatin:
+        case LowerNorwegian:
+        case LowerRoman:
+        case Malayalam:
+        case Mongolian:
+        case Myanmar:
+        case Octal:
+        case Oriya:
+        case Oromo:
+        case Persian:
+        case Sidama:
+        case Somali:
+        case Telugu:
+        case Thai:
+        case Tibetan:
+        case Tigre:
+        case TigrinyaEr:
+        case TigrinyaErAbegede:
+        case TigrinyaEt:
+        case TigrinyaEtAbegede:
+        case UpperAlpha:
+        case UpperArmenian:
+        case UpperGreek:
+        case UpperHexadecimal:
+        case UpperLatin:
+        case UpperNorwegian:
+        case UpperRoman:
+        case Urdu:
+            if (m_text.isEmpty())
+                return IntRect();
+            const Font& font = style()->font();
+            int itemWidth = font.width(m_text);
+            UChar suffixSpace[2] = { listMarkerSuffix(type, m_listItem->value()), ' ' };
+            int suffixSpaceWidth = font.width(RenderBlock::constructTextRun(this, font, suffixSpace, 2, style()));
+            relativeRect = IntRect(0, 0, itemWidth + suffixSpaceWidth, font.fontMetrics().height());
+    }
+
+    if (!style()->isHorizontalWritingMode()) {
+        relativeRect = relativeRect.transposedRect();
+        relativeRect.setX(width() - relativeRect.x() - relativeRect.width());
+    }
+
+    return relativeRect;
+}
+
+void RenderListMarker::setSelectionState(SelectionState state)
+{
+    // The selection state for our containing block hierarchy is updated by the base class call.
+    RenderBox::setSelectionState(state);
+
+    if (m_inlineBoxWrapper && canUpdateSelectionOnRootLineBoxes())
+        if (RootInlineBox* root = m_inlineBoxWrapper->root())
+            root->setHasSelectedChildren(state != SelectionNone);
+}
+
+LayoutRect RenderListMarker::selectionRectForRepaint(const RenderLayerModelObject* repaintContainer, bool clipToVisibleContent)
+{
+    ASSERT(!needsLayout());
+
+    if (selectionState() == SelectionNone || !inlineBoxWrapper())
+        return LayoutRect();
+
+    RootInlineBox* root = inlineBoxWrapper()->root();
+    LayoutRect rect(0, root->selectionTop() - y(), width(), root->selectionHeight());
+            
+    if (clipToVisibleContent)
+        computeRectForRepaint(repaintContainer, rect);
+    else
+        rect = localToContainerQuad(FloatRect(rect), repaintContainer).enclosingBoundingBox();
+    
+    return rect;
+}
+
+void RenderListMarker::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, PlatformMemoryTypes::Rendering);
+    RenderBox::reportMemoryUsage(memoryObjectInfo);
+    info.addMember(m_text, "text");
+    info.addMember(m_image, "image");
+    info.addMember(m_listItem, "listItem");
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderListMarker.h b/Source/core/rendering/RenderListMarker.h
new file mode 100644
index 0000000..e5ca966
--- /dev/null
+++ b/Source/core/rendering/RenderListMarker.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2009 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 "core/rendering/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 FINAL : public RenderBox {
+public:
+    static RenderListMarker* createAnonymous(RenderListItem*);
+
+    virtual ~RenderListMarker();
+
+    const String& text() const { return m_text; }
+    String suffix() const;
+
+    bool isInside() const;
+
+    virtual void reportMemoryUsage(MemoryObjectInfo*) const OVERRIDE;
+
+    void updateMarginsAndContent();
+
+private:
+    RenderListMarker(RenderListItem*);
+
+    virtual const char* renderName() const { return "RenderListMarker"; }
+    virtual void computePreferredLogicalWidths() OVERRIDE;
+
+    virtual bool isListMarker() const { return true; }
+
+    virtual void paint(PaintInfo&, const LayoutPoint&);
+
+    virtual void layout();
+
+    virtual void imageChanged(WrappedImagePtr, const IntRect* = 0);
+
+    virtual InlineBox* createInlineBox();
+
+    virtual LayoutUnit lineHeight(bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const;
+    virtual int baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const;
+
+    bool isImage() const;
+    bool isText() const { return !isImage(); }
+
+    virtual void setSelectionState(SelectionState);
+    virtual LayoutRect selectionRectForRepaint(const RenderLayerModelObject* repaintContainer, bool clipToVisibleContent = true) OVERRIDE;
+    virtual bool canBeSelectionLeaf() const { return true; }
+
+    void updateMargins();
+    void updateContent();
+
+    virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle);
+    virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+
+    IntRect getRelativeMarkerRect();
+    LayoutRect localSelectionRect();
+
+    String m_text;
+    RefPtr<StyleImage> m_image;
+    RenderListItem* m_listItem;
+};
+
+inline RenderListMarker* toRenderListMarker(RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isListMarker());
+    return static_cast<RenderListMarker*>(object);
+}
+
+inline const RenderListMarker* toRenderListMarker(const RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isListMarker());
+    return static_cast<const RenderListMarker*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderListMarker(const RenderListMarker*);
+
+} // namespace WebCore
+
+#endif // RenderListMarker_h
diff --git a/Source/core/rendering/RenderMarquee.cpp b/Source/core/rendering/RenderMarquee.cpp
new file mode 100644
index 0000000..8f91652
--- /dev/null
+++ b/Source/core/rendering/RenderMarquee.cpp
@@ -0,0 +1,311 @@
+/*
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ *
+ * Portions are Copyright (C) 1998 Netscape Communications Corporation.
+ *
+ * Other contributors:
+ *   Robert O'Callahan <roc+@cs.cmu.edu>
+ *   David Baron <dbaron@fas.harvard.edu>
+ *   Christian Biesinger <cbiesinger@web.de>
+ *   Randall Jesup <rjesup@wgate.com>
+ *   Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
+ *   Josh Soref <timeless@mac.com>
+ *   Boris Zbarsky <bzbarsky@mit.edu>
+ *
+ * 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 "core/rendering/RenderMarquee.h"
+
+#include "HTMLNames.h"
+#include "core/html/HTMLMarqueeElement.h"
+#include "core/page/FrameView.h"
+#include "core/rendering/RenderLayer.h"
+#include "core/rendering/RenderView.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)
+{
+}
+
+RenderMarquee::~RenderMarquee()
+{
+}
+
+int RenderMarquee::marqueeSpeed() const
+{
+    int result = m_layer->renderer()->style()->marqueeSpeed();
+    Node* n = m_layer->renderer()->node();
+    if (n && n->hasTagName(marqueeTag)) {
+        HTMLMarqueeElement* marqueeElt = static_cast<HTMLMarqueeElement*>(n);
+        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)
+{
+    RenderBox* box = m_layer->renderBox();
+    ASSERT(box);
+    RenderStyle* s = box->style();
+    if (isHorizontal()) {
+        bool ltr = s->isLeftToRightDirection();
+        LayoutUnit clientWidth = box->clientWidth();
+        LayoutUnit contentWidth = ltr ? box->maxPreferredLogicalWidth() : box->minPreferredLogicalWidth();
+        if (ltr)
+            contentWidth += (box->paddingRight() - box->borderLeft());
+        else {
+            contentWidth = box->width() - contentWidth;
+            contentWidth += (box->paddingLeft() - box->borderRight());
+        }
+        if (dir == MRIGHT) {
+            if (stopAtContentEdge)
+                return max<LayoutUnit>(0, ltr ? (contentWidth - clientWidth) : (clientWidth - contentWidth));
+            else
+                return ltr ? contentWidth : clientWidth;
+        }
+        else {
+            if (stopAtContentEdge)
+                return min<LayoutUnit>(0, ltr ? (contentWidth - clientWidth) : (clientWidth - contentWidth));
+            else
+                return ltr ? -clientWidth : -contentWidth;
+        }
+    }
+    else {
+        int contentHeight = box->layoutOverflowRect().maxY() - box->borderTop() + box->paddingBottom();
+        int clientHeight = box->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(IntSize(m_start, 0));
+        else
+            m_layer->scrollToOffset(IntSize(0, m_start));
+    }
+    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(TASTART);
+        }
+    }
+    
+    // Legacy hack - multiple browsers default vertical marquees to 200px tall.
+    if (!isHorizontal() && s->height().isAuto())
+        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()->view()->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->renderBox()->clientWidth() : m_layer->renderBox()->clientHeight());
+        int increment = abs(intValueForLength(m_layer->renderer()->style()->marqueeIncrement(), 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/Source/core/rendering/RenderMarquee.h b/Source/core/rendering/RenderMarquee.h
new file mode 100644
index 0000000..ce69255
--- /dev/null
+++ b/Source/core/rendering/RenderMarquee.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2003 Apple Computer, Inc.
+ *
+ * Portions are Copyright (C) 1998 Netscape Communications Corporation.
+ *
+ * Other contributors:
+ *   Robert O'Callahan <roc+@cs.cmu.edu>
+ *   David Baron <dbaron@fas.harvard.edu>
+ *   Christian Biesinger <cbiesinger@web.de>
+ *   Randall Jesup <rjesup@wgate.com>
+ *   Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
+ *   Josh Soref <timeless@mac.com>
+ *   Boris Zbarsky <bzbarsky@mit.edu>
+ *
+ * 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 "core/platform/Length.h"
+#include "core/platform/Timer.h"
+#include "core/rendering/style/RenderStyleConstants.h"
+
+namespace WebCore {
+
+class RenderLayer;
+
+// This class handles the auto-scrolling of layers with overflow: marquee.
+class RenderMarquee {
+    WTF_MAKE_NONCOPYABLE(RenderMarquee); WTF_MAKE_FAST_ALLOCATED;
+public:
+    explicit RenderMarquee(RenderLayer*);
+    virtual ~RenderMarquee();
+
+    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/Source/core/rendering/RenderMedia.cpp b/Source/core/rendering/RenderMedia.cpp
new file mode 100644
index 0000000..20634e4
--- /dev/null
+++ b/Source/core/rendering/RenderMedia.cpp
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2007, 2008, 2009, 2010 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 "core/rendering/RenderMedia.h"
+
+#include "core/html/HTMLMediaElement.h"
+#include "core/rendering/RenderFlowThread.h"
+#include "core/rendering/RenderView.h"
+
+namespace WebCore {
+
+RenderMedia::RenderMedia(HTMLMediaElement* video)
+    : RenderImage(video)
+{
+    setImageResource(RenderImageResource::create());
+}
+
+RenderMedia::RenderMedia(HTMLMediaElement* video, const IntSize& intrinsicSize)
+    : RenderImage(video)
+{
+    setImageResource(RenderImageResource::create());
+    setIntrinsicSize(intrinsicSize);
+}
+
+RenderMedia::~RenderMedia()
+{
+}
+
+HTMLMediaElement* RenderMedia::mediaElement() const
+{ 
+    return toMediaElement(node()); 
+}
+
+void RenderMedia::layout()
+{
+    StackStats::LayoutCheckPoint layoutCheckPoint;
+    LayoutSize oldSize = contentBoxRect().size();
+
+    RenderImage::layout();
+
+    RenderBox* controlsRenderer = toRenderBox(m_children.firstChild());
+    if (!controlsRenderer)
+        return;
+
+    bool controlsNeedLayout = controlsRenderer->needsLayout();
+    // If the region chain has changed we also need to relayout the controls to update the region box info.
+    // FIXME: We can do better once we compute region box info for RenderReplaced, not only for RenderBlock.
+    const RenderFlowThread* flowThread = flowThreadContainingBlock();
+    if (flowThread && !controlsNeedLayout) {
+        if (flowThread->pageLogicalSizeChanged())
+            controlsNeedLayout = true;
+    }
+
+    LayoutSize newSize = contentBoxRect().size();
+    if (newSize == oldSize && !controlsNeedLayout)
+        return;
+
+    // When calling layout() on a child node, a parent must either push a LayoutStateMaintainter, or 
+    // instantiate LayoutStateDisabler. Since using a LayoutStateMaintainer is slightly more efficient,
+    // and this method will be called many times per second during playback, use a LayoutStateMaintainer:
+    LayoutStateMaintainer statePusher(view(), this, locationOffset(), hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode());
+
+    controlsRenderer->setLocation(LayoutPoint(borderLeft(), borderTop()) + LayoutSize(paddingLeft(), paddingTop()));
+    controlsRenderer->style()->setHeight(Length(newSize.height(), Fixed));
+    controlsRenderer->style()->setWidth(Length(newSize.width(), Fixed));
+    controlsRenderer->setNeedsLayout(true, MarkOnlyThis);
+    controlsRenderer->layout();
+    setChildNeedsLayout(false);
+
+    statePusher.pop();
+}
+
+void RenderMedia::paintReplaced(PaintInfo&, const LayoutPoint&)
+{
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderMedia.h b/Source/core/rendering/RenderMedia.h
new file mode 100644
index 0000000..6c99a03
--- /dev/null
+++ b/Source/core/rendering/RenderMedia.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2007, 2008, 2009, 2010 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
+
+#include "core/rendering/RenderImage.h"
+
+namespace WebCore {
+
+class HTMLMediaElement;
+
+class RenderMedia : public RenderImage {
+public:
+    explicit RenderMedia(HTMLMediaElement*);
+    RenderMedia(HTMLMediaElement*, const IntSize& intrinsicSize);
+    virtual ~RenderMedia();
+
+    RenderObject* firstChild() const { ASSERT(children() == virtualChildren()); return children()->firstChild(); }
+    RenderObject* lastChild() const { ASSERT(children() == virtualChildren()); return children()->lastChild(); }
+
+    const RenderObjectChildList* children() const { return &m_children; }
+    RenderObjectChildList* children() { return &m_children; }
+
+    HTMLMediaElement* mediaElement() const;
+
+protected:
+    virtual void layout();
+
+private:
+    virtual RenderObjectChildList* virtualChildren() OVERRIDE FINAL { return children(); }
+    virtual const RenderObjectChildList* virtualChildren() const OVERRIDE FINAL { return children(); }
+    virtual bool canHaveChildren() const OVERRIDE FINAL { return true; }
+
+    virtual const char* renderName() const { return "RenderMedia"; }
+    virtual bool isMedia() const OVERRIDE FINAL { return true; }
+    virtual bool isImage() const OVERRIDE FINAL { return false; }
+    virtual void paintReplaced(PaintInfo&, const LayoutPoint&);
+
+    virtual bool requiresForcedStyleRecalcPropagation() const OVERRIDE FINAL { return true; }
+
+    RenderObjectChildList m_children;
+};
+
+inline RenderMedia* toRenderMedia(RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isMedia());
+    return static_cast<RenderMedia*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderMedia(const RenderMedia*);
+
+} // namespace WebCore
+
+#endif // RenderMedia_h
diff --git a/Source/core/rendering/RenderMediaControlElements.cpp b/Source/core/rendering/RenderMediaControlElements.cpp
new file mode 100644
index 0000000..33ee378
--- /dev/null
+++ b/Source/core/rendering/RenderMediaControlElements.cpp
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2012 Google 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 "core/rendering/RenderMediaControlElements.h"
+
+#include "core/rendering/RenderTheme.h"
+#include "core/rendering/RenderView.h"
+
+namespace WebCore {
+
+RenderTextTrackContainerElement::RenderTextTrackContainerElement(Element* element)
+    : RenderBlock(element)
+{
+}
+
+void RenderTextTrackContainerElement::layout()
+{
+    RenderBlock::layout();
+    if (style()->display() == NONE)
+        return;
+
+    ASSERT(mediaControlElementType(node()) == MediaTextTrackDisplayContainer);
+
+    LayoutStateDisabler layoutStateDisabler(view());
+    static_cast<MediaControlTextTrackContainerElement*>(node())->updateSizes();
+}
+
+
+} // namespace WebCore
+
diff --git a/Source/core/rendering/RenderMediaControlElements.h b/Source/core/rendering/RenderMediaControlElements.h
new file mode 100644
index 0000000..863a9cf
--- /dev/null
+++ b/Source/core/rendering/RenderMediaControlElements.h
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2012 Google 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 RenderMediaControlElements_h
+#define RenderMediaControlElements_h
+
+#include "core/html/shadow/MediaControlElements.h"
+#include "core/rendering/RenderBlock.h"
+#include "core/rendering/RenderFlexibleBox.h"
+
+namespace WebCore {
+
+class RenderTextTrackContainerElement FINAL : public RenderBlock {
+public:
+    RenderTextTrackContainerElement(Element*);
+
+private:
+    virtual void layout();
+};
+
+
+} // namespace WebCore
+
+#endif // RenderMediaControlElements_h
+
diff --git a/Source/core/rendering/RenderMediaControls.cpp b/Source/core/rendering/RenderMediaControls.cpp
new file mode 100644
index 0000000..6b3af4e
--- /dev/null
+++ b/Source/core/rendering/RenderMediaControls.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2009 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 "core/rendering/RenderMediaControls.h"
+
+#include "HTMLNames.h"
+#include "core/html/HTMLMediaElement.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/rendering/PaintInfo.h"
+#include "core/rendering/RenderTheme.h"
+
+// FIXME: Unify more of the code for Mac and Win.
+
+using namespace std;
+ 
+namespace WebCore {
+}
diff --git a/Source/core/rendering/RenderMediaControls.h b/Source/core/rendering/RenderMediaControls.h
new file mode 100644
index 0000000..d1b3f87
--- /dev/null
+++ b/Source/core/rendering/RenderMediaControls.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2009 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 RenderMediaControls_h
+#define RenderMediaControls_h
+
+#include "core/html/shadow/MediaControlElements.h"
+
+namespace WebCore {
+
+struct PaintInfo;
+
+class HTMLMediaElement;
+class IntRect;
+class IntSize;
+class RenderBox;
+class RenderObject;
+class RenderStyle;
+
+class RenderMediaControls {
+public:
+};
+
+} // namespace WebCore
+
+#endif // RenderMediaControls_h
diff --git a/Source/core/rendering/RenderMediaControlsChromium.cpp b/Source/core/rendering/RenderMediaControlsChromium.cpp
new file mode 100644
index 0000000..2c40fb0
--- /dev/null
+++ b/Source/core/rendering/RenderMediaControlsChromium.cpp
@@ -0,0 +1,454 @@
+/*
+ * Copyright (C) 2009 Apple Inc.
+ * Copyright (C) 2009 Google 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 "core/rendering/RenderMediaControlsChromium.h"
+
+#include "HTMLNames.h"
+#include "core/html/HTMLMediaElement.h"
+#include "core/html/TimeRanges.h"
+#include "core/platform/graphics/Gradient.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/rendering/PaintInfo.h"
+
+namespace WebCore {
+
+typedef WTF::HashMap<const char*, Image*> MediaControlImageMap;
+static MediaControlImageMap* gMediaControlImageMap = 0;
+
+static Image* platformResource(const char* name)
+{
+    if (!gMediaControlImageMap)
+        gMediaControlImageMap = new MediaControlImageMap();
+    if (Image* image = gMediaControlImageMap->get(name))
+        return image;
+    if (Image* image = Image::loadPlatformResource(name).leakRef()) {
+        gMediaControlImageMap->set(name, image);
+        return image;
+    }
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
+static bool hasSource(const HTMLMediaElement* mediaElement)
+{
+    return mediaElement->networkState() != HTMLMediaElement::NETWORK_EMPTY
+        && mediaElement->networkState() != HTMLMediaElement::NETWORK_NO_SOURCE;
+}
+
+static bool paintMediaButton(GraphicsContext* context, const IntRect& rect, Image* image)
+{
+    context->drawImage(image, ColorSpaceDeviceRGB, rect);
+    return true;
+}
+
+static bool paintMediaMuteButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
+{
+    HTMLMediaElement* mediaElement = toParentMediaElement(object);
+    if (!mediaElement)
+      return false;
+
+    static Image* soundLevel3 = platformResource("mediaplayerSoundLevel3");
+    static Image* soundLevel2 = platformResource("mediaplayerSoundLevel2");
+    static Image* soundLevel1 = platformResource("mediaplayerSoundLevel1");
+    static Image* soundLevel0 = platformResource("mediaplayerSoundLevel0");
+    static Image* soundDisabled = platformResource("mediaplayerSoundDisabled");
+
+    if (!hasSource(mediaElement) || !mediaElement->hasAudio())
+        return paintMediaButton(paintInfo.context, rect, soundDisabled);
+
+    if (mediaElement->muted() || mediaElement->volume() <= 0)
+        return paintMediaButton(paintInfo.context, rect, soundLevel0);
+
+    if (mediaElement->volume() <= 0.33)
+        return paintMediaButton(paintInfo.context, rect, soundLevel1);
+
+    if (mediaElement->volume() <= 0.66)
+        return paintMediaButton(paintInfo.context, rect, soundLevel2);
+
+    return paintMediaButton(paintInfo.context, rect, soundLevel3);
+}
+
+static bool paintMediaPlayButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
+{
+    HTMLMediaElement* mediaElement = toParentMediaElement(object);
+    if (!mediaElement)
+        return false;
+
+    static Image* mediaPlay = platformResource("mediaplayerPlay");
+    static Image* mediaPause = platformResource("mediaplayerPause");
+    static Image* mediaPlayDisabled = platformResource("mediaplayerPlayDisabled");
+
+    if (!hasSource(mediaElement))
+        return paintMediaButton(paintInfo.context, rect, mediaPlayDisabled);
+
+    return paintMediaButton(paintInfo.context, rect, mediaElement->canPlay() ? mediaPlay : mediaPause);
+}
+
+static bool paintMediaOverlayPlayButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
+{
+    HTMLMediaElement* mediaElement = toParentMediaElement(object);
+    if (!mediaElement)
+        return false;
+
+    if (!hasSource(mediaElement) || !mediaElement->canPlay())
+        return false;
+
+    static Image* mediaOverlayPlay = platformResource("mediaplayerOverlayPlay");
+    return paintMediaButton(paintInfo.context, rect, mediaOverlayPlay);
+}
+
+static Image* getMediaSliderThumb()
+{
+    static Image* mediaSliderThumb = platformResource("mediaplayerSliderThumb");
+    return mediaSliderThumb;
+}
+
+static void paintRoundedSliderBackground(const IntRect& rect, const RenderStyle* style, GraphicsContext* context)
+{
+    int borderRadius = rect.height() / 2;
+    IntSize radii(borderRadius, borderRadius);
+    Color sliderBackgroundColor = Color(11, 11, 11);
+    context->save();
+    context->fillRoundedRect(rect, radii, radii, radii, radii, sliderBackgroundColor, ColorSpaceDeviceRGB);
+    context->restore();
+}
+
+static void paintSliderRangeHighlight(const IntRect& rect, const RenderStyle* style, GraphicsContext* context, int startPosition, int endPosition, Color startColor, Color endColor)
+{
+    // Calculate border radius; need to avoid being smaller than half the slider height
+    // because of https://bugs.webkit.org/show_bug.cgi?id=30143.
+    int borderRadius = rect.height() / 2;
+    IntSize radii(borderRadius, borderRadius);
+
+    // Calculate highlight rectangle and edge dimensions.
+    int startOffset = startPosition;
+    int endOffset = rect.width() - endPosition;
+    int rangeWidth = endPosition - startPosition;
+
+    if (rangeWidth <= 0)
+        return;
+
+    // Make sure the range width is bigger than border radius at the edges to retain rounded corners.
+    if (startOffset < borderRadius && rangeWidth < borderRadius)
+        rangeWidth = borderRadius;
+    if (endOffset < borderRadius && rangeWidth < borderRadius) {
+        startPosition -= borderRadius - rangeWidth;
+        rangeWidth = borderRadius;
+    }
+
+    // Set rectangle to highlight range.
+    IntRect highlightRect = rect;
+    highlightRect.move(startOffset, 0);
+    highlightRect.setWidth(rangeWidth);
+
+    // Don't bother drawing an empty area.
+    if (highlightRect.isEmpty())
+        return;
+
+    // Calculate white-grey gradient.
+    IntPoint sliderTopLeft = highlightRect.location();
+    IntPoint sliderBottomLeft = sliderTopLeft;
+    sliderBottomLeft.move(0, highlightRect.height());
+    RefPtr<Gradient> gradient = Gradient::create(sliderTopLeft, sliderBottomLeft);
+    gradient->addColorStop(0.0, startColor);
+    gradient->addColorStop(1.0, endColor);
+
+    // Fill highlight rectangle with gradient, potentially rounded if on left or right edge.
+    context->save();
+    context->setFillGradient(gradient);
+
+    if (startOffset < borderRadius && endOffset < borderRadius)
+        context->fillRoundedRect(highlightRect, radii, radii, radii, radii, startColor, ColorSpaceDeviceRGB);
+    else if (startOffset < borderRadius)
+        context->fillRoundedRect(highlightRect, radii, IntSize(0, 0), radii, IntSize(0, 0), startColor, ColorSpaceDeviceRGB);
+    else if (endOffset < borderRadius)
+        context->fillRoundedRect(highlightRect, IntSize(0, 0), radii, IntSize(0, 0), radii, startColor, ColorSpaceDeviceRGB);
+    else
+        context->fillRect(highlightRect);
+
+    context->restore();
+}
+
+const int mediaSliderThumbWidth = 32;
+
+static bool paintMediaSlider(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
+{
+    HTMLMediaElement* mediaElement = toParentMediaElement(object);
+    if (!mediaElement)
+        return false;
+
+    RenderStyle* style = object->style();
+    GraphicsContext* context = paintInfo.context;
+
+    paintRoundedSliderBackground(rect, style, context);
+
+    // Draw the buffered range. Since the element may have multiple buffered ranges and it'd be
+    // distracting/'busy' to show all of them, show only the buffered range containing the current play head.
+    RefPtr<TimeRanges> bufferedTimeRanges = mediaElement->buffered();
+    float duration = mediaElement->duration();
+    float currentTime = mediaElement->currentTime();
+    if (std::isnan(duration) || std::isinf(duration) || !duration || std::isnan(currentTime))
+        return true;
+
+    for (unsigned i = 0; i < bufferedTimeRanges->length(); ++i) {
+        float start = bufferedTimeRanges->start(i, ASSERT_NO_EXCEPTION);
+        float end = bufferedTimeRanges->end(i, ASSERT_NO_EXCEPTION);
+        if (std::isnan(start) || std::isnan(end) || start > currentTime || end < currentTime)
+            continue;
+        int startPosition = int(start * rect.width() / duration);
+        int currentPosition = int(currentTime * rect.width() / duration);
+        int endPosition = int(end * rect.width() / duration);
+
+        // Add half the thumb width proportionally adjusted to the current painting position.
+        int thumbCenter = mediaSliderThumbWidth / 2;
+        int addWidth = thumbCenter * (1.0 - 2.0 * currentPosition / rect.width());
+        currentPosition += addWidth;
+
+        // Draw white-ish highlight before current time.
+        Color startColor = Color(195, 195, 195);
+        Color endColor = Color(217, 217, 217);
+        if (currentPosition > startPosition)
+            paintSliderRangeHighlight(rect, style, context, startPosition, currentPosition, startColor, endColor);
+
+        // Draw grey-ish highlight after current time.
+        startColor = Color(60, 60, 60);
+        endColor = Color(76, 76, 76);
+
+        if (endPosition > currentPosition)
+            paintSliderRangeHighlight(rect, style, context, currentPosition, endPosition, startColor, endColor);
+
+        return true;
+    }
+
+    return true;
+}
+
+static bool paintMediaSliderThumb(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
+{
+    ASSERT(object->node());
+    HTMLMediaElement* mediaElement = toParentMediaElement(object->node()->shadowHost());
+    if (!mediaElement)
+        return false;
+
+    if (!hasSource(mediaElement))
+        return true;
+
+    Image* mediaSliderThumb = getMediaSliderThumb();
+    return paintMediaButton(paintInfo.context, rect, mediaSliderThumb);
+}
+
+const int mediaVolumeSliderThumbWidth = 24;
+
+static bool paintMediaVolumeSlider(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
+{
+    HTMLMediaElement* mediaElement = toParentMediaElement(object);
+    if (!mediaElement)
+        return false;
+
+    GraphicsContext* context = paintInfo.context;
+    RenderStyle* style = object->style();
+
+    paintRoundedSliderBackground(rect, style, context);
+
+    // Calculate volume position for white background rectangle.
+    float volume = mediaElement->volume();
+    if (std::isnan(volume) || volume < 0)
+        return true;
+    if (volume > 1)
+        volume = 1;
+    if (!hasSource(mediaElement) || !mediaElement->hasAudio() || mediaElement->muted())
+        volume = 0;
+
+    // Calculate the position relative to the center of the thumb.
+    float fillWidth = 0;
+    if (volume > 0) {
+        float thumbCenter = mediaVolumeSliderThumbWidth / 2;
+        float zoomLevel = style->effectiveZoom();
+        float positionWidth = volume * (rect.width() - (zoomLevel * thumbCenter));
+        fillWidth = positionWidth + (zoomLevel * thumbCenter / 2);
+    }
+
+    Color startColor = Color(195, 195, 195);
+    Color endColor = Color(217, 217, 217);
+
+    paintSliderRangeHighlight(rect, style, context, 0.0, fillWidth, startColor, endColor);
+
+    return true;
+}
+
+static bool paintMediaVolumeSliderThumb(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
+{
+    ASSERT(object->node());
+    HTMLMediaElement* mediaElement = toParentMediaElement(object->node()->shadowHost());
+    if (!mediaElement)
+        return false;
+
+    if (!hasSource(mediaElement) || !mediaElement->hasAudio())
+        return true;
+
+    static Image* mediaVolumeSliderThumb = platformResource("mediaplayerVolumeSliderThumb");
+    return paintMediaButton(paintInfo.context, rect, mediaVolumeSliderThumb);
+}
+
+static bool paintMediaFullscreenButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
+{
+    HTMLMediaElement* mediaElement = toParentMediaElement(object);
+    if (!mediaElement)
+        return false;
+
+    static Image* mediaFullscreenButton = platformResource("mediaplayerFullscreen");
+    return paintMediaButton(paintInfo.context, rect, mediaFullscreenButton);
+}
+
+static bool paintMediaToggleClosedCaptionsButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
+{
+    HTMLMediaElement* mediaElement = toParentMediaElement(object);
+    if (!mediaElement)
+        return false;
+
+    static Image* mediaClosedCaptionButton = platformResource("mediaplayerClosedCaption");
+    static Image* mediaClosedCaptionButtonDisabled = platformResource("mediaplayerClosedCaptionDisabled");
+
+    if (mediaElement->webkitClosedCaptionsVisible())
+        return paintMediaButton(paintInfo.context, rect, mediaClosedCaptionButton);
+
+    return paintMediaButton(paintInfo.context, rect, mediaClosedCaptionButtonDisabled);
+}
+
+
+bool RenderMediaControlsChromium::paintMediaControlsPart(MediaControlElementType part, RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
+{
+    switch (part) {
+    case MediaMuteButton:
+    case MediaUnMuteButton:
+        return paintMediaMuteButton(object, paintInfo, rect);
+    case MediaPauseButton:
+    case MediaPlayButton:
+        return paintMediaPlayButton(object, paintInfo, rect);
+    case MediaShowClosedCaptionsButton:
+        return paintMediaToggleClosedCaptionsButton(object, paintInfo, rect);
+    case MediaSlider:
+        return paintMediaSlider(object, paintInfo, rect);
+    case MediaSliderThumb:
+        return paintMediaSliderThumb(object, paintInfo, rect);
+    case MediaVolumeSlider:
+        return paintMediaVolumeSlider(object, paintInfo, rect);
+    case MediaVolumeSliderThumb:
+        return paintMediaVolumeSliderThumb(object, paintInfo, rect);
+    case MediaEnterFullscreenButton:
+    case MediaExitFullscreenButton:
+        return paintMediaFullscreenButton(object, paintInfo, rect);
+    case MediaOverlayPlayButton:
+        return paintMediaOverlayPlayButton(object, paintInfo, rect);
+    case MediaVolumeSliderMuteButton:
+    case MediaSeekBackButton:
+    case MediaSeekForwardButton:
+    case MediaVolumeSliderContainer:
+    case MediaTimelineContainer:
+    case MediaCurrentTimeDisplay:
+    case MediaTimeRemainingDisplay:
+    case MediaControlsPanel:
+    case MediaRewindButton:
+    case MediaReturnToRealtimeButton:
+    case MediaStatusDisplay:
+    case MediaHideClosedCaptionsButton:
+    case MediaTextTrackDisplayContainer:
+    case MediaTextTrackDisplay:
+    case MediaFullScreenVolumeSlider:
+    case MediaFullScreenVolumeSliderThumb:
+    case MediaClosedCaptionsContainer:
+    case MediaClosedCaptionsTrackList:
+        ASSERT_NOT_REACHED();
+        break;
+    }
+    return false;
+}
+
+const int mediaSliderThumbHeight = 24;
+const int mediaVolumeSliderThumbHeight = 24;
+
+void RenderMediaControlsChromium::adjustMediaSliderThumbSize(RenderStyle* style)
+{
+    static Image* mediaSliderThumb = platformResource("mediaplayerSliderThumb");
+    static Image* mediaVolumeSliderThumb = platformResource("mediaplayerVolumeSliderThumb");
+    int width = 0;
+    int height = 0;
+
+    Image* thumbImage = 0;
+    if (style->appearance() == MediaSliderThumbPart) {
+        thumbImage = mediaSliderThumb;
+        width = mediaSliderThumbWidth;
+        height = mediaSliderThumbHeight;
+    } else if (style->appearance() == MediaVolumeSliderThumbPart) {
+        thumbImage = mediaVolumeSliderThumb;
+        width = mediaVolumeSliderThumbWidth;
+        height = mediaVolumeSliderThumbHeight;
+    }
+
+    float zoomLevel = style->effectiveZoom();
+    if (thumbImage) {
+        style->setWidth(Length(static_cast<int>(width * zoomLevel), Fixed));
+        style->setHeight(Length(static_cast<int>(height * zoomLevel), Fixed));
+    }
+}
+
+static String formatChromiumMediaControlsTime(float time, float duration)
+{
+    if (!std::isfinite(time))
+        time = 0;
+    if (!std::isfinite(duration))
+        duration = 0;
+    int seconds = static_cast<int>(fabsf(time));
+    int hours = seconds / (60 * 60);
+    int minutes = (seconds / 60) % 60;
+    seconds %= 60;
+
+    // duration defines the format of how the time is rendered
+    int durationSecs = static_cast<int>(fabsf(duration));
+    int durationHours = durationSecs / (60 * 60);
+    int durationMins = (durationSecs / 60) % 60;
+
+    if (durationHours || hours)
+        return String::format("%s%01d:%02d:%02d", (time < 0 ? "-" : ""), hours, minutes, seconds);
+    if (durationMins > 9)
+        return String::format("%s%02d:%02d", (time < 0 ? "-" : ""), minutes, seconds);
+
+    return String::format("%s%01d:%02d", (time < 0 ? "-" : ""), minutes, seconds);
+}
+
+String RenderMediaControlsChromium::formatMediaControlsTime(float time)
+{
+    return formatChromiumMediaControlsTime(time, time);
+}
+
+String RenderMediaControlsChromium::formatMediaControlsCurrentTime(float currentTime, float duration)
+{
+    return formatChromiumMediaControlsTime(currentTime, duration);
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderMediaControlsChromium.h b/Source/core/rendering/RenderMediaControlsChromium.h
new file mode 100644
index 0000000..9e9e810
--- /dev/null
+++ b/Source/core/rendering/RenderMediaControlsChromium.h
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2009 Apple Inc.
+ * Copyright (C) 2009 Google 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 RenderMediaControlsChromium_h
+#define RenderMediaControlsChromium_h
+
+#include "core/html/shadow/MediaControlElements.h"
+
+namespace WebCore {
+
+struct PaintInfo;
+
+class HTMLMediaElement;
+class IntRect;
+class RenderObject;
+
+class RenderMediaControlsChromium {
+public:
+    static bool paintMediaControlsPart(MediaControlElementType, RenderObject*, const PaintInfo&, const IntRect&);
+    static void adjustMediaSliderThumbSize(RenderStyle*);
+    static String formatMediaControlsTime(float time);
+    static String formatMediaControlsCurrentTime(float currentTime, float duration);
+};
+
+} // namespace WebCore
+
+#endif // RenderMediaControlsChromium_h
diff --git a/Source/core/rendering/RenderMenuList.cpp b/Source/core/rendering/RenderMenuList.cpp
new file mode 100644
index 0000000..8aa6de9
--- /dev/null
+++ b/Source/core/rendering/RenderMenuList.cpp
@@ -0,0 +1,619 @@
+/*
+ * This file is part of the select element renderer in WebCore.
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
+ *               2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ *
+ * 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 "core/rendering/RenderMenuList.h"
+
+#include <math.h>
+#include "HTMLNames.h"
+#include "core/accessibility/AXObjectCache.h"
+#include "core/accessibility/AccessibilityMenuList.h"
+#include "core/css/CSSFontSelector.h"
+#include "core/css/StyleResolver.h"
+#include "core/dom/NodeRenderStyle.h"
+#include "core/html/HTMLOptGroupElement.h"
+#include "core/html/HTMLOptionElement.h"
+#include "core/html/HTMLSelectElement.h"
+#include "core/page/Chrome.h"
+#include "core/page/Frame.h"
+#include "core/page/FrameView.h"
+#include "core/page/Page.h"
+#include "core/page/Settings.h"
+#include "core/platform/PopupMenu.h"
+#include "core/platform/graphics/FontCache.h"
+#include "core/platform/graphics/TextRun.h"
+#include "core/rendering/RenderBR.h"
+#include "core/rendering/RenderScrollbar.h"
+#include "core/rendering/RenderTheme.h"
+
+using namespace std;
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+RenderMenuList::RenderMenuList(Element* element)
+    : RenderFlexibleBox(element)
+    , m_buttonText(0)
+    , m_innerBlock(0)
+    , m_optionsChanged(true)
+    , m_optionsWidth(0)
+    , m_lastActiveIndex(-1)
+    , m_popupIsVisible(false)
+{
+    ASSERT(element);
+    ASSERT(element->isHTMLElement());
+    ASSERT(element->hasTagName(HTMLNames::selectTag));
+}
+
+RenderMenuList::~RenderMenuList()
+{
+    if (m_popup)
+        m_popup->disconnectClient();
+    m_popup = 0;
+}
+
+bool RenderMenuList::canBeReplacedWithInlineRunIn() const
+{
+    return false;
+}
+
+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()
+{
+    RenderStyle* innerStyle = m_innerBlock->style();
+    innerStyle->setFlexGrow(1);
+    innerStyle->setFlexShrink(1);
+    // min-width: 0; is needed for correct shrinking.
+    // FIXME: Remove this line when https://bugs.webkit.org/show_bug.cgi?id=111790 is fixed.
+    innerStyle->setMinWidth(Length(0, Fixed));
+    // Use margin:auto instead of align-items:center to get safe centering, i.e.
+    // when the content overflows, treat it the same as align-items: flex-start.
+    // But we only do that for the cases where html.css would otherwise use center.
+    if (style()->alignItems() == AlignCenter) {
+        innerStyle->setMarginTop(Length());
+        innerStyle->setMarginBottom(Length());
+        innerStyle->setAlignSelf(AlignFlexStart);
+    }
+
+    innerStyle->setPaddingLeft(Length(theme()->popupInternalPaddingLeft(style()), Fixed));
+    innerStyle->setPaddingRight(Length(theme()->popupInternalPaddingRight(style()), Fixed));
+    innerStyle->setPaddingTop(Length(theme()->popupInternalPaddingTop(style()), Fixed));
+    innerStyle->setPaddingBottom(Length(theme()->popupInternalPaddingBottom(style()), Fixed));
+
+    if (m_optionStyle) {
+        if ((m_optionStyle->direction() != innerStyle->direction() || m_optionStyle->unicodeBidi() != innerStyle->unicodeBidi()))
+            m_innerBlock->setNeedsLayoutAndPrefWidthsRecalc();
+        innerStyle->setTextAlign(style()->isLeftToRightDirection() ? LEFT : RIGHT);
+        innerStyle->setDirection(m_optionStyle->direction());
+        innerStyle->setUnicodeBidi(m_optionStyle->unicodeBidi());
+    }
+}
+
+inline HTMLSelectElement* RenderMenuList::selectElement() const
+{
+    return toHTMLSelectElement(node());
+}
+
+void RenderMenuList::addChild(RenderObject* newChild, RenderObject* beforeChild)
+{
+    createInnerBlock();
+    m_innerBlock->addChild(newChild, beforeChild);
+    ASSERT(m_innerBlock == firstChild());
+
+    if (AXObjectCache* cache = document()->existingAXObjectCache())
+        cache->childrenChanged(this);
+}
+
+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(StyleDifference 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();
+
+    bool fontChanged = !oldStyle || oldStyle->font() != style()->font();
+    if (fontChanged)
+        updateOptionsWidth();
+}
+
+void RenderMenuList::updateOptionsWidth()
+{
+    float maxOptionWidth = 0;
+    const Vector<HTMLElement*>& listItems = selectElement()->listItems();
+    int size = listItems.size();    
+    FontCachePurgePreventer fontCachePurgePreventer;
+
+    for (int i = 0; i < size; ++i) {
+        HTMLElement* element = listItems[i];
+        if (!element->hasTagName(optionTag))
+            continue;
+
+        String text = toHTMLOptionElement(element)->textIndentedToRespectGroupLabel();
+        applyTextTransform(style(), text, ' ');
+        if (theme()->popupOptionSupportsTextIndent()) {
+            // Add in the option's text indent.  We can't calculate percentage values for now.
+            float optionWidth = 0;
+            if (RenderStyle* optionStyle = element->renderStyle())
+                optionWidth += minimumValueForLength(optionStyle->textIndent(), 0, view());
+            if (!text.isEmpty())
+                optionWidth += style()->font().width(text);
+            maxOptionWidth = max(maxOptionWidth, optionWidth);
+        } else if (!text.isEmpty())
+            maxOptionWidth = max(maxOptionWidth, style()->font().width(text));
+    }
+
+    int width = static_cast<int>(ceilf(maxOptionWidth));
+    if (m_optionsWidth == width)
+        return;
+
+    m_optionsWidth = width;
+    if (parent())
+        setNeedsLayoutAndPrefWidthsRecalc();
+}
+
+void RenderMenuList::updateFromElement()
+{
+    if (m_optionsChanged) {
+        updateOptionsWidth();
+        m_optionsChanged = false;
+    }
+
+    if (m_popupIsVisible)
+        m_popup->updateFromElement();
+    else
+        setTextFromOption(selectElement()->selectedIndex());
+}
+
+void RenderMenuList::setTextFromOption(int optionIndex)
+{
+    HTMLSelectElement* select = selectElement();
+    const Vector<HTMLElement*>& listItems = select->listItems();
+    int size = listItems.size();
+
+    int i = select->optionToListIndex(optionIndex);
+    String text = emptyString();
+    if (i >= 0 && i < size) {
+        Element* element = listItems[i];
+        if (element->hasTagName(optionTag)) {
+            text = toHTMLOptionElement(element)->textIndentedToRespectGroupLabel();
+            m_optionStyle = element->renderStyle();
+        }
+    }
+
+    setText(text.stripWhiteSpace());
+    didUpdateActiveOption(optionIndex);
+}
+
+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(), true);
+        else {
+            if (m_buttonText)
+                m_buttonText->destroy();
+            m_buttonText = new (renderArena()) RenderText(document(), s.impl());
+            m_buttonText->setStyle(style());
+            // We need to set the text explicitly though it was specified in the
+            // constructor because RenderText doesn't refer to the text
+            // specified in the constructor in a case of re-transforming.
+            m_buttonText->setText(s.impl(), true);
+            addChild(m_buttonText);
+        }
+        adjustInnerStyle();
+    }
+}
+
+String RenderMenuList::text() const
+{
+    return m_buttonText ? m_buttonText->text() : 0;
+}
+
+LayoutRect RenderMenuList::controlClipRect(const LayoutPoint& additionalOffset) 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.
+    LayoutRect outerBox(additionalOffset.x() + borderLeft() + paddingLeft(), 
+                   additionalOffset.y() + borderTop() + paddingTop(),
+                   contentWidth(), 
+                   contentHeight());
+    
+    LayoutRect innerBox(additionalOffset.x() + m_innerBlock->x() + m_innerBlock->paddingLeft(), 
+                   additionalOffset.y() + m_innerBlock->y() + m_innerBlock->paddingTop(),
+                   m_innerBlock->contentWidth(), 
+                   m_innerBlock->contentHeight());
+
+    return intersection(outerBox, innerBox);
+}
+
+void RenderMenuList::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const
+{
+    maxLogicalWidth = max(m_optionsWidth, theme()->minimumMenuListSize(style())) + m_innerBlock->paddingLeft() + m_innerBlock->paddingRight();
+    if (!style()->width().isPercent())
+        minLogicalWidth = maxLogicalWidth;
+}
+
+void RenderMenuList::computePreferredLogicalWidths()
+{
+    m_minPreferredLogicalWidth = 0;
+    m_maxPreferredLogicalWidth = 0;
+    
+    if (style()->width().isFixed() && style()->width().value() > 0)
+        m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = adjustContentBoxLogicalWidthForBoxSizing(style()->width().value());
+    else
+        computeIntrinsicLogicalWidths(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);
+
+    if (style()->minWidth().isFixed() && style()->minWidth().value() > 0) {
+        m_maxPreferredLogicalWidth = max(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->minWidth().value()));
+        m_minPreferredLogicalWidth = max(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->minWidth().value()));
+    }
+
+    if (style()->maxWidth().isFixed()) {
+        m_maxPreferredLogicalWidth = min(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->maxWidth().value()));
+        m_minPreferredLogicalWidth = min(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->maxWidth().value()));
+    }
+
+    LayoutUnit toAdd = borderAndPaddingWidth();
+    m_minPreferredLogicalWidth += toAdd;
+    m_maxPreferredLogicalWidth += toAdd;
+
+    setPreferredLogicalWidthsDirty(false);
+}
+
+void RenderMenuList::showPopup()
+{
+    if (m_popupIsVisible)
+        return;
+
+    if (document()->page()->chrome()->hasOpenedPopup())
+        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 = document()->page()->chrome()->createPopupMenu(this);
+    m_popupIsVisible = true;
+
+    // Compute the top left taking transforms into account, but use
+    // the actual width of the element to size the popup.
+    FloatPoint absTopLeft = localToAbsolute(FloatPoint(), UseTransforms);
+    IntRect absBounds = absoluteBoundingBoxRectIgnoringTransforms();
+    absBounds.setLocation(roundedIntPoint(absTopLeft));
+    HTMLSelectElement* select = selectElement();
+    m_popup->show(absBounds, document()->view(), select->optionToListIndex(select->selectedIndex()));
+}
+
+void RenderMenuList::hidePopup()
+{
+    if (m_popup)
+        m_popup->hide();
+}
+
+void RenderMenuList::valueChanged(unsigned listIndex, bool fireOnChange)
+{
+    // Check to ensure a page navigation has not occurred while
+    // the popup was up.
+    Document* doc = toElement(node())->document();
+    if (!doc || doc != doc->frame()->document())
+        return;
+    
+    HTMLSelectElement* select = selectElement();
+    select->optionSelectedByUser(select->listToOptionIndex(listIndex), fireOnChange);
+}
+
+void RenderMenuList::listBoxSelectItem(int listIndex, bool allowMultiplySelections, bool shift, bool fireOnChangeNow)
+{
+    selectElement()->listBoxSelectItem(listIndex, allowMultiplySelections, shift, fireOnChangeNow);
+}
+
+bool RenderMenuList::multiple() const
+{
+    return selectElement()->multiple();
+}
+
+void RenderMenuList::didSetSelectedIndex(int listIndex)
+{
+    didUpdateActiveOption(selectElement()->listToOptionIndex(listIndex));
+}
+
+void RenderMenuList::didUpdateActiveOption(int optionIndex)
+{
+    if (!AXObjectCache::accessibilityEnabled() || !document()->existingAXObjectCache())
+        return;
+
+    if (m_lastActiveIndex == optionIndex)
+        return;
+    m_lastActiveIndex = optionIndex;
+
+    HTMLSelectElement* select = selectElement();
+    int listIndex = select->optionToListIndex(optionIndex);
+    if (listIndex < 0 || listIndex >= static_cast<int>(select->listItems().size()))
+        return;
+
+    ASSERT(select->listItems()[listIndex]);
+
+    if (AccessibilityMenuList* menuList = static_cast<AccessibilityMenuList*>(document()->axObjectCache()->get(this)))
+        menuList->didUpdateActiveOption(optionIndex);
+}
+
+String RenderMenuList::itemText(unsigned listIndex) const
+{
+    HTMLSelectElement* select = selectElement();
+    const Vector<HTMLElement*>& listItems = select->listItems();
+    if (listIndex >= listItems.size())
+        return String();
+
+    String itemString;
+    Element* element = listItems[listIndex];
+    if (element->hasTagName(optgroupTag))
+        itemString = static_cast<const HTMLOptGroupElement*>(element)->groupLabelText();
+    else if (element->hasTagName(optionTag))
+        itemString = toHTMLOptionElement(element)->textIndentedToRespectGroupLabel();
+
+    applyTextTransform(style(), itemString, ' ');
+    return itemString;
+}
+
+String RenderMenuList::itemLabel(unsigned) const
+{
+    return String();
+}
+
+String RenderMenuList::itemIcon(unsigned) const
+{
+    return String();
+}
+
+String RenderMenuList::itemAccessibilityText(unsigned listIndex) const
+{
+    // Allow the accessible name be changed if necessary.
+    const Vector<HTMLElement*>& listItems = selectElement()->listItems();
+    if (listIndex >= listItems.size())
+        return String();
+    return listItems[listIndex]->fastGetAttribute(aria_labelAttr);
+}
+    
+String RenderMenuList::itemToolTip(unsigned listIndex) const
+{
+    const Vector<HTMLElement*>& listItems = selectElement()->listItems();
+    if (listIndex >= listItems.size())
+        return String();
+    return listItems[listIndex]->title();
+}
+
+bool RenderMenuList::itemIsEnabled(unsigned listIndex) const
+{
+    const Vector<HTMLElement*>& listItems = selectElement()->listItems();
+    if (listIndex >= listItems.size())
+        return false;
+    HTMLElement* element = listItems[listIndex];
+    if (!element->hasTagName(optionTag))
+        return false;
+
+    bool groupEnabled = true;
+    if (Element* parentElement = element->parentElement()) {
+        if (parentElement->hasTagName(optgroupTag))
+            groupEnabled = !parentElement->isDisabledFormControl();
+    }
+    if (!groupEnabled)
+        return false;
+
+    return !element->isDisabledFormControl();
+}
+
+PopupMenuStyle RenderMenuList::itemStyle(unsigned listIndex) const
+{
+    const Vector<HTMLElement*>& listItems = selectElement()->listItems();
+    if (listIndex >= listItems.size()) {
+        // If we are making an out of bounds access, then we want to use the style
+        // of a different option element (index 0). However, if there isn't an option element
+        // before at index 0, we fall back to the menu's style.
+        if (!listIndex)
+            return menuStyle();
+
+        // Try to retrieve the style of an option element we know exists (index 0).
+        listIndex = 0;
+    }
+    HTMLElement* element = listItems[listIndex];
+
+    Color itemBackgroundColor;
+    bool itemHasCustomBackgroundColor;
+    getItemBackgroundColor(listIndex, itemBackgroundColor, itemHasCustomBackgroundColor);
+
+    RenderStyle* style = element->renderStyle() ? element->renderStyle() : element->computedStyle();
+    return style ? PopupMenuStyle(style->visitedDependentColor(CSSPropertyColor), itemBackgroundColor, style->font(), style->visibility() == VISIBLE,
+        style->display() == NONE, style->textIndent(), style->direction(), isOverride(style->unicodeBidi()),
+        itemHasCustomBackgroundColor ? PopupMenuStyle::CustomBackgroundColor : PopupMenuStyle::DefaultBackgroundColor) : menuStyle();
+}
+
+void RenderMenuList::getItemBackgroundColor(unsigned listIndex, Color& itemBackgroundColor, bool& itemHasCustomBackgroundColor) const
+{
+    const Vector<HTMLElement*>& listItems = selectElement()->listItems();
+    if (listIndex >= listItems.size()) {
+        itemBackgroundColor = style()->visitedDependentColor(CSSPropertyBackgroundColor);
+        itemHasCustomBackgroundColor = false;
+        return;
+    }
+    HTMLElement* element = listItems[listIndex];
+
+    Color backgroundColor;
+    if (element->renderStyle())
+        backgroundColor = element->renderStyle()->visitedDependentColor(CSSPropertyBackgroundColor);
+    itemHasCustomBackgroundColor = backgroundColor.isValid() && backgroundColor.alpha();
+    // If the item has an opaque background color, return that.
+    if (!backgroundColor.hasAlpha()) {
+        itemBackgroundColor = backgroundColor;
+        return;
+    }
+
+    // Otherwise, the item's background is overlayed on top of the menu background.
+    backgroundColor = style()->visitedDependentColor(CSSPropertyBackgroundColor).blend(backgroundColor);
+    if (!backgroundColor.hasAlpha()) {
+        itemBackgroundColor = backgroundColor;
+        return;
+    }
+
+    // If the menu background is not opaque, then add an opaque white background behind.
+    itemBackgroundColor = Color(Color::white).blend(backgroundColor);
+}
+
+PopupMenuStyle RenderMenuList::menuStyle() const
+{
+    RenderStyle* s = m_innerBlock ? m_innerBlock->style() : style();
+    return PopupMenuStyle(s->visitedDependentColor(CSSPropertyColor), s->visitedDependentColor(CSSPropertyBackgroundColor), s->font(), s->visibility() == VISIBLE,
+        s->display() == NONE, s->textIndent(), style()->direction(), isOverride(style()->unicodeBidi()));
+}
+
+HostWindow* RenderMenuList::hostWindow() const
+{
+    return document()->view()->hostWindow();
+}
+
+PassRefPtr<Scrollbar> RenderMenuList::createScrollbar(ScrollableArea* scrollableArea, ScrollbarOrientation orientation, ScrollbarControlSize controlSize)
+{
+    RefPtr<Scrollbar> widget;
+    bool hasCustomScrollbarStyle = style()->hasPseudoStyle(SCROLLBAR);
+    if (hasCustomScrollbarStyle)
+        widget = RenderScrollbar::createCustomScrollbar(scrollableArea, orientation, this->node());
+    else
+        widget = Scrollbar::createNativeScrollbar(scrollableArea, orientation, controlSize);
+    return widget.release();
+}
+
+int RenderMenuList::clientInsetLeft() const
+{
+    return 0;
+}
+
+int RenderMenuList::clientInsetRight() const
+{
+    return 0;
+}
+
+LayoutUnit RenderMenuList::clientPaddingLeft() const
+{
+    return paddingLeft() + m_innerBlock->paddingLeft();
+}
+
+const int endOfLinePadding = 2;
+LayoutUnit RenderMenuList::clientPaddingRight() const
+{
+    if (style()->appearance() == MenulistPart || style()->appearance() == MenulistButtonPart) {
+        // For these appearance values, the theme applies padding to leave room for the
+        // drop-down button. But leaving room for the button inside the popup menu itself
+        // looks strange, so we return a small default padding to avoid having a large empty
+        // space appear on the side of the popup menu.
+        return endOfLinePadding;
+    }
+
+    // If the appearance isn't MenulistPart, then the select is styled (non-native), so
+    // we want to return the user specified padding.
+    return paddingRight() + m_innerBlock->paddingRight();
+}
+
+int RenderMenuList::listSize() const
+{
+    return selectElement()->listItems().size();
+}
+
+int RenderMenuList::selectedIndex() const
+{
+    HTMLSelectElement* select = selectElement();
+    return select->optionToListIndex(select->selectedIndex());
+}
+
+void RenderMenuList::popupDidHide()
+{
+    m_popupIsVisible = false;
+}
+
+bool RenderMenuList::itemIsSeparator(unsigned listIndex) const
+{
+    const Vector<HTMLElement*>& listItems = selectElement()->listItems();
+    return listIndex < listItems.size() && listItems[listIndex]->hasTagName(hrTag);
+}
+
+bool RenderMenuList::itemIsLabel(unsigned listIndex) const
+{
+    const Vector<HTMLElement*>& listItems = selectElement()->listItems();
+    return listIndex < listItems.size() && listItems[listIndex]->hasTagName(optgroupTag);
+}
+
+bool RenderMenuList::itemIsSelected(unsigned listIndex) const
+{
+    const Vector<HTMLElement*>& listItems = selectElement()->listItems();
+    if (listIndex >= listItems.size())
+        return false;
+    HTMLElement* element = listItems[listIndex];
+    return element->hasTagName(optionTag) && toHTMLOptionElement(element)->selected();
+}
+
+void RenderMenuList::setTextFromItem(unsigned listIndex)
+{
+    setTextFromOption(selectElement()->listToOptionIndex(listIndex));
+}
+
+FontSelector* RenderMenuList::fontSelector() const
+{
+    return document()->styleResolver()->fontSelector();
+}
+
+}
diff --git a/Source/core/rendering/RenderMenuList.h b/Source/core/rendering/RenderMenuList.h
new file mode 100644
index 0000000..a91f3b8
--- /dev/null
+++ b/Source/core/rendering/RenderMenuList.h
@@ -0,0 +1,155 @@
+/*
+ * This file is part of the select element renderer in WebCore.
+ *
+ * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+ * Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011 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 "core/platform/PopupMenu.h"
+#include "core/platform/PopupMenuClient.h"
+#include "core/platform/graphics/LayoutRect.h"
+#include "core/rendering/RenderFlexibleBox.h"
+
+namespace WebCore {
+
+class HTMLSelectElement;
+class RenderText;
+
+class RenderMenuList FINAL : public RenderFlexibleBox, private PopupMenuClient {
+
+public:
+    RenderMenuList(Element*);
+    virtual ~RenderMenuList();
+
+public:
+    bool popupIsVisible() const { return m_popupIsVisible; }
+    void showPopup();
+    void hidePopup();
+
+    void setOptionsChanged(bool changed) { m_optionsChanged = changed; }
+
+    void didSetSelectedIndex(int listIndex);
+
+    String text() const;
+
+private:
+    HTMLSelectElement* selectElement() const;
+
+    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 void updateFromElement();
+
+    virtual LayoutRect controlClipRect(const LayoutPoint&) const;
+    virtual bool hasControlClip() const { return true; }
+    virtual bool canHaveGeneratedChildren() const OVERRIDE { return false; }
+    virtual bool canBeReplacedWithInlineRunIn() const OVERRIDE;
+
+    virtual const char* renderName() const { return "RenderMenuList"; }
+
+    virtual void computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const OVERRIDE;
+    virtual void computePreferredLogicalWidths() OVERRIDE;
+
+    virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+
+    virtual bool requiresForcedStyleRecalcPropagation() const { return true; }
+
+    // PopupMenuClient methods
+    virtual void valueChanged(unsigned listIndex, bool fireOnChange = true) OVERRIDE;
+    virtual void selectionChanged(unsigned, bool) OVERRIDE { }
+    virtual void selectionCleared() OVERRIDE { }
+    virtual String itemText(unsigned listIndex) const OVERRIDE;
+    virtual String itemLabel(unsigned listIndex) const OVERRIDE;
+    virtual String itemIcon(unsigned listIndex) const OVERRIDE;
+    virtual String itemToolTip(unsigned listIndex) const OVERRIDE;
+    virtual String itemAccessibilityText(unsigned listIndex) const OVERRIDE;
+    virtual bool itemIsEnabled(unsigned listIndex) const OVERRIDE;
+    virtual PopupMenuStyle itemStyle(unsigned listIndex) const OVERRIDE;
+    virtual PopupMenuStyle menuStyle() const OVERRIDE;
+    virtual int clientInsetLeft() const OVERRIDE;
+    virtual int clientInsetRight() const OVERRIDE;
+    virtual LayoutUnit clientPaddingLeft() const OVERRIDE;
+    virtual LayoutUnit clientPaddingRight() const OVERRIDE;
+    virtual int listSize() const OVERRIDE;
+    virtual int selectedIndex() const OVERRIDE;
+    virtual void popupDidHide() OVERRIDE;
+    virtual bool itemIsSeparator(unsigned listIndex) const OVERRIDE;
+    virtual bool itemIsLabel(unsigned listIndex) const OVERRIDE;
+    virtual bool itemIsSelected(unsigned listIndex) const OVERRIDE;
+    virtual bool valueShouldChangeOnHotTrack() const OVERRIDE { return true; }
+    virtual void setTextFromItem(unsigned listIndex) OVERRIDE;
+    virtual void listBoxSelectItem(int listIndex, bool allowMultiplySelections, bool shift, bool fireOnChangeNow = true) OVERRIDE;
+    virtual bool multiple() const OVERRIDE;
+    virtual FontSelector* fontSelector() const OVERRIDE;
+    virtual HostWindow* hostWindow() const OVERRIDE;
+    virtual PassRefPtr<Scrollbar> createScrollbar(ScrollableArea*, ScrollbarOrientation, ScrollbarControlSize) OVERRIDE;
+
+    virtual bool hasLineIfEmpty() const { return true; }
+
+    // Flexbox defines baselines differently than regular blocks.
+    // For backwards compatibility, menulists need to do the regular block behavior.
+    virtual int baselinePosition(FontBaseline baseline, bool firstLine, LineDirectionMode direction, LinePositionMode position) const OVERRIDE
+    {
+        return RenderBlock::baselinePosition(baseline, firstLine, direction, position);
+    }
+    virtual int firstLineBoxBaseline() const OVERRIDE { return RenderBlock::firstLineBoxBaseline(); }
+    virtual int inlineBlockBaseline(LineDirectionMode direction) const OVERRIDE { return RenderBlock::inlineBlockBaseline(direction); }
+
+    void getItemBackgroundColor(unsigned listIndex, Color&, bool& itemHasCustomBackgroundColor) const;
+
+    void createInnerBlock();
+    void adjustInnerStyle();
+    void setText(const String&);
+    void setTextFromOption(int optionIndex);
+    void updateOptionsWidth();
+
+    void didUpdateActiveOption(int optionIndex);
+
+    RenderText* m_buttonText;
+    RenderBlock* m_innerBlock;
+
+    bool m_optionsChanged;
+    int m_optionsWidth;
+
+    int m_lastActiveIndex;
+
+    RefPtr<RenderStyle> m_optionStyle;
+
+    RefPtr<PopupMenu> m_popup;
+    bool m_popupIsVisible;
+};
+
+inline RenderMenuList* toRenderMenuList(RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isMenuList());
+    return static_cast<RenderMenuList*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderMenuList(const RenderMenuList*);
+
+}
+
+#endif
diff --git a/Source/core/rendering/RenderMeter.cpp b/Source/core/rendering/RenderMeter.cpp
new file mode 100644
index 0000000..92b5663
--- /dev/null
+++ b/Source/core/rendering/RenderMeter.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2010 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 "core/rendering/RenderMeter.h"
+
+#include "HTMLNames.h"
+#include "core/html/HTMLMeterElement.h"
+#include "core/rendering/RenderTheme.h"
+
+using namespace std;
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+RenderMeter::RenderMeter(HTMLElement* element)
+    : RenderBlock(element)
+{
+}
+
+RenderMeter::~RenderMeter()
+{
+}
+
+HTMLMeterElement* RenderMeter::meterElement() const
+{
+    ASSERT(node());
+
+    if (isHTMLMeterElement(node()))
+        return toHTMLMeterElement(node());
+
+    ASSERT(node()->shadowHost());
+    return toHTMLMeterElement(node()->shadowHost());
+}
+
+void RenderMeter::updateLogicalWidth()
+{
+    RenderBox::updateLogicalWidth();
+
+    IntSize frameSize = theme()->meterSizeForBounds(this, pixelSnappedIntRect(frameRect()));
+    setLogicalWidth(isHorizontalWritingMode() ? frameSize.width() : frameSize.height());
+}
+
+void RenderMeter::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues& computedValues) const
+{
+    RenderBox::computeLogicalHeight(logicalHeight, logicalTop, computedValues);
+
+    LayoutRect frame = frameRect();
+    if (isHorizontalWritingMode())
+        frame.setHeight(computedValues.m_extent);
+    else
+        frame.setWidth(computedValues.m_extent);
+    IntSize frameSize = theme()->meterSizeForBounds(this, pixelSnappedIntRect(frame));
+    computedValues.m_extent = isHorizontalWritingMode() ? frameSize.height() : frameSize.width();
+}
+
+double RenderMeter::valueRatio() const
+{
+    return meterElement()->valueRatio();
+}
+
+void RenderMeter::updateFromElement()
+{
+    repaint();
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderMeter.h b/Source/core/rendering/RenderMeter.h
new file mode 100644
index 0000000..d157a39
--- /dev/null
+++ b/Source/core/rendering/RenderMeter.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2009 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 RenderMeter_h
+#define RenderMeter_h
+
+#include "core/rendering/RenderBlock.h"
+#include "core/rendering/RenderWidget.h"
+
+namespace WebCore {
+
+class HTMLMeterElement;
+
+class RenderMeter FINAL : public RenderBlock {
+public:
+    explicit RenderMeter(HTMLElement*);
+    virtual ~RenderMeter();
+
+    HTMLMeterElement* meterElement() const;
+    virtual void updateFromElement();
+
+private:    
+    virtual void updateLogicalWidth() OVERRIDE;
+    virtual void computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues&) const OVERRIDE;
+
+    virtual const char* renderName() const { return "RenderMeter"; }
+    virtual bool isMeter() const { return true; }
+    virtual bool requiresForcedStyleRecalcPropagation() const { return true; }
+
+    double valueRatio() const;
+};
+
+inline RenderMeter* toRenderMeter(RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isMeter());
+    return static_cast<RenderMeter*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderMeter(const RenderMeter*);
+
+} // namespace WebCore
+
+#endif // RenderMeter_h
diff --git a/Source/core/rendering/RenderMultiColumnBlock.cpp b/Source/core/rendering/RenderMultiColumnBlock.cpp
new file mode 100644
index 0000000..0445b81
--- /dev/null
+++ b/Source/core/rendering/RenderMultiColumnBlock.cpp
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2012 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 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 "core/rendering/RenderMultiColumnBlock.h"
+
+#include "core/rendering/RenderMultiColumnFlowThread.h"
+#include "core/rendering/RenderMultiColumnSet.h"
+#include "core/rendering/style/StyleInheritedData.h"
+
+using namespace std;
+
+namespace WebCore {
+
+RenderMultiColumnBlock::RenderMultiColumnBlock(Element* element)
+    : RenderBlock(element)
+    , m_flowThread(0)
+    , m_columnCount(1)
+    , m_columnWidth(0)
+    , m_columnHeight(0)
+    , m_requiresBalancing(false)
+{
+}
+
+void RenderMultiColumnBlock::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
+{
+    RenderBlock::styleDidChange(diff, oldStyle);
+    for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox())
+        child->setStyle(RenderStyle::createAnonymousStyleWithDisplay(style(), BLOCK));
+}
+
+void RenderMultiColumnBlock::computeColumnCountAndWidth()
+{
+    // Calculate our column width and column count.
+    // FIXME: Can overflow on fast/block/float/float-not-removed-from-next-sibling4.html, see https://bugs.webkit.org/show_bug.cgi?id=68744
+    m_columnCount = 1;
+    m_columnWidth = contentLogicalWidth();
+    
+    ASSERT(!style()->hasAutoColumnCount() || !style()->hasAutoColumnWidth());
+
+    LayoutUnit availWidth = m_columnWidth;
+    LayoutUnit colGap = columnGap();
+    LayoutUnit colWidth = max<LayoutUnit>(1, LayoutUnit(style()->columnWidth()));
+    int colCount = max<int>(1, style()->columnCount());
+
+    if (style()->hasAutoColumnWidth() && !style()->hasAutoColumnCount()) {
+        m_columnCount = colCount;
+        m_columnWidth = max<LayoutUnit>(0, (availWidth - ((m_columnCount - 1) * colGap)) / m_columnCount);
+    } else if (!style()->hasAutoColumnWidth() && style()->hasAutoColumnCount()) {
+        m_columnCount = max<LayoutUnit>(1, (availWidth + colGap) / (colWidth + colGap));
+        m_columnWidth = ((availWidth + colGap) / m_columnCount) - colGap;
+    } else {
+        m_columnCount = max<LayoutUnit>(min<LayoutUnit>(colCount, (availWidth + colGap) / (colWidth + colGap)), 1);
+        m_columnWidth = ((availWidth + colGap) / m_columnCount) - colGap;
+    }
+}
+
+bool RenderMultiColumnBlock::updateLogicalWidthAndColumnWidth()
+{
+    bool relayoutChildren = RenderBlock::updateLogicalWidthAndColumnWidth();
+    LayoutUnit oldColumnWidth = m_columnWidth;
+    computeColumnCountAndWidth();
+    if (m_columnWidth != oldColumnWidth)
+        relayoutChildren = true;
+    return relayoutChildren;
+}
+
+void RenderMultiColumnBlock::checkForPaginationLogicalHeightChange(LayoutUnit& /*pageLogicalHeight*/, bool& /*pageLogicalHeightChanged*/, bool& /*hasSpecifiedPageLogicalHeight*/)
+{
+    // We don't actually update any of the variables. We just subclassed to adjust our column height.
+    updateLogicalHeight();
+    LayoutUnit newContentLogicalHeight = contentLogicalHeight();
+    m_requiresBalancing = !newContentLogicalHeight;
+    if (!m_requiresBalancing) {
+        // The regions will be invalidated when we lay them out and they change size to
+        // the new column height.
+        if (columnHeight() != newContentLogicalHeight)
+            setColumnHeight(newContentLogicalHeight);
+    }
+    setLogicalHeight(0);
+}
+
+bool RenderMultiColumnBlock::relayoutForPagination(bool, LayoutUnit, LayoutStateMaintainer&)
+{
+    // FIXME: Implement.
+    return false;
+}
+
+void RenderMultiColumnBlock::addChild(RenderObject* newChild, RenderObject* beforeChild)
+{
+    if (!m_flowThread) {
+        m_flowThread = RenderMultiColumnFlowThread::createAnonymous(document());
+        m_flowThread->setStyle(RenderStyle::createAnonymousStyleWithDisplay(style(), BLOCK));
+        RenderBlock::addChild(m_flowThread);
+    }
+    m_flowThread->addChild(newChild, beforeChild);
+}
+    
+RenderObject* RenderMultiColumnBlock::layoutSpecialExcludedChild(bool relayoutChildren)
+{
+    if (!m_flowThread)
+        return 0;
+    
+    // Update the sizes of our regions (but not the placement) before we lay out the flow thread.
+    // FIXME: Eventually this is going to get way more complicated, and we will be destroying regions
+    // instead of trying to keep them around.
+    bool shouldInvalidateRegions = false;
+    for (RenderBox* childBox = firstChildBox(); childBox; childBox = childBox->nextSiblingBox()) {
+        if (childBox == m_flowThread)
+            continue;
+        
+        if (relayoutChildren || childBox->needsLayout()) {
+            childBox->updateLogicalWidth();
+            childBox->updateLogicalHeight();
+            shouldInvalidateRegions = true;
+        }
+    }
+    
+    if (shouldInvalidateRegions)
+        m_flowThread->invalidateRegions();
+
+    if (relayoutChildren)
+        m_flowThread->setChildNeedsLayout(true, MarkOnlyThis);
+    
+    setLogicalTopForChild(m_flowThread, borderBefore() + paddingBefore());
+    m_flowThread->layoutIfNeeded();
+    determineLogicalLeftPositionForChild(m_flowThread);
+    
+    return m_flowThread;
+}
+
+const char* RenderMultiColumnBlock::renderName() const
+{
+    if (isFloating())
+        return "RenderMultiColumnBlock (floating)";
+    if (isOutOfFlowPositioned())
+        return "RenderMultiColumnBlock (positioned)";
+    if (isAnonymousBlock())
+        return "RenderMultiColumnBlock (anonymous)";
+    // FIXME: Temporary hack while the new generated content system is being implemented.
+    if (isPseudoElement())
+        return "RenderMultiColumnBlock (generated)";
+    if (isAnonymous())
+        return "RenderMultiColumnBlock (generated)";
+    if (isRelPositioned())
+        return "RenderMultiColumnBlock (relative positioned)";
+    return "RenderMultiColumnBlock";
+}
+
+}
diff --git a/Source/core/rendering/RenderMultiColumnBlock.h b/Source/core/rendering/RenderMultiColumnBlock.h
new file mode 100644
index 0000000..1dfaf23
--- /dev/null
+++ b/Source/core/rendering/RenderMultiColumnBlock.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2012 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 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 RenderMultiColumnBlock_h
+#define RenderMultiColumnBlock_h
+
+#include "core/rendering/RenderBlock.h"
+
+namespace WebCore {
+
+class RenderMultiColumnFlowThread;
+
+class RenderMultiColumnBlock FINAL : public RenderBlock {
+public:
+    RenderMultiColumnBlock(Element*);
+
+    LayoutUnit columnHeight() const { return m_columnHeight; }
+    void setColumnHeight(LayoutUnit columnHeight) { m_columnHeight = columnHeight; }
+
+    LayoutUnit columnWidth() const { return m_columnWidth; }
+    unsigned columnCount() const { return m_columnCount; }
+
+    RenderMultiColumnFlowThread* flowThread() const { return m_flowThread; }
+
+    bool requiresBalancing() const { return m_requiresBalancing; }
+
+private:
+    virtual bool isRenderMultiColumnBlock() const { return true; }
+    
+    virtual const char* renderName() const;
+
+    virtual RenderObject* layoutSpecialExcludedChild(bool relayoutChildren) OVERRIDE;
+
+    virtual void styleDidChange(StyleDifference, const RenderStyle*) OVERRIDE;
+    
+    virtual bool updateLogicalWidthAndColumnWidth() OVERRIDE;
+    virtual void checkForPaginationLogicalHeightChange(LayoutUnit& pageLogicalHeight, bool& pageLogicalHeightChanged, bool& hasSpecifiedPageLogicalHeight) OVERRIDE;
+    virtual bool relayoutForPagination(bool hasSpecifiedPageLogicalHeight, LayoutUnit pageLogicalHeight, LayoutStateMaintainer&) OVERRIDE;
+
+    virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0) OVERRIDE;
+
+    void computeColumnCountAndWidth();
+
+    void ensureColumnSets();
+
+    RenderMultiColumnFlowThread* m_flowThread;
+    unsigned m_columnCount;   // The default column count/width that are based off our containing block width. These values represent only the default,
+    LayoutUnit m_columnWidth; // since a multi-column block that is split across variable width pages or regions will have different column counts and widths in each.
+                              // These values will be cached (eventually) for multi-column blocks.
+    LayoutUnit m_columnHeight; // The current column height.
+    bool m_requiresBalancing; // Whether or not the block specified any kind of logical height. We have to balance by default if it didn't.
+};
+
+inline RenderMultiColumnBlock* toRenderMultiColumnBlock(RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isRenderMultiColumnBlock());
+    return static_cast<RenderMultiColumnBlock*>(object);
+}
+
+inline const RenderMultiColumnBlock* toRenderMultiColumnBlock(const RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isRenderMultiColumnBlock());
+    return static_cast<const RenderMultiColumnBlock*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderMultiColumnBlock(const RenderMultiColumnBlock*);
+
+} // namespace WebCore
+
+#endif // RenderMultiColumnBlock_h
+
diff --git a/Source/core/rendering/RenderMultiColumnFlowThread.cpp b/Source/core/rendering/RenderMultiColumnFlowThread.cpp
new file mode 100644
index 0000000..2bf3688
--- /dev/null
+++ b/Source/core/rendering/RenderMultiColumnFlowThread.cpp
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2012 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 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 IN..0TERRUPTION) 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 "core/rendering/RenderMultiColumnFlowThread.h"
+
+#include "core/rendering/RenderMultiColumnBlock.h"
+#include "core/rendering/RenderMultiColumnSet.h"
+
+namespace WebCore {
+
+RenderMultiColumnFlowThread::RenderMultiColumnFlowThread()
+{
+    setFlowThreadState(InsideInFlowThread);
+}
+
+RenderMultiColumnFlowThread::~RenderMultiColumnFlowThread()
+{
+}
+
+RenderMultiColumnFlowThread* RenderMultiColumnFlowThread::createAnonymous(Document* document)
+{
+    RenderMultiColumnFlowThread* renderer = new (document->renderArena()) RenderMultiColumnFlowThread();
+    renderer->setDocumentForAnonymous(document);
+    return renderer;
+}
+
+const char* RenderMultiColumnFlowThread::renderName() const
+{    
+    return "RenderMultiColumnFlowThread";
+}
+
+void RenderMultiColumnFlowThread::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues& computedValues) const
+{
+    // We simply remain at our intrinsic height.
+    computedValues.m_extent = logicalHeight;
+    computedValues.m_position = logicalTop;
+}
+
+LayoutUnit RenderMultiColumnFlowThread::initialLogicalWidth() const
+{
+    RenderMultiColumnBlock* parentBlock = toRenderMultiColumnBlock(parent());
+    return parentBlock->columnWidth();
+}
+
+void RenderMultiColumnFlowThread::autoGenerateRegionsToBlockOffset(LayoutUnit /*offset*/)
+{
+    // This function ensures we have the correct column set information at all times.
+    // For a simple multi-column layout in continuous media, only one column set child is required.
+    // Once a column is nested inside an enclosing pagination context, the number of column sets
+    // required becomes 2n-1, where n is the total number of nested pagination contexts. For example:
+    //
+    // Column layout with no enclosing pagination model = 2 * 1 - 1 = 1 column set.
+    // Columns inside pages = 2 * 2 - 1 = 3 column sets (bottom of first page, all the subsequent pages, then the last page).
+    // Columns inside columns inside pages = 2 * 3 - 1 = 5 column sets.
+    //
+    // In addition, column spans will force a column set to "split" into before/after sets around the spanning element.
+    //
+    // Finally, we will need to deal with columns inside regions. If regions have variable widths, then there will need
+    // to be unique column sets created inside any region whose width is different from its surrounding regions. This is
+    // actually pretty similar to the spanning case, in that we break up the column sets whenever the width varies.
+    //
+    // FIXME: For now just make one column set. This matches the old multi-column code.
+    // Right now our goal is just feature parity with the old multi-column code so that we can switch over to the
+    // new code as soon as possible.
+    RenderMultiColumnSet* firstSet = toRenderMultiColumnSet(firstRegion());
+    if (firstSet)
+        return;
+    
+    invalidateRegions();
+
+    RenderMultiColumnBlock* parentBlock = toRenderMultiColumnBlock(parent());
+    firstSet = RenderMultiColumnSet::createAnonymous(this);
+    firstSet->setStyle(RenderStyle::createAnonymousStyleWithDisplay(parentBlock->style(), BLOCK));
+    parentBlock->RenderBlock::addChild(firstSet);
+    
+    // Even though we aren't placed yet, we can go ahead and set up our size.
+    firstSet->updateLogicalWidth();
+    firstSet->updateLogicalHeight();
+
+    firstSet->setRequiresBalancing(parentBlock->requiresBalancing());
+    
+    validateRegions();
+}
+
+}
diff --git a/Source/core/rendering/RenderMultiColumnFlowThread.h b/Source/core/rendering/RenderMultiColumnFlowThread.h
new file mode 100644
index 0000000..d57cb1b
--- /dev/null
+++ b/Source/core/rendering/RenderMultiColumnFlowThread.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2012 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 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 RenderMultiColumnFlowThread_h
+#define RenderMultiColumnFlowThread_h
+
+#include "core/rendering/RenderFlowThread.h"
+
+namespace WebCore {
+
+class RenderMultiColumnFlowThread FINAL : public RenderFlowThread {
+public:
+    ~RenderMultiColumnFlowThread();
+
+    static RenderMultiColumnFlowThread* createAnonymous(Document*);
+
+private:
+    RenderMultiColumnFlowThread();
+
+    virtual const char* renderName() const OVERRIDE;
+    virtual void computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues&) const OVERRIDE;
+    virtual void autoGenerateRegionsToBlockOffset(LayoutUnit) OVERRIDE;
+    virtual LayoutUnit initialLogicalWidth() const OVERRIDE;
+};
+
+} // namespace WebCore
+
+#endif // RenderMultiColumnFlowThread_h
+
diff --git a/Source/core/rendering/RenderMultiColumnSet.cpp b/Source/core/rendering/RenderMultiColumnSet.cpp
new file mode 100644
index 0000000..59b89ad
--- /dev/null
+++ b/Source/core/rendering/RenderMultiColumnSet.cpp
@@ -0,0 +1,421 @@
+/*
+ * Copyright (C) 2012 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 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 "core/rendering/RenderMultiColumnSet.h"
+
+#include "core/rendering/PaintInfo.h"
+#include "core/rendering/RenderLayer.h"
+#include "core/rendering/RenderMultiColumnBlock.h"
+#include "core/rendering/RenderMultiColumnFlowThread.h"
+
+using namespace std;
+
+namespace WebCore {
+
+RenderMultiColumnSet::RenderMultiColumnSet(RenderFlowThread* flowThread)
+    : RenderRegionSet(0, flowThread)
+    , m_computedColumnCount(1)
+    , m_computedColumnWidth(0)
+    , m_computedColumnHeight(0)
+    , m_requiresBalancing(false)
+    , m_minimumColumnHeight(0)
+    , m_forcedBreaksCount(0)
+    , m_maximumDistanceBetweenForcedBreaks(0)
+    , m_forcedBreakOffset(0)
+{
+}
+
+RenderMultiColumnSet* RenderMultiColumnSet::createAnonymous(RenderFlowThread* flowThread)
+{
+    Document* document = flowThread->document();
+    RenderMultiColumnSet* renderer = new (document->renderArena()) RenderMultiColumnSet(flowThread);
+    renderer->setDocumentForAnonymous(document);
+    return renderer;
+}
+
+LayoutUnit RenderMultiColumnSet::pageLogicalTopForOffset(LayoutUnit offset) const
+{
+    LayoutUnit portionLogicalTop = (isHorizontalWritingMode() ? flowThreadPortionRect().y() : flowThreadPortionRect().x());
+    unsigned columnIndex = (offset - portionLogicalTop) / computedColumnHeight();
+    return portionLogicalTop + columnIndex * computedColumnHeight();
+}
+
+void RenderMultiColumnSet::updateLogicalWidth()
+{
+    RenderMultiColumnBlock* parentBlock = toRenderMultiColumnBlock(parent());
+    setComputedColumnWidthAndCount(parentBlock->columnWidth(), parentBlock->columnCount()); // FIXME: This will eventually vary if we are contained inside regions.
+    
+    // FIXME: When we add regions support, we'll start it off at the width of the multi-column
+    // block in that particular region.
+    setLogicalWidth(parentBox()->contentLogicalWidth());
+
+    // If we overflow, increase our logical width.
+    unsigned colCount = columnCount();
+    if (!colCount)
+        return;
+    
+    LayoutUnit colGap = columnGap();
+    LayoutUnit minimumContentLogicalWidth = colCount * computedColumnWidth() + (colCount - 1) * colGap;
+    LayoutUnit currentContentLogicalWidth = contentLogicalWidth();
+    LayoutUnit delta = max(LayoutUnit(), minimumContentLogicalWidth - currentContentLogicalWidth);
+    if (!delta)
+        return;
+
+    // Increase our logical width by the delta.
+    setLogicalWidth(logicalWidth() + delta);
+}
+
+void RenderMultiColumnSet::updateLogicalHeight()
+{
+    // FIXME: This is the only class that overrides updateLogicalHeight. If we didn't have to set computedColumnHeight,
+    // we could remove this and make updateLogicalHeight non-virtual. https://bugs.webkit.org/show_bug.cgi?id=96804
+    // Make sure our column height is up to date.
+    LogicalExtentComputedValues computedValues;
+    computeLogicalHeight(0, 0, computedValues);
+    setComputedColumnHeight(computedValues.m_extent); // FIXME: Once we make more than one column set, this will become variable.
+    
+    // Our logical height is always just the height of our columns.
+    setLogicalHeight(computedColumnHeight());
+}
+
+void RenderMultiColumnSet::computeLogicalHeight(LayoutUnit, LayoutUnit, LogicalExtentComputedValues& computedValues) const
+{
+    RenderMultiColumnBlock* parentBlock = toRenderMultiColumnBlock(parent());
+    computedValues.m_extent = parentBlock->columnHeight();
+}
+
+LayoutUnit RenderMultiColumnSet::columnGap() const
+{
+    // FIXME: Eventually we will cache the column gap when the widths of columns start varying, but for now we just
+    // go to the parent block to get the gap.
+    RenderMultiColumnBlock* parentBlock = toRenderMultiColumnBlock(parent());
+    if (parentBlock->style()->hasNormalColumnGap())
+        return parentBlock->style()->fontDescription().computedPixelSize(); // "1em" is recommended as the normal gap setting. Matches <p> margins.
+    return parentBlock->style()->columnGap();
+}
+
+unsigned RenderMultiColumnSet::columnCount() const
+{
+    if (!computedColumnHeight())
+        return 0;
+    
+    // Our portion rect determines our column count. We have as many columns as needed to fit all the content.
+    LayoutUnit logicalHeightInColumns = flowThread()->isHorizontalWritingMode() ? flowThreadPortionRect().height() : flowThreadPortionRect().width();
+    return ceil(static_cast<float>(logicalHeightInColumns) / computedColumnHeight());
+}
+
+LayoutRect RenderMultiColumnSet::columnRectAt(unsigned index) const
+{
+    LayoutUnit colLogicalWidth = computedColumnWidth();
+    LayoutUnit colLogicalHeight = computedColumnHeight();
+    LayoutUnit colLogicalTop = borderBefore() + paddingBefore();
+    LayoutUnit colLogicalLeft = borderAndPaddingLogicalLeft();
+    LayoutUnit colGap = columnGap();
+    if (style()->isLeftToRightDirection())
+        colLogicalLeft += index * (colLogicalWidth + colGap);
+    else
+        colLogicalLeft += contentLogicalWidth() - colLogicalWidth - index * (colLogicalWidth + colGap);
+
+    if (isHorizontalWritingMode())
+        return LayoutRect(colLogicalLeft, colLogicalTop, colLogicalWidth, colLogicalHeight);
+    return LayoutRect(colLogicalTop, colLogicalLeft, colLogicalHeight, colLogicalWidth);
+}
+
+unsigned RenderMultiColumnSet::columnIndexAtOffset(LayoutUnit offset) const
+{
+    LayoutRect portionRect(flowThreadPortionRect());
+    LayoutUnit flowThreadLogicalTop = isHorizontalWritingMode() ? portionRect.y() : portionRect.x();
+    LayoutUnit flowThreadLogicalBottom = isHorizontalWritingMode() ? portionRect.maxY() : portionRect.maxX();
+    
+    // Handle the offset being out of range.
+    if (offset < flowThreadLogicalTop)
+        return 0;
+    if (offset >= flowThreadLogicalBottom)
+        return columnCount() - 1;
+    
+    // Just divide by the column height to determine the correct column.
+    return static_cast<float>(offset - flowThreadLogicalTop) / computedColumnHeight();
+}
+
+LayoutRect RenderMultiColumnSet::flowThreadPortionRectAt(unsigned index) const
+{
+    LayoutRect portionRect = flowThreadPortionRect();
+    if (isHorizontalWritingMode())
+        portionRect = LayoutRect(portionRect.x(), portionRect.y() + index * computedColumnHeight(), portionRect.width(), computedColumnHeight());
+    else
+        portionRect = LayoutRect(portionRect.x() + index * computedColumnHeight(), portionRect.y(), computedColumnHeight(), portionRect.height());
+    return portionRect;
+}
+
+LayoutRect RenderMultiColumnSet::flowThreadPortionOverflowRect(const LayoutRect& portionRect, unsigned index, unsigned colCount, LayoutUnit colGap) const
+{
+    // This function determines the portion of the flow thread that paints for the column. Along the inline axis, columns are
+    // unclipped at outside edges (i.e., the first and last column in the set), and they clip to half the column
+    // gap along interior edges.
+    //
+    // In the block direction, we will not clip overflow out of the top of the first column, or out of the bottom of
+    // the last column. This applies only to the true first column and last column across all column sets.
+    //
+    // FIXME: Eventually we will know overflow on a per-column basis, but we can't do this until we have a painting
+    // mode that understands not to paint contents from a previous column in the overflow area of a following column.
+    // This problem applies to regions and pages as well and is not unique to columns.
+    bool isFirstColumn = !index;
+    bool isLastColumn = index == colCount - 1;
+    bool isLeftmostColumn = style()->isLeftToRightDirection() ? isFirstColumn : isLastColumn;
+    bool isRightmostColumn = style()->isLeftToRightDirection() ? isLastColumn : isFirstColumn;
+    LayoutRect overflowRect(portionRect);
+    if (isHorizontalWritingMode()) {
+        if (isLeftmostColumn) {
+            // Shift to the logical left overflow of the flow thread to make sure it's all covered.
+            overflowRect.shiftXEdgeTo(min(flowThread()->visualOverflowRect().x(), portionRect.x()));
+        } else {
+            // Expand into half of the logical left column gap.
+            overflowRect.shiftXEdgeTo(portionRect.x() - colGap / 2);
+        }
+        if (isRightmostColumn) {
+            // Shift to the logical right overflow of the flow thread to ensure content can spill out of the column.
+            overflowRect.shiftMaxXEdgeTo(max(flowThread()->visualOverflowRect().maxX(), portionRect.maxX()));
+        } else {
+            // Expand into half of the logical right column gap.
+            overflowRect.shiftMaxXEdgeTo(portionRect.maxX() + colGap / 2);
+        }
+    } else {
+        if (isLeftmostColumn) {
+            // Shift to the logical left overflow of the flow thread to make sure it's all covered.
+            overflowRect.shiftYEdgeTo(min(flowThread()->visualOverflowRect().y(), portionRect.y()));
+        } else {
+            // Expand into half of the logical left column gap.
+            overflowRect.shiftYEdgeTo(portionRect.y() - colGap / 2);
+        }
+        if (isRightmostColumn) {
+            // Shift to the logical right overflow of the flow thread to ensure content can spill out of the column.
+            overflowRect.shiftMaxYEdgeTo(max(flowThread()->visualOverflowRect().maxY(), portionRect.maxY()));
+        } else {
+            // Expand into half of the logical right column gap.
+            overflowRect.shiftMaxYEdgeTo(portionRect.maxY() + colGap / 2);
+        }
+    }
+    return overflowRectForFlowThreadPortion(overflowRect, isFirstRegion() && isFirstColumn, isLastRegion() && isLastColumn);
+}
+
+void RenderMultiColumnSet::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    if (style()->visibility() != VISIBLE)
+        return;
+
+    RenderBlock::paintObject(paintInfo, paintOffset);
+
+    // FIXME: Right now we're only painting in the foreground phase.
+    // Columns should technically respect phases and allow for background/float/foreground overlap etc., just like
+    // RenderBlocks do. Note this is a pretty minor issue, since the old column implementation clipped columns
+    // anyway, thus making it impossible for them to overlap one another. It's also really unlikely that the columns
+    // would overlap another block.
+    if (!m_flowThread || !isValid() || (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseSelection))
+        return;
+
+    paintColumnRules(paintInfo, paintOffset);
+}
+
+void RenderMultiColumnSet::paintColumnRules(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    if (paintInfo.context->paintingDisabled())
+        return;
+
+    RenderStyle* blockStyle = toRenderMultiColumnBlock(parent())->style();
+    const Color& ruleColor = blockStyle->visitedDependentColor(CSSPropertyWebkitColumnRuleColor);
+    bool ruleTransparent = blockStyle->columnRuleIsTransparent();
+    EBorderStyle ruleStyle = blockStyle->columnRuleStyle();
+    LayoutUnit ruleThickness = blockStyle->columnRuleWidth();
+    LayoutUnit colGap = columnGap();
+    bool renderRule = ruleStyle > BHIDDEN && !ruleTransparent;
+    if (!renderRule)
+        return;
+
+    unsigned colCount = columnCount();
+    if (colCount <= 1)
+        return;
+
+    bool antialias = shouldAntialiasLines(paintInfo.context);
+
+    bool leftToRight = style()->isLeftToRightDirection();
+    LayoutUnit currLogicalLeftOffset = leftToRight ? LayoutUnit() : contentLogicalWidth();
+    LayoutUnit ruleAdd = borderAndPaddingLogicalLeft();
+    LayoutUnit ruleLogicalLeft = leftToRight ? LayoutUnit() : contentLogicalWidth();
+    LayoutUnit inlineDirectionSize = computedColumnWidth();
+    BoxSide boxSide = isHorizontalWritingMode()
+        ? leftToRight ? BSLeft : BSRight
+        : leftToRight ? BSTop : BSBottom;
+
+    for (unsigned i = 0; i < colCount; i++) {
+        // Move to the next position.
+        if (leftToRight) {
+            ruleLogicalLeft += inlineDirectionSize + colGap / 2;
+            currLogicalLeftOffset += inlineDirectionSize + colGap;
+        } else {
+            ruleLogicalLeft -= (inlineDirectionSize + colGap / 2);
+            currLogicalLeftOffset -= (inlineDirectionSize + colGap);
+        }
+
+        // Now paint the column rule.
+        if (i < colCount - 1) {
+            LayoutUnit ruleLeft = isHorizontalWritingMode() ? paintOffset.x() + ruleLogicalLeft - ruleThickness / 2 + ruleAdd : paintOffset.x() + borderLeft() + paddingLeft();
+            LayoutUnit ruleRight = isHorizontalWritingMode() ? ruleLeft + ruleThickness : ruleLeft + contentWidth();
+            LayoutUnit ruleTop = isHorizontalWritingMode() ? paintOffset.y() + borderTop() + paddingTop() : paintOffset.y() + ruleLogicalLeft - ruleThickness / 2 + ruleAdd;
+            LayoutUnit ruleBottom = isHorizontalWritingMode() ? ruleTop + contentHeight() : ruleTop + ruleThickness;
+            IntRect pixelSnappedRuleRect = pixelSnappedIntRectFromEdges(ruleLeft, ruleTop, ruleRight, ruleBottom);
+            drawLineForBoxSide(paintInfo.context, pixelSnappedRuleRect.x(), pixelSnappedRuleRect.y(), pixelSnappedRuleRect.maxX(), pixelSnappedRuleRect.maxY(), boxSide, ruleColor, ruleStyle, 0, 0, antialias);
+        }
+        
+        ruleLogicalLeft = currLogicalLeftOffset;
+    }
+}
+
+void RenderMultiColumnSet::repaintFlowThreadContent(const LayoutRect& repaintRect) const
+{
+    // Figure out the start and end columns and only check within that range so that we don't walk the
+    // entire column set. Put the repaint rect into flow thread coordinates by flipping it first.
+    LayoutRect flowThreadRepaintRect(repaintRect);
+    flowThread()->flipForWritingMode(flowThreadRepaintRect);
+    
+    // Now we can compare this rect with the flow thread portions owned by each column. First let's
+    // just see if the repaint rect intersects our flow thread portion at all.
+    LayoutRect clippedRect(flowThreadRepaintRect);
+    clippedRect.intersect(RenderRegion::flowThreadPortionOverflowRect());
+    if (clippedRect.isEmpty())
+        return;
+    
+    // Now we know we intersect at least one column. Let's figure out the logical top and logical
+    // bottom of the area we're repainting.
+    LayoutUnit repaintLogicalTop = isHorizontalWritingMode() ? flowThreadRepaintRect.y() : flowThreadRepaintRect.x();
+    LayoutUnit repaintLogicalBottom = (isHorizontalWritingMode() ? flowThreadRepaintRect.maxY() : flowThreadRepaintRect.maxX()) - 1;
+    
+    unsigned startColumn = columnIndexAtOffset(repaintLogicalTop);
+    unsigned endColumn = columnIndexAtOffset(repaintLogicalBottom);
+    
+    LayoutUnit colGap = columnGap();
+    unsigned colCount = columnCount();
+    for (unsigned i = startColumn; i <= endColumn; i++) {
+        LayoutRect colRect = columnRectAt(i);
+        
+        // Get the portion of the flow thread that corresponds to this column.
+        LayoutRect flowThreadPortion = flowThreadPortionRectAt(i);
+        
+        // Now get the overflow rect that corresponds to the column.
+        LayoutRect flowThreadOverflowPortion = flowThreadPortionOverflowRect(flowThreadPortion, i, colCount, colGap);
+
+        // Do a repaint for this specific column.
+        repaintFlowThreadContentRectangle(repaintRect, flowThreadPortion, flowThreadOverflowPortion, colRect.location());
+    }
+}
+
+void RenderMultiColumnSet::collectLayerFragments(LayerFragments& fragments, const LayoutRect& layerBoundingBox, const LayoutRect& dirtyRect)
+{
+    // Put the layer bounds into flow thread-local coordinates by flipping it first.
+    LayoutRect layerBoundsInFlowThread(layerBoundingBox);
+    flowThread()->flipForWritingMode(layerBoundsInFlowThread);
+
+    // Do the same for the dirty rect.
+    LayoutRect dirtyRectInFlowThread(dirtyRect);
+    flowThread()->flipForWritingMode(dirtyRectInFlowThread);
+
+    // Now we can compare with the flow thread portions owned by each column. First let's
+    // see if the rect intersects our flow thread portion at all.
+    LayoutRect clippedRect(layerBoundsInFlowThread);
+    clippedRect.intersect(RenderRegion::flowThreadPortionOverflowRect());
+    if (clippedRect.isEmpty())
+        return;
+    
+    // Now we know we intersect at least one column. Let's figure out the logical top and logical
+    // bottom of the area we're checking.
+    LayoutUnit layerLogicalTop = isHorizontalWritingMode() ? layerBoundsInFlowThread.y() : layerBoundsInFlowThread.x();
+    LayoutUnit layerLogicalBottom = (isHorizontalWritingMode() ? layerBoundsInFlowThread.maxY() : layerBoundsInFlowThread.maxX()) - 1;
+    
+    // Figure out the start and end columns and only check within that range so that we don't walk the
+    // entire column set.
+    unsigned startColumn = columnIndexAtOffset(layerLogicalTop);
+    unsigned endColumn = columnIndexAtOffset(layerLogicalBottom);
+    
+    LayoutUnit colLogicalWidth = computedColumnWidth();
+    LayoutUnit colGap = columnGap();
+    unsigned colCount = columnCount();
+    
+    for (unsigned i = startColumn; i <= endColumn; i++) {
+        // Get the portion of the flow thread that corresponds to this column.
+        LayoutRect flowThreadPortion = flowThreadPortionRectAt(i);
+        
+        // Now get the overflow rect that corresponds to the column.
+        LayoutRect flowThreadOverflowPortion = flowThreadPortionOverflowRect(flowThreadPortion, i, colCount, colGap);
+
+        // In order to create a fragment we must intersect the portion painted by this column.
+        LayoutRect clippedRect(layerBoundsInFlowThread);
+        clippedRect.intersect(flowThreadOverflowPortion);
+        if (clippedRect.isEmpty())
+            continue;
+        
+        // We also need to intersect the dirty rect. We have to apply a translation and shift based off
+        // our column index.
+        LayoutPoint translationOffset;
+        LayoutUnit inlineOffset = i * (colLogicalWidth + colGap);
+        if (!style()->isLeftToRightDirection())
+            inlineOffset = -inlineOffset;
+        translationOffset.setX(inlineOffset);
+        LayoutUnit blockOffset = isHorizontalWritingMode() ? -flowThreadPortion.y() : -flowThreadPortion.x();
+        if (isFlippedBlocksWritingMode(style()->writingMode()))
+            blockOffset = -blockOffset;
+        translationOffset.setY(blockOffset);
+        if (!isHorizontalWritingMode())
+            translationOffset = translationOffset.transposedPoint();
+        // FIXME: The translation needs to include the multicolumn set's content offset within the
+        // multicolumn block as well. This won't be an issue until we start creating multiple multicolumn sets.
+
+        // Shift the dirty rect to be in flow thread coordinates with this translation applied.
+        LayoutRect translatedDirtyRect(dirtyRectInFlowThread);
+        translatedDirtyRect.moveBy(-translationOffset);
+        
+        // See if we intersect the dirty rect.
+        clippedRect = layerBoundsInFlowThread;
+        clippedRect.intersect(translatedDirtyRect);
+        if (clippedRect.isEmpty())
+            continue;
+        
+        // Something does need to paint in this column. Make a fragment now and supply the physical translation
+        // offset and the clip rect for the column with that offset applied.
+        LayerFragment fragment;
+        fragment.paginationOffset = translationOffset;
+        
+        LayoutRect flippedFlowThreadOverflowPortion(flowThreadOverflowPortion);
+        flipForWritingMode(flippedFlowThreadOverflowPortion);
+        fragment.paginationClip = flippedFlowThreadOverflowPortion;
+        fragments.append(fragment);
+    }
+}
+
+const char* RenderMultiColumnSet::renderName() const
+{    
+    return "RenderMultiColumnSet";
+}
+
+}
diff --git a/Source/core/rendering/RenderMultiColumnSet.h b/Source/core/rendering/RenderMultiColumnSet.h
new file mode 100644
index 0000000..bd5b0cd
--- /dev/null
+++ b/Source/core/rendering/RenderMultiColumnSet.h
@@ -0,0 +1,159 @@
+/*
+ * Copyright (C) 2012 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 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 RenderMultiColumnSet_h
+#define RenderMultiColumnSet_h
+
+#include "core/rendering/RenderRegionSet.h"
+
+namespace WebCore {
+
+// RenderMultiColumnSet represents a set of columns that all have the same width and height. By combining runs of same-size columns into a single
+// object, we significantly reduce the number of unique RenderObjects required to represent columns.
+//
+// A simple multi-column block will have exactly one RenderMultiColumnSet child. A simple paginated multi-column block will have three
+// RenderMultiColumnSet children: one for the content at the bottom of the first page (whose columns will have a shorter height), one
+// for the 2nd to n-1 pages, and then one last column set that will hold the shorter columns on the final page (that may have to be balanced
+// as well).
+//
+// Column spans result in the creation of new column sets as well, since a spanning region has to be placed in between the column sets that
+// come before and after the span.
+class RenderMultiColumnSet FINAL : public RenderRegionSet {
+public:
+    static RenderMultiColumnSet* createAnonymous(RenderFlowThread*);
+
+    virtual bool isRenderMultiColumnSet() const OVERRIDE { return true; }
+
+    unsigned computedColumnCount() const { return m_computedColumnCount; }
+    LayoutUnit computedColumnWidth() const { return m_computedColumnWidth; }
+    LayoutUnit computedColumnHeight() const { return m_computedColumnHeight; }
+
+    void setComputedColumnWidthAndCount(LayoutUnit width, unsigned count)
+    {
+        m_computedColumnWidth = width;
+        m_computedColumnCount = count;
+    }
+    void setComputedColumnHeight(LayoutUnit height)
+    {
+        m_computedColumnHeight = height;
+    }
+
+    void updateMinimumColumnHeight(LayoutUnit height) { m_minimumColumnHeight = std::max(height, m_minimumColumnHeight); }
+    LayoutUnit minimumColumnHeight() const { return m_minimumColumnHeight; }
+
+    unsigned forcedBreaksCount() const { return m_forcedBreaksCount; }
+    LayoutUnit forcedBreakOffset() const { return m_forcedBreakOffset; }
+    LayoutUnit maximumDistanceBetweenForcedBreaks() const { return m_maximumDistanceBetweenForcedBreaks; }
+    void clearForcedBreaks()
+    { 
+        m_forcedBreaksCount = 0;
+        m_maximumDistanceBetweenForcedBreaks = 0;
+        m_forcedBreakOffset = 0;
+    }
+    void addForcedBreak(LayoutUnit offsetFromFirstPage)
+    { 
+        ASSERT(!computedColumnHeight());
+        LayoutUnit distanceFromLastBreak = offsetFromFirstPage - m_forcedBreakOffset;
+        if (!distanceFromLastBreak)
+            return;
+        m_forcedBreaksCount++;
+        m_maximumDistanceBetweenForcedBreaks = std::max(m_maximumDistanceBetweenForcedBreaks, distanceFromLastBreak);
+        m_forcedBreakOffset = offsetFromFirstPage;
+    }
+
+    bool requiresBalancing() const { return m_requiresBalancing; }
+    void setRequiresBalancing(bool balancing) { m_requiresBalancing = balancing; }
+
+    virtual void updateLogicalWidth() OVERRIDE;
+    virtual void updateLogicalHeight() OVERRIDE;
+    
+private:
+    RenderMultiColumnSet(RenderFlowThread*);
+
+    virtual void computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues&) const OVERRIDE;
+
+    virtual void paintObject(PaintInfo&, const LayoutPoint& paintOffset) OVERRIDE;
+
+    virtual LayoutUnit pageLogicalWidth() const OVERRIDE { return m_computedColumnWidth; }
+    virtual LayoutUnit pageLogicalHeight() const OVERRIDE { return m_computedColumnHeight; }
+
+    virtual LayoutUnit pageLogicalTopForOffset(LayoutUnit offset) const OVERRIDE;
+    
+    // FIXME: This will change once we have column sets constrained by enclosing pages, etc.
+    virtual LayoutUnit logicalHeightOfAllFlowThreadContent() const OVERRIDE { return m_computedColumnHeight; }
+
+    // FIXME: For now we return false, but it's likely we will leverage the auto height region code to do column
+    // balancing. That's why we have an override of this function that is distinct from RenderRegionSet's override.
+    virtual bool shouldHaveAutoLogicalHeight() const OVERRIDE { return false; }
+    
+    virtual void repaintFlowThreadContent(const LayoutRect& repaintRect) const OVERRIDE;
+
+    virtual void collectLayerFragments(LayerFragments&, const LayoutRect& layerBoundingBox, const LayoutRect& dirtyRect) OVERRIDE;
+
+    virtual const char* renderName() const;
+    
+    void paintColumnRules(PaintInfo&, const LayoutPoint& paintOffset);
+
+    LayoutUnit columnGap() const;
+    LayoutRect columnRectAt(unsigned index) const;
+    unsigned columnCount() const;
+
+    LayoutRect flowThreadPortionRectAt(unsigned index) const;
+    LayoutRect flowThreadPortionOverflowRect(const LayoutRect& flowThreadPortion, unsigned index, unsigned colCount, LayoutUnit colGap) const;
+    
+    unsigned columnIndexAtOffset(LayoutUnit) const;
+    
+    unsigned m_computedColumnCount;
+    LayoutUnit m_computedColumnWidth;
+    LayoutUnit m_computedColumnHeight;
+    
+    // The following variables are used when balancing the column set.
+    bool m_requiresBalancing; // Whether or not the columns in the column set have to be balanced, i.e., made to be similar logical heights.
+    LayoutUnit m_minimumColumnHeight;
+    unsigned m_forcedBreaksCount; // FIXME: We will ultimately need to cache more information to balance around forced breaks properly.
+    LayoutUnit m_maximumDistanceBetweenForcedBreaks;
+    LayoutUnit m_forcedBreakOffset;
+};
+
+inline RenderMultiColumnSet* toRenderMultiColumnSet(RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isRenderMultiColumnSet());
+    return static_cast<RenderMultiColumnSet*>(object);
+}
+
+inline const RenderMultiColumnSet* toRenderMultiColumnSet(const RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isRenderMultiColumnSet());
+    return static_cast<const RenderMultiColumnSet*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderMultiColumnSet(const RenderMultiColumnSet*);
+
+} // namespace WebCore
+
+#endif // RenderMultiColumnSet_h
+
diff --git a/Source/core/rendering/RenderNamedFlowThread.cpp b/Source/core/rendering/RenderNamedFlowThread.cpp
new file mode 100644
index 0000000..2f18d51
--- /dev/null
+++ b/Source/core/rendering/RenderNamedFlowThread.cpp
@@ -0,0 +1,613 @@
+/*
+ * Copyright (C) 2012 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 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 IN..0TERRUPTION) 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 "core/rendering/RenderNamedFlowThread.h"
+
+#include "RuntimeEnabledFeatures.h"
+#include "core/dom/ExceptionCodePlaceholder.h"
+#include "core/dom/NamedFlow.h"
+#include "core/dom/NodeTraversal.h"
+#include "core/dom/Position.h"
+#include "core/dom/Range.h"
+#include "core/dom/Text.h"
+#include "core/inspector/InspectorInstrumentation.h"
+#include "core/rendering/FlowThreadController.h"
+#include "core/rendering/InlineTextBox.h"
+#include "core/rendering/RenderInline.h"
+#include "core/rendering/RenderRegion.h"
+#include "core/rendering/RenderText.h"
+#include "core/rendering/RenderView.h"
+
+namespace WebCore {
+
+RenderNamedFlowThread* RenderNamedFlowThread::createAnonymous(Document* document, PassRefPtr<NamedFlow> namedFlow)
+{
+    ASSERT(RuntimeEnabledFeatures::cssRegionsEnabled());
+    RenderNamedFlowThread* renderer = new (document->renderArena()) RenderNamedFlowThread(namedFlow);
+    renderer->setDocumentForAnonymous(document);
+    return renderer;
+}
+
+RenderNamedFlowThread::RenderNamedFlowThread(PassRefPtr<NamedFlow> namedFlow)
+    : m_namedFlow(namedFlow)
+    , m_regionLayoutUpdateEventTimer(this, &RenderNamedFlowThread::regionLayoutUpdateEventTimerFired)
+{
+}
+
+RenderNamedFlowThread::~RenderNamedFlowThread()
+{
+    // The flow thread can be destroyed without unregistering the content nodes if the document is destroyed.
+    // This can lead to problems because the nodes are still marked as belonging to a flow thread.
+    clearContentNodes();
+
+    // Also leave the NamedFlow object in a consistent state by calling mark for destruction.
+    setMarkForDestruction();
+}
+
+const char* RenderNamedFlowThread::renderName() const
+{    
+    return "RenderNamedFlowThread";
+}
+    
+void RenderNamedFlowThread::clearContentNodes()
+{
+    for (NamedFlowContentNodes::iterator it = m_contentNodes.begin(); it != m_contentNodes.end(); ++it) {
+        Node* contentNode = *it;
+        
+        ASSERT(contentNode && contentNode->isElementNode());
+        ASSERT(contentNode->inNamedFlow());
+        ASSERT(contentNode->document() == document());
+        
+        contentNode->clearInNamedFlow();
+    }
+    
+    m_contentNodes.clear();
+}
+
+RenderObject* RenderNamedFlowThread::nextRendererForNode(Node* node) const
+{
+    FlowThreadChildList::const_iterator it = m_flowThreadChildList.begin();
+    FlowThreadChildList::const_iterator end = m_flowThreadChildList.end();
+
+    for (; it != end; ++it) {
+        RenderObject* child = *it;
+        ASSERT(child->node());
+        unsigned short position = node->compareDocumentPosition(child->node());
+        if (position & Node::DOCUMENT_POSITION_FOLLOWING)
+            return child;
+    }
+
+    return 0;
+}
+
+RenderObject* RenderNamedFlowThread::previousRendererForNode(Node* node) const
+{
+    if (m_flowThreadChildList.isEmpty())
+        return 0;
+
+    FlowThreadChildList::const_iterator begin = m_flowThreadChildList.begin();
+    FlowThreadChildList::const_iterator end = m_flowThreadChildList.end();
+    FlowThreadChildList::const_iterator it = end;
+
+    do {
+        --it;
+        RenderObject* child = *it;
+        ASSERT(child->node());
+        unsigned short position = node->compareDocumentPosition(child->node());
+        if (position & Node::DOCUMENT_POSITION_PRECEDING)
+            return child;
+    } while (it != begin);
+
+    return 0;
+}
+
+void RenderNamedFlowThread::addFlowChild(RenderObject* newChild)
+{
+    // The child list is used to sort the flow thread's children render objects 
+    // based on their corresponding nodes DOM order. The list is needed to avoid searching the whole DOM.
+
+    Node* childNode = newChild->node();
+
+    // Do not add anonymous objects.
+    if (!childNode)
+        return;
+
+    ASSERT(childNode->isElementNode());
+
+    RenderObject* beforeChild = nextRendererForNode(childNode);
+    if (beforeChild)
+        m_flowThreadChildList.insertBefore(beforeChild, newChild);
+    else
+        m_flowThreadChildList.add(newChild);
+}
+
+void RenderNamedFlowThread::removeFlowChild(RenderObject* child)
+{
+    m_flowThreadChildList.remove(child);
+}
+
+bool RenderNamedFlowThread::dependsOn(RenderNamedFlowThread* otherRenderFlowThread) const
+{
+    if (m_layoutBeforeThreadsSet.contains(otherRenderFlowThread))
+        return true;
+
+    // Recursively traverse the m_layoutBeforeThreadsSet.
+    RenderNamedFlowThreadCountedSet::const_iterator iterator = m_layoutBeforeThreadsSet.begin();
+    RenderNamedFlowThreadCountedSet::const_iterator end = m_layoutBeforeThreadsSet.end();
+    for (; iterator != end; ++iterator) {
+        const RenderNamedFlowThread* beforeFlowThread = (*iterator).key;
+        if (beforeFlowThread->dependsOn(otherRenderFlowThread))
+            return true;
+    }
+
+    return false;
+}
+
+// Compare two regions to determine in which one the content should flow first.
+// The function returns true if the first passed region is "less" than the second passed region.
+// If the first region appears before second region in DOM,
+// the first region is "less" than the second region.
+// If the first region is "less" than the second region, the first region receives content before second region.
+static bool compareRenderRegions(const RenderRegion* firstRegion, const RenderRegion* secondRegion)
+{
+    ASSERT(firstRegion);
+    ASSERT(secondRegion);
+
+    ASSERT(firstRegion->generatingNode());
+    ASSERT(secondRegion->generatingNode());
+
+    // If the regions belong to different nodes, compare their position in the DOM.
+    if (firstRegion->generatingNode() != secondRegion->generatingNode()) {
+        unsigned short position = firstRegion->generatingNode()->compareDocumentPosition(secondRegion->generatingNode());
+
+        // If the second region is contained in the first one, the first region is "less" if it's :before.
+        if (position & Node::DOCUMENT_POSITION_CONTAINED_BY) {
+            ASSERT(secondRegion->style()->styleType() == NOPSEUDO);
+            return firstRegion->style()->styleType() == BEFORE;
+        }
+
+        // If the second region contains the first region, the first region is "less" if the second is :after.
+        if (position & Node::DOCUMENT_POSITION_CONTAINS) {
+            ASSERT(firstRegion->style()->styleType() == NOPSEUDO);
+            return secondRegion->style()->styleType() == AFTER;
+        }
+
+        return (position & Node::DOCUMENT_POSITION_FOLLOWING);
+    }
+
+    // FIXME: Currently it's not possible for an element to be both a region and have pseudo-children. The case is covered anyway.
+    switch (firstRegion->style()->styleType()) {
+    case BEFORE:
+        // The second region can be the node or the after pseudo-element (before is smaller than any of those).
+        return true;
+    case AFTER:
+        // The second region can be the node or the before pseudo-element (after is greater than any of those).
+        return false;
+    case NOPSEUDO:
+        // The second region can either be the before or the after pseudo-element (the node is only smaller than the after pseudo-element).
+        return firstRegion->style()->styleType() == AFTER;
+    default:
+        break;
+    }
+
+    ASSERT_NOT_REACHED();
+    return true;
+}
+
+// This helper function adds a region to a list preserving the order property of the list.
+static void addRegionToList(RenderRegionList& regionList, RenderRegion* renderRegion)
+{
+    if (regionList.isEmpty())
+        regionList.add(renderRegion);
+    else {
+        // Find the first region "greater" than renderRegion.
+        RenderRegionList::iterator it = regionList.begin();
+        while (it != regionList.end() && !compareRenderRegions(renderRegion, *it))
+            ++it;
+        regionList.insertBefore(it, renderRegion);
+    }
+}
+
+void RenderNamedFlowThread::addRegionToNamedFlowThread(RenderRegion* renderRegion)
+{
+    ASSERT(renderRegion);
+    ASSERT(!renderRegion->isValid());
+
+    if (renderRegion->parentNamedFlowThread())
+        addDependencyOnFlowThread(renderRegion->parentNamedFlowThread());
+
+    renderRegion->setIsValid(true);
+    addRegionToList(m_regionList, renderRegion);
+}
+
+void RenderNamedFlowThread::addRegionToThread(RenderRegion* renderRegion)
+{
+    ASSERT(renderRegion);
+    ASSERT(!renderRegion->isValid());
+
+    resetMarkForDestruction();
+
+    if (renderRegion->parentNamedFlowThread() && renderRegion->parentNamedFlowThread()->dependsOn(this)) {
+        // The order of invalid regions is irrelevant.
+        m_invalidRegionList.add(renderRegion);
+        // Register ourself to get a notification when the state changes.
+        renderRegion->parentNamedFlowThread()->m_observerThreadsSet.add(this);
+        return;
+    }
+
+    addRegionToNamedFlowThread(renderRegion);
+
+    invalidateRegions();
+}
+
+void RenderNamedFlowThread::removeRegionFromThread(RenderRegion* renderRegion)
+{
+    ASSERT(renderRegion);
+
+    if (renderRegion->parentNamedFlowThread()) {
+        if (!renderRegion->isValid()) {
+            ASSERT(m_invalidRegionList.contains(renderRegion));
+            m_invalidRegionList.remove(renderRegion);
+            renderRegion->parentNamedFlowThread()->m_observerThreadsSet.remove(this);
+            // No need to invalidate the regions rectangles. The removed region
+            // was not taken into account. Just return here.
+            return;
+        }
+        removeDependencyOnFlowThread(renderRegion->parentNamedFlowThread());
+    }
+
+    ASSERT(m_regionList.contains(renderRegion));
+    m_regionList.remove(renderRegion);
+
+    if (canBeDestroyed())
+        setMarkForDestruction();
+
+    // After removing all the regions in the flow the following layout needs to dispatch the regionLayoutUpdate event
+    if (m_regionList.isEmpty())
+        setDispatchRegionLayoutUpdateEvent(true);
+
+    invalidateRegions();
+}
+
+void RenderNamedFlowThread::checkInvalidRegions()
+{
+    Vector<RenderRegion*> newValidRegions;
+    for (RenderRegionList::iterator iter = m_invalidRegionList.begin(); iter != m_invalidRegionList.end(); ++iter) {
+        RenderRegion* region = *iter;
+        // The only reason a region would be invalid is because it has a parent flow thread.
+        ASSERT(!region->isValid() && region->parentNamedFlowThread());
+        if (region->parentNamedFlowThread()->dependsOn(this))
+            continue;
+
+        newValidRegions.append(region);
+    }
+
+    for (Vector<RenderRegion*>::iterator iter = newValidRegions.begin(); iter != newValidRegions.end(); ++iter) {
+        RenderRegion* region = *iter;
+        m_invalidRegionList.remove(region);
+        region->parentNamedFlowThread()->m_observerThreadsSet.remove(this);
+        addRegionToNamedFlowThread(region);
+    }
+
+    if (!newValidRegions.isEmpty())
+        invalidateRegions();
+
+    if (m_observerThreadsSet.isEmpty())
+        return;
+
+    // Notify all the flow threads that were dependent on this flow.
+
+    // Create a copy of the list first. That's because observers might change the list when calling checkInvalidRegions.
+    Vector<RenderNamedFlowThread*> observers;
+    copyToVector(m_observerThreadsSet, observers);
+
+    for (size_t i = 0; i < observers.size(); ++i) {
+        RenderNamedFlowThread* flowThread = observers.at(i);
+        flowThread->checkInvalidRegions();
+    }
+}
+
+void RenderNamedFlowThread::addDependencyOnFlowThread(RenderNamedFlowThread* otherFlowThread)
+{
+    RenderNamedFlowThreadCountedSet::AddResult result = m_layoutBeforeThreadsSet.add(otherFlowThread);
+    if (result.isNewEntry) {
+        // This is the first time we see this dependency. Make sure we recalculate all the dependencies.
+        view()->flowThreadController()->setIsRenderNamedFlowThreadOrderDirty(true);
+    }
+}
+
+void RenderNamedFlowThread::removeDependencyOnFlowThread(RenderNamedFlowThread* otherFlowThread)
+{
+    bool removed = m_layoutBeforeThreadsSet.remove(otherFlowThread);
+    if (removed) {
+        checkInvalidRegions();
+        view()->flowThreadController()->setIsRenderNamedFlowThreadOrderDirty(true);
+    }
+}
+
+void RenderNamedFlowThread::pushDependencies(RenderNamedFlowThreadList& list)
+{
+    for (RenderNamedFlowThreadCountedSet::iterator iter = m_layoutBeforeThreadsSet.begin(); iter != m_layoutBeforeThreadsSet.end(); ++iter) {
+        RenderNamedFlowThread* flowThread = (*iter).key;
+        if (list.contains(flowThread))
+            continue;
+        flowThread->pushDependencies(list);
+        list.add(flowThread);
+    }
+}
+
+// The content nodes list contains those nodes with -webkit-flow-into: flow.
+// An element with display:none should also be listed among those nodes.
+// The list of nodes is ordered.
+void RenderNamedFlowThread::registerNamedFlowContentNode(Node* contentNode)
+{
+    ASSERT(contentNode && contentNode->isElementNode());
+    ASSERT(contentNode->document() == document());
+
+    contentNode->setInNamedFlow();
+
+    resetMarkForDestruction();
+
+    // Find the first content node following the new content node.
+    for (NamedFlowContentNodes::iterator it = m_contentNodes.begin(); it != m_contentNodes.end(); ++it) {
+        Node* node = *it;
+        unsigned short position = contentNode->compareDocumentPosition(node);
+        if (position & Node::DOCUMENT_POSITION_FOLLOWING) {
+            m_contentNodes.insertBefore(node, contentNode);
+            return;
+        }
+    }
+    m_contentNodes.add(contentNode);
+}
+
+void RenderNamedFlowThread::unregisterNamedFlowContentNode(Node* contentNode)
+{
+    ASSERT(contentNode && contentNode->isElementNode());
+    ASSERT(m_contentNodes.contains(contentNode));
+    ASSERT(contentNode->inNamedFlow());
+    ASSERT(contentNode->document() == document());
+
+    contentNode->clearInNamedFlow();
+    m_contentNodes.remove(contentNode);
+
+    if (canBeDestroyed())
+        setMarkForDestruction();
+}
+
+const AtomicString& RenderNamedFlowThread::flowThreadName() const
+{
+    return m_namedFlow->name();
+}
+
+void RenderNamedFlowThread::dispatchRegionLayoutUpdateEvent()
+{
+    RenderFlowThread::dispatchRegionLayoutUpdateEvent();
+    InspectorInstrumentation::didUpdateRegionLayout(document(), m_namedFlow.get());
+
+    if (!m_regionLayoutUpdateEventTimer.isActive() && m_namedFlow->hasEventListeners())
+        m_regionLayoutUpdateEventTimer.startOneShot(0);
+}
+
+void RenderNamedFlowThread::regionLayoutUpdateEventTimerFired(Timer<RenderNamedFlowThread>*)
+{
+    ASSERT(m_namedFlow);
+
+    m_namedFlow->dispatchRegionLayoutUpdateEvent();
+}
+
+void RenderNamedFlowThread::setMarkForDestruction()
+{
+    if (m_namedFlow->flowState() == NamedFlow::FlowStateNull)
+        return;
+
+    m_namedFlow->setRenderer(0);
+    // After this call ends, the renderer can be safely destroyed.
+    // The NamedFlow object may outlive its renderer if it's referenced from a script and may be reatached to one if the named flow is recreated in the stylesheet.
+}
+
+void RenderNamedFlowThread::resetMarkForDestruction()
+{
+    if (m_namedFlow->flowState() == NamedFlow::FlowStateCreated)
+        return;
+
+    m_namedFlow->setRenderer(this);
+}
+
+bool RenderNamedFlowThread::isMarkedForDestruction() const
+{
+    // Flow threads in the "NULL" state can be destroyed.
+    return m_namedFlow->flowState() == NamedFlow::FlowStateNull;
+}
+
+static bool isContainedInNodes(Vector<Node*> others, Node* node)
+{
+    for (size_t i = 0; i < others.size(); i++) {
+        Node* other = others.at(i);
+        if (other->contains(node))
+            return true;
+    }
+    return false;
+}
+
+static bool boxIntersectsRegion(LayoutUnit logicalTopForBox, LayoutUnit logicalBottomForBox, LayoutUnit logicalTopForRegion, LayoutUnit logicalBottomForRegion)
+{
+    bool regionIsEmpty = logicalBottomForRegion != LayoutUnit::max() && logicalTopForRegion != LayoutUnit::min()
+        && (logicalBottomForRegion - logicalTopForRegion) <= 0;
+    return  (logicalBottomForBox - logicalTopForBox) > 0
+        && !regionIsEmpty
+        && logicalTopForBox < logicalBottomForRegion && logicalTopForRegion < logicalBottomForBox;
+}
+
+void RenderNamedFlowThread::getRanges(Vector<RefPtr<Range> >& rangeObjects, const RenderRegion* region) const
+{
+    LayoutUnit logicalTopForRegion;
+    LayoutUnit logicalBottomForRegion;
+
+    // extend the first region top to contain everything up to its logical height
+    if (region->isFirstRegion())
+        logicalTopForRegion = LayoutUnit::min();
+    else
+        logicalTopForRegion =  region->logicalTopForFlowThreadContent();
+
+    // extend the last region to contain everything above its y()
+    if (region->isLastRegion())
+        logicalBottomForRegion = LayoutUnit::max();
+    else
+        logicalBottomForRegion = region->logicalBottomForFlowThreadContent();
+
+    Vector<Node*> nodes;
+    // eliminate the contentNodes that are descendants of other contentNodes
+    for (NamedFlowContentNodes::const_iterator it = contentNodes().begin(); it != contentNodes().end(); ++it) {
+        Node* node = *it;
+        if (!isContainedInNodes(nodes, node))
+            nodes.append(node);
+    }
+
+    for (size_t i = 0; i < nodes.size(); i++) {
+        Node* contentNode = nodes.at(i);
+        if (!contentNode->renderer())
+            continue;
+
+        RefPtr<Range> range = Range::create(contentNode->document());
+        bool foundStartPosition = false;
+        bool startsAboveRegion = true;
+        bool endsBelowRegion = true;
+        bool skipOverOutsideNodes = false;
+        Node* lastEndNode = 0;
+
+        for (Node* node = contentNode; node; node = NodeTraversal::next(node, contentNode)) {
+            RenderObject* renderer = node->renderer();
+            if (!renderer)
+                continue;
+
+            LayoutRect boundingBox;
+            if (renderer->isRenderInline())
+                boundingBox = toRenderInline(renderer)->linesBoundingBox();
+            else if (renderer->isText())
+                boundingBox = toRenderText(renderer)->linesBoundingBox();
+            else {
+                boundingBox =  toRenderBox(renderer)->frameRect();
+                if (toRenderBox(renderer)->isRelPositioned())
+                    boundingBox.move(toRenderBox(renderer)->relativePositionLogicalOffset());
+            }
+
+            LayoutUnit offsetTop = renderer->containingBlock()->offsetFromLogicalTopOfFirstPage();
+            const LayoutPoint logicalOffsetFromTop(isHorizontalWritingMode() ? LayoutUnit() :  offsetTop,
+                isHorizontalWritingMode() ? offsetTop : LayoutUnit());
+
+            boundingBox.moveBy(logicalOffsetFromTop);
+
+            LayoutUnit logicalTopForRenderer = region->logicalTopOfFlowThreadContentRect(boundingBox);
+            LayoutUnit logicalBottomForRenderer = region->logicalBottomOfFlowThreadContentRect(boundingBox);
+
+            // if the bounding box of the current element doesn't intersect the region box
+            // close the current range only if the start element began inside the region,
+            // otherwise just move the start position after this node and keep skipping them until we found a proper start position.
+            if (!boxIntersectsRegion(logicalTopForRenderer, logicalBottomForRenderer, logicalTopForRegion, logicalBottomForRegion)) {
+                if (foundStartPosition) {
+                    if (!startsAboveRegion) {
+                        if (range->intersectsNode(node, IGNORE_EXCEPTION))
+                            range->setEndBefore(node, IGNORE_EXCEPTION);
+                        rangeObjects.append(range->cloneRange(IGNORE_EXCEPTION));
+                        range = Range::create(contentNode->document());
+                        startsAboveRegion = true;
+                    } else
+                        skipOverOutsideNodes = true;
+                }
+                if (skipOverOutsideNodes)
+                    range->setStartAfter(node, IGNORE_EXCEPTION);
+                foundStartPosition = false;
+                continue;
+            }
+
+            // start position
+            if (logicalTopForRenderer < logicalTopForRegion && startsAboveRegion) {
+                if (renderer->isText()) { // Text crosses region top
+                    // for Text elements, just find the last textbox that is contained inside the region and use its start() offset as start position
+                    RenderText* textRenderer = toRenderText(renderer);
+                    for (InlineTextBox* box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
+                        if (offsetTop + box->logicalBottom() < logicalTopForRegion)
+                            continue;
+                        range->setStart(Position(toText(node), box->start()));
+                        startsAboveRegion = false;
+                        break;
+                    }
+                } else { // node crosses region top
+                    // for all elements, except Text, just set the start position to be before their children
+                    startsAboveRegion = true;
+                    range->setStart(Position(node, Position::PositionIsBeforeChildren));
+                }
+            } else { // node starts inside region
+                // for elements that start inside the region, set the start position to be before them. If we found one, we will just skip the others until
+                // the range is closed.
+                if (startsAboveRegion) {
+                    startsAboveRegion = false;
+                    range->setStartBefore(node, IGNORE_EXCEPTION);
+                }
+            }
+            skipOverOutsideNodes  = false;
+            foundStartPosition = true;
+
+            // end position
+            if (logicalBottomForRegion < logicalBottomForRenderer && (endsBelowRegion || (!endsBelowRegion && !node->isDescendantOf(lastEndNode)))) {
+                // for Text elements, just find just find the last textbox that is contained inside the region and use its start()+len() offset as end position
+                if (renderer->isText()) { // Text crosses region bottom
+                    RenderText* textRenderer = toRenderText(renderer);
+                    InlineTextBox* lastBox = 0;
+                    for (InlineTextBox* box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
+                        if ((offsetTop + box->logicalTop()) < logicalBottomForRegion) {
+                            lastBox = box;
+                            continue;
+                        }
+                        ASSERT(lastBox);
+                        if (lastBox)
+                            range->setEnd(Position(toText(node), lastBox->start() + lastBox->len()));
+                        break;
+                    }
+                    endsBelowRegion = false;
+                    lastEndNode = node;
+                } else { // node crosses region bottom
+                    // for all elements, except Text, just set the start position to be after their children
+                    range->setEnd(Position(node, Position::PositionIsAfterChildren));
+                    endsBelowRegion = true;
+                    lastEndNode = node;
+                }
+            } else { // node ends inside region
+                // for elements that ends inside the region, set the end position to be after them
+                // allow this end position to be changed only by other elements that are not descendants of the current end node
+                if (endsBelowRegion || (!endsBelowRegion && !node->isDescendantOf(lastEndNode))) {
+                    range->setEndAfter(node, IGNORE_EXCEPTION);
+                    endsBelowRegion = false;
+                    lastEndNode = node;
+                }
+            }
+        }
+        if (foundStartPosition || skipOverOutsideNodes)
+            rangeObjects.append(range);
+    }
+}
+
+}
diff --git a/Source/core/rendering/RenderNamedFlowThread.h b/Source/core/rendering/RenderNamedFlowThread.h
new file mode 100644
index 0000000..16434df
--- /dev/null
+++ b/Source/core/rendering/RenderNamedFlowThread.h
@@ -0,0 +1,145 @@
+/*
+ * Copyright (C) 2012 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 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 RenderNamedFlowThread_h
+#define RenderNamedFlowThread_h
+
+#include "core/platform/Timer.h"
+#include "core/rendering/RenderFlowThread.h"
+#include <wtf/HashCountedSet.h>
+#include <wtf/ListHashSet.h>
+#include <wtf/text/AtomicString.h>
+
+namespace WebCore {
+
+class NamedFlow;
+class Node;
+class RenderNamedFlowThread;
+
+typedef ListHashSet<RenderNamedFlowThread*> RenderNamedFlowThreadList;
+typedef HashCountedSet<RenderNamedFlowThread*> RenderNamedFlowThreadCountedSet;
+typedef ListHashSet<Node*> NamedFlowContentNodes;
+
+class RenderNamedFlowThread FINAL : public RenderFlowThread {
+public:
+    virtual ~RenderNamedFlowThread();
+
+    static RenderNamedFlowThread* createAnonymous(Document*, PassRefPtr<NamedFlow>);
+
+    const AtomicString& flowThreadName() const;
+
+    const RenderRegionList& invalidRenderRegionList() const { return m_invalidRegionList; }
+
+    RenderObject* nextRendererForNode(Node*) const;
+    RenderObject* previousRendererForNode(Node*) const;
+
+    void addFlowChild(RenderObject* newChild);
+    void removeFlowChild(RenderObject*);
+    bool hasChildren() const { return !m_flowThreadChildList.isEmpty(); }
+#ifndef NDEBUG
+    bool hasChild(RenderObject* child) const { return m_flowThreadChildList.contains(child); }
+#endif
+
+    void pushDependencies(RenderNamedFlowThreadList&);
+
+    virtual void addRegionToThread(RenderRegion*) OVERRIDE;
+    virtual void removeRegionFromThread(RenderRegion*) OVERRIDE;
+
+    void registerNamedFlowContentNode(Node*);
+    void unregisterNamedFlowContentNode(Node*);
+    const NamedFlowContentNodes& contentNodes() const { return m_contentNodes; }
+    bool hasContentNode(Node* contentNode) const { ASSERT(contentNode); return m_contentNodes.contains(contentNode); }
+    bool isMarkedForDestruction() const;
+    void getRanges(Vector<RefPtr<Range> >&, const RenderRegion*) const;
+
+protected:
+    void setMarkForDestruction();
+    void resetMarkForDestruction();
+
+private:
+    RenderNamedFlowThread(PassRefPtr<NamedFlow>);
+
+    virtual const char* renderName() const OVERRIDE;
+    virtual bool isRenderNamedFlowThread() const OVERRIDE { return true; }
+
+    virtual void dispatchRegionLayoutUpdateEvent() OVERRIDE;
+
+    bool dependsOn(RenderNamedFlowThread* otherRenderFlowThread) const;
+    void addDependencyOnFlowThread(RenderNamedFlowThread*);
+    void removeDependencyOnFlowThread(RenderNamedFlowThread*);
+
+    void addRegionToNamedFlowThread(RenderRegion*);
+
+    void checkInvalidRegions();
+
+    bool canBeDestroyed() const { return m_invalidRegionList.isEmpty() && m_regionList.isEmpty() && m_contentNodes.isEmpty(); }
+    void regionLayoutUpdateEventTimerFired(Timer<RenderNamedFlowThread>*);
+    void clearContentNodes();
+
+private:
+    // Observer flow threads have invalid regions that depend on the state of this thread
+    // to re-validate their regions. Keeping a set of observer threads make it easy
+    // to notify them when a region was removed from this flow.
+    RenderNamedFlowThreadCountedSet m_observerThreadsSet;
+
+    // Some threads need to have a complete layout before we layout this flow.
+    // That's because they contain a RenderRegion that should display this thread. The set makes it
+    // easy to sort the order of threads layout.
+    RenderNamedFlowThreadCountedSet m_layoutBeforeThreadsSet;
+
+    // Holds the sorted children of a named flow. This is the only way we can get the ordering right.
+    typedef ListHashSet<RenderObject*> FlowThreadChildList;
+    FlowThreadChildList m_flowThreadChildList;
+
+    NamedFlowContentNodes m_contentNodes;
+
+    RenderRegionList m_invalidRegionList;
+
+    // The DOM Object that represents a named flow.
+    RefPtr<NamedFlow> m_namedFlow;
+
+    Timer<RenderNamedFlowThread> m_regionLayoutUpdateEventTimer;
+};
+
+inline RenderNamedFlowThread* toRenderNamedFlowThread(RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isRenderNamedFlowThread());
+    return static_cast<RenderNamedFlowThread*>(object);
+}
+
+inline const RenderNamedFlowThread* toRenderNamedFlowThread(const RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isRenderNamedFlowThread());
+    return static_cast<const RenderNamedFlowThread*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderNamedFlowThread(const RenderNamedFlowThread*);
+
+} // namespace WebCore
+
+#endif // RenderNamedFlowThread_h
+
diff --git a/Source/core/rendering/RenderObject.cpp b/Source/core/rendering/RenderObject.cpp
new file mode 100644
index 0000000..3f277d3
--- /dev/null
+++ b/Source/core/rendering/RenderObject.cpp
@@ -0,0 +1,3185 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2000 Dirk Mueller (mueller@kde.org)
+ *           (C) 2004 Allan Sandfeld Jensen (kde@carewolf.com)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ *
+ * 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 "core/rendering/RenderObject.h"
+
+#include <stdio.h>
+#include <algorithm>
+#include "HTMLNames.h"
+#include "core/accessibility/AXObjectCache.h"
+#include "core/css/StyleResolver.h"
+#include "core/dom/WebCoreMemoryInstrumentation.h"
+#include "core/editing/EditingBoundary.h"
+#include "core/editing/FrameSelection.h"
+#include "core/editing/htmlediting.h"
+#include "core/html/HTMLElement.h"
+#include "core/page/Chrome.h"
+#include "core/page/EventHandler.h"
+#include "core/page/Frame.h"
+#include "core/page/FrameView.h"
+#include "core/page/Page.h"
+#include "core/page/Settings.h"
+#include "core/page/animation/AnimationController.h"
+#include "core/platform/graphics/DashArray.h"
+#include "core/platform/graphics/FloatQuad.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/platform/graphics/transforms/TransformState.h"
+#include "core/rendering/FlowThreadController.h"
+#include "core/rendering/HitTestResult.h"
+#include "core/rendering/RenderArena.h"
+#include "core/rendering/RenderCounter.h"
+#include "core/rendering/RenderDeprecatedFlexibleBox.h"
+#include "core/rendering/RenderFlexibleBox.h"
+#include "core/rendering/RenderGeometryMap.h"
+#include "core/rendering/RenderGrid.h"
+#include "core/rendering/RenderImage.h"
+#include "core/rendering/RenderImageResourceStyleImage.h"
+#include "core/rendering/RenderInline.h"
+#include "core/rendering/RenderLayer.h"
+#include "core/rendering/RenderLayerBacking.h"
+#include "core/rendering/RenderLayerCompositor.h"
+#include "core/rendering/RenderLazyBlock.h"
+#include "core/rendering/RenderListItem.h"
+#include "core/rendering/RenderMultiColumnBlock.h"
+#include "core/rendering/RenderNamedFlowThread.h"
+#include "core/rendering/RenderRegion.h"
+#include "core/rendering/RenderRuby.h"
+#include "core/rendering/RenderRubyText.h"
+#include "core/rendering/RenderScrollbarPart.h"
+#include "core/rendering/RenderTableCaption.h"
+#include "core/rendering/RenderTableCell.h"
+#include "core/rendering/RenderTableCol.h"
+#include "core/rendering/RenderTableRow.h"
+#include "core/rendering/RenderTheme.h"
+#include "core/rendering/RenderView.h"
+#include "core/rendering/style/ContentData.h"
+#include "core/rendering/style/CursorList.h"
+#include <wtf/RefCountedLeakCounter.h>
+#include <wtf/UnusedParam.h>
+
+#if ENABLE(SVG)
+#include "core/rendering/svg/RenderSVGResourceContainer.h"
+#include "core/rendering/svg/SVGRenderSupport.h"
+#endif
+
+using namespace std;
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+#ifndef NDEBUG
+static void* baseOfRenderObjectBeingDeleted;
+
+RenderObject::SetLayoutNeededForbiddenScope::SetLayoutNeededForbiddenScope(RenderObject* renderObject, bool isForbidden)
+    : m_renderObject(renderObject)
+    , m_preexistingForbidden(m_renderObject->isSetNeedsLayoutForbidden())
+{
+    m_renderObject->setNeedsLayoutIsForbidden(isForbidden);
+}
+
+RenderObject::SetLayoutNeededForbiddenScope::~SetLayoutNeededForbiddenScope()
+{
+    m_renderObject->setNeedsLayoutIsForbidden(m_preexistingForbidden);
+}
+#endif
+
+struct SameSizeAsRenderObject {
+    virtual ~SameSizeAsRenderObject() { } // Allocate vtable pointer.
+    void* pointers[5];
+#ifndef NDEBUG
+    unsigned m_debugBitfields : 2;
+#endif
+    unsigned m_bitfields;
+};
+
+COMPILE_ASSERT(sizeof(RenderObject) == sizeof(SameSizeAsRenderObject), RenderObject_should_stay_small);
+
+bool RenderObject::s_affectsParentBlock = false;
+
+RenderObjectAncestorLineboxDirtySet* RenderObject::s_ancestorLineboxDirtySet = 0;
+
+void* RenderObject::operator new(size_t sz, RenderArena* renderArena)
+{
+    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(Element* element, RenderStyle* style)
+{
+    Document* doc = element->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->next() && contentData->isImage() && !element->isPseudoElement()) {
+        RenderImage* image = new (arena) RenderImage(element);
+        // RenderImageResourceStyleImage requires a style being present on the image but we don't want to
+        // trigger a style change now as the node is not fully attached. Moving this code to style change
+        // doesn't make sense as it should be run once at renderer creation.
+        image->setStyleInternal(style);
+        if (const StyleImage* styleImage = static_cast<const ImageContentData*>(contentData)->image()) {
+            image->setImageResource(RenderImageResourceStyleImage::create(const_cast<StyleImage*>(styleImage)));
+            image->setIsGeneratedContent();
+        } else
+            image->setImageResource(RenderImageResource::create());
+        image->setStyleInternal(0);
+        return image;
+    }
+
+    if (element->hasTagName(rubyTag)) {
+        if (style->display() == INLINE)
+            return new (arena) RenderRubyAsInline(element);
+        else if (style->display() == BLOCK)
+            return new (arena) RenderRubyAsBlock(element);
+    }
+    // treat <rt> as ruby text ONLY if it still has its default treatment of block
+    if (element->hasTagName(rtTag) && style->display() == BLOCK)
+        return new (arena) RenderRubyText(element);
+    if (RuntimeEnabledFeatures::cssRegionsEnabled() && style->isDisplayRegionType() && !style->regionThread().isEmpty() && doc->renderView())
+        return new (arena) RenderRegion(element, 0);
+    switch (style->display()) {
+    case NONE:
+        return 0;
+    case INLINE:
+        return new (arena) RenderInline(element);
+    case BLOCK:
+    case INLINE_BLOCK:
+    case RUN_IN:
+    case COMPACT:
+        if ((!style->hasAutoColumnCount() || !style->hasAutoColumnWidth()) && doc->regionBasedColumnsEnabled())
+            return new (arena) RenderMultiColumnBlock(element);
+        return new (arena) RenderBlock(element);
+    case LIST_ITEM:
+        return new (arena) RenderListItem(element);
+    case TABLE:
+    case INLINE_TABLE:
+        return new (arena) RenderTable(element);
+    case TABLE_ROW_GROUP:
+    case TABLE_HEADER_GROUP:
+    case TABLE_FOOTER_GROUP:
+        return new (arena) RenderTableSection(element);
+    case TABLE_ROW:
+        return new (arena) RenderTableRow(element);
+    case TABLE_COLUMN_GROUP:
+    case TABLE_COLUMN:
+        return new (arena) RenderTableCol(element);
+    case TABLE_CELL:
+        return new (arena) RenderTableCell(element);
+    case TABLE_CAPTION:
+        return new (arena) RenderTableCaption(element);
+    case BOX:
+    case INLINE_BOX:
+        return new (arena) RenderDeprecatedFlexibleBox(element);
+    case FLEX:
+    case INLINE_FLEX:
+        return new (arena) RenderFlexibleBox(element);
+    case GRID:
+    case INLINE_GRID:
+        return new (arena) RenderGrid(element);
+    case LAZY_BLOCK:
+        return new (arena) RenderLazyBlock(element);
+    }
+
+    return 0;
+}
+
+DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, renderObjectCounter, ("RenderObject"));
+
+RenderObject::RenderObject(Node* node)
+    : CachedImageClient()
+    , m_style(0)
+    , m_node(node)
+    , m_parent(0)
+    , m_previous(0)
+    , m_next(0)
+#ifndef NDEBUG
+    , m_hasAXObject(false)
+    , m_setNeedsLayoutForbidden(false)
+#endif
+    , m_bitfields(node)
+{
+#ifndef NDEBUG
+    renderObjectCounter.increment();
+#endif
+}
+
+RenderObject::~RenderObject()
+{
+#ifndef NDEBUG
+    ASSERT(!m_hasAXObject);
+    renderObjectCounter.decrement();
+#endif
+}
+
+RenderTheme* RenderObject::theme() const
+{
+    ASSERT(document()->page());
+
+    return document()->page()->theme();
+}
+
+#ifndef NDEBUG
+String RenderObject::debugName() const
+{
+    StringBuilder name;
+    name.append(renderName());
+
+    if (Node* node = this->node()) {
+        name.append(' ');
+        name.append(node->debugName());
+    }
+
+    return name.toString();
+}
+#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() && node()->hasTagName(bodyTag);
+}
+
+bool RenderObject::isHR() const
+{
+    return node() && node()->hasTagName(hrTag);
+}
+
+bool RenderObject::isLegend() const
+{
+    return node() && node()->hasTagName(legendTag);
+}
+
+bool RenderObject::isHTMLMarquee() const
+{
+    return node() && node()->renderer() == this && node()->hasTagName(marqueeTag);
+}
+
+void RenderObject::setFlowThreadStateIncludingDescendants(FlowThreadState state)
+{
+    setFlowThreadState(state);
+
+    for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+        // If the child is a fragmentation context it already updated the descendants flag accordingly.
+        if (child->isRenderFlowThread())
+            continue;
+        ASSERT(state != child->flowThreadState());
+        child->setFlowThreadStateIncludingDescendants(state);
+    }
+}
+
+bool RenderObject::requiresAnonymousTableWrappers(const RenderObject* newChild) const
+{
+    // Check should agree with:
+    // CSS 2.1 Tables: 17.2.1 Anonymous table objects
+    // http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes
+    if (newChild->isRenderTableCol()) {
+        const RenderTableCol* newTableColumn = toRenderTableCol(newChild);
+        bool isColumnInColumnGroup = newTableColumn->isTableColumn() && isRenderTableCol();
+        return !isTable() && !isColumnInColumnGroup;
+    } else if (newChild->isTableCaption())
+        return !isTable();
+    else if (newChild->isTableSection())
+        return !isTable();
+    else if (newChild->isTableRow())
+        return !isTableSection();
+    else if (newChild->isTableCell())
+        return !isTableRow();
+    return false;
+}
+
+void RenderObject::addChild(RenderObject* newChild, RenderObject* beforeChild)
+{
+    RenderObjectChildList* children = virtualChildren();
+    ASSERT(children);
+    if (!children)
+        return;
+
+    if (requiresAnonymousTableWrappers(newChild)) {
+        // Generate an anonymous table or reuse existing one from previous child
+        // Per: 17.2.1 Anonymous table objects 3. Generate missing parents
+        // http://www.w3.org/TR/CSS21/tables.html#anonymous-boxes
+        RenderTable* table;
+        RenderObject* afterChild = beforeChild ? beforeChild->previousSibling() : children->lastChild();
+        if (afterChild && afterChild->isAnonymous() && afterChild->isTable() && !afterChild->isBeforeContent())
+            table = toRenderTable(afterChild);
+        else {
+            table = RenderTable::createAnonymousWithParentRenderer(this);
+            addChild(table, beforeChild);
+        }
+        table->addChild(newChild);
+    } else
+        children->insertChildNode(this, newChild, beforeChild);
+
+    if (newChild->isText() && newChild->style()->textTransform() == CAPITALIZE)
+        toRenderText(newChild)->transformText();
+
+    // SVG creates renderers for <g display="none">, as SVG requires children of hidden
+    // <g>s to have renderers - at least that's how our implementation works. Consider:
+    // <g display="none"><foreignObject><body style="position: relative">FOO...
+    // - requiresLayer() would return true for the <body>, creating a new RenderLayer
+    // - when the document is painted, both layers are painted. The <body> layer doesn't
+    //   know that it's inside a "hidden SVG subtree", and thus paints, even if it shouldn't.
+    // To avoid the problem alltogether, detect early if we're inside a hidden SVG subtree
+    // and stop creating layers at all for these cases - they're not used anyways.
+    if (newChild->hasLayer() && !layerCreationAllowedForSubtree())
+        toRenderLayerModelObject(newChild)->layer()->removeOnlyThisLayer();
+
+#if ENABLE(SVG)
+    SVGRenderSupport::childAdded(this, newChild);
+#endif
+}
+
+void RenderObject::removeChild(RenderObject* oldChild)
+{
+    RenderObjectChildList* children = virtualChildren();
+    ASSERT(children);
+    if (!children)
+        return;
+
+    children->removeChildNode(this, oldChild);
+}
+
+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(const RenderObject* stayWithin) const
+{
+    if (RenderObject* o = firstChild())
+        return o;
+
+    return nextInPreOrderAfterChildren(stayWithin);
+}
+
+RenderObject* RenderObject::nextInPreOrderAfterChildren(const RenderObject* stayWithin) const
+{
+    if (this == stayWithin)
+        return 0;
+
+    const RenderObject* current = this;
+    RenderObject* next;
+    while (!(next = current->nextSibling())) {
+        current = current->parent();
+        if (!current || current == stayWithin)
+            return 0;
+    }
+    return next;
+}
+
+RenderObject* RenderObject::previousInPreOrder() const
+{
+    if (RenderObject* o = previousSibling()) {
+        while (o->lastChild())
+            o = o->lastChild();
+        return o;
+    }
+
+    return parent();
+}
+
+RenderObject* RenderObject::previousInPreOrder(const RenderObject* stayWithin) const
+{
+    if (this == stayWithin)
+        return 0;
+
+    return previousInPreOrder();
+}
+
+RenderObject* RenderObject::childAt(unsigned index) const
+{
+    RenderObject* child = firstChild();
+    for (unsigned i = 0; child && i < index; i++)
+        child = child->nextSibling();
+    return child;
+}
+
+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(toRenderLayerModelObject(obj)->layer(), beforeChild);
+        return;
+    }
+
+    for (RenderObject* curr = obj->firstChild(); curr; curr = curr->nextSibling())
+        addLayers(curr, parentLayer, newObject, beforeChild);
+}
+
+void RenderObject::addLayers(RenderLayer* parentLayer)
+{
+    if (!parentLayer)
+        return;
+
+    RenderObject* object = this;
+    RenderLayer* beforeChild = 0;
+    WebCore::addLayers(this, parentLayer, object, beforeChild);
+}
+
+void RenderObject::removeLayers(RenderLayer* parentLayer)
+{
+    if (!parentLayer)
+        return;
+
+    if (hasLayer()) {
+        parentLayer->removeChild(toRenderLayerModelObject(this)->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()) {
+        RenderLayer* layer = toRenderLayerModelObject(this)->layer();
+        ASSERT(oldParent == layer->parent());
+        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 = hasLayer() ? toRenderLayerModelObject(this)->layer() : 0;
+    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->hasLayer() ? toRenderLayerModelObject(curr)->layer() : 0;
+        if (layer)
+            return layer;
+        curr = curr->parent();
+    }
+    return 0;
+}
+
+bool RenderObject::scrollRectToVisible(const LayoutRect& rect, const ScrollAlignment& alignX, const ScrollAlignment& alignY)
+{
+    RenderLayer* enclosingLayer = this->enclosingLayer();
+    if (!enclosingLayer)
+        return false;
+
+    enclosingLayer->scrollRectToVisible(rect, alignX, alignY);
+    return true;
+}
+
+RenderBox* RenderObject::enclosingBox() const
+{
+    RenderObject* curr = const_cast<RenderObject*>(this);
+    while (curr) {
+        if (curr->isBox())
+            return toRenderBox(curr);
+        curr = curr->parent();
+    }
+    
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
+RenderBoxModelObject* RenderObject::enclosingBoxModelObject() const
+{
+    RenderObject* curr = const_cast<RenderObject*>(this);
+    while (curr) {
+        if (curr->isBoxModelObject())
+            return toRenderBoxModelObject(curr);
+        curr = curr->parent();
+    }
+
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
+RenderFlowThread* RenderObject::locateFlowThreadContainingBlock() const
+{
+    ASSERT(flowThreadState() != NotInsideFlowThread);
+
+    // See if we have the thread cached because we're in the middle of layout.
+    RenderFlowThread* flowThread = view()->flowThreadController()->currentRenderFlowThread();
+    if (flowThread)
+        return flowThread;
+    
+    // Not in the middle of layout so have to find the thread the slow way.
+    RenderObject* curr = const_cast<RenderObject*>(this);
+    while (curr) {
+        if (curr->isRenderFlowThread())
+            return toRenderFlowThread(curr);
+        curr = curr->containingBlock();
+    }
+    return 0;
+}
+
+RenderNamedFlowThread* RenderObject::renderNamedFlowThreadWrapper() const
+{
+    RenderObject* object = const_cast<RenderObject*>(this);
+    while (object && object->isAnonymousBlock() && !object->isRenderNamedFlowThread())
+        object = object->parent();
+
+    return object && object->isRenderNamedFlowThread() ? toRenderNamedFlowThread(object) : 0;
+}
+
+RenderBlock* RenderObject::firstLineBlock() const
+{
+    return 0;
+}
+
+static inline bool objectIsRelayoutBoundary(const RenderObject* object)
+{
+    // FIXME: In future it may be possible to broaden these conditions in order to improve performance.
+    if (object->isTextControl())
+        return true;
+
+#if ENABLE(SVG)
+    if (object->isSVGRoot())
+        return true;
+#endif
+
+    if (!object->hasOverflowClip())
+        return false;
+
+    if (object->style()->width().isIntrinsicOrAuto() || object->style()->height().isIntrinsicOrAuto() || object->style()->height().isPercent())
+        return false;
+
+    // Table parts can't be relayout roots since the table is responsible for layouting all the parts.
+    if (object->isTablePart())
+        return false;
+
+    return true;
+}
+
+void RenderObject::markContainingBlocksForLayout(bool scheduleRelayout, RenderObject* newRoot)
+{
+    ASSERT(!scheduleRelayout || !newRoot);
+    ASSERT(!isSetNeedsLayoutForbidden());
+
+    RenderObject* object = container();
+    RenderObject* last = this;
+
+    bool simplifiedNormalFlowLayout = needsSimplifiedNormalFlowLayout() && !selfNeedsLayout() && !normalChildNeedsLayout();
+
+    while (object) {
+#ifndef NDEBUG
+        // FIXME: Remove this once we remove the special cases for counters, quotes and mathml
+        // calling setNeedsLayout during preferred width computation.
+        SetLayoutNeededForbiddenScope layoutForbiddenScope(object, isSetNeedsLayoutForbidden());
+#endif
+        // Don't mark the outermost object of an unrooted subtree. That object will be
+        // marked when the subtree is added to the document.
+        RenderObject* container = object->container();
+        if (!container && !object->isRenderView())
+            return;
+        if (!last->isText() && last->style()->hasOutOfFlowPosition()) {
+            bool willSkipRelativelyPositionedInlines = !object->isRenderBlock() || object->isAnonymousBlock();
+            // Skip relatively positioned inlines and anonymous blocks to get to the enclosing RenderBlock.
+            while (object && (!object->isRenderBlock() || object->isAnonymousBlock()))
+                object = object->container();
+            if (!object || object->posChildNeedsLayout())
+                return;
+            if (willSkipRelativelyPositionedInlines)
+                container = object->container();
+            object->setPosChildNeedsLayout(true);
+            simplifiedNormalFlowLayout = true;
+            ASSERT(!object->isSetNeedsLayoutForbidden());
+        } else if (simplifiedNormalFlowLayout) {
+            if (object->needsSimplifiedNormalFlowLayout())
+                return;
+            object->setNeedsSimplifiedNormalFlowLayout(true);
+            ASSERT(!object->isSetNeedsLayoutForbidden());
+        } else {
+            if (object->normalChildNeedsLayout())
+                return;
+            object->setNormalChildNeedsLayout(true);
+            ASSERT(!object->isSetNeedsLayoutForbidden());
+        }
+
+        if (object == newRoot)
+            return;
+
+        last = object;
+        if (scheduleRelayout && objectIsRelayoutBoundary(last))
+            break;
+        object = container;
+    }
+
+    if (scheduleRelayout)
+        last->scheduleRelayout();
+}
+
+#ifndef NDEBUG
+void RenderObject::checkBlockPositionedObjectsNeedLayout()
+{
+    ASSERT(!needsLayout());
+
+    if (isRenderBlock())
+        toRenderBlock(this)->checkPositionedObjectsNeedLayout();
+}
+#endif
+
+void RenderObject::setPreferredLogicalWidthsDirty(bool shouldBeDirty, MarkingBehavior markParents)
+{
+    bool alreadyDirty = preferredLogicalWidthsDirty();
+    m_bitfields.setPreferredLogicalWidthsDirty(shouldBeDirty);
+    if (shouldBeDirty && !alreadyDirty && markParents == MarkContainingBlockChain && (isText() || !style()->hasOutOfFlowPosition()))
+        invalidateContainerPreferredLogicalWidths();
+}
+
+void RenderObject::invalidateContainerPreferredLogicalWidths()
+{
+    // 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->preferredLogicalWidthsDirty()) {
+        // Don't invalidate the outermost object of an unrooted subtree. That object will be 
+        // invalidated when the subtree is added to the document.
+        RenderObject* container = o->isTableCell() ? o->containingBlock() : o->container();
+        if (!container && !o->isRenderView())
+            break;
+
+        o->m_bitfields.setPreferredLogicalWidthsDirty(true);
+        if (o->style()->hasOutOfFlowPosition())
+            // 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 = container;
+    }
+}
+
+void RenderObject::setLayerNeedsFullRepaint()
+{
+    ASSERT(hasLayer());
+    toRenderLayerModelObject(this)->layer()->setRepaintStatus(NeedsFullRepaint);
+}
+
+void RenderObject::setLayerNeedsFullRepaintForPositionedMovementLayout()
+{
+    ASSERT(hasLayer());
+    toRenderLayerModelObject(this)->layer()->setRepaintStatus(NeedsFullRepaintForPositionedMovementLayout);
+}
+
+RenderBlock* RenderObject::containingBlock() const
+{
+    RenderObject* o = parent();
+    if (!o && isRenderScrollbarPart())
+        o = toRenderScrollbarPart(this)->rendererOwningScrollbar();
+    if (!isText() && m_style->position() == FixedPosition) {
+        while (o) {
+            if (o->canContainFixedPositionObjects())
+                break;
+            o = o->parent();
+        }
+        ASSERT(!o || !o->isAnonymousBlock());
+    } else if (!isText() && m_style->position() == AbsolutePosition) {
+        while (o) {
+            // For relpositioned inlines, we return the nearest non-anonymous 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() != StaticPosition && (!o->isInline() || o->isReplaced()))
+                break;
+            if (o->isRenderView())
+                break;
+            if (o->hasTransform() && o->isRenderBlock())
+                break;
+
+            if (o->style()->hasInFlowPosition() && o->isInline() && !o->isReplaced()) {
+                o = o->containingBlock();
+                break;
+            }
+#if ENABLE(SVG)
+            if (o->isSVGForeignObject()) //foreignObject is the containing block for contents inside it
+                break;
+#endif
+
+            o = o->parent();
+        }
+
+        while (o && o->isAnonymousBlock())
+            o = o->containingBlock();
+    } else {
+        while (o && ((o->isInline() && !o->isReplaced()) || !o->isRenderBlock()))
+            o = o->parent();
+    }
+
+    if (!o || !o->isRenderBlock())
+        return 0; // This can still happen in case of an orphaned tree
+
+    return toRenderBlock(o);
+}
+
+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();
+    if (!img || !img->canRender(renderer, renderer->style()->effectiveZoom()))
+        return false;
+
+    if (!layer->xPosition().isZero() || !layer->yPosition().isZero())
+        return true;
+
+    EFillSizeType sizeType = layer->sizeType();
+
+    if (sizeType == Contain || sizeType == Cover)
+        return true;
+    
+    if (sizeType == SizeLength) {
+        if (layer->sizeLength().width().isPercent() || layer->sizeLength().height().isPercent())
+            return true;
+    } else if (img->usesImageContainerSize())
+        return true;
+
+    return false;
+}
+
+bool RenderObject::borderImageIsLoadedAndCanBeRendered() const
+{
+    ASSERT(style()->hasBorder());
+
+    StyleImage* borderImage = style()->borderImage().image();
+    return borderImage && borderImage->canRender(this, style()->effectiveZoom()) && borderImage->isLoaded();
+}
+
+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() && borderImageIsLoadedAndCanBeRendered())
+        return true;
+
+    return false;
+}
+
+void RenderObject::drawLineForBoxSide(GraphicsContext* graphicsContext, int x1, int y1, int x2, int y2,
+                                      BoxSide side, Color color, EBorderStyle style,
+                                      int adjacentWidth1, int adjacentWidth2, bool antialias)
+{
+    int thickness;
+    int length;
+    if (side == BSTop || side == BSBottom) {
+        thickness = y2 - y1;
+        length = x2 - x1;
+    } else {
+        thickness = x2 - x1;
+        length = y2 - y1;
+    }
+
+    // FIXME: We really would like this check to be an ASSERT as we don't want to draw empty borders. However
+    // nothing guarantees that the following recursive calls to drawLineForBoxSide will have non-null dimensions.
+    if (!thickness || !length)
+        return;
+
+    if (style == DOUBLE && thickness < 3)
+        style = SOLID;
+
+    switch (style) {
+        case BNONE:
+        case BHIDDEN:
+            return;
+        case DOTTED:
+        case DASHED: {
+            if (thickness > 0) {
+                bool wasAntialiased = graphicsContext->shouldAntialias();
+                StrokeStyle oldStrokeStyle = graphicsContext->strokeStyle();
+                graphicsContext->setShouldAntialias(antialias);
+                graphicsContext->setStrokeColor(color, m_style->colorSpace());
+                graphicsContext->setStrokeThickness(thickness);
+                graphicsContext->setStrokeStyle(style == DASHED ? DashedStroke : DottedStroke);
+
+                switch (side) {
+                    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;
+                }
+                graphicsContext->setShouldAntialias(wasAntialiased);
+                graphicsContext->setStrokeStyle(oldStrokeStyle);
+            }
+            break;
+        }
+        case DOUBLE: {
+            int thirdOfThickness = (thickness + 1) / 3;
+            ASSERT(thirdOfThickness);
+
+            if (adjacentWidth1 == 0 && adjacentWidth2 == 0) {
+                StrokeStyle oldStrokeStyle = graphicsContext->strokeStyle();
+                graphicsContext->setStrokeStyle(NoStroke);
+                graphicsContext->setFillColor(color, m_style->colorSpace());
+                
+                bool wasAntialiased = graphicsContext->shouldAntialias();
+                graphicsContext->setShouldAntialias(antialias);
+
+                switch (side) {
+                    case BSTop:
+                    case BSBottom:
+                        graphicsContext->drawRect(IntRect(x1, y1, length, thirdOfThickness));
+                        graphicsContext->drawRect(IntRect(x1, y2 - thirdOfThickness, length, thirdOfThickness));
+                        break;
+                    case BSLeft:
+                    case BSRight:
+                        // FIXME: Why do we offset the border by 1 in this case but not the other one?
+                        if (length > 1) {
+                            graphicsContext->drawRect(IntRect(x1, y1 + 1, thirdOfThickness, length - 1));
+                            graphicsContext->drawRect(IntRect(x2 - thirdOfThickness, y1 + 1, thirdOfThickness, length - 1));
+                        }
+                        break;
+                }
+
+                graphicsContext->setShouldAntialias(wasAntialiased);
+                graphicsContext->setStrokeStyle(oldStrokeStyle);
+            } else {
+                int adjacent1BigThird = ((adjacentWidth1 > 0) ? adjacentWidth1 + 1 : adjacentWidth1 - 1) / 3;
+                int adjacent2BigThird = ((adjacentWidth2 > 0) ? adjacentWidth2 + 1 : adjacentWidth2 - 1) / 3;
+
+                switch (side) {
+                    case BSTop:
+                        drawLineForBoxSide(graphicsContext, x1 + max((-adjacentWidth1 * 2 + 1) / 3, 0),
+                                   y1, x2 - max((-adjacentWidth2 * 2 + 1) / 3, 0), y1 + thirdOfThickness,
+                                   side, color, SOLID, adjacent1BigThird, adjacent2BigThird, antialias);
+                        drawLineForBoxSide(graphicsContext, x1 + max((adjacentWidth1 * 2 + 1) / 3, 0),
+                                   y2 - thirdOfThickness, x2 - max((adjacentWidth2 * 2 + 1) / 3, 0), y2,
+                                   side, color, SOLID, adjacent1BigThird, adjacent2BigThird, antialias);
+                        break;
+                    case BSLeft:
+                        drawLineForBoxSide(graphicsContext, x1, y1 + max((-adjacentWidth1 * 2 + 1) / 3, 0),
+                                   x1 + thirdOfThickness, y2 - max((-adjacentWidth2 * 2 + 1) / 3, 0),
+                                   side, color, SOLID, adjacent1BigThird, adjacent2BigThird, antialias);
+                        drawLineForBoxSide(graphicsContext, x2 - thirdOfThickness, y1 + max((adjacentWidth1 * 2 + 1) / 3, 0),
+                                   x2, y2 - max((adjacentWidth2 * 2 + 1) / 3, 0),
+                                   side, color, SOLID, adjacent1BigThird, adjacent2BigThird, antialias);
+                        break;
+                    case BSBottom:
+                        drawLineForBoxSide(graphicsContext, x1 + max((adjacentWidth1 * 2 + 1) / 3, 0),
+                                   y1, x2 - max((adjacentWidth2 * 2 + 1) / 3, 0), y1 + thirdOfThickness,
+                                   side, color, SOLID, adjacent1BigThird, adjacent2BigThird, antialias);
+                        drawLineForBoxSide(graphicsContext, x1 + max((-adjacentWidth1 * 2 + 1) / 3, 0),
+                                   y2 - thirdOfThickness, x2 - max((-adjacentWidth2 * 2 + 1) / 3, 0), y2,
+                                   side, color, SOLID, adjacent1BigThird, adjacent2BigThird, antialias);
+                        break;
+                    case BSRight:
+                        drawLineForBoxSide(graphicsContext, x1, y1 + max((adjacentWidth1 * 2 + 1) / 3, 0),
+                                   x1 + thirdOfThickness, y2 - max((adjacentWidth2 * 2 + 1) / 3, 0),
+                                   side, color, SOLID, adjacent1BigThird, adjacent2BigThird, antialias);
+                        drawLineForBoxSide(graphicsContext, x2 - thirdOfThickness, y1 + max((-adjacentWidth1 * 2 + 1) / 3, 0),
+                                   x2, y2 - max((-adjacentWidth2 * 2 + 1) / 3, 0),
+                                   side, color, SOLID, adjacent1BigThird, adjacent2BigThird, antialias);
+                        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 adjacent1BigHalf = ((adjacentWidth1 > 0) ? adjacentWidth1 + 1 : adjacentWidth1 - 1) / 2;
+            int adjacent2BigHalf = ((adjacentWidth2 > 0) ? adjacentWidth2 + 1 : adjacentWidth2 - 1) / 2;
+
+            switch (side) {
+                case BSTop:
+                    drawLineForBoxSide(graphicsContext, x1 + max(-adjacentWidth1, 0) / 2, y1, x2 - max(-adjacentWidth2, 0) / 2, (y1 + y2 + 1) / 2,
+                               side, color, s1, adjacent1BigHalf, adjacent2BigHalf, antialias);
+                    drawLineForBoxSide(graphicsContext, x1 + max(adjacentWidth1 + 1, 0) / 2, (y1 + y2 + 1) / 2, x2 - max(adjacentWidth2 + 1, 0) / 2, y2,
+                               side, color, s2, adjacentWidth1 / 2, adjacentWidth2 / 2, antialias);
+                    break;
+                case BSLeft:
+                    drawLineForBoxSide(graphicsContext, x1, y1 + max(-adjacentWidth1, 0) / 2, (x1 + x2 + 1) / 2, y2 - max(-adjacentWidth2, 0) / 2,
+                               side, color, s1, adjacent1BigHalf, adjacent2BigHalf, antialias);
+                    drawLineForBoxSide(graphicsContext, (x1 + x2 + 1) / 2, y1 + max(adjacentWidth1 + 1, 0) / 2, x2, y2 - max(adjacentWidth2 + 1, 0) / 2,
+                               side, color, s2, adjacentWidth1 / 2, adjacentWidth2 / 2, antialias);
+                    break;
+                case BSBottom:
+                    drawLineForBoxSide(graphicsContext, x1 + max(adjacentWidth1, 0) / 2, y1, x2 - max(adjacentWidth2, 0) / 2, (y1 + y2 + 1) / 2,
+                               side, color, s2, adjacent1BigHalf, adjacent2BigHalf, antialias);
+                    drawLineForBoxSide(graphicsContext, x1 + max(-adjacentWidth1 + 1, 0) / 2, (y1 + y2 + 1) / 2, x2 - max(-adjacentWidth2 + 1, 0) / 2, y2,
+                               side, color, s1, adjacentWidth1 / 2, adjacentWidth2 / 2, antialias);
+                    break;
+                case BSRight:
+                    drawLineForBoxSide(graphicsContext, x1, y1 + max(adjacentWidth1, 0) / 2, (x1 + x2 + 1) / 2, y2 - max(adjacentWidth2, 0) / 2,
+                               side, color, s2, adjacent1BigHalf, adjacent2BigHalf, antialias);
+                    drawLineForBoxSide(graphicsContext, (x1 + x2 + 1) / 2, y1 + max(-adjacentWidth1 + 1, 0) / 2, x2, y2 - max(-adjacentWidth2 + 1, 0) / 2,
+                               side, color, s1, adjacentWidth1 / 2, adjacentWidth2 / 2, antialias);
+                    break;
+            }
+            break;
+        }
+        case INSET:
+            // FIXME: Maybe we should lighten the colors on one side like Firefox.
+            // https://bugs.webkit.org/show_bug.cgi?id=58608
+            if (side == BSTop || side == BSLeft)
+                color = color.dark();
+            // fall through
+        case OUTSET:
+            if (style == OUTSET && (side == BSBottom || side == BSRight))
+                color = color.dark();
+            // fall through
+        case SOLID: {
+            StrokeStyle oldStrokeStyle = graphicsContext->strokeStyle();
+            graphicsContext->setStrokeStyle(NoStroke);
+            graphicsContext->setFillColor(color, m_style->colorSpace());
+            ASSERT(x2 >= x1);
+            ASSERT(y2 >= y1);
+            if (!adjacentWidth1 && !adjacentWidth2) {
+                // Turn off antialiasing to match the behavior of drawConvexPolygon();
+                // this matters for rects in transformed contexts.
+                bool wasAntialiased = graphicsContext->shouldAntialias();
+                graphicsContext->setShouldAntialias(antialias);
+                graphicsContext->drawRect(IntRect(x1, y1, x2 - x1, y2 - y1));
+                graphicsContext->setShouldAntialias(wasAntialiased);
+                graphicsContext->setStrokeStyle(oldStrokeStyle);
+                return;
+            }
+            FloatPoint quad[4];
+            switch (side) {
+                case BSTop:
+                    quad[0] = FloatPoint(x1 + max(-adjacentWidth1, 0), y1);
+                    quad[1] = FloatPoint(x1 + max(adjacentWidth1, 0), y2);
+                    quad[2] = FloatPoint(x2 - max(adjacentWidth2, 0), y2);
+                    quad[3] = FloatPoint(x2 - max(-adjacentWidth2, 0), y1);
+                    break;
+                case BSBottom:
+                    quad[0] = FloatPoint(x1 + max(adjacentWidth1, 0), y1);
+                    quad[1] = FloatPoint(x1 + max(-adjacentWidth1, 0), y2);
+                    quad[2] = FloatPoint(x2 - max(-adjacentWidth2, 0), y2);
+                    quad[3] = FloatPoint(x2 - max(adjacentWidth2, 0), y1);
+                    break;
+                case BSLeft:
+                    quad[0] = FloatPoint(x1, y1 + max(-adjacentWidth1, 0));
+                    quad[1] = FloatPoint(x1, y2 - max(-adjacentWidth2, 0));
+                    quad[2] = FloatPoint(x2, y2 - max(adjacentWidth2, 0));
+                    quad[3] = FloatPoint(x2, y1 + max(adjacentWidth1, 0));
+                    break;
+                case BSRight:
+                    quad[0] = FloatPoint(x1, y1 + max(adjacentWidth1, 0));
+                    quad[1] = FloatPoint(x1, y2 - max(adjacentWidth2, 0));
+                    quad[2] = FloatPoint(x2, y2 - max(-adjacentWidth2, 0));
+                    quad[3] = FloatPoint(x2, y1 + max(-adjacentWidth1, 0));
+                    break;
+            }
+
+            graphicsContext->drawConvexPolygon(4, quad, antialias);
+            graphicsContext->setStrokeStyle(oldStrokeStyle);
+            break;
+        }
+    }
+}
+
+void RenderObject::paintFocusRing(PaintInfo& paintInfo, const LayoutPoint& paintOffset, RenderStyle* style)
+{
+    Vector<IntRect> focusRingRects;
+    addFocusRingRects(focusRingRects, paintOffset, paintInfo.paintContainer);
+    if (style->outlineStyleIsAuto())
+        paintInfo.context->drawFocusRing(focusRingRects, style->outlineWidth(), style->outlineOffset(), style->visitedDependentColor(CSSPropertyOutlineColor));
+    else
+        addPDFURLRect(paintInfo.context, unionRect(focusRingRects));
+}
+
+void RenderObject::addPDFURLRect(GraphicsContext* context, const LayoutRect& rect)
+{
+    if (rect.isEmpty())
+        return;
+    Node* n = node();
+    if (!n || !n->isLink() || !n->isElementNode())
+        return;
+    const AtomicString& href = toElement(n)->getAttribute(hrefAttr);
+    if (href.isNull())
+        return;
+    context->setURLForRect(n->document()->completeURL(href), pixelSnappedIntRect(rect));
+}
+
+void RenderObject::paintOutline(PaintInfo& paintInfo, const LayoutRect& paintRect)
+{
+    if (!hasOutline())
+        return;
+
+    RenderStyle* styleToUse = style();
+    LayoutUnit outlineWidth = styleToUse->outlineWidth();
+
+    int outlineOffset = styleToUse->outlineOffset();
+
+    if (styleToUse->outlineStyleIsAuto() || hasOutlineAnnotation()) {
+        if (!theme()->supportsFocusRing(styleToUse)) {
+            // Only paint the focus ring by hand if the theme isn't able to draw the focus ring.
+            paintFocusRing(paintInfo, paintRect.location(), styleToUse);
+        }
+    }
+
+    if (styleToUse->outlineStyleIsAuto() || styleToUse->outlineStyle() == BNONE)
+        return;
+
+    IntRect inner = pixelSnappedIntRect(paintRect);
+    inner.inflate(outlineOffset);
+
+    IntRect outer = pixelSnappedIntRect(inner);
+    outer.inflate(outlineWidth);
+
+    // FIXME: This prevents outlines from painting inside the object. See bug 12042
+    if (outer.isEmpty())
+        return;
+
+    EBorderStyle outlineStyle = styleToUse->outlineStyle();
+    Color outlineColor = styleToUse->visitedDependentColor(CSSPropertyOutlineColor);
+
+    GraphicsContext* graphicsContext = paintInfo.context;
+    bool useTransparencyLayer = outlineColor.hasAlpha();
+    if (useTransparencyLayer) {
+        if (outlineStyle == SOLID) {
+            Path path;
+            path.addRect(outer);
+            path.addRect(inner);
+            graphicsContext->setFillRule(RULE_EVENODD);
+            graphicsContext->setFillColor(outlineColor, styleToUse->colorSpace());
+            graphicsContext->fillPath(path);
+            return;
+        }
+        graphicsContext->beginTransparencyLayer(static_cast<float>(outlineColor.alpha()) / 255);
+        outlineColor = Color(outlineColor.red(), outlineColor.green(), outlineColor.blue());
+    }
+
+    int leftOuter = outer.x();
+    int leftInner = inner.x();
+    int rightOuter = outer.maxX();
+    int rightInner = inner.maxX();
+    int topOuter = outer.y();
+    int topInner = inner.y();
+    int bottomOuter = outer.maxY();
+    int bottomInner = inner.maxY();
+    
+    drawLineForBoxSide(graphicsContext, leftOuter, topOuter, leftInner, bottomOuter, BSLeft, outlineColor, outlineStyle, outlineWidth, outlineWidth);
+    drawLineForBoxSide(graphicsContext, leftOuter, topOuter, rightOuter, topInner, BSTop, outlineColor, outlineStyle, outlineWidth, outlineWidth);
+    drawLineForBoxSide(graphicsContext, rightInner, topOuter, rightOuter, bottomOuter, BSRight, outlineColor, outlineStyle, outlineWidth, outlineWidth);
+    drawLineForBoxSide(graphicsContext, leftOuter, bottomInner, rightOuter, bottomOuter, BSBottom, outlineColor, outlineStyle, outlineWidth, outlineWidth);
+
+    if (useTransparencyLayer)
+        graphicsContext->endTransparencyLayer();
+}
+
+IntRect RenderObject::absoluteBoundingBoxRect(bool useTransforms) const
+{
+    if (useTransforms) {
+        Vector<FloatQuad> quads;
+        absoluteQuads(quads);
+
+        size_t n = quads.size();
+        if (!n)
+            return IntRect();
+    
+        IntRect result = quads[0].enclosingBoundingBox();
+        for (size_t i = 1; i < n; ++i)
+            result.unite(quads[i].enclosingBoundingBox());
+        return result;
+    }
+
+    FloatPoint absPos = localToAbsolute();
+    Vector<IntRect> rects;
+    absoluteRects(rects, flooredLayoutPoint(absPos));
+
+    size_t n = rects.size();
+    if (!n)
+        return IntRect();
+
+    LayoutRect result = rects[0];
+    for (size_t i = 1; i < n; ++i)
+        result.unite(rects[i]);
+    return pixelSnappedIntRect(result);
+}
+
+void RenderObject::absoluteFocusRingQuads(Vector<FloatQuad>& quads)
+{
+    Vector<IntRect> rects;
+    // FIXME: addFocusRingRects() needs to be passed this transform-unaware
+    // localToAbsolute() offset here because RenderInline::addFocusRingRects()
+    // implicitly assumes that. This doesn't work correctly with transformed
+    // descendants.
+    FloatPoint absolutePoint = localToAbsolute();
+    addFocusRingRects(rects, flooredLayoutPoint(absolutePoint));
+    size_t count = rects.size();
+    for (size_t i = 0; i < count; ++i) {
+        IntRect rect = rects[i];
+        rect.move(-absolutePoint.x(), -absolutePoint.y());
+        quads.append(localToAbsoluteQuad(FloatQuad(rect)));
+    }
+}
+
+FloatRect RenderObject::absoluteBoundingBoxRectForRange(const Range* range)
+{
+    if (!range || !range->startContainer())
+        return FloatRect();
+
+    if (range->ownerDocument())
+        range->ownerDocument()->updateLayout();
+
+    Vector<FloatQuad> quads;
+    range->textQuads(quads);
+
+    FloatRect result;
+    for (size_t i = 0; i < quads.size(); ++i)
+        result.unite(quads[i].boundingBox());
+
+    return result;
+}
+
+void RenderObject::addAbsoluteRectForLayer(LayoutRect& result)
+{
+    if (hasLayer())
+        result.unite(absoluteBoundingBoxRectIgnoringTransforms());
+    for (RenderObject* current = firstChild(); current; current = current->nextSibling())
+        current->addAbsoluteRectForLayer(result);
+}
+
+LayoutRect RenderObject::paintingRootRect(LayoutRect& topLevelRect)
+{
+    LayoutRect result = absoluteBoundingBoxRectIgnoringTransforms();
+    topLevelRect = result;
+    for (RenderObject* current = firstChild(); current; current = current->nextSibling())
+        current->addAbsoluteRectForLayer(result);
+    return result;
+}
+
+void RenderObject::paint(PaintInfo&, const LayoutPoint&)
+{
+}
+
+RenderLayerModelObject* RenderObject::containerForRepaint() const
+{
+    RenderView* v = view();
+    if (!v)
+        return 0;
+    
+    RenderLayerModelObject* repaintContainer = 0;
+
+    if (v->usesCompositing()) {
+        if (RenderLayer* parentLayer = enclosingLayer()) {
+            RenderLayer* compLayer = parentLayer->enclosingCompositingLayerForRepaint();
+            if (compLayer)
+                repaintContainer = compLayer->renderer();
+        }
+    }
+
+    if (document()->view()->hasSoftwareFilters()) {
+        if (RenderLayer* parentLayer = enclosingLayer()) {
+            RenderLayer* enclosingFilterLayer = parentLayer->enclosingFilterLayer();
+            if (enclosingFilterLayer)
+                return enclosingFilterLayer->renderer();
+        }
+    }
+
+    // If we have a flow thread, then we need to do individual repaints within the RenderRegions instead.
+    // Return the flow thread as a repaint container in order to create a chokepoint that allows us to change
+    // repainting to do individual region repaints.
+    RenderFlowThread* parentRenderFlowThread = flowThreadContainingBlock();
+    if (parentRenderFlowThread) {
+        // The ancestor document will do the reparenting when the repaint propagates further up.
+        // We're just a seamless child document, and we don't need to do the hacking.
+        if (parentRenderFlowThread && parentRenderFlowThread->document() != document())
+            return repaintContainer;
+        // If we have already found a repaint container then we will repaint into that container only if it is part of the same
+        // flow thread. Otherwise we will need to catch the repaint call and send it to the flow thread.
+        RenderFlowThread* repaintContainerFlowThread = repaintContainer ? repaintContainer->flowThreadContainingBlock() : 0;
+        if (!repaintContainerFlowThread || repaintContainerFlowThread != parentRenderFlowThread)
+            repaintContainer = parentRenderFlowThread;
+    }
+    return repaintContainer;
+}
+
+void RenderObject::repaintUsingContainer(const RenderLayerModelObject* repaintContainer, const IntRect& r) const
+{
+    if (!repaintContainer) {
+        view()->repaintViewRectangle(r);
+        return;
+    }
+
+    if (repaintContainer->isRenderFlowThread()) {
+        toRenderFlowThread(repaintContainer)->repaintRectangleInRegions(r);
+        return;
+    }
+
+    if (repaintContainer->hasFilter() && repaintContainer->layer() && repaintContainer->layer()->requiresFullLayerImageForFilters()) {
+        repaintContainer->layer()->setFilterBackendNeedsRepaintingInRect(r);
+        return;
+    }
+
+    RenderView* v = view();
+    if (repaintContainer->isRenderView()) {
+        ASSERT(repaintContainer == v);
+        bool viewHasCompositedLayer = v->hasLayer() && v->layer()->isComposited();
+        if (!viewHasCompositedLayer || v->layer()->backing()->paintsIntoWindow()) {
+            LayoutRect repaintRectangle = r;
+            if (viewHasCompositedLayer &&  v->layer()->transform())
+                repaintRectangle = enclosingIntRect(v->layer()->transform()->mapRect(r));
+            v->repaintViewRectangle(repaintRectangle);
+            return;
+        }
+    }
+    
+    if (v->usesCompositing()) {
+        ASSERT(repaintContainer->hasLayer() && repaintContainer->layer()->isComposited());
+        repaintContainer->layer()->setBackingNeedsRepaintInRect(r);
+    }
+}
+
+void RenderObject::repaint() const
+{
+    // Don't repaint if we're unrooted (note that view() still returns the view when unrooted)
+    RenderView* view;
+    if (!isRooted(&view))
+        return;
+
+    if (view->printing())
+        return; // Don't repaint if we're printing.
+
+    RenderLayerModelObject* repaintContainer = containerForRepaint();
+    repaintUsingContainer(repaintContainer ? repaintContainer : view, pixelSnappedIntRect(clippedOverflowRectForRepaint(repaintContainer)));
+}
+
+void RenderObject::repaintRectangle(const LayoutRect& r) const
+{
+    // Don't repaint if we're unrooted (note that view() still returns the view when unrooted)
+    RenderView* view;
+    if (!isRooted(&view))
+        return;
+
+    if (view->printing())
+        return; // Don't repaint if we're printing.
+
+    LayoutRect dirtyRect(r);
+
+    // FIXME: layoutDelta needs to be applied in parts before/after transforms and
+    // repaint containers. https://bugs.webkit.org/show_bug.cgi?id=23308
+    dirtyRect.move(view->layoutDelta());
+
+    RenderLayerModelObject* repaintContainer = containerForRepaint();
+    computeRectForRepaint(repaintContainer, dirtyRect);
+    repaintUsingContainer(repaintContainer ? repaintContainer : view, pixelSnappedIntRect(dirtyRect));
+}
+
+IntRect RenderObject::pixelSnappedAbsoluteClippedOverflowRect() const
+{
+    return pixelSnappedIntRect(absoluteClippedOverflowRect());
+}
+
+bool RenderObject::repaintAfterLayoutIfNeeded(const RenderLayerModelObject* repaintContainer, const LayoutRect& oldBounds, const LayoutRect& oldOutlineBox, const LayoutRect* newBoundsPtr, const LayoutRect* newOutlineBoxRectPtr)
+{
+    RenderView* v = view();
+    if (v->printing())
+        return false; // Don't repaint if we're printing.
+
+    // This ASSERT fails due to animations.  See https://bugs.webkit.org/show_bug.cgi?id=37048
+    // ASSERT(!newBoundsPtr || *newBoundsPtr == clippedOverflowRectForRepaint(repaintContainer));
+    LayoutRect newBounds = newBoundsPtr ? *newBoundsPtr : clippedOverflowRectForRepaint(repaintContainer);
+    LayoutRect 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) {
+        // This ASSERT fails due to animations.  See https://bugs.webkit.org/show_bug.cgi?id=37048
+        // ASSERT(!newOutlineBoxRectPtr || *newOutlineBoxRectPtr == outlineBoundsForRepaint(repaintContainer));
+        newOutlineBox = newOutlineBoxRectPtr ? *newOutlineBoxRectPtr : outlineBoundsForRepaint(repaintContainer);
+        if (newOutlineBox.location() != oldOutlineBox.location() || (mustRepaintBackgroundOrBorder() && (newBounds != oldBounds || newOutlineBox != oldOutlineBox)))
+            fullRepaint = true;
+    }
+
+    if (!repaintContainer)
+        repaintContainer = v;
+
+    if (fullRepaint) {
+        repaintUsingContainer(repaintContainer, pixelSnappedIntRect(oldBounds));
+        if (newBounds != oldBounds)
+            repaintUsingContainer(repaintContainer, pixelSnappedIntRect(newBounds));
+        return true;
+    }
+
+    if (newBounds == oldBounds && newOutlineBox == oldOutlineBox)
+        return false;
+
+    LayoutUnit deltaLeft = newBounds.x() - oldBounds.x();
+    if (deltaLeft > 0)
+        repaintUsingContainer(repaintContainer, pixelSnappedIntRect(oldBounds.x(), oldBounds.y(), deltaLeft, oldBounds.height()));
+    else if (deltaLeft < 0)
+        repaintUsingContainer(repaintContainer, pixelSnappedIntRect(newBounds.x(), newBounds.y(), -deltaLeft, newBounds.height()));
+
+    LayoutUnit deltaRight = newBounds.maxX() - oldBounds.maxX();
+    if (deltaRight > 0)
+        repaintUsingContainer(repaintContainer, pixelSnappedIntRect(oldBounds.maxX(), newBounds.y(), deltaRight, newBounds.height()));
+    else if (deltaRight < 0)
+        repaintUsingContainer(repaintContainer, pixelSnappedIntRect(newBounds.maxX(), oldBounds.y(), -deltaRight, oldBounds.height()));
+
+    LayoutUnit deltaTop = newBounds.y() - oldBounds.y();
+    if (deltaTop > 0)
+        repaintUsingContainer(repaintContainer, pixelSnappedIntRect(oldBounds.x(), oldBounds.y(), oldBounds.width(), deltaTop));
+    else if (deltaTop < 0)
+        repaintUsingContainer(repaintContainer, pixelSnappedIntRect(newBounds.x(), newBounds.y(), newBounds.width(), -deltaTop));
+
+    LayoutUnit deltaBottom = newBounds.maxY() - oldBounds.maxY();
+    if (deltaBottom > 0)
+        repaintUsingContainer(repaintContainer, pixelSnappedIntRect(newBounds.x(), oldBounds.maxY(), newBounds.width(), deltaBottom));
+    else if (deltaBottom < 0)
+        repaintUsingContainer(repaintContainer, pixelSnappedIntRect(oldBounds.x(), newBounds.maxY(), 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 = outlineStyleForRepaint();
+    LayoutUnit outlineWidth = outlineStyle->outlineSize();
+    LayoutBoxExtent insetShadowExtent = style()->getBoxShadowInsetExtent();
+    LayoutUnit width = absoluteValue(newOutlineBox.width() - oldOutlineBox.width());
+    if (width) {
+        LayoutUnit shadowLeft;
+        LayoutUnit shadowRight;
+        style()->getBoxShadowHorizontalExtent(shadowLeft, shadowRight);
+        int borderRight = isBox() ? toRenderBox(this)->borderRight() : 0;
+        LayoutUnit boxWidth = isBox() ? toRenderBox(this)->width() : LayoutUnit();
+        LayoutUnit minInsetRightShadowExtent = min<LayoutUnit>(-insetShadowExtent.right(), min<LayoutUnit>(newBounds.width(), oldBounds.width()));
+        LayoutUnit borderWidth = max<LayoutUnit>(borderRight, max<LayoutUnit>(valueForLength(style()->borderTopRightRadius().width(), boxWidth, v), valueForLength(style()->borderBottomRightRadius().width(), boxWidth, v)));
+        LayoutUnit decorationsWidth = max<LayoutUnit>(-outlineStyle->outlineOffset(), borderWidth + minInsetRightShadowExtent) + max<LayoutUnit>(outlineWidth, shadowRight);
+        LayoutRect rightRect(newOutlineBox.x() + min(newOutlineBox.width(), oldOutlineBox.width()) - decorationsWidth,
+            newOutlineBox.y(),
+            width + decorationsWidth,
+            max(newOutlineBox.height(), oldOutlineBox.height()));
+        LayoutUnit right = min<LayoutUnit>(newBounds.maxX(), oldBounds.maxX());
+        if (rightRect.x() < right) {
+            rightRect.setWidth(min(rightRect.width(), right - rightRect.x()));
+            repaintUsingContainer(repaintContainer, pixelSnappedIntRect(rightRect));
+        }
+    }
+    LayoutUnit height = absoluteValue(newOutlineBox.height() - oldOutlineBox.height());
+    if (height) {
+        LayoutUnit shadowTop;
+        LayoutUnit shadowBottom;
+        style()->getBoxShadowVerticalExtent(shadowTop, shadowBottom);
+        int borderBottom = isBox() ? toRenderBox(this)->borderBottom() : 0;
+        LayoutUnit boxHeight = isBox() ? toRenderBox(this)->height() : LayoutUnit();
+        LayoutUnit minInsetBottomShadowExtent = min<LayoutUnit>(-insetShadowExtent.bottom(), min<LayoutUnit>(newBounds.height(), oldBounds.height()));
+        LayoutUnit borderHeight = max<LayoutUnit>(borderBottom, max<LayoutUnit>(valueForLength(style()->borderBottomLeftRadius().height(), boxHeight, v), valueForLength(style()->borderBottomRightRadius().height(), boxHeight, v)));
+        LayoutUnit decorationsHeight = max<LayoutUnit>(-outlineStyle->outlineOffset(), borderHeight + minInsetBottomShadowExtent) + max<LayoutUnit>(outlineWidth, shadowBottom);
+        LayoutRect bottomRect(newOutlineBox.x(),
+            min(newOutlineBox.maxY(), oldOutlineBox.maxY()) - decorationsHeight,
+            max(newOutlineBox.width(), oldOutlineBox.width()),
+            height + decorationsHeight);
+        LayoutUnit bottom = min(newBounds.maxY(), oldBounds.maxY());
+        if (bottomRect.y() < bottom) {
+            bottomRect.setHeight(min(bottomRect.height(), bottom - bottomRect.y()));
+            repaintUsingContainer(repaintContainer, pixelSnappedIntRect(bottomRect));
+        }
+    }
+    return false;
+}
+
+bool RenderObject::checkForRepaintDuringLayout() const
+{
+    return !document()->view()->needsFullRepaint() && !hasLayer() && everHadLayout();
+}
+
+LayoutRect RenderObject::rectWithOutlineForRepaint(const RenderLayerModelObject* repaintContainer, LayoutUnit outlineWidth) const
+{
+    LayoutRect r(clippedOverflowRectForRepaint(repaintContainer));
+    r.inflate(outlineWidth);
+    return r;
+}
+
+LayoutRect RenderObject::clippedOverflowRectForRepaint(const RenderLayerModelObject*) const
+{
+    ASSERT_NOT_REACHED();
+    return LayoutRect();
+}
+
+void RenderObject::computeRectForRepaint(const RenderLayerModelObject* repaintContainer, LayoutRect& rect, bool fixed) const
+{
+    if (repaintContainer == this)
+        return;
+
+    if (RenderObject* o = parent()) {
+        if (o->isBlockFlow()) {
+            RenderBlock* cb = toRenderBlock(o);
+            if (cb->hasColumns())
+                cb->adjustRectForColumns(rect);
+        }
+
+        if (o->hasOverflowClip()) {
+            RenderBox* boxParent = toRenderBox(o);
+            boxParent->applyCachedClipAndScrollOffsetForRepaint(rect);
+            if (rect.isEmpty())
+                return;
+        }
+
+        o->computeRectForRepaint(repaintContainer, rect, fixed);
+    }
+}
+
+void RenderObject::computeFloatRectForRepaint(const RenderLayerModelObject*, FloatRect&, bool) const
+{
+    ASSERT_NOT_REACHED();
+}
+
+void RenderObject::dirtyLinesFromChangedChild(RenderObject*)
+{
+}
+
+#ifndef NDEBUG
+
+void RenderObject::showTreeForThis() const
+{
+    if (node())
+        node()->showTreeForThis();
+}
+
+void RenderObject::showRenderTreeForThis() const
+{
+    showRenderTree(this, 0);
+}
+
+void RenderObject::showLineTreeForThis() const
+{
+    if (containingBlock())
+        containingBlock()->showLineTreeAndMark(0, 0, 0, 0, this);
+}
+
+void RenderObject::showRenderObject() const
+{
+    showRenderObject(0);
+}
+
+void RenderObject::showRenderObject(int printedCharacters) const
+{
+    // As this function is intended to be used when debugging, the
+    // this pointer may be 0.
+    if (!this) {
+        fputs("(null)\n", stderr);
+        return;
+    }
+
+    printedCharacters += fprintf(stderr, "%s %p", renderName(), this);
+
+    if (node()) {
+        if (printedCharacters)
+            for (; printedCharacters < showTreeCharacterOffset; printedCharacters++)
+                fputc(' ', stderr);
+        fputc('\t', stderr);
+        node()->showNode();
+    } else
+        fputc('\n', stderr);
+}
+
+void RenderObject::showRenderTreeAndMark(const RenderObject* markedObject1, const char* markedLabel1, const RenderObject* markedObject2, const char* markedLabel2, int depth) const
+{
+    int printedCharacters = 0;
+    if (markedObject1 == this && markedLabel1)
+        printedCharacters += fprintf(stderr, "%s", markedLabel1);
+    if (markedObject2 == this && markedLabel2)
+        printedCharacters += fprintf(stderr, "%s", markedLabel2);
+    for (; printedCharacters < depth * 2; printedCharacters++)
+        fputc(' ', stderr);
+
+    showRenderObject(printedCharacters);
+    if (!this)
+        return;
+
+    for (const RenderObject* child = firstChild(); child; child = child->nextSibling())
+        child->showRenderTreeAndMark(markedObject1, markedLabel1, markedObject2, markedLabel2, depth + 1);
+}
+
+#endif // NDEBUG
+
+Color RenderObject::selectionBackgroundColor() const
+{
+    Color color;
+    if (style()->userSelect() != SELECT_NONE) {
+        RefPtr<RenderStyle> pseudoStyle = getUncachedPseudoStyle(PseudoStyleRequest(SELECTION));
+        if (pseudoStyle && pseudoStyle->visitedDependentColor(CSSPropertyBackgroundColor).isValid())
+            color = pseudoStyle->visitedDependentColor(CSSPropertyBackgroundColor).blendWithWhite();
+        else
+            color = frame()->selection()->isFocusedAndActive() ?
+                    theme()->activeSelectionBackgroundColor() :
+                    theme()->inactiveSelectionBackgroundColor();
+    }
+
+    return color;
+}
+
+Color RenderObject::selectionColor(int colorProperty) const
+{
+    Color color;
+    // If the element is unselectable, or we are only painting the selection,
+    // don't override the foreground color with the selection foreground color.
+    if (style()->userSelect() == SELECT_NONE
+        || (frame()->view()->paintBehavior() & PaintBehaviorSelectionOnly))
+        return color;
+
+    if (RefPtr<RenderStyle> pseudoStyle = getUncachedPseudoStyle(PseudoStyleRequest(SELECTION))) {
+        color = pseudoStyle->visitedDependentColor(colorProperty);
+        if (!color.isValid())
+            color = pseudoStyle->visitedDependentColor(CSSPropertyColor);
+    } else
+        color = frame()->selection()->isFocusedAndActive() ?
+                theme()->activeSelectionForegroundColor() :
+                theme()->inactiveSelectionForegroundColor();
+
+    return color;
+}
+
+Color RenderObject::selectionForegroundColor() const
+{
+    return selectionColor(CSSPropertyWebkitTextFillColor);
+}
+
+Color RenderObject::selectionEmphasisMarkColor() const
+{
+    return selectionColor(CSSPropertyWebkitTextEmphasisColor);
+}
+
+void RenderObject::selectionStartEnd(int& spos, int& epos) const
+{
+    view()->selectionStartEnd(spos, epos);
+}
+
+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())
+            toRenderBoxModelObject(parent())->childBecameNonInline(this);
+        else {
+            // An anonymous block must be made to wrap this inline.
+            RenderBlock* block = toRenderBlock(parent())->createAnonymousBlock();
+            RenderObjectChildList* childlist = parent()->virtualChildren();
+            childlist->insertChildNode(parent(), block, this);
+            block->children()->appendChildNode(block, childlist->removeChildNode(parent(), this));
+        }
+    }
+}
+
+void RenderObject::setAnimatableStyle(PassRefPtr<RenderStyle> style)
+{
+    if (!isText() && style)
+        setStyle(animation()->updateAnimations(this, style.get()));
+    else
+        setStyle(style);
+}
+
+StyleDifference RenderObject::adjustStyleDifference(StyleDifference diff, unsigned contextSensitiveProperties) const
+{
+    // If transform changed, and we are not composited, need to do a layout.
+    if (contextSensitiveProperties & ContextSensitivePropertyTransform) {
+        // Text nodes share style with their parents but transforms don't apply to them,
+        // hence the !isText() check.
+        // FIXME: when transforms are taken into account for overflow, we will need to do a layout.
+        if (!isText() && (!hasLayer() || !toRenderLayerModelObject(this)->layer()->isComposited())) {
+            // We need to set at least SimplifiedLayout, but if PositionedMovementOnly is already set
+            // then we actually need SimplifiedLayoutAndPositionedMovement.
+            if (!hasLayer())
+                diff = StyleDifferenceLayout; // FIXME: Do this for now since SimplifiedLayout cannot handle updating floating objects lists.
+            else if (diff < StyleDifferenceLayoutPositionedMovementOnly)
+                diff = StyleDifferenceSimplifiedLayout;
+            else if (diff < StyleDifferenceSimplifiedLayout)
+                diff = StyleDifferenceSimplifiedLayoutAndPositionedMovement;
+        } else if (diff < StyleDifferenceRecompositeLayer)
+            diff = StyleDifferenceRecompositeLayer;
+    }
+
+    // If opacity changed, and we are not composited, need to repaint (also
+    // ignoring text nodes)
+    if (contextSensitiveProperties & ContextSensitivePropertyOpacity) {
+        if (!isText() && (!hasLayer() || !toRenderLayerModelObject(this)->layer()->isComposited()))
+            diff = StyleDifferenceRepaintLayer;
+        else if (diff < StyleDifferenceRecompositeLayer)
+            diff = StyleDifferenceRecompositeLayer;
+    }
+
+    if ((contextSensitiveProperties & ContextSensitivePropertyFilter) && hasLayer()) {
+        RenderLayer* layer = toRenderLayerModelObject(this)->layer();
+        if (!layer->isComposited() || layer->paintsWithFilters())
+            diff = StyleDifferenceRepaintLayer;
+        else if (diff < StyleDifferenceRecompositeLayer)
+            diff = StyleDifferenceRecompositeLayer;
+    }
+    
+    // The answer to requiresLayer() for plugins, iframes, and canvas can change without the actual
+    // style changing, since it depends on whether we decide to composite these elements. When the
+    // layer status of one of these elements changes, we need to force a layout.
+    if (diff == StyleDifferenceEqual && style() && isLayerModelObject()) {
+        if (hasLayer() != toRenderLayerModelObject(this)->requiresLayer())
+            diff = StyleDifferenceLayout;
+    }
+
+    // If we have no layer(), just treat a RepaintLayer hint as a normal Repaint.
+    if (diff == StyleDifferenceRepaintLayer && !hasLayer())
+        diff = StyleDifferenceRepaint;
+
+    return diff;
+}
+
+void RenderObject::setPseudoStyle(PassRefPtr<RenderStyle> pseudoStyle)
+{
+    ASSERT(pseudoStyle->styleType() == BEFORE || pseudoStyle->styleType() == AFTER);
+
+    // Images are special and must inherit the pseudoStyle so the width and height of
+    // the pseudo element doesn't change the size of the image. In all other cases we
+    // can just share the style.
+    if (isImage()) {
+        RefPtr<RenderStyle> style = RenderStyle::create();
+        style->inheritFrom(pseudoStyle.get());
+        setStyle(style.release());
+        return;
+    }
+
+    setStyle(pseudoStyle);
+}
+
+void RenderObject::setStyle(PassRefPtr<RenderStyle> style)
+{
+    if (m_style == style) {
+        // We need to run through adjustStyleDifference() for iframes, plugins, and canvas so
+        // style sharing is disabled for them. That should ensure that we never hit this code path.
+        ASSERT(!isRenderIFrame() && !isEmbeddedObject() && !isCanvas());
+        return;
+    }
+
+    StyleDifference diff = StyleDifferenceEqual;
+    unsigned contextSensitiveProperties = ContextSensitivePropertyNone;
+    if (m_style)
+        diff = m_style->diff(style.get(), contextSensitiveProperties);
+
+    diff = adjustStyleDifference(diff, contextSensitiveProperties);
+
+    styleWillChange(diff, style.get());
+    
+    RefPtr<RenderStyle> oldStyle = m_style.release();
+    setStyleInternal(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);
+
+    // We need to ensure that view->maximalOutlineSize() is valid for any repaints that happen
+    // during styleDidChange (it's used by clippedOverflowRectForRepaint()).
+    if (m_style->outlineWidth() > 0 && m_style->outlineSize() > maximalOutlineSize(PaintPhaseOutline))
+        toRenderView(document()->renderer())->setMaximalOutlineSize(m_style->outlineSize());
+
+    bool doesNotNeedLayout = !m_parent || isText();
+
+    styleDidChange(diff, oldStyle.get());
+
+    // FIXME: |this| might be destroyed here. This can currently happen for a RenderTextFragment when
+    // its first-letter block gets an update in RenderTextFragment::styleDidChange. For RenderTextFragment(s),
+    // we will safely bail out with the doesNotNeedLayout flag. We might want to broaden this condition
+    // in the future as we move renderer changes out of layout and into style changes.
+    if (doesNotNeedLayout)
+        return;
+
+    // Now that the layer (if any) has been updated, we need to adjust the diff again,
+    // check whether we should layout now, and decide if we need to repaint.
+    StyleDifference updatedDiff = adjustStyleDifference(diff, contextSensitiveProperties);
+    
+    if (diff <= StyleDifferenceLayoutPositionedMovementOnly) {
+        if (updatedDiff == StyleDifferenceLayout)
+            setNeedsLayoutAndPrefWidthsRecalc();
+        else if (updatedDiff == StyleDifferenceLayoutPositionedMovementOnly)
+            setNeedsPositionedMovementLayout();
+        else if (updatedDiff == StyleDifferenceSimplifiedLayoutAndPositionedMovement) {
+            setNeedsPositionedMovementLayout();
+            setNeedsSimplifiedNormalFlowLayout();
+        } else if (updatedDiff == StyleDifferenceSimplifiedLayout)
+            setNeedsSimplifiedNormalFlowLayout();
+    }
+    
+    if (updatedDiff == StyleDifferenceRepaintLayer || updatedDiff == StyleDifferenceRepaint) {
+        // 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();
+    }
+}
+
+static inline bool rendererHasBackground(const RenderObject* renderer)
+{
+    return renderer && renderer->hasBackground();
+}
+
+void RenderObject::styleWillChange(StyleDifference 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) {
+            bool visibilityChanged = m_style->visibility() != newStyle->visibility() 
+                || m_style->zIndex() != newStyle->zIndex() 
+                || m_style->hasAutoZIndex() != newStyle->hasAutoZIndex();
+            if (visibilityChanged) {
+                document()->setAnnotatedRegionsDirty(true);
+                if (AXObjectCache* cache = document()->existingAXObjectCache())
+                    cache->childrenChanged(parent());
+            }
+
+            // 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();
+                    else if (l->hasVisibleContent() && (this == l->renderer() || l->renderer()->style()->visibility() != VISIBLE)) {
+                        l->dirtyVisibleContentStatus();
+                        if (diff > StyleDifferenceRepaintLayer)
+                            repaint();
+                    }
+                }
+            }
+        }
+
+        if (m_parent && (diff == StyleDifferenceRepaint || newStyle->outlineSize() < m_style->outlineSize()))
+            repaint();
+        if (isFloating() && (m_style->floating() != newStyle->floating()))
+            // For changes in float styles, we need to conceivably remove ourselves
+            // from the floating objects list.
+            toRenderBox(this)->removeFloatingOrPositionedChildFromBlockLists();
+        else if (isOutOfFlowPositioned() && (m_style->position() != newStyle->position()))
+            // For changes in positioning styles, we need to conceivably remove ourselves
+            // from the positioned objects list.
+            toRenderBox(this)->removeFloatingOrPositionedChildFromBlockLists();
+
+        s_affectsParentBlock = isFloatingOrOutOfFlowPositioned()
+            && (!newStyle->isFloating() && !newStyle->hasOutOfFlowPosition())
+            && parent() && (parent()->isBlockFlow() || parent()->isRenderInline());
+
+        // reset style flags
+        if (diff == StyleDifferenceLayout || diff == StyleDifferenceLayoutPositionedMovementOnly) {
+            setFloating(false);
+            clearPositionedState();
+        }
+        setHorizontalWritingMode(true);
+        setHasBoxDecorations(false);
+        setHasOverflowClip(false);
+        setHasTransform(false);
+        setHasReflection(false);
+    } else
+        s_affectsParentBlock = false;
+
+    if (view()->frameView()) {
+        bool shouldBlitOnFixedBackgroundImage = false;
+#if ENABLE(FAST_MOBILE_SCROLLING)
+        // On low-powered/mobile devices, preventing blitting on a scroll can cause noticeable delays
+        // when scrolling a page with a fixed background image. As an optimization, assuming there are
+        // no fixed positoned elements on the page, we can acclerate scrolling (via blitting) if we
+        // ignore the CSS property "background-attachment: fixed".
+        shouldBlitOnFixedBackgroundImage = true;
+#endif
+
+        bool newStyleSlowScroll = newStyle && !shouldBlitOnFixedBackgroundImage && newStyle->hasFixedBackgroundImage();
+        bool oldStyleSlowScroll = m_style && !shouldBlitOnFixedBackgroundImage && m_style->hasFixedBackgroundImage();
+
+        bool drawsRootBackground = isRoot() || (isBody() && !rendererHasBackground(document()->documentElement()->renderer()));
+        if (drawsRootBackground && !shouldBlitOnFixedBackgroundImage) {
+            if (view()->compositor()->supportsFixedRootBackgroundCompositing()) {
+                if (newStyleSlowScroll && newStyle->hasEntirelyFixedBackground())
+                    newStyleSlowScroll = false;
+
+                if (oldStyleSlowScroll && m_style->hasEntirelyFixedBackground())
+                    oldStyleSlowScroll = false;
+            }
+        }
+
+        if (oldStyleSlowScroll != newStyleSlowScroll) {
+            if (oldStyleSlowScroll)
+                view()->frameView()->removeSlowRepaintObject();
+            if (newStyleSlowScroll)
+                view()->frameView()->addSlowRepaintObject();
+        }
+    }
+}
+
+static bool areNonIdenticalCursorListsEqual(const RenderStyle* a, const RenderStyle* b)
+{
+    ASSERT(a->cursors() != b->cursors());
+    return a->cursors() && b->cursors() && *a->cursors() == *b->cursors();
+}
+
+static inline bool areCursorsEqual(const RenderStyle* a, const RenderStyle* b)
+{
+    return a->cursor() == b->cursor() && (a->cursors() == b->cursors() || areNonIdenticalCursorListsEqual(a, b));
+}
+
+void RenderObject::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
+{
+    if (s_affectsParentBlock)
+        handleDynamicFloatPositionChange();
+
+#if ENABLE(SVG)
+    SVGRenderSupport::styleChanged(this);
+#endif
+
+    if (!m_parent)
+        return;
+    
+    if (diff == StyleDifferenceLayout || diff == StyleDifferenceSimplifiedLayout) {
+        RenderCounter::rendererStyleChanged(this, oldStyle, m_style.get());
+
+        // If the object already needs layout, then setNeedsLayout won't do
+        // any work. But if the containing block has changed, then we may need
+        // to mark the new containing blocks for layout. The change that can
+        // directly affect the containing block of this object is a change to
+        // the position style.
+        if (needsLayout() && oldStyle->position() != m_style->position())
+            markContainingBlocksForLayout();
+
+        if (diff == StyleDifferenceLayout)
+            setNeedsLayoutAndPrefWidthsRecalc();
+        else
+            setNeedsSimplifiedNormalFlowLayout();
+    } else if (diff == StyleDifferenceSimplifiedLayoutAndPositionedMovement) {
+        setNeedsPositionedMovementLayout();
+        setNeedsSimplifiedNormalFlowLayout();
+    } else if (diff == StyleDifferenceLayoutPositionedMovementOnly)
+        setNeedsPositionedMovementLayout();
+
+    // Don't check for repaint here; we need to wait until the layer has been
+    // updated by subclasses before we know if we have to repaint (in setStyle()).
+
+    if (oldStyle && !areCursorsEqual(oldStyle, style())) {
+        if (Frame* frame = this->frame())
+            frame->eventHandler()->dispatchFakeMouseMoveEventSoon();
+    }
+}
+
+void RenderObject::propagateStyleToAnonymousChildren(bool blockChildrenOnly)
+{
+    // FIXME: We could save this call when the change only affected non-inherited properties.
+    for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+        if (!child->isAnonymous() || child->style()->styleType() != NOPSEUDO)
+            continue;
+
+        if (blockChildrenOnly && !child->isRenderBlock())
+            continue;
+
+        if (child->isRenderFullScreen() || child->isRenderFullScreenPlaceholder())
+            continue;
+
+        RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(style(), child->style()->display());
+        if (style()->specifiesColumns()) {
+            if (child->style()->specifiesColumns())
+                newStyle->inheritColumnPropertiesFrom(style());
+            if (child->style()->columnSpan())
+                newStyle->setColumnSpan(ColumnSpanAll);
+        }
+
+        // Preserve the position style of anonymous block continuations as they can have relative or sticky position when
+        // they contain block descendants of relative or sticky positioned inlines.
+        if (child->isInFlowPositioned() && toRenderBlock(child)->isAnonymousBlockContinuation())
+            newStyle->setPosition(child->style()->position());
+
+        child->setStyle(newStyle.release());
+    }
+}
+
+void RenderObject::updateFillImages(const FillLayer* oldLayers, const FillLayer* newLayers)
+{
+    // Optimize the common case
+    if (oldLayers && !oldLayers->next() && newLayers && !newLayers->next() && (oldLayers->image() == newLayers->image()))
+        return;
+    
+    // Go through the new layers and addClients first, to avoid removing all clients of an image.
+    for (const FillLayer* currNew = newLayers; currNew; currNew = currNew->next()) {
+        if (currNew->image())
+            currNew->image()->addClient(this);
+    }
+
+    for (const FillLayer* currOld = oldLayers; currOld; currOld = currOld->next()) {
+        if (currOld->image())
+            currOld->image()->removeClient(this);
+    }
+}
+
+void RenderObject::updateImage(StyleImage* oldImage, StyleImage* newImage)
+{
+    if (oldImage != newImage) {
+        if (oldImage)
+            oldImage->removeClient(this);
+        if (newImage)
+            newImage->addClient(this);
+    }
+}
+
+LayoutRect RenderObject::viewRect() const
+{
+    return view()->viewRect();
+}
+
+FloatPoint RenderObject::localToAbsolute(const FloatPoint& localPoint, MapCoordinatesFlags mode) const
+{
+    TransformState transformState(TransformState::ApplyTransformDirection, localPoint);
+    mapLocalToContainer(0, transformState, mode | ApplyContainerFlip);
+    transformState.flatten();
+    
+    return transformState.lastPlanarPoint();
+}
+
+FloatPoint RenderObject::absoluteToLocal(const FloatPoint& containerPoint, MapCoordinatesFlags mode) const
+{
+    TransformState transformState(TransformState::UnapplyInverseTransformDirection, containerPoint);
+    mapAbsoluteToLocalPoint(mode, transformState);
+    transformState.flatten();
+    
+    return transformState.lastPlanarPoint();
+}
+
+FloatQuad RenderObject::absoluteToLocalQuad(const FloatQuad& quad, MapCoordinatesFlags mode) const
+{
+    TransformState transformState(TransformState::UnapplyInverseTransformDirection, quad.boundingBox().center(), quad);
+    mapAbsoluteToLocalPoint(mode, transformState);
+    transformState.flatten();
+    return transformState.lastPlanarQuad();
+}
+
+void RenderObject::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags mode, bool* wasFixed) const
+{
+    if (repaintContainer == this)
+        return;
+
+    RenderObject* o = parent();
+    if (!o)
+        return;
+
+    // FIXME: this should call offsetFromContainer to share code, but I'm not sure it's ever called.
+    LayoutPoint centerPoint = roundedLayoutPoint(transformState.mappedPoint());
+    if (mode & ApplyContainerFlip && o->isBox()) {
+        if (o->style()->isFlippedBlocksWritingMode())
+            transformState.move(toRenderBox(o)->flipForWritingModeIncludingColumns(roundedLayoutPoint(transformState.mappedPoint())) - centerPoint);
+        mode &= ~ApplyContainerFlip;
+    }
+
+    LayoutSize columnOffset;
+    o->adjustForColumns(columnOffset, roundedLayoutPoint(transformState.mappedPoint()));
+    if (!columnOffset.isZero())
+        transformState.move(columnOffset);
+
+    if (o->hasOverflowClip())
+        transformState.move(-toRenderBox(o)->scrolledContentOffset());
+
+    o->mapLocalToContainer(repaintContainer, transformState, mode, wasFixed);
+}
+
+const RenderObject* RenderObject::pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const
+{
+    ASSERT_UNUSED(ancestorToStopAt, ancestorToStopAt != this);
+
+    RenderObject* container = parent();
+    if (!container)
+        return 0;
+
+    // FIXME: this should call offsetFromContainer to share code, but I'm not sure it's ever called.
+    LayoutSize offset;
+    if (container->hasOverflowClip())
+        offset = -toRenderBox(container)->scrolledContentOffset();
+
+    geometryMap.push(this, offset, hasColumns());
+    
+    return container;
+}
+
+void RenderObject::mapAbsoluteToLocalPoint(MapCoordinatesFlags mode, TransformState& transformState) const
+{
+    RenderObject* o = parent();
+    if (o) {
+        o->mapAbsoluteToLocalPoint(mode, transformState);
+        if (o->hasOverflowClip())
+            transformState.move(toRenderBox(o)->scrolledContentOffset());
+    }
+}
+
+bool RenderObject::shouldUseTransformFromContainer(const RenderObject* containerObject) const
+{
+    // hasTransform() indicates whether the object has transform, transform-style or perspective. We just care about transform,
+    // so check the layer's transform directly.
+    return (hasLayer() && toRenderLayerModelObject(this)->layer()->transform()) || (containerObject && containerObject->style()->hasPerspective());
+}
+
+void RenderObject::getTransformFromContainer(const RenderObject* containerObject, const LayoutSize& offsetInContainer, TransformationMatrix& transform) const
+{
+    transform.makeIdentity();
+    transform.translate(offsetInContainer.width(), offsetInContainer.height());
+    RenderLayer* layer;
+    if (hasLayer() && (layer = toRenderLayerModelObject(this)->layer()) && layer->transform())
+        transform.multiply(layer->currentTransform());
+    
+    if (containerObject && containerObject->hasLayer() && containerObject->style()->hasPerspective()) {
+        // Perpsective on the container affects us, so we have to factor it in here.
+        ASSERT(containerObject->hasLayer());
+        FloatPoint perspectiveOrigin = toRenderLayerModelObject(containerObject)->layer()->perspectiveOrigin();
+
+        TransformationMatrix perspectiveMatrix;
+        perspectiveMatrix.applyPerspective(containerObject->style()->perspective());
+        
+        transform.translateRight3d(-perspectiveOrigin.x(), -perspectiveOrigin.y(), 0);
+        transform = perspectiveMatrix * transform;
+        transform.translateRight3d(perspectiveOrigin.x(), perspectiveOrigin.y(), 0);
+    }
+}
+
+FloatQuad RenderObject::localToContainerQuad(const FloatQuad& localQuad, const RenderLayerModelObject* repaintContainer, MapCoordinatesFlags mode, bool* wasFixed) const
+{
+    // Track the point at the center of the quad's bounding box. As mapLocalToContainer() calls offsetFromContainer(),
+    // it will use that point as the reference point to decide which column's transform to apply in multiple-column blocks.
+    TransformState transformState(TransformState::ApplyTransformDirection, localQuad.boundingBox().center(), localQuad);
+    mapLocalToContainer(repaintContainer, transformState, mode | ApplyContainerFlip | UseTransforms, wasFixed);
+    transformState.flatten();
+    
+    return transformState.lastPlanarQuad();
+}
+
+FloatPoint RenderObject::localToContainerPoint(const FloatPoint& localPoint, const RenderLayerModelObject* repaintContainer, MapCoordinatesFlags mode, bool* wasFixed) const
+{
+    TransformState transformState(TransformState::ApplyTransformDirection, localPoint);
+    mapLocalToContainer(repaintContainer, transformState, mode | ApplyContainerFlip | UseTransforms, wasFixed);
+    transformState.flatten();
+
+    return transformState.lastPlanarPoint();
+}
+
+LayoutSize RenderObject::offsetFromContainer(RenderObject* o, const LayoutPoint& point, bool* offsetDependsOnPoint) const
+{
+    ASSERT(o == container());
+
+    LayoutSize offset;
+
+    o->adjustForColumns(offset, point);
+
+    if (o->hasOverflowClip())
+        offset -= toRenderBox(o)->scrolledContentOffset();
+
+    if (offsetDependsOnPoint)
+        *offsetDependsOnPoint = hasColumns();
+
+    return offset;
+}
+
+LayoutSize RenderObject::offsetFromAncestorContainer(RenderObject* container) const
+{
+    LayoutSize offset;
+    LayoutPoint referencePoint;
+    const RenderObject* currContainer = this;
+    do {
+        RenderObject* nextContainer = currContainer->container();
+        ASSERT(nextContainer);  // This means we reached the top without finding container.
+        if (!nextContainer)
+            break;
+        ASSERT(!currContainer->hasTransform());
+        LayoutSize currentOffset = currContainer->offsetFromContainer(nextContainer, referencePoint);
+        offset += currentOffset;
+        referencePoint.move(currentOffset);
+        currContainer = nextContainer;
+    } while (currContainer != container);
+
+    return offset;
+}
+
+LayoutRect RenderObject::localCaretRect(InlineBox*, int, LayoutUnit* extraWidthToEndOfLine)
+{
+    if (extraWidthToEndOfLine)
+        *extraWidthToEndOfLine = 0;
+
+    return LayoutRect();
+}
+
+bool RenderObject::isRooted(RenderView** view) const
+{
+    const RenderObject* o = this;
+    while (o->parent())
+        o = o->parent();
+
+    if (!o->isRenderView())
+        return false;
+
+    if (view)
+        *view = const_cast<RenderView*>(toRenderView(o));
+
+    return true;
+}
+
+RenderObject* RenderObject::rendererForRootBackground()
+{
+    ASSERT(isRoot());
+    if (!hasBackground() && node() && node()->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)
+            return bodyObject;
+    }
+    
+    return this;
+}
+
+RespectImageOrientationEnum RenderObject::shouldRespectImageOrientation() const
+{
+    // Respect the image's orientation if it's being used as a full-page image or it's
+    // an <img> and the setting to respect it everywhere is set.
+    return document()->isImageDocument() ||
+        (document()->settings() && document()->settings()->shouldRespectImageOrientation() && node() && node()->hasTagName(HTMLNames::imgTag)) ? RespectImageOrientation : DoNotRespectImageOrientation;
+}
+
+bool RenderObject::hasOutlineAnnotation() const
+{
+    return node() && node()->isLink() && document()->printing();
+}
+
+bool RenderObject::hasEntirelyFixedBackground() const
+{
+    return m_style->hasEntirelyFixedBackground();
+}
+
+RenderObject* RenderObject::container(const RenderLayerModelObject* repaintContainer, bool* repaintContainerSkipped) const
+{
+    if (repaintContainerSkipped)
+        *repaintContainerSkipped = false;
+
+    // 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 computePositionedLogicalWidth and
+    // computePositionedLogicalHeight 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).
+        // FIXME: The definition of view() has changed to not crawl up the render tree.  It might
+        // be safe now to use it.
+        while (o && o->parent() && !(o->hasTransform() && o->isRenderBlock())) {
+#if ENABLE(SVG)
+            // foreignObject is the containing block for its contents.
+            if (o->isSVGForeignObject())
+                break;
+#endif
+            // The render flow thread is the top most containing block
+            // for the fixed positioned elements.
+            if (o->isOutOfFlowRenderFlowThread())
+                break;
+
+            if (repaintContainerSkipped && o == repaintContainer)
+                *repaintContainerSkipped = true;
+
+            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())) {
+#if ENABLE(SVG)
+            if (o->isSVGForeignObject()) // foreignObject is the containing block for contents inside it
+                break;
+#endif
+            if (repaintContainerSkipped && o == repaintContainer)
+                *repaintContainerSkipped = true;
+
+            o = o->parent();
+        }
+    }
+
+    return o;
+}
+
+bool RenderObject::isSelectionBorder() const
+{
+    SelectionState st = selectionState();
+    return st == SelectionStart || st == SelectionEnd || st == SelectionBoth;
+}
+
+inline void RenderObject::clearLayoutRootIfNeeded() const
+{
+    if (!documentBeingDestroyed() && frame()) {
+        if (FrameView* view = frame()->view()) {
+            if (view->layoutRoot() == this) {
+                ASSERT_NOT_REACHED();
+                // This indicates a failure to layout the child, which is why
+                // the layout root is still set to |this|. Make sure to clear it
+                // since we are getting destroyed.
+                view->clearLayoutRoot();
+            }
+        }
+    }
+}
+
+void RenderObject::willBeDestroyed()
+{
+    // Destroy any leftover anonymous children.
+    RenderObjectChildList* children = virtualChildren();
+    if (children)
+        children->destroyLeftoverChildren();
+
+    // If this renderer is being autoscrolled, stop the autoscroll timer
+    
+    // FIXME: RenderObject::destroy should not get called with a renderer whose document
+    // has a null frame, so we assert this. However, we don't want release builds to crash which is why we
+    // check that the frame is not null.
+    ASSERT(frame());
+    if (frame() && frame()->eventHandler()->autoscrollRenderer() == this)
+        frame()->eventHandler()->stopAutoscrollTimer(true);
+
+    animation()->cancelAnimations(this);
+
+    // For accessibility management, notify the parent of the imminent change to its child set.
+    // We do it now, before remove(), while the parent pointer is still available.
+    if (AXObjectCache* cache = document()->existingAXObjectCache())
+        cache->childrenChanged(this->parent());
+
+    remove();
+
+    // The remove() call above may invoke axObjectCache()->childrenChanged() on the parent, which may require the AX render
+    // object for this renderer. So we remove the AX render object now, after the renderer is removed.
+    if (AXObjectCache* cache = document()->existingAXObjectCache())
+        cache->remove(this);
+
+#ifndef NDEBUG
+    if (!documentBeingDestroyed() && view() && view()->hasRenderNamedFlowThreads()) {
+        // After remove, the object and the associated information should not be in any flow thread.
+        const RenderNamedFlowThreadList* flowThreadList = view()->flowThreadController()->renderNamedFlowThreadList();
+        for (RenderNamedFlowThreadList::const_iterator iter = flowThreadList->begin(); iter != flowThreadList->end(); ++iter) {
+            const RenderNamedFlowThread* renderFlowThread = *iter;
+            ASSERT(!renderFlowThread->hasChild(this));
+            ASSERT(!renderFlowThread->hasChildInfo(this));
+        }
+    }
+#endif
+
+    // If this renderer had a parent, remove should have destroyed any counters
+    // attached to this renderer and marked the affected other counters for
+    // reevaluation. This apparently redundant check is here for the case when
+    // this renderer had no parent at the time remove() was called.
+
+    if (hasCounterNodeMap())
+        RenderCounter::destroyCounterNodes(this);
+
+    // FIXME: Would like to do this in RenderBoxModelObject, but the timing is so complicated that this can't easily
+    // be moved into RenderBoxModelObject::destroy.
+    if (hasLayer()) {
+        setHasLayer(false);
+        toRenderLayerModelObject(this)->destroyLayer();
+    }
+
+    setAncestorLineBoxDirty(false);
+
+    clearLayoutRootIfNeeded();
+}
+
+void RenderObject::insertedIntoTree()
+{
+    // FIXME: We should ASSERT(isRooted()) here but generated content makes some out-of-order insertion.
+
+    // 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 (firstChild() || hasLayer()) {
+        layer = parent()->enclosingLayer();
+        addLayers(layer);
+    }
+
+    // If |this| 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 (parent()->style()->visibility() != VISIBLE && style()->visibility() == VISIBLE && !hasLayer()) {
+        if (!layer)
+            layer = parent()->enclosingLayer();
+        if (layer)
+            layer->setHasVisibleContent();
+    }
+
+    if (!isFloating() && parent()->childrenInline())
+        parent()->dirtyLinesFromChangedChild(this);
+
+    if (RenderNamedFlowThread* containerFlowThread = parent()->renderNamedFlowThreadWrapper())
+        containerFlowThread->addFlowChild(this);
+}
+
+void RenderObject::willBeRemovedFromTree()
+{
+    // FIXME: We should ASSERT(isRooted()) but we have some out-of-order removals which would need to be fixed first.
+
+    // If we remove a visible child from an invisible parent, we don't know the layer visibility any more.
+    RenderLayer* layer = 0;
+    if (parent()->style()->visibility() != VISIBLE && style()->visibility() == VISIBLE && !hasLayer()) {
+        if ((layer = parent()->enclosingLayer()))
+            layer->dirtyVisibleContentStatus();
+    }
+
+    // Keep our layer hierarchy updated.
+    if (firstChild() || hasLayer()) {
+        if (!layer)
+            layer = parent()->enclosingLayer();
+        removeLayers(layer);
+    }
+
+    if (isOutOfFlowPositioned() && parent()->childrenInline())
+        parent()->dirtyLinesFromChangedChild(this);
+
+    removeFromRenderFlowThread();
+
+    if (RenderNamedFlowThread* containerFlowThread = parent()->renderNamedFlowThreadWrapper())
+        containerFlowThread->removeFlowChild(this);
+
+#if ENABLE(SVG)
+    // Update cached boundaries in SVG renderers, if a child is removed.
+    parent()->setNeedsBoundariesUpdate();
+#endif
+}
+
+void RenderObject::removeFromRenderFlowThread()
+{
+    if (flowThreadState() == NotInsideFlowThread)
+        return;
+    
+    // Sometimes we remove the element from the flow, but it's not destroyed at that time.
+    // It's only until later when we actually destroy it and remove all the children from it. 
+    // Currently, that happens for firstLetter elements and list markers.
+    // Pass in the flow thread so that we don't have to look it up for all the children.
+    removeFromRenderFlowThreadRecursive(flowThreadContainingBlock());
+}
+
+void RenderObject::removeFromRenderFlowThreadRecursive(RenderFlowThread* renderFlowThread)
+{
+    if (const RenderObjectChildList* children = virtualChildren()) {
+        for (RenderObject* child = children->firstChild(); child; child = child->nextSibling())
+            child->removeFromRenderFlowThreadRecursive(renderFlowThread);
+    }
+    
+    RenderFlowThread* localFlowThread = renderFlowThread;
+    if (flowThreadState() == InsideInFlowThread)
+        localFlowThread = flowThreadContainingBlock(); // We have to ask. We can't just assume we are in the same flow thread.
+    if (localFlowThread)
+        localFlowThread->removeFlowChildInfo(this);
+    setFlowThreadState(NotInsideFlowThread);
+}
+
+void RenderObject::destroyAndCleanupAnonymousWrappers()
+{
+    // If the tree is destroyed, there is no need for a clean-up phase.
+    if (documentBeingDestroyed()) {
+        destroy();
+        return;
+    }
+
+    RenderObject* destroyRoot = this;
+    for (RenderObject* destroyRootParent = destroyRoot->parent(); destroyRootParent && destroyRootParent->isAnonymous(); destroyRoot = destroyRootParent, destroyRootParent = destroyRootParent->parent()) {
+        // Currently we only remove anonymous cells' and table sections' wrappers but we should remove all unneeded
+        // wrappers. See http://webkit.org/b/52123 as an example where this is needed.
+        if (!destroyRootParent->isTableCell() && !destroyRootParent->isTableSection())
+            break;
+
+        if (destroyRootParent->firstChild() != this || destroyRootParent->lastChild() != this)
+            break;
+    }
+
+    destroyRoot->destroy();
+
+    // WARNING: |this| is deleted here.
+}
+
+void RenderObject::destroy()
+{
+    willBeDestroyed();
+    arenaDelete(renderArena(), 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::positionForPoint(const LayoutPoint&)
+{
+    return createVisiblePosition(caretMinOffset(), DOWNSTREAM);
+}
+
+void RenderObject::updateDragState(bool dragOn)
+{
+    bool valueChanged = (dragOn != isDragging());
+    setIsDragging(dragOn);
+    if (valueChanged && node() && (style()->affectedByDrag() || (node()->isElementNode() && toElement(node())->childrenAffectedByDrag())))
+        node()->setNeedsStyleRecalc();
+    for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling())
+        curr->updateDragState(dragOn);
+}
+
+bool RenderObject::isComposited() const
+{
+    return hasLayer() && toRenderLayerModelObject(this)->layer()->isComposited();
+}
+
+bool RenderObject::hitTest(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestFilter hitTestFilter)
+{
+    bool inside = false;
+    if (hitTestFilter != HitTestSelf) {
+        // First test the foreground layer (lines and inlines).
+        inside = nodeAtPoint(request, result, locationInContainer, accumulatedOffset, HitTestForeground);
+
+        // Test floats next.
+        if (!inside)
+            inside = nodeAtPoint(request, result, locationInContainer, accumulatedOffset, HitTestFloat);
+
+        // Finally test to see if the mouse is in the background (within a child block's background).
+        if (!inside)
+            inside = nodeAtPoint(request, result, locationInContainer, accumulatedOffset, HitTestChildBlockBackgrounds);
+    }
+
+    // See if the mouse is inside us but not any of our descendants
+    if (hitTestFilter != HitTestDescendants && !inside)
+        inside = nodeAtPoint(request, result, locationInContainer, accumulatedOffset, HitTestBlockBackground);
+
+    return inside;
+}
+
+void RenderObject::updateHitTestResult(HitTestResult& result, const LayoutPoint& point)
+{
+    if (result.innerNode())
+        return;
+
+    Node* node = this->node();
+
+    // If we hit the anonymous renderers inside generated content we should
+    // actually hit the generated content so walk up to the PseudoElement.
+    if (!node && parent() && parent()->isBeforeOrAfterContent()) {
+        for (RenderObject* renderer = parent(); renderer && !node; renderer = renderer->parent())
+            node = renderer->node();
+    }
+
+    if (node) {
+        result.setInnerNode(node);
+        if (!result.innerNonSharedNode())
+            result.setInnerNonSharedNode(node);
+        result.setLocalPoint(point);
+    }
+}
+
+bool RenderObject::nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& /*locationInContainer*/, const LayoutPoint& /*accumulatedOffset*/, HitTestAction)
+{
+    return false;
+}
+
+void RenderObject::scheduleRelayout()
+{
+    if (isRenderView()) {
+        FrameView* view = toRenderView(this)->frameView();
+        if (view)
+            view->scheduleRelayout();
+    } else {
+        if (isRooted()) {
+            if (RenderView* renderView = view()) {
+                if (FrameView* frameView = renderView->frameView())
+                    frameView->scheduleRelayoutOfSubtree(this);
+            }
+        }
+    }
+}
+
+void RenderObject::layout()
+{
+    StackStats::LayoutCheckPoint layoutCheckPoint;
+    ASSERT(needsLayout());
+    RenderObject* child = firstChild();
+    while (child) {
+        child->layoutIfNeeded();
+        ASSERT(!child->needsLayout());
+        child = child->nextSibling();
+    }
+    setNeedsLayout(false);
+}
+
+enum StyleCacheState {
+    Cached,
+    Uncached
+};
+
+static PassRefPtr<RenderStyle> firstLineStyleForCachedUncachedType(StyleCacheState type, const RenderObject* renderer, RenderStyle* style)
+{
+    const RenderObject* rendererForFirstLineStyle = renderer;
+    if (renderer->isBeforeOrAfterContent())
+        rendererForFirstLineStyle = renderer->parent();
+
+    if (rendererForFirstLineStyle->isBlockFlow()) {
+        if (RenderBlock* firstLineBlock = rendererForFirstLineStyle->firstLineBlock()) {
+            if (type == Cached)
+                return firstLineBlock->getCachedPseudoStyle(FIRST_LINE, style);
+            return firstLineBlock->getUncachedPseudoStyle(PseudoStyleRequest(FIRST_LINE), style, firstLineBlock == renderer ? style : 0);
+        }
+    } else if (!rendererForFirstLineStyle->isAnonymous() && rendererForFirstLineStyle->isRenderInline()) {
+        RenderStyle* parentStyle = rendererForFirstLineStyle->parent()->firstLineStyle();
+        if (parentStyle != rendererForFirstLineStyle->parent()->style()) {
+            if (type == Cached) {
+                // A first-line style is in effect. Cache a first-line style for ourselves.
+                rendererForFirstLineStyle->style()->setHasPseudoStyle(FIRST_LINE_INHERITED);
+                return rendererForFirstLineStyle->getCachedPseudoStyle(FIRST_LINE_INHERITED, parentStyle);
+            }
+            return rendererForFirstLineStyle->getUncachedPseudoStyle(PseudoStyleRequest(FIRST_LINE_INHERITED), parentStyle, style);
+        }
+    }
+    return 0;
+}
+
+PassRefPtr<RenderStyle> RenderObject::uncachedFirstLineStyle(RenderStyle* style) const
+{
+    if (!document()->styleSheetCollection()->usesFirstLineRules())
+        return 0;
+
+    ASSERT(!isText());
+
+    return firstLineStyleForCachedUncachedType(Uncached, this, style);
+}
+
+RenderStyle* RenderObject::cachedFirstLineStyle() const
+{
+    ASSERT(document()->styleSheetCollection()->usesFirstLineRules());
+
+    if (RefPtr<RenderStyle> style = firstLineStyleForCachedUncachedType(Cached, isText() ? parent() : this, m_style.get()))
+        return style.get();
+
+    return m_style.get();
+}
+
+RenderStyle* RenderObject::getCachedPseudoStyle(PseudoId pseudo, RenderStyle* parentStyle) const
+{
+    if (pseudo < FIRST_INTERNAL_PSEUDOID && !style()->hasPseudoStyle(pseudo))
+        return 0;
+
+    RenderStyle* cachedStyle = style()->getCachedPseudoStyle(pseudo);
+    if (cachedStyle)
+        return cachedStyle;
+    
+    RefPtr<RenderStyle> result = getUncachedPseudoStyle(PseudoStyleRequest(pseudo), parentStyle);
+    if (result)
+        return style()->addCachedPseudoStyle(result.release());
+    return 0;
+}
+
+PassRefPtr<RenderStyle> RenderObject::getUncachedPseudoStyle(const PseudoStyleRequest& pseudoStyleRequest, RenderStyle* parentStyle, RenderStyle* ownStyle) const
+{
+    if (pseudoStyleRequest.pseudoId < FIRST_INTERNAL_PSEUDOID && !ownStyle && !style()->hasPseudoStyle(pseudoStyleRequest.pseudoId))
+        return 0;
+    
+    if (!parentStyle) {
+        ASSERT(!ownStyle);
+        parentStyle = style();
+    }
+
+    // FIXME: This "find nearest element parent" should be a helper function.
+    Node* n = node();
+    while (n && !n->isElementNode())
+        n = n->parentNode();
+    if (!n)
+        return 0;
+    Element* element = toElement(n);
+
+    if (pseudoStyleRequest.pseudoId == FIRST_LINE_INHERITED) {
+        RefPtr<RenderStyle> result = document()->styleResolver()->styleForElement(element, parentStyle, DisallowStyleSharing);
+        result->setStyleType(FIRST_LINE_INHERITED);
+        return result.release();
+    }
+
+    return document()->styleResolver()->pseudoStyleForElement(element, pseudoStyleRequest, parentStyle);
+}
+
+static Color decorationColor(RenderStyle* style)
+{
+    Color result;
+#if ENABLE(CSS3_TEXT)
+    // Check for text decoration color first.
+    result = style->visitedDependentColor(CSSPropertyWebkitTextDecorationColor);
+    if (result.isValid())
+        return result;
+#endif // CSS3_TEXT
+    if (style->textStrokeWidth() > 0) {
+        // Prefer stroke color if possible but not if it's fully transparent.
+        result = style->visitedDependentColor(CSSPropertyWebkitTextStrokeColor);
+        if (result.alpha())
+            return result;
+    }
+    
+    result = style->visitedDependentColor(CSSPropertyWebkitTextFillColor);
+    return result;
+}
+
+void RenderObject::getTextDecorationColors(int decorations, Color& underline, Color& overline,
+                                           Color& linethrough, bool quirksMode, bool firstlineStyle)
+{
+    RenderObject* curr = this;
+    RenderStyle* styleToUse = 0;
+    ETextDecoration currDecs = TDNONE;
+    Color resultColor;
+    do {
+        styleToUse = curr->style(firstlineStyle);
+        currDecs = styleToUse->textDecoration();
+        resultColor = decorationColor(styleToUse);
+        // Parameter 'decorations' is cast as an int to enable the bitwise operations below.
+        if (currDecs) {
+            if (currDecs & UNDERLINE) {
+                decorations &= ~UNDERLINE;
+                underline = resultColor;
+            }
+            if (currDecs & OVERLINE) {
+                decorations &= ~OVERLINE;
+                overline = resultColor;
+            }
+            if (currDecs & LINE_THROUGH) {
+                decorations &= ~LINE_THROUGH;
+                linethrough = resultColor;
+            }
+        }
+        if (curr->isRubyText())
+            return;
+        curr = curr->parent();
+        if (curr && curr->isAnonymousBlock() && toRenderBlock(curr)->continuation())
+            curr = toRenderBlock(curr)->continuation();
+    } while (curr && decorations && (!quirksMode || !curr->node() ||
+                                     (!curr->node()->hasTagName(aTag) && !curr->node()->hasTagName(fontTag))));
+
+    // If we bailed out, use the element we bailed out at (typically a <font> or <a> element).
+    if (decorations && curr) {
+        styleToUse = curr->style(firstlineStyle);
+        resultColor = decorationColor(styleToUse);
+        if (decorations & UNDERLINE)
+            underline = resultColor;
+        if (decorations & OVERLINE)
+            overline = resultColor;
+        if (decorations & LINE_THROUGH)
+            linethrough = resultColor;
+    }
+}
+
+void RenderObject::addAnnotatedRegions(Vector<AnnotatedRegionValue>& regions)
+{
+    // Convert the style regions to absolute coordinates.
+    if (style()->visibility() != VISIBLE || !isBox())
+        return;
+    
+    RenderBox* box = toRenderBox(this);
+    FloatPoint absPos = localToAbsolute();
+
+    if (style()->getDraggableRegionMode() == DraggableRegionNone)
+        return;
+    AnnotatedRegionValue region;
+    region.draggable = style()->getDraggableRegionMode() == DraggableRegionDrag;
+    region.bounds = LayoutRect(absPos.x(), absPos.y(), box->width(), box->height());
+    regions.append(region);
+}
+
+void RenderObject::collectAnnotatedRegions(Vector<AnnotatedRegionValue>& 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;
+
+    addAnnotatedRegions(regions);
+    for (RenderObject* curr = firstChild(); curr; curr = curr->nextSibling())
+        curr->collectAnnotatedRegions(regions);
+}
+
+bool RenderObject::willRenderImage(CachedImage*)
+{
+    // Without visibility we won't render (and therefore don't care about animation).
+    if (style()->visibility() != VISIBLE)
+        return false;
+
+    // We will not render a new image when Active DOM is suspended
+    if (document()->activeDOMObjectsAreSuspended())
+        return false;
+
+    // If we're not in a window (i.e., we're dormant from being in a background tab)
+    // then we don't want to render either.
+    return !document()->view()->isOffscreen();
+}
+
+int RenderObject::maximalOutlineSize(PaintPhase p) const
+{
+    if (p != PaintPhaseOutline && p != PaintPhaseSelfOutline && p != PaintPhaseChildOutlines)
+        return 0;
+    return view()->maximalOutlineSize();
+}
+
+int RenderObject::caretMinOffset() const
+{
+    return 0;
+}
+
+int RenderObject::caretMaxOffset() const
+{
+    if (isReplaced())
+        return node() ? max(1U, node()->childNodeCount()) : 1;
+    if (isHR())
+        return 1;
+    return 0;
+}
+
+int RenderObject::previousOffset(int current) const
+{
+    return current - 1;
+}
+
+int RenderObject::previousOffsetForBackwardDeletion(int current) const
+{
+    return current - 1;
+}
+
+int RenderObject::nextOffset(int current) const
+{
+    return current + 1;
+}
+
+void RenderObject::adjustRectForOutlineAndShadow(LayoutRect& rect) const
+{
+    int outlineSize = outlineStyleForRepaint()->outlineSize();
+    if (const ShadowData* boxShadow = style()->boxShadow()) {
+        boxShadow->adjustRectForShadow(rect, outlineSize);
+        return;
+    }
+
+    rect.inflate(outlineSize);
+}
+
+AnimationController* RenderObject::animation() const
+{
+    return frame()->animation();
+}
+
+void RenderObject::imageChanged(CachedImage* image, const IntRect* rect)
+{
+    imageChanged(static_cast<WrappedImagePtr>(image), rect);
+}
+
+Element* RenderObject::offsetParent() const
+{
+    if (isRoot() || isBody())
+        return 0;
+
+    if (isOutOfFlowPositioned() && style()->position() == FixedPosition)
+        return 0;
+
+    // If A is an area HTML element which has a map HTML element somewhere in the ancestor
+    // chain return the nearest ancestor map HTML element and stop this algorithm.
+    // FIXME: Implement!
+
+    // FIXME: Figure out the right behavior for elements inside a flow thread.
+    // https://bugs.webkit.org/show_bug.cgi?id=113276
+
+    float effectiveZoom = style()->effectiveZoom();
+    Node* node = 0;
+    for (RenderObject* ancestor = parent(); ancestor; ancestor = ancestor->parent()) {
+        node = ancestor->node();
+
+        // Spec: http://www.w3.org/TR/cssom-view/#offset-attributes
+
+        if (!node)
+            continue;
+
+        if (ancestor->isPositioned())
+            break;
+
+        if (node->hasTagName(HTMLNames::bodyTag))
+            break;
+
+        if (!isPositioned() && (node->hasTagName(tableTag) || node->hasTagName(tdTag) || node->hasTagName(thTag)))
+            break;
+
+        // Webkit specific extension where offsetParent stops at zoom level changes.
+        if (effectiveZoom != ancestor->style()->effectiveZoom())
+            break;
+    }
+
+    return node && node->isElementNode() ? toElement(node) : 0;
+}
+
+VisiblePosition RenderObject::createVisiblePosition(int offset, EAffinity affinity)
+{
+    // If this is a non-anonymous renderer in an editable area, then it's simple.
+    if (Node* node = nonPseudoNode()) {
+        if (!node->rendererIsEditable()) {
+            // If it can be found, we prefer a visually equivalent position that is editable. 
+            Position position = createLegacyEditingPosition(node, offset);
+            Position candidate = position.downstream(CanCrossEditingBoundary);
+            if (candidate.deprecatedNode()->rendererIsEditable())
+                return VisiblePosition(candidate, affinity);
+            candidate = position.upstream(CanCrossEditingBoundary);
+            if (candidate.deprecatedNode()->rendererIsEditable())
+                return VisiblePosition(candidate, affinity);
+        }
+        // FIXME: Eliminate legacy editing positions
+        return VisiblePosition(createLegacyEditingPosition(node, offset), affinity);
+    }
+
+    // We don't want to cross the boundary between editable and non-editable
+    // regions of the document, but that is either impossible or at least
+    // extremely unlikely in any normal case because we stop as soon as we
+    // find a single non-anonymous renderer.
+
+    // Find a nearby non-anonymous renderer.
+    RenderObject* child = this;
+    while (RenderObject* parent = child->parent()) {
+        // Find non-anonymous content after.
+        RenderObject* renderer = child;
+        while ((renderer = renderer->nextInPreOrder(parent))) {
+            if (Node* node = renderer->nonPseudoNode())
+                return VisiblePosition(firstPositionInOrBeforeNode(node), DOWNSTREAM);
+        }
+
+        // Find non-anonymous content before.
+        renderer = child;
+        while ((renderer = renderer->previousInPreOrder())) {
+            if (renderer == parent)
+                break;
+            if (Node* node = renderer->nonPseudoNode())
+                return VisiblePosition(lastPositionInOrAfterNode(node), DOWNSTREAM);
+        }
+
+        // Use the parent itself unless it too is anonymous.
+        if (Node* node = parent->nonPseudoNode())
+            return VisiblePosition(firstPositionInOrBeforeNode(node), DOWNSTREAM);
+
+        // Repeat at the next level up.
+        child = parent;
+    }
+
+    // Everything was anonymous. Give up.
+    return VisiblePosition();
+}
+
+VisiblePosition RenderObject::createVisiblePosition(const Position& position)
+{
+    if (position.isNotNull())
+        return VisiblePosition(position);
+
+    ASSERT(!node());
+    return createVisiblePosition(0, DOWNSTREAM);
+}
+
+CursorDirective RenderObject::getCursor(const LayoutPoint&, Cursor&) const
+{
+    return SetCursorBasedOnStyle;
+}
+
+bool RenderObject::canUpdateSelectionOnRootLineBoxes()
+{
+    if (needsLayout())
+        return false;
+
+    RenderBlock* containingBlock = this->containingBlock();
+    return containingBlock ? !containingBlock->needsLayout() : true;
+}
+
+// We only create "generated" child renderers like one for first-letter if:
+// - the firstLetterBlock can have children in the DOM and
+// - the block doesn't have any special assumption on its text children.
+// This correctly prevents form controls from having such renderers.
+bool RenderObject::canHaveGeneratedChildren() const
+{
+    return canHaveChildren();
+}
+
+bool RenderObject::canBeReplacedWithInlineRunIn() const
+{
+    return true;
+}
+
+void RenderObject::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, PlatformMemoryTypes::Rendering);
+    info.addMember(m_style, "style");
+    info.addWeakPointer(m_node);
+    info.addWeakPointer(m_parent);
+    info.addWeakPointer(m_previous);
+    info.addWeakPointer(m_next);
+
+    info.setCustomAllocation(true);
+}
+
+#if ENABLE(SVG)
+
+RenderSVGResourceContainer* RenderObject::toRenderSVGResourceContainer()
+{
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
+void RenderObject::setNeedsBoundariesUpdate()
+{
+    if (RenderObject* renderer = parent())
+        renderer->setNeedsBoundariesUpdate();
+}
+
+FloatRect RenderObject::objectBoundingBox() const
+{
+    ASSERT_NOT_REACHED();
+    return FloatRect();
+}
+
+FloatRect RenderObject::strokeBoundingBox() const
+{
+    ASSERT_NOT_REACHED();
+    return FloatRect();
+}
+
+// Returns the smallest rectangle enclosing all of the painted content
+// respecting clipping, masking, filters, opacity, stroke-width and markers
+FloatRect RenderObject::repaintRectInLocalCoordinates() const
+{
+    ASSERT_NOT_REACHED();
+    return FloatRect();
+}
+
+AffineTransform RenderObject::localTransform() const
+{
+    static const AffineTransform identity;
+    return identity;
+}
+
+const AffineTransform& RenderObject::localToParentTransform() const
+{
+    static const AffineTransform identity;
+    return identity;
+}
+
+bool RenderObject::nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint&, HitTestAction)
+{
+    ASSERT_NOT_REACHED();
+    return false;
+}
+
+#endif // ENABLE(SVG)
+
+} // namespace WebCore
+
+#ifndef NDEBUG
+
+void showTree(const WebCore::RenderObject* object)
+{
+    if (object)
+        object->showTreeForThis();
+}
+
+void showLineTree(const WebCore::RenderObject* object)
+{
+    if (object)
+        object->showLineTreeForThis();
+}
+
+void showRenderTree(const WebCore::RenderObject* object1)
+{
+    showRenderTree(object1, 0);
+}
+
+void showRenderTree(const WebCore::RenderObject* object1, const WebCore::RenderObject* object2)
+{
+    if (object1) {
+        const WebCore::RenderObject* root = object1;
+        while (root->parent())
+            root = root->parent();
+        root->showRenderTreeAndMark(object1, "*", object2, "-", 0);
+    }
+}
+
+#endif
diff --git a/Source/core/rendering/RenderObject.h b/Source/core/rendering/RenderObject.h
new file mode 100644
index 0000000..243ec1b
--- /dev/null
+++ b/Source/core/rendering/RenderObject.h
@@ -0,0 +1,1340 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ *           (C) 2000 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2000 Dirk Mueller (mueller@kde.org)
+ *           (C) 2004 Allan Sandfeld Jensen (kde@carewolf.com)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2012 Apple Inc. All rights reserved.
+ * Copyright (C) 2009 Google 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 "core/dom/DocumentStyleSheetCollection.h"
+#include "core/dom/Element.h"
+#include "core/editing/TextAffinity.h"
+#include "core/loader/cache/CachedImageClient.h"
+#include "core/platform/graphics/FloatQuad.h"
+#include "core/platform/graphics/LayoutRect.h"
+#include "core/platform/graphics/transforms/TransformationMatrix.h"
+#include "core/rendering/PaintPhase.h"
+#include "core/rendering/RenderObjectChildList.h"
+#include "core/rendering/ScrollBehavior.h"
+#include "core/rendering/style/RenderStyle.h"
+#include "core/rendering/style/StyleInheritedData.h"
+#include <wtf/HashSet.h>
+#include <wtf/StackStats.h>
+#include <wtf/UnusedParam.h>
+
+namespace WebCore {
+
+class AffineTransform;
+class AnimationController;
+class Cursor;
+class Document;
+class HitTestLocation;
+class HitTestResult;
+class InlineBox;
+class InlineFlowBox;
+class OverlapTestRequestClient;
+class Path;
+class Position;
+class PseudoStyleRequest;
+class RenderBoxModelObject;
+class RenderInline;
+class RenderBlock;
+class RenderFlowThread;
+class RenderGeometryMap;
+class RenderLayer;
+class RenderLayerModelObject;
+class RenderNamedFlowThread;
+class RenderTable;
+class RenderTheme;
+class TransformState;
+class VisiblePosition;
+#if ENABLE(SVG)
+class RenderSVGResourceContainer;
+#endif
+
+struct PaintInfo;
+
+enum CursorDirective {
+    SetCursorBasedOnStyle,
+    SetCursor,
+    DoNotSetCursor
+};
+
+enum HitTestFilter {
+    HitTestAll,
+    HitTestSelf,
+    HitTestDescendants
+};
+
+enum HitTestAction {
+    HitTestBlockBackground,
+    HitTestChildBlockBackground,
+    HitTestChildBlockBackgrounds,
+    HitTestFloat,
+    HitTestForeground
+};
+
+// Sides used when drawing borders and outlines. The values should run clockwise from top.
+enum BoxSide {
+    BSTop,
+    BSRight,
+    BSBottom,
+    BSLeft
+};
+
+enum MarkingBehavior {
+    MarkOnlyThis,
+    MarkContainingBlockChain,
+};
+
+enum MapCoordinatesMode {
+    IsFixed = 1 << 0,
+    UseTransforms = 1 << 1,
+    ApplyContainerFlip = 1 << 2
+};
+typedef unsigned MapCoordinatesFlags;
+
+const int caretWidth = 1;
+
+struct AnnotatedRegionValue {
+    bool operator==(const AnnotatedRegionValue& o) const
+    {
+        return draggable == o.draggable && bounds == o.bounds;
+    }
+    bool operator!=(const AnnotatedRegionValue& o) const
+    {
+        return !(*this == o);
+    }
+
+    LayoutRect bounds;
+    bool draggable;
+};
+
+typedef WTF::HashSet<const RenderObject*> RenderObjectAncestorLineboxDirtySet;
+
+#ifndef NDEBUG
+const int showTreeCharacterOffset = 39;
+#endif
+
+// Base class for all rendering tree objects.
+class RenderObject : public CachedImageClient, public MemoryReporterTag {
+    friend class RenderBlock;
+    friend class RenderLayer;
+    friend class RenderObjectChildList;
+public:
+    // Anonymous objects should pass the document as their node, and they will then automatically be
+    // marked as anonymous in the constructor.
+    explicit RenderObject(Node*);
+    virtual ~RenderObject();
+
+    RenderTheme* theme() const;
+
+    virtual const char* renderName() const = 0;
+
+#ifndef NDEBUG
+    String debugName() const;
+#endif
+
+    RenderObject* parent() const { return m_parent; }
+    bool isDescendantOf(const RenderObject*) const;
+
+    RenderObject* previousSibling() const { return m_previous; }
+    RenderObject* nextSibling() const { return m_next; }
+
+    // FIXME: These should be renamed slowFirstChild, slowLastChild, etc.
+    // to discourage their use. The virtualChildren() call inside these
+    // can be slow for hot code paths.
+    // Currently, some subclasses like RenderBlock, override these NON-virtual
+    // functions to make these fast when we already have a more specific pointer type.
+    RenderObject* firstChild() const
+    {
+        if (const RenderObjectChildList* children = virtualChildren())
+            return children->firstChild();
+        return 0;
+    }
+    RenderObject* lastChild() const
+    {
+        if (const RenderObjectChildList* children = virtualChildren())
+            return children->lastChild();
+        return 0;
+    }
+
+    virtual RenderObjectChildList* virtualChildren() { return 0; }
+    virtual const RenderObjectChildList* virtualChildren() const { return 0; }
+
+    RenderObject* nextInPreOrder() const;
+    RenderObject* nextInPreOrder(const RenderObject* stayWithin) const;
+    RenderObject* nextInPreOrderAfterChildren() const;
+    RenderObject* nextInPreOrderAfterChildren(const RenderObject* stayWithin) const;
+    RenderObject* previousInPreOrder() const;
+    RenderObject* previousInPreOrder(const RenderObject* stayWithin) const;
+    RenderObject* childAt(unsigned) const;
+
+    RenderObject* firstLeafChild() const;
+    RenderObject* lastLeafChild() const;
+
+    // The following six functions are used when the render tree hierarchy changes to make sure layers get
+    // properly added and removed.  Since containership can be implemented by any subclass, and since a hierarchy
+    // can contain a mixture of boxes and other object types, these functions need to be in the base class.
+    RenderLayer* enclosingLayer() const;
+    void addLayers(RenderLayer* parentLayer);
+    void removeLayers(RenderLayer* parentLayer);
+    void moveLayers(RenderLayer* oldParent, RenderLayer* newParent);
+    RenderLayer* findNextLayer(RenderLayer* parentLayer, RenderObject* startPoint, bool checkParent = true);
+
+    // Scrolling is a RenderBox concept, however some code just cares about recursively scrolling our enclosing ScrollableArea(s).
+    bool scrollRectToVisible(const LayoutRect&, const ScrollAlignment& alignX = ScrollAlignment::alignCenterIfNeeded, const ScrollAlignment& alignY = ScrollAlignment::alignCenterIfNeeded);
+
+    // Convenience function for getting to the nearest enclosing box of a RenderObject.
+    RenderBox* enclosingBox() const;
+    RenderBoxModelObject* enclosingBoxModelObject() const;
+
+    // Function to return our enclosing flow thread if we are contained inside one. This
+    // function follows the containing block chain.
+    RenderFlowThread* flowThreadContainingBlock() const
+    {
+        if (flowThreadState() == NotInsideFlowThread)
+            return 0;
+        return locateFlowThreadContainingBlock();
+    }
+
+    RenderNamedFlowThread* renderNamedFlowThreadWrapper() const;
+
+    virtual bool isEmpty() const { return firstChild() == 0; }
+
+#ifndef NDEBUG
+    void setHasAXObject(bool flag) { m_hasAXObject = flag; }
+    bool hasAXObject() const { return m_hasAXObject; }
+
+    // Helper class forbidding calls to setNeedsLayout() during its lifetime.
+    class SetLayoutNeededForbiddenScope {
+    public:
+        explicit SetLayoutNeededForbiddenScope(RenderObject*, bool isForbidden = true);
+        ~SetLayoutNeededForbiddenScope();
+    private:
+        RenderObject* m_renderObject;
+        bool m_preexistingForbidden;
+    };
+#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();
+    
+    // RenderObject tree manipulation
+    //////////////////////////////////////////
+    virtual bool canHaveChildren() const { return virtualChildren(); }
+    virtual bool canHaveGeneratedChildren() const;
+    virtual bool isChildAllowed(RenderObject*, RenderStyle*) const { return true; }
+    virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0);
+    virtual void addChildIgnoringContinuation(RenderObject* newChild, RenderObject* beforeChild = 0) { return addChild(newChild, beforeChild); }
+    virtual void removeChild(RenderObject*);
+    virtual bool createsAnonymousWrapper() const { return false; }
+    //////////////////////////////////////////
+
+    virtual void reportMemoryUsage(MemoryObjectInfo*) const;
+
+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;
+        
+        // Only update if our flow thread state is different from our new parent and if we're not a RenderFlowThread.
+        // A RenderFlowThread is always considered to be inside itself, so it never has to change its state
+        // in response to parent changes.
+        FlowThreadState newState = parent ? parent->flowThreadState() : NotInsideFlowThread;
+        if (newState != flowThreadState() && !isRenderFlowThread())
+            setFlowThreadStateIncludingDescendants(newState);
+    }
+
+    //////////////////////////////////////////
+private:
+#ifndef NDEBUG
+    bool isSetNeedsLayoutForbidden() const { return m_setNeedsLayoutForbidden; }
+    void setNeedsLayoutIsForbidden(bool flag) { m_setNeedsLayoutForbidden = flag; }
+#endif
+
+    void addAbsoluteRectForLayer(LayoutRect& result);
+    void setLayerNeedsFullRepaint();
+    void setLayerNeedsFullRepaintForPositionedMovementLayout();
+    bool requiresAnonymousTableWrappers(const RenderObject*) const;
+
+public:
+#ifndef NDEBUG
+    void showTreeForThis() const;
+    void showRenderTreeForThis() const;
+    void showLineTreeForThis() const;
+
+    void showRenderObject() const;
+    // We don't make printedCharacters an optional parameter so that
+    // showRenderObject can be called from gdb easily.
+    void showRenderObject(int printedCharacters) const;
+    void showRenderTreeAndMark(const RenderObject* markedObject1 = 0, const char* markedLabel1 = 0, const RenderObject* markedObject2 = 0, const char* markedLabel2 = 0, int depth = 0) const;
+#endif
+
+    static RenderObject* createObject(Element*, RenderStyle*);
+
+    // Overloaded new operator.  Derived classes must override operator new
+    // in order to allocate out of the RenderArena.
+    void* operator new(size_t, RenderArena*);
+
+    // 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(); }
+
+    bool isPseudoElement() const { return node() && node()->isPseudoElement(); }
+
+    virtual bool isBR() const { return false; }
+    virtual bool isBlockFlow() const { return false; }
+    virtual bool isBoxModelObject() const { return false; }
+    virtual bool isCounter() const { return false; }
+    virtual bool isDialog() const { return false; }
+    virtual bool isQuote() const { return false; }
+
+    virtual bool isDetailsMarker() const { return false; }
+    virtual bool isEmbeddedObject() const { return false; }
+    virtual bool isFieldset() const { return false; }
+    virtual bool isFileUploadControl() 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 isLayerModelObject() 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 isMeter() const { return false; }
+    virtual bool isProgress() const { return false; }
+    virtual bool isRenderBlock() const { return false; }
+    virtual bool isRenderLazyBlock() const { return false; }
+    virtual bool isRenderButton() const { return false; }
+    virtual bool isRenderIFrame() const { return false; }
+    virtual bool isRenderImage() const { return false; }
+    virtual bool isRenderInline() const { return false; }
+    virtual bool isRenderPart() const { return false; }
+    virtual bool isRenderRegion() const { return false; }
+    virtual bool isRenderView() const { return false; }
+    virtual bool isReplica() const { return false; }
+
+    virtual bool isRuby() const { return false; }
+    virtual bool isRubyBase() const { return false; }
+    virtual bool isRubyRun() const { return false; }
+    virtual bool isRubyText() const { return false; }
+
+    virtual bool isSlider() const { return false; }
+    virtual bool isSliderThumb() const { return false; }
+    virtual bool isTable() const { return false; }
+    virtual bool isTableCell() const { return false; }
+    virtual bool isRenderTableCol() const { return false; }
+    virtual bool isTableCaption() const { return false; }
+    virtual bool isTableRow() const { return false; }
+    virtual bool isTableSection() const { return false; }
+    virtual bool isTextControl() const { return false; }
+    virtual bool isTextArea() const { return false; }
+    virtual bool isTextField() const { return false; }
+    virtual bool isVideo() const { return false; }
+    virtual bool isWidget() const { return false; }
+    virtual bool isCanvas() const { return false; }
+    virtual bool isRenderFullScreen() const { return false; }
+    virtual bool isRenderFullScreenPlaceholder() const { return false; }
+
+    virtual bool isRenderGrid() const { return false; }
+
+    virtual bool isRenderFlowThread() const { return false; }
+    virtual bool isRenderNamedFlowThread() const { return false; }
+    bool isInFlowRenderFlowThread() const { return isRenderFlowThread() && !isOutOfFlowPositioned(); }
+    bool isOutOfFlowRenderFlowThread() const { return isRenderFlowThread() && isOutOfFlowPositioned(); }
+
+    virtual bool isRenderMultiColumnBlock() const { return false; }
+    virtual bool isRenderMultiColumnSet() const { return false; }
+
+    virtual bool isRenderScrollbarPart() const { return false; }
+
+    bool isRoot() const { return document()->documentElement() == m_node; }
+    bool isBody() const;
+    bool isHR() const;
+    bool isLegend() const;
+
+    bool isHTMLMarquee() const;
+
+    bool isTablePart() const { return isTableCell() || isRenderTableCol() || isTableCaption() || isTableRow() || isTableSection(); }
+
+    inline bool isBeforeContent() const;
+    inline bool isAfterContent() const;
+    inline bool isBeforeOrAfterContent() const;
+    static inline bool isBeforeContent(const RenderObject* obj) { return obj && obj->isBeforeContent(); }
+    static inline bool isAfterContent(const RenderObject* obj) { return obj && obj->isAfterContent(); }
+    static inline bool isBeforeOrAfterContent(const RenderObject* obj) { return obj && obj->isBeforeOrAfterContent(); }
+
+    bool hasCounterNodeMap() const { return m_bitfields.hasCounterNodeMap(); }
+    void setHasCounterNodeMap(bool hasCounterNodeMap) { m_bitfields.setHasCounterNodeMap(hasCounterNodeMap); }
+    bool everHadLayout() const { return m_bitfields.everHadLayout(); }
+
+    bool childrenInline() const { return m_bitfields.childrenInline(); }
+    void setChildrenInline(bool b) { m_bitfields.setChildrenInline(b); }
+    bool hasColumns() const { return m_bitfields.hasColumns(); }
+    void setHasColumns(bool b = true) { m_bitfields.setHasColumns(b); }
+
+    bool ancestorLineBoxDirty() const { return s_ancestorLineboxDirtySet && s_ancestorLineboxDirtySet->contains(this); }
+    void setAncestorLineBoxDirty(bool b = true)
+    {
+        if (b) {
+            if (!s_ancestorLineboxDirtySet)
+                s_ancestorLineboxDirtySet = new RenderObjectAncestorLineboxDirtySet;
+            s_ancestorLineboxDirtySet->add(this);
+            setNeedsLayout(true);
+        } else if (s_ancestorLineboxDirtySet) {
+            s_ancestorLineboxDirtySet->remove(this);
+            if (s_ancestorLineboxDirtySet->isEmpty()) {
+                delete s_ancestorLineboxDirtySet;
+                s_ancestorLineboxDirtySet = 0;
+            }
+        }
+    }
+
+    enum FlowThreadState {
+        NotInsideFlowThread = 0,
+        InsideOutOfFlowThread = 1,
+        InsideInFlowThread = 2,
+    };
+
+    void setFlowThreadStateIncludingDescendants(FlowThreadState);
+
+    FlowThreadState flowThreadState() const { return m_bitfields.flowThreadState(); }
+    void setFlowThreadState(FlowThreadState state) { m_bitfields.setFlowThreadState(state); }
+
+    virtual bool requiresForcedStyleRecalcPropagation() const { return false; }
+
+#if ENABLE(SVG)
+    // FIXME: Until all SVG renders can be subclasses of RenderSVGModelObject we have
+    // to add SVG renderer methods to RenderObject with an ASSERT_NOT_REACHED() default implementation.
+    virtual bool isSVGRoot() const { return false; }
+    virtual bool isSVGContainer() const { return false; }
+    virtual bool isSVGTransformableContainer() const { return false; }
+    virtual bool isSVGViewportContainer() const { return false; }
+    virtual bool isSVGGradientStop() const { return false; }
+    virtual bool isSVGHiddenContainer() const { return false; }
+    virtual bool isSVGPath() const { return false; }
+    virtual bool isSVGShape() const { return false; }
+    virtual bool isSVGText() const { return false; }
+    virtual bool isSVGTextPath() const { return false; }
+    virtual bool isSVGInline() const { return false; }
+    virtual bool isSVGInlineText() const { return false; }
+    virtual bool isSVGImage() const { return false; }
+    virtual bool isSVGForeignObject() const { return false; }
+    virtual bool isSVGResourceContainer() const { return false; }
+    virtual bool isSVGResourceFilter() const { return false; }
+    virtual bool isSVGResourceFilterPrimitive() const { return false; }
+
+    virtual RenderSVGResourceContainer* toRenderSVGResourceContainer();
+
+    // FIXME: Those belong into a SVG specific base-class for all renderers (see above)
+    // Unfortunately we don't have such a class yet, because it's not possible for all renderers
+    // to inherit from RenderSVGObject -> RenderObject (some need RenderBlock inheritance for instance)
+    virtual void setNeedsTransformUpdate() { }
+    virtual void setNeedsBoundariesUpdate();
+    virtual bool needsBoundariesUpdate() { return false; }
+
+    // Per SVG 1.1 objectBoundingBox ignores clipping, masking, filter effects, opacity and stroke-width.
+    // This is used for all computation of objectBoundingBox relative units and by SVGLocatable::getBBox().
+    // NOTE: Markers are not specifically ignored here by SVG 1.1 spec, but we ignore them
+    // since stroke-width is ignored (and marker size can depend on stroke-width).
+    // objectBoundingBox is returned local coordinates.
+    // The name objectBoundingBox is taken from the SVG 1.1 spec.
+    virtual FloatRect objectBoundingBox() const;
+    virtual FloatRect strokeBoundingBox() const;
+
+    // Returns the smallest rectangle enclosing all of the painted content
+    // respecting clipping, masking, filters, opacity, stroke-width and markers
+    virtual FloatRect repaintRectInLocalCoordinates() const;
+
+    // This only returns the transform="" value from the element
+    // most callsites want localToParentTransform() instead.
+    virtual AffineTransform localTransform() const;
+
+    // Returns the full transform mapping from local coordinates to local coords for the parent SVG renderer
+    // This includes any viewport transforms and x/y offsets as well as the transform="" value off the element.
+    virtual const AffineTransform& localToParentTransform() const;
+
+    // SVG uses FloatPoint precise hit testing, and passes the point in parent
+    // coordinates instead of in repaint container coordinates.  Eventually the
+    // rest of the rendering tree will move to a similar model.
+    virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction);
+#endif
+
+    bool isAnonymous() const { return m_bitfields.isAnonymous(); }
+    bool isAnonymousBlock() const
+    {
+        // This function is kept in sync with anonymous block creation conditions in
+        // RenderBlock::createAnonymousBlock(). This includes creating an anonymous
+        // RenderBlock having a BLOCK or BOX display. Other classes such as RenderTextFragment
+        // are not RenderBlocks and will return false. See https://bugs.webkit.org/show_bug.cgi?id=56709. 
+        return isAnonymous() && (style()->display() == BLOCK || style()->display() == BOX) && style()->styleType() == NOPSEUDO && isRenderBlock() && !isListMarker() && !isRenderFlowThread()
+            && !isRenderFullScreen()
+            && !isRenderFullScreenPlaceholder();
+    }
+    bool isAnonymousColumnsBlock() const { return style()->specifiesColumns() && isAnonymousBlock(); }
+    bool isAnonymousColumnSpanBlock() const { return style()->columnSpan() && isAnonymousBlock(); }
+    bool isElementContinuation() const { return node() && node()->renderer() != this; }
+    bool isInlineElementContinuation() const { return isElementContinuation() && isInline(); }
+    bool isBlockElementContinuation() const { return isElementContinuation() && !isInline(); }
+    virtual RenderBoxModelObject* virtualContinuation() const { return 0; }
+
+    bool isFloating() const { return m_bitfields.floating(); }
+
+    bool isOutOfFlowPositioned() const { return m_bitfields.isOutOfFlowPositioned(); } // absolute or fixed positioning
+    bool isInFlowPositioned() const { return m_bitfields.isRelPositioned() || m_bitfields.isStickyPositioned(); } // relative or sticky positioning
+    bool hasPaintOffset() const
+    {
+        bool positioned = isInFlowPositioned();
+        // Shape outside on a float can reposition the float in much the
+        // same way as relative positioning, so treat it as such.
+        positioned = positioned || isFloatingWithShapeOutside();
+        return positioned;
+    }
+    bool isRelPositioned() const { return m_bitfields.isRelPositioned(); } // relative positioning
+    bool isStickyPositioned() const { return m_bitfields.isStickyPositioned(); }
+    bool isPositioned() const { return m_bitfields.isPositioned(); }
+
+    bool isText() const  { return m_bitfields.isText(); }
+    bool isBox() const { return m_bitfields.isBox(); }
+    bool isInline() const { return m_bitfields.isInline(); } // inline object
+    bool isRunIn() const { return style()->display() == RUN_IN; } // run-in object
+    bool isDragging() const { return m_bitfields.isDragging(); }
+    bool isReplaced() const { return m_bitfields.isReplaced(); } // a "replaced" element (see CSS)
+    bool isHorizontalWritingMode() const { return m_bitfields.horizontalWritingMode(); }
+
+    bool hasLayer() const { return m_bitfields.hasLayer(); }
+
+    enum BoxDecorationState {
+        NoBoxDecorations,
+        HasBoxDecorationsAndBackgroundObscurationStatusInvalid,
+        HasBoxDecorationsAndBackgroundIsKnownToBeObscured,
+        HasBoxDecorationsAndBackgroundMayBeVisible,
+    };
+    bool hasBoxDecorations() const { return m_bitfields.boxDecorationState() != NoBoxDecorations; }
+    bool backgroundIsKnownToBeObscured();
+    bool borderImageIsLoadedAndCanBeRendered() const;
+    bool mustRepaintBackgroundOrBorder() const;
+    bool hasBackground() const { return style()->hasBackground(); }
+    bool hasEntirelyFixedBackground() const;
+
+    bool needsLayout() const
+    {
+        return m_bitfields.needsLayout() || m_bitfields.normalChildNeedsLayout() || m_bitfields.posChildNeedsLayout()
+            || m_bitfields.needsSimplifiedNormalFlowLayout() || m_bitfields.needsPositionedMovementLayout();
+    }
+
+    bool selfNeedsLayout() const { return m_bitfields.needsLayout(); }
+    bool needsPositionedMovementLayout() const { return m_bitfields.needsPositionedMovementLayout(); }
+    bool needsPositionedMovementLayoutOnly() const
+    {
+        return m_bitfields.needsPositionedMovementLayout() && !m_bitfields.needsLayout() && !m_bitfields.normalChildNeedsLayout()
+            && !m_bitfields.posChildNeedsLayout() && !m_bitfields.needsSimplifiedNormalFlowLayout();
+    }
+
+    bool posChildNeedsLayout() const { return m_bitfields.posChildNeedsLayout(); }
+    bool needsSimplifiedNormalFlowLayout() const { return m_bitfields.needsSimplifiedNormalFlowLayout(); }
+    bool normalChildNeedsLayout() const { return m_bitfields.normalChildNeedsLayout(); }
+    
+    bool preferredLogicalWidthsDirty() const { return m_bitfields.preferredLogicalWidthsDirty(); }
+
+    bool isSelectionBorder() const;
+
+    bool hasClip() const { return isOutOfFlowPositioned() && style()->hasClip(); }
+    bool hasOverflowClip() const { return m_bitfields.hasOverflowClip(); }
+    bool hasClipOrOverflowClip() const { return hasClip() || hasOverflowClip(); }
+
+    bool hasTransform() const { return m_bitfields.hasTransform(); }
+    bool hasMask() const { return style() && style()->hasMask(); }
+    bool hasClipPath() const { return style() && style()->clipPath(); }
+    bool hasHiddenBackface() const { return style() && style()->backfaceVisibility() == BackfaceVisibilityHidden; }
+
+    bool hasFilter() const { return style() && style()->hasFilter(); }
+
+#if ENABLE(CSS_COMPOSITING)
+    bool hasBlendMode() const { return style() && style()->hasBlendMode(); }
+#else
+    bool hasBlendMode() const { return false; }
+#endif
+
+    inline bool preservesNewline() const;
+
+    // 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(PseudoId, RenderStyle* parentStyle = 0) const;
+    PassRefPtr<RenderStyle> getUncachedPseudoStyle(const PseudoStyleRequest&, RenderStyle* parentStyle = 0, RenderStyle* ownStyle = 0) const;
+    
+    virtual void updateDragState(bool dragOn);
+
+    RenderView* view() const { return document()->renderView(); };
+
+    // Returns true if this renderer is rooted, and optionally returns the hosting view (the root of the hierarchy).
+    bool isRooted(RenderView** = 0) const;
+
+    Node* node() const { return isAnonymous() ? 0 : m_node; }
+    Node* nonPseudoNode() const { return isPseudoElement() ? 0 : node(); }
+
+    // FIXME: Why does RenderWidget need this?
+    void clearNode() { m_node = 0; }
+
+    // Returns the styled node that caused the generation of this renderer.
+    // This is the same as node() except for renderers of :before and :after
+    // pseudo elements for which their parent node is returned.
+    Node* generatingNode() const { return isPseudoElement() ? node()->parentOrShadowHostNode() : node(); }
+
+    Document* document() const { return m_node->document(); }
+    Frame* frame() const { return document()->frame(); }
+
+    bool hasOutlineAnnotation() const;
+    bool hasOutline() const { return style()->hasOutline() || hasOutlineAnnotation(); }
+
+    // Returns the object containing this one. Can be different from parent for positioned elements.
+    // If repaintContainer and repaintContainerSkipped are not null, on return *repaintContainerSkipped
+    // is true if the renderer returned is an ancestor of repaintContainer.
+    RenderObject* container(const RenderLayerModelObject* repaintContainer = 0, bool* repaintContainerSkipped = 0) const;
+
+    virtual RenderObject* hoverAncestor() const { return parent(); }
+
+    Element* offsetParent() const;
+
+    void markContainingBlocksForLayout(bool scheduleRelayout = true, RenderObject* newRoot = 0);
+    void setNeedsLayout(bool needsLayout, MarkingBehavior = MarkContainingBlockChain);
+    void setChildNeedsLayout(bool childNeedsLayout, MarkingBehavior = MarkContainingBlockChain);
+    void setNeedsPositionedMovementLayout();
+    void setNeedsSimplifiedNormalFlowLayout();
+    void setPreferredLogicalWidthsDirty(bool, MarkingBehavior = MarkContainingBlockChain);
+    void invalidateContainerPreferredLogicalWidths();
+    
+    void setNeedsLayoutAndPrefWidthsRecalc()
+    {
+        setNeedsLayout(true);
+        setPreferredLogicalWidthsDirty(true);
+    }
+
+    void setPositionState(EPosition position)
+    {
+        ASSERT((position != AbsolutePosition && position != FixedPosition) || isBox());
+        m_bitfields.setPositionedState(position);
+    }
+    void clearPositionedState() { m_bitfields.clearPositionedState(); }
+
+    void setFloating(bool b = true) { m_bitfields.setFloating(b); }
+    void setInline(bool b = true) { m_bitfields.setIsInline(b); }
+
+    void setHasBoxDecorations(bool = true);
+    void invalidateBackgroundObscurationStatus();
+    virtual bool computeBackgroundIsKnownToBeObscured() { return false; }
+
+    void setIsText() { m_bitfields.setIsText(true); }
+    void setIsBox() { m_bitfields.setIsBox(true); }
+    void setReplaced(bool b = true) { m_bitfields.setIsReplaced(b); }
+    void setHorizontalWritingMode(bool b = true) { m_bitfields.setHorizontalWritingMode(b); }
+    void setHasOverflowClip(bool b = true) { m_bitfields.setHasOverflowClip(b); }
+    void setHasLayer(bool b = true) { m_bitfields.setHasLayer(b); }
+    void setHasTransform(bool b = true) { m_bitfields.setHasTransform(b); }
+    void setHasReflection(bool b = true) { m_bitfields.setHasReflection(b); }
+
+    void scheduleRelayout();
+
+    void updateFillImages(const FillLayer*, const FillLayer*);
+    void updateImage(StyleImage*, StyleImage*);
+
+    virtual void paint(PaintInfo&, const LayoutPoint&);
+
+    // Recursive function that computes the size and position of this object and all its descendants.
+    virtual void layout();
+
+    /* This function performs a layout only if one is needed. */
+    void layoutIfNeeded() { if (needsLayout()) layout(); }
+    
+    // used for element state updates that cannot be fixed with a
+    // repaint and do not need a relayout
+    virtual void updateFromElement() { }
+
+    virtual void addAnnotatedRegions(Vector<AnnotatedRegionValue>&);
+    void collectAnnotatedRegions(Vector<AnnotatedRegionValue>&);
+
+    bool isComposited() const;
+
+    bool hitTest(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestFilter = HitTestAll);
+    virtual void updateHitTestResult(HitTestResult&, const LayoutPoint&);
+    virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction);
+
+    virtual VisiblePosition positionForPoint(const LayoutPoint&);
+    VisiblePosition createVisiblePosition(int offset, EAffinity);
+    VisiblePosition createVisiblePosition(const Position&);
+
+    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>);
+
+    // Set the style of the object if it's generated content.
+    void setPseudoStyle(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> style) { m_style = style; }
+
+    // returns the containing block level element for this element.
+    RenderBlock* containingBlock() const;
+
+    bool canContainFixedPositionObjects() const
+    {
+        return isRenderView() || (hasTransform() && isRenderBlock())
+#if ENABLE(SVG)
+                || isSVGForeignObject()
+#endif
+                || isOutOfFlowRenderFlowThread();
+    }
+
+    // Convert the given local point to absolute coordinates
+    // FIXME: Temporary. If UseTransforms is true, take transforms into account. Eventually localToAbsolute() will always be transform-aware.
+    FloatPoint localToAbsolute(const FloatPoint& localPoint = FloatPoint(), MapCoordinatesFlags = 0) const;
+    FloatPoint absoluteToLocal(const FloatPoint&, MapCoordinatesFlags = 0) const;
+
+    // Convert a local quad to absolute coordinates, taking transforms into account.
+    FloatQuad localToAbsoluteQuad(const FloatQuad& quad, MapCoordinatesFlags mode = 0, bool* wasFixed = 0) const
+    {
+        return localToContainerQuad(quad, 0, mode, wasFixed);
+    }
+    // Convert an absolute quad to local coordinates.
+    FloatQuad absoluteToLocalQuad(const FloatQuad&, MapCoordinatesFlags mode = 0) const;
+
+    // Convert a local quad into the coordinate system of container, taking transforms into account.
+    FloatQuad localToContainerQuad(const FloatQuad&, const RenderLayerModelObject* repaintContainer, MapCoordinatesFlags = 0, bool* wasFixed = 0) const;
+    FloatPoint localToContainerPoint(const FloatPoint&, const RenderLayerModelObject* repaintContainer, MapCoordinatesFlags = 0, bool* wasFixed = 0) const;
+
+    // Return the offset from the container() renderer (excluding transforms). In multi-column layout,
+    // different offsets apply at different points, so return the offset that applies to the given point.
+    virtual LayoutSize offsetFromContainer(RenderObject*, const LayoutPoint&, bool* offsetDependsOnPoint = 0) const;
+    // Return the offset from an object up the container() chain. Asserts that none of the intermediate objects have transforms.
+    LayoutSize offsetFromAncestorContainer(RenderObject*) const;
+    
+    virtual void absoluteRects(Vector<IntRect>&, const LayoutPoint&) const { }
+
+    // FIXME: useTransforms should go away eventually
+    IntRect absoluteBoundingBoxRect(bool useTransform = true) const;
+    IntRect absoluteBoundingBoxRectIgnoringTransforms() const { return absoluteBoundingBoxRect(false); }
+
+    // Build an array of quads in absolute coords for line boxes
+    virtual void absoluteQuads(Vector<FloatQuad>&, bool* /*wasFixed*/ = 0) const { }
+
+    virtual void absoluteFocusRingQuads(Vector<FloatQuad>&);
+
+    static FloatRect absoluteBoundingBoxRectForRange(const Range*);
+
+    // the rect that will be painted if this object is passed as the paintingRoot
+    LayoutRect paintingRootRect(LayoutRect& topLevelRect);
+
+    virtual LayoutUnit minPreferredLogicalWidth() const { return 0; }
+    virtual LayoutUnit maxPreferredLogicalWidth() const { return 0; }
+
+    RenderStyle* style() const { return m_style.get(); }
+    RenderStyle* firstLineStyle() const { return document()->styleSheetCollection()->usesFirstLineRules() ? cachedFirstLineStyle() : style(); }
+    RenderStyle* style(bool firstLine) const { return firstLine ? firstLineStyle() : style(); }
+
+    // Used only by Element::pseudoStyleCacheIsInvalid to get a first line style based off of a
+    // given new style, without accessing the cache.
+    PassRefPtr<RenderStyle> uncachedFirstLineStyle(RenderStyle*) const;
+
+    // Anonymous blocks that are part of of a continuation chain will return their inline continuation's outline style instead.
+    // This is typically only relevant when repainting.
+    virtual RenderStyle* outlineStyleForRepaint() const { return style(); }
+    
+    virtual CursorDirective getCursor(const LayoutPoint&, Cursor&) const;
+
+    void getTextDecorationColors(int decorations, Color& underline, Color& overline, Color& linethrough, bool quirksMode = false, bool firstlineStyle = false);
+
+    // Return the RenderLayerModelObject in the container chain which is responsible for painting this object, or 0
+    // if painting is root-relative. This is the container that should be passed to the 'forRepaint'
+    // methods.
+    RenderLayerModelObject* containerForRepaint() const;
+    // Actually do the repaint of rect r for this object which has been computed in the coordinate space
+    // of repaintContainer. If repaintContainer is 0, repaint via the view.
+    void repaintUsingContainer(const RenderLayerModelObject* repaintContainer, const IntRect&) const;
+    
+    // Repaint the entire object.  Called when, e.g., the color of a border changes, or when a border
+    // style changes.
+    void repaint() const;
+
+    // Repaint a specific subrectangle within a given object.  The rect |r| is in the object's coordinate space.
+    void repaintRectangle(const LayoutRect&) const;
+
+    // Repaint only if our old bounds and new bounds are different. The caller may pass in newBounds and newOutlineBox if they are known.
+    bool repaintAfterLayoutIfNeeded(const RenderLayerModelObject* repaintContainer, const LayoutRect& oldBounds, const LayoutRect& oldOutlineBox, const LayoutRect* newBoundsPtr = 0, const LayoutRect* newOutlineBoxPtr = 0);
+
+    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.
+    LayoutRect absoluteClippedOverflowRect() const
+    {
+        return clippedOverflowRectForRepaint(0);
+    }
+    IntRect pixelSnappedAbsoluteClippedOverflowRect() const;
+    virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const;
+    virtual LayoutRect rectWithOutlineForRepaint(const RenderLayerModelObject* repaintContainer, LayoutUnit outlineWidth) const;
+    virtual LayoutRect outlineBoundsForRepaint(const RenderLayerModelObject* /*repaintContainer*/, const RenderGeometryMap* = 0) const { return LayoutRect(); }
+
+    // Given a rect in the object's coordinate space, compute a rect suitable for repainting
+    // that rect in view coordinates.
+    void computeAbsoluteRepaintRect(LayoutRect& r, bool fixed = false) const
+    {
+        computeRectForRepaint(0, r, fixed);
+    }
+    // Given a rect in the object's coordinate space, compute a rect suitable for repainting
+    // that rect in the coordinate space of repaintContainer.
+    virtual void computeRectForRepaint(const RenderLayerModelObject* repaintContainer, LayoutRect&, bool fixed = false) const;
+    virtual void computeFloatRectForRepaint(const RenderLayerModelObject* repaintContainer, FloatRect& repaintRect, bool fixed = false) const;
+
+    // If multiple-column layout results in applying an offset to the given point, add the same
+    // offset to the given size.
+    virtual void adjustForColumns(LayoutSize&, const LayoutPoint&) const { }
+    LayoutSize offsetForColumns(const LayoutPoint& point) const
+    {
+        LayoutSize offset;
+        adjustForColumns(offset, point);
+        return offset;
+    }
+
+    virtual unsigned int length() const { return 1; }
+
+    bool isFloatingOrOutOfFlowPositioned() const { return (isFloating() || isOutOfFlowPositioned()); }
+    bool isFloatingWithShapeOutside() const { return isBox() && isFloating() && style()->shapeOutside(); }
+
+    bool isTransparent() const { return style()->opacity() < 1.0f; }
+    float opacity() const { return style()->opacity(); }
+
+    bool hasReflection() const { return m_bitfields.hasReflection(); }
+
+    // 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).
+    SelectionState selectionState() const { return m_bitfields.selectionState(); }
+    virtual void setSelectionState(SelectionState state) { m_bitfields.setSelectionState(state); }
+    inline void setSelectionStateIfNeeded(SelectionState);
+    bool canUpdateSelectionOnRootLineBoxes();
+
+    // A single rectangle that encompasses all of the selected objects within this object.  Used to determine the tightest
+    // possible bounding box for the selection.
+    LayoutRect selectionRect(bool clipToVisibleContent = true) { return selectionRectForRepaint(0, clipToVisibleContent); }
+    virtual LayoutRect selectionRectForRepaint(const RenderLayerModelObject* /*repaintContainer*/, bool /*clipToVisibleContent*/ = true) { return LayoutRect(); }
+
+    virtual bool canBeSelectionLeaf() const { return false; }
+    bool hasSelectedChildren() const { return selectionState() != SelectionNone; }
+
+    // Obtains the selection colors that should be used when painting a selection.
+    Color selectionBackgroundColor() const;
+    Color selectionForegroundColor() const;
+    Color selectionEmphasisMarkColor() const;
+
+    // Whether or not a given block needs to paint selection gaps.
+    virtual bool shouldPaintSelectionGaps() const { return false; }
+
+    /**
+     * Returns the local coordinates of the caret within this render object.
+     * @param caretOffset zero-based offset determining position within the render object.
+     * @param extraWidthToEndOfLine optional out arg to give extra width to end of line -
+     * useful for character range rect computations
+     */
+    virtual LayoutRect localCaretRect(InlineBox*, int caretOffset, LayoutUnit* extraWidthToEndOfLine = 0);
+
+    // 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;
+
+    void destroyAndCleanupAnonymousWrappers();
+    virtual void destroy();
+
+    // Virtual function helpers for the deprecated Flexible Box Layout (display: -webkit-box).
+    virtual bool isDeprecatedFlexibleBox() const { return false; }
+    virtual bool isStretchingChildren() const { return false; }
+
+    // Virtual function helper for the new FlexibleBox Layout (display: -webkit-flex).
+    virtual bool isFlexibleBox() const { return false; }
+
+    bool isFlexibleBoxIncludingDeprecated() const
+    {
+        return isFlexibleBox() || isDeprecatedFlexibleBox();
+    }
+
+    virtual bool isCombineText() const { return false; }
+
+    virtual int caretMinOffset() const;
+    virtual int caretMaxOffset() const;
+
+    virtual int previousOffset(int current) const;
+    virtual int previousOffsetForBackwardDeletion(int current) const;
+    virtual int nextOffset(int current) const;
+
+    virtual void imageChanged(CachedImage*, const IntRect* = 0);
+    virtual void imageChanged(WrappedImagePtr, const IntRect* = 0) { }
+    virtual bool willRenderImage(CachedImage*);
+
+    void selectionStartEnd(int& spos, int& epos) const;
+    
+    void remove() { if (parent()) parent()->removeChild(this); }
+
+    AnimationController* animation() const;
+
+    bool visibleToHitTestRequest(const HitTestRequest& request) const { return style()->visibility() == VISIBLE && (request.ignorePointerEventsNone() || style()->pointerEvents() != PE_NONE); }
+    bool visibleToHitTesting() const { return style()->visibility() == VISIBLE && style()->pointerEvents() != PE_NONE; }
+
+    // Map points and quads through elements, potentially via 3d transforms. You should never need to call these directly; use
+    // localToAbsolute/absoluteToLocal methods instead.
+    virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = 0) const;
+    virtual void mapAbsoluteToLocalPoint(MapCoordinatesFlags, TransformState&) const;
+
+    // Pushes state onto RenderGeometryMap about how to map coordinates from this renderer to its container, or ancestorToStopAt (whichever is encountered first).
+    // Returns the renderer which was mapped to (container or ancestorToStopAt).
+    virtual const RenderObject* pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap&) const;
+    
+    bool shouldUseTransformFromContainer(const RenderObject* container) const;
+    void getTransformFromContainer(const RenderObject* container, const LayoutSize& offsetInContainer, TransformationMatrix&) const;
+    
+    // return true if this object requires a new stacking context
+    bool createsGroup() const { return isTransparent() || hasMask() || hasFilter() || hasBlendMode(); } 
+    
+    virtual void addFocusRingRects(Vector<IntRect>&, const LayoutPoint& /* additionalOffset */, const RenderLayerModelObject* /* paintContainer */ = 0) { };
+
+    LayoutRect absoluteOutlineBounds() const
+    {
+        return outlineBoundsForRepaint(0);
+    }
+
+    // Return the renderer whose background style is used to paint the root background. Should only be called on the renderer for which isRoot() is true.
+    RenderObject* rendererForRootBackground();
+
+    RespectImageOrientationEnum shouldRespectImageOrientation() const;
+
+protected:
+    inline bool layerCreationAllowedForSubtree() const;
+
+    // Overrides should call the superclass at the end
+    virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle);
+    // Overrides should call the superclass at the start
+    virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+    void propagateStyleToAnonymousChildren(bool blockChildrenOnly = false);
+
+    void drawLineForBoxSide(GraphicsContext*, int x1, int y1, int x2, int y2, BoxSide,
+                            Color, EBorderStyle, int adjbw1, int adjbw2, bool antialias = false);
+
+    void paintFocusRing(PaintInfo&, const LayoutPoint&, RenderStyle*);
+    void paintOutline(PaintInfo&, const LayoutRect&);
+    void addPDFURLRect(GraphicsContext*, const LayoutRect&);
+    
+    virtual LayoutRect viewRect() const;
+
+    void adjustRectForOutlineAndShadow(LayoutRect&) const;
+
+    void clearLayoutRootIfNeeded() const;
+    virtual void willBeDestroyed();
+    void arenaDelete(RenderArena*, void* objectBase);
+
+    virtual bool canBeReplacedWithInlineRunIn() const;
+
+    virtual void insertedIntoTree();
+    virtual void willBeRemovedFromTree();
+
+    void setDocumentForAnonymous(Document* document) { ASSERT(isAnonymous()); m_node = document; }
+
+private:
+    RenderFlowThread* locateFlowThreadContainingBlock() const;
+    void removeFromRenderFlowThread();
+    void removeFromRenderFlowThreadRecursive(RenderFlowThread*);
+
+    RenderStyle* cachedFirstLineStyle() const;
+    StyleDifference adjustStyleDifference(StyleDifference, unsigned contextSensitiveProperties) const;
+
+    Color selectionColor(int colorProperty) const;
+
+#ifndef NDEBUG
+    void checkBlockPositionedObjectsNeedLayout();
+#endif
+
+    RefPtr<RenderStyle> m_style;
+
+    Node* m_node;
+
+    RenderObject* m_parent;
+    RenderObject* m_previous;
+    RenderObject* m_next;
+
+    static RenderObjectAncestorLineboxDirtySet* s_ancestorLineboxDirtySet;
+
+#ifndef NDEBUG
+    bool m_hasAXObject             : 1;
+    bool m_setNeedsLayoutForbidden : 1;
+#endif
+
+#define ADD_BOOLEAN_BITFIELD(name, Name) \
+    private:\
+        unsigned m_##name : 1;\
+    public:\
+        bool name() const { return m_##name; }\
+        void set##Name(bool name) { m_##name = name; }\
+
+    class RenderObjectBitfields {
+        enum PositionedState {
+            IsStaticallyPositioned = 0,
+            IsRelativelyPositioned = 1,
+            IsOutOfFlowPositioned = 2,
+            IsStickyPositioned = 3
+        };
+
+    public:
+        RenderObjectBitfields(Node* node)
+            : m_needsLayout(false)
+            , m_needsPositionedMovementLayout(false)
+            , m_normalChildNeedsLayout(false)
+            , m_posChildNeedsLayout(false)
+            , m_needsSimplifiedNormalFlowLayout(false)
+            , m_preferredLogicalWidthsDirty(false)
+            , m_floating(false)
+            , m_isAnonymous(!node)
+            , m_isText(false)
+            , m_isBox(false)
+            , m_isInline(true)
+            , m_isReplaced(false)
+            , m_horizontalWritingMode(true)
+            , m_isDragging(false)
+            , m_hasLayer(false)
+            , m_hasOverflowClip(false)
+            , m_hasTransform(false)
+            , m_hasReflection(false)
+            , m_hasCounterNodeMap(false)
+            , m_everHadLayout(false)
+            , m_childrenInline(false)
+            , m_hasColumns(false)
+            , m_positionedState(IsStaticallyPositioned)
+            , m_selectionState(SelectionNone)
+            , m_flowThreadState(NotInsideFlowThread)
+            , m_boxDecorationState(NoBoxDecorations)
+        {
+        }
+        
+        // 31 bits have been used here. There is one bit available.
+        ADD_BOOLEAN_BITFIELD(needsLayout, NeedsLayout);
+        ADD_BOOLEAN_BITFIELD(needsPositionedMovementLayout, NeedsPositionedMovementLayout);
+        ADD_BOOLEAN_BITFIELD(normalChildNeedsLayout, NormalChildNeedsLayout);
+        ADD_BOOLEAN_BITFIELD(posChildNeedsLayout, PosChildNeedsLayout);
+        ADD_BOOLEAN_BITFIELD(needsSimplifiedNormalFlowLayout, NeedsSimplifiedNormalFlowLayout);
+        ADD_BOOLEAN_BITFIELD(preferredLogicalWidthsDirty, PreferredLogicalWidthsDirty);
+        ADD_BOOLEAN_BITFIELD(floating, Floating);
+
+        ADD_BOOLEAN_BITFIELD(isAnonymous, IsAnonymous);
+        ADD_BOOLEAN_BITFIELD(isText, IsText);
+        ADD_BOOLEAN_BITFIELD(isBox, IsBox);
+        ADD_BOOLEAN_BITFIELD(isInline, IsInline);
+        ADD_BOOLEAN_BITFIELD(isReplaced, IsReplaced);
+        ADD_BOOLEAN_BITFIELD(horizontalWritingMode, HorizontalWritingMode);
+        ADD_BOOLEAN_BITFIELD(isDragging, IsDragging);
+
+        ADD_BOOLEAN_BITFIELD(hasLayer, HasLayer);
+        ADD_BOOLEAN_BITFIELD(hasOverflowClip, HasOverflowClip); // Set in the case of overflow:auto/scroll/hidden
+        ADD_BOOLEAN_BITFIELD(hasTransform, HasTransform);
+        ADD_BOOLEAN_BITFIELD(hasReflection, HasReflection);
+
+        ADD_BOOLEAN_BITFIELD(hasCounterNodeMap, HasCounterNodeMap);
+        ADD_BOOLEAN_BITFIELD(everHadLayout, EverHadLayout);
+
+        // from RenderBlock
+        ADD_BOOLEAN_BITFIELD(childrenInline, ChildrenInline);
+        ADD_BOOLEAN_BITFIELD(hasColumns, HasColumns);
+
+    private:
+        unsigned m_positionedState : 2; // PositionedState
+        unsigned m_selectionState : 3; // SelectionState
+        unsigned m_flowThreadState : 2; // FlowThreadState
+        unsigned m_boxDecorationState : 2; // BoxDecorationState
+
+    public:
+        bool isOutOfFlowPositioned() const { return m_positionedState == IsOutOfFlowPositioned; }
+        bool isRelPositioned() const { return m_positionedState == IsRelativelyPositioned; }
+        bool isStickyPositioned() const { return m_positionedState == IsStickyPositioned; }
+        bool isPositioned() const { return m_positionedState != IsStaticallyPositioned; }
+
+        void setPositionedState(int positionState)
+        {
+            // This mask maps FixedPosition and AbsolutePosition to IsOutOfFlowPositioned, saving one bit.
+            m_positionedState = static_cast<PositionedState>(positionState & 0x3);
+        }
+        void clearPositionedState() { m_positionedState = StaticPosition; }
+
+        ALWAYS_INLINE SelectionState selectionState() const { return static_cast<SelectionState>(m_selectionState); }
+        ALWAYS_INLINE void setSelectionState(SelectionState selectionState) { m_selectionState = selectionState; }
+        
+        ALWAYS_INLINE FlowThreadState flowThreadState() const { return static_cast<FlowThreadState>(m_flowThreadState); }
+        ALWAYS_INLINE void setFlowThreadState(FlowThreadState flowThreadState) { m_flowThreadState = flowThreadState; }
+
+        ALWAYS_INLINE BoxDecorationState boxDecorationState() const { return static_cast<BoxDecorationState>(m_boxDecorationState); }
+        ALWAYS_INLINE void setBoxDecorationState(BoxDecorationState boxDecorationState) { m_boxDecorationState = boxDecorationState; }
+    };
+
+#undef ADD_BOOLEAN_BITFIELD
+
+    RenderObjectBitfields m_bitfields;
+
+    void setNeedsPositionedMovementLayout(bool b) { m_bitfields.setNeedsPositionedMovementLayout(b); }
+    void setNormalChildNeedsLayout(bool b) { m_bitfields.setNormalChildNeedsLayout(b); }
+    void setPosChildNeedsLayout(bool b) { m_bitfields.setPosChildNeedsLayout(b); }
+    void setNeedsSimplifiedNormalFlowLayout(bool b) { m_bitfields.setNeedsSimplifiedNormalFlowLayout(b); }
+    void setIsDragging(bool b) { m_bitfields.setIsDragging(b); }
+    void setEverHadLayout(bool b) { m_bitfields.setEverHadLayout(b); }
+
+private:
+    // Store state between styleWillChange and styleDidChange
+    static bool s_affectsParentBlock;
+};
+
+inline bool RenderObject::documentBeingDestroyed() const
+{
+    return !document()->renderer();
+}
+
+inline bool RenderObject::isBeforeContent() const
+{
+    if (style()->styleType() != BEFORE)
+        return false;
+    // Text nodes don't have their own styles, so ignore the style on a text node.
+    if (isText() && !isBR())
+        return false;
+    return true;
+}
+
+inline bool RenderObject::isAfterContent() const
+{
+    if (style()->styleType() != AFTER)
+        return false;
+    // Text nodes don't have their own styles, so ignore the style on a text node.
+    if (isText() && !isBR())
+        return false;
+    return true;
+}
+
+inline bool RenderObject::isBeforeOrAfterContent() const
+{
+    return isBeforeContent() || isAfterContent();
+}
+
+inline void RenderObject::setNeedsLayout(bool needsLayout, MarkingBehavior markParents)
+{
+    bool alreadyNeededLayout = m_bitfields.needsLayout();
+    m_bitfields.setNeedsLayout(needsLayout);
+    if (needsLayout) {
+        ASSERT(!isSetNeedsLayoutForbidden());
+        if (!alreadyNeededLayout) {
+            if (markParents == MarkContainingBlockChain)
+                markContainingBlocksForLayout();
+            if (hasLayer())
+                setLayerNeedsFullRepaint();
+        }
+    } else {
+        setEverHadLayout(true);
+        setPosChildNeedsLayout(false);
+        setNeedsSimplifiedNormalFlowLayout(false);
+        setNormalChildNeedsLayout(false);
+        setNeedsPositionedMovementLayout(false);
+        setAncestorLineBoxDirty(false);
+#ifndef NDEBUG
+        checkBlockPositionedObjectsNeedLayout();
+#endif
+    }
+}
+
+inline void RenderObject::setChildNeedsLayout(bool childNeedsLayout, MarkingBehavior markParents)
+{
+    bool alreadyNeededLayout = normalChildNeedsLayout();
+    setNormalChildNeedsLayout(childNeedsLayout);
+    if (childNeedsLayout) {
+        ASSERT(!isSetNeedsLayoutForbidden());
+        if (!alreadyNeededLayout && markParents == MarkContainingBlockChain)
+            markContainingBlocksForLayout();
+    } else {
+        setPosChildNeedsLayout(false);
+        setNeedsSimplifiedNormalFlowLayout(false);
+        setNormalChildNeedsLayout(false);
+        setNeedsPositionedMovementLayout(false);
+    }
+}
+
+inline void RenderObject::setNeedsPositionedMovementLayout()
+{
+    bool alreadyNeededLayout = needsPositionedMovementLayout();
+    setNeedsPositionedMovementLayout(true);
+    ASSERT(!isSetNeedsLayoutForbidden());
+    if (!alreadyNeededLayout) {
+        markContainingBlocksForLayout();
+        if (hasLayer())
+            setLayerNeedsFullRepaintForPositionedMovementLayout();
+    }
+}
+
+inline void RenderObject::setNeedsSimplifiedNormalFlowLayout()
+{
+    bool alreadyNeededLayout = needsSimplifiedNormalFlowLayout();
+    setNeedsSimplifiedNormalFlowLayout(true);
+    ASSERT(!isSetNeedsLayoutForbidden());
+    if (!alreadyNeededLayout) {
+        markContainingBlocksForLayout();
+        if (hasLayer())
+            setLayerNeedsFullRepaint();
+    }
+}
+
+inline bool RenderObject::preservesNewline() const
+{
+#if ENABLE(SVG)
+    if (isSVGInlineText())
+        return false;
+#endif
+        
+    return style()->preserveNewline();
+}
+
+inline bool RenderObject::layerCreationAllowedForSubtree() const
+{
+#if ENABLE(SVG)
+    RenderObject* parentRenderer = parent();
+    while (parentRenderer) {
+        if (parentRenderer->isSVGHiddenContainer())
+            return false;
+        parentRenderer = parentRenderer->parent();
+    }
+#endif
+
+    return true;
+}
+
+inline void RenderObject::setSelectionStateIfNeeded(SelectionState state)
+{
+    if (selectionState() == state)
+        return;
+
+    setSelectionState(state);
+}
+
+inline void RenderObject::setHasBoxDecorations(bool b)
+{
+    if (!b) {
+        m_bitfields.setBoxDecorationState(NoBoxDecorations);
+        return;
+    }
+    if (hasBoxDecorations())
+        return;
+    m_bitfields.setBoxDecorationState(HasBoxDecorationsAndBackgroundObscurationStatusInvalid);
+}
+
+inline void RenderObject::invalidateBackgroundObscurationStatus()
+{
+    if (!hasBoxDecorations())
+        return;
+    m_bitfields.setBoxDecorationState(HasBoxDecorationsAndBackgroundObscurationStatusInvalid);
+}
+
+inline bool RenderObject::backgroundIsKnownToBeObscured()
+{
+    if (m_bitfields.boxDecorationState() == HasBoxDecorationsAndBackgroundObscurationStatusInvalid) {
+        BoxDecorationState boxDecorationState = computeBackgroundIsKnownToBeObscured() ? HasBoxDecorationsAndBackgroundIsKnownToBeObscured : HasBoxDecorationsAndBackgroundMayBeVisible;
+        m_bitfields.setBoxDecorationState(boxDecorationState);
+    }
+    return m_bitfields.boxDecorationState() == HasBoxDecorationsAndBackgroundIsKnownToBeObscured;
+}
+
+inline void makeMatrixRenderable(TransformationMatrix& matrix, bool has3DRendering)
+{
+    if (!has3DRendering)
+        matrix.makeAffine();
+}
+
+inline int adjustForAbsoluteZoom(int value, RenderObject* renderer)
+{
+    return adjustForAbsoluteZoom(value, renderer->style());
+}
+
+inline LayoutUnit adjustLayoutUnitForAbsoluteZoom(LayoutUnit value, RenderObject* renderer)
+{
+    return adjustLayoutUnitForAbsoluteZoom(value, renderer->style());
+}
+
+inline void adjustFloatQuadForAbsoluteZoom(FloatQuad& quad, RenderObject* renderer)
+{
+    float zoom = renderer->style()->effectiveZoom();
+    if (zoom != 1)
+        quad.scale(1 / zoom, 1 / zoom);
+}
+
+inline void adjustFloatRectForAbsoluteZoom(FloatRect& rect, RenderObject* renderer)
+{
+    float zoom = renderer->style()->effectiveZoom();
+    if (zoom != 1)
+        rect.scale(1 / zoom, 1 / zoom);
+}
+
+} // namespace WebCore
+
+#ifndef NDEBUG
+// Outside the WebCore namespace for ease of invocation from gdb.
+void showTree(const WebCore::RenderObject*);
+void showLineTree(const WebCore::RenderObject*);
+void showRenderTree(const WebCore::RenderObject* object1);
+// We don't make object2 an optional parameter so that showRenderTree
+// can be called from gdb easily.
+void showRenderTree(const WebCore::RenderObject* object1, const WebCore::RenderObject* object2);
+#endif
+
+#endif // RenderObject_h
diff --git a/Source/core/rendering/RenderObjectChildList.cpp b/Source/core/rendering/RenderObjectChildList.cpp
new file mode 100644
index 0000000..012bca5
--- /dev/null
+++ b/Source/core/rendering/RenderObjectChildList.cpp
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) Research In Motion Limited 2010. 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 "core/rendering/RenderObjectChildList.h"
+
+#include "core/accessibility/AXObjectCache.h"
+#include "core/rendering/RenderCounter.h"
+#include "core/rendering/RenderObject.h"
+#include "core/rendering/RenderView.h"
+#include "core/rendering/style/RenderStyle.h"
+
+namespace WebCore {
+
+void RenderObjectChildList::destroyLeftoverChildren()
+{
+    while (firstChild()) {
+        if (firstChild()->isListMarker() || (firstChild()->style()->styleType() == FIRST_LETTER && !firstChild()->isText()))
+            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 if (firstChild()->isRunIn() && firstChild()->node()) {
+            firstChild()->node()->setRenderer(0);
+            firstChild()->node()->setNeedsStyleRecalc();
+            firstChild()->destroy();
+        } 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 (firstChild()->node())
+                firstChild()->node()->setRenderer(0);
+            firstChild()->destroy();
+        }
+    }
+}
+
+RenderObject* RenderObjectChildList::removeChildNode(RenderObject* owner, RenderObject* oldChild, bool notifyRenderer)
+{
+    ASSERT(oldChild->parent() == owner);
+
+    if (oldChild->isFloatingOrOutOfFlowPositioned())
+        toRenderBox(oldChild)->removeFloatingOrPositionedChildFromBlockLists();
+
+    // 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 (!owner->documentBeingDestroyed() && notifyRenderer && oldChild->everHadLayout()) {
+        oldChild->setNeedsLayoutAndPrefWidthsRecalc();
+        // We only repaint |oldChild| if we have a RenderLayer as its visual overflow may not be tracked by its parent.
+        if (oldChild->isBody())
+            owner->view()->repaint();
+        else
+            oldChild->repaint();
+    }
+
+    // If we have a line box wrapper, delete it.
+    if (oldChild->isBox())
+        toRenderBox(oldChild)->deleteLineBoxWrapper();
+
+    // If oldChild is the start or end of the selection, then clear the selection to
+    // avoid problems of invalid pointers.
+    // FIXME: The FrameSelection should be responsible for this when it
+    // is notified of DOM mutations.
+    if (!owner->documentBeingDestroyed() && oldChild->isSelectionBorder())
+        owner->view()->clearSelection();
+
+    if (!owner->documentBeingDestroyed() && notifyRenderer)
+        oldChild->willBeRemovedFromTree();
+
+    // WARNING: There should be no code running between willBeRemovedFromTree and the actual removal below.
+    // This is needed to avoid race conditions where willBeRemovedFromTree would dirty the tree's structure
+    // and the code running here would force an untimely rebuilding, leaving |oldChild| dangling.
+
+    if (oldChild->previousSibling())
+        oldChild->previousSibling()->setNextSibling(oldChild->nextSibling());
+    if (oldChild->nextSibling())
+        oldChild->nextSibling()->setPreviousSibling(oldChild->previousSibling());
+
+    if (firstChild() == oldChild)
+        setFirstChild(oldChild->nextSibling());
+    if (lastChild() == oldChild)
+        setLastChild(oldChild->previousSibling());
+
+    oldChild->setPreviousSibling(0);
+    oldChild->setNextSibling(0);
+    oldChild->setParent(0);
+
+    // rendererRemovedFromTree walks the whole subtree. We can improve performance
+    // by skipping this step when destroying the entire tree.
+    if (!owner->documentBeingDestroyed())
+        RenderCounter::rendererRemovedFromTree(oldChild);
+
+    if (AXObjectCache* cache = owner->document()->existingAXObjectCache())
+        cache->childrenChanged(owner);
+
+    return oldChild;
+}
+
+void RenderObjectChildList::insertChildNode(RenderObject* owner, RenderObject* newChild, RenderObject* beforeChild, bool notifyRenderer)
+{
+    ASSERT(!newChild->parent());
+    ASSERT(!owner->isBlockFlow() || (!newChild->isTableSection() && !newChild->isTableRow() && !newChild->isTableCell()));
+
+    while (beforeChild && beforeChild->parent() && beforeChild->parent() != owner)
+        beforeChild = beforeChild->parent();
+
+    // This should never happen, but if it does prevent render tree corruption
+    // where child->parent() ends up being owner but child->nextSibling()->parent()
+    // is not owner.
+    if (beforeChild && beforeChild->parent() != owner) {
+        ASSERT_NOT_REACHED();
+        return;
+    }
+
+    newChild->setParent(owner);
+
+    if (firstChild() == beforeChild)
+        setFirstChild(newChild);
+
+    if (beforeChild) {
+        RenderObject* previousSibling = beforeChild->previousSibling();
+        if (previousSibling)
+            previousSibling->setNextSibling(newChild);
+        newChild->setPreviousSibling(previousSibling);
+        newChild->setNextSibling(beforeChild);
+        beforeChild->setPreviousSibling(newChild);
+    } else {
+        if (lastChild())
+            lastChild()->setNextSibling(newChild);
+        newChild->setPreviousSibling(lastChild());
+        setLastChild(newChild);
+    }
+
+    if (!owner->documentBeingDestroyed() && notifyRenderer)
+        newChild->insertedIntoTree();
+
+    if (!owner->documentBeingDestroyed()) {
+        RenderCounter::rendererSubtreeAttached(newChild);
+    }
+
+    newChild->setNeedsLayoutAndPrefWidthsRecalc();
+    if (!owner->normalChildNeedsLayout())
+        owner->setChildNeedsLayout(true); // We may supply the static position for an absolute positioned child.
+
+    if (AXObjectCache* cache = owner->document()->axObjectCache())
+        cache->childrenChanged(owner);
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderObjectChildList.h b/Source/core/rendering/RenderObjectChildList.h
new file mode 100644
index 0000000..b2804ec
--- /dev/null
+++ b/Source/core/rendering/RenderObjectChildList.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2009 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 RenderObjectChildList_h
+#define RenderObjectChildList_h
+
+#include <wtf/Forward.h>
+
+namespace WebCore {
+
+class RenderObject;
+
+class RenderObjectChildList {
+public:
+    RenderObjectChildList()
+        : m_firstChild(0)
+        , m_lastChild(0)
+    {
+    }
+
+    RenderObject* firstChild() const { return m_firstChild; }
+    RenderObject* lastChild() const { return m_lastChild; }
+
+    // FIXME: Temporary while RenderBox still exists. Eventually this will just happen during insert/append/remove methods on the child list, and nobody
+    // will need to manipulate firstChild or lastChild directly.
+    void setFirstChild(RenderObject* child) { m_firstChild = child; }
+    void setLastChild(RenderObject* child) { m_lastChild = child; }
+
+    void destroyLeftoverChildren();
+
+    RenderObject* removeChildNode(RenderObject* owner, RenderObject*, bool notifyRenderer = true);
+    void insertChildNode(RenderObject* owner, RenderObject* newChild, RenderObject* beforeChild, bool notifyRenderer = true);
+    void appendChildNode(RenderObject* owner, RenderObject* newChild, bool notifyRenderer = true)
+    {
+        insertChildNode(owner, newChild, 0, notifyRenderer);
+    }
+
+private:
+    RenderObject* m_firstChild;
+    RenderObject* m_lastChild;
+};
+
+} // namespace WebCore
+
+#endif // RenderObjectChildList_h
diff --git a/Source/core/rendering/RenderOverflow.h b/Source/core/rendering/RenderOverflow.h
new file mode 100644
index 0000000..c737eb3
--- /dev/null
+++ b/Source/core/rendering/RenderOverflow.h
@@ -0,0 +1,118 @@
+/*
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 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 RenderOverflow_h
+#define RenderOverflow_h
+
+#include "core/platform/graphics/LayoutRect.h"
+
+namespace WebCore
+{
+// RenderOverflow is a class for tracking content that spills out of a box.  This class is used by RenderBox and
+// InlineFlowBox.
+//
+// There are two types of overflow: layout overflow (which is expected to be reachable via scrolling mechanisms) and
+// visual overflow (which is not expected to be reachable via scrolling mechanisms).
+//
+// Layout overflow examples include other boxes that spill out of our box,  For example, in the inline case a tall image
+// could spill out of a line box. 
+    
+// Examples of visual overflow are shadows, text stroke (and eventually outline and border-image).
+
+// This object is allocated only when some of these fields have non-default values in the owning box.
+class RenderOverflow {
+    WTF_MAKE_NONCOPYABLE(RenderOverflow); WTF_MAKE_FAST_ALLOCATED;
+public:
+    RenderOverflow(const LayoutRect& layoutRect, const LayoutRect& visualRect) 
+        : m_layoutOverflow(layoutRect)
+        , m_visualOverflow(visualRect)
+    {
+    }
+   
+    const LayoutRect layoutOverflowRect() const { return m_layoutOverflow; }
+    const LayoutRect visualOverflowRect() const { return m_visualOverflow; }
+
+    void setMinYLayoutOverflow(LayoutUnit overflow) { m_layoutOverflow.setY(overflow); }
+    void setMaxYLayoutOverflow(LayoutUnit overflow) { m_layoutOverflow.setHeight(overflow - m_layoutOverflow.y()); }
+    void setMinXLayoutOverflow(LayoutUnit overflow) { m_layoutOverflow.setX(overflow); }
+    void setMaxXLayoutOverflow(LayoutUnit overflow) { m_layoutOverflow.setWidth(overflow - m_layoutOverflow.x()); }
+    
+    void setMinYVisualOverflow(LayoutUnit overflow) { m_visualOverflow.setY(overflow); }
+    void setMaxYVisualOverflow(LayoutUnit overflow) { m_visualOverflow.setHeight(overflow - m_layoutOverflow.y()); }
+    void setMinXVisualOverflow(LayoutUnit overflow) { m_visualOverflow.setX(overflow); }
+    void setMaxXVisualOverflow(LayoutUnit overflow) { m_visualOverflow.setWidth(overflow - m_layoutOverflow.x()); }
+    
+    void move(LayoutUnit dx, LayoutUnit dy);
+    
+    void addLayoutOverflow(const LayoutRect&);
+    void addVisualOverflow(const LayoutRect&);
+
+    void setLayoutOverflow(const LayoutRect&);
+    void setVisualOverflow(const LayoutRect&);
+
+    LayoutUnit layoutClientAfterEdge() const { return m_layoutClientAfterEdge; }
+    void setLayoutClientAfterEdge(LayoutUnit clientAfterEdge) { m_layoutClientAfterEdge = clientAfterEdge; }
+
+private:
+    LayoutRect m_layoutOverflow;
+    LayoutRect m_visualOverflow;
+
+    LayoutUnit m_layoutClientAfterEdge;
+};
+
+inline void RenderOverflow::move(LayoutUnit dx, LayoutUnit dy)
+{
+    m_layoutOverflow.move(dx, dy);
+    m_visualOverflow.move(dx, dy);
+}
+
+inline void RenderOverflow::addLayoutOverflow(const LayoutRect& rect)
+{
+    LayoutUnit maxX = std::max(rect.maxX(), m_layoutOverflow.maxX());
+    LayoutUnit maxY = std::max(rect.maxY(), m_layoutOverflow.maxY());
+    m_layoutOverflow.setX(std::min(rect.x(), m_layoutOverflow.x()));
+    m_layoutOverflow.setY(std::min(rect.y(), m_layoutOverflow.y()));
+    m_layoutOverflow.setWidth(maxX - m_layoutOverflow.x());
+    m_layoutOverflow.setHeight(maxY - m_layoutOverflow.y());
+}
+
+inline void RenderOverflow::addVisualOverflow(const LayoutRect& rect)
+{
+    LayoutUnit maxX = std::max(rect.maxX(), m_visualOverflow.maxX());
+    LayoutUnit maxY = std::max(rect.maxY(), m_visualOverflow.maxY());
+    m_visualOverflow.setX(std::min(rect.x(), m_visualOverflow.x()));
+    m_visualOverflow.setY(std::min(rect.y(), m_visualOverflow.y()));
+    m_visualOverflow.setWidth(maxX - m_visualOverflow.x());
+    m_visualOverflow.setHeight(maxY - m_visualOverflow.y());
+}
+
+inline void RenderOverflow::setLayoutOverflow(const LayoutRect& rect)
+{
+    m_layoutOverflow = rect;
+}
+
+inline void RenderOverflow::setVisualOverflow(const LayoutRect& rect)
+{
+    m_visualOverflow = rect;
+}
+
+} // namespace WebCore
+
+#endif // RenderOverflow_h
diff --git a/Source/core/rendering/RenderPart.cpp b/Source/core/rendering/RenderPart.cpp
new file mode 100644
index 0000000..dad2632
--- /dev/null
+++ b/Source/core/rendering/RenderPart.cpp
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 2000 Simon Hausmann <hausmann@kde.org>
+ *           (C) 2000 Stefan Schimanski (1Stein@gmx.de)
+ * Copyright (C) 2004, 2005, 2006, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) Research In Motion Limited 2011. 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 "core/rendering/RenderPart.h"
+
+#include "core/html/HTMLFrameElementBase.h"
+#include "core/page/Frame.h"
+#include "core/page/FrameView.h"
+#include "core/plugins/PluginView.h"
+#include "core/rendering/HitTestResult.h"
+#include "core/rendering/RenderLayer.h"
+#include "core/rendering/RenderView.h"
+#include "core/rendering/svg/RenderSVGRoot.h"
+
+using namespace std;
+
+namespace WebCore {
+
+RenderPart::RenderPart(Element* node)
+    : RenderWidget(node)
+{
+    setInline(false);
+}
+
+RenderPart::~RenderPart()
+{
+    clearWidget();
+}
+
+void RenderPart::setWidget(PassRefPtr<Widget> widget)
+{
+    if (widget == this->widget())
+        return;
+
+    RenderWidget::setWidget(widget);
+
+    // make sure the scrollbars are set correctly for restore
+    // ### find better fix
+    viewCleared();
+}
+
+void RenderPart::viewCleared()
+{
+}
+
+bool RenderPart::requiresLayer() const
+{
+    if (RenderWidget::requiresLayer())
+        return true;
+    
+    return requiresAcceleratedCompositing();
+}
+
+bool RenderPart::requiresAcceleratedCompositing() const
+{
+    // There are two general cases in which we can return true. First, if this is a plugin 
+    // renderer and the plugin has a layer, then we need a layer. Second, if this is 
+    // a renderer with a contentDocument and that document needs a layer, then we need
+    // a layer.
+    if (widget() && widget()->isPluginView() && toPluginView(widget())->platformLayer())
+        return true;
+
+    if (!node() || !node()->isFrameOwnerElement())
+        return false;
+
+    HTMLFrameOwnerElement* element = toFrameOwnerElement(node());
+    if (Document* contentDocument = element->contentDocument()) {
+        if (RenderView* view = contentDocument->renderView())
+            return view->usesCompositing();
+    }
+
+    return false;
+}
+
+bool RenderPart::needsPreferredWidthsRecalculation() const
+{
+    if (RenderWidget::needsPreferredWidthsRecalculation())
+        return true;
+    return embeddedContentBox();
+}
+
+RenderBox* RenderPart::embeddedContentBox() const
+{
+    if (!node() || !widget() || !widget()->isFrameView())
+        return 0;
+    return toFrameView(widget())->embeddedContentBox();
+}
+
+bool RenderPart::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action)
+{
+    if (!widget() || !widget()->isFrameView() || !request.allowsChildFrameContent())
+        return RenderWidget::nodeAtPoint(request, result, locationInContainer, accumulatedOffset, action);
+
+    FrameView* childFrameView = toFrameView(widget());
+    RenderView* childRoot = childFrameView->renderView();
+
+    if (childRoot) {
+        LayoutPoint adjustedLocation = accumulatedOffset + location();
+        LayoutPoint contentOffset = LayoutPoint(borderLeft() + paddingLeft(), borderTop() + paddingTop()) - childFrameView->scrollOffset();
+        HitTestLocation newHitTestLocation(locationInContainer, -adjustedLocation - contentOffset);
+        HitTestRequest newHitTestRequest(request.type() | HitTestRequest::ChildFrameHitTest);
+        HitTestResult childFrameResult(newHitTestLocation);
+
+        bool isInsideChildFrame = childRoot->hitTest(newHitTestRequest, newHitTestLocation, childFrameResult);
+
+        if (newHitTestLocation.isRectBasedTest())
+            result.append(childFrameResult);
+        else if (isInsideChildFrame)
+            result = childFrameResult;
+
+        if (isInsideChildFrame)
+            return true;
+
+        if (request.allowsFrameScrollbars()) {
+            // ScrollView scrollbars are not the same as RenderLayer scrollbars tested by RenderLayer::hitTestOverflowControls,
+            // so we need to test ScrollView scrollbars separately here.
+            // FIXME: Consider if this test could be done unconditionally.
+            Scrollbar* frameScrollbar = childFrameView->scrollbarAtPoint(newHitTestLocation.roundedPoint());
+            if (frameScrollbar)
+                result.setScrollbar(frameScrollbar);
+        }
+    }
+
+    return RenderWidget::nodeAtPoint(request, result, locationInContainer, accumulatedOffset, action);
+}
+
+}
diff --git a/Source/core/rendering/RenderPart.h b/Source/core/rendering/RenderPart.h
new file mode 100644
index 0000000..f86e61e
--- /dev/null
+++ b/Source/core/rendering/RenderPart.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 2000 Simon Hausmann <hausmann@kde.org>
+ * Copyright (C) 2006, 2009 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 RenderPart_h
+#define RenderPart_h
+
+#include "core/rendering/RenderWidget.h"
+
+namespace WebCore {
+
+// Renderer for frames via RenderFrameBase, and plug-ins via RenderEmbeddedObject.
+class RenderPart : public RenderWidget {
+public:
+    explicit RenderPart(Element*);
+    virtual ~RenderPart();
+
+    virtual void setWidget(PassRefPtr<Widget>) OVERRIDE FINAL;
+    virtual void viewCleared();
+
+    bool requiresAcceleratedCompositing() const;
+
+    virtual bool needsPreferredWidthsRecalculation() const OVERRIDE FINAL;
+    virtual RenderBox* embeddedContentBox() const OVERRIDE FINAL;
+
+    virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
+
+protected:
+    virtual bool requiresLayer() const;
+
+private:
+    virtual bool isRenderPart() const OVERRIDE FINAL { return true; }
+    virtual const char* renderName() const { return "RenderPart"; }
+};
+
+inline RenderPart* toRenderPart(RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isRenderPart());
+    return static_cast<RenderPart*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderPart(const RenderPart*);
+
+}
+
+#endif
diff --git a/Source/core/rendering/RenderProgress.cpp b/Source/core/rendering/RenderProgress.cpp
new file mode 100644
index 0000000..ef72caf
--- /dev/null
+++ b/Source/core/rendering/RenderProgress.cpp
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2010 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 "core/rendering/RenderProgress.h"
+
+#include "HTMLNames.h"
+#include "core/html/HTMLProgressElement.h"
+#include "core/rendering/PaintInfo.h"
+#include "core/rendering/RenderTheme.h"
+#include <wtf/CurrentTime.h>
+#include <wtf/RefPtr.h>
+
+using namespace std;
+
+namespace WebCore {
+
+RenderProgress::RenderProgress(HTMLElement* element)
+    : RenderBlock(element)
+    , m_position(HTMLProgressElement::InvalidPosition)
+    , m_animationStartTime(0)
+    , m_animationRepeatInterval(0)
+    , m_animationDuration(0)
+    , m_animating(false)
+    , m_animationTimer(this, &RenderProgress::animationTimerFired)
+{
+}
+
+RenderProgress::~RenderProgress()
+{
+}
+
+void RenderProgress::updateFromElement()
+{
+    HTMLProgressElement* element = progressElement();
+    if (m_position == element->position())
+        return;
+    m_position = element->position();
+
+    updateAnimationState();
+    repaint();
+    RenderBlock::updateFromElement();
+}
+
+bool RenderProgress::canBeReplacedWithInlineRunIn() const
+{
+    return false;
+}
+
+double RenderProgress::animationProgress() const
+{
+    return m_animating ? (fmod((currentTime() - m_animationStartTime), m_animationDuration) / m_animationDuration) : 0;
+}
+
+bool RenderProgress::isDeterminate() const
+{
+    return (HTMLProgressElement::IndeterminatePosition != position()
+            && HTMLProgressElement::InvalidPosition != position());
+}
+
+void RenderProgress::animationTimerFired(Timer<RenderProgress>*)
+{
+    repaint();
+    if (!m_animationTimer.isActive() && m_animating)
+        m_animationTimer.startOneShot(m_animationRepeatInterval);
+}
+
+void RenderProgress::updateAnimationState()
+{
+    m_animationDuration = theme()->animationDurationForProgressBar(this);
+    m_animationRepeatInterval = theme()->animationRepeatIntervalForProgressBar(this);
+
+    bool animating = style()->hasAppearance() && m_animationDuration > 0;
+    if (animating == m_animating)
+        return;
+
+    m_animating = animating;
+    if (m_animating) {
+        m_animationStartTime = currentTime();
+        m_animationTimer.startOneShot(m_animationRepeatInterval);
+    } else
+        m_animationTimer.stop();
+}
+
+HTMLProgressElement* RenderProgress::progressElement() const
+{
+    if (!node())
+        return 0;
+
+    if (isHTMLProgressElement(node()))
+        return toHTMLProgressElement(node());
+
+    ASSERT(node()->shadowHost());
+    return toHTMLProgressElement(node()->shadowHost());
+}    
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderProgress.h b/Source/core/rendering/RenderProgress.h
new file mode 100644
index 0000000..6484536
--- /dev/null
+++ b/Source/core/rendering/RenderProgress.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2009 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 RenderProgress_h
+#define RenderProgress_h
+
+#include "core/rendering/RenderBlock.h"
+
+namespace WebCore {
+
+class HTMLProgressElement;
+
+class RenderProgress FINAL : public RenderBlock {
+public:
+    explicit RenderProgress(HTMLElement*);
+    virtual ~RenderProgress();
+
+    double position() const { return m_position; }
+    double animationProgress() const;
+    double animationStartTime() const { return m_animationStartTime; }
+
+    bool isDeterminate() const;
+    virtual void updateFromElement();
+
+    HTMLProgressElement* progressElement() const;
+
+private:
+    virtual const char* renderName() const { return "RenderProgress"; }
+    virtual bool isProgress() const { return true; }
+    virtual bool requiresForcedStyleRecalcPropagation() const { return true; }
+    virtual bool canBeReplacedWithInlineRunIn() const OVERRIDE;
+
+    void animationTimerFired(Timer<RenderProgress>*);
+    void updateAnimationState();
+
+    double m_position;
+    double m_animationStartTime;
+    double m_animationRepeatInterval;
+    double m_animationDuration;
+    bool m_animating;
+    Timer<RenderProgress> m_animationTimer;
+};
+
+inline RenderProgress* toRenderProgress(RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isProgress());
+    return static_cast<RenderProgress*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderProgress(const RenderProgress*);
+
+} // namespace WebCore
+
+#endif // RenderProgress_h
diff --git a/Source/core/rendering/RenderQuote.cpp b/Source/core/rendering/RenderQuote.cpp
new file mode 100644
index 0000000..6586d04
--- /dev/null
+++ b/Source/core/rendering/RenderQuote.cpp
@@ -0,0 +1,353 @@
+/**
+ * Copyright (C) 2011 Nokia Inc.  All rights reserved.
+ * Copyright (C) 2012 Google 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 "core/rendering/RenderQuote.h"
+
+#include "core/rendering/RenderView.h"
+#include <wtf/text/AtomicString.h>
+
+#define U(x) ((const UChar*)L##x)
+
+namespace WebCore {
+
+RenderQuote::RenderQuote(Document* node, QuoteType quote)
+    : RenderText(node, StringImpl::empty())
+    , m_type(quote)
+    , m_depth(0)
+    , m_next(0)
+    , m_previous(0)
+    , m_attached(false)
+{
+}
+
+RenderQuote::~RenderQuote()
+{
+    ASSERT(!m_attached);
+    ASSERT(!m_next && !m_previous);
+}
+
+void RenderQuote::willBeDestroyed()
+{
+    detachQuote();
+    RenderText::willBeDestroyed();
+}
+
+void RenderQuote::willBeRemovedFromTree()
+{
+    RenderText::willBeRemovedFromTree();
+    detachQuote();
+}
+
+void RenderQuote::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
+{
+    RenderText::styleDidChange(diff, oldStyle);
+    setText(originalText());
+}
+
+typedef HashMap<AtomicString, const QuotesData*, CaseFoldingHash> QuotesMap;
+
+static const QuotesMap& quotesDataLanguageMap()
+{
+    DEFINE_STATIC_LOCAL(QuotesMap, staticQuotesMap, ());
+    if (staticQuotesMap.size())
+        return staticQuotesMap;
+
+    // Table of quotes from http://www.whatwg.org/specs/web-apps/current-work/multipage/rendering.html#quotes
+    #define QUOTES_LANG(lang, o1, c1, o2, c2) staticQuotesMap.set(lang, QuotesData::create(U(o1), U(c1), U(o2), U(c2)).leakRef())
+    QUOTES_LANG("af",            "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("agq",           "\x201e", "\x201d", "\x201a", "\x2019");
+    QUOTES_LANG("ak",            "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("am",            "\x00ab", "\x00bb", "\x2039", "\x203a");
+    QUOTES_LANG("ar",            "\x201d", "\x201c", "\x2019", "\x2018");
+    QUOTES_LANG("asa",           "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("az-Cyrl",       "\x00ab", "\x00bb", "\x2039", "\x203a");
+    QUOTES_LANG("bas",           "\x00ab", "\x00bb", "\x201e", "\x201c");
+    QUOTES_LANG("bem",           "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("bez",           "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("bg",            "\x201e", "\x201c", "\x201a", "\x2018");
+    QUOTES_LANG("bm",            "\x00ab", "\x00bb", "\x201c", "\x201d");
+    QUOTES_LANG("bn",            "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("br",            "\x00ab", "\x00bb", "\x2039", "\x203a");
+    QUOTES_LANG("brx",           "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("bs-Cyrl",       "\x201e", "\x201c", "\x201a", "\x2018");
+    QUOTES_LANG("ca",            "\x201c", "\x201d", "\x00ab", "\x00bb");
+    QUOTES_LANG("cgg",           "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("chr",           "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("cs",            "\x201e", "\x201c", "\x201a", "\x2018");
+    QUOTES_LANG("da",            "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("dav",           "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("de",            "\x201e", "\x201c", "\x201a", "\x2018");
+    QUOTES_LANG("de-CH",         "\x00ab", "\x00bb", "\x2039", "\x203a");
+    QUOTES_LANG("dje",           "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("dua",           "\x00ab", "\x00bb", "\x2018", "\x2019");
+    QUOTES_LANG("dyo",           "\x00ab", "\x00bb", "\x201c", "\x201d");
+    QUOTES_LANG("dz",            "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("ebu",           "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("ee",            "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("el",            "\x00ab", "\x00bb", "\x201c", "\x201d");
+    QUOTES_LANG("en",            "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("en-GB",         "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("es",            "\x201c", "\x201d", "\x00ab", "\x00bb");
+    QUOTES_LANG("et",            "\x201e", "\x201c", "\x201a", "\x2018");
+    QUOTES_LANG("eu",            "\x201c", "\x201d", "\x00ab", "\x00bb");
+    QUOTES_LANG("ewo",           "\x00ab", "\x00bb", "\x201c", "\x201d");
+    QUOTES_LANG("fa",            "\x00ab", "\x00bb", "\x2039", "\x203a");
+    QUOTES_LANG("ff",            "\x201e", "\x201d", "\x201a", "\x2019");
+    QUOTES_LANG("fi",            "\x201d", "\x201d", "\x2019", "\x2019");
+    QUOTES_LANG("fr",            "\x00ab", "\x00bb", "\x00ab", "\x00bb");
+    QUOTES_LANG("fr-CA",         "\x00ab", "\x00bb", "\x2039", "\x203a");
+    QUOTES_LANG("fr-CH",         "\x00ab", "\x00bb", "\x2039", "\x203a");
+    QUOTES_LANG("gsw",           "\x00ab", "\x00bb", "\x2039", "\x203a");
+    QUOTES_LANG("gu",            "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("guz",           "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("ha",            "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("he",            "\x0022", "\x0022", "\x0027", "\x0027");
+    QUOTES_LANG("hi",            "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("hr",            "\x201e", "\x201c", "\x201a", "\x2018");
+    QUOTES_LANG("hu",            "\x201e", "\x201d", "\x00bb", "\x00ab");
+    QUOTES_LANG("id",            "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("ig",            "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("it",            "\x00ab", "\x00bb", "\x201c", "\x201d");
+    QUOTES_LANG("ja",            "\x300c", "\x300d", "\x300e", "\x300f");
+    QUOTES_LANG("jgo",           "\x00ab", "\x00bb", "\x2039", "\x203a");
+    QUOTES_LANG("jmc",           "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("kab",           "\x00ab", "\x00bb", "\x201c", "\x201d");
+    QUOTES_LANG("kam",           "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("kde",           "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("kea",           "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("khq",           "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("ki",            "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("kkj",           "\x00ab", "\x00bb", "\x2039", "\x203a");
+    QUOTES_LANG("kln",           "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("km",            "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("kn",            "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("ko",            "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("ksb",           "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("ksf",           "\x00ab", "\x00bb", "\x2018", "\x2019");
+    QUOTES_LANG("lag",           "\x201d", "\x201d", "\x2019", "\x2019");
+    QUOTES_LANG("lg",            "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("ln",            "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("lo",            "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("lt",            "\x201e", "\x201c", "\x201e", "\x201c");
+    QUOTES_LANG("lu",            "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("luo",           "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("luy",           "\x201e", "\x201c", "\x201a", "\x2018");
+    QUOTES_LANG("lv",            "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("mas",           "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("mer",           "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("mfe",           "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("mg",            "\x00ab", "\x00bb", "\x201c", "\x201d");
+    QUOTES_LANG("mgo",           "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("mk",            "\x201e", "\x201c", "\x201a", "\x2018");
+    QUOTES_LANG("ml",            "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("mr",            "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("ms",            "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("mua",           "\x00ab", "\x00bb", "\x201c", "\x201d");
+    QUOTES_LANG("my",            "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("naq",           "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("nb",            "\x00ab", "\x00bb", "\x2018", "\x2019");
+    QUOTES_LANG("nd",            "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("nl",            "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("nmg",           "\x201e", "\x201d", "\x00ab", "\x00bb");
+    QUOTES_LANG("nn",            "\x00ab", "\x00bb", "\x2018", "\x2019");
+    QUOTES_LANG("nnh",           "\x00ab", "\x00bb", "\x201c", "\x201d");
+    QUOTES_LANG("nus",           "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("nyn",           "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("pl",            "\x201e", "\x201d", "\x00ab", "\x00bb");
+    QUOTES_LANG("pt",            "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("pt-PT",         "\x00ab", "\x00bb", "\x201c", "\x201d");
+    QUOTES_LANG("rn",            "\x201d", "\x201d", "\x2019", "\x2019");
+    QUOTES_LANG("ro",            "\x201e", "\x201d", "\x00ab", "\x00bb");
+    QUOTES_LANG("rof",           "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("ru",            "\x00ab", "\x00bb", "\x201e", "\x201c");
+    QUOTES_LANG("rw",            "\x00ab", "\x00bb", "\x2018", "\x2019");
+    QUOTES_LANG("rwk",           "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("saq",           "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("sbp",           "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("seh",           "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("ses",           "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("sg",            "\x00ab", "\x00bb", "\x201c", "\x201d");
+    QUOTES_LANG("shi",           "\x00ab", "\x00bb", "\x201e", "\x201d");
+    QUOTES_LANG("shi-Tfng",      "\x00ab", "\x00bb", "\x201e", "\x201d");
+    QUOTES_LANG("si",            "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("sk",            "\x201e", "\x201c", "\x201a", "\x2018");
+    QUOTES_LANG("sl",            "\x201e", "\x201c", "\x201a", "\x2018");
+    QUOTES_LANG("sn",            "\x201d", "\x201d", "\x2019", "\x2019");
+    QUOTES_LANG("so",            "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("sq",            "\x201e", "\x201c", "\x201a", "\x2018");
+    QUOTES_LANG("sr",            "\x201e", "\x201c", "\x201a", "\x2018");
+    QUOTES_LANG("sr-Latn",       "\x201e", "\x201c", "\x201a", "\x2018");
+    QUOTES_LANG("sv",            "\x201d", "\x201d", "\x2019", "\x2019");
+    QUOTES_LANG("sw",            "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("swc",           "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("ta",            "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("te",            "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("teo",           "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("th",            "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("ti-ER",         "\x2018", "\x2019", "\x201c", "\x201d");
+    QUOTES_LANG("to",            "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("tr",            "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("twq",           "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("tzm",           "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("uk",            "\x00ab", "\x00bb", "\x201e", "\x201c");
+    QUOTES_LANG("ur",            "\x201d", "\x201c", "\x2019", "\x2018");
+    QUOTES_LANG("vai",           "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("vai-Latn",      "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("vi",            "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("vun",           "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("xh",            "\x2018", "\x2019", "\x201c", "\x201d");
+    QUOTES_LANG("xog",           "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("yav",           "\x00ab", "\x00bb", "\x00ab", "\x00bb");
+    QUOTES_LANG("yo",            "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("zh",            "\x201c", "\x201d", "\x2018", "\x2019");
+    QUOTES_LANG("zh-Hant",       "\x300c", "\x300d", "\x300e", "\x300f");
+    QUOTES_LANG("zu",            "\x201c", "\x201d", "\x2018", "\x2019");
+    #undef QUOTES_LANG
+
+    return staticQuotesMap;
+}
+
+static const QuotesData* basicQuotesData()
+{
+    // FIXME: The default quotes should be the fancy quotes for "en".
+    static const QuotesData* staticBasicQuotes = QuotesData::create(U("\""), U("\""), U("'"), U("'")).leakRef();
+    return staticBasicQuotes;
+}
+
+PassRefPtr<StringImpl> RenderQuote::originalText() const
+{
+    switch (m_type) {
+    case NO_OPEN_QUOTE:
+    case NO_CLOSE_QUOTE:
+        return StringImpl::empty();
+    case CLOSE_QUOTE:
+        return quotesData()->getCloseQuote(m_depth - 1).impl();
+    case OPEN_QUOTE:
+        return quotesData()->getOpenQuote(m_depth).impl();
+    }
+    ASSERT_NOT_REACHED();
+    return StringImpl::empty();
+}
+
+const QuotesData* RenderQuote::quotesData() const
+{
+    if (QuotesData* customQuotes = style()->quotes())
+        return customQuotes;
+
+    AtomicString language = style()->locale();
+    if (language.isNull())
+        return basicQuotesData();
+    const QuotesData* quotes = quotesDataLanguageMap().get(language);
+    if (!quotes)
+        return basicQuotesData();
+    return quotes;
+}
+
+void RenderQuote::attachQuote()
+{
+    ASSERT(view());
+    ASSERT(!m_attached);
+    ASSERT(!m_next && !m_previous);
+    ASSERT(isRooted());
+
+    if (!view()->renderQuoteHead()) {
+        view()->setRenderQuoteHead(this);
+        m_attached = true;
+        return;
+    }
+
+    for (RenderObject* predecessor = previousInPreOrder(); predecessor; predecessor = predecessor->previousInPreOrder()) {
+        // Skip unattached predecessors to avoid having stale m_previous pointers
+        // if the previous node is never attached and is then destroyed.
+        if (!predecessor->isQuote() || !toRenderQuote(predecessor)->isAttached())
+            continue;
+        m_previous = toRenderQuote(predecessor);
+        m_next = m_previous->m_next;
+        m_previous->m_next = this;
+        if (m_next)
+            m_next->m_previous = this;
+        break;
+    }
+
+    if (!m_previous) {
+        m_next = view()->renderQuoteHead();
+        view()->setRenderQuoteHead(this);
+        if (m_next)
+            m_next->m_previous = this;
+    }
+    m_attached = true;
+
+    for (RenderQuote* quote = this; quote; quote = quote->m_next)
+        quote->updateDepth();
+
+    ASSERT(!m_next || m_next->m_attached);
+    ASSERT(!m_next || m_next->m_previous == this);
+    ASSERT(!m_previous || m_previous->m_attached);
+    ASSERT(!m_previous || m_previous->m_next == this);
+}
+
+void RenderQuote::detachQuote()
+{
+    ASSERT(!m_next || m_next->m_attached);
+    ASSERT(!m_previous || m_previous->m_attached);
+    if (!m_attached)
+        return;
+    if (m_previous)
+        m_previous->m_next = m_next;
+    else if (view())
+        view()->setRenderQuoteHead(m_next);
+    if (m_next)
+        m_next->m_previous = m_previous;
+    if (!documentBeingDestroyed()) {
+        for (RenderQuote* quote = m_next; quote; quote = quote->m_next)
+            quote->updateDepth();
+    }
+    m_attached = false;
+    m_next = 0;
+    m_previous = 0;
+    m_depth = 0;
+}
+
+void RenderQuote::updateDepth()
+{
+    ASSERT(m_attached);
+    int oldDepth = m_depth;
+    m_depth = 0;
+    if (m_previous) {
+        m_depth = m_previous->m_depth;
+        switch (m_previous->m_type) {
+        case OPEN_QUOTE:
+        case NO_OPEN_QUOTE:
+            m_depth++;
+            break;
+        case CLOSE_QUOTE:
+        case NO_CLOSE_QUOTE:
+            if (m_depth)
+                m_depth--;
+            break;
+        }
+    }
+    if (oldDepth != m_depth)
+        setText(originalText());
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderQuote.h b/Source/core/rendering/RenderQuote.h
new file mode 100644
index 0000000..3bd608b
--- /dev/null
+++ b/Source/core/rendering/RenderQuote.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2011 Nokia Inc. All rights reserved.
+ * Copyright (C) 2012 Google 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 RenderQuote_h
+#define RenderQuote_h
+
+#include "core/rendering/RenderText.h"
+#include "core/rendering/style/QuotesData.h"
+#include "core/rendering/style/RenderStyle.h"
+#include "core/rendering/style/RenderStyleConstants.h"
+
+namespace WebCore {
+
+class Document;
+
+class RenderQuote FINAL : public RenderText {
+public:
+    RenderQuote(Document*, const QuoteType);
+    virtual ~RenderQuote();
+    void attachQuote();
+
+private:
+    void detachQuote();
+
+    virtual void willBeDestroyed() OVERRIDE;
+    virtual const char* renderName() const OVERRIDE { return "RenderQuote"; };
+    virtual bool isQuote() const OVERRIDE { return true; };
+    virtual PassRefPtr<StringImpl> originalText() const OVERRIDE;
+    virtual void styleDidChange(StyleDifference, const RenderStyle*) OVERRIDE;
+    virtual void willBeRemovedFromTree() OVERRIDE;
+
+    const QuotesData* quotesData() const;
+    void updateDepth();
+    bool isAttached() { return m_attached; }
+
+    QuoteType m_type;
+    int m_depth;
+    RenderQuote* m_next;
+    RenderQuote* m_previous;
+    bool m_attached;
+};
+
+inline RenderQuote* toRenderQuote(RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isQuote());
+    return static_cast<RenderQuote*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderQuote(const RenderQuote*);
+
+} // namespace WebCore
+
+#endif // RenderQuote_h
diff --git a/Source/core/rendering/RenderRegion.cpp b/Source/core/rendering/RenderRegion.cpp
new file mode 100644
index 0000000..73754b2
--- /dev/null
+++ b/Source/core/rendering/RenderRegion.cpp
@@ -0,0 +1,642 @@
+/*
+ * Copyright (C) 2011 Adobe Systems Incorporated. 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 THE COPYRIGHT HOLDER "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 THE COPYRIGHT HOLDER 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 "core/rendering/RenderRegion.h"
+
+#include "core/css/StyleResolver.h"
+#include "core/dom/Range.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/platform/graphics/IntRect.h"
+#include "core/rendering/FlowThreadController.h"
+#include "core/rendering/HitTestResult.h"
+#include "core/rendering/LayoutRepainter.h"
+#include "core/rendering/PaintInfo.h"
+#include "core/rendering/RenderBoxRegionInfo.h"
+#include "core/rendering/RenderNamedFlowThread.h"
+#include "core/rendering/RenderView.h"
+
+using namespace std;
+
+namespace WebCore {
+
+RenderRegion::RenderRegion(Element* element, RenderFlowThread* flowThread)
+    : RenderBlock(element)
+    , m_flowThread(flowThread)
+    , m_parentNamedFlowThread(0)
+    , m_isValid(false)
+    , m_hasCustomRegionStyle(false)
+    , m_hasAutoLogicalHeight(false)
+    , m_regionState(RegionUndefined)
+{
+}
+
+LayoutUnit RenderRegion::pageLogicalWidth() const
+{
+    ASSERT(m_flowThread);
+    return m_flowThread->isHorizontalWritingMode() ? contentWidth() : contentHeight();
+}
+
+LayoutUnit RenderRegion::pageLogicalHeight() const
+{
+    ASSERT(m_flowThread);
+    if (hasOverrideHeight() && !m_flowThread->inConstrainedLayoutPhase()) {
+        ASSERT(hasAutoLogicalHeight());
+        return overrideLogicalContentHeight();
+    }
+    return m_flowThread->isHorizontalWritingMode() ? contentHeight() : contentWidth();
+}
+
+// This method returns the maximum page size of a region with auto-height. This is the initial
+// height value for auto-height regions in the first layout phase of the parent named flow.
+LayoutUnit RenderRegion::maxPageLogicalHeight() const
+{
+    ASSERT(m_flowThread);
+    ASSERT(hasAutoLogicalHeight() && !m_flowThread->inConstrainedLayoutPhase());
+    return style()->logicalMaxHeight().isUndefined() ? LayoutUnit::max() / 2 : computeReplacedLogicalHeightUsing(style()->logicalMaxHeight());
+}
+
+LayoutUnit RenderRegion::logicalHeightOfAllFlowThreadContent() const
+{
+    ASSERT(m_flowThread);
+    if (hasOverrideHeight() && !m_flowThread->inConstrainedLayoutPhase()) {
+        ASSERT(hasAutoLogicalHeight());
+        return overrideLogicalContentHeight();
+    }
+    return m_flowThread->isHorizontalWritingMode() ? contentHeight() : contentWidth();
+}
+
+LayoutRect RenderRegion::flowThreadPortionOverflowRect() const
+{
+    return overflowRectForFlowThreadPortion(flowThreadPortionRect(), isFirstRegion(), isLastRegion());
+}
+
+LayoutRect RenderRegion::overflowRectForFlowThreadPortion(LayoutRect flowThreadPortionRect, bool isFirstPortion, bool isLastPortion) const
+{
+    ASSERT(isValid());
+
+    // FIXME: Would like to just use hasOverflowClip() but we aren't a block yet. When RenderRegion is eliminated and
+    // folded into RenderBlock, switch to hasOverflowClip().
+    bool clipX = style()->overflowX() != OVISIBLE;
+    bool clipY = style()->overflowY() != OVISIBLE;
+    bool isLastRegionWithRegionOverflowBreak = (isLastPortion && (style()->regionOverflow() == BreakRegionOverflow));
+    if ((clipX && clipY) || isLastRegionWithRegionOverflowBreak)
+        return flowThreadPortionRect;
+
+    LayoutRect flowThreadOverflow = m_flowThread->visualOverflowRect();
+
+    // Only clip along the flow thread axis.
+    LayoutUnit outlineSize = maximalOutlineSize(PaintPhaseOutline);
+    LayoutRect clipRect;
+    if (m_flowThread->isHorizontalWritingMode()) {
+        LayoutUnit minY = isFirstPortion ? (flowThreadOverflow.y() - outlineSize) : flowThreadPortionRect.y();
+        LayoutUnit maxY = isLastPortion ? max(flowThreadPortionRect.maxY(), flowThreadOverflow.maxY()) + outlineSize : flowThreadPortionRect.maxY();
+        LayoutUnit minX = clipX ? flowThreadPortionRect.x() : min(flowThreadPortionRect.x(), flowThreadOverflow.x() - outlineSize);
+        LayoutUnit maxX = clipX ? flowThreadPortionRect.maxX() : max(flowThreadPortionRect.maxX(), (flowThreadOverflow.maxX() + outlineSize));
+        clipRect = LayoutRect(minX, minY, maxX - minX, maxY - minY);
+    } else {
+        LayoutUnit minX = isFirstPortion ? (flowThreadOverflow.x() - outlineSize) : flowThreadPortionRect.x();
+        LayoutUnit maxX = isLastPortion ? max(flowThreadPortionRect.maxX(), flowThreadOverflow.maxX()) + outlineSize : flowThreadPortionRect.maxX();
+        LayoutUnit minY = clipY ? flowThreadPortionRect.y() : min(flowThreadPortionRect.y(), (flowThreadOverflow.y() - outlineSize));
+        LayoutUnit maxY = clipY ? flowThreadPortionRect.maxY() : max(flowThreadPortionRect.y(), (flowThreadOverflow.maxY() + outlineSize));
+        clipRect = LayoutRect(minX, minY, maxX - minX, maxY - minY);
+    }
+
+    return clipRect;
+}
+
+LayoutUnit RenderRegion::pageLogicalTopForOffset(LayoutUnit /* offset */) const
+{
+    return flowThread()->isHorizontalWritingMode() ? flowThreadPortionRect().y() : flowThreadPortionRect().x();
+}
+
+bool RenderRegion::isFirstRegion() const
+{
+    ASSERT(isValid());
+
+    return m_flowThread->firstRegion() == this;
+}
+
+bool RenderRegion::isLastRegion() const
+{
+    ASSERT(isValid());
+
+    return m_flowThread->lastRegion() == this;
+}
+
+void RenderRegion::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    if (style()->visibility() != VISIBLE)
+        return;
+
+    RenderBlock::paintObject(paintInfo, paintOffset);
+
+    // Delegate painting of content in region to RenderFlowThread.
+    // RenderFlowThread is a self painting layer (being a positioned object) who is painting its children, the collected objects.
+    // Since we do not want to paint the flow thread content multiple times (for each painting phase of the region object),
+    // we allow the flow thread painting only for the selection and the foreground phase.
+    if (!isValid() || (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseSelection))
+        return;
+
+    setRegionObjectsRegionStyle();
+    m_flowThread->paintFlowThreadPortionInRegion(paintInfo, this, flowThreadPortionRect(), flowThreadPortionOverflowRect(), LayoutPoint(paintOffset.x() + borderLeft() + paddingLeft(), paintOffset.y() + borderTop() + paddingTop()));
+    restoreRegionObjectsOriginalStyle();
+}
+
+// Hit Testing
+bool RenderRegion::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action)
+{
+    if (!isValid())
+        return false;
+
+    LayoutPoint adjustedLocation = accumulatedOffset + location();
+
+    // 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).
+    // FIXME: Once we support overflow, we need to intersect with that and not with the bounds rect.
+    LayoutRect boundsRect = borderBoxRectInRegion(locationInContainer.region());
+    boundsRect.moveBy(adjustedLocation);
+    if (visibleToHitTestRequest(request) && action == HitTestForeground && locationInContainer.intersects(boundsRect)) {
+        // Check the contents of the RenderFlowThread.
+        if (m_flowThread->hitTestFlowThreadPortionInRegion(this, flowThreadPortionRect(), flowThreadPortionOverflowRect(), request, result, locationInContainer, LayoutPoint(adjustedLocation.x() + borderLeft() + paddingLeft(), adjustedLocation.y() + borderTop() + paddingTop())))
+            return true;
+        updateHitTestResult(result, locationInContainer.point() - toLayoutSize(adjustedLocation));
+        if (!result.addNodeToRectBasedTestResult(generatingNode(), request, locationInContainer, boundsRect))
+            return true;
+    }
+
+    return false;
+}
+
+void RenderRegion::checkRegionStyle()
+{
+    ASSERT(m_flowThread);
+    bool customRegionStyle = false;
+
+    // FIXME: Region styling doesn't work for pseudo elements.
+    if (node()) {
+        Element* regionElement = toElement(node());
+        customRegionStyle = view()->document()->styleResolver()->checkRegionStyle(regionElement);
+    }
+    setHasCustomRegionStyle(customRegionStyle);
+    m_flowThread->checkRegionsWithStyling();
+}
+
+void RenderRegion::incrementAutoLogicalHeightCount()
+{
+    ASSERT(isValid());
+    ASSERT(m_hasAutoLogicalHeight);
+
+    m_flowThread->incrementAutoLogicalHeightRegions();
+}
+
+void RenderRegion::decrementAutoLogicalHeightCount()
+{
+    ASSERT(isValid());
+
+    m_flowThread->decrementAutoLogicalHeightRegions();
+}
+
+void RenderRegion::updateRegionHasAutoLogicalHeightFlag()
+{
+    ASSERT(m_flowThread);
+
+    if (!isValid())
+        return;
+
+    bool didHaveAutoLogicalHeight = m_hasAutoLogicalHeight;
+    m_hasAutoLogicalHeight = shouldHaveAutoLogicalHeight();
+    if (m_hasAutoLogicalHeight != didHaveAutoLogicalHeight) {
+        if (m_hasAutoLogicalHeight)
+            incrementAutoLogicalHeightCount();
+        else {
+            clearOverrideLogicalContentHeight();
+            decrementAutoLogicalHeightCount();
+        }
+    }
+}
+
+bool RenderRegion::shouldHaveAutoLogicalHeight() const
+{
+    bool hasSpecifiedEndpointsForHeight = style()->logicalTop().isSpecified() && style()->logicalBottom().isSpecified();
+    bool hasAnchoredEndpointsForHeight = isOutOfFlowPositioned() && hasSpecifiedEndpointsForHeight;
+    return style()->logicalHeight().isAuto() && !hasAnchoredEndpointsForHeight;
+}
+    
+void RenderRegion::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
+{
+    RenderBlock::styleDidChange(diff, oldStyle);
+
+    // If the region is not attached to any thread, there is no need to check
+    // whether the region has region styling since no content will be displayed
+    // into the region.
+    if (!m_flowThread) {
+        setHasCustomRegionStyle(false);
+        return;
+    }
+
+    checkRegionStyle();
+    updateRegionHasAutoLogicalHeightFlag();
+}
+
+void RenderRegion::layoutBlock(bool relayoutChildren, LayoutUnit)
+{
+    StackStats::LayoutCheckPoint layoutCheckPoint;
+    RenderBlock::layoutBlock(relayoutChildren);
+
+    if (isValid()) {
+        LayoutRect oldRegionRect(flowThreadPortionRect());
+        if (!isHorizontalWritingMode())
+            oldRegionRect = oldRegionRect.transposedRect();
+
+        if (hasAutoLogicalHeight() && !m_flowThread->inConstrainedLayoutPhase()) {
+            m_flowThread->invalidateRegions();
+            clearOverrideLogicalContentHeight();
+            return;
+        }
+
+        if (!isRenderRegionSet() && (oldRegionRect.width() != pageLogicalWidth() || oldRegionRect.height() != pageLogicalHeight()))
+            // This can happen even if we are in the inConstrainedLayoutPhase and it will trigger a pathological layout of the flow thread.
+            m_flowThread->invalidateRegions();
+    }
+
+    // FIXME: We need to find a way to set up overflow properly. Our flow thread hasn't gotten a layout
+    // yet, so we can't look to it for correct information. It's possible we could wait until after the RenderFlowThread
+    // gets a layout, and then try to propagate overflow information back to the region, and then mark for a second layout.
+    // That second layout would then be able to use the information from the RenderFlowThread to set up overflow.
+    //
+    // The big problem though is that overflow needs to be region-specific. We can't simply use the RenderFlowThread's global
+    // overflow values, since then we'd always think any narrow region had huge overflow (all the way to the width of the
+    // RenderFlowThread itself).
+    //
+    // We'll need to expand RenderBoxRegionInfo to also hold left and right overflow values.
+}
+
+void RenderRegion::repaintFlowThreadContent(const LayoutRect& repaintRect) const
+{
+    repaintFlowThreadContentRectangle(repaintRect, flowThreadPortionRect(), flowThreadPortionOverflowRect(), contentBoxRect().location());
+}
+
+void RenderRegion::repaintFlowThreadContentRectangle(const LayoutRect& repaintRect, const LayoutRect& flowThreadPortionRect, const LayoutRect& flowThreadPortionOverflowRect, const LayoutPoint& regionLocation) const
+{
+    ASSERT(isValid());
+
+    // We only have to issue a repaint in this region if the region rect intersects the repaint rect.
+    LayoutRect flippedFlowThreadPortionRect(flowThreadPortionRect);
+    LayoutRect flippedFlowThreadPortionOverflowRect(flowThreadPortionOverflowRect);
+    flowThread()->flipForWritingMode(flippedFlowThreadPortionRect); // Put the region rects into physical coordinates.
+    flowThread()->flipForWritingMode(flippedFlowThreadPortionOverflowRect);
+
+    LayoutRect clippedRect(repaintRect);
+    clippedRect.intersect(flippedFlowThreadPortionOverflowRect);
+    if (clippedRect.isEmpty())
+        return;
+
+    // Put the region rect into the region's physical coordinate space.
+    clippedRect.setLocation(regionLocation + (clippedRect.location() - flippedFlowThreadPortionRect.location()));
+
+    // Now switch to the region's writing mode coordinate space and let it repaint itself.
+    flipForWritingMode(clippedRect);
+    
+    // Issue the repaint.
+    repaintRectangle(clippedRect);
+}
+
+void RenderRegion::installFlowThread()
+{
+    ASSERT(view());
+
+    m_flowThread = view()->flowThreadController()->ensureRenderFlowThreadWithName(style()->regionThread());
+
+    // By now the flow thread should already be added to the rendering tree,
+    // so we go up the rendering parents and check that this region is not part of the same
+    // flow that it actually needs to display. It would create a circular reference.
+    RenderObject* parentObject = parent();
+    m_parentNamedFlowThread = 0;
+    for ( ; parentObject; parentObject = parentObject->parent()) {
+        if (parentObject->isRenderNamedFlowThread()) {
+            m_parentNamedFlowThread = toRenderNamedFlowThread(parentObject);
+            // Do not take into account a region that links a flow with itself. The dependency
+            // cannot change, so it is not worth adding it to the list.
+            if (m_flowThread == m_parentNamedFlowThread)
+                m_flowThread = 0;
+            break;
+        }
+    }
+}
+
+void RenderRegion::attachRegion()
+{
+    if (documentBeingDestroyed())
+        return;
+    
+    // A region starts off invalid.
+    setIsValid(false);
+
+    // Initialize the flow thread reference and create the flow thread object if needed.
+    // The flow thread lifetime is influenced by the number of regions attached to it,
+    // and we are attaching the region to the flow thread.
+    installFlowThread();
+    
+    if (!m_flowThread)
+        return;
+
+    // Only after adding the region to the thread, the region is marked to be valid.
+    m_flowThread->addRegionToThread(this);
+
+    // The region just got attached to the flow thread, lets check whether
+    // it has region styling rules associated.
+    checkRegionStyle();
+
+    if (!isValid())
+        return;
+
+    m_hasAutoLogicalHeight = shouldHaveAutoLogicalHeight();
+    if (hasAutoLogicalHeight())
+        incrementAutoLogicalHeightCount();
+}
+
+void RenderRegion::detachRegion()
+{
+    if (m_flowThread) {
+        m_flowThread->removeRegionFromThread(this);
+        if (hasAutoLogicalHeight())
+            decrementAutoLogicalHeightCount();
+    }
+    m_flowThread = 0;
+}
+
+RenderBoxRegionInfo* RenderRegion::renderBoxRegionInfo(const RenderBox* box) const
+{
+    ASSERT(isValid());
+    return m_renderBoxRegionInfo.get(box);
+}
+
+RenderBoxRegionInfo* RenderRegion::setRenderBoxRegionInfo(const RenderBox* box, LayoutUnit logicalLeftInset, LayoutUnit logicalRightInset,
+    bool containingBlockChainIsInset)
+{
+    ASSERT(isValid());
+
+    OwnPtr<RenderBoxRegionInfo>& boxInfo = m_renderBoxRegionInfo.add(box, nullptr).iterator->value;
+    if (boxInfo)
+        *boxInfo = RenderBoxRegionInfo(logicalLeftInset, logicalRightInset, containingBlockChainIsInset);
+    else
+        boxInfo = adoptPtr(new RenderBoxRegionInfo(logicalLeftInset, logicalRightInset, containingBlockChainIsInset));
+
+    return boxInfo.get();
+}
+
+PassOwnPtr<RenderBoxRegionInfo> RenderRegion::takeRenderBoxRegionInfo(const RenderBox* box)
+{
+    return m_renderBoxRegionInfo.take(box);
+}
+
+void RenderRegion::removeRenderBoxRegionInfo(const RenderBox* box)
+{
+    m_renderBoxRegionInfo.remove(box);
+}
+
+void RenderRegion::deleteAllRenderBoxRegionInfo()
+{
+    m_renderBoxRegionInfo.clear();
+}
+
+LayoutUnit RenderRegion::logicalTopOfFlowThreadContentRect(const LayoutRect& rect) const
+{
+    ASSERT(isValid());
+    return flowThread()->isHorizontalWritingMode() ? rect.y() : rect.x();
+}
+
+LayoutUnit RenderRegion::logicalBottomOfFlowThreadContentRect(const LayoutRect& rect) const
+{
+    ASSERT(isValid());
+    return flowThread()->isHorizontalWritingMode() ? rect.maxY() : rect.maxX();
+}
+
+void RenderRegion::setRegionObjectsRegionStyle()
+{
+    if (!hasCustomRegionStyle())
+        return;
+
+    // Start from content nodes and recursively compute the style in region for the render objects below.
+    // If the style in region was already computed, used that style instead of computing a new one.
+    RenderNamedFlowThread* namedFlow = view()->flowThreadController()->ensureRenderFlowThreadWithName(style()->regionThread());
+    const NamedFlowContentNodes& contentNodes = namedFlow->contentNodes();
+
+    for (NamedFlowContentNodes::const_iterator iter = contentNodes.begin(), end = contentNodes.end(); iter != end; ++iter) {
+        const Node* node = *iter;
+        // The list of content nodes contains also the nodes with display:none.
+        if (!node->renderer())
+            continue;
+
+        RenderObject* object = node->renderer();
+        // If the content node does not flow any of its children in this region,
+        // we do not compute any style for them in this region.
+        if (!flowThread()->objectInFlowRegion(object, this))
+            continue;
+
+        // If the object has style in region, use that instead of computing a new one.
+        RenderObjectRegionStyleMap::iterator it = m_renderObjectRegionStyle.find(object);
+        RefPtr<RenderStyle> objectStyleInRegion;
+        bool objectRegionStyleCached = false;
+        if (it != m_renderObjectRegionStyle.end()) {
+            objectStyleInRegion = it->value.style;
+            ASSERT(it->value.cached);
+            objectRegionStyleCached = true;
+        } else
+            objectStyleInRegion = computeStyleInRegion(object);
+
+        setObjectStyleInRegion(object, objectStyleInRegion, objectRegionStyleCached);
+
+        computeChildrenStyleInRegion(object);
+    }
+}
+
+void RenderRegion::restoreRegionObjectsOriginalStyle()
+{
+    if (!hasCustomRegionStyle())
+        return;
+
+    RenderObjectRegionStyleMap temp;
+    for (RenderObjectRegionStyleMap::iterator iter = m_renderObjectRegionStyle.begin(), end = m_renderObjectRegionStyle.end(); iter != end; ++iter) {
+        RenderObject* object = const_cast<RenderObject*>(iter->key);
+        RefPtr<RenderStyle> objectRegionStyle = object->style();
+        RefPtr<RenderStyle> objectOriginalStyle = iter->value.style;
+        object->setStyleInternal(objectOriginalStyle);
+
+        bool shouldCacheRegionStyle = iter->value.cached;
+        if (!shouldCacheRegionStyle) {
+            // Check whether we should cache the computed style in region.
+            unsigned changedContextSensitiveProperties = ContextSensitivePropertyNone;
+            StyleDifference styleDiff = objectOriginalStyle->diff(objectRegionStyle.get(), changedContextSensitiveProperties);
+            if (styleDiff < StyleDifferenceLayoutPositionedMovementOnly)
+                shouldCacheRegionStyle = true;
+        }
+        if (shouldCacheRegionStyle) {
+            ObjectRegionStyleInfo styleInfo;
+            styleInfo.style = objectRegionStyle;
+            styleInfo.cached = true;
+            temp.set(object, styleInfo);
+        }
+    }
+
+    m_renderObjectRegionStyle.swap(temp);
+}
+
+void RenderRegion::insertedIntoTree()
+{
+    RenderBlock::insertedIntoTree();
+
+    attachRegion();
+}
+
+void RenderRegion::willBeRemovedFromTree()
+{
+    RenderBlock::willBeRemovedFromTree();
+
+    detachRegion();
+}
+
+PassRefPtr<RenderStyle> RenderRegion::computeStyleInRegion(const RenderObject* object)
+{
+    ASSERT(object);
+    ASSERT(object->view());
+    ASSERT(object->view()->document());
+    ASSERT(!object->isAnonymous());
+    ASSERT(object->node() && object->node()->isElementNode());
+
+    // FIXME: Region styling fails for pseudo-elements because the renderers don't have a node.
+    Element* element = toElement(object->node());
+    RefPtr<RenderStyle> renderObjectRegionStyle = object->view()->document()->styleResolver()->styleForElement(element, 0, DisallowStyleSharing, MatchAllRules, this);
+
+    return renderObjectRegionStyle.release();
+}
+
+void RenderRegion::computeChildrenStyleInRegion(const RenderObject* object)
+{
+    for (RenderObject* child = object->firstChild(); child; child = child->nextSibling()) {
+
+        RenderObjectRegionStyleMap::iterator it = m_renderObjectRegionStyle.find(child);
+
+        RefPtr<RenderStyle> childStyleInRegion;
+        bool objectRegionStyleCached = false;
+        if (it != m_renderObjectRegionStyle.end()) {
+            childStyleInRegion = it->value.style;
+            objectRegionStyleCached = true;
+        } else {
+            if (child->isAnonymous() || child->isInFlowRenderFlowThread())
+                childStyleInRegion = RenderStyle::createAnonymousStyleWithDisplay(object->style(), child->style()->display());
+            else if (child->isText())
+                childStyleInRegion = RenderStyle::clone(object->style());
+            else
+                childStyleInRegion = computeStyleInRegion(child);
+        }
+
+        setObjectStyleInRegion(child, childStyleInRegion, objectRegionStyleCached);
+
+        computeChildrenStyleInRegion(child);
+    }
+}
+
+void RenderRegion::setObjectStyleInRegion(RenderObject* object, PassRefPtr<RenderStyle> styleInRegion, bool objectRegionStyleCached)
+{
+    ASSERT(object->flowThreadContainingBlock());
+
+    RefPtr<RenderStyle> objectOriginalStyle = object->style();
+    object->setStyleInternal(styleInRegion);
+
+    if (object->isBoxModelObject() && !object->hasBoxDecorations()) {
+        bool hasBoxDecorations = object->isTableCell()
+        || object->style()->hasBackground()
+        || object->style()->hasBorder()
+        || object->style()->hasAppearance()
+        || object->style()->boxShadow();
+        object->setHasBoxDecorations(hasBoxDecorations);
+    }
+
+    ObjectRegionStyleInfo styleInfo;
+    styleInfo.style = objectOriginalStyle;
+    styleInfo.cached = objectRegionStyleCached;
+    m_renderObjectRegionStyle.set(object, styleInfo);
+}
+
+void RenderRegion::clearObjectStyleInRegion(const RenderObject* object)
+{
+    ASSERT(object);
+    m_renderObjectRegionStyle.remove(object);
+
+    // Clear the style for the children of this object.
+    for (RenderObject* child = object->firstChild(); child; child = child->nextSibling())
+        clearObjectStyleInRegion(child);
+}
+
+void RenderRegion::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const
+{
+    if (!isValid()) {
+        RenderBlock::computeIntrinsicLogicalWidths(minLogicalWidth, maxLogicalWidth);
+        return;
+    }
+
+    minLogicalWidth = m_flowThread->minPreferredLogicalWidth();
+    maxLogicalWidth = m_flowThread->maxPreferredLogicalWidth();
+}
+
+void RenderRegion::getRanges(Vector<RefPtr<Range> >& rangeObjects) const
+{
+    RenderNamedFlowThread* namedFlow = view()->flowThreadController()->ensureRenderFlowThreadWithName(style()->regionThread());
+    namedFlow->getRanges(rangeObjects, this);
+}
+
+void RenderRegion::updateLogicalHeight()
+{
+    RenderBlock::updateLogicalHeight();
+
+    if (!hasAutoLogicalHeight())
+        return;
+
+    // We want to update the logical height based on the computed override logical
+    // content height only if the view is in the layout phase
+    // in which all the auto logical height regions have their override logical height set.
+    if (!m_flowThread->inConstrainedLayoutPhase())
+        return;
+
+    // There may be regions with auto logical height that during the prerequisite layout phase
+    // did not have the chance to layout flow thread content. Because of that, these regions do not
+    // have an overrideLogicalContentHeight computed and they will not be able to fragment any flow
+    // thread content.
+    if (!hasOverrideHeight())
+        return;
+
+    LayoutUnit newLogicalHeight = overrideLogicalContentHeight() + borderAndPaddingLogicalHeight();
+    ASSERT(newLogicalHeight < LayoutUnit::max() / 2);
+    if (newLogicalHeight > logicalHeight())
+        setLogicalHeight(newLogicalHeight);
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderRegion.h b/Source/core/rendering/RenderRegion.h
new file mode 100644
index 0000000..a4a7238
--- /dev/null
+++ b/Source/core/rendering/RenderRegion.h
@@ -0,0 +1,220 @@
+/*
+ * Copyright (C) 2011 Adobe Systems Incorporated. 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 THE COPYRIGHT HOLDER “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 THE COPYRIGHT HOLDER 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 RenderRegion_h
+#define RenderRegion_h
+
+#include "core/rendering/RenderBlock.h"
+#include "core/rendering/style/StyleInheritedData.h"
+
+namespace WebCore {
+
+struct LayerFragment;
+typedef Vector<LayerFragment, 1> LayerFragments;
+class RenderBox;
+class RenderBoxRegionInfo;
+class RenderFlowThread;
+class RenderNamedFlowThread;
+
+class RenderRegion : public RenderBlock {
+public:
+    explicit RenderRegion(Element*, RenderFlowThread*);
+
+    virtual bool isRenderRegion() const { return true; }
+
+    virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
+
+    virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+
+    void setFlowThreadPortionRect(const LayoutRect& rect) { m_flowThreadPortionRect = rect; }
+    LayoutRect flowThreadPortionRect() const { return m_flowThreadPortionRect; }
+    LayoutRect flowThreadPortionOverflowRect() const;
+
+    void attachRegion();
+    void detachRegion();
+
+    RenderNamedFlowThread* parentNamedFlowThread() const { return m_parentNamedFlowThread; }
+    RenderFlowThread* flowThread() const { return m_flowThread; }
+
+    // Valid regions do not create circular dependencies with other flows.
+    bool isValid() const { return m_isValid; }
+    void setIsValid(bool valid) { m_isValid = valid; }
+
+    bool hasCustomRegionStyle() const { return m_hasCustomRegionStyle; }
+    void setHasCustomRegionStyle(bool hasCustomRegionStyle) { m_hasCustomRegionStyle = hasCustomRegionStyle; }
+
+    RenderBoxRegionInfo* renderBoxRegionInfo(const RenderBox*) const;
+    RenderBoxRegionInfo* setRenderBoxRegionInfo(const RenderBox*, LayoutUnit logicalLeftInset, LayoutUnit logicalRightInset,
+        bool containingBlockChainIsInset);
+    PassOwnPtr<RenderBoxRegionInfo> takeRenderBoxRegionInfo(const RenderBox*);
+    void removeRenderBoxRegionInfo(const RenderBox*);
+
+    void deleteAllRenderBoxRegionInfo();
+
+    bool isFirstRegion() const;
+    bool isLastRegion() const;
+
+    void clearObjectStyleInRegion(const RenderObject*);
+
+    enum RegionState {
+        RegionUndefined,
+        RegionEmpty,
+        RegionFit,
+        RegionOverset
+    };
+
+    RegionState regionState() const { return isValid() ? m_regionState : RegionUndefined; }
+    void setRegionState(RegionState regionState) { m_regionState = regionState; }
+    
+    // These methods represent the width and height of a "page" and for a RenderRegion they are just the
+    // content width and content height of a region. For RenderRegionSets, however, they will be the width and
+    // height of a single column or page in the set.
+    virtual LayoutUnit pageLogicalWidth() const;
+    virtual LayoutUnit pageLogicalHeight() const;
+    LayoutUnit maxPageLogicalHeight() const;
+
+    LayoutUnit logicalTopOfFlowThreadContentRect(const LayoutRect&) const;
+    LayoutUnit logicalBottomOfFlowThreadContentRect(const LayoutRect&) const;
+    LayoutUnit logicalTopForFlowThreadContent() const { return logicalTopOfFlowThreadContentRect(flowThreadPortionRect()); };
+    LayoutUnit logicalBottomForFlowThreadContent() const { return logicalBottomOfFlowThreadContentRect(flowThreadPortionRect()); };
+
+    void getRanges(Vector<RefPtr<Range> >&) const;
+
+    // This method represents the logical height of the entire flow thread portion used by the region or set.
+    // For RenderRegions it matches logicalPaginationHeight(), but for sets it is the height of all the pages
+    // or columns added together.
+    virtual LayoutUnit logicalHeightOfAllFlowThreadContent() const;
+
+    bool hasAutoLogicalHeight() const { return m_hasAutoLogicalHeight; }
+
+    virtual void updateLogicalHeight() OVERRIDE;
+
+    // The top of the nearest page inside the region. For RenderRegions, this is just the logical top of the
+    // flow thread portion we contain. For sets, we have to figure out the top of the nearest column or
+    // page.
+    virtual LayoutUnit pageLogicalTopForOffset(LayoutUnit offset) const;
+    
+    virtual void expandToEncompassFlowThreadContentsIfNeeded() { };
+
+    // Whether or not this region is a set.
+    virtual bool isRenderRegionSet() const { return false; }
+    
+    virtual void repaintFlowThreadContent(const LayoutRect& repaintRect) const;
+
+    virtual void collectLayerFragments(LayerFragments&, const LayoutRect&, const LayoutRect&) { }
+
+protected:
+    void setRegionObjectsRegionStyle();
+    void restoreRegionObjectsOriginalStyle();
+
+    virtual void computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const OVERRIDE;
+
+    LayoutRect overflowRectForFlowThreadPortion(LayoutRect flowThreadPortionRect, bool isFirstPortion, bool isLastPortion) const;
+    void repaintFlowThreadContentRectangle(const LayoutRect& repaintRect, const LayoutRect& flowThreadPortionRect,
+        const LayoutRect& flowThreadPortionOverflowRect, const LayoutPoint& regionLocation) const;
+
+    virtual bool shouldHaveAutoLogicalHeight() const;
+
+private:
+    virtual const char* renderName() const { return "RenderRegion"; }
+
+    virtual bool canHaveChildren() const OVERRIDE { return false; }
+
+    virtual void insertedIntoTree() OVERRIDE;
+    virtual void willBeRemovedFromTree() OVERRIDE;
+
+    virtual void layoutBlock(bool relayoutChildren, LayoutUnit pageLogicalHeight = 0) OVERRIDE;
+    virtual void paintObject(PaintInfo&, const LayoutPoint&) OVERRIDE;
+
+    virtual void installFlowThread();
+
+    PassRefPtr<RenderStyle> computeStyleInRegion(const RenderObject*);
+    void computeChildrenStyleInRegion(const RenderObject*);
+    void setObjectStyleInRegion(RenderObject*, PassRefPtr<RenderStyle>, bool objectRegionStyleCached);
+
+    void checkRegionStyle();
+    void updateRegionHasAutoLogicalHeightFlag();
+
+    void incrementAutoLogicalHeightCount();
+    void decrementAutoLogicalHeightCount();
+
+protected:
+    RenderFlowThread* m_flowThread;
+
+private:
+    // If this RenderRegion is displayed as part of another named flow,
+    // we need to create a dependency tree, so that layout of the
+    // regions is always done before the regions themselves.
+    RenderNamedFlowThread* m_parentNamedFlowThread;
+    LayoutRect m_flowThreadPortionRect;
+
+    // This map holds unique information about a block that is split across regions.
+    // A RenderBoxRegionInfo* tells us about any layout information for a RenderBox that
+    // is unique to the region. For now it just holds logical width information for RenderBlocks, but eventually
+    // it will also hold a custom style for any box (for region styling).
+    typedef HashMap<const RenderBox*, OwnPtr<RenderBoxRegionInfo> > RenderBoxRegionInfoMap;
+    RenderBoxRegionInfoMap m_renderBoxRegionInfo;
+
+    struct ObjectRegionStyleInfo {
+        // Used to store the original style of the object in region
+        // so that the original style is properly restored after paint.
+        // Also used to store computed style of the object in region between
+        // region paintings, so that the style in region is computed only
+        // when necessary.
+        RefPtr<RenderStyle> style;
+        // True if the computed style in region is cached.
+        bool cached;
+    };
+    typedef HashMap<const RenderObject*, ObjectRegionStyleInfo > RenderObjectRegionStyleMap;
+    RenderObjectRegionStyleMap m_renderObjectRegionStyle;
+
+    bool m_isValid : 1;
+    bool m_hasCustomRegionStyle : 1;
+    bool m_hasAutoLogicalHeight : 1;
+    RegionState m_regionState;
+};
+
+inline RenderRegion* toRenderRegion(RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isRenderRegion());
+    return static_cast<RenderRegion*>(object);
+}
+
+inline const RenderRegion* toRenderRegion(const RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isRenderRegion());
+    return static_cast<const RenderRegion*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderRegion(const RenderRegion*);
+
+} // namespace WebCore
+
+#endif // RenderRegion_h
diff --git a/Source/core/rendering/RenderRegionSet.cpp b/Source/core/rendering/RenderRegionSet.cpp
new file mode 100644
index 0000000..217ac85
--- /dev/null
+++ b/Source/core/rendering/RenderRegionSet.cpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2012 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 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 "core/rendering/RenderRegionSet.h"
+
+#include "core/rendering/RenderFlowThread.h"
+
+namespace WebCore {
+
+RenderRegionSet::RenderRegionSet(Element* element, RenderFlowThread* flowThread)
+    : RenderRegion(element, flowThread)
+{
+}
+
+void RenderRegionSet::installFlowThread()
+{
+    // We don't have to do anything, since we were able to connect the flow thread
+    // in the constructor.
+}
+
+void RenderRegionSet::expandToEncompassFlowThreadContentsIfNeeded()
+{
+    // Whenever the last region is a set, it always expands its region rect to consume all
+    // of the flow thread content. This is because it is always capable of generating an
+    // infinite number of boxes in order to hold all of the remaining content.
+    LayoutRect rect(flowThreadPortionRect());
+    
+    // Get the offset within the flow thread in its block progression direction. Then get the
+    // flow thread's remaining logical height including its overflow and expand our rect
+    // to encompass that remaining height and overflow. The idea is that we will generate
+    // additional columns and pages to hold that overflow, since people do write bad
+    // content like <body style="height:0px"> in multi-column layouts.
+    bool isHorizontal = flowThread()->isHorizontalWritingMode();
+    LayoutUnit logicalTopOffset = isHorizontal ? rect.y() : rect.x();
+    LayoutRect layoutRect = flowThread()->layoutOverflowRect();
+    LayoutUnit logicalHeightWithOverflow = (isHorizontal ? layoutRect.maxY() : layoutRect.maxX()) - logicalTopOffset;
+    setFlowThreadPortionRect(LayoutRect(rect.x(), rect.y(), isHorizontal ? rect.width() : logicalHeightWithOverflow, isHorizontal ? logicalHeightWithOverflow : rect.height()));
+}
+
+}
diff --git a/Source/core/rendering/RenderRegionSet.h b/Source/core/rendering/RenderRegionSet.h
new file mode 100644
index 0000000..3d19e88
--- /dev/null
+++ b/Source/core/rendering/RenderRegionSet.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2012 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 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 RenderRegionSet_h
+#define RenderRegionSet_h
+
+#include "core/rendering/RenderBoxRegionInfo.h"
+#include "core/rendering/RenderRegion.h"
+
+namespace WebCore {
+
+class RenderFlowThread;
+
+// RenderRegionSet represents a set of regions that all have the same width and height. It is a "composite region box" that
+// can be used to represent a single run of contiguous regions.
+//
+// By combining runs of same-size columns or pages into a single object, we significantly reduce the number of unique RenderObjects
+// required to represent those objects.
+//
+// This class is abstract and is only intended for use by renderers that generate anonymous runs of identical regions, i.e.,
+// columns and printing. RenderMultiColumnSet and RenderPageSet represent runs of columns and pages respectively.
+//
+// FIXME: For now we derive from RenderRegion, but this may change at some point.
+
+class RenderRegionSet : public RenderRegion {
+public:
+    RenderRegionSet(Element*, RenderFlowThread*);
+    
+protected:
+    virtual bool shouldHaveAutoLogicalHeight() const OVERRIDE { return false; }
+
+private:
+    virtual void installFlowThread() OVERRIDE FINAL;
+
+    virtual void expandToEncompassFlowThreadContentsIfNeeded() OVERRIDE FINAL;
+
+    virtual const char* renderName() const = 0;
+    
+    virtual bool isRenderRegionSet() const OVERRIDE FINAL { return true; }
+};
+
+} // namespace WebCore
+
+#endif // RenderRegionSet_h
+
diff --git a/Source/core/rendering/RenderReplaced.cpp b/Source/core/rendering/RenderReplaced.cpp
new file mode 100644
index 0000000..d57ac96
--- /dev/null
+++ b/Source/core/rendering/RenderReplaced.cpp
@@ -0,0 +1,585 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2004, 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) Research In Motion Limited 2011-2012. 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 "core/rendering/RenderReplaced.h"
+
+#include "core/dom/WebCoreMemoryInstrumentation.h"
+#include "core/editing/VisiblePosition.h"
+#include "core/page/Frame.h"
+#include "core/page/Page.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/rendering/LayoutRepainter.h"
+#include "core/rendering/RenderBlock.h"
+#include "core/rendering/RenderLayer.h"
+#include "core/rendering/RenderTheme.h"
+#include "core/rendering/RenderView.h"
+
+using namespace std;
+
+namespace WebCore {
+
+const int cDefaultWidth = 300;
+const int cDefaultHeight = 150;
+
+RenderReplaced::RenderReplaced(Element* element)
+    : RenderBox(element)
+    , m_intrinsicSize(cDefaultWidth, cDefaultHeight)
+{
+    setReplaced(true);
+}
+
+RenderReplaced::RenderReplaced(Element* element, const LayoutSize& intrinsicSize)
+    : RenderBox(element)
+    , m_intrinsicSize(intrinsicSize)
+{
+    setReplaced(true);
+}
+
+RenderReplaced::~RenderReplaced()
+{
+}
+
+void RenderReplaced::willBeDestroyed()
+{
+    if (!documentBeingDestroyed() && parent())
+        parent()->dirtyLinesFromChangedChild(this);
+
+    RenderBox::willBeDestroyed();
+}
+
+void RenderReplaced::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
+{
+    RenderBox::styleDidChange(diff, oldStyle);
+
+    bool hadStyle = (oldStyle != 0);
+    float oldZoom = hadStyle ? oldStyle->effectiveZoom() : RenderStyle::initialZoom();
+    if (style() && style()->effectiveZoom() != oldZoom)
+        intrinsicSizeChanged();
+}
+
+void RenderReplaced::layout()
+{
+    StackStats::LayoutCheckPoint layoutCheckPoint;
+    ASSERT(needsLayout());
+    
+    LayoutRepainter repainter(*this, checkForRepaintDuringLayout());
+    
+    setHeight(minimumReplacedHeight());
+
+    updateLogicalWidth();
+    updateLogicalHeight();
+
+    m_overflow.clear();
+    addVisualEffectOverflow();
+    updateLayerTransform();
+    invalidateBackgroundObscurationStatus();
+
+    repainter.repaintAfterLayout();
+    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, const LayoutPoint& paintOffset)
+{
+    if (!shouldPaint(paintInfo, paintOffset))
+        return;
+    
+    LayoutPoint adjustedPaintOffset = paintOffset + location();
+    
+    if (hasBoxDecorations() && (paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection)) 
+        paintBoxDecorations(paintInfo, adjustedPaintOffset);
+    
+    if (paintInfo.phase == PaintPhaseMask) {
+        paintMask(paintInfo, adjustedPaintOffset);
+        return;
+    }
+
+    LayoutRect paintRect = LayoutRect(adjustedPaintOffset, size());
+    if ((paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) && style()->outlineWidth())
+        paintOutline(paintInfo, paintRect);
+    
+    if (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseSelection && !canHaveChildren())
+        return;
+    
+    if (!paintInfo.shouldPaintWithinRoot(this))
+        return;
+    
+    bool drawSelectionTint = selectionState() != SelectionNone && !document()->printing();
+    if (paintInfo.phase == PaintPhaseSelection) {
+        if (selectionState() == SelectionNone)
+            return;
+        drawSelectionTint = false;
+    }
+
+    bool completelyClippedOut = false;
+    if (style()->hasBorderRadius()) {
+        LayoutRect borderRect = LayoutRect(adjustedPaintOffset, size());
+
+        if (borderRect.isEmpty())
+            completelyClippedOut = true;
+        else {
+            // Push a clip if we have a border radius, since we want to round the foreground content that gets painted.
+            paintInfo.context->save();
+            RoundedRect roundedInnerRect = style()->getRoundedInnerBorderFor(paintRect,
+                paddingTop() + borderTop(), paddingBottom() + borderBottom(), paddingLeft() + borderLeft(), paddingRight() + borderRight(), true, true);
+            clipRoundedInnerRect(paintInfo.context, paintRect, roundedInnerRect);
+        }
+    }
+
+    if (!completelyClippedOut) {
+        paintReplaced(paintInfo, adjustedPaintOffset);
+
+        if (style()->hasBorderRadius())
+            paintInfo.context->restore();
+    }
+        
+    // The selection tint never gets clipped by border-radius rounding, since we want it to run right up to the edges of
+    // surrounding content.
+    if (drawSelectionTint) {
+        LayoutRect selectionPaintingRect = localSelectionRect();
+        selectionPaintingRect.moveBy(adjustedPaintOffset);
+        paintInfo.context->fillRect(pixelSnappedIntRect(selectionPaintingRect), selectionBackgroundColor(), style()->colorSpace());
+    }
+}
+
+bool RenderReplaced::shouldPaint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    if (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseOutline && paintInfo.phase != PaintPhaseSelfOutline 
+            && paintInfo.phase != PaintPhaseSelection && paintInfo.phase != PaintPhaseMask)
+        return false;
+
+    if (!paintInfo.shouldPaintWithinRoot(this))
+        return false;
+        
+    // if we're invisible or haven't received a layout yet, then just bail.
+    if (style()->visibility() != VISIBLE)
+        return false;
+
+    LayoutPoint adjustedPaintOffset = paintOffset + location();
+
+    // Early exit if the element touches the edges.
+    LayoutUnit top = adjustedPaintOffset.y() + visualOverflowRect().y();
+    LayoutUnit bottom = adjustedPaintOffset.y() + visualOverflowRect().maxY();
+    if (isSelected() && m_inlineBoxWrapper) {
+        LayoutUnit selTop = paintOffset.y() + m_inlineBoxWrapper->root()->selectionTop();
+        LayoutUnit selBottom = paintOffset.y() + selTop + m_inlineBoxWrapper->root()->selectionHeight();
+        top = min(selTop, top);
+        bottom = max(selBottom, bottom);
+    }
+    
+    LayoutRect localRepaintRect = paintInfo.rect;
+    localRepaintRect.inflate(maximalOutlineSize(paintInfo.phase));
+    if (adjustedPaintOffset.x() + visualOverflowRect().x() >= localRepaintRect.maxX() || adjustedPaintOffset.x() + visualOverflowRect().maxX() <= localRepaintRect.x())
+        return false;
+
+    if (top >= localRepaintRect.maxY() || bottom <= localRepaintRect.y())
+        return false;
+
+    return true;
+}
+
+static inline RenderBlock* firstContainingBlockWithLogicalWidth(const RenderReplaced* replaced)
+{
+    // We have to lookup the containing block, which has an explicit width, which must not be equal to our direct containing block.
+    // If the embedded document appears _after_ we performed the initial layout, our intrinsic size is 300x150. If our containing
+    // block doesn't provide an explicit width, it's set to the 300 default, coming from the initial layout run.
+    RenderBlock* containingBlock = replaced->containingBlock();
+    if (!containingBlock)
+        return 0;
+
+    for (; !containingBlock->isRenderView() && !containingBlock->isBody(); containingBlock = containingBlock->containingBlock()) {
+        if (containingBlock->style()->logicalWidth().isSpecified())
+            return containingBlock;
+    }
+
+    return 0;
+}
+
+bool RenderReplaced::hasReplacedLogicalWidth() const
+{
+    if (style()->logicalWidth().isSpecified())
+        return true;
+
+    if (style()->logicalWidth().isAuto())
+        return false;
+
+    return firstContainingBlockWithLogicalWidth(this);
+}
+
+bool RenderReplaced::hasReplacedLogicalHeight() const
+{
+    if (style()->logicalHeight().isAuto())
+        return false;
+
+    if (style()->logicalHeight().isSpecified()) {
+        if (hasAutoHeightOrContainingBlockWithAutoHeight())
+            return false;
+        return true;
+    }
+
+    if (style()->logicalHeight().isIntrinsic())
+        return true;
+
+    return false;
+}
+
+static inline bool rendererHasAspectRatio(const RenderObject* renderer)
+{
+    ASSERT(renderer);
+    return renderer->isImage() || renderer->isCanvas() || renderer->isVideo();
+}
+
+void RenderReplaced::computeAspectRatioInformationForRenderBox(RenderBox* contentRenderer, FloatSize& constrainedSize, double& intrinsicRatio, bool& isPercentageIntrinsicSize) const
+{
+    FloatSize intrinsicSize;
+    if (contentRenderer) {
+        contentRenderer->computeIntrinsicRatioInformation(intrinsicSize, intrinsicRatio, isPercentageIntrinsicSize);
+        if (intrinsicRatio)
+            ASSERT(!isPercentageIntrinsicSize);
+
+        // Handle zoom & vertical writing modes here, as the embedded document doesn't know about them.
+        if (!isPercentageIntrinsicSize)
+            intrinsicSize.scale(style()->effectiveZoom());
+
+        if (rendererHasAspectRatio(this) && isPercentageIntrinsicSize)
+            intrinsicRatio = 1;
+            
+        // Update our intrinsic size to match what the content renderer has computed, so that when we
+        // constrain the size below, the correct intrinsic size will be obtained for comparison against
+        // min and max widths.
+        if (intrinsicRatio && !isPercentageIntrinsicSize && !intrinsicSize.isEmpty())
+            m_intrinsicSize = LayoutSize(intrinsicSize);
+
+        if (!isHorizontalWritingMode()) {
+            if (intrinsicRatio)
+                intrinsicRatio = 1 / intrinsicRatio;
+            intrinsicSize = intrinsicSize.transposedSize();
+        }
+    } else {
+        computeIntrinsicRatioInformation(intrinsicSize, intrinsicRatio, isPercentageIntrinsicSize);
+        if (intrinsicRatio) {
+            ASSERT(!isPercentageIntrinsicSize);
+            if (!intrinsicSize.isEmpty())
+                m_intrinsicSize = LayoutSize(isHorizontalWritingMode() ? intrinsicSize : intrinsicSize.transposedSize());
+        }
+    }
+
+    // Now constrain the intrinsic size along each axis according to minimum and maximum width/heights along the
+    // opposite axis. So for example a maximum width that shrinks our width will result in the height we compute here
+    // having to shrink in order to preserve the aspect ratio. Because we compute these values independently along
+    // each axis, the final returned size may in fact not preserve the aspect ratio.
+    // FIXME: In the long term, it might be better to just return this code more to the way it used to be before this
+    // function was added, since all it has done is make the code more unclear.
+    constrainedSize = intrinsicSize;
+    if (intrinsicRatio && !isPercentageIntrinsicSize && !intrinsicSize.isEmpty() && style()->logicalWidth().isAuto() && style()->logicalHeight().isAuto()) {
+        // We can't multiply or divide by 'intrinsicRatio' here, it breaks tests, like fast/images/zoomed-img-size.html, which
+        // can only be fixed once subpixel precision is available for things like intrinsicWidth/Height - which include zoom!
+        constrainedSize.setWidth(RenderBox::computeReplacedLogicalHeight() * intrinsicSize.width() / intrinsicSize.height());
+        constrainedSize.setHeight(RenderBox::computeReplacedLogicalWidth() * intrinsicSize.height() / intrinsicSize.width());
+    }
+}
+
+void RenderReplaced::computeIntrinsicRatioInformation(FloatSize& intrinsicSize, double& intrinsicRatio, bool& isPercentageIntrinsicSize) const
+{
+    // If there's an embeddedContentBox() of a remote, referenced document available, this code-path should never be used.
+    ASSERT(!embeddedContentBox());
+    isPercentageIntrinsicSize = false;
+    intrinsicSize = FloatSize(intrinsicLogicalWidth(), intrinsicLogicalHeight());
+
+    // Figure out if we need to compute an intrinsic ratio.
+    if (intrinsicSize.isEmpty() || !rendererHasAspectRatio(this))
+        return;
+
+    intrinsicRatio = intrinsicSize.width() / intrinsicSize.height();
+}
+
+LayoutUnit RenderReplaced::computeReplacedLogicalWidth(ShouldComputePreferred shouldComputePreferred) const
+{
+    if (style()->logicalWidth().isSpecified() || style()->logicalWidth().isIntrinsic())
+        return computeReplacedLogicalWidthRespectingMinMaxWidth(computeReplacedLogicalWidthUsing(style()->logicalWidth()), shouldComputePreferred);
+
+    RenderBox* contentRenderer = embeddedContentBox();
+
+    // 10.3.2 Inline, replaced elements: http://www.w3.org/TR/CSS21/visudet.html#inline-replaced-width
+    bool isPercentageIntrinsicSize = false;
+    double intrinsicRatio = 0;
+    FloatSize constrainedSize;
+    computeAspectRatioInformationForRenderBox(contentRenderer, constrainedSize, intrinsicRatio, isPercentageIntrinsicSize);
+
+    if (style()->logicalWidth().isAuto()) {
+        bool heightIsAuto = style()->logicalHeight().isAuto();
+        bool hasIntrinsicWidth = !isPercentageIntrinsicSize && constrainedSize.width() > 0;
+
+        // If 'height' and 'width' both have computed values of 'auto' and the element also has an intrinsic width, then that intrinsic width is the used value of 'width'.
+        if (heightIsAuto && hasIntrinsicWidth)
+            return computeReplacedLogicalWidthRespectingMinMaxWidth(constrainedSize.width(), shouldComputePreferred);
+
+        bool hasIntrinsicHeight = !isPercentageIntrinsicSize && constrainedSize.height() > 0;
+        if (intrinsicRatio || isPercentageIntrinsicSize) {
+            // If 'height' and 'width' both have computed values of 'auto' and the element has no intrinsic width, but does have an intrinsic height and intrinsic ratio;
+            // or if 'width' has a computed value of 'auto', 'height' has some other computed value, and the element does have an intrinsic ratio; then the used value
+            // of 'width' is: (used height) * (intrinsic ratio)
+            if (intrinsicRatio && ((heightIsAuto && !hasIntrinsicWidth && hasIntrinsicHeight) || !heightIsAuto)) {
+                LayoutUnit logicalHeight = computeReplacedLogicalHeight();
+                return computeReplacedLogicalWidthRespectingMinMaxWidth(roundToInt(round(logicalHeight * intrinsicRatio)), shouldComputePreferred);
+            }
+
+            // If 'height' and 'width' both have computed values of 'auto' and the element has an intrinsic ratio but no intrinsic height or width, then the used value of
+            // 'width' is undefined in CSS 2.1. However, it is suggested that, if the containing block's width does not itself depend on the replaced element's width, then
+            // the used value of 'width' is calculated from the constraint equation used for block-level, non-replaced elements in normal flow.
+            if (heightIsAuto && !hasIntrinsicWidth && !hasIntrinsicHeight) {
+                // The aforementioned 'constraint equation' used for block-level, non-replaced elements in normal flow:
+                // 'margin-left' + 'border-left-width' + 'padding-left' + 'width' + 'padding-right' + 'border-right-width' + 'margin-right' = width of containing block
+                LayoutUnit logicalWidth;
+                if (RenderBlock* blockWithWidth = firstContainingBlockWithLogicalWidth(this))
+                    logicalWidth = blockWithWidth->computeReplacedLogicalWidthRespectingMinMaxWidth(blockWithWidth->computeReplacedLogicalWidthUsing(blockWithWidth->style()->logicalWidth()), shouldComputePreferred);
+                else
+                    logicalWidth = containingBlock()->availableLogicalWidth();
+
+                // This solves above equation for 'width' (== logicalWidth).
+                LayoutUnit marginStart = minimumValueForLength(style()->marginStart(), logicalWidth);
+                LayoutUnit marginEnd = minimumValueForLength(style()->marginEnd(), logicalWidth);
+                logicalWidth = max<LayoutUnit>(0, logicalWidth - (marginStart + marginEnd + (width() - clientWidth())));
+                if (isPercentageIntrinsicSize)
+                    logicalWidth = logicalWidth * constrainedSize.width() / 100;
+                return computeReplacedLogicalWidthRespectingMinMaxWidth(logicalWidth, shouldComputePreferred);
+            }
+        }
+
+        // Otherwise, if 'width' has a computed value of 'auto', and the element has an intrinsic width, then that intrinsic width is the used value of 'width'.
+        if (hasIntrinsicWidth)
+            return computeReplacedLogicalWidthRespectingMinMaxWidth(constrainedSize.width(), shouldComputePreferred);
+
+        // Otherwise, if 'width' has a computed value of 'auto', but none of the conditions above are met, then the used value of 'width' becomes 300px. If 300px is too
+        // wide to fit the device, UAs should use the width of the largest rectangle that has a 2:1 ratio and fits the device instead.
+        // Note: We fall through and instead return intrinsicLogicalWidth() here - to preserve existing WebKit behavior, which might or might not be correct, or desired.
+        // Changing this to return cDefaultWidth, will affect lots of test results. Eg. some tests assume that a blank <img> tag (which implies width/height=auto)
+        // has no intrinsic size, which is wrong per CSS 2.1, but matches our behavior since a long time.
+    }
+
+    return computeReplacedLogicalWidthRespectingMinMaxWidth(intrinsicLogicalWidth(), shouldComputePreferred);
+}
+
+LayoutUnit RenderReplaced::computeReplacedLogicalHeight() const
+{
+    // 10.5 Content height: the 'height' property: http://www.w3.org/TR/CSS21/visudet.html#propdef-height
+    if (hasReplacedLogicalHeight())
+        return computeReplacedLogicalHeightRespectingMinMaxHeight(computeReplacedLogicalHeightUsing(style()->logicalHeight()));
+
+    RenderBox* contentRenderer = embeddedContentBox();
+
+    // 10.6.2 Inline, replaced elements: http://www.w3.org/TR/CSS21/visudet.html#inline-replaced-height
+    bool isPercentageIntrinsicSize = false;
+    double intrinsicRatio = 0;
+    FloatSize constrainedSize;
+    computeAspectRatioInformationForRenderBox(contentRenderer, constrainedSize, intrinsicRatio, isPercentageIntrinsicSize);
+
+    bool widthIsAuto = style()->logicalWidth().isAuto();
+    bool hasIntrinsicHeight = !isPercentageIntrinsicSize && constrainedSize.height() > 0;
+
+    // If 'height' and 'width' both have computed values of 'auto' and the element also has an intrinsic height, then that intrinsic height is the used value of 'height'.
+    if (widthIsAuto && hasIntrinsicHeight)
+        return computeReplacedLogicalHeightRespectingMinMaxHeight(constrainedSize.height());
+
+    // Otherwise, if 'height' has a computed value of 'auto', and the element has an intrinsic ratio then the used value of 'height' is:
+    // (used width) / (intrinsic ratio)
+    if (intrinsicRatio)
+        return computeReplacedLogicalHeightRespectingMinMaxHeight(roundToInt(round(availableLogicalWidth() / intrinsicRatio)));
+
+    // Otherwise, if 'height' has a computed value of 'auto', and the element has an intrinsic height, then that intrinsic height is the used value of 'height'.
+    if (hasIntrinsicHeight)
+        return computeReplacedLogicalHeightRespectingMinMaxHeight(constrainedSize.height());
+
+    // Otherwise, if 'height' has a computed value of 'auto', but none of the conditions above are met, then the used value of 'height' must be set to the height
+    // of the largest rectangle that has a 2:1 ratio, has a height not greater than 150px, and has a width not greater than the device width.
+    return computeReplacedLogicalHeightRespectingMinMaxHeight(intrinsicLogicalHeight());
+}
+
+void RenderReplaced::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const
+{
+    minLogicalWidth = maxLogicalWidth = intrinsicLogicalWidth();
+}
+
+void RenderReplaced::computePreferredLogicalWidths()
+{
+    ASSERT(preferredLogicalWidthsDirty());
+
+    // We cannot resolve any percent logical width here as the available logical
+    // width may not be set on our containing block.
+    if (style()->logicalWidth().isPercent())
+        computeIntrinsicLogicalWidths(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);
+    else
+        m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = computeReplacedLogicalWidth(ComputePreferred);
+
+    RenderStyle* styleToUse = style();
+    if (styleToUse->logicalWidth().isPercent() || styleToUse->logicalMaxWidth().isPercent() || hasRelativeIntrinsicLogicalWidth())
+        m_minPreferredLogicalWidth = 0;
+
+    if (styleToUse->logicalMinWidth().isFixed() && styleToUse->logicalMinWidth().value() > 0) {
+        m_maxPreferredLogicalWidth = max(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->logicalMinWidth().value()));
+        m_minPreferredLogicalWidth = max(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->logicalMinWidth().value()));
+    }
+    
+    if (styleToUse->logicalMaxWidth().isFixed()) {
+        m_maxPreferredLogicalWidth = min(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->logicalMaxWidth().value()));
+        m_minPreferredLogicalWidth = min(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->logicalMaxWidth().value()));
+    }
+
+    LayoutUnit borderAndPadding = borderAndPaddingLogicalWidth();
+    m_minPreferredLogicalWidth += borderAndPadding;
+    m_maxPreferredLogicalWidth += borderAndPadding;
+
+    setPreferredLogicalWidthsDirty(false);
+}
+
+VisiblePosition RenderReplaced::positionForPoint(const LayoutPoint& point)
+{
+    // FIXME: This code is buggy if the replaced element is relative positioned.
+    InlineBox* box = inlineBoxWrapper();
+    RootInlineBox* rootBox = box ? box->root() : 0;
+    
+    LayoutUnit top = rootBox ? rootBox->selectionTop() : logicalTop();
+    LayoutUnit bottom = rootBox ? rootBox->selectionBottom() : logicalBottom();
+    
+    LayoutUnit blockDirectionPosition = isHorizontalWritingMode() ? point.y() + y() : point.x() + x();
+    LayoutUnit lineDirectionPosition = isHorizontalWritingMode() ? point.x() + x() : point.y() + y();
+    
+    if (blockDirectionPosition < top)
+        return createVisiblePosition(caretMinOffset(), DOWNSTREAM); // coordinates are above
+    
+    if (blockDirectionPosition >= bottom)
+        return createVisiblePosition(caretMaxOffset(), DOWNSTREAM); // coordinates are below
+    
+    if (node()) {
+        if (lineDirectionPosition <= logicalLeft() + (logicalWidth() / 2))
+            return createVisiblePosition(0, DOWNSTREAM);
+        return createVisiblePosition(1, DOWNSTREAM);
+    }
+
+    return RenderBox::positionForPoint(point);
+}
+
+LayoutRect RenderReplaced::selectionRectForRepaint(const RenderLayerModelObject* repaintContainer, bool clipToVisibleContent)
+{
+    ASSERT(!needsLayout());
+
+    if (!isSelected())
+        return LayoutRect();
+    
+    LayoutRect rect = localSelectionRect();
+    if (clipToVisibleContent)
+        computeRectForRepaint(repaintContainer, rect);
+    else
+        rect = localToContainerQuad(FloatRect(rect), repaintContainer).enclosingBoundingBox();
+    
+    return rect;
+}
+
+LayoutRect RenderReplaced::localSelectionRect(bool checkWhetherSelected) const
+{
+    if (checkWhetherSelected && !isSelected())
+        return LayoutRect();
+
+    if (!m_inlineBoxWrapper)
+        // We're a block-level replaced element.  Just return our own dimensions.
+        return LayoutRect(LayoutPoint(), size());
+    
+    RootInlineBox* root = m_inlineBoxWrapper->root();
+    LayoutUnit newLogicalTop = root->block()->style()->isFlippedBlocksWritingMode() ? m_inlineBoxWrapper->logicalBottom() - root->selectionBottom() : root->selectionTop() - m_inlineBoxWrapper->logicalTop();
+    if (root->block()->style()->isHorizontalWritingMode())
+        return LayoutRect(0, newLogicalTop, width(), root->selectionHeight());
+    return LayoutRect(newLogicalTop, 0, root->selectionHeight(), height());
+}
+
+void RenderReplaced::setSelectionState(SelectionState state)
+{
+    // The selection state for our containing block hierarchy is updated by the base class call.
+    RenderBox::setSelectionState(state);
+
+    if (m_inlineBoxWrapper && canUpdateSelectionOnRootLineBoxes())
+        if (RootInlineBox* root = m_inlineBoxWrapper->root())
+            root->setHasSelectedChildren(isSelected());
+}
+
+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 = node()->hasChildNodes() ? node()->childNodeCount() : 1;
+    if (s == SelectionEnd)
+        return selectionEnd == end;
+    if (s == SelectionBoth)
+        return selectionStart == 0 && selectionEnd == end;
+        
+    ASSERT(0);
+    return false;
+}
+
+LayoutRect RenderReplaced::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const
+{
+    if (style()->visibility() != VISIBLE && !enclosingLayer()->hasVisibleContent())
+        return LayoutRect();
+
+    // The selectionRect can project outside of the overflowRect, so take their union
+    // for repainting to avoid selection painting glitches.
+    LayoutRect r = unionRect(localSelectionRect(false), visualOverflowRect());
+
+    RenderView* v = view();
+    if (v) {
+        // FIXME: layoutDelta needs to be applied in parts before/after transforms and
+        // repaint containers. https://bugs.webkit.org/show_bug.cgi?id=23308
+        r.move(v->layoutDelta());
+    }
+
+    if (style()) {
+        if (v)
+            r.inflate(style()->outlineSize());
+    }
+    computeRectForRepaint(repaintContainer, r);
+    return r;
+}
+
+void RenderReplaced::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, PlatformMemoryTypes::Rendering);
+    RenderBox::reportMemoryUsage(memoryObjectInfo);
+}
+
+}
diff --git a/Source/core/rendering/RenderReplaced.h b/Source/core/rendering/RenderReplaced.h
new file mode 100644
index 0000000..7c1e223
--- /dev/null
+++ b/Source/core/rendering/RenderReplaced.h
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2009 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 RenderReplaced_h
+#define RenderReplaced_h
+
+#include "core/rendering/RenderBox.h"
+
+namespace WebCore {
+
+class RenderReplaced : public RenderBox {
+public:
+    RenderReplaced(Element*);
+    RenderReplaced(Element*, const LayoutSize& intrinsicSize);
+    virtual ~RenderReplaced();
+
+    virtual LayoutUnit computeReplacedLogicalWidth(ShouldComputePreferred  = ComputeActual) const OVERRIDE;
+    virtual LayoutUnit computeReplacedLogicalHeight() const;
+
+    bool hasReplacedLogicalWidth() const;
+    bool hasReplacedLogicalHeight() const;
+
+    virtual void reportMemoryUsage(MemoryObjectInfo*) const OVERRIDE FINAL;
+
+protected:
+    virtual void willBeDestroyed();
+
+    virtual void layout();
+
+    virtual LayoutSize intrinsicSize() const OVERRIDE FINAL { return m_intrinsicSize; }
+    virtual void computeIntrinsicRatioInformation(FloatSize& intrinsicSize, double& intrinsicRatio, bool& isPercentageIntrinsicSize) const;
+
+    virtual void computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const OVERRIDE FINAL;
+
+    virtual LayoutUnit minimumReplacedHeight() const { return LayoutUnit(); }
+
+    virtual void setSelectionState(SelectionState) OVERRIDE FINAL;
+
+    bool isSelected() const;
+
+    virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+
+    void setIntrinsicSize(const LayoutSize& intrinsicSize) { m_intrinsicSize = intrinsicSize; }
+    virtual void intrinsicSizeChanged();
+    virtual bool hasRelativeIntrinsicLogicalWidth() const { return false; }
+
+    virtual void paint(PaintInfo&, const LayoutPoint&);
+    bool shouldPaint(PaintInfo&, const LayoutPoint&);
+    LayoutRect localSelectionRect(bool checkWhetherSelected = true) const; // This is in local coordinates, but it's a physical rect (so the top left corner is physical top left).
+
+private:
+    virtual RenderBox* embeddedContentBox() const { return 0; }
+    virtual const char* renderName() const { return "RenderReplaced"; }
+
+    virtual bool canHaveChildren() const { return false; }
+
+    virtual void computePreferredLogicalWidths() OVERRIDE FINAL;
+    virtual void paintReplaced(PaintInfo&, const LayoutPoint&) { }
+
+    virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const OVERRIDE;
+
+    virtual VisiblePosition positionForPoint(const LayoutPoint&) OVERRIDE FINAL;
+    
+    virtual bool canBeSelectionLeaf() const { return true; }
+
+    virtual LayoutRect selectionRectForRepaint(const RenderLayerModelObject* repaintContainer, bool clipToVisibleContent = true) OVERRIDE FINAL;
+    void computeAspectRatioInformationForRenderBox(RenderBox*, FloatSize& constrainedSize, double& intrinsicRatio, bool& isPercentageIntrinsicSize) const;
+
+    mutable LayoutSize m_intrinsicSize;
+};
+
+}
+
+#endif
diff --git a/Source/core/rendering/RenderReplica.cpp b/Source/core/rendering/RenderReplica.cpp
new file mode 100644
index 0000000..5f19135
--- /dev/null
+++ b/Source/core/rendering/RenderReplica.cpp
@@ -0,0 +1,90 @@
+/*
+ * 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 "core/rendering/RenderReplica.h"
+
+#include "core/rendering/RenderLayer.h"
+
+namespace WebCore {
+
+RenderReplica::RenderReplica()
+    : RenderBox(0)
+{
+    // This is a hack. Replicas are synthetic, and don't pick up the attributes of the
+    // renderers being replicated, so they always report that they are inline, non-replaced.
+    // However, we need transforms to be applied to replicas for reflections, so have to pass
+    // the if (!isInline() || isReplaced()) check before setHasTransform().
+    setReplaced(true);
+}
+
+RenderReplica* RenderReplica::createAnonymous(Document* document)
+{
+    RenderReplica* renderer = new (document->renderArena()) RenderReplica();
+    renderer->setDocumentForAnonymous(document);
+    return renderer;
+}
+
+RenderReplica::~RenderReplica()
+{
+}
+    
+void RenderReplica::layout()
+{
+    StackStats::LayoutCheckPoint layoutCheckPoint;
+    setFrameRect(parentBox()->borderBoxRect());
+    updateLayerTransform();
+    setNeedsLayout(false);
+}
+
+void RenderReplica::computePreferredLogicalWidths()
+{
+    m_minPreferredLogicalWidth = parentBox()->width();
+    m_maxPreferredLogicalWidth = m_minPreferredLogicalWidth;
+    setPreferredLogicalWidthsDirty(false);
+}
+
+void RenderReplica::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    if (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseMask)
+        return;
+ 
+    LayoutPoint adjustedPaintOffset = paintOffset + location();
+
+    if (paintInfo.phase == PaintPhaseForeground) {
+        // Turn around and paint the parent layer. Use temporary clipRects, so that the layer doesn't end up caching clip rects
+        // computing using the wrong rootLayer
+        RenderLayer* rootPaintingLayer = layer()->transform() ? layer()->parent() : layer()->enclosingTransformedAncestor();
+        RenderLayer::LayerPaintingInfo paintingInfo(rootPaintingLayer, paintInfo.rect, PaintBehaviorNormal, LayoutSize(), 0, paintInfo.renderRegion);
+        RenderLayer::PaintLayerFlags flags = RenderLayer::PaintLayerHaveTransparency | RenderLayer::PaintLayerAppliedTransform | RenderLayer::PaintLayerTemporaryClipRects | RenderLayer::PaintLayerPaintingReflection;
+        layer()->parent()->paintLayer(paintInfo.context, paintingInfo, flags);
+    } else if (paintInfo.phase == PaintPhaseMask)
+        paintMask(paintInfo, adjustedPaintOffset);
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderReplica.h b/Source/core/rendering/RenderReplica.h
new file mode 100644
index 0000000..365e424
--- /dev/null
+++ b/Source/core/rendering/RenderReplica.h
@@ -0,0 +1,60 @@
+/*
+ * 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 "core/rendering/RenderBox.h"
+
+namespace WebCore {
+
+class RenderReplica FINAL : public RenderBox {
+public:
+    static RenderReplica* createAnonymous(Document*);
+
+    virtual ~RenderReplica();
+
+    virtual const char* renderName() const { return "RenderReplica"; }
+    
+    virtual bool requiresLayer() const { return true; }
+
+    virtual void layout();
+    
+    virtual void paint(PaintInfo&, const LayoutPoint&);
+
+private:
+    RenderReplica();
+
+    virtual bool isReplica() const { return true; }
+    virtual void computePreferredLogicalWidths();
+
+};
+
+} // namespace WebCore
+
+#endif // RenderReplica_h
diff --git a/Source/core/rendering/RenderRuby.cpp b/Source/core/rendering/RenderRuby.cpp
new file mode 100644
index 0000000..9470c4e
--- /dev/null
+++ b/Source/core/rendering/RenderRuby.cpp
@@ -0,0 +1,322 @@
+/*
+ * Copyright (C) 2009 Google 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:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+ * OWNER 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 "core/rendering/RenderRuby.h"
+
+#include "core/rendering/RenderRubyRun.h"
+#include "core/rendering/style/RenderStyle.h"
+#include "core/rendering/style/StyleInheritedData.h"
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+//=== generic helper functions to avoid excessive code duplication ===
+
+static inline bool isAnonymousRubyInlineBlock(const RenderObject* object)
+{
+    ASSERT(!object
+        || !object->parent()->isRuby()
+        || object->isRubyRun()
+        || (object->isInline() && (object->isBeforeContent() || object->isAfterContent()))
+        || (object->isAnonymous() && object->isRenderBlock() && object->style()->display() == INLINE_BLOCK));
+
+    return object
+        && object->parent()->isRuby()
+        && object->isRenderBlock()
+        && !object->isRubyRun();
+}
+
+static inline bool isRubyBeforeBlock(const RenderObject* object)
+{
+    return isAnonymousRubyInlineBlock(object)
+        && !object->previousSibling()
+        && object->firstChild()
+        && object->firstChild()->style()->styleType() == BEFORE;
+}
+
+static inline bool isRubyAfterBlock(const RenderObject* object)
+{
+    return isAnonymousRubyInlineBlock(object)
+        && !object->nextSibling()
+        && object->firstChild()
+        && object->firstChild()->style()->styleType() == AFTER;
+}
+
+static inline RenderBlock* rubyBeforeBlock(const RenderObject* ruby)
+{
+    RenderObject* child = ruby->firstChild();
+    return isRubyBeforeBlock(child) ? toRenderBlock(child) : 0;
+}
+
+static inline RenderBlock* rubyAfterBlock(const RenderObject* ruby)
+{
+    RenderObject* child = ruby->lastChild();
+    return isRubyAfterBlock(child) ? toRenderBlock(child) : 0;
+}
+
+static RenderBlock* createAnonymousRubyInlineBlock(RenderObject* ruby)
+{
+    RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(ruby->style(), INLINE_BLOCK);
+    RenderBlock* newBlock = RenderBlock::createAnonymous(ruby->document());
+    newBlock->setStyle(newStyle.release());
+    return newBlock;
+}
+
+static RenderRubyRun* lastRubyRun(const RenderObject* ruby)
+{
+    RenderObject* child = ruby->lastChild();
+    if (child && !child->isRubyRun())
+        child = child->previousSibling();
+    ASSERT(!child || child->isRubyRun() || child->isBeforeContent() || child == rubyBeforeBlock(ruby));
+    return child && child->isRubyRun() ? toRenderRubyRun(child) : 0;
+}
+
+static inline RenderRubyRun* findRubyRunParent(RenderObject* child)
+{
+    while (child && !child->isRubyRun())
+        child = child->parent();
+    return toRenderRubyRun(child);
+}
+
+//=== ruby as inline object ===
+
+RenderRubyAsInline::RenderRubyAsInline(Element* element)
+    : RenderInline(element)
+{
+}
+
+RenderRubyAsInline::~RenderRubyAsInline()
+{
+}
+
+void RenderRubyAsInline::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
+{
+    RenderInline::styleDidChange(diff, oldStyle);
+    propagateStyleToAnonymousChildren();
+}
+
+void RenderRubyAsInline::addChild(RenderObject* child, RenderObject* beforeChild)
+{
+    // Insert :before and :after content before/after the RenderRubyRun(s)
+    if (child->isBeforeContent()) {
+        if (child->isInline()) {
+            // Add generated inline content normally
+            RenderInline::addChild(child, firstChild());
+        } else {
+            // Wrap non-inline content with an anonymous inline-block.
+            RenderBlock* beforeBlock = rubyBeforeBlock(this);
+            if (!beforeBlock) {
+                beforeBlock = createAnonymousRubyInlineBlock(this);
+                RenderInline::addChild(beforeBlock, firstChild());
+            }
+            beforeBlock->addChild(child);
+        }
+        return;
+    }
+    if (child->isAfterContent()) {
+        if (child->isInline()) {
+            // Add generated inline content normally
+            RenderInline::addChild(child);
+        } else {
+            // Wrap non-inline content with an anonymous inline-block.
+            RenderBlock* afterBlock = rubyAfterBlock(this);
+            if (!afterBlock) {
+                afterBlock = createAnonymousRubyInlineBlock(this);
+                RenderInline::addChild(afterBlock);
+            }
+            afterBlock->addChild(child);
+        }
+        return;
+    }
+
+    // If the child is a ruby run, just add it normally.
+    if (child->isRubyRun()) {
+        RenderInline::addChild(child, beforeChild);
+        return;
+    }
+
+    if (beforeChild && !isAfterContent(beforeChild)) {
+        // insert child into run
+        ASSERT(!beforeChild->isRubyRun());
+        RenderObject* run = beforeChild;
+        while (run && !run->isRubyRun())
+            run = run->parent();
+        if (run) {
+            run->addChild(child, beforeChild);
+            return;
+        }
+        ASSERT_NOT_REACHED(); // beforeChild should always have a run as parent!
+        // Emergency fallback: fall through and just append.
+    }
+
+    // If the new child would be appended, try to add the child to the previous run
+    // if possible, or create a new run otherwise.
+    // (The RenderRubyRun object will handle the details)
+    RenderRubyRun* lastRun = lastRubyRun(this);
+    if (!lastRun || lastRun->hasRubyText()) {
+        lastRun = RenderRubyRun::staticCreateRubyRun(this);
+        RenderInline::addChild(lastRun, beforeChild);
+    }
+    lastRun->addChild(child);
+}
+
+void RenderRubyAsInline::removeChild(RenderObject* child)
+{
+    // If the child's parent is *this (must be a ruby run or generated content or anonymous block),
+    // just use the normal remove method.
+    if (child->parent() == this) {
+        ASSERT(child->isRubyRun() || child->isBeforeContent() || child->isAfterContent() || isAnonymousRubyInlineBlock(child));
+        RenderInline::removeChild(child);
+        return;
+    }
+    // If the child's parent is an anoymous block (must be generated :before/:after content)
+    // just use the block's remove method.
+    if (isAnonymousRubyInlineBlock(child->parent())) {
+        ASSERT(child->isBeforeContent() || child->isAfterContent());
+        child->parent()->removeChild(child);
+        removeChild(child->parent());
+        return;
+    }
+
+    // Otherwise find the containing run and remove it from there.
+    RenderRubyRun* run = findRubyRunParent(child);
+    ASSERT(run);
+    run->removeChild(child);
+}
+
+//=== ruby as block object ===
+
+RenderRubyAsBlock::RenderRubyAsBlock(Element* element)
+    : RenderBlock(element)
+{
+}
+
+RenderRubyAsBlock::~RenderRubyAsBlock()
+{
+}
+
+void RenderRubyAsBlock::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
+{
+    RenderBlock::styleDidChange(diff, oldStyle);
+    propagateStyleToAnonymousChildren();
+}
+
+void RenderRubyAsBlock::addChild(RenderObject* child, RenderObject* beforeChild)
+{
+    // Insert :before and :after content before/after the RenderRubyRun(s)
+    if (child->isBeforeContent()) {
+        if (child->isInline()) {
+            // Add generated inline content normally
+            RenderBlock::addChild(child, firstChild());
+        } else {
+            // Wrap non-inline content with an anonymous inline-block.
+            RenderBlock* beforeBlock = rubyBeforeBlock(this);
+            if (!beforeBlock) {
+                beforeBlock = createAnonymousRubyInlineBlock(this);
+                RenderBlock::addChild(beforeBlock, firstChild());
+            }
+            beforeBlock->addChild(child);
+        }
+        return;
+    }
+    if (child->isAfterContent()) {
+        if (child->isInline()) {
+            // Add generated inline content normally
+            RenderBlock::addChild(child);
+        } else {
+            // Wrap non-inline content with an anonymous inline-block.
+            RenderBlock* afterBlock = rubyAfterBlock(this);
+            if (!afterBlock) {
+                afterBlock = createAnonymousRubyInlineBlock(this);
+                RenderBlock::addChild(afterBlock);
+            }
+            afterBlock->addChild(child);
+        }
+        return;
+    }
+
+    // If the child is a ruby run, just add it normally.
+    if (child->isRubyRun()) {
+        RenderBlock::addChild(child, beforeChild);
+        return;
+    }
+
+    if (beforeChild && !isAfterContent(beforeChild)) {
+        // insert child into run
+        ASSERT(!beforeChild->isRubyRun());
+        RenderObject* run = beforeChild;
+        while (run && !run->isRubyRun())
+            run = run->parent();
+        if (run) {
+            run->addChild(child, beforeChild);
+            return;
+        }
+        ASSERT_NOT_REACHED(); // beforeChild should always have a run as parent!
+        // Emergency fallback: fall through and just append.
+    }
+
+    // If the new child would be appended, try to add the child to the previous run
+    // if possible, or create a new run otherwise.
+    // (The RenderRubyRun object will handle the details)
+    RenderRubyRun* lastRun = lastRubyRun(this);
+    if (!lastRun || lastRun->hasRubyText()) {
+        lastRun = RenderRubyRun::staticCreateRubyRun(this);
+        RenderBlock::addChild(lastRun, beforeChild);
+    }
+    lastRun->addChild(child);
+}
+
+void RenderRubyAsBlock::removeChild(RenderObject* child)
+{
+    // If the child's parent is *this (must be a ruby run or generated content or anonymous block),
+    // just use the normal remove method.
+    if (child->parent() == this) {
+        ASSERT(child->isRubyRun() || child->isBeforeContent() || child->isAfterContent() || isAnonymousRubyInlineBlock(child));
+        RenderBlock::removeChild(child);
+        return;
+    }
+    // If the child's parent is an anoymous block (must be generated :before/:after content)
+    // just use the block's remove method.
+    if (isAnonymousRubyInlineBlock(child->parent())) {
+        ASSERT(child->isBeforeContent() || child->isAfterContent());
+        child->parent()->removeChild(child);
+        removeChild(child->parent());
+        return;
+    }
+
+    // Otherwise find the containing run and remove it from there.
+    RenderRubyRun* run = findRubyRunParent(child);
+    ASSERT(run);
+    run->removeChild(child);
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderRuby.h b/Source/core/rendering/RenderRuby.h
new file mode 100644
index 0000000..e254b05
--- /dev/null
+++ b/Source/core/rendering/RenderRuby.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2009 Google 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:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+ * OWNER 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 RenderRuby_h
+#define RenderRuby_h
+
+#include "core/rendering/RenderBlock.h"
+#include "core/rendering/RenderInline.h"
+
+namespace WebCore {
+
+// Following the HTML 5 spec, the box object model for a <ruby> element allows several runs of ruby
+// bases with their respective ruby texts looks as follows:
+//
+// 1 RenderRuby object, corresponding to the whole <ruby> HTML element
+//      1+ RenderRubyRun (anonymous)
+//          0 or 1 RenderRubyText - shuffled to the front in order to re-use existing block layouting
+//              0-n inline object(s)
+//          0 or 1 RenderRubyBase - contains the inline objects that make up the ruby base
+//              1-n inline object(s)
+//
+// Note: <rp> elements are defined as having 'display:none' and thus normally are not assigned a renderer.
+//
+// Generated :before/:after content is shunted into anonymous inline blocks
+
+// <ruby> when used as 'display:inline'
+class RenderRubyAsInline FINAL : public RenderInline {
+public:
+    RenderRubyAsInline(Element*);
+    virtual ~RenderRubyAsInline();
+
+    virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0);
+    virtual void removeChild(RenderObject* child);
+
+protected:
+    virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+
+private:
+    virtual bool isRuby() const { return true; }
+    virtual const char* renderName() const { return "RenderRuby (inline)"; }
+    virtual bool createsAnonymousWrapper() const { return true; }
+    virtual void removeLeftoverAnonymousBlock(RenderBlock*) { ASSERT_NOT_REACHED(); }
+};
+
+// <ruby> when used as 'display:block' or 'display:inline-block'
+class RenderRubyAsBlock FINAL : public RenderBlock {
+public:
+    RenderRubyAsBlock(Element*);
+    virtual ~RenderRubyAsBlock();
+
+    virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0);
+    virtual void removeChild(RenderObject* child);
+
+protected:
+    virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+
+private:
+    virtual bool isRuby() const { return true; }
+    virtual const char* renderName() const { return "RenderRuby (block)"; }
+    virtual bool createsAnonymousWrapper() const { return true; }
+    virtual void removeLeftoverAnonymousBlock(RenderBlock*) { ASSERT_NOT_REACHED(); }
+};
+
+} // namespace WebCore
+
+#endif // RenderRuby_h
diff --git a/Source/core/rendering/RenderRubyBase.cpp b/Source/core/rendering/RenderRubyBase.cpp
new file mode 100644
index 0000000..71b98c6
--- /dev/null
+++ b/Source/core/rendering/RenderRubyBase.cpp
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2009 Google 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:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+ * OWNER 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 "core/rendering/RenderRubyBase.h"
+#include "core/rendering/RenderRubyRun.h"
+#include "core/rendering/RenderRubyText.h"
+
+using namespace std;
+
+namespace WebCore {
+
+RenderRubyBase::RenderRubyBase()
+    : RenderBlock(0)
+{
+    setInline(false);
+}
+
+RenderRubyBase::~RenderRubyBase()
+{
+}
+
+RenderRubyBase* RenderRubyBase::createAnonymous(Document* document)
+{
+    RenderRubyBase* renderer = new (document->renderArena()) RenderRubyBase();
+    renderer->setDocumentForAnonymous(document);
+    return renderer;
+}
+
+bool RenderRubyBase::isChildAllowed(RenderObject* child, RenderStyle*) const
+{
+    return child->isInline();
+}
+
+void RenderRubyBase::moveChildren(RenderRubyBase* toBase, RenderObject* beforeChild)
+{
+    // This function removes all children that are before (!) beforeChild
+    // and appends them to toBase.
+    ASSERT_ARG(toBase, toBase);
+
+    if (beforeChild && beforeChild->parent() != this)
+        beforeChild = splitAnonymousBoxesAroundChild(beforeChild);
+
+    if (childrenInline())
+        moveInlineChildren(toBase, beforeChild);
+    else
+        moveBlockChildren(toBase, beforeChild);
+
+    setNeedsLayoutAndPrefWidthsRecalc();
+    toBase->setNeedsLayoutAndPrefWidthsRecalc();
+}
+
+void RenderRubyBase::moveInlineChildren(RenderRubyBase* toBase, RenderObject* beforeChild)
+{
+    ASSERT(childrenInline());
+    ASSERT_ARG(toBase, toBase);
+
+    if (!firstChild())
+        return;
+
+    RenderBlock* toBlock;
+    if (toBase->childrenInline()) {
+        // The standard and easy case: move the children into the target base
+        toBlock = toBase;
+    } else {
+        // We need to wrap the inline objects into an anonymous block.
+        // If toBase has a suitable block, we re-use it, otherwise create a new one.
+        RenderObject* lastChild = toBase->lastChild();
+        if (lastChild && lastChild->isAnonymousBlock() && lastChild->childrenInline())
+            toBlock = toRenderBlock(lastChild);
+        else {
+            toBlock = toBase->createAnonymousBlock();
+            toBase->children()->appendChildNode(toBase, toBlock);
+        }
+    }
+    // Move our inline children into the target block we determined above.
+    moveChildrenTo(toBlock, firstChild(), beforeChild);
+}
+
+void RenderRubyBase::moveBlockChildren(RenderRubyBase* toBase, RenderObject* beforeChild)
+{
+    ASSERT(!childrenInline());
+    ASSERT_ARG(toBase, toBase);
+
+    if (!firstChild())
+        return;
+
+    if (toBase->childrenInline())
+        toBase->makeChildrenNonInline();
+
+    // If an anonymous block would be put next to another such block, then merge those.
+    RenderObject* firstChildHere = firstChild();
+    RenderObject* lastChildThere = toBase->lastChild();
+    if (firstChildHere->isAnonymousBlock() && firstChildHere->childrenInline() 
+            && lastChildThere && lastChildThere->isAnonymousBlock() && lastChildThere->childrenInline()) {            
+        RenderBlock* anonBlockHere = toRenderBlock(firstChildHere);
+        RenderBlock* anonBlockThere = toRenderBlock(lastChildThere);
+        anonBlockHere->moveAllChildrenTo(anonBlockThere, anonBlockThere->children());
+        anonBlockHere->deleteLineBoxTree();
+        anonBlockHere->destroy();
+    }
+    // Move all remaining children normally.
+    moveChildrenTo(toBase, firstChild(), beforeChild);
+}
+
+RenderRubyRun* RenderRubyBase::rubyRun() const
+{
+    ASSERT(parent());
+    ASSERT(parent()->isRubyRun());
+
+    return toRenderRubyRun(parent());
+}
+
+ETextAlign RenderRubyBase::textAlignmentForLine(bool /* endsWithSoftBreak */) const
+{
+    return JUSTIFY;
+}
+
+void RenderRubyBase::adjustInlineDirectionLineBounds(int expansionOpportunityCount, float& logicalLeft, float& logicalWidth) const
+{
+    int maxPreferredLogicalWidth = this->maxPreferredLogicalWidth();
+    if (maxPreferredLogicalWidth >= logicalWidth)
+        return;
+
+    // Inset the ruby base by half the inter-ideograph expansion amount.
+    float inset = (logicalWidth - maxPreferredLogicalWidth) / (expansionOpportunityCount + 1);
+
+    logicalLeft += inset / 2;
+    logicalWidth -= inset;
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderRubyBase.h b/Source/core/rendering/RenderRubyBase.h
new file mode 100644
index 0000000..3a00b33
--- /dev/null
+++ b/Source/core/rendering/RenderRubyBase.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2009 Google 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:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+ * OWNER 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 RenderRubyBase_h
+#define RenderRubyBase_h
+
+#include "core/rendering/RenderBlock.h"
+
+namespace WebCore {
+
+class RenderRubyRun;
+
+class RenderRubyBase FINAL : public RenderBlock {
+public:
+    virtual ~RenderRubyBase();
+    
+    static RenderRubyBase* createAnonymous(Document*);
+
+    virtual const char* renderName() const { return "RenderRubyBase (anonymous)"; }
+
+    virtual bool isRubyBase() const { return true; }
+
+    virtual bool isChildAllowed(RenderObject*, RenderStyle*) const;
+
+private:
+    RenderRubyBase();
+
+    virtual ETextAlign textAlignmentForLine(bool endsWithSoftBreak) const;
+    virtual void adjustInlineDirectionLineBounds(int expansionOpportunityCount, float& logicalLeft, float& logicalWidth) const;
+
+    void moveChildren(RenderRubyBase* toBase, RenderObject* beforeChild = 0);
+    void moveInlineChildren(RenderRubyBase* toBase, RenderObject* beforeChild = 0);
+    void moveBlockChildren(RenderRubyBase* toBase, RenderObject* beforeChild = 0);
+
+    RenderRubyRun* rubyRun() const;
+
+    // Allow RenderRubyRun to manipulate the children within ruby bases.
+    friend class RenderRubyRun;
+};
+
+} // namespace WebCore
+
+#endif // RenderRubyBase_h
diff --git a/Source/core/rendering/RenderRubyRun.cpp b/Source/core/rendering/RenderRubyRun.cpp
new file mode 100644
index 0000000..8ae0453
--- /dev/null
+++ b/Source/core/rendering/RenderRubyRun.cpp
@@ -0,0 +1,321 @@
+/*
+ * Copyright (C) 2009 Google 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:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+ * OWNER 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 "core/rendering/RenderRubyRun.h"
+
+#include "core/rendering/RenderRubyBase.h"
+#include "core/rendering/RenderRubyText.h"
+#include "core/rendering/RenderText.h"
+#include "core/rendering/RenderView.h"
+#include "core/rendering/style/StyleInheritedData.h"
+
+using namespace std;
+
+namespace WebCore {
+
+RenderRubyRun::RenderRubyRun()
+    : RenderBlock(0)
+{
+    setReplaced(true);
+    setInline(true);
+}
+
+RenderRubyRun::~RenderRubyRun()
+{
+}
+
+bool RenderRubyRun::hasRubyText() const
+{
+    // The only place where a ruby text can be is in the first position
+    // Note: As anonymous blocks, ruby runs do not have ':before' or ':after' content themselves.
+    return firstChild() && firstChild()->isRubyText();
+}
+
+bool RenderRubyRun::hasRubyBase() const
+{
+    // The only place where a ruby base can be is in the last position
+    // Note: As anonymous blocks, ruby runs do not have ':before' or ':after' content themselves.
+    return lastChild() && lastChild()->isRubyBase();
+}
+
+bool RenderRubyRun::isEmpty() const
+{
+    return !hasRubyText() && !hasRubyBase();
+}
+
+RenderRubyText* RenderRubyRun::rubyText() const
+{
+    RenderObject* child = firstChild();
+    // If in future it becomes necessary to support floating or positioned ruby text,
+    // layout will have to be changed to handle them properly.
+    ASSERT(!child || !child->isRubyText() || !child->isFloatingOrOutOfFlowPositioned());
+    return child && child->isRubyText() ? static_cast<RenderRubyText*>(child) : 0;
+}
+
+RenderRubyBase* RenderRubyRun::rubyBase() const
+{
+    RenderObject* child = lastChild();
+    return child && child->isRubyBase() ? static_cast<RenderRubyBase*>(child) : 0;
+}
+
+RenderRubyBase* RenderRubyRun::rubyBaseSafe()
+{
+    RenderRubyBase* base = rubyBase();
+    if (!base) {
+        base = createRubyBase();
+        RenderBlock::addChild(base);
+    }
+    return base;
+}
+
+RenderBlock* RenderRubyRun::firstLineBlock() const
+{
+    return 0;
+}
+
+void RenderRubyRun::updateFirstLetter()
+{
+}
+
+bool RenderRubyRun::isChildAllowed(RenderObject* child, RenderStyle*) const
+{
+    return child->isRubyText() || child->isInline();
+}
+
+void RenderRubyRun::addChild(RenderObject* child, RenderObject* beforeChild)
+{
+    ASSERT(child);
+
+    if (child->isRubyText()) {
+        if (!beforeChild) {
+            // RenderRuby has already ascertained that we can add the child here.
+            ASSERT(!hasRubyText());
+            // prepend ruby texts as first child
+            RenderBlock::addChild(child, firstChild());
+        }  else if (beforeChild->isRubyText()) {
+            // New text is inserted just before another.
+            // In this case the new text takes the place of the old one, and
+            // the old text goes into a new run that is inserted as next sibling.
+            ASSERT(beforeChild->parent() == this);
+            RenderObject* ruby = parent();
+            ASSERT(ruby->isRuby());
+            RenderBlock* newRun = staticCreateRubyRun(ruby);
+            ruby->addChild(newRun, nextSibling());
+            // Add the new ruby text and move the old one to the new run
+            // Note: Doing it in this order and not using RenderRubyRun's methods,
+            // in order to avoid automatic removal of the ruby run in case there is no
+            // other child besides the old ruby text.
+            RenderBlock::addChild(child, beforeChild);
+            RenderBlock::removeChild(beforeChild);
+            newRun->addChild(beforeChild);
+        } else if (hasRubyBase()) {
+            // Insertion before a ruby base object.
+            // In this case we need insert a new run before the current one and split the base.
+            RenderObject* ruby = parent();
+            RenderRubyRun* newRun = staticCreateRubyRun(ruby);
+            ruby->addChild(newRun, this);
+            newRun->addChild(child);
+            rubyBaseSafe()->moveChildren(newRun->rubyBaseSafe(), beforeChild);
+        }
+    } else {
+        // child is not a text -> insert it into the base
+        // (append it instead if beforeChild is the ruby text)
+        if (beforeChild && beforeChild->isRubyText())
+            beforeChild = 0;
+        rubyBaseSafe()->addChild(child, beforeChild);
+    }
+}
+
+void RenderRubyRun::removeChild(RenderObject* child)
+{
+    // If the child is a ruby text, then merge the ruby base with the base of
+    // the right sibling run, if possible.
+    if (!beingDestroyed() && !documentBeingDestroyed() && child->isRubyText()) {
+        RenderRubyBase* base = rubyBase();
+        RenderObject* rightNeighbour = nextSibling();
+        if (base && rightNeighbour && rightNeighbour->isRubyRun()) {
+            // Ruby run without a base can happen only at the first run.
+            RenderRubyRun* rightRun = toRenderRubyRun(rightNeighbour);
+            if (rightRun->hasRubyBase()) {
+                RenderRubyBase* rightBase = rightRun->rubyBaseSafe();
+                // Collect all children in a single base, then swap the bases.
+                rightBase->moveChildren(base);
+                moveChildTo(rightRun, base);
+                rightRun->moveChildTo(this, rightBase);
+                // The now empty ruby base will be removed below.
+                ASSERT(!rubyBase()->firstChild());
+            }
+        }
+    }
+
+    RenderBlock::removeChild(child);
+
+    if (!beingDestroyed() && !documentBeingDestroyed()) {
+        // Check if our base (if any) is now empty. If so, destroy it.
+        RenderBlock* base = rubyBase();
+        if (base && !base->firstChild()) {
+            RenderBlock::removeChild(base);
+            base->deleteLineBoxTree();
+            base->destroy();
+        }
+
+        // If any of the above leaves the run empty, destroy it as well.
+        if (isEmpty()) {
+            parent()->removeChild(this);
+            deleteLineBoxTree();
+            destroy();
+        }
+    }
+}
+
+RenderRubyBase* RenderRubyRun::createRubyBase() const
+{
+    RenderRubyBase* renderer = RenderRubyBase::createAnonymous(document());
+    RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(style(), BLOCK);
+    newStyle->setTextAlign(CENTER); // FIXME: use WEBKIT_CENTER?
+    renderer->setStyle(newStyle.release());
+    return renderer;
+}
+
+RenderRubyRun* RenderRubyRun::staticCreateRubyRun(const RenderObject* parentRuby)
+{
+    ASSERT(parentRuby && parentRuby->isRuby());
+    RenderRubyRun* rr = new (parentRuby->renderArena()) RenderRubyRun();
+    rr->setDocumentForAnonymous(parentRuby->document());
+    RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(parentRuby->style(), INLINE_BLOCK);
+    rr->setStyle(newStyle.release());
+    return rr;
+}
+
+RenderObject* RenderRubyRun::layoutSpecialExcludedChild(bool relayoutChildren)
+{
+    StackStats::LayoutCheckPoint layoutCheckPoint;
+    // Don't bother positioning the RenderRubyRun yet.
+    RenderRubyText* rt = rubyText();
+    if (!rt)
+        return 0;
+    if (relayoutChildren)
+        rt->setChildNeedsLayout(true, MarkOnlyThis);
+    rt->layoutIfNeeded();
+    return rt;
+}
+
+void RenderRubyRun::layout()
+{
+    RenderBlock::layout();
+    
+    RenderRubyText* rt = rubyText();
+    if (!rt)
+        return;
+
+    rt->setLogicalLeft(0);
+    
+    // Place the RenderRubyText such that its bottom is flush with the lineTop of the first line of the RenderRubyBase.
+    LayoutUnit lastLineRubyTextBottom = rt->logicalHeight();
+    LayoutUnit firstLineRubyTextTop = 0;
+    RootInlineBox* rootBox = rt->lastRootBox();
+    if (rootBox) {
+        // In order to align, we have to ignore negative leading.
+        firstLineRubyTextTop = rt->firstRootBox()->logicalTopLayoutOverflow();
+        lastLineRubyTextBottom = rootBox->logicalBottomLayoutOverflow();
+    }
+
+    if (style()->isFlippedLinesWritingMode() == (style()->rubyPosition() == RubyPositionAfter)) {
+        LayoutUnit firstLineTop = 0;
+        if (RenderRubyBase* rb = rubyBase()) {
+            RootInlineBox* rootBox = rb->firstRootBox();
+            if (rootBox)
+                firstLineTop = rootBox->logicalTopLayoutOverflow();
+            firstLineTop += rb->logicalTop();
+        }
+        
+        rt->setLogicalTop(-lastLineRubyTextBottom + firstLineTop);
+    } else {
+        LayoutUnit lastLineBottom = logicalHeight();
+        if (RenderRubyBase* rb = rubyBase()) {
+            RootInlineBox* rootBox = rb->lastRootBox();
+            if (rootBox)
+                lastLineBottom = rootBox->logicalBottomLayoutOverflow();
+            lastLineBottom += rb->logicalTop();
+        }
+
+        rt->setLogicalTop(-firstLineRubyTextTop + lastLineBottom);
+    }
+
+    // Update our overflow to account for the new RenderRubyText position.
+    computeOverflow(clientLogicalBottom());
+}
+
+void RenderRubyRun::getOverhang(bool firstLine, RenderObject* startRenderer, RenderObject* endRenderer, int& startOverhang, int& endOverhang) const
+{
+    ASSERT(!needsLayout());
+
+    startOverhang = 0;
+    endOverhang = 0;
+
+    RenderRubyBase* rubyBase = this->rubyBase();
+    RenderRubyText* rubyText = this->rubyText();
+
+    if (!rubyBase || !rubyText)
+        return;
+
+    if (!rubyBase->firstRootBox())
+        return;
+
+    int logicalWidth = this->logicalWidth();
+    int logicalLeftOverhang = numeric_limits<int>::max();
+    int logicalRightOverhang = numeric_limits<int>::max();
+    for (RootInlineBox* rootInlineBox = rubyBase->firstRootBox(); rootInlineBox; rootInlineBox = rootInlineBox->nextRootBox()) {
+        logicalLeftOverhang = min<int>(logicalLeftOverhang, rootInlineBox->logicalLeft());
+        logicalRightOverhang = min<int>(logicalRightOverhang, logicalWidth - rootInlineBox->logicalRight());
+    }
+
+    startOverhang = style()->isLeftToRightDirection() ? logicalLeftOverhang : logicalRightOverhang;
+    endOverhang = style()->isLeftToRightDirection() ? logicalRightOverhang : logicalLeftOverhang;
+
+    if (!startRenderer || !startRenderer->isText() || startRenderer->style(firstLine)->fontSize() > rubyBase->style(firstLine)->fontSize())
+        startOverhang = 0;
+
+    if (!endRenderer || !endRenderer->isText() || endRenderer->style(firstLine)->fontSize() > rubyBase->style(firstLine)->fontSize())
+        endOverhang = 0;
+
+    // We overhang a ruby only if the neighboring render object is a text.
+    // We can overhang the ruby by no more than half the width of the neighboring text
+    // and no more than half the font size.
+    int halfWidthOfFontSize = rubyText->style(firstLine)->fontSize() / 2;
+    if (startOverhang)
+        startOverhang = min<int>(startOverhang, min<int>(toRenderText(startRenderer)->minLogicalWidth(), halfWidthOfFontSize));
+    if (endOverhang)
+        endOverhang = min<int>(endOverhang, min<int>(toRenderText(endRenderer)->minLogicalWidth(), halfWidthOfFontSize));
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderRubyRun.h b/Source/core/rendering/RenderRubyRun.h
new file mode 100644
index 0000000..2c8bdae
--- /dev/null
+++ b/Source/core/rendering/RenderRubyRun.h
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2009 Google 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:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+ * OWNER 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 RenderRubyRun_h
+#define RenderRubyRun_h
+
+#include "core/rendering/RenderBlock.h"
+
+namespace WebCore {
+
+class RenderRubyBase;
+class RenderRubyText;
+
+// RenderRubyRun are 'inline-block/table' like objects,and wrap a single pairing of a ruby base with its ruby text(s).
+// See RenderRuby.h for further comments on the structure
+
+class RenderRubyRun FINAL : public RenderBlock {
+public:
+    virtual ~RenderRubyRun();
+
+    bool hasRubyText() const;
+    bool hasRubyBase() const;
+    bool isEmpty() const;
+    RenderRubyText* rubyText() const;
+    RenderRubyBase* rubyBase() const;
+    RenderRubyBase* rubyBaseSafe(); // creates the base if it doesn't already exist
+
+    virtual RenderObject* layoutSpecialExcludedChild(bool relayoutChildren);
+    virtual void layout();
+
+    virtual bool isChildAllowed(RenderObject*, RenderStyle*) const;
+    virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0);
+    virtual void removeChild(RenderObject* child);
+
+    virtual RenderBlock* firstLineBlock() const;
+    virtual void updateFirstLetter();
+
+    void getOverhang(bool firstLine, RenderObject* startRenderer, RenderObject* endRenderer, int& startOverhang, int& endOverhang) const;
+
+    static RenderRubyRun* staticCreateRubyRun(const RenderObject* parentRuby);
+
+protected:
+    RenderRubyBase* createRubyBase() const;
+
+private:
+    RenderRubyRun();
+
+    virtual bool isRubyRun() const { return true; }
+    virtual const char* renderName() const { return "RenderRubyRun (anonymous)"; }
+    virtual bool createsAnonymousWrapper() const { return true; }
+    virtual void removeLeftoverAnonymousBlock(RenderBlock*) { }
+};
+
+inline RenderRubyRun* toRenderRubyRun(RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isRubyRun());
+    return static_cast<RenderRubyRun*>(object);
+}
+
+inline const RenderRubyRun* toRenderRubyRun(const RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isBox());
+    return static_cast<const RenderRubyRun*>(object);
+}
+
+void toRenderRubyRun(const RenderRubyRun*);
+
+} // namespace WebCore
+
+#endif // RenderRubyRun_h
diff --git a/Source/core/rendering/RenderRubyText.cpp b/Source/core/rendering/RenderRubyText.cpp
new file mode 100644
index 0000000..0d4dba1
--- /dev/null
+++ b/Source/core/rendering/RenderRubyText.cpp
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2009 Google Inc. All rights reserved.
+ * Copyright (C) 2011 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:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+ * OWNER 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 "core/rendering/RenderRubyText.h"
+
+using namespace std;
+
+namespace WebCore {
+
+RenderRubyText::RenderRubyText(Element* element)
+    : RenderBlock(element)
+{
+}
+
+RenderRubyText::~RenderRubyText()
+{
+}
+
+bool RenderRubyText::isChildAllowed(RenderObject* child, RenderStyle*) const
+{
+    return child->isInline();
+}
+
+ETextAlign RenderRubyText::textAlignmentForLine(bool endsWithSoftBreak) const
+{
+    ETextAlign textAlign = style()->textAlign();
+    // FIXME: This check is bogus since user can set the initial value.
+    if (textAlign != RenderStyle::initialTextAlign())
+        return RenderBlock::textAlignmentForLine(endsWithSoftBreak);
+
+    // The default behavior is to allow ruby text to expand if it is shorter than the ruby base.
+    return JUSTIFY;
+}
+
+void RenderRubyText::adjustInlineDirectionLineBounds(int expansionOpportunityCount, float& logicalLeft, float& logicalWidth) const
+{
+    ETextAlign textAlign = style()->textAlign();
+    // FIXME: This check is bogus since user can set the initial value.
+    if (textAlign != RenderStyle::initialTextAlign())
+        return RenderBlock::adjustInlineDirectionLineBounds(expansionOpportunityCount, logicalLeft, logicalWidth);
+
+    int maxPreferredLogicalWidth = this->maxPreferredLogicalWidth();
+    if (maxPreferredLogicalWidth >= logicalWidth)
+        return;
+
+    // Inset the ruby text by half the inter-ideograph expansion amount, but no more than a full-width
+    // ruby character on each side.
+    float inset = (logicalWidth - maxPreferredLogicalWidth) / (expansionOpportunityCount + 1);
+    if (expansionOpportunityCount)
+        inset = min<float>(2 * style()->fontSize(), inset);
+
+    logicalLeft += inset / 2;
+    logicalWidth -= inset;
+}
+
+bool RenderRubyText::avoidsFloats() const
+{
+    return true;
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderRubyText.h b/Source/core/rendering/RenderRubyText.h
new file mode 100644
index 0000000..3d38776
--- /dev/null
+++ b/Source/core/rendering/RenderRubyText.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2009 Google 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:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+ * OWNER 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 RenderRubyText_h
+#define RenderRubyText_h
+
+#include "core/rendering/RenderBlock.h"
+
+namespace WebCore {
+
+class RenderRubyText FINAL : public RenderBlock {
+public:
+    RenderRubyText(Element*);
+    virtual ~RenderRubyText();
+
+    virtual const char* renderName() const { return "RenderRubyText"; }
+
+    virtual bool isRubyText() const { return true; }
+
+    virtual bool isChildAllowed(RenderObject*, RenderStyle*) const;
+
+private:
+    virtual bool avoidsFloats() const;
+
+    virtual ETextAlign textAlignmentForLine(bool endsWithSoftBreak) const;
+    virtual void adjustInlineDirectionLineBounds(int expansionOpportunityCount, float& logicalLeft, float& logicalWidth) const;
+};
+
+} // namespace WebCore
+
+#endif // RenderRubyText_h
diff --git a/Source/core/rendering/RenderScrollbar.cpp b/Source/core/rendering/RenderScrollbar.cpp
new file mode 100644
index 0000000..b83655f
--- /dev/null
+++ b/Source/core/rendering/RenderScrollbar.cpp
@@ -0,0 +1,360 @@
+/*
+ * Copyright (C) 2008, 2009 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 "core/rendering/RenderScrollbar.h"
+
+#include "core/css/StyleResolver.h"
+#include "core/page/Frame.h"
+#include "core/page/FrameView.h"
+#include "core/rendering/RenderPart.h"
+#include "core/rendering/RenderScrollbarPart.h"
+#include "core/rendering/RenderScrollbarTheme.h"
+#include "core/rendering/style/StyleInheritedData.h"
+
+namespace WebCore {
+
+PassRefPtr<Scrollbar> RenderScrollbar::createCustomScrollbar(ScrollableArea* scrollableArea, ScrollbarOrientation orientation, Node* ownerNode, Frame* owningFrame)
+{
+    return adoptRef(new RenderScrollbar(scrollableArea, orientation, ownerNode, owningFrame));
+}
+
+RenderScrollbar::RenderScrollbar(ScrollableArea* scrollableArea, ScrollbarOrientation orientation, Node* ownerNode, Frame* owningFrame)
+    : Scrollbar(scrollableArea, orientation, RegularScrollbar, RenderScrollbarTheme::renderScrollbarTheme())
+    , m_owner(ownerNode)
+    , m_owningFrame(owningFrame)
+{
+    ASSERT(ownerNode || owningFrame);
+
+    // FIXME: We need to do this because RenderScrollbar::styleChanged is called as soon as the scrollbar is created.
+    
+    // Update the scrollbar size.
+    int width = 0;
+    int height = 0;
+    updateScrollbarPart(ScrollbarBGPart);
+    if (RenderScrollbarPart* part = m_parts.get(ScrollbarBGPart)) {
+        part->layout();
+        width = part->width();
+        height = part->height();
+    } else if (this->orientation() == HorizontalScrollbar)
+        width = this->width();
+    else
+        height = this->height();
+
+    setFrameRect(IntRect(0, 0, width, height));
+}
+
+RenderScrollbar::~RenderScrollbar()
+{
+    if (!m_parts.isEmpty()) {
+        // When a scrollbar is detached from its parent (causing all parts removal) and 
+        // ready to be destroyed, its destruction can be delayed because of RefPtr
+        // maintained in other classes such as EventHandler (m_lastScrollbarUnderMouse).
+        // Meanwhile, we can have a call to updateScrollbarPart which recreates the 
+        // scrollbar part. So, we need to destroy these parts since we don't want them
+        // to call on a destroyed scrollbar. See webkit bug 68009.
+        updateScrollbarParts(true);
+    }
+}
+
+RenderBox* RenderScrollbar::owningRenderer() const
+{
+    if (m_owningFrame) {
+        RenderBox* currentRenderer = m_owningFrame->ownerRenderer();
+        return currentRenderer;
+    }
+    return m_owner && m_owner->renderer() ? m_owner->renderer()->enclosingBox() : 0;
+}
+
+void RenderScrollbar::setParent(ScrollView* parent)
+{
+    Scrollbar::setParent(parent);
+    if (!parent) {
+        // Destroy all of the scrollbar's RenderBoxes.
+        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);
+}
+
+PassRefPtr<RenderStyle> RenderScrollbar::getScrollbarPseudoStyle(ScrollbarPart partType, PseudoId pseudoId)
+{
+    if (!owningRenderer())
+        return 0;
+
+    RefPtr<RenderStyle> result = owningRenderer()->getUncachedPseudoStyle(PseudoStyleRequest(pseudoId, this, partType), owningRenderer()->style());
+    // Scrollbars for root frames should always have background color 
+    // unless explicitly specified as transparent. So we force it.
+    // This is because WebKit assumes scrollbar to be always painted and missing background
+    // causes visual artifact like non-repainted dirty region.
+    if (result && m_owningFrame && m_owningFrame->view() && !m_owningFrame->view()->isTransparent() && !result->hasBackground())
+        result->setBackgroundColor(Color::white);
+
+    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(location(), IntSize(isHorizontal ? width() : newThickness, isHorizontal ? newThickness : height())));
+        if (RenderBox* box = owningRenderer())
+            box->setChildNeedsLayout(true);
+    }
+}
+
+static PseudoId pseudoForScrollbarPart(ScrollbarPart part)
+{
+    switch (part) {
+        case BackButtonStartPart:
+        case ForwardButtonStartPart:
+        case BackButtonEndPart:
+        case ForwardButtonEndPart:
+            return SCROLLBAR_BUTTON;
+        case BackTrackPart:
+        case ForwardTrackPart:
+            return SCROLLBAR_TRACK_PIECE;
+        case ThumbPart:
+            return SCROLLBAR_THUMB;
+        case TrackBGPart:
+            return SCROLLBAR_TRACK;
+        case ScrollbarBGPart:
+            return SCROLLBAR;
+        case NoPart:
+        case AllParts:
+            break;
+    }
+    ASSERT_NOT_REACHED();
+    return SCROLLBAR;
+}
+
+void RenderScrollbar::updateScrollbarPart(ScrollbarPart partType, bool destroy)
+{
+    if (partType == NoPart)
+        return;
+
+    RefPtr<RenderStyle> partStyle = !destroy ? getScrollbarPseudoStyle(partType,  pseudoForScrollbarPart(partType)) : PassRefPtr<RenderStyle>(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 = RenderScrollbarPart::createAnonymous(owningRenderer()->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, location(), 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(location(), IntSize(isHorizontal ? partRenderer->pixelSnappedWidth() : width(), isHorizontal ? height() : partRenderer->pixelSnappedHeight()));
+    if (partType == ForwardButtonEndPart)
+        return IntRect(isHorizontal ? x() + width() - partRenderer->pixelSnappedWidth() : x(),
+                       isHorizontal ? y() : y() + height() - partRenderer->pixelSnappedHeight(),
+                       isHorizontal ? partRenderer->pixelSnappedWidth() : width(),
+                       isHorizontal ? height() : partRenderer->pixelSnappedHeight());
+    
+    if (partType == ForwardButtonStartPart) {
+        IntRect previousButton = buttonRect(BackButtonStartPart);
+        return IntRect(isHorizontal ? x() + previousButton.width() : x(),
+                       isHorizontal ? y() : y() + previousButton.height(),
+                       isHorizontal ? partRenderer->pixelSnappedWidth() : width(),
+                       isHorizontal ? height() : partRenderer->pixelSnappedHeight());
+    }
+    
+    IntRect followingButton = buttonRect(ForwardButtonEndPart);
+    return IntRect(isHorizontal ? x() + width() - followingButton.width() - partRenderer->pixelSnappedWidth() : x(),
+                   isHorizontal ? y() : y() + height() - followingButton.height() - partRenderer->pixelSnappedHeight(),
+                   isHorizontal ? partRenderer->pixelSnappedWidth() : width(),
+                   isHorizontal ? height() : partRenderer->pixelSnappedHeight());
+}
+
+IntRect RenderScrollbar::trackRect(int startLength, int endLength)
+{
+    RenderScrollbarPart* part = m_parts.get(TrackBGPart);
+    if (part)
+        part->layout();
+
+    if (orientation() == HorizontalScrollbar) {
+        int marginLeft = part ? static_cast<int>(part->marginLeft()) : 0;
+        int marginRight = part ? static_cast<int>(part->marginRight()) : 0;
+        startLength += marginLeft;
+        endLength += marginRight;
+        int totalLength = startLength + endLength;
+        return IntRect(x() + startLength, y(), width() - totalLength, height());
+    }
+    
+    int marginTop = part ? static_cast<int>(part->marginTop()) : 0;
+    int marginBottom = part ? static_cast<int>(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->marginWidth());
+    } else {
+        rect.setY(rect.y() + partRenderer->marginTop());
+        rect.setHeight(rect.height() - partRenderer->marginHeight());
+    }
+    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/Source/core/rendering/RenderScrollbar.h b/Source/core/rendering/RenderScrollbar.h
new file mode 100644
index 0000000..12c6032
--- /dev/null
+++ b/Source/core/rendering/RenderScrollbar.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2008, 2009 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 "core/platform/Scrollbar.h"
+#include "core/rendering/style/RenderStyleConstants.h"
+#include <wtf/HashMap.h>
+
+namespace WebCore {
+
+class Frame;
+class Node;
+class RenderBox;
+class RenderScrollbarPart;
+class RenderStyle;
+
+class RenderScrollbar : public Scrollbar {
+protected:
+    RenderScrollbar(ScrollableArea*, ScrollbarOrientation, Node*, Frame*);
+
+public:
+    friend class Scrollbar;
+    static PassRefPtr<Scrollbar> createCustomScrollbar(ScrollableArea*, ScrollbarOrientation, Node*, Frame* owningFrame = 0);
+    virtual ~RenderScrollbar();
+
+    RenderBox* owningRenderer() const;
+
+    void paintPart(GraphicsContext*, ScrollbarPart, const IntRect&);
+
+    IntRect buttonRect(ScrollbarPart);
+    IntRect trackRect(int startLength, int endLength);
+    IntRect trackPieceRectWithMargins(ScrollbarPart, const IntRect&);
+
+    int minimumThumbLength();
+
+    virtual bool isOverlayScrollbar() const { return false; }
+
+private:
+    virtual void setParent(ScrollView*);
+    virtual void setEnabled(bool);
+
+    virtual void paint(GraphicsContext*, const IntRect& damageRect);
+
+    virtual void setHoveredPart(ScrollbarPart);
+    virtual void setPressedPart(ScrollbarPart);
+
+    virtual void styleChanged();
+
+    virtual bool isCustomScrollbar() const { return true; }
+
+    void updateScrollbarParts(bool destroy = false);
+
+    PassRefPtr<RenderStyle> getScrollbarPseudoStyle(ScrollbarPart, PseudoId);
+    void updateScrollbarPart(ScrollbarPart, bool destroy = false);
+
+    // This Scrollbar(Widget) may outlive the DOM which created it (during tear down),
+    // so we keep a reference to the Node which caused this custom scrollbar creation.
+    // This will not create a reference cycle as the Widget tree is owned by our containing
+    // FrameView which this Node pointer can in no way keep alive. See webkit bug 80610.
+    RefPtr<Node> m_owner;
+
+    Frame* m_owningFrame;
+    HashMap<unsigned, RenderScrollbarPart*> m_parts;
+};
+
+inline RenderScrollbar* toRenderScrollbar(ScrollbarThemeClient* scrollbar)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!scrollbar || scrollbar->isCustomScrollbar());
+    return static_cast<RenderScrollbar*>(scrollbar);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderScrollbar(const RenderScrollbar*);
+
+} // namespace WebCore
+
+#endif // RenderScrollbar_h
diff --git a/Source/core/rendering/RenderScrollbarPart.cpp b/Source/core/rendering/RenderScrollbarPart.cpp
new file mode 100644
index 0000000..0e45be1
--- /dev/null
+++ b/Source/core/rendering/RenderScrollbarPart.cpp
@@ -0,0 +1,206 @@
+/*
+ * 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 "core/rendering/RenderScrollbarPart.h"
+
+#include "core/rendering/PaintInfo.h"
+#include "core/rendering/RenderScrollbar.h"
+#include "core/rendering/RenderScrollbarTheme.h"
+#include "core/rendering/RenderView.h"
+
+using namespace std;
+
+namespace WebCore {
+
+RenderScrollbarPart::RenderScrollbarPart(RenderScrollbar* scrollbar, ScrollbarPart part)
+    : RenderBlock(0)
+    , m_scrollbar(scrollbar)
+    , m_part(part)
+{
+}
+
+RenderScrollbarPart::~RenderScrollbarPart()
+{
+}
+
+RenderScrollbarPart* RenderScrollbarPart::createAnonymous(Document* document, RenderScrollbar* scrollbar, ScrollbarPart part)
+{
+    RenderScrollbarPart* renderer = new (document->renderArena()) RenderScrollbarPart(scrollbar, part);
+    renderer->setDocumentForAnonymous(document);
+    return renderer;
+}
+
+void RenderScrollbarPart::layout()
+{
+    StackStats::LayoutCheckPoint layoutCheckPoint;
+    setLocation(LayoutPoint()); // We don't worry about positioning ourselves. We're just determining our minimum width/height.
+    if (m_scrollbar->orientation() == HorizontalScrollbar)
+        layoutHorizontalPart();
+    else
+        layoutVerticalPart();
+
+    setNeedsLayout(false);
+}
+
+void RenderScrollbarPart::layoutHorizontalPart()
+{
+    if (m_part == ScrollbarBGPart) {
+        setWidth(m_scrollbar->width());
+        computeScrollbarHeight();
+    } else {
+        computeScrollbarWidth();
+        setHeight(m_scrollbar->height());
+    }
+}
+
+void RenderScrollbarPart::layoutVerticalPart()
+{
+    if (m_part == ScrollbarBGPart) {
+        computeScrollbarWidth();
+        setHeight(m_scrollbar->height());
+    } else {
+        setWidth(m_scrollbar->width());
+        computeScrollbarHeight();
+    } 
+}
+
+static int calcScrollbarThicknessUsing(SizeType sizeType, const Length& length, int containingLength, RenderView* renderView)
+{
+    if (!length.isIntrinsicOrAuto() || (sizeType == MinSize && length.isAuto()))
+        return minimumValueForLength(length, containingLength, renderView);
+    return ScrollbarTheme::theme()->scrollbarThickness();
+}
+
+void RenderScrollbarPart::computeScrollbarWidth()
+{
+    if (!m_scrollbar->owningRenderer())
+        return;
+    RenderView* renderView = view();
+    // FIXME: We are querying layout information but nothing guarantees that it's up-to-date, especially since we are called at style change.
+    // FIXME: Querying the style's border information doesn't work on table cells with collapsing borders.
+    int visibleSize = m_scrollbar->owningRenderer()->width() - m_scrollbar->owningRenderer()->style()->borderLeftWidth() - m_scrollbar->owningRenderer()->style()->borderRightWidth();
+    int w = calcScrollbarThicknessUsing(MainOrPreferredSize, style()->width(), visibleSize, renderView);
+    int minWidth = calcScrollbarThicknessUsing(MinSize, style()->minWidth(), visibleSize, renderView);
+    int maxWidth = style()->maxWidth().isUndefined() ? w : calcScrollbarThicknessUsing(MaxSize, style()->maxWidth(), visibleSize, renderView);
+    setWidth(max(minWidth, min(maxWidth, w)));
+    
+    // Buttons and track pieces can all have margins along the axis of the scrollbar. 
+    m_marginBox.setLeft(minimumValueForLength(style()->marginLeft(), visibleSize, renderView));
+    m_marginBox.setRight(minimumValueForLength(style()->marginRight(), visibleSize, renderView));
+}
+
+void RenderScrollbarPart::computeScrollbarHeight()
+{
+    if (!m_scrollbar->owningRenderer())
+        return;
+    RenderView* renderView = view();
+    // FIXME: We are querying layout information but nothing guarantees that it's up-to-date, especially since we are called at style change.
+    // FIXME: Querying the style's border information doesn't work on table cells with collapsing borders.
+    int visibleSize = m_scrollbar->owningRenderer()->height() -  m_scrollbar->owningRenderer()->style()->borderTopWidth() - m_scrollbar->owningRenderer()->style()->borderBottomWidth();
+    int h = calcScrollbarThicknessUsing(MainOrPreferredSize, style()->height(), visibleSize, renderView);
+    int minHeight = calcScrollbarThicknessUsing(MinSize, style()->minHeight(), visibleSize, renderView);
+    int maxHeight = style()->maxHeight().isUndefined() ? h : calcScrollbarThicknessUsing(MaxSize, style()->maxHeight(), visibleSize, renderView);
+    setHeight(max(minHeight, min(maxHeight, h)));
+
+    // Buttons and track pieces can all have margins along the axis of the scrollbar. 
+    m_marginBox.setTop(minimumValueForLength(style()->marginTop(), visibleSize, renderView));
+    m_marginBox.setBottom(minimumValueForLength(style()->marginBottom(), visibleSize, renderView));
+}
+
+void RenderScrollbarPart::computePreferredLogicalWidths()
+{
+    if (!preferredLogicalWidthsDirty())
+        return;
+    
+    m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = 0;
+
+    setPreferredLogicalWidthsDirty(false);
+}
+
+void RenderScrollbarPart::styleWillChange(StyleDifference diff, const RenderStyle* newStyle)
+{
+    RenderBlock::styleWillChange(diff, newStyle);
+    setInline(false);
+}
+
+void RenderScrollbarPart::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
+{
+    RenderBlock::styleDidChange(diff, oldStyle);
+    setInline(false);
+    clearPositionedState();
+    setFloating(false);
+    setHasOverflowClip(false);
+    if (oldStyle && m_scrollbar && m_part != NoPart && diff >= StyleDifferenceRepaint)
+        m_scrollbar->theme()->invalidatePart(m_scrollbar, m_part);
+}
+
+void RenderScrollbarPart::imageChanged(WrappedImagePtr image, const IntRect* rect)
+{
+    if (m_scrollbar && m_part != NoPart)
+        m_scrollbar->theme()->invalidatePart(m_scrollbar, m_part);
+    else {
+        if (FrameView* frameView = view()->frameView()) {
+            if (frameView->isFrameViewScrollCorner(this)) {
+                frameView->invalidateScrollCorner(frameView->scrollCornerRect());
+                return;
+            }
+        }
+        
+        RenderBlock::imageChanged(image, rect);
+    }
+}
+
+void RenderScrollbarPart::paintIntoRect(GraphicsContext* graphicsContext, const LayoutPoint& paintOffset, const LayoutRect& rect)
+{
+    // Make sure our dimensions match the rect.
+    setLocation(rect.location() - toSize(paintOffset));
+    setWidth(rect.width());
+    setHeight(rect.height());
+
+    if (graphicsContext->paintingDisabled())
+        return;
+
+    // Now do the paint.
+    PaintInfo paintInfo(graphicsContext, pixelSnappedIntRect(rect), PaintPhaseBlockBackground, PaintBehaviorNormal);
+    paint(paintInfo, paintOffset);
+    paintInfo.phase = PaintPhaseChildBlockBackgrounds;
+    paint(paintInfo, paintOffset);
+    paintInfo.phase = PaintPhaseFloat;
+    paint(paintInfo, paintOffset);
+    paintInfo.phase = PaintPhaseForeground;
+    paint(paintInfo, paintOffset);
+    paintInfo.phase = PaintPhaseOutline;
+    paint(paintInfo, paintOffset);
+}
+
+RenderObject* RenderScrollbarPart::rendererOwningScrollbar() const
+{
+    if (!m_scrollbar)
+        return 0;
+    return m_scrollbar->owningRenderer();
+}
+
+}
diff --git a/Source/core/rendering/RenderScrollbarPart.h b/Source/core/rendering/RenderScrollbarPart.h
new file mode 100644
index 0000000..dac6d3b
--- /dev/null
+++ b/Source/core/rendering/RenderScrollbarPart.h
@@ -0,0 +1,96 @@
+/*
+ * 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 "core/platform/ScrollTypes.h"
+#include "core/rendering/RenderBlock.h"
+
+namespace WebCore {
+
+class RenderScrollbar;
+
+class RenderScrollbarPart FINAL : public RenderBlock {
+public:
+    static RenderScrollbarPart* createAnonymous(Document*, RenderScrollbar* = 0, ScrollbarPart = NoPart);
+    
+    virtual ~RenderScrollbarPart();
+
+    virtual const char* renderName() const { return "RenderScrollbarPart"; }
+    
+    virtual bool requiresLayer() const { return false; }
+
+    virtual void layout();
+    
+    void paintIntoRect(GraphicsContext*, const LayoutPoint&, const LayoutRect&);
+
+    // Scrollbar parts needs to be rendered at device pixel boundaries.
+    virtual LayoutUnit marginTop() const OVERRIDE { ASSERT(isIntegerValue(m_marginBox.top())); return m_marginBox.top(); }
+    virtual LayoutUnit marginBottom() const OVERRIDE { ASSERT(isIntegerValue(m_marginBox.bottom())); return m_marginBox.bottom(); }
+    virtual LayoutUnit marginLeft() const OVERRIDE { ASSERT(isIntegerValue(m_marginBox.left())); return m_marginBox.left(); }
+    virtual LayoutUnit marginRight() const OVERRIDE { ASSERT(isIntegerValue(m_marginBox.right())); return m_marginBox.right(); }
+
+    virtual bool isRenderScrollbarPart() const { return true; }
+    RenderObject* rendererOwningScrollbar() const;
+
+protected:
+    virtual void styleWillChange(StyleDifference diff, const RenderStyle* newStyle);
+    virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+    virtual void imageChanged(WrappedImagePtr, const IntRect* = 0);
+
+private:
+    RenderScrollbarPart(RenderScrollbar*, ScrollbarPart);
+
+    virtual void computePreferredLogicalWidths();
+
+    void layoutHorizontalPart();
+    void layoutVerticalPart();
+
+    void computeScrollbarWidth();
+    void computeScrollbarHeight();
+    
+    RenderScrollbar* m_scrollbar;
+    ScrollbarPart m_part;
+};
+
+inline RenderScrollbarPart* toRenderScrollbarPart(RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isRenderScrollbarPart());
+    return static_cast<RenderScrollbarPart*>(object);
+}
+
+inline const RenderScrollbarPart* toRenderScrollbarPart(const RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isRenderScrollbarPart());
+    return static_cast<const RenderScrollbarPart*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderScrollbarPart(const RenderScrollbarPart*);
+
+} // namespace WebCore
+
+#endif // RenderScrollbarPart_h
diff --git a/Source/core/rendering/RenderScrollbarTheme.cpp b/Source/core/rendering/RenderScrollbarTheme.cpp
new file mode 100644
index 0000000..a655fb8
--- /dev/null
+++ b/Source/core/rendering/RenderScrollbarTheme.cpp
@@ -0,0 +1,146 @@
+/*
+ * 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 "core/platform/ScrollbarThemeClient.h"
+#include "core/rendering/RenderScrollbar.h"
+#include "core/rendering/RenderScrollbarTheme.h"
+#include <wtf/StdLibExtras.h>
+
+namespace WebCore {
+
+RenderScrollbarTheme* RenderScrollbarTheme::renderScrollbarTheme()
+{
+    DEFINE_STATIC_LOCAL(RenderScrollbarTheme, theme, ());
+    return &theme;
+}
+
+void RenderScrollbarTheme::buttonSizesAlongTrackAxis(ScrollbarThemeClient* 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(ScrollbarThemeClient* scrollbar)
+{
+    int startSize;
+    int endSize;
+    buttonSizesAlongTrackAxis(scrollbar, startSize, endSize);
+    return (startSize + endSize) <= (scrollbar->orientation() == HorizontalScrollbar ? scrollbar->width() : scrollbar->height());
+}
+
+bool RenderScrollbarTheme::hasThumb(ScrollbarThemeClient* scrollbar)
+{
+    return trackLength(scrollbar) - thumbLength(scrollbar) >= 0;
+}
+
+int RenderScrollbarTheme::minimumThumbLength(ScrollbarThemeClient* scrollbar)
+{
+    return toRenderScrollbar(scrollbar)->minimumThumbLength();
+}
+
+IntRect RenderScrollbarTheme::backButtonRect(ScrollbarThemeClient* scrollbar, ScrollbarPart partType, bool)
+{
+    return toRenderScrollbar(scrollbar)->buttonRect(partType);
+}
+
+IntRect RenderScrollbarTheme::forwardButtonRect(ScrollbarThemeClient* scrollbar, ScrollbarPart partType, bool)
+{
+    return toRenderScrollbar(scrollbar)->buttonRect(partType);
+}
+
+IntRect RenderScrollbarTheme::trackRect(ScrollbarThemeClient* scrollbar, bool)
+{
+    if (!hasButtons(scrollbar))
+        return scrollbar->frameRect();
+    
+    int startLength;
+    int endLength;
+    buttonSizesAlongTrackAxis(scrollbar, startLength, endLength);
+    
+    return toRenderScrollbar(scrollbar)->trackRect(startLength, endLength);
+}
+
+IntRect RenderScrollbarTheme::constrainTrackRectToTrackPieces(ScrollbarThemeClient* scrollbar, const IntRect& rect)
+{ 
+    IntRect backRect = toRenderScrollbar(scrollbar)->trackPieceRectWithMargins(BackTrackPart, rect);
+    IntRect forwardRect = toRenderScrollbar(scrollbar)->trackPieceRectWithMargins(ForwardTrackPart, rect);
+    IntRect result = rect;
+    if (scrollbar->orientation() == HorizontalScrollbar) {
+        result.setX(backRect.x());
+        result.setWidth(forwardRect.maxX() - backRect.x());
+    } else {
+        result.setY(backRect.y());
+        result.setHeight(forwardRect.maxY() - backRect.y());
+    }
+    return result;
+}
+
+void RenderScrollbarTheme::paintScrollCorner(ScrollView*, GraphicsContext* context, const IntRect& cornerRect)
+{
+    // FIXME: Implement.
+    context->fillRect(cornerRect, Color::white, ColorSpaceDeviceRGB);
+}
+
+void RenderScrollbarTheme::paintScrollbarBackground(GraphicsContext* context, ScrollbarThemeClient* scrollbar)
+{
+    toRenderScrollbar(scrollbar)->paintPart(context, ScrollbarBGPart, scrollbar->frameRect());
+}
+
+void RenderScrollbarTheme::paintTrackBackground(GraphicsContext* context, ScrollbarThemeClient* scrollbar, const IntRect& rect)
+{
+    toRenderScrollbar(scrollbar)->paintPart(context, TrackBGPart, rect);
+}
+
+void RenderScrollbarTheme::paintTrackPiece(GraphicsContext* context, ScrollbarThemeClient* scrollbar, const IntRect& rect, ScrollbarPart part)
+{
+    toRenderScrollbar(scrollbar)->paintPart(context, part, rect);
+}
+
+void RenderScrollbarTheme::paintButton(GraphicsContext* context, ScrollbarThemeClient* scrollbar, const IntRect& rect, ScrollbarPart part)
+{
+    toRenderScrollbar(scrollbar)->paintPart(context, part, rect);
+}
+
+void RenderScrollbarTheme::paintThumb(GraphicsContext* context, ScrollbarThemeClient* scrollbar, const IntRect& rect)
+{
+    toRenderScrollbar(scrollbar)->paintPart(context, ThumbPart, rect);
+}
+
+void RenderScrollbarTheme::paintTickmarks(GraphicsContext* context, ScrollbarThemeClient* scrollbar, const IntRect& rect)
+{
+    ScrollbarTheme::theme()->paintTickmarks(context, scrollbar, rect);
+}
+
+}
diff --git a/Source/core/rendering/RenderScrollbarTheme.h b/Source/core/rendering/RenderScrollbarTheme.h
new file mode 100644
index 0000000..fea8540
--- /dev/null
+++ b/Source/core/rendering/RenderScrollbarTheme.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 RenderScrollbarTheme_h
+#define RenderScrollbarTheme_h
+
+#include "core/platform/ScrollbarThemeComposite.h"
+
+namespace WebCore {
+
+class PlatformMouseEvent;
+class Scrollbar;
+class ScrollView;
+
+class RenderScrollbarTheme : public ScrollbarThemeComposite {
+public:
+    virtual ~RenderScrollbarTheme() {};
+    
+    virtual int scrollbarThickness(ScrollbarControlSize controlSize) { return ScrollbarTheme::theme()->scrollbarThickness(controlSize); }
+
+    virtual ScrollbarButtonsPlacement buttonsPlacement() const { return ScrollbarTheme::theme()->buttonsPlacement(); }
+
+    virtual bool supportsControlTints() const { return true; }
+
+    virtual void paintScrollCorner(ScrollView*, GraphicsContext* context, const IntRect& cornerRect);
+
+    virtual bool shouldCenterOnThumb(ScrollbarThemeClient* scrollbar, const PlatformMouseEvent& event) { return ScrollbarTheme::theme()->shouldCenterOnThumb(scrollbar, event); }
+    
+    virtual double initialAutoscrollTimerDelay() { return ScrollbarTheme::theme()->initialAutoscrollTimerDelay(); }
+    virtual double autoscrollTimerDelay() { return ScrollbarTheme::theme()->autoscrollTimerDelay(); }
+
+    virtual void registerScrollbar(ScrollbarThemeClient* scrollbar) { return ScrollbarTheme::theme()->registerScrollbar(scrollbar); }
+    virtual void unregisterScrollbar(ScrollbarThemeClient* scrollbar) { return ScrollbarTheme::theme()->unregisterScrollbar(scrollbar); }
+
+    virtual int minimumThumbLength(ScrollbarThemeClient*);
+
+    void buttonSizesAlongTrackAxis(ScrollbarThemeClient*, int& beforeSize, int& afterSize);
+    
+    static RenderScrollbarTheme* renderScrollbarTheme();
+
+protected:
+    virtual bool hasButtons(ScrollbarThemeClient*);
+    virtual bool hasThumb(ScrollbarThemeClient*);
+
+    virtual IntRect backButtonRect(ScrollbarThemeClient*, ScrollbarPart, bool painting = false);
+    virtual IntRect forwardButtonRect(ScrollbarThemeClient*, ScrollbarPart, bool painting = false);
+    virtual IntRect trackRect(ScrollbarThemeClient*, bool painting = false);
+    
+    virtual void paintScrollbarBackground(GraphicsContext*, ScrollbarThemeClient*);
+    virtual void paintTrackBackground(GraphicsContext*, ScrollbarThemeClient*, const IntRect&);
+    virtual void paintTrackPiece(GraphicsContext*, ScrollbarThemeClient*, const IntRect&, ScrollbarPart);
+    virtual void paintButton(GraphicsContext*, ScrollbarThemeClient*, const IntRect&, ScrollbarPart);
+    virtual void paintThumb(GraphicsContext*, ScrollbarThemeClient*, const IntRect&);
+    virtual void paintTickmarks(GraphicsContext*, ScrollbarThemeClient*, const IntRect&) OVERRIDE;
+
+    virtual IntRect constrainTrackRectToTrackPieces(ScrollbarThemeClient*, const IntRect&);
+};
+
+} // namespace WebCore
+
+#endif // RenderScrollbarTheme_h
diff --git a/Source/core/rendering/RenderSearchField.cpp b/Source/core/rendering/RenderSearchField.cpp
new file mode 100644
index 0000000..fa4c187
--- /dev/null
+++ b/Source/core/rendering/RenderSearchField.cpp
@@ -0,0 +1,381 @@
+/**
+ * Copyright (C) 2006, 2007, 2010 Apple Inc. All rights reserved.
+ *           (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) 
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ * Copyright (C) 2010 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 "core/rendering/RenderSearchField.h"
+
+#include "CSSValueKeywords.h"
+#include "HTMLNames.h"
+#include "core/css/CSSFontSelector.h"
+#include "core/css/StyleResolver.h"
+#include "core/editing/FrameSelection.h"
+#include "core/html/HTMLInputElement.h"
+#include "core/html/shadow/TextControlInnerElements.h"
+#include "core/page/Chrome.h"
+#include "core/page/Frame.h"
+#include "core/page/FrameView.h"
+#include "core/page/Page.h"
+#include "core/page/Settings.h"
+#include "core/platform/LocalizedStrings.h"
+#include "core/platform/PlatformKeyboardEvent.h"
+#include "core/platform/SearchPopupMenu.h"
+#include "core/platform/graphics/SimpleFontData.h"
+#include "core/rendering/HitTestResult.h"
+#include "core/rendering/RenderLayer.h"
+#include "core/rendering/RenderScrollbar.h"
+#include "core/rendering/RenderTheme.h"
+
+using namespace std;
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+// ----------------------------
+
+RenderSearchField::RenderSearchField(Element* element)
+    : RenderTextControlSingleLine(element)
+    , m_searchPopupIsVisible(false)
+    , m_searchPopup(0)
+{
+    ASSERT(element->isHTMLElement());
+    ASSERT(element->toInputElement());
+    ASSERT(element->toInputElement()->isSearchField());
+}
+
+RenderSearchField::~RenderSearchField()
+{
+    if (m_searchPopup) {
+        m_searchPopup->popupMenu()->disconnectClient();
+        m_searchPopup = 0;
+    }
+}
+
+inline HTMLElement* RenderSearchField::resultsButtonElement() const
+{
+    return inputElement()->resultsButtonElement();
+}
+
+inline HTMLElement* RenderSearchField::cancelButtonElement() const
+{
+    return inputElement()->cancelButtonElement();
+}
+
+void RenderSearchField::addSearchResult()
+{
+    HTMLInputElement* input = inputElement();
+    if (input->maxResults() <= 0)
+        return;
+
+    String value = input->value();
+    if (value.isEmpty())
+        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 = document()->page()->chrome()->createSearchPopupMenu(this);
+
+    m_searchPopup->saveRecentSearches(name, m_recentSearches);
+}
+
+void RenderSearchField::showPopup()
+{
+    if (m_searchPopupIsVisible)
+        return;
+
+    if (!m_searchPopup)
+        m_searchPopup = document()->page()->chrome()->createSearchPopupMenu(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 = inputElement();
+    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->popupMenu()->show(pixelSnappedIntRect(absoluteBoundingBoxRect()), document()->view(), -1);
+}
+
+void RenderSearchField::hidePopup()
+{
+    if (m_searchPopup)
+        m_searchPopup->popupMenu()->hide();
+}
+
+LayoutUnit RenderSearchField::computeControlLogicalHeight(LayoutUnit lineHeight, LayoutUnit nonContentHeight) const
+{
+    HTMLElement* resultsButton = resultsButtonElement();
+    if (RenderBox* resultsRenderer = resultsButton ? resultsButton->renderBox() : 0) {
+        resultsRenderer->updateLogicalHeight();
+        nonContentHeight = max(nonContentHeight, resultsRenderer->borderAndPaddingLogicalHeight() + resultsRenderer->marginLogicalHeight());
+        lineHeight = max(lineHeight, resultsRenderer->logicalHeight());
+    }
+    HTMLElement* cancelButton = cancelButtonElement();
+    if (RenderBox* cancelRenderer = cancelButton ? cancelButton->renderBox() : 0) {
+        cancelRenderer->updateLogicalHeight();
+        nonContentHeight = max(nonContentHeight, cancelRenderer->borderAndPaddingLogicalHeight() + cancelRenderer->marginLogicalHeight());
+        lineHeight = max(lineHeight, cancelRenderer->logicalHeight());
+    }
+
+    return lineHeight + nonContentHeight;
+}
+
+void RenderSearchField::updateFromElement()
+{
+    RenderTextControlSingleLine::updateFromElement();
+
+    if (cancelButtonElement())
+        updateCancelButtonVisibility();
+
+    if (m_searchPopupIsVisible)
+        m_searchPopup->popupMenu()->updateFromElement();
+}
+
+void RenderSearchField::updateCancelButtonVisibility() const
+{
+    RenderObject* cancelButtonRenderer = cancelButtonElement()->renderer();
+    if (!cancelButtonRenderer)
+        return;
+
+    const RenderStyle* curStyle = cancelButtonRenderer->style();
+    EVisibility buttonVisibility = visibilityForCancelButton();
+    if (curStyle->visibility() == buttonVisibility)
+        return;
+
+    RefPtr<RenderStyle> cancelButtonStyle = RenderStyle::clone(curStyle);
+    cancelButtonStyle->setVisibility(buttonVisibility);
+    cancelButtonRenderer->setStyle(cancelButtonStyle);
+}
+
+EVisibility RenderSearchField::visibilityForCancelButton() const
+{
+    return (style()->visibility() == HIDDEN || inputElement()->value().isEmpty()) ? HIDDEN : VISIBLE;
+}
+
+const AtomicString& RenderSearchField::autosaveName() const
+{
+    return toElement(node())->getAttribute(autosaveAttr);
+}
+
+// PopupMenuClient methods
+void RenderSearchField::valueChanged(unsigned listIndex, bool fireEvents)
+{
+    ASSERT(static_cast<int>(listIndex) < listSize());
+    HTMLInputElement* input = inputElement();
+    if (static_cast<int>(listIndex) == (listSize() - 1)) {
+        if (fireEvents) {
+            m_recentSearches.clear();
+            const AtomicString& name = autosaveName();
+            if (!name.isEmpty()) {
+                if (!m_searchPopup)
+                    m_searchPopup = document()->page()->chrome()->createSearchPopupMenu(this);
+                m_searchPopup->saveRecentSearches(name, m_recentSearches);
+            }
+        }
+    } else {
+        input->setValue(itemText(listIndex));
+        if (fireEvents)
+            input->onSearch();
+        input->select();
+    }
+}
+
+String RenderSearchField::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];
+}
+
+String RenderSearchField::itemLabel(unsigned) const
+{
+    return String();
+}
+
+String RenderSearchField::itemIcon(unsigned) const
+{
+    return String();
+}
+
+bool RenderSearchField::itemIsEnabled(unsigned listIndex) const
+{
+     if (!listIndex || itemIsSeparator(listIndex))
+        return false;
+    return true;
+}
+
+PopupMenuStyle RenderSearchField::itemStyle(unsigned) const
+{
+    return menuStyle();
+}
+
+PopupMenuStyle RenderSearchField::menuStyle() const
+{
+    return PopupMenuStyle(style()->visitedDependentColor(CSSPropertyColor), style()->visitedDependentColor(CSSPropertyBackgroundColor), style()->font(), style()->visibility() == VISIBLE,
+        style()->display() == NONE, style()->textIndent(), style()->direction(), isOverride(style()->unicodeBidi()), PopupMenuStyle::CustomBackgroundColor);
+}
+
+int RenderSearchField::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 RenderSearchField::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;
+}
+
+LayoutUnit RenderSearchField::clientPaddingLeft() const
+{
+    LayoutUnit padding = paddingLeft();
+    if (RenderBox* box = innerBlockElement() ? innerBlockElement()->renderBox() : 0)
+        padding += box->x();
+    return padding;
+}
+
+LayoutUnit RenderSearchField::clientPaddingRight() const
+{
+    LayoutUnit padding = paddingRight();
+    if (RenderBox* containerBox = containerElement() ? containerElement()->renderBox() : 0) {
+        if (RenderBox* innerBlockBox = innerBlockElement() ? innerBlockElement()->renderBox() : 0)
+            padding += containerBox->width() - (innerBlockBox->x() + innerBlockBox->width());
+    }
+    return padding;
+}
+
+int RenderSearchField::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 RenderSearchField::selectedIndex() const
+{
+    return -1;
+}
+
+void RenderSearchField::popupDidHide()
+{
+    m_searchPopupIsVisible = false;
+}
+
+bool RenderSearchField::itemIsSeparator(unsigned listIndex) const
+{
+    // The separator will be the second to last item in our list.
+    return static_cast<int>(listIndex) == (listSize() - 2);
+}
+
+bool RenderSearchField::itemIsLabel(unsigned listIndex) const
+{
+    return !listIndex;
+}
+
+bool RenderSearchField::itemIsSelected(unsigned) const
+{
+    return false;
+}
+
+void RenderSearchField::setTextFromItem(unsigned listIndex)
+{
+    inputElement()->setValue(itemText(listIndex));
+}
+
+FontSelector* RenderSearchField::fontSelector() const
+{
+    return document()->styleResolver()->fontSelector();
+}
+
+HostWindow* RenderSearchField::hostWindow() const
+{
+    return document()->view()->hostWindow();
+}
+
+PassRefPtr<Scrollbar> RenderSearchField::createScrollbar(ScrollableArea* scrollableArea, ScrollbarOrientation orientation, ScrollbarControlSize controlSize)
+{
+    RefPtr<Scrollbar> widget;
+    bool hasCustomScrollbarStyle = style()->hasPseudoStyle(SCROLLBAR);
+    if (hasCustomScrollbarStyle)
+        widget = RenderScrollbar::createCustomScrollbar(scrollableArea, orientation, this->node());
+    else
+        widget = Scrollbar::createNativeScrollbar(scrollableArea, orientation, controlSize);
+    return widget.release();
+}
+
+LayoutUnit RenderSearchField::computeLogicalHeightLimit() const
+{
+    return logicalHeight();
+}
+
+void RenderSearchField::centerContainerIfNeeded(RenderBox* containerRenderer) const
+{
+    if (!containerRenderer)
+        return;
+
+    if (containerRenderer->logicalHeight() <= contentLogicalHeight())
+        return;
+
+    // A quirk for find-in-page box on Safari Windows.
+    // http://webkit.org/b/63157
+    LayoutUnit logicalHeightDiff = containerRenderer->logicalHeight() - contentLogicalHeight();
+    containerRenderer->setLogicalTop(containerRenderer->logicalTop() - (logicalHeightDiff / 2 + layoutMod(logicalHeightDiff, 2)));
+}
+
+}
diff --git a/Source/core/rendering/RenderSearchField.h b/Source/core/rendering/RenderSearchField.h
new file mode 100644
index 0000000..026eb68
--- /dev/null
+++ b/Source/core/rendering/RenderSearchField.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2006, 2007, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ * Copyright (C) 2010 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 RenderSearchField_h
+#define RenderSearchField_h
+
+#include "core/platform/PopupMenuClient.h"
+#include "core/rendering/RenderTextControlSingleLine.h"
+
+namespace WebCore {
+
+class HTMLInputElement;
+class SearchPopupMenu;
+
+class RenderSearchField FINAL : public RenderTextControlSingleLine, private PopupMenuClient {
+public:
+    RenderSearchField(Element*);
+    virtual ~RenderSearchField();
+
+    void updateCancelButtonVisibility() const;
+
+    void addSearchResult();
+    void stopSearchEventTimer();
+
+    bool popupIsVisible() const { return m_searchPopupIsVisible; }
+    void showPopup();
+    void hidePopup();
+
+private:
+    virtual void centerContainerIfNeeded(RenderBox*) const OVERRIDE;
+    virtual LayoutUnit computeControlLogicalHeight(LayoutUnit lineHeight, LayoutUnit nonContentHeight) const OVERRIDE;
+    virtual LayoutUnit computeLogicalHeightLimit() const OVERRIDE;
+    virtual void updateFromElement() OVERRIDE;
+    EVisibility visibilityForCancelButton() const;
+    const AtomicString& autosaveName() const;
+
+    // PopupMenuClient methods
+    virtual void valueChanged(unsigned listIndex, bool fireEvents = true) OVERRIDE;
+    virtual void selectionChanged(unsigned, bool) OVERRIDE { }
+    virtual void selectionCleared() OVERRIDE { }
+    virtual String itemText(unsigned listIndex) const OVERRIDE;
+    virtual String itemLabel(unsigned listIndex) const OVERRIDE;
+    virtual String itemIcon(unsigned listIndex) const OVERRIDE;
+    virtual String itemToolTip(unsigned) const OVERRIDE { return String(); }
+    virtual String itemAccessibilityText(unsigned) const OVERRIDE { return String(); }
+    virtual bool itemIsEnabled(unsigned listIndex) const OVERRIDE;
+    virtual PopupMenuStyle itemStyle(unsigned listIndex) const OVERRIDE;
+    virtual PopupMenuStyle menuStyle() const OVERRIDE;
+    virtual int clientInsetLeft() const OVERRIDE;
+    virtual int clientInsetRight() const OVERRIDE;
+    virtual LayoutUnit clientPaddingLeft() const OVERRIDE;
+    virtual LayoutUnit clientPaddingRight() const OVERRIDE;
+    virtual int listSize() const OVERRIDE;
+    virtual int selectedIndex() const OVERRIDE;
+    virtual void popupDidHide() OVERRIDE;
+    virtual bool itemIsSeparator(unsigned listIndex) const OVERRIDE;
+    virtual bool itemIsLabel(unsigned listIndex) const OVERRIDE;
+    virtual bool itemIsSelected(unsigned listIndex) const OVERRIDE;
+    virtual bool valueShouldChangeOnHotTrack() const OVERRIDE { return false; }
+    virtual void setTextFromItem(unsigned listIndex) OVERRIDE;
+    virtual FontSelector* fontSelector() const OVERRIDE;
+    virtual HostWindow* hostWindow() const OVERRIDE;
+    virtual PassRefPtr<Scrollbar> createScrollbar(ScrollableArea*, ScrollbarOrientation, ScrollbarControlSize) OVERRIDE;
+
+    HTMLElement* resultsButtonElement() const;
+    HTMLElement* cancelButtonElement() const;
+
+    bool m_searchPopupIsVisible;
+    RefPtr<SearchPopupMenu> m_searchPopup;
+    Vector<String> m_recentSearches;
+};
+
+inline RenderSearchField* toRenderSearchField(RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isTextField());
+    return static_cast<RenderSearchField*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderSearchField(const RenderSearchField*);
+
+}
+
+#endif
diff --git a/Source/core/rendering/RenderSelectionInfo.h b/Source/core/rendering/RenderSelectionInfo.h
new file mode 100644
index 0000000..f916214
--- /dev/null
+++ b/Source/core/rendering/RenderSelectionInfo.h
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ *           (C) 2000 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2000 Dirk Mueller (mueller@kde.org)
+ *           (C) 2004 Allan Sandfeld Jensen (kde@carewolf.com)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 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 RenderSelectionInfo_h
+#define RenderSelectionInfo_h
+
+#include "core/platform/graphics/IntRect.h"
+#include "core/rendering/RenderBox.h"
+
+namespace WebCore {
+
+class RenderSelectionInfoBase {
+    WTF_MAKE_NONCOPYABLE(RenderSelectionInfoBase); WTF_MAKE_FAST_ALLOCATED;
+public:
+    RenderSelectionInfoBase()
+        : m_object(0)
+        , m_repaintContainer(0)
+        , m_state(RenderObject::SelectionNone)
+    {
+    }
+
+    RenderSelectionInfoBase(RenderObject* o)
+        : m_object(o)
+        , m_repaintContainer(o->containerForRepaint())
+        , m_state(o->selectionState())
+    {
+    }
+    
+    RenderObject* object() const { return m_object; }
+    RenderLayerModelObject* repaintContainer() const { return m_repaintContainer; }
+    RenderObject::SelectionState state() const { return m_state; }
+
+protected:
+    RenderObject* m_object;
+    RenderLayerModelObject* m_repaintContainer;
+    RenderObject::SelectionState m_state;
+};
+
+// This struct is used when the selection changes to cache the old and new state of the selection for each RenderObject.
+class RenderSelectionInfo : public RenderSelectionInfoBase {
+public:
+    RenderSelectionInfo(RenderObject* o, bool clipToVisibleContent)
+        : RenderSelectionInfoBase(o)
+        , m_rect(o->canUpdateSelectionOnRootLineBoxes() ? o->selectionRectForRepaint(m_repaintContainer, clipToVisibleContent) : LayoutRect())
+    {
+    }
+    
+    void repaint()
+    {
+        m_object->repaintUsingContainer(m_repaintContainer, enclosingIntRect(m_rect));
+    }
+
+    LayoutRect rect() const { return m_rect; }
+
+private:
+    LayoutRect m_rect; // relative to repaint container
+};
+
+
+// This struct is used when the selection changes to cache the old and new state of the selection for each RenderBlock.
+class RenderBlockSelectionInfo : public RenderSelectionInfoBase {
+public:
+    RenderBlockSelectionInfo(RenderBlock* b)
+        : RenderSelectionInfoBase(b)
+        , m_rects(b->canUpdateSelectionOnRootLineBoxes() ? block()->selectionGapRectsForRepaint(m_repaintContainer) : GapRects())
+    { 
+    }
+
+    void repaint()
+    {
+        m_object->repaintUsingContainer(m_repaintContainer, enclosingIntRect(m_rects));
+    }
+    
+    RenderBlock* block() const { return toRenderBlock(m_object); }
+    GapRects rects() const { return m_rects; }
+
+private:
+    GapRects m_rects; // relative to repaint container
+};
+
+} // namespace WebCore
+
+
+#endif // RenderSelectionInfo_h
diff --git a/Source/core/rendering/RenderSlider.cpp b/Source/core/rendering/RenderSlider.cpp
new file mode 100644
index 0000000..eac96e8
--- /dev/null
+++ b/Source/core/rendering/RenderSlider.cpp
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 2006, 2007, 2008, 2009, 2010 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 "core/rendering/RenderSlider.h"
+
+#include "CSSPropertyNames.h"
+#include "HTMLNames.h"
+#include "core/css/StyleResolver.h"
+#include "core/dom/Document.h"
+#include "core/dom/Event.h"
+#include "core/dom/EventNames.h"
+#include "core/dom/MouseEvent.h"
+#include "core/dom/Node.h"
+#include "core/dom/ShadowRoot.h"
+#include "core/html/HTMLInputElement.h"
+#include "core/html/StepRange.h"
+#include "core/html/parser/HTMLParserIdioms.h"
+#include "core/html/shadow/MediaControlElements.h"
+#include "core/html/shadow/SliderThumbElement.h"
+#include "core/page/EventHandler.h"
+#include "core/page/Frame.h"
+#include "core/rendering/RenderLayer.h"
+#include "core/rendering/RenderTheme.h"
+#include "core/rendering/RenderView.h"
+#include <wtf/MathExtras.h>
+
+using std::min;
+
+namespace WebCore {
+
+const int RenderSlider::defaultTrackLength = 129;
+
+RenderSlider::RenderSlider(HTMLInputElement* element)
+    : RenderFlexibleBox(element)
+{
+    // We assume RenderSlider works only with <input type=range>.
+    ASSERT(element->isRangeControl());
+}
+
+RenderSlider::~RenderSlider()
+{
+}
+
+bool RenderSlider::canBeReplacedWithInlineRunIn() const
+{
+    return false;
+}
+
+int RenderSlider::baselinePosition(FontBaseline, bool /*firstLine*/, LineDirectionMode, LinePositionMode linePositionMode) const
+{
+    ASSERT(linePositionMode == PositionOnContainingLine);
+    // FIXME: Patch this function for writing-mode.
+    return height() + marginTop();
+}
+
+void RenderSlider::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const
+{
+    maxLogicalWidth = defaultTrackLength * style()->effectiveZoom();
+    if (!style()->width().isPercent())
+        minLogicalWidth = maxLogicalWidth;
+}
+
+void RenderSlider::computePreferredLogicalWidths()
+{
+    m_minPreferredLogicalWidth = 0;
+    m_maxPreferredLogicalWidth = 0;
+
+    if (style()->width().isFixed() && style()->width().value() > 0)
+        m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = adjustContentBoxLogicalWidthForBoxSizing(style()->width().value());
+    else
+        computeIntrinsicLogicalWidths(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);
+
+    if (style()->minWidth().isFixed() && style()->minWidth().value() > 0) {
+        m_maxPreferredLogicalWidth = max(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->minWidth().value()));
+        m_minPreferredLogicalWidth = max(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->minWidth().value()));
+    }
+
+    if (style()->maxWidth().isFixed()) {
+        m_maxPreferredLogicalWidth = min(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->maxWidth().value()));
+        m_minPreferredLogicalWidth = min(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->maxWidth().value()));
+    }
+
+    LayoutUnit toAdd = borderAndPaddingWidth();
+    m_minPreferredLogicalWidth += toAdd;
+    m_maxPreferredLogicalWidth += toAdd;
+
+    setPreferredLogicalWidthsDirty(false); 
+}
+
+void RenderSlider::layout()
+{
+    StackStats::LayoutCheckPoint layoutCheckPoint;
+    // FIXME: Find a way to cascade appearance.
+    // http://webkit.org/b/62535
+    RenderBox* thumbBox = sliderThumbElementOf(node())->renderBox();
+    if (thumbBox && thumbBox->isSliderThumb())
+        static_cast<RenderSliderThumb*>(thumbBox)->updateAppearance(style());
+
+    RenderFlexibleBox::layout();
+}
+
+bool RenderSlider::inDragMode() const
+{
+    return sliderThumbElementOf(node())->active();
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderSlider.h b/Source/core/rendering/RenderSlider.h
new file mode 100644
index 0000000..68dfbd0
--- /dev/null
+++ b/Source/core/rendering/RenderSlider.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2006, 2007, 2008, 2009 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 RenderSlider_h
+#define RenderSlider_h
+
+#include "core/rendering/RenderFlexibleBox.h"
+
+namespace WebCore {
+
+class HTMLInputElement;
+class MouseEvent;
+class SliderThumbElement;
+
+class RenderSlider FINAL : public RenderFlexibleBox {
+public:
+    static const int defaultTrackLength;
+
+    explicit RenderSlider(HTMLInputElement*);
+    virtual ~RenderSlider();
+
+    bool inDragMode() const;
+
+private:
+    virtual const char* renderName() const { return "RenderSlider"; }
+    virtual bool isSlider() const { return true; }
+    virtual bool canBeReplacedWithInlineRunIn() const OVERRIDE;
+
+    virtual int baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const;
+    virtual void computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const OVERRIDE;
+    virtual void computePreferredLogicalWidths() OVERRIDE;
+    virtual bool requiresForcedStyleRecalcPropagation() const { return true; }
+    virtual void layout();
+};
+
+inline RenderSlider* toRenderSlider(RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isSlider());
+    return static_cast<RenderSlider*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderSlider(const RenderSlider*);
+
+} // namespace WebCore
+
+#endif // RenderSlider_h
diff --git a/Source/core/rendering/RenderTable.cpp b/Source/core/rendering/RenderTable.cpp
new file mode 100644
index 0000000..5637be1
--- /dev/null
+++ b/Source/core/rendering/RenderTable.cpp
@@ -0,0 +1,1443 @@
+/*
+ * Copyright (C) 1997 Martin Jones (mjones@kde.org)
+ *           (C) 1997 Torben Weis (weis@kde.org)
+ *           (C) 1998 Waldo Bastian (bastian@kde.org)
+ *           (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
+ *
+ * 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 "core/rendering/RenderTable.h"
+
+#include "HTMLNames.h"
+#include "core/dom/Document.h"
+#include "core/page/FrameView.h"
+#include "core/rendering/AutoTableLayout.h"
+#include "core/rendering/FixedTableLayout.h"
+#include "core/rendering/HitTestResult.h"
+#include "core/rendering/LayoutRepainter.h"
+#include "core/rendering/RenderLayer.h"
+#include "core/rendering/RenderTableCaption.h"
+#include "core/rendering/RenderTableCell.h"
+#include "core/rendering/RenderTableCol.h"
+#include "core/rendering/RenderTableSection.h"
+#include "core/rendering/RenderView.h"
+#include "core/rendering/style/CollapsedBorderValue.h"
+#include "core/rendering/style/StyleInheritedData.h"
+
+using namespace std;
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+RenderTable::RenderTable(Element* element)
+    : RenderBlock(element)
+    , m_head(0)
+    , m_foot(0)
+    , m_firstBody(0)
+    , m_currentBorder(0)
+    , m_collapsedBordersValid(false)
+    , m_hasColElements(false)
+    , m_needsSectionRecalc(false)
+    , m_columnLogicalWidthChanged(false)
+    , m_columnRenderersValid(false)
+    , m_hSpacing(0)
+    , m_vSpacing(0)
+    , m_borderStart(0)
+    , m_borderEnd(0)
+{
+    setChildrenInline(false);
+    m_columnPos.fill(0, 1);
+    
+}
+
+RenderTable::~RenderTable()
+{
+}
+
+void RenderTable::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
+{
+    RenderBlock::styleDidChange(diff, oldStyle);
+    propagateStyleToAnonymousChildren();
+
+    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) {
+        // 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()->logicalWidth().isAuto())
+            m_tableLayout = adoptPtr(new FixedTableLayout(this));
+        else
+            m_tableLayout = adoptPtr(new AutoTableLayout(this));
+    }
+
+    // If border was changed, invalidate collapsed borders cache.
+    if (!needsLayout() && oldStyle && oldStyle->border() != style()->border())
+        invalidateCollapsedBorders();
+}
+
+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)
+{
+    bool wrapInAnonymousSection = !child->isOutOfFlowPositioned();
+
+    if (child->isTableCaption())
+        wrapInAnonymousSection = false;
+    else if (child->isRenderTableCol()) {
+        m_hasColElements = true;
+        wrapInAnonymousSection = false;
+    } else if (child->isTableSection()) {
+        switch (child->style()->display()) {
+            case TABLE_HEADER_GROUP:
+                resetSectionPointerIfNotBefore(m_head, beforeChild);
+                if (!m_head) {
+                    m_head = toRenderTableSection(child);
+                } else {
+                    resetSectionPointerIfNotBefore(m_firstBody, beforeChild);
+                    if (!m_firstBody) 
+                        m_firstBody = toRenderTableSection(child);
+                }
+                wrapInAnonymousSection = false;
+                break;
+            case TABLE_FOOTER_GROUP:
+                resetSectionPointerIfNotBefore(m_foot, beforeChild);
+                if (!m_foot) {
+                    m_foot = toRenderTableSection(child);
+                    wrapInAnonymousSection = false;
+                    break;
+                }
+                // Fall through.
+            case TABLE_ROW_GROUP:
+                resetSectionPointerIfNotBefore(m_firstBody, beforeChild);
+                if (!m_firstBody)
+                    m_firstBody = toRenderTableSection(child);
+                wrapInAnonymousSection = false;
+                break;
+            default:
+                ASSERT_NOT_REACHED();
+        }
+    } else if (child->isTableCell() || child->isTableRow())
+        wrapInAnonymousSection = true;
+    else
+        wrapInAnonymousSection = true;
+
+    if (child->isTableSection())
+        setNeedsSectionRecalc();
+
+    if (!wrapInAnonymousSection) {
+        if (beforeChild && beforeChild->parent() != this)
+            beforeChild = splitAnonymousBoxesAroundChild(beforeChild);
+
+        RenderBox::addChild(child, beforeChild);
+        return;
+    }
+
+    if (!beforeChild && lastChild() && lastChild()->isTableSection() && lastChild()->isAnonymous() && !lastChild()->isBeforeContent()) {
+        lastChild()->addChild(child);
+        return;
+    }
+
+    if (beforeChild && !beforeChild->isAnonymous() && beforeChild->parent() == this) {
+        RenderObject* section = beforeChild->previousSibling();
+        if (section && section->isTableSection() && section->isAnonymous()) {
+            section->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)) {
+        if (beforeChild == lastBox)
+            beforeChild = lastBox->firstChild();
+        lastBox->addChild(child, beforeChild);
+        return;
+    }
+
+    if (beforeChild && !beforeChild->isTableSection() && beforeChild->style()->display() != TABLE_CAPTION && beforeChild->style()->display() != TABLE_COLUMN_GROUP)
+        beforeChild = 0;
+
+    RenderTableSection* section = RenderTableSection::createAnonymousWithParentRenderer(this);
+    addChild(section, beforeChild);
+    section->addChild(child);
+}
+
+void RenderTable::addCaption(const RenderTableCaption* caption)
+{
+    ASSERT(m_captions.find(caption) == notFound);
+    m_captions.append(const_cast<RenderTableCaption*>(caption));
+}
+
+void RenderTable::removeCaption(const RenderTableCaption* oldCaption)
+{
+    size_t index = m_captions.find(oldCaption);
+    ASSERT(index != notFound);
+    if (index == notFound)
+        return;
+
+    m_captions.remove(index);
+}
+
+void RenderTable::invalidateCachedColumns()
+{
+    m_columnRenderersValid = false;
+    m_columnRenderers.resize(0);
+}
+
+void RenderTable::addColumn(const RenderTableCol*)
+{
+    invalidateCachedColumns();
+}
+
+void RenderTable::removeColumn(const RenderTableCol*)
+{
+    invalidateCachedColumns();
+    // We don't really need to recompute our sections, but we need to update our
+    // column count and whether we have a column. Currently, we only have one
+    // size-fit-all flag but we may have to consider splitting it.
+    setNeedsSectionRecalc();
+}
+
+void RenderTable::updateLogicalWidth()
+{
+    recalcSectionsIfNeeded();
+
+    if (isOutOfFlowPositioned()) {
+        LogicalExtentComputedValues computedValues;
+        computePositionedLogicalWidth(computedValues);
+        setLogicalWidth(computedValues.m_extent);
+        setLogicalLeft(computedValues.m_position);
+        setMarginStart(computedValues.m_margins.m_start);
+        setMarginEnd(computedValues.m_margins.m_end);
+    }
+
+    RenderBlock* cb = containingBlock();
+    RenderView* renderView = view();
+
+    LayoutUnit availableLogicalWidth = containingBlockLogicalWidthForContent();
+    bool hasPerpendicularContainingBlock = cb->style()->isHorizontalWritingMode() != style()->isHorizontalWritingMode();
+    LayoutUnit containerWidthInInlineDirection = hasPerpendicularContainingBlock ? perpendicularContainingBlockLogicalHeight() : availableLogicalWidth;
+
+    Length styleLogicalWidth = style()->logicalWidth();
+    if ((styleLogicalWidth.isSpecified() && styleLogicalWidth.isPositive()) || styleLogicalWidth.isIntrinsic())
+        setLogicalWidth(convertStyleLogicalWidthToComputedWidth(styleLogicalWidth, containerWidthInInlineDirection));
+    else {
+        // Subtract out any fixed margins from our available width for auto width tables.
+        LayoutUnit marginStart = minimumValueForLength(style()->marginStart(), availableLogicalWidth, renderView);
+        LayoutUnit marginEnd = minimumValueForLength(style()->marginEnd(), availableLogicalWidth, renderView);
+        LayoutUnit marginTotal = marginStart + marginEnd;
+
+        // Subtract out our margins to get the available content width.
+        LayoutUnit availableContentLogicalWidth = max<LayoutUnit>(0, containerWidthInInlineDirection - marginTotal);
+        if (shrinkToAvoidFloats() && cb->containsFloats() && !hasPerpendicularContainingBlock) {
+            // FIXME: Work with regions someday.
+            availableContentLogicalWidth = shrinkLogicalWidthToAvoidFloats(marginStart, marginEnd, cb, 0, 0);
+        }
+
+        // Ensure we aren't bigger than our available width.
+        setLogicalWidth(min<int>(availableContentLogicalWidth, maxPreferredLogicalWidth()));
+    }
+
+    // Ensure we aren't bigger than our max-width style.
+    Length styleMaxLogicalWidth = style()->logicalMaxWidth();
+    if ((styleMaxLogicalWidth.isSpecified() && !styleMaxLogicalWidth.isNegative()) || styleMaxLogicalWidth.isIntrinsic()) {
+        LayoutUnit computedMaxLogicalWidth = convertStyleLogicalWidthToComputedWidth(styleMaxLogicalWidth, availableLogicalWidth);
+        setLogicalWidth(min<int>(logicalWidth(), computedMaxLogicalWidth));
+    }
+
+    // Ensure we aren't smaller than our min preferred width. This MUST be done after 'max-width' as
+    // we ignore it if it means we wouldn't accomodate our content.
+    setLogicalWidth(max<int>(logicalWidth(), minPreferredLogicalWidth()));
+
+     // Ensure we aren't smaller than our min-width style.
+    Length styleMinLogicalWidth = style()->logicalMinWidth();
+    if ((styleMinLogicalWidth.isSpecified() && !styleMinLogicalWidth.isNegative()) || styleMinLogicalWidth.isIntrinsic()) {
+        LayoutUnit computedMinLogicalWidth = convertStyleLogicalWidthToComputedWidth(styleMinLogicalWidth, availableLogicalWidth);
+        setLogicalWidth(max<int>(logicalWidth(), computedMinLogicalWidth));
+    }
+
+    // Finally, with our true width determined, compute our margins for real.
+    setMarginStart(0);
+    setMarginEnd(0);
+    if (!hasPerpendicularContainingBlock) {
+        LayoutUnit containerLogicalWidthForAutoMargins = availableLogicalWidth;
+        if (avoidsFloats() && cb->containsFloats())
+            containerLogicalWidthForAutoMargins = containingBlockAvailableLineWidthInRegion(0, 0); // FIXME: Work with regions someday.
+        ComputedMarginValues marginValues;
+        bool hasInvertedDirection =  cb->style()->isLeftToRightDirection() == style()->isLeftToRightDirection();
+        computeInlineDirectionMargins(cb, containerLogicalWidthForAutoMargins, logicalWidth(),
+            hasInvertedDirection ? marginValues.m_start : marginValues.m_end,
+            hasInvertedDirection ? marginValues.m_end : marginValues.m_start);
+        setMarginStart(marginValues.m_start);
+        setMarginEnd(marginValues.m_end);
+    } else {
+        setMarginStart(minimumValueForLength(style()->marginStart(), availableLogicalWidth, renderView));
+        setMarginEnd(minimumValueForLength(style()->marginEnd(), availableLogicalWidth, renderView));
+    }
+
+    // We should NEVER shrink the table below the min-content logical width, or else the table can't accomodate
+    // its own content which doesn't match CSS nor what authors expect.
+    ASSERT(logicalWidth() >= minPreferredLogicalWidth());
+}
+
+// This method takes a RenderStyle's logical width, min-width, or max-width length and computes its actual value.
+LayoutUnit RenderTable::convertStyleLogicalWidthToComputedWidth(const Length& styleLogicalWidth, LayoutUnit availableWidth)
+{
+    if (styleLogicalWidth.isIntrinsic())
+        return computeIntrinsicLogicalWidthUsing(styleLogicalWidth, availableWidth, bordersPaddingAndSpacingInRowDirection());
+
+    // HTML tables' width styles already include borders and paddings, but CSS tables' width styles do not.
+    LayoutUnit borders = 0;
+    bool isCSSTable = !node() || !node()->hasTagName(tableTag);
+    if (isCSSTable && styleLogicalWidth.isSpecified() && styleLogicalWidth.isPositive() && style()->boxSizing() == CONTENT_BOX)
+        borders = borderStart() + borderEnd() + (collapseBorders() ? LayoutUnit() : paddingStart() + paddingEnd());
+
+    return minimumValueForLength(styleLogicalWidth, availableWidth, view()) + borders;
+}
+
+LayoutUnit RenderTable::convertStyleLogicalHeightToComputedHeight(const Length& styleLogicalHeight)
+{
+    LayoutUnit borderAndPaddingBefore = borderBefore() + (collapseBorders() ? LayoutUnit() : paddingBefore());
+    LayoutUnit borderAndPaddingAfter = borderAfter() + (collapseBorders() ? LayoutUnit() : paddingAfter());
+    LayoutUnit borderAndPadding = borderAndPaddingBefore + borderAndPaddingAfter;
+    LayoutUnit computedLogicalHeight = 0;
+    if (styleLogicalHeight.isFixed()) {
+        // HTML tables size as though CSS height includes border/padding, CSS tables do not.
+        LayoutUnit borders = LayoutUnit();
+        // FIXME: We cannot apply box-sizing: content-box on <table> which other browsers allow.
+        if ((node() && node()->hasTagName(tableTag)) || style()->boxSizing() == BORDER_BOX) {
+            borders = borderAndPadding;
+        }
+        computedLogicalHeight = styleLogicalHeight.value() - borders;
+    } else if (styleLogicalHeight.isPercent())
+        computedLogicalHeight = computePercentageLogicalHeight(styleLogicalHeight);
+    else if (styleLogicalHeight.isViewportPercentage())
+        computedLogicalHeight = minimumValueForLength(styleLogicalHeight, 0, view());
+    else if (styleLogicalHeight.isIntrinsic())
+        computedLogicalHeight = computeIntrinsicLogicalContentHeightUsing(styleLogicalHeight, logicalHeight() - borderAndPadding, borderAndPadding);
+    else
+        ASSERT_NOT_REACHED();
+    return max<LayoutUnit>(0, computedLogicalHeight);
+}
+
+void RenderTable::layoutCaption(RenderTableCaption* caption)
+{
+    LayoutRect captionRect(caption->frameRect());
+
+    if (caption->needsLayout()) {
+        // The margins may not be available but ensure the caption is at least located beneath any previous sibling caption
+        // so that it does not mistakenly think any floats in the previous caption intrude into it.
+        caption->setLogicalLocation(LayoutPoint(caption->marginStart(), caption->marginBefore() + logicalHeight()));
+        // If RenderTableCaption ever gets a layout() function, use it here.
+        caption->layoutIfNeeded();
+    }
+    // Apply the margins to the location now that they are definitely available from layout
+    caption->setLogicalLocation(LayoutPoint(caption->marginStart(), caption->marginBefore() + logicalHeight()));
+
+    if (!selfNeedsLayout() && caption->checkForRepaintDuringLayout())
+        caption->repaintDuringLayoutIfMoved(captionRect);
+
+    setLogicalHeight(logicalHeight() + caption->logicalHeight() + caption->marginBefore() + caption->marginAfter());
+}
+
+void RenderTable::distributeExtraLogicalHeight(int extraLogicalHeight)
+{
+    if (extraLogicalHeight <= 0)
+        return;
+
+    // FIXME: Distribute the extra logical height between all table sections instead of giving it all to the first one.
+    if (RenderTableSection* section = firstBody())
+        extraLogicalHeight -= section->distributeExtraLogicalHeightToRows(extraLogicalHeight);
+
+    // FIXME: We really would like to enable this ASSERT to ensure that all the extra space has been distributed.
+    // However our current distribution algorithm does not round properly and thus we can have some remaining height.
+    // ASSERT(!topSection() || !extraLogicalHeight);
+}
+
+void RenderTable::simplifiedNormalFlowLayout()
+{
+    for (RenderTableSection* section = topSection(); section; section = sectionBelow(section)) {
+        section->layoutIfNeeded();
+        section->computeOverflowFromCells();
+    }
+}
+
+void RenderTable::layout()
+{
+    StackStats::LayoutCheckPoint layoutCheckPoint;
+    ASSERT(needsLayout());
+
+    if (simplifiedLayout())
+        return;
+
+    recalcSectionsIfNeeded();
+    // FIXME: We should do this recalc lazily in borderStart/borderEnd so that we don't have to make sure
+    // to call this before we call borderStart/borderEnd to avoid getting a stale value.
+    recalcBordersInRowDirection();
+        
+    LayoutRepainter repainter(*this, checkForRepaintDuringLayout());
+    LayoutStateMaintainer statePusher(view(), this, locationOffset(), style()->isFlippedBlocksWritingMode());
+
+    setLogicalHeight(0);
+
+    initMaxMarginValues();
+    
+    LayoutUnit oldLogicalWidth = logicalWidth();
+    updateLogicalWidth();
+
+    if (logicalWidth() != oldLogicalWidth) {
+        for (unsigned i = 0; i < m_captions.size(); i++)
+            m_captions[i]->setNeedsLayout(true, MarkOnlyThis);
+    }
+    // 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 != width() || columns.size() + 1 != columnPos.size() )
+    m_tableLayout->layout();
+
+    LayoutUnit totalSectionLogicalHeight = 0;
+    LayoutUnit oldTableLogicalTop = 0;
+    for (unsigned i = 0; i < m_captions.size(); i++)
+        oldTableLogicalTop += m_captions[i]->logicalHeight() + m_captions[i]->marginBefore() + m_captions[i]->marginAfter();
+
+    bool collapsing = collapseBorders();
+
+    for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+        if (child->isTableSection()) {
+            RenderTableSection* section = toRenderTableSection(child);
+            if (m_columnLogicalWidthChanged)
+                section->setChildNeedsLayout(true, MarkOnlyThis);
+            section->layoutIfNeeded();
+            totalSectionLogicalHeight += section->calcRowLogicalHeight();
+            if (collapsing)
+                section->recalcOuterBorder();
+            ASSERT(!section->needsLayout());
+        } else if (child->isRenderTableCol()) {
+            child->layoutIfNeeded();
+            ASSERT(!child->needsLayout());
+        }
+    }
+
+    // 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;
+    LayoutUnit movedSectionLogicalTop = 0;
+
+    // FIXME: Collapse caption margin.
+    if (!m_captions.isEmpty()) {
+        for (unsigned i = 0; i < m_captions.size(); i++) {
+            if (m_captions[i]->style()->captionSide() == CAPBOTTOM)
+                continue;
+            layoutCaption(m_captions[i]);
+        }
+        if (logicalHeight() != oldTableLogicalTop) {
+            sectionMoved = true;
+            movedSectionLogicalTop = min(logicalHeight(), oldTableLogicalTop);
+        }
+    }
+
+    LayoutUnit borderAndPaddingBefore = borderBefore() + (collapsing ? LayoutUnit() : paddingBefore());
+    LayoutUnit borderAndPaddingAfter = borderAfter() + (collapsing ? LayoutUnit() : paddingAfter());
+
+    setLogicalHeight(logicalHeight() + borderAndPaddingBefore);
+
+    if (!isOutOfFlowPositioned())
+        updateLogicalHeight();
+
+    LayoutUnit computedLogicalHeight = 0;
+    
+    Length logicalHeightLength = style()->logicalHeight();
+    if (logicalHeightLength.isIntrinsic() || (logicalHeightLength.isSpecified() && logicalHeightLength.isPositive()))
+        computedLogicalHeight = convertStyleLogicalHeightToComputedHeight(logicalHeightLength);
+    
+    Length logicalMaxHeightLength = style()->logicalMaxHeight();
+    if (logicalMaxHeightLength.isIntrinsic() || (logicalMaxHeightLength.isSpecified() && !logicalMaxHeightLength.isNegative())) {
+        LayoutUnit computedMaxLogicalHeight = convertStyleLogicalHeightToComputedHeight(logicalMaxHeightLength);
+        computedLogicalHeight = min(computedLogicalHeight, computedMaxLogicalHeight);
+    }
+
+    Length logicalMinHeightLength = style()->logicalMinHeight();
+    if (logicalMinHeightLength.isIntrinsic() || (logicalMinHeightLength.isSpecified() && !logicalMinHeightLength.isNegative())) {
+        LayoutUnit computedMinLogicalHeight = convertStyleLogicalHeightToComputedHeight(logicalMinHeightLength);
+        computedLogicalHeight = max(computedLogicalHeight, computedMinLogicalHeight);
+    }
+
+    distributeExtraLogicalHeight(floorToInt(computedLogicalHeight - totalSectionLogicalHeight));
+
+    for (RenderTableSection* section = topSection(); section; section = sectionBelow(section))
+        section->layoutRows();
+
+    if (!topSection() && computedLogicalHeight > totalSectionLogicalHeight && !document()->inQuirksMode()) {
+        // Completely empty tables (with no sections or anything) should at least honor specified height
+        // in strict mode.
+        setLogicalHeight(logicalHeight() + computedLogicalHeight);
+    }
+
+    LayoutUnit sectionLogicalLeft = style()->isLeftToRightDirection() ? borderStart() : borderEnd();
+    if (!collapsing)
+        sectionLogicalLeft += style()->isLeftToRightDirection() ? paddingStart() : paddingEnd();
+
+    // position the table sections
+    RenderTableSection* section = topSection();
+    while (section) {
+        if (!sectionMoved && section->logicalTop() != logicalHeight()) {
+            sectionMoved = true;
+            movedSectionLogicalTop = min(logicalHeight(), section->logicalTop()) + (style()->isHorizontalWritingMode() ? section->visualOverflowRect().y() : section->visualOverflowRect().x());
+        }
+        section->setLogicalLocation(LayoutPoint(sectionLogicalLeft, logicalHeight()));
+
+        setLogicalHeight(logicalHeight() + section->logicalHeight());
+        section = sectionBelow(section);
+    }
+
+    setLogicalHeight(logicalHeight() + borderAndPaddingAfter);
+
+    for (unsigned i = 0; i < m_captions.size(); i++) {
+        if (m_captions[i]->style()->captionSide() != CAPBOTTOM)
+            continue;
+        layoutCaption(m_captions[i]);
+    }
+
+    if (isOutOfFlowPositioned())
+        updateLogicalHeight();
+
+    // table can be containing block of positioned elements.
+    // FIXME: Only pass true if width or height changed.
+    layoutPositionedObjects(true);
+
+    updateLayerTransform();
+
+    // Layout was changed, so probably borders too.
+    invalidateCollapsedBorders();
+
+    computeOverflow(clientLogicalBottom());
+
+    statePusher.pop();
+
+    if (view()->layoutState()->pageLogicalHeight())
+        setPageLogicalOffset(view()->layoutState()->pageLogicalOffset(this, logicalTop()));
+
+    bool didFullRepaint = repainter.repaintAfterLayout();
+    // Repaint with our new bounds if they are different from our old bounds.
+    if (!didFullRepaint && sectionMoved) {
+        if (style()->isHorizontalWritingMode())
+            repaintRectangle(LayoutRect(visualOverflowRect().x(), movedSectionLogicalTop, visualOverflowRect().width(), visualOverflowRect().maxY() - movedSectionLogicalTop));
+        else
+            repaintRectangle(LayoutRect(movedSectionLogicalTop, visualOverflowRect().y(), visualOverflowRect().maxX() - movedSectionLogicalTop, visualOverflowRect().height()));
+    }
+
+    m_columnLogicalWidthChanged = false;
+    setNeedsLayout(false);
+}
+
+// Collect all the unique border values that we want to paint in a sorted list.
+void RenderTable::recalcCollapsedBorders()
+{
+    if (m_collapsedBordersValid)
+        return;
+    m_collapsedBordersValid = true;
+    m_collapsedBorders.clear();
+    for (RenderObject* section = firstChild(); section; section = section->nextSibling()) {
+        if (!section->isTableSection())
+            continue;
+        for (RenderObject* row = section->firstChild(); row; row = row->nextSibling()) {
+            if (!row->isTableRow())
+                continue;
+            for (RenderObject* cell = row->firstChild(); cell; cell = cell->nextSibling()) {
+                if (!cell->isTableCell())
+                    continue;
+                ASSERT(toRenderTableCell(cell)->table() == this);
+                toRenderTableCell(cell)->collectBorderValues(m_collapsedBorders);
+            }
+        }
+    }
+    RenderTableCell::sortBorderValues(m_collapsedBorders);
+}
+
+
+void RenderTable::addOverflowFromChildren()
+{
+    // Add overflow from borders.
+    // Technically it's odd that we are incorporating the borders into layout overflow, which is only supposed to be about overflow from our
+    // descendant objects, but since tables don't support overflow:auto, this works out fine.
+    if (collapseBorders()) {
+        int rightBorderOverflow = width() + outerBorderRight() - borderRight();
+        int leftBorderOverflow = borderLeft() - outerBorderLeft();
+        int bottomBorderOverflow = height() + outerBorderBottom() - borderBottom();
+        int topBorderOverflow = borderTop() - outerBorderTop();
+        IntRect borderOverflowRect(leftBorderOverflow, topBorderOverflow, rightBorderOverflow - leftBorderOverflow, bottomBorderOverflow - topBorderOverflow);
+        if (borderOverflowRect != pixelSnappedBorderBoxRect()) {
+            addLayoutOverflow(borderOverflowRect);
+            addVisualOverflow(borderOverflowRect);
+        }
+    }
+
+    // Add overflow from our caption.
+    for (unsigned i = 0; i < m_captions.size(); i++) 
+        addOverflowFromChild(m_captions[i]);
+
+    // Add overflow from our sections.
+    for (RenderTableSection* section = topSection(); section; section = sectionBelow(section))
+        addOverflowFromChild(section);
+}
+
+void RenderTable::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    LayoutPoint adjustedPaintOffset = paintOffset + location();
+
+    PaintPhase paintPhase = paintInfo.phase;
+
+    if (!isRoot()) {
+        LayoutRect overflowBox = visualOverflowRect();
+        flipForWritingMode(overflowBox);
+        overflowBox.inflate(maximalOutlineSize(paintInfo.phase));
+        overflowBox.moveBy(adjustedPaintOffset);
+        if (!overflowBox.intersects(paintInfo.rect))
+            return;
+    }
+
+    bool pushedClip = pushContentsClip(paintInfo, adjustedPaintOffset);
+    paintObject(paintInfo, adjustedPaintOffset);
+    if (pushedClip)
+        popContentsClip(paintInfo, paintPhase, adjustedPaintOffset);
+}
+
+void RenderTable::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    PaintPhase paintPhase = paintInfo.phase;
+    if ((paintPhase == PaintPhaseBlockBackground || paintPhase == PaintPhaseChildBlockBackground) && hasBoxDecorations() && style()->visibility() == VISIBLE)
+        paintBoxDecorations(paintInfo, paintOffset);
+
+    if (paintPhase == PaintPhaseMask) {
+        paintMask(paintInfo, paintOffset);
+        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.updatePaintingRootForChildren(this);
+
+    for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+        if (child->isBox() && !toRenderBox(child)->hasSelfPaintingLayer() && (child->isTableSection() || child->isTableCaption())) {
+            LayoutPoint childPoint = flipForWritingModeForChild(toRenderBox(child), paintOffset);
+            child->paint(info, childPoint);
+        }
+    }
+    
+    if (collapseBorders() && paintPhase == PaintPhaseChildBlockBackground && style()->visibility() == VISIBLE) {
+        recalcCollapsedBorders();
+        // Using our cached sorted styles, we then do individual passes,
+        // painting each style of border from lowest precedence to highest precedence.
+        info.phase = PaintPhaseCollapsedTableBorders;
+        size_t count = m_collapsedBorders.size();
+        for (size_t i = 0; i < count; ++i) {
+            m_currentBorder = &m_collapsedBorders[i];
+            for (RenderTableSection* section = bottomSection(); section; section = sectionAbove(section)) {
+                LayoutPoint childPoint = flipForWritingModeForChild(section, paintOffset);
+                section->paint(info, childPoint);
+            }
+        }
+        m_currentBorder = 0;
+    }
+
+    // Paint outline.
+    if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseSelfOutline) && hasOutline() && style()->visibility() == VISIBLE)
+        paintOutline(paintInfo, LayoutRect(paintOffset, size()));
+}
+
+void RenderTable::subtractCaptionRect(LayoutRect& rect) const
+{
+    for (unsigned i = 0; i < m_captions.size(); i++) {
+        LayoutUnit captionLogicalHeight = m_captions[i]->logicalHeight() + m_captions[i]->marginBefore() + m_captions[i]->marginAfter();
+        bool captionIsBefore = (m_captions[i]->style()->captionSide() != CAPBOTTOM) ^ style()->isFlippedBlocksWritingMode();
+        if (style()->isHorizontalWritingMode()) {
+            rect.setHeight(rect.height() - captionLogicalHeight);
+            if (captionIsBefore)
+                rect.move(0, captionLogicalHeight);
+        } else {
+            rect.setWidth(rect.width() - captionLogicalHeight);
+            if (captionIsBefore)
+                rect.move(captionLogicalHeight, 0);
+        }
+    }
+}
+
+void RenderTable::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    if (!paintInfo.shouldPaintWithinRoot(this))
+        return;
+
+    LayoutRect rect(paintOffset, size());
+    subtractCaptionRect(rect);
+
+    BackgroundBleedAvoidance bleedAvoidance = determineBackgroundBleedAvoidance(paintInfo.context);
+    if (!boxShadowShouldBeAppliedToBackground(bleedAvoidance))
+        paintBoxShadow(paintInfo, rect, style(), Normal);
+    paintBackground(paintInfo, rect, bleedAvoidance);
+    paintBoxShadow(paintInfo, rect, style(), Inset);
+
+    if (style()->hasBorder() && !collapseBorders())
+        paintBorder(paintInfo, rect, style());
+}
+
+void RenderTable::paintMask(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    if (style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask)
+        return;
+
+    LayoutRect rect(paintOffset, size());
+    subtractCaptionRect(rect);
+
+    paintMaskImages(paintInfo, rect);
+}
+
+void RenderTable::computeIntrinsicLogicalWidths(LayoutUnit& minWidth, LayoutUnit& maxWidth) const
+{
+    recalcSectionsIfNeeded();
+    // FIXME: Do the recalc in borderStart/borderEnd and make those const_cast this call.
+    // Then m_borderStart/m_borderEnd will be transparent a cache and it removes the possibility
+    // of reading out stale values.
+    const_cast<RenderTable*>(this)->recalcBordersInRowDirection();
+    // FIXME: Restructure the table layout code so that we can make this method const.
+    const_cast<RenderTable*>(this)->m_tableLayout->computeIntrinsicLogicalWidths(minWidth, maxWidth);
+
+    // FIXME: We should include captions widths here like we do in computePreferredLogicalWidths.
+}
+
+void RenderTable::computePreferredLogicalWidths()
+{
+    ASSERT(preferredLogicalWidthsDirty());
+
+    computeIntrinsicLogicalWidths(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);
+
+    int bordersPaddingAndSpacing = bordersPaddingAndSpacingInRowDirection();
+    m_minPreferredLogicalWidth += bordersPaddingAndSpacing;
+    m_maxPreferredLogicalWidth += bordersPaddingAndSpacing;
+
+    m_tableLayout->applyPreferredLogicalWidthQuirks(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);
+
+    for (unsigned i = 0; i < m_captions.size(); i++)
+        m_minPreferredLogicalWidth = max(m_minPreferredLogicalWidth, m_captions[i]->minPreferredLogicalWidth());
+
+    RenderStyle* styleToUse = style();
+    // FIXME: This should probably be checking for isSpecified since you should be able to use percentage, calc or viewport relative values for min-width.
+    if (styleToUse->logicalMinWidth().isFixed() && styleToUse->logicalMinWidth().value() > 0) {
+        m_maxPreferredLogicalWidth = std::max(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->logicalMinWidth().value()));
+        m_minPreferredLogicalWidth = std::max(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->logicalMinWidth().value()));
+    }
+
+    // FIXME: This should probably be checking for isSpecified since you should be able to use percentage, calc or viewport relative values for maxWidth.
+    if (styleToUse->logicalMaxWidth().isFixed()) {
+        // We don't constrain m_minPreferredLogicalWidth as the table should be at least the size of its min-content, regardless of 'max-width'.
+        m_maxPreferredLogicalWidth = std::min(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(styleToUse->logicalMaxWidth().value()));
+        m_maxPreferredLogicalWidth = std::max(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);
+    }
+
+    // FIXME: We should be adding borderAndPaddingLogicalWidth here, but m_tableLayout->computePreferredLogicalWidths already does,
+    // so a bunch of tests break doing this naively.
+    setPreferredLogicalWidthsDirty(false);
+}
+
+RenderTableSection* RenderTable::topNonEmptySection() const
+{
+    RenderTableSection* section = topSection();
+    if (section && !section->numRows())
+        section = sectionBelow(section, SkipEmptySections);
+    return section;
+}
+
+void RenderTable::splitColumn(unsigned position, unsigned firstSpan)
+{
+    // We split the column at "position", taking "firstSpan" cells from the span.
+    ASSERT(m_columns[position].span > firstSpan);
+    m_columns.insert(position, ColumnStruct(firstSpan));
+    m_columns[position + 1].span -= firstSpan;
+
+    // Propagate the change in our columns representation to the sections that don't need
+    // cell recalc. If they do, they will be synced up directly with m_columns later.
+    for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+        if (!child->isTableSection())
+            continue;
+
+        RenderTableSection* section = toRenderTableSection(child);
+        if (section->needsCellRecalc())
+            continue;
+
+        section->splitColumn(position, firstSpan);
+    }
+
+    m_columnPos.grow(numEffCols() + 1);
+}
+
+void RenderTable::appendColumn(unsigned span)
+{
+    unsigned newColumnIndex = m_columns.size();
+    m_columns.append(ColumnStruct(span));
+
+    // Propagate the change in our columns representation to the sections that don't need
+    // cell recalc. If they do, they will be synced up directly with m_columns later.
+    for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+        if (!child->isTableSection())
+            continue;
+
+        RenderTableSection* section = toRenderTableSection(child);
+        if (section->needsCellRecalc())
+            continue;
+
+        section->appendColumn(newColumnIndex);
+    }
+
+    m_columnPos.grow(numEffCols() + 1);
+}
+
+RenderTableCol* RenderTable::firstColumn() const
+{
+    for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+        if (child->isRenderTableCol())
+            return toRenderTableCol(child);
+
+        // We allow only table-captions before columns or column-groups.
+        if (!child->isTableCaption())
+            return 0;
+    }
+
+    return 0;
+}
+
+void RenderTable::updateColumnCache() const
+{
+    ASSERT(m_hasColElements);
+    ASSERT(m_columnRenderers.isEmpty());
+    ASSERT(!m_columnRenderersValid);
+
+    for (RenderTableCol* columnRenderer = firstColumn(); columnRenderer; columnRenderer = columnRenderer->nextColumn()) {
+        if (columnRenderer->isTableColumnGroupWithColumnChildren())
+            continue;
+        m_columnRenderers.append(columnRenderer);
+    }
+    m_columnRenderersValid = true;
+}
+
+RenderTableCol* RenderTable::slowColElement(unsigned col, bool* startEdge, bool* endEdge) const
+{
+    ASSERT(m_hasColElements);
+
+    if (!m_columnRenderersValid)
+        updateColumnCache();
+
+    unsigned columnCount = 0;
+    for (unsigned i = 0; i < m_columnRenderers.size(); i++) {
+        RenderTableCol* columnRenderer = m_columnRenderers[i];
+        unsigned span = columnRenderer->span();
+        unsigned startCol = columnCount;
+        ASSERT(span >= 1);
+        unsigned endCol = columnCount + span - 1;
+        columnCount += span;
+        if (columnCount > col) {
+            if (startEdge)
+                *startEdge = startCol == col;
+            if (endEdge)
+                *endEdge = endCol == col;
+            return columnRenderer;
+        }
+    }
+    return 0;
+}
+
+void RenderTable::recalcSections() const
+{
+    ASSERT(m_needsSectionRecalc);
+
+    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
+    RenderObject* nextSibling;
+    for (RenderObject* child = firstChild(); child; child = nextSibling) {
+        nextSibling = child->nextSibling();
+        switch (child->style()->display()) {
+        case TABLE_COLUMN:
+        case TABLE_COLUMN_GROUP:
+            m_hasColElements = true;
+            break;
+        case TABLE_HEADER_GROUP:
+            if (child->isTableSection()) {
+                RenderTableSection* section = toRenderTableSection(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 = toRenderTableSection(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 = toRenderTableSection(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)
+    unsigned maxCols = 0;
+    for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+        if (child->isTableSection()) {
+            RenderTableSection* section = toRenderTableSection(child);
+            unsigned sectionCols = section->numColumns();
+            if (sectionCols > maxCols)
+                maxCols = sectionCols;
+        }
+    }
+    
+    m_columns.resize(maxCols);
+    m_columnPos.resize(maxCols + 1);
+
+    ASSERT(selfNeedsLayout());
+
+    m_needsSectionRecalc = false;
+}
+
+int RenderTable::calcBorderStart() const
+{
+    if (!collapseBorders())
+        return RenderBlock::borderStart();
+
+    // 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& tableStartBorder = style()->borderStart();
+    if (tableStartBorder.style() == BHIDDEN)
+        return 0;
+    if (tableStartBorder.style() > BHIDDEN)
+        borderWidth = tableStartBorder.width();
+
+    if (RenderTableCol* column = colElement(0)) {
+        // FIXME: We don't account for direction on columns and column groups.
+        const BorderValue& columnAdjoiningBorder = column->style()->borderStart();
+        if (columnAdjoiningBorder.style() == BHIDDEN)
+            return 0;
+        if (columnAdjoiningBorder.style() > BHIDDEN)
+            borderWidth = max(borderWidth, columnAdjoiningBorder.width());
+        // FIXME: This logic doesn't properly account for the first column in the first column-group case.
+    }
+
+    if (const RenderTableSection* topNonEmptySection = this->topNonEmptySection()) {
+        const BorderValue& sectionAdjoiningBorder = topNonEmptySection->borderAdjoiningTableStart();
+        if (sectionAdjoiningBorder.style() == BHIDDEN)
+            return 0;
+
+        if (sectionAdjoiningBorder.style() > BHIDDEN)
+            borderWidth = max(borderWidth, sectionAdjoiningBorder.width());
+
+        if (const RenderTableCell* adjoiningStartCell = topNonEmptySection->firstRowCellAdjoiningTableStart()) {
+            // FIXME: Make this work with perpendicular and flipped cells.
+            const BorderValue& startCellAdjoiningBorder = adjoiningStartCell->borderAdjoiningTableStart();
+            if (startCellAdjoiningBorder.style() == BHIDDEN)
+                return 0;
+
+            const BorderValue& firstRowAdjoiningBorder = adjoiningStartCell->row()->borderAdjoiningTableStart();
+            if (firstRowAdjoiningBorder.style() == BHIDDEN)
+                return 0;
+
+            if (startCellAdjoiningBorder.style() > BHIDDEN)
+                borderWidth = max(borderWidth, startCellAdjoiningBorder.width());
+            if (firstRowAdjoiningBorder.style() > BHIDDEN)
+                borderWidth = max(borderWidth, firstRowAdjoiningBorder.width());
+        }
+    }
+    return (borderWidth + (style()->isLeftToRightDirection() ? 0 : 1)) / 2;
+}
+
+int RenderTable::calcBorderEnd() const
+{
+    if (!collapseBorders())
+        return RenderBlock::borderEnd();
+
+    // 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& tableEndBorder = style()->borderEnd();
+    if (tableEndBorder.style() == BHIDDEN)
+        return 0;
+    if (tableEndBorder.style() > BHIDDEN)
+        borderWidth = tableEndBorder.width();
+
+    unsigned endColumn = numEffCols() - 1;
+    if (RenderTableCol* column = colElement(endColumn)) {
+        // FIXME: We don't account for direction on columns and column groups.
+        const BorderValue& columnAdjoiningBorder = column->style()->borderEnd();
+        if (columnAdjoiningBorder.style() == BHIDDEN)
+            return 0;
+        if (columnAdjoiningBorder.style() > BHIDDEN)
+            borderWidth = max(borderWidth, columnAdjoiningBorder.width());
+        // FIXME: This logic doesn't properly account for the last column in the last column-group case.
+    }
+
+    if (const RenderTableSection* topNonEmptySection = this->topNonEmptySection()) {
+        const BorderValue& sectionAdjoiningBorder = topNonEmptySection->borderAdjoiningTableEnd();
+        if (sectionAdjoiningBorder.style() == BHIDDEN)
+            return 0;
+
+        if (sectionAdjoiningBorder.style() > BHIDDEN)
+            borderWidth = max(borderWidth, sectionAdjoiningBorder.width());
+
+        if (const RenderTableCell* adjoiningEndCell = topNonEmptySection->firstRowCellAdjoiningTableEnd()) {
+            // FIXME: Make this work with perpendicular and flipped cells.
+            const BorderValue& endCellAdjoiningBorder = adjoiningEndCell->borderAdjoiningTableEnd();
+            if (endCellAdjoiningBorder.style() == BHIDDEN)
+                return 0;
+
+            const BorderValue& firstRowAdjoiningBorder = adjoiningEndCell->row()->borderAdjoiningTableEnd();
+            if (firstRowAdjoiningBorder.style() == BHIDDEN)
+                return 0;
+
+            if (endCellAdjoiningBorder.style() > BHIDDEN)
+                borderWidth = max(borderWidth, endCellAdjoiningBorder.width());
+            if (firstRowAdjoiningBorder.style() > BHIDDEN)
+                borderWidth = max(borderWidth, firstRowAdjoiningBorder.width());
+        }
+    }
+    return (borderWidth + (style()->isLeftToRightDirection() ? 1 : 0)) / 2;
+}
+
+void RenderTable::recalcBordersInRowDirection()
+{
+    // FIXME: We need to compute the collapsed before / after borders in the same fashion.
+    m_borderStart = calcBorderStart();
+    m_borderEnd = calcBorderEnd();
+}
+
+int RenderTable::borderBefore() const
+{
+    if (collapseBorders()) {
+        recalcSectionsIfNeeded();
+        return outerBorderBefore();
+    }
+    return RenderBlock::borderBefore();
+}
+
+int RenderTable::borderAfter() const
+{
+    if (collapseBorders()) {
+        recalcSectionsIfNeeded();
+        return outerBorderAfter();
+    }
+    return RenderBlock::borderAfter();
+}
+
+int RenderTable::outerBorderBefore() const
+{
+    if (!collapseBorders())
+        return 0;
+    int borderWidth = 0;
+    if (RenderTableSection* topSection = this->topSection()) {
+        borderWidth = topSection->outerBorderBefore();
+        if (borderWidth < 0)
+            return 0;   // Overridden by hidden
+    }
+    const BorderValue& tb = style()->borderBefore();
+    if (tb.style() == BHIDDEN)
+        return 0;
+    if (tb.style() > BHIDDEN)
+        borderWidth = max<int>(borderWidth, tb.width() / 2);
+    return borderWidth;
+}
+
+int RenderTable::outerBorderAfter() const
+{
+    if (!collapseBorders())
+        return 0;
+    int borderWidth = 0;
+
+    if (RenderTableSection* section = bottomSection()) {
+        borderWidth = section->outerBorderAfter();
+        if (borderWidth < 0)
+            return 0; // Overridden by hidden
+    }
+    const BorderValue& tb = style()->borderAfter();
+    if (tb.style() == BHIDDEN)
+        return 0;
+    if (tb.style() > BHIDDEN)
+        borderWidth = max<int>(borderWidth, (tb.width() + 1) / 2);
+    return borderWidth;
+}
+
+int RenderTable::outerBorderStart() const
+{
+    if (!collapseBorders())
+        return 0;
+
+    int borderWidth = 0;
+
+    const BorderValue& tb = style()->borderStart();
+    if (tb.style() == BHIDDEN)
+        return 0;
+    if (tb.style() > BHIDDEN)
+        borderWidth = (tb.width() + (style()->isLeftToRightDirection() ? 0 : 1)) / 2;
+
+    bool allHidden = true;
+    for (RenderTableSection* section = topSection(); section; section = sectionBelow(section)) {
+        int sw = section->outerBorderStart();
+        if (sw < 0)
+            continue;
+        allHidden = false;
+        borderWidth = max(borderWidth, sw);
+    }
+    if (allHidden)
+        return 0;
+
+    return borderWidth;
+}
+
+int RenderTable::outerBorderEnd() const
+{
+    if (!collapseBorders())
+        return 0;
+
+    int borderWidth = 0;
+
+    const BorderValue& tb = style()->borderEnd();
+    if (tb.style() == BHIDDEN)
+        return 0;
+    if (tb.style() > BHIDDEN)
+        borderWidth = (tb.width() + (style()->isLeftToRightDirection() ? 1 : 0)) / 2;
+
+    bool allHidden = true;
+    for (RenderTableSection* section = topSection(); section; section = sectionBelow(section)) {
+        int sw = section->outerBorderEnd();
+        if (sw < 0)
+            continue;
+        allHidden = false;
+        borderWidth = max(borderWidth, sw);
+    }
+    if (allHidden)
+        return 0;
+
+    return borderWidth;
+}
+
+RenderTableSection* RenderTable::sectionAbove(const RenderTableSection* section, SkipEmptySectionsValue 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 == DoNotSkipEmptySections || toRenderTableSection(prevSection)->numRows()))
+            break;
+        prevSection = prevSection->previousSibling();
+    }
+    if (!prevSection && m_head && (skipEmptySections == DoNotSkipEmptySections || m_head->numRows()))
+        prevSection = m_head;
+    return toRenderTableSection(prevSection);
+}
+
+RenderTableSection* RenderTable::sectionBelow(const RenderTableSection* section, SkipEmptySectionsValue 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  == DoNotSkipEmptySections || toRenderTableSection(nextSection)->numRows()))
+            break;
+        nextSection = nextSection->nextSibling();
+    }
+    if (!nextSection && m_foot && (skipEmptySections == DoNotSkipEmptySections || m_foot->numRows()))
+        nextSection = m_foot;
+    return toRenderTableSection(nextSection);
+}
+
+RenderTableSection* RenderTable::bottomSection() const
+{
+    recalcSectionsIfNeeded();
+
+    if (m_foot)
+        return m_foot;
+
+    for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
+        if (child->isTableSection())
+            return toRenderTableSection(child);
+    }
+
+    return 0;
+}
+
+RenderTableCell* RenderTable::cellAbove(const RenderTableCell* cell) const
+{
+    recalcSectionsIfNeeded();
+
+    // Find the section and row to look in
+    unsigned r = cell->rowIndex();
+    RenderTableSection* section = 0;
+    unsigned 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(), SkipEmptySections);
+        if (section) {
+            ASSERT(section->numRows());
+            rAbove = section->numRows() - 1;
+        }
+    }
+
+    // Look up the cell in the section's grid, which requires effective col index
+    if (section) {
+        unsigned effCol = colToEffCol(cell->col());
+        RenderTableSection::CellStruct& aboveCell = section->cellAt(rAbove, effCol);
+        return aboveCell.primaryCell();
+    } else
+        return 0;
+}
+
+RenderTableCell* RenderTable::cellBelow(const RenderTableCell* cell) const
+{
+    recalcSectionsIfNeeded();
+
+    // Find the section and row to look in
+    unsigned r = cell->rowIndex() + cell->rowSpan() - 1;
+    RenderTableSection* section = 0;
+    unsigned 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(), SkipEmptySections);
+        if (section)
+            rBelow = 0;
+    }
+
+    // Look up the cell in the section's grid, which requires effective col index
+    if (section) {
+        unsigned effCol = colToEffCol(cell->col());
+        RenderTableSection::CellStruct& belowCell = section->cellAt(rBelow, effCol);
+        return belowCell.primaryCell();
+    } else
+        return 0;
+}
+
+RenderTableCell* RenderTable::cellBefore(const RenderTableCell* cell) const
+{
+    recalcSectionsIfNeeded();
+
+    RenderTableSection* section = cell->section();
+    unsigned effCol = colToEffCol(cell->col());
+    if (!effCol)
+        return 0;
+    
+    // If we hit a colspan back up to a real cell.
+    RenderTableSection::CellStruct& prevCell = section->cellAt(cell->rowIndex(), effCol - 1);
+    return prevCell.primaryCell();
+}
+
+RenderTableCell* RenderTable::cellAfter(const RenderTableCell* cell) const
+{
+    recalcSectionsIfNeeded();
+
+    unsigned effCol = colToEffCol(cell->col() + cell->colSpan());
+    if (effCol >= numEffCols())
+        return 0;
+    return cell->section()->primaryCellAt(cell->rowIndex(), effCol);
+}
+
+RenderBlock* RenderTable::firstLineBlock() const
+{
+    return 0;
+}
+
+void RenderTable::updateFirstLetter()
+{
+}
+
+int RenderTable::baselinePosition(FontBaseline baselineType, bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const
+{
+    ASSERT(linePositionMode == PositionOnContainingLine);
+    LayoutUnit baseline = firstLineBoxBaseline();
+    if (baseline != -1)
+        return baseline;
+
+    return RenderBox::baselinePosition(baselineType, firstLine, direction, linePositionMode);
+}
+
+int RenderTable::inlineBlockBaseline(LineDirectionMode) const
+{
+    // Tables are skipped when computing an inline-block's baseline.
+    return -1;
+}
+
+int RenderTable::firstLineBoxBaseline() const
+{
+    // The baseline of a 'table' is the same as the 'inline-table' baseline per CSS 3 Flexbox (CSS 2.1
+    // doesn't define the baseline of a 'table' only an 'inline-table').
+    // This is also needed to properly determine the baseline of a cell if it has a table child.
+
+    if (isWritingModeRoot())
+        return -1;
+
+    recalcSectionsIfNeeded();
+
+    const RenderTableSection* topNonEmptySection = this->topNonEmptySection();
+    if (!topNonEmptySection)
+        return -1;
+
+    int baseline = topNonEmptySection->firstLineBoxBaseline();
+    if (baseline > 0)
+        return topNonEmptySection->logicalTop() + baseline;
+
+    // FIXME: A table row always has a baseline per CSS 2.1. Will this return the right value?
+    return -1;
+}
+
+LayoutRect RenderTable::overflowClipRect(const LayoutPoint& location, RenderRegion* region, OverlayScrollbarSizeRelevancy relevancy)
+{
+    LayoutRect rect = RenderBlock::overflowClipRect(location, region, relevancy);
+    
+    // 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_captions.isEmpty()) {
+        if (style()->isHorizontalWritingMode()) {
+            rect.setHeight(height());
+            rect.setY(location.y());
+        } else {
+            rect.setWidth(width());
+            rect.setX(location.x());
+        }
+    }
+
+    return rect;
+}
+
+bool RenderTable::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action)
+{
+    LayoutPoint adjustedLocation = accumulatedOffset + location();
+
+    // Check kids first.
+    if (!hasOverflowClip() || locationInContainer.intersects(overflowClipRect(adjustedLocation, locationInContainer.region()))) {
+        for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
+            if (child->isBox() && !toRenderBox(child)->hasSelfPaintingLayer() && (child->isTableSection() || child->isTableCaption())) {
+                LayoutPoint childPoint = flipForWritingModeForChild(toRenderBox(child), adjustedLocation);
+                if (child->nodeAtPoint(request, result, locationInContainer, childPoint, action)) {
+                    updateHitTestResult(result, toLayoutPoint(locationInContainer.point() - childPoint));
+                    return true;
+                }
+            }
+        }
+    }
+
+    // Check our bounds next.
+    LayoutRect boundsRect(adjustedLocation, size());
+    if (visibleToHitTestRequest(request) && (action == HitTestBlockBackground || action == HitTestChildBlockBackground) && locationInContainer.intersects(boundsRect)) {
+        updateHitTestResult(result, flipForWritingMode(locationInContainer.point() - toLayoutSize(adjustedLocation)));
+        if (!result.addNodeToRectBasedTestResult(node(), request, locationInContainer, boundsRect))
+            return true;
+    }
+
+    return false;
+}
+
+RenderTable* RenderTable::createAnonymousWithParentRenderer(const RenderObject* parent)
+{
+    RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(parent->style(), TABLE);
+    RenderTable* newTable = new (parent->renderArena()) RenderTable(0);
+    newTable->setDocumentForAnonymous(parent->document());
+    newTable->setStyle(newStyle.release());
+    return newTable;
+}
+
+const BorderValue& RenderTable::tableStartBorderAdjoiningCell(const RenderTableCell* cell) const
+{
+    ASSERT(cell->isFirstOrLastCellInRow());
+    if (hasSameDirectionAs(cell->row()))
+        return style()->borderStart();
+
+    return style()->borderEnd();
+}
+
+const BorderValue& RenderTable::tableEndBorderAdjoiningCell(const RenderTableCell* cell) const
+{
+    ASSERT(cell->isFirstOrLastCellInRow());
+    if (hasSameDirectionAs(cell->row()))
+        return style()->borderEnd();
+
+    return style()->borderStart();
+}
+
+}
diff --git a/Source/core/rendering/RenderTable.h b/Source/core/rendering/RenderTable.h
new file mode 100644
index 0000000..6f4e72a
--- /dev/null
+++ b/Source/core/rendering/RenderTable.h
@@ -0,0 +1,368 @@
+/*
+ * Copyright (C) 1997 Martin Jones (mjones@kde.org)
+ *           (C) 1997 Torben Weis (weis@kde.org)
+ *           (C) 1998 Waldo Bastian (bastian@kde.org)
+ *           (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2009, 2010 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 RenderTable_h
+#define RenderTable_h
+
+#include "CSSPropertyNames.h"
+#include "core/rendering/RenderBlock.h"
+#include "core/rendering/style/CollapsedBorderValue.h"
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class RenderTableCol;
+class RenderTableCaption;
+class RenderTableCell;
+class RenderTableSection;
+class TableLayout;
+
+enum SkipEmptySectionsValue { DoNotSkipEmptySections, SkipEmptySections };
+
+class RenderTable FINAL : public RenderBlock {
+public:
+    explicit RenderTable(Element*);
+    virtual ~RenderTable();
+
+    // Per CSS 3 writing-mode: "The first and second values of the 'border-spacing' property represent spacing between columns
+    // and rows respectively, not necessarily the horizontal and vertical spacing respectively".
+    int hBorderSpacing() const { return m_hSpacing; }
+    int vBorderSpacing() const { return m_vSpacing; }
+    
+    bool collapseBorders() const { return style()->borderCollapse(); }
+
+    int borderStart() const { return m_borderStart; }
+    int borderEnd() const { return m_borderEnd; }
+    int borderBefore() const;
+    int borderAfter() const;
+
+    int borderLeft() const
+    {
+        if (style()->isHorizontalWritingMode())
+            return style()->isLeftToRightDirection() ? borderStart() : borderEnd();
+        return style()->isFlippedBlocksWritingMode() ? borderAfter() : borderBefore();
+    }
+
+    int borderRight() const
+    {
+        if (style()->isHorizontalWritingMode())
+            return style()->isLeftToRightDirection() ? borderEnd() : borderStart();
+        return style()->isFlippedBlocksWritingMode() ? borderBefore() : borderAfter();
+    }
+
+    int borderTop() const
+    {
+        if (style()->isHorizontalWritingMode())
+            return style()->isFlippedBlocksWritingMode() ? borderAfter() : borderBefore();
+        return style()->isLeftToRightDirection() ? borderStart() : borderEnd();
+    }
+
+    int borderBottom() const
+    {
+        if (style()->isHorizontalWritingMode())
+            return style()->isFlippedBlocksWritingMode() ? borderBefore() : borderAfter();
+        return style()->isLeftToRightDirection() ? borderEnd() : borderStart();
+    }
+
+    Color bgColor() const { return style()->visitedDependentColor(CSSPropertyBackgroundColor); }
+
+    int outerBorderBefore() const;
+    int outerBorderAfter() const;
+    int outerBorderStart() const;
+    int outerBorderEnd() const;
+
+    int outerBorderLeft() const
+    {
+        if (style()->isHorizontalWritingMode())
+            return style()->isLeftToRightDirection() ? outerBorderStart() : outerBorderEnd();
+        return style()->isFlippedBlocksWritingMode() ? outerBorderAfter() : outerBorderBefore();
+    }
+
+    int outerBorderRight() const
+    {
+        if (style()->isHorizontalWritingMode())
+            return style()->isLeftToRightDirection() ? outerBorderEnd() : outerBorderStart();
+        return style()->isFlippedBlocksWritingMode() ? outerBorderBefore() : outerBorderAfter();
+    }
+
+    int outerBorderTop() const
+    {
+        if (style()->isHorizontalWritingMode())
+            return style()->isFlippedBlocksWritingMode() ? outerBorderAfter() : outerBorderBefore();
+        return style()->isLeftToRightDirection() ? outerBorderStart() : outerBorderEnd();
+    }
+
+    int outerBorderBottom() const
+    {
+        if (style()->isHorizontalWritingMode())
+            return style()->isFlippedBlocksWritingMode() ? outerBorderBefore() : outerBorderAfter();
+        return style()->isLeftToRightDirection() ? outerBorderEnd() : outerBorderStart();
+    }
+
+    int calcBorderStart() const;
+    int calcBorderEnd() const;
+    void recalcBordersInRowDirection();
+
+    virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0);
+
+    struct ColumnStruct {
+        explicit ColumnStruct(unsigned initialSpan = 1)
+            : span(initialSpan)
+        {
+        }
+
+        unsigned span;
+    };
+
+    void forceSectionsRecalc()
+    {
+        setNeedsSectionRecalc();
+        recalcSections();
+    }
+
+    const Vector<ColumnStruct>& columns() const { return m_columns; }
+    const Vector<int>& columnPositions() const { return m_columnPos; }
+    void setColumnPosition(unsigned index, int position)
+    {
+        // Note that if our horizontal border-spacing changed, our position will change but not
+        // our column's width. In practice, horizontal border-spacing won't change often.
+        m_columnLogicalWidthChanged |= m_columnPos[index] != position;
+        m_columnPos[index] = position;
+    }
+
+    RenderTableSection* header() const { return m_head; }
+    RenderTableSection* footer() const { return m_foot; }
+    RenderTableSection* firstBody() const { return m_firstBody; }
+
+    // This function returns 0 if the table has no section.
+    RenderTableSection* topSection() const;
+    RenderTableSection* bottomSection() const;
+
+    // This function returns 0 if the table has no non-empty sections.
+    RenderTableSection* topNonEmptySection() const;
+
+    unsigned lastColumnIndex() const { return numEffCols() - 1; }
+
+    void splitColumn(unsigned position, unsigned firstSpan);
+    void appendColumn(unsigned span);
+    unsigned numEffCols() const { return m_columns.size(); }
+    unsigned spanOfEffCol(unsigned effCol) const { return m_columns[effCol].span; }
+    
+    unsigned colToEffCol(unsigned column) const
+    {
+        unsigned effColumn = 0;
+        unsigned numColumns = numEffCols();
+        for (unsigned c = 0; effColumn < numColumns && c + m_columns[effColumn].span - 1 < column; ++effColumn)
+            c += m_columns[effColumn].span;
+        return effColumn;
+    }
+    
+    unsigned effColToCol(unsigned effCol) const
+    {
+        unsigned c = 0;
+        for (unsigned i = 0; i < effCol; i++)
+            c += m_columns[i].span;
+        return c;
+    }
+
+    LayoutUnit borderSpacingInRowDirection() const
+    {
+        if (unsigned effectiveColumnCount = numEffCols())
+            return static_cast<LayoutUnit>(effectiveColumnCount + 1) * hBorderSpacing();
+
+        return 0;
+    }
+
+    // Override paddingStart/End to return pixel values to match behavor of RenderTableCell.
+    virtual LayoutUnit paddingEnd() const OVERRIDE { return static_cast<int>(RenderBlock::paddingEnd()); }
+    virtual LayoutUnit paddingStart() const OVERRIDE { return static_cast<int>(RenderBlock::paddingStart()); }
+
+    LayoutUnit bordersPaddingAndSpacingInRowDirection() const
+    {
+        // 'border-spacing' only applies to separate borders (see 17.6.1 The separated borders model).
+        return borderStart() + borderEnd() + (collapseBorders() ? LayoutUnit() : (paddingStart() + paddingEnd() + borderSpacingInRowDirection()));
+    }
+
+    // Return the first column or column-group.
+    RenderTableCol* firstColumn() const;
+
+    RenderTableCol* colElement(unsigned col, bool* startEdge = 0, bool* endEdge = 0) const
+    {
+        // The common case is to not have columns, make that case fast.
+        if (!m_hasColElements)
+            return 0;
+        return slowColElement(col, startEdge, endEdge);
+    }
+
+    bool needsSectionRecalc() const { return m_needsSectionRecalc; }
+    void setNeedsSectionRecalc()
+    {
+        if (documentBeingDestroyed())
+            return;
+        m_needsSectionRecalc = true;
+        setNeedsLayout(true);
+    }
+
+    RenderTableSection* sectionAbove(const RenderTableSection*, SkipEmptySectionsValue = DoNotSkipEmptySections) const;
+    RenderTableSection* sectionBelow(const RenderTableSection*, SkipEmptySectionsValue = DoNotSkipEmptySections) const;
+
+    RenderTableCell* cellAbove(const RenderTableCell*) const;
+    RenderTableCell* cellBelow(const RenderTableCell*) const;
+    RenderTableCell* cellBefore(const RenderTableCell*) const;
+    RenderTableCell* cellAfter(const RenderTableCell*) const;
+ 
+    typedef Vector<CollapsedBorderValue> CollapsedBorderValues;
+    void invalidateCollapsedBorders()
+    {
+        m_collapsedBordersValid = false;
+        m_collapsedBorders.clear();
+    }
+    const CollapsedBorderValue* currentBorderValue() const { return m_currentBorder; }
+    
+    bool hasSections() const { return m_head || m_foot || m_firstBody; }
+
+    void recalcSectionsIfNeeded() const
+    {
+        if (m_needsSectionRecalc)
+            recalcSections();
+    }
+
+    static RenderTable* createAnonymousWithParentRenderer(const RenderObject*);
+    virtual RenderBox* createAnonymousBoxWithSameTypeAs(const RenderObject* parent) const OVERRIDE
+    {
+        return createAnonymousWithParentRenderer(parent);
+    }
+
+    const BorderValue& tableStartBorderAdjoiningCell(const RenderTableCell*) const;
+    const BorderValue& tableEndBorderAdjoiningCell(const RenderTableCell*) const;
+
+    void addCaption(const RenderTableCaption*);
+    void removeCaption(const RenderTableCaption*);
+    void addColumn(const RenderTableCol*);
+    void removeColumn(const RenderTableCol*);
+
+protected:
+    virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+    virtual void simplifiedNormalFlowLayout();
+
+private:
+    virtual const char* renderName() const { return "RenderTable"; }
+
+    virtual bool isTable() const { return true; }
+
+    virtual bool avoidsFloats() const { return true; }
+
+    virtual void paint(PaintInfo&, const LayoutPoint&);
+    virtual void paintObject(PaintInfo&, const LayoutPoint&);
+    virtual void paintBoxDecorations(PaintInfo&, const LayoutPoint&);
+    virtual void paintMask(PaintInfo&, const LayoutPoint&);
+    virtual void layout();
+    virtual void computeIntrinsicLogicalWidths(LayoutUnit& minWidth, LayoutUnit& maxWidth) const OVERRIDE;
+    virtual void computePreferredLogicalWidths() OVERRIDE;
+    virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
+
+    virtual int baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const OVERRIDE;
+    virtual int firstLineBoxBaseline() const OVERRIDE;
+    virtual int inlineBlockBaseline(LineDirectionMode) const OVERRIDE;
+
+    RenderTableCol* slowColElement(unsigned col, bool* startEdge, bool* endEdge) const;
+
+    void updateColumnCache() const;
+    void invalidateCachedColumns();
+
+    virtual RenderBlock* firstLineBlock() const;
+    virtual void updateFirstLetter();
+    
+    virtual void updateLogicalWidth() OVERRIDE;
+
+    LayoutUnit convertStyleLogicalWidthToComputedWidth(const Length& styleLogicalWidth, LayoutUnit availableWidth);
+    LayoutUnit convertStyleLogicalHeightToComputedHeight(const Length& styleLogicalHeight);
+
+    virtual LayoutRect overflowClipRect(const LayoutPoint& location, RenderRegion*, OverlayScrollbarSizeRelevancy = IgnoreOverlayScrollbarSize);
+
+    virtual void addOverflowFromChildren();
+
+    void subtractCaptionRect(LayoutRect&) const;
+
+    void recalcCollapsedBorders();
+    void recalcSections() const;
+    void layoutCaption(RenderTableCaption*);
+
+    void distributeExtraLogicalHeight(int extraLogicalHeight);
+
+    mutable Vector<int> m_columnPos;
+    mutable Vector<ColumnStruct> m_columns;
+    mutable Vector<RenderTableCaption*> m_captions;
+    mutable Vector<RenderTableCol*> m_columnRenderers;
+
+    mutable RenderTableSection* m_head;
+    mutable RenderTableSection* m_foot;
+    mutable RenderTableSection* m_firstBody;
+
+    OwnPtr<TableLayout> m_tableLayout;
+
+    CollapsedBorderValues m_collapsedBorders;
+    const CollapsedBorderValue* m_currentBorder;
+    bool m_collapsedBordersValid : 1;
+
+    mutable bool m_hasColElements : 1;
+    mutable bool m_needsSectionRecalc : 1;
+
+    bool m_columnLogicalWidthChanged : 1;
+    mutable bool m_columnRenderersValid: 1;
+
+    short m_hSpacing;
+    short m_vSpacing;
+    int m_borderStart;
+    int m_borderEnd;
+};
+
+inline RenderTableSection* RenderTable::topSection() const
+{
+    ASSERT(!needsSectionRecalc());
+    if (m_head)
+        return m_head;
+    if (m_firstBody)
+        return m_firstBody;
+    return m_foot;
+}
+
+inline RenderTable* toRenderTable(RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isTable());
+    return static_cast<RenderTable*>(object);
+}
+
+inline const RenderTable* toRenderTable(const RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isTable());
+    return static_cast<const RenderTable*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderTable(const RenderTable*);
+
+} // namespace WebCore
+
+#endif // RenderTable_h
diff --git a/Source/core/rendering/RenderTableCaption.cpp b/Source/core/rendering/RenderTableCaption.cpp
new file mode 100644
index 0000000..171ebb2
--- /dev/null
+++ b/Source/core/rendering/RenderTableCaption.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2011 Robert Hogan <robert@roberthogan.net>
+ *
+ * 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 "core/rendering/RenderTableCaption.h"
+
+#include "core/rendering/RenderTable.h"
+
+namespace WebCore {
+
+RenderTableCaption::RenderTableCaption(Element* element)
+    : RenderBlock(element)
+{
+}
+
+RenderTableCaption::~RenderTableCaption()
+{
+}
+
+LayoutUnit RenderTableCaption::containingBlockLogicalWidthForContent() const
+{
+    RenderBlock* cb = containingBlock();
+    return cb->logicalWidth();
+}
+
+void RenderTableCaption::insertedIntoTree()
+{
+    RenderBlock::insertedIntoTree();
+
+    table()->addCaption(this);
+}
+
+void RenderTableCaption::willBeRemovedFromTree()
+{
+    RenderBlock::willBeRemovedFromTree();
+
+    table()->removeCaption(this);
+}
+
+RenderTable* RenderTableCaption::table() const
+{
+    return toRenderTable(parent());
+}
+
+}
diff --git a/Source/core/rendering/RenderTableCaption.h b/Source/core/rendering/RenderTableCaption.h
new file mode 100644
index 0000000..6213053
--- /dev/null
+++ b/Source/core/rendering/RenderTableCaption.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2011 Robert Hogan <robert@roberthogan.net>
+ *
+ * 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 RenderTableCaption_h
+#define RenderTableCaption_h
+
+#include "core/rendering/RenderBlock.h"
+
+namespace WebCore {
+
+class RenderTable;
+
+class RenderTableCaption FINAL : public RenderBlock {
+public:
+    explicit RenderTableCaption(Element*);
+    virtual ~RenderTableCaption();
+    virtual LayoutUnit containingBlockLogicalWidthForContent() const OVERRIDE;
+    
+private:
+    virtual bool isTableCaption() const OVERRIDE { return true; }
+
+    virtual void insertedIntoTree() OVERRIDE;
+    virtual void willBeRemovedFromTree() OVERRIDE;
+
+    RenderTable* table() const;
+};
+
+inline RenderTableCaption* toRenderTableCaption(RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isTableCaption());
+    return static_cast<RenderTableCaption*>(object);
+}
+
+inline const RenderTableCaption* toRenderTableCaption(const RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isTableCaption());
+    return static_cast<const RenderTableCaption*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderTableCaption(const RenderTableCaption*);
+
+} // namespace WebCore
+
+#endif // RenderTableCaption_h
diff --git a/Source/core/rendering/RenderTableCell.cpp b/Source/core/rendering/RenderTableCell.cpp
new file mode 100644
index 0000000..403a042
--- /dev/null
+++ b/Source/core/rendering/RenderTableCell.cpp
@@ -0,0 +1,1261 @@
+/*
+ * Copyright (C) 1997 Martin Jones (mjones@kde.org)
+ *           (C) 1997 Torben Weis (weis@kde.org)
+ *           (C) 1998 Waldo Bastian (bastian@kde.org)
+ *           (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009 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 "core/rendering/RenderTableCell.h"
+
+#include "HTMLNames.h"
+#include "core/css/StylePropertySet.h"
+#include "core/html/HTMLTableCellElement.h"
+#include "core/platform/graphics/FloatQuad.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/platform/graphics/transforms/TransformState.h"
+#include "core/rendering/PaintInfo.h"
+#include "core/rendering/RenderTableCol.h"
+#include "core/rendering/RenderView.h"
+#include "core/rendering/style/CollapsedBorderValue.h"
+
+using namespace std;
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+struct SameSizeAsRenderTableCell : public RenderBlock {
+    unsigned bitfields;
+    int paddings[2];
+};
+
+COMPILE_ASSERT(sizeof(RenderTableCell) == sizeof(SameSizeAsRenderTableCell), RenderTableCell_should_stay_small);
+COMPILE_ASSERT(sizeof(CollapsedBorderValue) == 8, CollapsedBorderValue_should_stay_small);
+
+RenderTableCell::RenderTableCell(Element* element)
+    : RenderBlock(element)
+    , m_column(unsetColumnIndex)
+    , m_cellWidthChanged(false)
+    , m_intrinsicPaddingBefore(0)
+    , m_intrinsicPaddingAfter(0)
+{
+    // We only update the flags when notified of DOM changes in colSpanOrRowSpanChanged()
+    // so we need to set their initial values here in case something asks for colSpan()/rowSpan() before then.
+    updateColAndRowSpanFlags();
+}
+
+void RenderTableCell::willBeRemovedFromTree()
+{
+    RenderBlock::willBeRemovedFromTree();
+
+    section()->setNeedsCellRecalc();
+    section()->removeCachedCollapsedBorders(this);
+}
+
+unsigned RenderTableCell::parseColSpanFromDOM() const
+{
+    ASSERT(node());
+    if (node()->hasTagName(tdTag) || node()->hasTagName(thTag))
+        return min<unsigned>(toHTMLTableCellElement(node())->colSpan(), maxColumnIndex);
+    return 1;
+}
+
+unsigned RenderTableCell::parseRowSpanFromDOM() const
+{
+    ASSERT(node());
+    if (node()->hasTagName(tdTag) || node()->hasTagName(thTag))
+        return min<unsigned>(toHTMLTableCellElement(node())->rowSpan(), maxRowIndex);
+    return 1;
+}
+
+void RenderTableCell::updateColAndRowSpanFlags()
+{
+    // The vast majority of table cells do not have a colspan or rowspan,
+    // so we keep a bool to know if we need to bother reading from the DOM.
+    m_hasColSpan = node() && parseColSpanFromDOM() != 1;
+    m_hasRowSpan = node() && parseRowSpanFromDOM() != 1;
+}
+
+void RenderTableCell::colSpanOrRowSpanChanged()
+{
+    ASSERT(node());
+    ASSERT(node()->hasTagName(tdTag) || node()->hasTagName(thTag));
+
+    updateColAndRowSpanFlags();
+
+    // FIXME: I suspect that we could return early here if !m_hasColSpan && !m_hasRowSpan.
+
+    setNeedsLayoutAndPrefWidthsRecalc();
+    if (parent() && section())
+        section()->setNeedsCellRecalc();
+}
+
+Length RenderTableCell::logicalWidthFromColumns(RenderTableCol* firstColForThisCell, Length widthFromStyle) const
+{
+    ASSERT(firstColForThisCell && firstColForThisCell == table()->colElement(col()));
+    RenderTableCol* tableCol = firstColForThisCell;
+
+    unsigned colSpanCount = colSpan();
+    int colWidthSum = 0;
+    for (unsigned i = 1; i <= colSpanCount; i++) {
+        Length colWidth = tableCol->style()->logicalWidth();
+
+        // Percentage value should be returned only for colSpan == 1.
+        // Otherwise we return original width for the cell.
+        if (!colWidth.isFixed()) {
+            if (colSpanCount > 1)
+                return widthFromStyle;
+            return colWidth;
+        }
+
+        colWidthSum += colWidth.value();
+        tableCol = tableCol->nextColumn();
+        // If no next <col> tag found for the span we just return what we have for now.
+        if (!tableCol)
+            break;
+    }
+
+    // Column widths specified on <col> apply to the border box of the cell, see bug 8126.
+    // FIXME: Why is border/padding ignored in the negative width case?
+    if (colWidthSum > 0)
+        return Length(max(0, colWidthSum - borderAndPaddingLogicalWidth().ceil()), Fixed);
+    return Length(colWidthSum, Fixed);
+}
+
+void RenderTableCell::computePreferredLogicalWidths()
+{
+    // The child cells rely on the grids up in the sections to do their computePreferredLogicalWidths 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::computePreferredLogicalWidths();
+    if (node() && style()->autoWrap()) {
+        // See if nowrap was set.
+        Length w = styleOrColLogicalWidth();
+        String nowrap = toElement(node())->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_minPreferredLogicalWidth = max<LayoutUnit>(w.value(), m_minPreferredLogicalWidth);
+    }
+}
+
+void RenderTableCell::computeIntrinsicPadding(int rowHeight)
+{
+    int oldIntrinsicPaddingBefore = intrinsicPaddingBefore();
+    int oldIntrinsicPaddingAfter = intrinsicPaddingAfter();
+    int logicalHeightWithoutIntrinsicPadding = pixelSnappedLogicalHeight() - oldIntrinsicPaddingBefore - oldIntrinsicPaddingAfter;
+
+    int intrinsicPaddingBefore = 0;
+    switch (style()->verticalAlign()) {
+    case SUB:
+    case SUPER:
+    case TEXT_TOP:
+    case TEXT_BOTTOM:
+    case LENGTH:
+    case BASELINE: {
+        LayoutUnit baseline = cellBaselinePosition();
+        if (baseline > borderBefore() + paddingBefore())
+            intrinsicPaddingBefore = section()->rowBaseline(rowIndex()) - (baseline - oldIntrinsicPaddingBefore);
+        break;
+    }
+    case TOP:
+        break;
+    case MIDDLE:
+        intrinsicPaddingBefore = (rowHeight - logicalHeightWithoutIntrinsicPadding) / 2;
+        break;
+    case BOTTOM:
+        intrinsicPaddingBefore = rowHeight - logicalHeightWithoutIntrinsicPadding;
+        break;
+    case BASELINE_MIDDLE:
+        break;
+    }
+
+    int intrinsicPaddingAfter = rowHeight - logicalHeightWithoutIntrinsicPadding - intrinsicPaddingBefore;
+    setIntrinsicPaddingBefore(intrinsicPaddingBefore);
+    setIntrinsicPaddingAfter(intrinsicPaddingAfter);
+
+    // FIXME: Changing an intrinsic padding shouldn't trigger a relayout as it only shifts the cell inside the row but
+    // doesn't change the logical height.
+    if (intrinsicPaddingBefore != oldIntrinsicPaddingBefore || intrinsicPaddingAfter != oldIntrinsicPaddingAfter)
+        setNeedsLayout(true, MarkOnlyThis);
+}
+
+void RenderTableCell::updateLogicalWidth()
+{
+}
+
+void RenderTableCell::setCellLogicalWidth(int tableLayoutLogicalWidth)
+{
+    if (tableLayoutLogicalWidth == logicalWidth())
+        return;
+
+    setNeedsLayout(true, MarkOnlyThis);
+    row()->setChildNeedsLayout(true, MarkOnlyThis);
+
+    if (!table()->selfNeedsLayout() && checkForRepaintDuringLayout())
+        repaint();
+
+    setLogicalWidth(tableLayoutLogicalWidth);
+    setCellWidthChanged(true);
+}
+
+void RenderTableCell::layout()
+{
+    StackStats::LayoutCheckPoint layoutCheckPoint;
+    updateFirstLetter();
+
+    int oldCellBaseline = cellBaselinePosition();
+    layoutBlock(cellWidthChanged());
+
+    // If we have replaced content, the intrinsic height of our content may have changed since the last time we laid out. If that's the case the intrinsic padding we used
+    // for layout (the padding required to push the contents of the cell down to the row's baseline) is included in our new height and baseline and makes both
+    // of them wrong. So if our content's intrinsic height has changed push the new content up into the intrinsic padding and relayout so that the rest of
+    // table and row layout can use the correct baseline and height for this cell.
+    if (isBaselineAligned() && section()->rowBaseline(rowIndex()) && cellBaselinePosition() > section()->rowBaseline(rowIndex())) {
+        int newIntrinsicPaddingBefore = max<LayoutUnit>(0, intrinsicPaddingBefore() - max<LayoutUnit>(0, cellBaselinePosition() - oldCellBaseline));
+        setIntrinsicPaddingBefore(newIntrinsicPaddingBefore);
+        setNeedsLayout(true, MarkOnlyThis);
+        layoutBlock(cellWidthChanged());
+    }
+
+    setCellWidthChanged(false);
+}
+
+LayoutUnit RenderTableCell::paddingTop() const
+{
+    int result = computedCSSPaddingTop();
+    if (!isHorizontalWritingMode())
+        return result;
+    return result + (style()->writingMode() == TopToBottomWritingMode ? intrinsicPaddingBefore() : intrinsicPaddingAfter());
+}
+
+LayoutUnit RenderTableCell::paddingBottom() const
+{
+    int result = computedCSSPaddingBottom();
+    if (!isHorizontalWritingMode())
+        return result;
+    return result + (style()->writingMode() == TopToBottomWritingMode ? intrinsicPaddingAfter() : intrinsicPaddingBefore());
+}
+
+LayoutUnit RenderTableCell::paddingLeft() const
+{
+    int result = computedCSSPaddingLeft();
+    if (isHorizontalWritingMode())
+        return result;
+    return result + (style()->writingMode() == LeftToRightWritingMode ? intrinsicPaddingBefore() : intrinsicPaddingAfter());
+}
+
+LayoutUnit RenderTableCell::paddingRight() const
+{   
+    int result = computedCSSPaddingRight();
+    if (isHorizontalWritingMode())
+        return result;
+    return result + (style()->writingMode() == LeftToRightWritingMode ? intrinsicPaddingAfter() : intrinsicPaddingBefore());
+}
+
+LayoutUnit RenderTableCell::paddingBefore() const
+{
+    return static_cast<int>(computedCSSPaddingBefore()) + intrinsicPaddingBefore();
+}
+
+LayoutUnit RenderTableCell::paddingAfter() const
+{
+    return static_cast<int>(computedCSSPaddingAfter()) + intrinsicPaddingAfter();
+}
+
+void RenderTableCell::setOverrideLogicalContentHeightFromRowHeight(LayoutUnit rowHeight)
+{
+    clearIntrinsicPadding();
+    setOverrideLogicalContentHeight(max<LayoutUnit>(0, rowHeight - borderAndPaddingLogicalHeight()));
+}
+
+LayoutSize RenderTableCell::offsetFromContainer(RenderObject* o, const LayoutPoint& point, bool* offsetDependsOnPoint) const
+{
+    ASSERT(o == container());
+
+    LayoutSize offset = RenderBlock::offsetFromContainer(o, point, offsetDependsOnPoint);
+    if (parent())
+        offset -= parentBox()->locationOffset();
+
+    return offset;
+}
+
+LayoutRect RenderTableCell::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const
+{
+    // 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::clippedOverflowRectForRepaint(repaintContainer);
+
+    bool rtl = !styleForCellFlow()->isLeftToRightDirection();
+    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));
+        }
+    }
+    LayoutPoint location(max<LayoutUnit>(left, -visualOverflowRect().x()), max<LayoutUnit>(top, -visualOverflowRect().y()));
+    LayoutRect r(-location.x(), -location.y(), location.x() + max(width() + right, visualOverflowRect().maxX()), location.y() + max(height() + bottom, visualOverflowRect().maxY()));
+
+    if (RenderView* v = view()) {
+        // FIXME: layoutDelta needs to be applied in parts before/after transforms and
+        // repaint containers. https://bugs.webkit.org/show_bug.cgi?id=23308
+        r.move(v->layoutDelta());
+    }
+    computeRectForRepaint(repaintContainer, r);
+    return r;
+}
+
+void RenderTableCell::computeRectForRepaint(const RenderLayerModelObject* repaintContainer, LayoutRect& r, bool fixed) const
+{
+    if (repaintContainer == this)
+        return;
+    r.setY(r.y());
+    RenderView* v = view();
+    if ((!v || !v->layoutStateEnabled() || repaintContainer) && parent())
+        r.moveBy(-parentBox()->location()); // Rows are in the same coordinate space, so don't add their offset in.
+    RenderBlock::computeRectForRepaint(repaintContainer, r, fixed);
+}
+
+LayoutUnit RenderTableCell::cellBaselinePosition() 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.
+    LayoutUnit firstLineBaseline = firstLineBoxBaseline();
+    if (firstLineBaseline != -1)
+        return firstLineBaseline;
+    return paddingBefore() + borderBefore() + contentLogicalHeight();
+}
+
+void RenderTableCell::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
+{
+    ASSERT(style()->display() == TABLE_CELL);
+    ASSERT(!row() || row()->rowIndexWasSet());
+
+    RenderBlock::styleDidChange(diff, oldStyle);
+    setHasBoxDecorations(true);
+
+    if (parent() && section() && oldStyle && style()->height() != oldStyle->height())
+        section()->rowLogicalHeightChanged(rowIndex());
+
+    // If border was changed, notify table.
+    if (parent()) {
+        RenderTable* table = this->table();
+        if (table && !table->selfNeedsLayout() && !table->normalChildNeedsLayout()&& oldStyle && oldStyle->border() != style()->border())
+            table->invalidateCollapsedBorders();
+    }
+}
+
+// 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 int compareBorders(const CollapsedBorderValue& border1, const CollapsedBorderValue& border2)
+{
+    // Sanity check the values passed in. The null border have lowest priority.
+    if (!border2.exists()) {
+        if (!border1.exists())
+            return 0;
+        return 1;
+    }
+    if (!border1.exists())
+        return -1;
+
+    // Rule #1 above.
+    if (border2.style() == BHIDDEN) {
+        if (border1.style() == BHIDDEN)
+            return 0;
+        return -1;
+    }
+    if (border1.style() == BHIDDEN)
+        return 1;
+    
+    // Rule #2 above.  A style of 'none' has lowest priority and always loses to any other border.
+    if (border2.style() == BNONE) {
+        if (border1.style() == BNONE)
+            return 0;
+        return 1;
+    }
+    if (border1.style() == BNONE)
+        return -1;
+
+    // The first part of rule #3 above. Wider borders win.
+    if (border1.width() != border2.width())
+        return border1.width() < border2.width() ? -1 : 1;
+    
+    // The borders have equal width.  Sort by border style.
+    if (border1.style() != border2.style())
+        return border1.style() < border2.style() ? -1 : 1;
+    
+    // The border have the same width and style.  Rely on precedence (cell over row over row group, etc.)
+    if (border1.precedence() == border2.precedence())
+        return 0;
+    return border1.precedence() < border2.precedence() ? -1 : 1;
+}
+
+static CollapsedBorderValue chooseBorder(const CollapsedBorderValue& border1, const CollapsedBorderValue& border2)
+{
+    const CollapsedBorderValue& border = compareBorders(border1, border2) < 0 ? border2 : border1;
+    return border.style() == BHIDDEN ? CollapsedBorderValue() : border;
+}
+
+bool RenderTableCell::hasStartBorderAdjoiningTable() const
+{
+    bool isStartColumn = !col();
+    bool isEndColumn = table()->colToEffCol(col() + colSpan() - 1) == table()->numEffCols() - 1;
+    bool hasSameDirectionAsTable = hasSameDirectionAs(table());
+
+    // The table direction determines the row direction. In mixed directionality, we cannot guarantee that
+    // we have a common border with the table (think a ltr table with rtl start cell).
+    return (isStartColumn && hasSameDirectionAsTable) || (isEndColumn && !hasSameDirectionAsTable);
+}
+
+bool RenderTableCell::hasEndBorderAdjoiningTable() const
+{
+    bool isStartColumn = !col();
+    bool isEndColumn = table()->colToEffCol(col() + colSpan() - 1) == table()->numEffCols() - 1;
+    bool hasSameDirectionAsTable = hasSameDirectionAs(table());
+
+    // The table direction determines the row direction. In mixed directionality, we cannot guarantee that
+    // we have a common border with the table (think a ltr table with ltr end cell).
+    return (isStartColumn && !hasSameDirectionAsTable) || (isEndColumn && hasSameDirectionAsTable);
+}
+
+CollapsedBorderValue RenderTableCell::collapsedStartBorder(IncludeBorderColorOrNot includeColor) const
+{
+    CollapsedBorderValue result = computeCollapsedStartBorder(includeColor);
+    if (includeColor)
+        section()->setCachedCollapsedBorder(this, CBSStart, result);
+    return result;
+}
+
+CollapsedBorderValue RenderTableCell::computeCollapsedStartBorder(IncludeBorderColorOrNot includeColor) const
+{
+    RenderTable* table = this->table();
+
+    // For the start border, we need to check, in order of precedence:
+    // (1) Our start border.
+    int startColorProperty = includeColor ? CSSProperty::resolveDirectionAwareProperty(CSSPropertyWebkitBorderStartColor, styleForCellFlow()->direction(), styleForCellFlow()->writingMode()) : 0;
+    int endColorProperty = includeColor ? CSSProperty::resolveDirectionAwareProperty(CSSPropertyWebkitBorderEndColor, styleForCellFlow()->direction(), styleForCellFlow()->writingMode()) : 0;
+    CollapsedBorderValue result(style()->borderStart(), includeColor ? style()->visitedDependentColor(startColorProperty) : Color(), BCELL);
+
+    // (2) The end border of the preceding cell.
+    RenderTableCell* cellBefore = table->cellBefore(this);
+    if (cellBefore) {
+        CollapsedBorderValue cellBeforeAdjoiningBorder = CollapsedBorderValue(cellBefore->borderAdjoiningCellAfter(this), includeColor ? cellBefore->style()->visitedDependentColor(endColorProperty) : Color(), BCELL);
+        // |result| should be the 2nd argument as |cellBefore| should win in case of equality per CSS 2.1 (Border conflict resolution, point 4).
+        result = chooseBorder(cellBeforeAdjoiningBorder, result);
+        if (!result.exists())
+            return result;
+    }
+
+    bool startBorderAdjoinsTable = hasStartBorderAdjoiningTable();
+    if (startBorderAdjoinsTable) {
+        // (3) Our row's start border.
+        result = chooseBorder(result, CollapsedBorderValue(row()->borderAdjoiningStartCell(this), includeColor ? parent()->style()->visitedDependentColor(startColorProperty) : Color(), BROW));
+        if (!result.exists())
+            return result;
+
+        // (4) Our row group's start border.
+        result = chooseBorder(result, CollapsedBorderValue(section()->borderAdjoiningStartCell(this), includeColor ? section()->style()->visitedDependentColor(startColorProperty) : Color(), BROWGROUP));
+        if (!result.exists())
+            return result;
+    }
+    
+    // (5) Our column and column group's start borders.
+    bool startColEdge;
+    bool endColEdge;
+    if (RenderTableCol* colElt = table->colElement(col(), &startColEdge, &endColEdge)) {
+        if (colElt->isTableColumnGroup() && startColEdge) {
+            // The |colElt| is a column group and is also the first colgroup (in case of spanned colgroups).
+            result = chooseBorder(result, CollapsedBorderValue(colElt->borderAdjoiningCellStartBorder(this), includeColor ? colElt->style()->visitedDependentColor(startColorProperty) : Color(), BCOLGROUP));
+            if (!result.exists())
+                return result;
+        } else if (!colElt->isTableColumnGroup()) {
+            // We first consider the |colElt| and irrespective of whether it is a spanned col or not, we apply
+            // its start border. This is as per HTML5 which states that: "For the purposes of the CSS table model,
+            // the col element is expected to be treated as if it was present as many times as its span attribute specifies".
+            result = chooseBorder(result, CollapsedBorderValue(colElt->borderAdjoiningCellStartBorder(this), includeColor ? colElt->style()->visitedDependentColor(startColorProperty) : Color(), BCOL));
+            if (!result.exists())
+                return result;
+            // Next, apply the start border of the enclosing colgroup but only if it is adjacent to the cell's edge.
+            if (RenderTableCol* enclosingColumnGroup = colElt->enclosingColumnGroupIfAdjacentBefore()) {
+                result = chooseBorder(result, CollapsedBorderValue(enclosingColumnGroup->borderAdjoiningCellStartBorder(this), includeColor ? enclosingColumnGroup->style()->visitedDependentColor(startColorProperty) : Color(), BCOLGROUP));
+                if (!result.exists())
+                    return result;
+            }
+        }
+    }
+    
+    // (6) The end border of the preceding column.
+    if (cellBefore) {
+        if (RenderTableCol* colElt = table->colElement(col() - 1, &startColEdge, &endColEdge)) {
+            if (colElt->isTableColumnGroup() && endColEdge) {
+                // The element is a colgroup and is also the last colgroup (in case of spanned colgroups).
+                result = chooseBorder(CollapsedBorderValue(colElt->borderAdjoiningCellAfter(this), includeColor ? colElt->style()->visitedDependentColor(endColorProperty) : Color(), BCOLGROUP), result);
+                if (!result.exists())
+                    return result;
+            } else if (colElt->isTableColumn()) {
+                // Resolve the collapsing border against the col's border ignoring any 'span' as per HTML5.
+                result = chooseBorder(CollapsedBorderValue(colElt->borderAdjoiningCellAfter(this), includeColor ? colElt->style()->visitedDependentColor(endColorProperty) : Color(), BCOL), result);
+                if (!result.exists())
+                    return result;
+                // Next, if the previous col has a parent colgroup then its end border should be applied
+                // but only if it is adjacent to the cell's edge.
+                if (RenderTableCol* enclosingColumnGroup = colElt->enclosingColumnGroupIfAdjacentAfter()) {
+                    result = chooseBorder(CollapsedBorderValue(enclosingColumnGroup->borderAdjoiningCellEndBorder(this), includeColor ? enclosingColumnGroup->style()->visitedDependentColor(endColorProperty) : Color(), BCOLGROUP), result);
+                    if (!result.exists())
+                        return result;
+                }
+            }
+        }
+    }
+
+    if (startBorderAdjoinsTable) {
+        // (7) The table's start border.
+        result = chooseBorder(result, CollapsedBorderValue(table->tableStartBorderAdjoiningCell(this), includeColor ? table->style()->visitedDependentColor(startColorProperty) : Color(), BTABLE));
+        if (!result.exists())
+            return result;
+    }
+    
+    return result;
+}
+
+CollapsedBorderValue RenderTableCell::collapsedEndBorder(IncludeBorderColorOrNot includeColor) const
+{
+    CollapsedBorderValue result = computeCollapsedEndBorder(includeColor);
+    if (includeColor)
+        section()->setCachedCollapsedBorder(this, CBSEnd, result);
+    return result;
+}
+
+CollapsedBorderValue RenderTableCell::computeCollapsedEndBorder(IncludeBorderColorOrNot includeColor) const
+{
+    RenderTable* table = this->table();
+    // Note: We have to use the effective column information instead of whether we have a cell after as a table doesn't
+    // have to be regular (any row can have less cells than the total cell count).
+    bool isEndColumn = table->colToEffCol(col() + colSpan() - 1) == table->numEffCols() - 1;
+
+    // For end border, we need to check, in order of precedence:
+    // (1) Our end border.
+    int startColorProperty = includeColor ? CSSProperty::resolveDirectionAwareProperty(CSSPropertyWebkitBorderStartColor, styleForCellFlow()->direction(), styleForCellFlow()->writingMode()) : 0;
+    int endColorProperty = includeColor ? CSSProperty::resolveDirectionAwareProperty(CSSPropertyWebkitBorderEndColor, styleForCellFlow()->direction(), styleForCellFlow()->writingMode()) : 0;
+    CollapsedBorderValue result = CollapsedBorderValue(style()->borderEnd(), includeColor ? style()->visitedDependentColor(endColorProperty) : Color(), BCELL);
+    
+    // (2) The start border of the following cell.
+    if (!isEndColumn) {
+        if (RenderTableCell* cellAfter = table->cellAfter(this)) {
+            CollapsedBorderValue cellAfterAdjoiningBorder = CollapsedBorderValue(cellAfter->borderAdjoiningCellBefore(this), includeColor ? cellAfter->style()->visitedDependentColor(startColorProperty) : Color(), BCELL);
+            result = chooseBorder(result, cellAfterAdjoiningBorder);
+            if (!result.exists())
+                return result;
+        }
+    }
+
+    bool endBorderAdjoinsTable = hasEndBorderAdjoiningTable();
+    if (endBorderAdjoinsTable) {
+        // (3) Our row's end border.
+        result = chooseBorder(result, CollapsedBorderValue(row()->borderAdjoiningEndCell(this), includeColor ? parent()->style()->visitedDependentColor(endColorProperty) : Color(), BROW));
+        if (!result.exists())
+            return result;
+        
+        // (4) Our row group's end border.
+        result = chooseBorder(result, CollapsedBorderValue(section()->borderAdjoiningEndCell(this), includeColor ? section()->style()->visitedDependentColor(endColorProperty) : Color(), BROWGROUP));
+        if (!result.exists())
+            return result;
+    }
+    
+    // (5) Our column and column group's end borders.
+    bool startColEdge;
+    bool endColEdge;
+    if (RenderTableCol* colElt = table->colElement(col() + colSpan() - 1, &startColEdge, &endColEdge)) {
+        if (colElt->isTableColumnGroup() && endColEdge) {
+            // The element is a colgroup and is also the last colgroup (in case of spanned colgroups).
+            result = chooseBorder(result, CollapsedBorderValue(colElt->borderAdjoiningCellEndBorder(this), includeColor ? colElt->style()->visitedDependentColor(endColorProperty) : Color(), BCOLGROUP));
+            if (!result.exists())
+                return result;
+        } else if (!colElt->isTableColumnGroup()) {
+            // First apply the end border of the column irrespective of whether it is spanned or not. This is as per
+            // HTML5 which states that: "For the purposes of the CSS table model, the col element is expected to be
+            // treated as if it was present as many times as its span attribute specifies".
+            result = chooseBorder(result, CollapsedBorderValue(colElt->borderAdjoiningCellEndBorder(this), includeColor ? colElt->style()->visitedDependentColor(endColorProperty) : Color(), BCOL));
+            if (!result.exists())
+                return result;
+            // Next, if it has a parent colgroup then we apply its end border but only if it is adjacent to the cell.
+            if (RenderTableCol* enclosingColumnGroup = colElt->enclosingColumnGroupIfAdjacentAfter()) {
+                result = chooseBorder(result, CollapsedBorderValue(enclosingColumnGroup->borderAdjoiningCellEndBorder(this), includeColor ? enclosingColumnGroup->style()->visitedDependentColor(endColorProperty) : Color(), BCOLGROUP));
+                if (!result.exists())
+                    return result;
+            }
+        }
+    }
+    
+    // (6) The start border of the next column.
+    if (!isEndColumn) {
+        if (RenderTableCol* colElt = table->colElement(col() + colSpan(), &startColEdge, &endColEdge)) {
+            if (colElt->isTableColumnGroup() && startColEdge) {
+                // This case is a colgroup without any col, we only compute it if it is adjacent to the cell's edge.
+                result = chooseBorder(result, CollapsedBorderValue(colElt->borderAdjoiningCellBefore(this), includeColor ? colElt->style()->visitedDependentColor(startColorProperty) : Color(), BCOLGROUP));
+                if (!result.exists())
+                    return result;
+            } else if (colElt->isTableColumn()) {
+                // Resolve the collapsing border against the col's border ignoring any 'span' as per HTML5.
+                result = chooseBorder(result, CollapsedBorderValue(colElt->borderAdjoiningCellBefore(this), includeColor ? colElt->style()->visitedDependentColor(startColorProperty) : Color(), BCOL));
+                if (!result.exists())
+                    return result;
+                // If we have a parent colgroup, resolve the border only if it is adjacent to the cell.
+                if (RenderTableCol* enclosingColumnGroup = colElt->enclosingColumnGroupIfAdjacentBefore()) {
+                    result = chooseBorder(result, CollapsedBorderValue(enclosingColumnGroup->borderAdjoiningCellStartBorder(this), includeColor ? enclosingColumnGroup->style()->visitedDependentColor(startColorProperty) : Color(), BCOLGROUP));
+                    if (!result.exists())
+                        return result;
+                }
+            }
+        }
+    }
+
+    if (endBorderAdjoinsTable) {
+        // (7) The table's end border.
+        result = chooseBorder(result, CollapsedBorderValue(table->tableEndBorderAdjoiningCell(this), includeColor ? table->style()->visitedDependentColor(endColorProperty) : Color(), BTABLE));
+        if (!result.exists())
+            return result;
+    }
+    
+    return result;
+}
+
+CollapsedBorderValue RenderTableCell::collapsedBeforeBorder(IncludeBorderColorOrNot includeColor) const
+{
+    CollapsedBorderValue result = computeCollapsedBeforeBorder(includeColor);
+    if (includeColor)
+        section()->setCachedCollapsedBorder(this, CBSBefore, result);
+    return result;
+}
+
+CollapsedBorderValue RenderTableCell::computeCollapsedBeforeBorder(IncludeBorderColorOrNot includeColor) const
+{
+    RenderTable* table = this->table();
+
+    // For before border, we need to check, in order of precedence:
+    // (1) Our before border.
+    int beforeColorProperty = includeColor ? CSSProperty::resolveDirectionAwareProperty(CSSPropertyWebkitBorderBeforeColor, styleForCellFlow()->direction(), styleForCellFlow()->writingMode()) : 0;
+    int afterColorProperty = includeColor ? CSSProperty::resolveDirectionAwareProperty(CSSPropertyWebkitBorderAfterColor, styleForCellFlow()->direction(), styleForCellFlow()->writingMode()) : 0;
+    CollapsedBorderValue result = CollapsedBorderValue(style()->borderBefore(), includeColor ? style()->visitedDependentColor(beforeColorProperty) : Color(), BCELL);
+    
+    RenderTableCell* prevCell = table->cellAbove(this);
+    if (prevCell) {
+        // (2) A before cell's after border.
+        result = chooseBorder(CollapsedBorderValue(prevCell->style()->borderAfter(), includeColor ? prevCell->style()->visitedDependentColor(afterColorProperty) : Color(), BCELL), result);
+        if (!result.exists())
+            return result;
+    }
+    
+    // (3) Our row's before border.
+    result = chooseBorder(result, CollapsedBorderValue(parent()->style()->borderBefore(), includeColor ? parent()->style()->visitedDependentColor(beforeColorProperty) : Color(), BROW));
+    if (!result.exists())
+        return result;
+    
+    // (4) The previous row's after border.
+    if (prevCell) {
+        RenderObject* prevRow = 0;
+        if (prevCell->section() == section())
+            prevRow = parent()->previousSibling();
+        else
+            prevRow = prevCell->section()->lastChild();
+    
+        if (prevRow) {
+            result = chooseBorder(CollapsedBorderValue(prevRow->style()->borderAfter(), includeColor ? prevRow->style()->visitedDependentColor(afterColorProperty) : Color(), BROW), result);
+            if (!result.exists())
+                return result;
+        }
+    }
+    
+    // Now check row groups.
+    RenderTableSection* currSection = section();
+    if (!rowIndex()) {
+        // (5) Our row group's before border.
+        result = chooseBorder(result, CollapsedBorderValue(currSection->style()->borderBefore(), includeColor ? currSection->style()->visitedDependentColor(beforeColorProperty) : Color(), BROWGROUP));
+        if (!result.exists())
+            return result;
+        
+        // (6) Previous row group's after border.
+        currSection = table->sectionAbove(currSection, SkipEmptySections);
+        if (currSection) {
+            result = chooseBorder(CollapsedBorderValue(currSection->style()->borderAfter(), includeColor ? currSection->style()->visitedDependentColor(afterColorProperty) : Color(), BROWGROUP), result);
+            if (!result.exists())
+                return result;
+        }
+    }
+    
+    if (!currSection) {
+        // (8) Our column and column group's before borders.
+        RenderTableCol* colElt = table->colElement(col());
+        if (colElt) {
+            result = chooseBorder(result, CollapsedBorderValue(colElt->style()->borderBefore(), includeColor ? colElt->style()->visitedDependentColor(beforeColorProperty) : Color(), BCOL));
+            if (!result.exists())
+                return result;
+            if (RenderTableCol* enclosingColumnGroup = colElt->enclosingColumnGroup()) {
+                result = chooseBorder(result, CollapsedBorderValue(enclosingColumnGroup->style()->borderBefore(), includeColor ? enclosingColumnGroup->style()->visitedDependentColor(beforeColorProperty) : Color(), BCOLGROUP));
+                if (!result.exists())
+                    return result;
+            }
+        }
+        
+        // (9) The table's before border.
+        result = chooseBorder(result, CollapsedBorderValue(table->style()->borderBefore(), includeColor ? table->style()->visitedDependentColor(beforeColorProperty) : Color(), BTABLE));
+        if (!result.exists())
+            return result;
+    }
+    
+    return result;
+}
+
+CollapsedBorderValue RenderTableCell::collapsedAfterBorder(IncludeBorderColorOrNot includeColor) const
+{
+    CollapsedBorderValue result = computeCollapsedAfterBorder(includeColor);
+    if (includeColor)
+        section()->setCachedCollapsedBorder(this, CBSAfter, result);
+    return result;
+}
+
+CollapsedBorderValue RenderTableCell::computeCollapsedAfterBorder(IncludeBorderColorOrNot includeColor) const
+{
+    RenderTable* table = this->table();
+
+    // For after border, we need to check, in order of precedence:
+    // (1) Our after border.
+    int beforeColorProperty = includeColor ? CSSProperty::resolveDirectionAwareProperty(CSSPropertyWebkitBorderBeforeColor, styleForCellFlow()->direction(), styleForCellFlow()->writingMode()) : 0;
+    int afterColorProperty = includeColor ? CSSProperty::resolveDirectionAwareProperty(CSSPropertyWebkitBorderAfterColor, styleForCellFlow()->direction(), styleForCellFlow()->writingMode()) : 0;
+    CollapsedBorderValue result = CollapsedBorderValue(style()->borderAfter(), includeColor ? style()->visitedDependentColor(afterColorProperty) : Color(), BCELL);
+    
+    RenderTableCell* nextCell = table->cellBelow(this);
+    if (nextCell) {
+        // (2) An after cell's before border.
+        result = chooseBorder(result, CollapsedBorderValue(nextCell->style()->borderBefore(), includeColor ? nextCell->style()->visitedDependentColor(beforeColorProperty) : Color(), BCELL));
+        if (!result.exists())
+            return result;
+    }
+    
+    // (3) Our row's after border. (FIXME: Deal with rowspan!)
+    result = chooseBorder(result, CollapsedBorderValue(parent()->style()->borderAfter(), includeColor ? parent()->style()->visitedDependentColor(afterColorProperty) : Color(), BROW));
+    if (!result.exists())
+        return result;
+    
+    // (4) The next row's before border.
+    if (nextCell) {
+        result = chooseBorder(result, CollapsedBorderValue(nextCell->parent()->style()->borderBefore(), includeColor ? nextCell->parent()->style()->visitedDependentColor(beforeColorProperty) : Color(), BROW));
+        if (!result.exists())
+            return result;
+    }
+    
+    // Now check row groups.
+    RenderTableSection* currSection = section();
+    if (rowIndex() + rowSpan() >= currSection->numRows()) {
+        // (5) Our row group's after border.
+        result = chooseBorder(result, CollapsedBorderValue(currSection->style()->borderAfter(), includeColor ? currSection->style()->visitedDependentColor(afterColorProperty) : Color(), BROWGROUP));
+        if (!result.exists())
+            return result;
+        
+        // (6) Following row group's before border.
+        currSection = table->sectionBelow(currSection, SkipEmptySections);
+        if (currSection) {
+            result = chooseBorder(result, CollapsedBorderValue(currSection->style()->borderBefore(), includeColor ? currSection->style()->visitedDependentColor(beforeColorProperty) : Color(), BROWGROUP));
+            if (!result.exists())
+                return result;
+        }
+    }
+    
+    if (!currSection) {
+        // (8) Our column and column group's after borders.
+        RenderTableCol* colElt = table->colElement(col());
+        if (colElt) {
+            result = chooseBorder(result, CollapsedBorderValue(colElt->style()->borderAfter(), includeColor ? colElt->style()->visitedDependentColor(afterColorProperty) : Color(), BCOL));
+            if (!result.exists()) return result;
+            if (RenderTableCol* enclosingColumnGroup = colElt->enclosingColumnGroup()) {
+                result = chooseBorder(result, CollapsedBorderValue(enclosingColumnGroup->style()->borderAfter(), includeColor ? enclosingColumnGroup->style()->visitedDependentColor(afterColorProperty) : Color(), BCOLGROUP));
+                if (!result.exists())
+                    return result;
+            }
+        }
+        
+        // (9) The table's after border.
+        result = chooseBorder(result, CollapsedBorderValue(table->style()->borderAfter(), includeColor ? table->style()->visitedDependentColor(afterColorProperty) : Color(), BTABLE));
+        if (!result.exists())
+            return result;
+    }
+    
+    return result;    
+}
+
+inline CollapsedBorderValue RenderTableCell::cachedCollapsedLeftBorder(const RenderStyle* styleForCellFlow) const
+{
+    if (styleForCellFlow->isHorizontalWritingMode())
+        return styleForCellFlow->isLeftToRightDirection() ? section()->cachedCollapsedBorder(this, CBSStart) : section()->cachedCollapsedBorder(this, CBSEnd);
+    return styleForCellFlow->isFlippedBlocksWritingMode() ? section()->cachedCollapsedBorder(this, CBSAfter) : section()->cachedCollapsedBorder(this, CBSBefore);
+}
+
+inline CollapsedBorderValue RenderTableCell::cachedCollapsedRightBorder(const RenderStyle* styleForCellFlow) const
+{
+    if (styleForCellFlow->isHorizontalWritingMode())
+        return styleForCellFlow->isLeftToRightDirection() ? section()->cachedCollapsedBorder(this, CBSEnd) : section()->cachedCollapsedBorder(this, CBSStart);
+    return styleForCellFlow->isFlippedBlocksWritingMode() ? section()->cachedCollapsedBorder(this, CBSBefore) : section()->cachedCollapsedBorder(this, CBSAfter);
+}
+
+inline CollapsedBorderValue RenderTableCell::cachedCollapsedTopBorder(const RenderStyle* styleForCellFlow) const
+{
+    if (styleForCellFlow->isHorizontalWritingMode())
+        return styleForCellFlow->isFlippedBlocksWritingMode() ? section()->cachedCollapsedBorder(this, CBSAfter) : section()->cachedCollapsedBorder(this, CBSBefore);
+    return styleForCellFlow->isLeftToRightDirection() ? section()->cachedCollapsedBorder(this, CBSStart) : section()->cachedCollapsedBorder(this, CBSEnd);
+}
+
+inline CollapsedBorderValue RenderTableCell::cachedCollapsedBottomBorder(const RenderStyle* styleForCellFlow) const
+{
+    if (styleForCellFlow->isHorizontalWritingMode())
+        return styleForCellFlow->isFlippedBlocksWritingMode() ? section()->cachedCollapsedBorder(this, CBSBefore) : section()->cachedCollapsedBorder(this, CBSAfter);
+    return styleForCellFlow->isLeftToRightDirection() ? section()->cachedCollapsedBorder(this, CBSEnd) : section()->cachedCollapsedBorder(this, CBSStart);
+}
+
+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();
+}
+
+// FIXME: https://bugs.webkit.org/show_bug.cgi?id=46191, make the collapsed border drawing
+// work with different block flow values instead of being hard-coded to top-to-bottom.
+int RenderTableCell::borderStart() const
+{
+    return table()->collapseBorders() ? borderHalfStart(false) : RenderBlock::borderStart();
+}
+
+int RenderTableCell::borderEnd() const
+{
+    return table()->collapseBorders() ? borderHalfEnd(false) : RenderBlock::borderEnd();
+}
+
+int RenderTableCell::borderBefore() const
+{
+    return table()->collapseBorders() ? borderHalfBefore(false) : RenderBlock::borderBefore();
+}
+
+int RenderTableCell::borderAfter() const
+{
+    return table()->collapseBorders() ? borderHalfAfter(false) : RenderBlock::borderAfter();
+}
+
+int RenderTableCell::borderHalfLeft(bool outer) const
+{
+    const RenderStyle* styleForCellFlow = this->styleForCellFlow();
+    if (styleForCellFlow->isHorizontalWritingMode())
+        return styleForCellFlow->isLeftToRightDirection() ? borderHalfStart(outer) : borderHalfEnd(outer);
+    return styleForCellFlow->isFlippedBlocksWritingMode() ? borderHalfAfter(outer) : borderHalfBefore(outer);
+}
+
+int RenderTableCell::borderHalfRight(bool outer) const
+{
+    const RenderStyle* styleForCellFlow = this->styleForCellFlow();
+    if (styleForCellFlow->isHorizontalWritingMode())
+        return styleForCellFlow->isLeftToRightDirection() ? borderHalfEnd(outer) : borderHalfStart(outer);
+    return styleForCellFlow->isFlippedBlocksWritingMode() ? borderHalfBefore(outer) : borderHalfAfter(outer);
+}
+
+int RenderTableCell::borderHalfTop(bool outer) const
+{
+    const RenderStyle* styleForCellFlow = this->styleForCellFlow();
+    if (styleForCellFlow->isHorizontalWritingMode())
+        return styleForCellFlow->isFlippedBlocksWritingMode() ? borderHalfAfter(outer) : borderHalfBefore(outer);
+    return styleForCellFlow->isLeftToRightDirection() ? borderHalfStart(outer) : borderHalfEnd(outer);
+}
+
+int RenderTableCell::borderHalfBottom(bool outer) const
+{
+    const RenderStyle* styleForCellFlow = this->styleForCellFlow();
+    if (styleForCellFlow->isHorizontalWritingMode())
+        return styleForCellFlow->isFlippedBlocksWritingMode() ? borderHalfBefore(outer) : borderHalfAfter(outer);
+    return styleForCellFlow->isLeftToRightDirection() ? borderHalfEnd(outer) : borderHalfStart(outer);
+}
+
+int RenderTableCell::borderHalfStart(bool outer) const
+{
+    CollapsedBorderValue border = collapsedStartBorder(DoNotIncludeBorderColor);
+    if (border.exists())
+        return (border.width() + ((styleForCellFlow()->isLeftToRightDirection() ^ outer) ? 1 : 0)) / 2; // Give the extra pixel to top and left.
+    return 0;
+}
+    
+int RenderTableCell::borderHalfEnd(bool outer) const
+{
+    CollapsedBorderValue border = collapsedEndBorder(DoNotIncludeBorderColor);
+    if (border.exists())
+        return (border.width() + ((styleForCellFlow()->isLeftToRightDirection() ^ outer) ? 0 : 1)) / 2;
+    return 0;
+}
+
+int RenderTableCell::borderHalfBefore(bool outer) const
+{
+    CollapsedBorderValue border = collapsedBeforeBorder(DoNotIncludeBorderColor);
+    if (border.exists())
+        return (border.width() + ((styleForCellFlow()->isFlippedBlocksWritingMode() ^ outer) ? 0 : 1)) / 2; // Give the extra pixel to top and left.
+    return 0;
+}
+
+int RenderTableCell::borderHalfAfter(bool outer) const
+{
+    CollapsedBorderValue border = collapsedAfterBorder(DoNotIncludeBorderColor);
+    if (border.exists())
+        return (border.width() + ((styleForCellFlow()->isFlippedBlocksWritingMode() ^ outer) ? 1 : 0)) / 2;
+    return 0;
+}
+
+void RenderTableCell::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    ASSERT(paintInfo.phase != PaintPhaseCollapsedTableBorders);
+    RenderBlock::paint(paintInfo, paintOffset);
+}
+
+static EBorderStyle collapsedBorderStyle(EBorderStyle style)
+{
+    if (style == OUTSET)
+        return GROOVE;
+    if (style == INSET)
+        return RIDGE;
+    return style;
+}
+
+struct CollapsedBorder {
+    CollapsedBorderValue borderValue;
+    BoxSide 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, BoxSide 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 (unsigned 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];
+    unsigned m_count;
+};
+
+static void addBorderStyle(RenderTable::CollapsedBorderValues& borderValues,
+                           CollapsedBorderValue borderValue)
+{
+    if (!borderValue.exists())
+        return;
+    size_t count = borderValues.size();
+    for (size_t i = 0; i < count; ++i)
+        if (borderValues[i].isSameIgnoringColor(borderValue))
+            return;
+    borderValues.append(borderValue);
+}
+
+void RenderTableCell::collectBorderValues(RenderTable::CollapsedBorderValues& borderValues) const
+{
+    addBorderStyle(borderValues, collapsedStartBorder());
+    addBorderStyle(borderValues, collapsedEndBorder());
+    addBorderStyle(borderValues, collapsedBeforeBorder());
+    addBorderStyle(borderValues, collapsedAfterBorder());
+}
+
+static int compareBorderValuesForQSort(const void* pa, const void* pb)
+{
+    const CollapsedBorderValue* a = static_cast<const CollapsedBorderValue*>(pa);
+    const CollapsedBorderValue* b = static_cast<const CollapsedBorderValue*>(pb);
+    if (a->isSameIgnoringColor(*b))
+        return 0;
+    return compareBorders(*a, *b);
+}
+
+void RenderTableCell::sortBorderValues(RenderTable::CollapsedBorderValues& borderValues)
+{
+    qsort(borderValues.data(), borderValues.size(), sizeof(CollapsedBorderValue),
+        compareBorderValuesForQSort);
+}
+
+void RenderTableCell::paintCollapsedBorders(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    ASSERT(paintInfo.phase == PaintPhaseCollapsedTableBorders);
+
+    if (!paintInfo.shouldPaintWithinRoot(this) || style()->visibility() != VISIBLE)
+        return;
+
+    LayoutRect localRepaintRect = paintInfo.rect;
+    localRepaintRect.inflate(maximalOutlineSize(paintInfo.phase));
+
+    LayoutRect paintRect = LayoutRect(paintOffset + location(), pixelSnappedSize());
+    if (paintRect.y() - table()->outerBorderTop() >= localRepaintRect.maxY())
+        return;
+
+    if (paintRect.maxY() + table()->outerBorderBottom() <= localRepaintRect.y())
+        return;
+
+    GraphicsContext* graphicsContext = paintInfo.context;
+    if (!table()->currentBorderValue() || graphicsContext->paintingDisabled())
+        return;
+
+    const RenderStyle* styleForCellFlow = this->styleForCellFlow();
+    CollapsedBorderValue leftVal = cachedCollapsedLeftBorder(styleForCellFlow);
+    CollapsedBorderValue rightVal = cachedCollapsedRightBorder(styleForCellFlow);
+    CollapsedBorderValue topVal = cachedCollapsedTopBorder(styleForCellFlow);
+    CollapsedBorderValue bottomVal = cachedCollapsedBottomBorder(styleForCellFlow);
+     
+    // 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();
+
+    IntRect borderRect = pixelSnappedIntRect(paintRect.x() - leftWidth / 2,
+            paintRect.y() - topWidth / 2,
+            paintRect.width() + leftWidth / 2 + (rightWidth + 1) / 2,
+            paintRect.height() + 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, borderRect.x(), borderRect.y(), borderRect.maxX(), borderRect.y() + topWidth, topStyle);
+    borders.addBorder(bottomVal, BSBottom, renderBottom, borderRect.x(), borderRect.maxY() - bottomWidth, borderRect.maxX(), borderRect.maxY(), bottomStyle);
+    borders.addBorder(leftVal, BSLeft, renderLeft, borderRect.x(), borderRect.y(), borderRect.x() + leftWidth, borderRect.maxY(), leftStyle);
+    borders.addBorder(rightVal, BSRight, renderRight, borderRect.maxX() - rightWidth, borderRect.y(), borderRect.maxX(), borderRect.maxY(), rightStyle);
+
+    bool antialias = shouldAntialiasLines(graphicsContext);
+    
+    for (CollapsedBorder* border = borders.nextBorder(); border; border = borders.nextBorder()) {
+        if (border->borderValue.isSameIgnoringColor(*table()->currentBorderValue()))
+            drawLineForBoxSide(graphicsContext, border->x1, border->y1, border->x2, border->y2, border->side, 
+                               border->borderValue.color(), border->style, 0, 0, antialias);
+    }
+}
+
+void RenderTableCell::paintBackgroundsBehindCell(PaintInfo& paintInfo, const LayoutPoint& paintOffset, RenderObject* backgroundObject)
+{
+    if (!paintInfo.shouldPaintWithinRoot(this))
+        return;
+
+    if (!backgroundObject)
+        return;
+
+    if (style()->visibility() != VISIBLE)
+        return;
+
+    RenderTable* tableElt = table();
+    if (!tableElt->collapseBorders() && style()->emptyCells() == HIDE && !firstChild())
+        return;
+
+    LayoutPoint adjustedPaintOffset = paintOffset;
+    if (backgroundObject != this)
+        adjustedPaintOffset.moveBy(location());
+
+    Color c = backgroundObject->style()->visitedDependentColor(CSSPropertyBackgroundColor);
+    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();
+        GraphicsContextStateSaver stateSaver(*paintInfo.context, shouldClip);
+        if (shouldClip) {
+            LayoutRect clipRect(adjustedPaintOffset.x() + borderLeft(), adjustedPaintOffset.y() + borderTop(),
+                width() - borderLeft() - borderRight(), height() - borderTop() - borderBottom());
+            paintInfo.context->clip(clipRect);
+        }
+        paintFillLayers(paintInfo, c, bgLayer, LayoutRect(adjustedPaintOffset, pixelSnappedSize()), BackgroundBleedNone, CompositeSourceOver, backgroundObject);
+    }
+}
+
+void RenderTableCell::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    if (!paintInfo.shouldPaintWithinRoot(this))
+        return;
+
+    RenderTable* tableElt = table();
+    if (!tableElt->collapseBorders() && style()->emptyCells() == HIDE && !firstChild())
+        return;
+
+    LayoutRect paintRect = LayoutRect(paintOffset, pixelSnappedSize());
+    paintBoxShadow(paintInfo, paintRect, style(), Normal);
+    
+    // Paint our cell background.
+    paintBackgroundsBehindCell(paintInfo, paintOffset, this);
+
+    paintBoxShadow(paintInfo, paintRect, style(), Inset);
+
+    if (!style()->hasBorder() || tableElt->collapseBorders())
+        return;
+
+    paintBorder(paintInfo, paintRect, style());
+}
+
+void RenderTableCell::paintMask(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    if (style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask)
+        return;
+
+    RenderTable* tableElt = table();
+    if (!tableElt->collapseBorders() && style()->emptyCells() == HIDE && !firstChild())
+        return;
+   
+    paintMaskImages(paintInfo, LayoutRect(paintOffset, pixelSnappedSize()));
+}
+
+bool RenderTableCell::boxShadowShouldBeAppliedToBackground(BackgroundBleedAvoidance, InlineFlowBox*) const
+{
+    return false;
+}
+
+void RenderTableCell::scrollbarsChanged(bool horizontalScrollbarChanged, bool verticalScrollbarChanged)
+{
+    LayoutUnit scrollbarHeight = scrollbarLogicalHeight();
+    if (!scrollbarHeight)
+        return; // Not sure if we should be doing something when a scrollbar goes away or not.
+    
+    // We only care if the scrollbar that affects our intrinsic padding has been added.
+    if ((isHorizontalWritingMode() && !horizontalScrollbarChanged) ||
+        (!isHorizontalWritingMode() && !verticalScrollbarChanged))
+        return;
+
+    // Shrink our intrinsic padding as much as possible to accommodate the scrollbar.
+    if (style()->verticalAlign() == MIDDLE) {
+        LayoutUnit totalHeight = logicalHeight();
+        LayoutUnit heightWithoutIntrinsicPadding = totalHeight - intrinsicPaddingBefore() - intrinsicPaddingAfter();
+        totalHeight -= scrollbarHeight;
+        LayoutUnit newBeforePadding = (totalHeight - heightWithoutIntrinsicPadding) / 2;
+        LayoutUnit newAfterPadding = totalHeight - heightWithoutIntrinsicPadding - newBeforePadding;
+        setIntrinsicPaddingBefore(newBeforePadding);
+        setIntrinsicPaddingAfter(newAfterPadding);
+    } else
+        setIntrinsicPaddingAfter(intrinsicPaddingAfter() - scrollbarHeight);
+}
+
+RenderTableCell* RenderTableCell::createAnonymous(Document* document)
+{
+    RenderTableCell* renderer = new (document->renderArena()) RenderTableCell(0);
+    renderer->setDocumentForAnonymous(document);
+    return renderer;
+}
+
+RenderTableCell* RenderTableCell::createAnonymousWithParentRenderer(const RenderObject* parent)
+{
+    RenderTableCell* newCell = RenderTableCell::createAnonymous(parent->document());
+    RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(parent->style(), TABLE_CELL);
+    newCell->setStyle(newStyle.release());
+    return newCell;
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderTableCell.h b/Source/core/rendering/RenderTableCell.h
new file mode 100644
index 0000000..933ff4c
--- /dev/null
+++ b/Source/core/rendering/RenderTableCell.h
@@ -0,0 +1,300 @@
+/*
+ * Copyright (C) 1997 Martin Jones (mjones@kde.org)
+ *           (C) 1997 Torben Weis (weis@kde.org)
+ *           (C) 1998 Waldo Bastian (bastian@kde.org)
+ *           (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2009 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 "core/rendering/RenderTableRow.h"
+#include "core/rendering/RenderTableSection.h"
+
+namespace WebCore {
+
+static const unsigned unsetColumnIndex = 0x1FFFFFFF;
+static const unsigned maxColumnIndex = 0x1FFFFFFE; // 536,870,910
+
+enum IncludeBorderColorOrNot { DoNotIncludeBorderColor, IncludeBorderColor };
+
+class RenderTableCell FINAL : public RenderBlock {
+public:
+    explicit RenderTableCell(Element*);
+    
+    unsigned colSpan() const
+    {
+        if (!m_hasColSpan)
+            return 1;
+        return parseColSpanFromDOM();
+    }
+    unsigned rowSpan() const
+    {
+        if (!m_hasRowSpan)
+            return 1;
+        return parseRowSpanFromDOM();
+    }
+
+    // Called from HTMLTableCellElement.
+    void colSpanOrRowSpanChanged();
+
+    void setCol(unsigned column)
+    {
+        if (UNLIKELY(column > maxColumnIndex))
+            CRASH();
+
+        m_column = column;
+    }
+
+    unsigned col() const
+    {
+        ASSERT(m_column != unsetColumnIndex);
+        return m_column;
+    }
+
+    RenderTableRow* row() const { return toRenderTableRow(parent()); }
+    RenderTableSection* section() const { return toRenderTableSection(parent()->parent()); }
+    RenderTable* table() const { return toRenderTable(parent()->parent()->parent()); }
+
+    unsigned rowIndex() const
+    {
+        // This function shouldn't be called on a detached cell.
+        ASSERT(row());
+        return row()->rowIndex();
+    }
+
+    Length styleOrColLogicalWidth() const
+    {
+        Length styleWidth = style()->logicalWidth();
+        if (!styleWidth.isAuto())
+            return styleWidth;
+        if (RenderTableCol* firstColumn = table()->colElement(col()))
+            return logicalWidthFromColumns(firstColumn, styleWidth);
+        return styleWidth;
+    }
+
+    int logicalHeightForRowSizing() const
+    {
+        // FIXME: This function does too much work, and is very hot during table layout!
+        int adjustedLogicalHeight = pixelSnappedLogicalHeight() - (intrinsicPaddingBefore() + intrinsicPaddingAfter());
+        int styleLogicalHeight = valueForLength(style()->logicalHeight(), 0, view());
+        // In strict mode, box-sizing: content-box do the right thing and actually add in the border and padding.
+        // Call computedCSSPadding* directly to avoid including implicitPadding.
+        if (!document()->inQuirksMode() && style()->boxSizing() != BORDER_BOX)
+            styleLogicalHeight += (computedCSSPaddingBefore() + computedCSSPaddingAfter()).floor() + borderBefore() + borderAfter();
+        return max(styleLogicalHeight, adjustedLogicalHeight);
+    }
+
+
+    void setCellLogicalWidth(int constrainedLogicalWidth);
+
+    virtual int borderLeft() const;
+    virtual int borderRight() const;
+    virtual int borderTop() const;
+    virtual int borderBottom() const;
+    virtual int borderStart() const;
+    virtual int borderEnd() const;
+    virtual int borderBefore() const;
+    virtual int borderAfter() const;
+
+    void collectBorderValues(RenderTable::CollapsedBorderValues&) const;
+    static void sortBorderValues(RenderTable::CollapsedBorderValues&);
+
+    virtual void layout();
+
+    virtual void paint(PaintInfo&, const LayoutPoint&);
+
+    void paintCollapsedBorders(PaintInfo&, const LayoutPoint&);
+    void paintBackgroundsBehindCell(PaintInfo&, const LayoutPoint&, RenderObject* backgroundObject);
+
+    LayoutUnit cellBaselinePosition() const;
+    bool isBaselineAligned() const 
+    { 
+        EVerticalAlign va = style()->verticalAlign();
+        return va == BASELINE || va == TEXT_BOTTOM || va == TEXT_TOP || va == SUPER || va == SUB || va == LENGTH; 
+    }
+
+    void computeIntrinsicPadding(int rowHeight);
+    void clearIntrinsicPadding() { setIntrinsicPadding(0, 0); }
+
+    int intrinsicPaddingBefore() const { return m_intrinsicPaddingBefore; }
+    int intrinsicPaddingAfter() const { return m_intrinsicPaddingAfter; }
+
+    virtual LayoutUnit paddingTop() const OVERRIDE;
+    virtual LayoutUnit paddingBottom() const OVERRIDE;
+    virtual LayoutUnit paddingLeft() const OVERRIDE;
+    virtual LayoutUnit paddingRight() const OVERRIDE;
+    
+    // FIXME: For now we just assume the cell has the same block flow direction as the table. It's likely we'll
+    // create an extra anonymous RenderBlock to handle mixing directionality anyway, in which case we can lock
+    // the block flow directionality of the cells to the table's directionality.
+    virtual LayoutUnit paddingBefore() const OVERRIDE;
+    virtual LayoutUnit paddingAfter() const OVERRIDE;
+
+    void setOverrideLogicalContentHeightFromRowHeight(LayoutUnit);
+
+    virtual void scrollbarsChanged(bool horizontalScrollbarChanged, bool verticalScrollbarChanged);
+
+    bool cellWidthChanged() const { return m_cellWidthChanged; }
+    void setCellWidthChanged(bool b = true) { m_cellWidthChanged = b; }
+
+    static RenderTableCell* createAnonymous(Document*);
+    static RenderTableCell* createAnonymousWithParentRenderer(const RenderObject*);
+    virtual RenderBox* createAnonymousBoxWithSameTypeAs(const RenderObject* parent) const OVERRIDE
+    {
+        return createAnonymousWithParentRenderer(parent);
+    }
+
+    // This function is used to unify which table part's style we use for computing direction and
+    // writing mode. Writing modes are not allowed on row group and row but direction is.
+    // This means we can safely use the same style in all cases to simplify our code.
+    // FIXME: Eventually this function should replaced by style() once we support direction
+    // on all table parts and writing-mode on cells.
+    const RenderStyle* styleForCellFlow() const
+    {
+        return row()->style();
+    }
+
+    const BorderValue& borderAdjoiningTableStart() const
+    {
+        ASSERT(isFirstOrLastCellInRow());
+        if (section()->hasSameDirectionAs(table()))
+            return style()->borderStart();
+
+        return style()->borderEnd();
+    }
+
+    const BorderValue& borderAdjoiningTableEnd() const
+    {
+        ASSERT(isFirstOrLastCellInRow());
+        if (section()->hasSameDirectionAs(table()))
+            return style()->borderEnd();
+
+        return style()->borderStart();
+    }
+
+    const BorderValue& borderAdjoiningCellBefore(const RenderTableCell* cell)
+    {
+        ASSERT_UNUSED(cell, table()->cellAfter(cell) == this);
+        // FIXME: https://webkit.org/b/79272 - Add support for mixed directionality at the cell level.
+        return style()->borderStart();
+    }
+
+    const BorderValue& borderAdjoiningCellAfter(const RenderTableCell* cell)
+    {
+        ASSERT_UNUSED(cell, table()->cellBefore(cell) == this);
+        // FIXME: https://webkit.org/b/79272 - Add support for mixed directionality at the cell level.
+        return style()->borderEnd();
+    }
+
+#ifndef NDEBUG
+    bool isFirstOrLastCellInRow() const
+    {
+        return !table()->cellAfter(this) || !table()->cellBefore(this);
+    }
+#endif
+protected:
+    virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+    virtual void computePreferredLogicalWidths();
+
+private:
+    virtual const char* renderName() const { return (isAnonymous() || isPseudoElement()) ? "RenderTableCell (anonymous)" : "RenderTableCell"; }
+
+    virtual bool isTableCell() const { return true; }
+
+    virtual void willBeRemovedFromTree() OVERRIDE;
+
+    virtual void updateLogicalWidth() OVERRIDE;
+
+    virtual void paintBoxDecorations(PaintInfo&, const LayoutPoint&);
+    virtual void paintMask(PaintInfo&, const LayoutPoint&);
+
+    virtual bool boxShadowShouldBeAppliedToBackground(BackgroundBleedAvoidance, InlineFlowBox*) const OVERRIDE;
+
+    virtual LayoutSize offsetFromContainer(RenderObject*, const LayoutPoint&, bool* offsetDependsOnPoint = 0) const;
+    virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const OVERRIDE;
+    virtual void computeRectForRepaint(const RenderLayerModelObject* repaintContainer, LayoutRect&, bool fixed = false) const OVERRIDE;
+
+    int borderHalfLeft(bool outer) const;
+    int borderHalfRight(bool outer) const;
+    int borderHalfTop(bool outer) const;
+    int borderHalfBottom(bool outer) const;
+
+    int borderHalfStart(bool outer) const;
+    int borderHalfEnd(bool outer) const;
+    int borderHalfBefore(bool outer) const;
+    int borderHalfAfter(bool outer) const;
+
+    void setIntrinsicPaddingBefore(int p) { m_intrinsicPaddingBefore = p; }
+    void setIntrinsicPaddingAfter(int p) { m_intrinsicPaddingAfter = p; }
+    void setIntrinsicPadding(int before, int after) { setIntrinsicPaddingBefore(before); setIntrinsicPaddingAfter(after); }
+
+    bool hasStartBorderAdjoiningTable() const;
+    bool hasEndBorderAdjoiningTable() const;
+
+    CollapsedBorderValue collapsedStartBorder(IncludeBorderColorOrNot = IncludeBorderColor) const;
+    CollapsedBorderValue collapsedEndBorder(IncludeBorderColorOrNot = IncludeBorderColor) const;
+    CollapsedBorderValue collapsedBeforeBorder(IncludeBorderColorOrNot = IncludeBorderColor) const;
+    CollapsedBorderValue collapsedAfterBorder(IncludeBorderColorOrNot = IncludeBorderColor) const;
+
+    CollapsedBorderValue cachedCollapsedLeftBorder(const RenderStyle*) const;
+    CollapsedBorderValue cachedCollapsedRightBorder(const RenderStyle*) const;
+    CollapsedBorderValue cachedCollapsedTopBorder(const RenderStyle*) const;
+    CollapsedBorderValue cachedCollapsedBottomBorder(const RenderStyle*) const;
+
+    CollapsedBorderValue computeCollapsedStartBorder(IncludeBorderColorOrNot = IncludeBorderColor) const;
+    CollapsedBorderValue computeCollapsedEndBorder(IncludeBorderColorOrNot = IncludeBorderColor) const;
+    CollapsedBorderValue computeCollapsedBeforeBorder(IncludeBorderColorOrNot = IncludeBorderColor) const;
+    CollapsedBorderValue computeCollapsedAfterBorder(IncludeBorderColorOrNot = IncludeBorderColor) const;
+
+    Length logicalWidthFromColumns(RenderTableCol* firstColForThisCell, Length widthFromStyle) const;
+
+    void updateColAndRowSpanFlags();
+
+    unsigned parseRowSpanFromDOM() const;
+    unsigned parseColSpanFromDOM() const;
+
+    // Note MSVC will only pack members if they have identical types, hence we use unsigned instead of bool here.
+    unsigned m_column : 29;
+    unsigned m_cellWidthChanged : 1;
+    unsigned m_hasColSpan: 1;
+    unsigned m_hasRowSpan: 1;
+    int m_intrinsicPaddingBefore;
+    int m_intrinsicPaddingAfter;
+};
+
+inline RenderTableCell* toRenderTableCell(RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isTableCell());
+    return static_cast<RenderTableCell*>(object);
+}
+
+inline const RenderTableCell* toRenderTableCell(const RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isTableCell());
+    return static_cast<const RenderTableCell*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderTableCell(const RenderTableCell*);
+
+} // namespace WebCore
+
+#endif // RenderTableCell_h
diff --git a/Source/core/rendering/RenderTableCol.cpp b/Source/core/rendering/RenderTableCol.cpp
new file mode 100644
index 0000000..64dde07
--- /dev/null
+++ b/Source/core/rendering/RenderTableCol.cpp
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 1997 Martin Jones (mjones@kde.org)
+ *           (C) 1997 Torben Weis (weis@kde.org)
+ *           (C) 1998 Waldo Bastian (bastian@kde.org)
+ *           (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2009 Apple Inc. All rights reserved.
+ * 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 "core/rendering/RenderTableCol.h"
+
+#include "HTMLNames.h"
+#include "core/dom/WebCoreMemoryInstrumentation.h"
+#include "core/html/HTMLTableColElement.h"
+#include "core/loader/cache/CachedImage.h"
+#include "core/rendering/RenderTable.h"
+#include "core/rendering/RenderTableCell.h"
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+RenderTableCol::RenderTableCol(Element* element)
+    : RenderBox(element)
+    , m_span(1)
+{
+    // init RenderObject attributes
+    setInline(true); // our object is not Inline
+    updateFromElement();
+}
+
+void RenderTableCol::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
+{
+    RenderBox::styleDidChange(diff, oldStyle);
+
+    // If border was changed, notify table.
+    if (parent()) {
+        RenderTable* table = this->table();
+        if (table && !table->selfNeedsLayout() && !table->normalChildNeedsLayout() && oldStyle && oldStyle->border() != style()->border())
+            table->invalidateCollapsedBorders();
+    }
+}
+
+void RenderTableCol::updateFromElement()
+{
+    unsigned oldSpan = m_span;
+    Node* n = node();
+    if (n && (n->hasTagName(colTag) || n->hasTagName(colgroupTag))) {
+        HTMLTableColElement* tc = static_cast<HTMLTableColElement*>(n);
+        m_span = tc->span();
+    } else
+        m_span = !(style() && style()->display() == TABLE_COLUMN_GROUP);
+    if (m_span != oldSpan && style() && parent())
+        setNeedsLayoutAndPrefWidthsRecalc();
+}
+
+void RenderTableCol::insertedIntoTree()
+{
+    RenderBox::insertedIntoTree();
+    table()->addColumn(this);
+}
+
+void RenderTableCol::willBeRemovedFromTree()
+{
+    RenderBox::willBeRemovedFromTree();
+    table()->removeColumn(this);
+}
+
+bool RenderTableCol::isChildAllowed(RenderObject* child, RenderStyle* style) const
+{
+    // We cannot use isTableColumn here as style() may return 0.
+    return child->isRenderTableCol() && 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 isTableColumnGroup();
+}
+
+LayoutRect RenderTableCol::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const
+{
+    // 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.
+    // FIXME: check for repaintContainer each time here?
+
+    RenderTable* parentTable = table();
+    if (!parentTable)
+        return LayoutRect();
+    return parentTable->clippedOverflowRectForRepaint(repaintContainer);
+}
+
+void RenderTableCol::imageChanged(WrappedImagePtr, const IntRect*)
+{
+    // FIXME: Repaint only the rect the image paints in.
+    repaint();
+}
+
+void RenderTableCol::clearPreferredLogicalWidthsDirtyBits()
+{
+    setPreferredLogicalWidthsDirty(false);
+
+    for (RenderObject* child = firstChild(); child; child = child->nextSibling())
+        child->setPreferredLogicalWidthsDirty(false);
+}
+
+RenderTable* RenderTableCol::table() const
+{
+    RenderObject* table = parent();
+    if (table && !table->isTable())
+        table = table->parent();
+    return table && table->isTable() ? toRenderTable(table) : 0;
+}
+
+RenderTableCol* RenderTableCol::enclosingColumnGroup() const
+{
+    if (!parent()->isRenderTableCol())
+        return 0;
+
+    RenderTableCol* parentColumnGroup = toRenderTableCol(parent());
+    ASSERT(parentColumnGroup->isTableColumnGroup());
+    ASSERT(isTableColumn());
+    return parentColumnGroup;
+}
+
+RenderTableCol* RenderTableCol::nextColumn() const
+{
+    // If |this| is a column-group, the next column is the colgroup's first child column.
+    if (RenderObject* firstChild = this->firstChild())
+        return toRenderTableCol(firstChild);
+
+    // Otherwise it's the next column along.
+    RenderObject* next = nextSibling();
+
+    // Failing that, the child is the last column in a column-group, so the next column is the next column/column-group after its column-group.
+    if (!next && parent()->isRenderTableCol())
+        next = parent()->nextSibling();
+
+    for (; next && !next->isRenderTableCol(); next = next->nextSibling()) {
+        // We allow captions mixed with columns and column-groups.
+        if (next->isTableCaption())
+            continue;
+
+        return 0;
+    }
+
+    return toRenderTableCol(next);
+}
+
+const BorderValue& RenderTableCol::borderAdjoiningCellStartBorder(const RenderTableCell*) const
+{
+    return style()->borderStart();
+}
+
+const BorderValue& RenderTableCol::borderAdjoiningCellEndBorder(const RenderTableCell*) const
+{
+    return style()->borderEnd();
+}
+
+const BorderValue& RenderTableCol::borderAdjoiningCellBefore(const RenderTableCell* cell) const
+{
+    ASSERT_UNUSED(cell, table()->colElement(cell->col() + cell->colSpan()) == this);
+    return style()->borderStart();
+}
+
+const BorderValue& RenderTableCol::borderAdjoiningCellAfter(const RenderTableCell* cell) const
+{
+    ASSERT_UNUSED(cell, table()->colElement(cell->col() - 1) == this);
+    return style()->borderEnd();
+}
+
+void RenderTableCol::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, PlatformMemoryTypes::Rendering);
+    RenderBox::reportMemoryUsage(memoryObjectInfo);
+    info.addMember(m_children, "children");
+}
+
+}
diff --git a/Source/core/rendering/RenderTableCol.h b/Source/core/rendering/RenderTableCol.h
new file mode 100644
index 0000000..066d8ce
--- /dev/null
+++ b/Source/core/rendering/RenderTableCol.h
@@ -0,0 +1,125 @@
+/*
+ * Copyright (C) 1997 Martin Jones (mjones@kde.org)
+ *           (C) 1997 Torben Weis (weis@kde.org)
+ *           (C) 1998 Waldo Bastian (bastian@kde.org)
+ *           (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2009 Apple Inc. All rights reserved.
+ * 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 "core/rendering/RenderBox.h"
+
+namespace WebCore {
+
+class RenderTable;
+class RenderTableCell;
+
+class RenderTableCol FINAL : public RenderBox {
+public:
+    explicit RenderTableCol(Element*);
+
+    RenderObject* firstChild() const { ASSERT(children() == virtualChildren()); return children()->firstChild(); }
+    RenderObject* lastChild() const { ASSERT(children() == virtualChildren()); return children()->lastChild(); }
+
+    const RenderObjectChildList* children() const { return &m_children; }
+    RenderObjectChildList* children() { return &m_children; }
+
+    void clearPreferredLogicalWidthsDirtyBits();
+
+    unsigned span() const { return m_span; }
+    void setSpan(unsigned span) { m_span = span; }
+
+    bool isTableColumnGroupWithColumnChildren() { return firstChild(); }
+    bool isTableColumn() const { return style()->display() == TABLE_COLUMN; }
+    bool isTableColumnGroup() const { return style()->display() == TABLE_COLUMN_GROUP; }
+
+    RenderTableCol* enclosingColumnGroup() const;
+    RenderTableCol* enclosingColumnGroupIfAdjacentBefore() const
+    {
+        if (previousSibling())
+            return 0;
+        return enclosingColumnGroup();
+    }
+
+    RenderTableCol* enclosingColumnGroupIfAdjacentAfter() const
+    {
+        if (nextSibling())
+            return 0;
+        return enclosingColumnGroup();
+    }
+
+
+    // Returns the next column or column-group.
+    RenderTableCol* nextColumn() const;
+
+    const BorderValue& borderAdjoiningCellStartBorder(const RenderTableCell*) const;
+    const BorderValue& borderAdjoiningCellEndBorder(const RenderTableCell*) const;
+    const BorderValue& borderAdjoiningCellBefore(const RenderTableCell*) const;
+    const BorderValue& borderAdjoiningCellAfter(const RenderTableCell*) const;
+
+    virtual void reportMemoryUsage(MemoryObjectInfo*) const OVERRIDE;
+
+private:
+    virtual RenderObjectChildList* virtualChildren() { return children(); }
+    virtual const RenderObjectChildList* virtualChildren() const { return children(); }
+
+    virtual const char* renderName() const { return "RenderTableCol"; }
+    virtual bool isRenderTableCol() const OVERRIDE { return true; }
+    virtual void updateFromElement();
+    virtual void computePreferredLogicalWidths() OVERRIDE { ASSERT_NOT_REACHED(); }
+
+    virtual void insertedIntoTree() OVERRIDE;
+    virtual void willBeRemovedFromTree() OVERRIDE;
+
+    virtual bool isChildAllowed(RenderObject*, RenderStyle*) const;
+    virtual bool canHaveChildren() const;
+    virtual bool requiresLayer() const { return false; }
+
+    virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const OVERRIDE;
+    virtual void imageChanged(WrappedImagePtr, const IntRect* = 0);
+
+    virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+
+    RenderTable* table() const;
+
+    RenderObjectChildList m_children;
+    unsigned m_span;
+};
+
+inline RenderTableCol* toRenderTableCol(RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isRenderTableCol());
+    return static_cast<RenderTableCol*>(object);
+}
+
+inline const RenderTableCol* toRenderTableCol(const RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isRenderTableCol());
+    return static_cast<const RenderTableCol*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderTableCol(const RenderTableCol*);
+
+}
+
+#endif
diff --git a/Source/core/rendering/RenderTableRow.cpp b/Source/core/rendering/RenderTableRow.cpp
new file mode 100644
index 0000000..db2f8cd
--- /dev/null
+++ b/Source/core/rendering/RenderTableRow.cpp
@@ -0,0 +1,290 @@
+/**
+ * Copyright (C) 1997 Martin Jones (mjones@kde.org)
+ *           (C) 1997 Torben Weis (weis@kde.org)
+ *           (C) 1998 Waldo Bastian (bastian@kde.org)
+ *           (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 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 "core/rendering/RenderTableRow.h"
+
+#include "HTMLNames.h"
+#include "core/dom/Document.h"
+#include "core/dom/WebCoreMemoryInstrumentation.h"
+#include "core/loader/cache/CachedImage.h"
+#include "core/rendering/HitTestResult.h"
+#include "core/rendering/PaintInfo.h"
+#include "core/rendering/RenderTableCell.h"
+#include "core/rendering/RenderView.h"
+#include "core/rendering/style/StyleInheritedData.h"
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+RenderTableRow::RenderTableRow(Element* element)
+    : RenderBox(element)
+    , m_rowIndex(unsetRowIndex)
+{
+    // init RenderObject attributes
+    setInline(false);   // our object is not Inline
+}
+
+void RenderTableRow::willBeRemovedFromTree()
+{
+    RenderBox::willBeRemovedFromTree();
+
+    section()->setNeedsCellRecalc();
+}
+
+static bool borderWidthChanged(const RenderStyle* oldStyle, const RenderStyle* newStyle)
+{
+    return oldStyle->borderLeftWidth() != newStyle->borderLeftWidth()
+        || oldStyle->borderTopWidth() != newStyle->borderTopWidth()
+        || oldStyle->borderRightWidth() != newStyle->borderRightWidth()
+        || oldStyle->borderBottomWidth() != newStyle->borderBottomWidth();
+}
+
+void RenderTableRow::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
+{
+    ASSERT(style()->display() == TABLE_ROW);
+
+    RenderBox::styleDidChange(diff, oldStyle);
+    propagateStyleToAnonymousChildren();
+
+    if (section() && oldStyle && style()->logicalHeight() != oldStyle->logicalHeight())
+        section()->rowLogicalHeightChanged(rowIndex());
+
+    // If border was changed, notify table.
+    if (parent()) {
+        RenderTable* table = this->table();
+        if (table && !table->selfNeedsLayout() && !table->normalChildNeedsLayout() && oldStyle && oldStyle->border() != style()->border())
+            table->invalidateCollapsedBorders();
+        
+        if (table && oldStyle && diff == StyleDifferenceLayout && needsLayout() && table->collapseBorders() && borderWidthChanged(oldStyle, style())) {
+            // If the border width changes on a row, we need to make sure the cells in the row know to lay out again.
+            // This only happens when borders are collapsed, since they end up affecting the border sides of the cell
+            // itself.
+            for (RenderBox* childBox = firstChildBox(); childBox; childBox = childBox->nextSiblingBox()) {
+                if (!childBox->isTableCell())
+                    continue;
+                childBox->setChildNeedsLayout(true, MarkOnlyThis);
+            }
+        }
+    }
+}
+
+const BorderValue& RenderTableRow::borderAdjoiningStartCell(const RenderTableCell* cell) const
+{
+    ASSERT_UNUSED(cell, cell->isFirstOrLastCellInRow());
+    // FIXME: https://webkit.org/b/79272 - Add support for mixed directionality at the cell level.
+    return style()->borderStart();
+}
+
+const BorderValue& RenderTableRow::borderAdjoiningEndCell(const RenderTableCell* cell) const
+{
+    ASSERT_UNUSED(cell, cell->isFirstOrLastCellInRow());
+    // FIXME: https://webkit.org/b/79272 - Add support for mixed directionality at the cell level.
+    return style()->borderEnd();
+}
+
+void RenderTableRow::addChild(RenderObject* child, RenderObject* beforeChild)
+{
+    if (!child->isTableCell()) {
+        RenderObject* last = beforeChild;
+        if (!last)
+            last = lastChild();
+        if (last && last->isAnonymous() && last->isTableCell() && !last->isBeforeOrAfterContent()) {
+            if (beforeChild == last)
+                beforeChild = last->firstChild();
+            last->addChild(child, beforeChild);
+            return;
+        }
+
+        if (beforeChild && !beforeChild->isAnonymous() && beforeChild->parent() == this) {
+            RenderObject* cell = beforeChild->previousSibling();
+            if (cell && cell->isTableCell() && cell->isAnonymous()) {
+                cell->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()->isBeforeOrAfterContent()) {
+            last->parent()->addChild(child, beforeChild);
+            return;
+        }
+
+        RenderTableCell* cell = RenderTableCell::createAnonymousWithParentRenderer(this);
+        addChild(cell, beforeChild);
+        cell->addChild(child);
+        return;
+    } 
+
+    if (beforeChild && beforeChild->parent() != this)
+        beforeChild = splitAnonymousBoxesAroundChild(beforeChild);    
+
+    RenderTableCell* cell = toRenderTableCell(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());
+    RenderBox::addChild(cell, beforeChild);
+
+    if (beforeChild || nextSibling())
+        section()->setNeedsCellRecalc();
+}
+
+void RenderTableRow::layout()
+{
+    StackStats::LayoutCheckPoint layoutCheckPoint;
+    ASSERT(needsLayout());
+
+    // Table rows do not add translation.
+    LayoutStateMaintainer statePusher(view(), this, LayoutSize(), style()->isFlippedBlocksWritingMode());
+
+    bool paginated = view()->layoutState()->isPaginated();
+                
+    for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+        if (child->isTableCell()) {
+            RenderTableCell* cell = toRenderTableCell(child);
+            if (!cell->needsLayout() && paginated && view()->layoutState()->pageLogicalHeight() && view()->layoutState()->pageLogicalOffset(cell, cell->logicalTop()) != cell->pageLogicalOffset())
+                cell->setChildNeedsLayout(true, MarkOnlyThis);
+
+            if (child->needsLayout()) {
+                cell->computeAndSetBlockDirectionMargins(table());
+                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 clippedOverflowRectForRepaint() 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();
+        }
+    }
+
+    statePusher.pop();
+    // RenderTableSection::layoutRows will set our logical height and width later, so it calls updateLayerTransform().
+    setNeedsLayout(false);
+}
+
+LayoutRect RenderTableRow::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const
+{
+    ASSERT(parent());
+
+    if (repaintContainer == this)
+        return RenderBox::clippedOverflowRectForRepaint(repaintContainer);
+
+    // 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.
+    // FIXME: do repaintContainer checks here
+    if (RenderTable* parentTable = table())
+        return parentTable->clippedOverflowRectForRepaint(repaintContainer);
+
+    return LayoutRect();
+}
+
+// Hit Testing
+bool RenderTableRow::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, 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->isTableCell() && !toRenderBox(child)->hasSelfPaintingLayer()) {
+            LayoutPoint cellPoint = flipForWritingModeForChild(toRenderTableCell(child), accumulatedOffset);
+            if (child->nodeAtPoint(request, result, locationInContainer, cellPoint, action)) {
+                updateHitTestResult(result, locationInContainer.point() - toLayoutSize(cellPoint));
+                return true;
+            }
+        }
+    }
+
+    return false;
+}
+
+void RenderTableRow::paintOutlineForRowIfNeeded(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    LayoutPoint adjustedPaintOffset = paintOffset + location();
+    PaintPhase paintPhase = paintInfo.phase;
+    if ((paintPhase == PaintPhaseOutline || paintPhase == PaintPhaseSelfOutline) && style()->visibility() == VISIBLE)
+        paintOutline(paintInfo, LayoutRect(adjustedPaintOffset, size()));
+}
+
+void RenderTableRow::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    ASSERT(hasSelfPaintingLayer());
+
+    paintOutlineForRowIfNeeded(paintInfo, paintOffset);
+    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 = toRenderTableCell(child);
+                cell->paintBackgroundsBehindCell(paintInfo, paintOffset, this);
+            }
+            if (!toRenderBox(child)->hasSelfPaintingLayer())
+                child->paint(paintInfo, paintOffset);
+        }
+    }
+}
+
+void RenderTableRow::imageChanged(WrappedImagePtr, const IntRect*)
+{
+    // FIXME: Examine cells and repaint only the rect the image paints in.
+    repaint();
+}
+
+RenderTableRow* RenderTableRow::createAnonymous(Document* document)
+{
+    RenderTableRow* renderer = new (document->renderArena()) RenderTableRow(0);
+    renderer->setDocumentForAnonymous(document);
+    return renderer;
+}
+
+RenderTableRow* RenderTableRow::createAnonymousWithParentRenderer(const RenderObject* parent)
+{
+    RenderTableRow* newRow = RenderTableRow::createAnonymous(parent->document());
+    RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(parent->style(), TABLE_ROW);
+    newRow->setStyle(newStyle.release());
+    return newRow;
+}
+
+void RenderTableRow::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, PlatformMemoryTypes::Rendering);
+    RenderBox::reportMemoryUsage(memoryObjectInfo);
+    info.addMember(m_children, "children");
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderTableRow.h b/Source/core/rendering/RenderTableRow.h
new file mode 100644
index 0000000..505dcf4
--- /dev/null
+++ b/Source/core/rendering/RenderTableRow.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 1997 Martin Jones (mjones@kde.org)
+ *           (C) 1997 Torben Weis (weis@kde.org)
+ *           (C) 1998 Waldo Bastian (bastian@kde.org)
+ *           (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2009 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 RenderTableRow_h
+#define RenderTableRow_h
+
+#include "core/rendering/RenderTableSection.h"
+
+namespace WebCore {
+
+static const unsigned unsetRowIndex = 0x7FFFFFFF;
+static const unsigned maxRowIndex = 0x7FFFFFFE; // 2,147,483,646
+
+class RenderTableRow FINAL : public RenderBox {
+public:
+    explicit RenderTableRow(Element*);
+
+    RenderObject* firstChild() const { ASSERT(children() == virtualChildren()); return children()->firstChild(); }
+    RenderObject* lastChild() const { ASSERT(children() == virtualChildren()); return children()->lastChild(); }
+
+    const RenderObjectChildList* children() const { return &m_children; }
+    RenderObjectChildList* children() { return &m_children; }
+
+    RenderTableSection* section() const { return toRenderTableSection(parent()); }
+    RenderTable* table() const { return toRenderTable(parent()->parent()); }
+
+    void paintOutlineForRowIfNeeded(PaintInfo&, const LayoutPoint&);
+
+    static RenderTableRow* createAnonymous(Document*);
+    static RenderTableRow* createAnonymousWithParentRenderer(const RenderObject*);
+    virtual RenderBox* createAnonymousBoxWithSameTypeAs(const RenderObject* parent) const OVERRIDE
+    {
+        return createAnonymousWithParentRenderer(parent);
+    }
+
+    void setRowIndex(unsigned rowIndex)
+    {
+        if (UNLIKELY(rowIndex > maxRowIndex))
+            CRASH();
+
+        m_rowIndex = rowIndex;
+    }
+
+    bool rowIndexWasSet() const { return m_rowIndex != unsetRowIndex; }
+    unsigned rowIndex() const
+    {
+        ASSERT(rowIndexWasSet());
+        return m_rowIndex;
+    }
+
+    const BorderValue& borderAdjoiningTableStart() const
+    {
+        if (section()->hasSameDirectionAs(table()))
+            return style()->borderStart();
+
+        return style()->borderEnd();
+    }
+
+    const BorderValue& borderAdjoiningTableEnd() const
+    {
+        if (section()->hasSameDirectionAs(table()))
+            return style()->borderEnd();
+
+        return style()->borderStart();
+    }
+
+    const BorderValue& borderAdjoiningStartCell(const RenderTableCell*) const;
+    const BorderValue& borderAdjoiningEndCell(const RenderTableCell*) const;
+
+    virtual void reportMemoryUsage(MemoryObjectInfo*) const OVERRIDE;
+
+private:
+    virtual RenderObjectChildList* virtualChildren() { return children(); }
+    virtual const RenderObjectChildList* virtualChildren() const { return children(); }
+
+    virtual const char* renderName() const { return (isAnonymous() || isPseudoElement()) ? "RenderTableRow (anonymous)" : "RenderTableRow"; }
+
+    virtual bool isTableRow() const { return true; }
+
+    virtual void willBeRemovedFromTree() OVERRIDE;
+
+    virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0);
+    virtual void layout();
+    virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const;
+    virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
+
+    virtual bool requiresLayer() const OVERRIDE { return hasOverflowClip() || hasTransform() || hasHiddenBackface() || hasClipPath() || createsGroup(); }
+
+    virtual void paint(PaintInfo&, const LayoutPoint&);
+
+    virtual void imageChanged(WrappedImagePtr, const IntRect* = 0);
+
+    virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+
+    RenderObjectChildList m_children;
+    unsigned m_rowIndex : 31;
+};
+
+inline RenderTableRow* toRenderTableRow(RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isTableRow());
+    return static_cast<RenderTableRow*>(object);
+}
+
+inline const RenderTableRow* toRenderTableRow(const RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isTableRow());
+    return static_cast<const RenderTableRow*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderTableRow(const RenderTableRow*);
+
+} // namespace WebCore
+
+#endif // RenderTableRow_h
diff --git a/Source/core/rendering/RenderTableSection.cpp b/Source/core/rendering/RenderTableSection.cpp
new file mode 100644
index 0000000..ab55b7b
--- /dev/null
+++ b/Source/core/rendering/RenderTableSection.cpp
@@ -0,0 +1,1471 @@
+/*
+ * Copyright (C) 1997 Martin Jones (mjones@kde.org)
+ *           (C) 1997 Torben Weis (weis@kde.org)
+ *           (C) 1998 Waldo Bastian (bastian@kde.org)
+ *           (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Alexey Proskuryakov (ap@nypop.com)
+ *
+ * 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 <limits>
+#include "HTMLNames.h"
+#include "core/dom/Document.h"
+#include "core/dom/WebCoreMemoryInstrumentation.h"
+#include "core/loader/cache/CachedImage.h"
+#include "core/rendering/HitTestResult.h"
+#include "core/rendering/PaintInfo.h"
+#include "core/rendering/RenderTableCell.h"
+#include "core/rendering/RenderTableCol.h"
+#include "core/rendering/RenderTableRow.h"
+#include "core/rendering/RenderTableSection.h"
+#include "core/rendering/RenderView.h"
+#include "core/rendering/style/StyleInheritedData.h"
+#include <wtf/HashSet.h>
+#include <wtf/MemoryInstrumentationHashMap.h>
+#include <wtf/MemoryInstrumentationHashSet.h>
+#include <wtf/MemoryInstrumentationVector.h>
+#include <wtf/Vector.h>
+
+using namespace std;
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+// Those 2 variables are used to balance the memory consumption vs the repaint time on big tables.
+static unsigned gMinTableSizeToUseFastPaintPathWithOverflowingCell = 75 * 75;
+static float gMaxAllowedOverflowingCellRatioForFastPaintPath = 0.1f;
+
+static inline void setRowLogicalHeightToRowStyleLogicalHeightIfNotRelative(RenderTableSection::RowStruct& row)
+{
+    ASSERT(row.rowRenderer);
+    row.logicalHeight = row.rowRenderer->style()->logicalHeight();
+    if (row.logicalHeight.isRelative())
+        row.logicalHeight = Length();
+}
+
+static inline void updateLogicalHeightForCell(RenderTableSection::RowStruct& row, const RenderTableCell* cell)
+{
+    // We ignore height settings on rowspan cells.
+    if (cell->rowSpan() != 1)
+        return;
+
+    Length logicalHeight = cell->style()->logicalHeight();
+    if (logicalHeight.isPositive() || (logicalHeight.isRelative() && logicalHeight.value() >= 0)) {
+        Length cRowLogicalHeight = row.logicalHeight;
+        switch (logicalHeight.type()) {
+        case Percent:
+            if (!(cRowLogicalHeight.isPercent())
+                || (cRowLogicalHeight.isPercent() && cRowLogicalHeight.percent() < logicalHeight.percent()))
+                row.logicalHeight = logicalHeight;
+            break;
+        case Fixed:
+            if (cRowLogicalHeight.type() < Percent
+                || (cRowLogicalHeight.isFixed() && cRowLogicalHeight.value() < logicalHeight.value()))
+                row.logicalHeight = logicalHeight;
+            break;
+        case Relative:
+        default:
+            break;
+        }
+    }
+}
+
+
+RenderTableSection::RenderTableSection(Element* element)
+    : RenderBox(element)
+    , m_cCol(0)
+    , m_cRow(0)
+    , m_outerBorderStart(0)
+    , m_outerBorderEnd(0)
+    , m_outerBorderBefore(0)
+    , m_outerBorderAfter(0)
+    , m_needsCellRecalc(false)
+    , m_hasMultipleCellLevels(false)
+{
+    // init RenderObject attributes
+    setInline(false); // our object is not Inline
+}
+
+RenderTableSection::~RenderTableSection()
+{
+}
+
+void RenderTableSection::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
+{
+    RenderBox::styleDidChange(diff, oldStyle);
+    propagateStyleToAnonymousChildren();
+
+    // If border was changed, notify table.
+    RenderTable* table = this->table();
+    if (table && !table->selfNeedsLayout() && !table->normalChildNeedsLayout() && oldStyle && oldStyle->border() != style()->border())
+        table->invalidateCollapsedBorders();
+}
+
+void RenderTableSection::willBeRemovedFromTree()
+{
+    RenderBox::willBeRemovedFromTree();
+
+    // Preventively invalidate our cells as we may be re-inserted into
+    // a new table which would require us to rebuild our structure.
+    setNeedsCellRecalc();
+}
+
+void RenderTableSection::addChild(RenderObject* child, RenderObject* beforeChild)
+{
+    if (!child->isTableRow()) {
+        RenderObject* last = beforeChild;
+        if (!last)
+            last = lastChild();
+        if (last && last->isAnonymous() && !last->isBeforeOrAfterContent()) {
+            if (beforeChild == last)
+                beforeChild = last->firstChild();
+            last->addChild(child, beforeChild);
+            return;
+        }
+
+        if (beforeChild && !beforeChild->isAnonymous() && beforeChild->parent() == this) {
+            RenderObject* row = beforeChild->previousSibling();
+            if (row && row->isTableRow() && row->isAnonymous()) {
+                row->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->isBeforeOrAfterContent()) {
+            lastBox->addChild(child, beforeChild);
+            return;
+        }
+
+        RenderObject* row = RenderTableRow::createAnonymousWithParentRenderer(this);
+        addChild(row, beforeChild);
+        row->addChild(child);
+        return;
+    }
+
+    if (beforeChild)
+        setNeedsCellRecalc();
+
+    unsigned insertionRow = m_cRow;
+    ++m_cRow;
+    m_cCol = 0;
+
+    ensureRows(m_cRow);
+
+    RenderTableRow* row = toRenderTableRow(child);
+    m_grid[insertionRow].rowRenderer = row;
+    row->setRowIndex(insertionRow);
+
+    if (!beforeChild)
+        setRowLogicalHeightToRowStyleLogicalHeightIfNotRelative(m_grid[insertionRow]);
+
+    if (beforeChild && beforeChild->parent() != this)
+        beforeChild = splitAnonymousBoxesAroundChild(beforeChild);
+
+    ASSERT(!beforeChild || beforeChild->isTableRow());
+    RenderBox::addChild(child, beforeChild);
+}
+
+void RenderTableSection::ensureRows(unsigned numRows)
+{
+    if (numRows <= m_grid.size())
+        return;
+
+    unsigned oldSize = m_grid.size();
+    m_grid.grow(numRows);
+
+    unsigned effectiveColumnCount = max(1u, table()->numEffCols());
+    for (unsigned row = oldSize; row < m_grid.size(); ++row)
+        m_grid[row].row.grow(effectiveColumnCount);
+}
+
+void RenderTableSection::addCell(RenderTableCell* cell, RenderTableRow* row)
+{
+    // We don't insert the cell if we need cell recalc as our internal columns' representation
+    // will have drifted from the table's representation. Also recalcCells will call addCell
+    // at a later time after sync'ing our columns' with the table's.
+    if (needsCellRecalc())
+        return;
+
+    unsigned rSpan = cell->rowSpan();
+    unsigned cSpan = cell->colSpan();
+    const Vector<RenderTable::ColumnStruct>& columns = table()->columns();
+    unsigned nCols = columns.size();
+    unsigned insertionRow = row->rowIndex();
+
+    // ### 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(insertionRow, m_cCol).hasCells() || cellAt(insertionRow, m_cCol).inColSpan))
+        m_cCol++;
+
+    updateLogicalHeightForCell(m_grid[insertionRow], cell);
+
+    ensureRows(insertionRow + rSpan);
+
+    m_grid[insertionRow].rowRenderer = row;
+
+    unsigned col = m_cCol;
+    // tell the cell where it is
+    bool inColSpan = false;
+    while (cSpan) {
+        unsigned 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 (unsigned r = 0; r < rSpan; r++) {
+            CellStruct& c = cellAt(insertionRow + r, m_cCol);
+            ASSERT(cell);
+            c.cells.append(cell);
+            // If cells overlap then we take the slow path for painting.
+            if (c.cells.size() > 1)
+                m_hasMultipleCellLevels = true;
+            if (inColSpan)
+                c.inColSpan = true;
+        }
+        m_cCol++;
+        cSpan -= currentSpan;
+        inColSpan = true;
+    }
+    cell->setCol(table()->effColToCol(col));
+}
+
+int RenderTableSection::calcRowLogicalHeight()
+{
+#ifndef NDEBUG
+    SetLayoutNeededForbiddenScope layoutForbiddenScope(this);
+#endif
+
+    ASSERT(!needsLayout());
+
+    RenderTableCell* cell;
+
+    int spacing = table()->vBorderSpacing();
+    
+    RenderView* viewRenderer = view();
+    LayoutStateMaintainer statePusher(viewRenderer);
+
+    m_rowPos.resize(m_grid.size() + 1);
+    m_rowPos[0] = spacing;
+
+    for (unsigned r = 0; r < m_grid.size(); r++) {
+        m_grid[r].baseline = 0;
+        LayoutUnit baselineDescent = 0;
+
+        // Our base size is the biggest logical height from our cells' styles (excluding row spanning cells).
+        m_rowPos[r + 1] = max(m_rowPos[r] + minimumValueForLength(m_grid[r].logicalHeight, 0, viewRenderer).round(), 0);
+
+        Row& row = m_grid[r].row;
+        unsigned totalCols = row.size();
+
+        for (unsigned c = 0; c < totalCols; c++) {
+            CellStruct& current = cellAt(r, c);
+            for (unsigned i = 0; i < current.cells.size(); i++) {
+                cell = current.cells[i];
+                if (current.inColSpan && cell->rowSpan() == 1)
+                    continue;
+
+                // FIXME: We are always adding the height of a rowspan to the last rows which doesn't match
+                // other browsers. See webkit.org/b/52185 for example.
+                if ((cell->rowIndex() + cell->rowSpan() - 1) != r)
+                    continue;
+
+                // For row spanning cells, |r| is the last row in the span.
+                unsigned cellStartRow = cell->rowIndex();
+
+                if (cell->hasOverrideHeight()) {
+                    if (!statePusher.didPush()) {
+                        // Technically, we should also push state for the row, but since
+                        // rows don't push a coordinate transform, that's not necessary.
+                        statePusher.push(this, locationOffset());
+                    }
+                    cell->clearIntrinsicPadding();
+                    cell->clearOverrideSize();
+                    cell->setChildNeedsLayout(true, MarkOnlyThis);
+                    cell->layoutIfNeeded();
+                }
+
+                int cellLogicalHeight = cell->logicalHeightForRowSizing();
+                m_rowPos[r + 1] = max(m_rowPos[r + 1], m_rowPos[cellStartRow] + cellLogicalHeight);
+
+                // Find out the baseline. The baseline is set on the first row in a rowspan.
+                if (cell->isBaselineAligned()) {
+                    LayoutUnit baselinePosition = cell->cellBaselinePosition();
+                    if (baselinePosition > cell->borderBefore() + cell->paddingBefore()) {
+                        m_grid[cellStartRow].baseline = max(m_grid[cellStartRow].baseline, baselinePosition);
+                        // The descent of a cell that spans multiple rows does not affect the height of the first row it spans, so don't let it
+                        // become the baseline descent applied to the rest of the row. Also we don't account for the baseline descent of
+                        // non-spanning cells when computing a spanning cell's extent.
+                        int cellStartRowBaselineDescent = 0;
+                        if (cell->rowSpan() == 1) {
+                            baselineDescent = max(baselineDescent, cellLogicalHeight - (baselinePosition - cell->intrinsicPaddingBefore()));
+                            cellStartRowBaselineDescent = baselineDescent;
+                        }
+                        m_rowPos[cellStartRow + 1] = max<int>(m_rowPos[cellStartRow + 1], m_rowPos[cellStartRow] + m_grid[cellStartRow].baseline + cellStartRowBaselineDescent);
+                    }
+                }
+            }
+        }
+
+        // Add the border-spacing to our final position.
+        m_rowPos[r + 1] += m_grid[r].rowRenderer ? spacing : 0;
+        m_rowPos[r + 1] = max(m_rowPos[r + 1], m_rowPos[r]);
+    }
+
+    ASSERT(!needsLayout());
+
+    statePusher.pop();
+
+    return m_rowPos[m_grid.size()];
+}
+
+void RenderTableSection::layout()
+{
+    StackStats::LayoutCheckPoint layoutCheckPoint;
+    ASSERT(needsLayout());
+    ASSERT(!needsCellRecalc());
+    ASSERT(!table()->needsSectionRecalc());
+
+    // addChild may over-grow m_grid but we don't want to throw away the memory too early as addChild
+    // can be called in a loop (e.g during parsing). Doing it now ensures we have a stable-enough structure.
+    m_grid.shrinkToFit();
+
+    LayoutStateMaintainer statePusher(view(), this, locationOffset(), style()->isFlippedBlocksWritingMode());
+
+    const Vector<int>& columnPos = table()->columnPositions();
+
+    for (unsigned r = 0; r < m_grid.size(); ++r) {
+        Row& row = m_grid[r].row;
+        unsigned cols = row.size();
+        // First, propagate our table layout's information to the cells. This will mark the row as needing layout
+        // if there was a column logical width change.
+        for (unsigned startColumn = 0; startColumn < cols; ++startColumn) {
+            CellStruct& current = row[startColumn];
+            RenderTableCell* cell = current.primaryCell();
+            if (!cell || current.inColSpan)
+                continue;
+
+            unsigned endCol = startColumn;
+            unsigned cspan = cell->colSpan();
+            while (cspan && endCol < cols) {
+                ASSERT(endCol < table()->columns().size());
+                cspan -= table()->columns()[endCol].span;
+                endCol++;
+            }
+            int tableLayoutLogicalWidth = columnPos[endCol] - columnPos[startColumn] - table()->hBorderSpacing();
+            cell->setCellLogicalWidth(tableLayoutLogicalWidth);
+        }
+
+        if (RenderTableRow* rowRenderer = m_grid[r].rowRenderer)
+            rowRenderer->layoutIfNeeded();
+    }
+
+    statePusher.pop();
+    setNeedsLayout(false);
+}
+
+void RenderTableSection::distributeExtraLogicalHeightToPercentRows(int& extraLogicalHeight, int totalPercent)
+{
+    if (!totalPercent)
+        return;
+
+    unsigned totalRows = m_grid.size();
+    int totalHeight = m_rowPos[totalRows] + extraLogicalHeight;
+    int totalLogicalHeightAdded = 0;
+    totalPercent = min(totalPercent, 100);
+    int rowHeight = m_rowPos[1] - m_rowPos[0];
+    for (unsigned r = 0; r < totalRows; ++r) {
+        if (totalPercent > 0 && m_grid[r].logicalHeight.isPercent()) {
+            int toAdd = min<int>(extraLogicalHeight, (totalHeight * m_grid[r].logicalHeight.percent() / 100) - rowHeight);
+            // If toAdd is negative, then we don't want to shrink the row (this bug
+            // affected Outlook Web Access).
+            toAdd = max(0, toAdd);
+            totalLogicalHeightAdded += toAdd;
+            extraLogicalHeight -= toAdd;
+            totalPercent -= m_grid[r].logicalHeight.percent();
+        }
+        ASSERT(totalRows >= 1);
+        if (r < totalRows - 1)
+            rowHeight = m_rowPos[r + 2] - m_rowPos[r + 1];
+        m_rowPos[r + 1] += totalLogicalHeightAdded;
+    }
+}
+
+void RenderTableSection::distributeExtraLogicalHeightToAutoRows(int& extraLogicalHeight, unsigned autoRowsCount)
+{
+    if (!autoRowsCount)
+        return;
+
+    int totalLogicalHeightAdded = 0;
+    for (unsigned r = 0; r < m_grid.size(); ++r) {
+        if (autoRowsCount > 0 && m_grid[r].logicalHeight.isAuto()) {
+            // Recomputing |extraLogicalHeightForRow| guarantees that we properly ditribute round |extraLogicalHeight|.
+            int extraLogicalHeightForRow = extraLogicalHeight / autoRowsCount;
+            totalLogicalHeightAdded += extraLogicalHeightForRow;
+            extraLogicalHeight -= extraLogicalHeightForRow;
+            --autoRowsCount;
+        }
+        m_rowPos[r + 1] += totalLogicalHeightAdded;
+    }
+}
+
+void RenderTableSection::distributeRemainingExtraLogicalHeight(int& extraLogicalHeight)
+{
+    unsigned totalRows = m_grid.size();
+
+    if (extraLogicalHeight <= 0 || !m_rowPos[totalRows])
+        return;
+
+    // FIXME: m_rowPos[totalRows] - m_rowPos[0] is the total rows' size.
+    int totalRowSize = m_rowPos[totalRows];
+    int totalLogicalHeightAdded = 0;
+    int previousRowPosition = m_rowPos[0];
+    for (unsigned r = 0; r < totalRows; r++) {
+        // weight with the original height
+        totalLogicalHeightAdded += extraLogicalHeight * (m_rowPos[r + 1] - previousRowPosition) / totalRowSize;
+        previousRowPosition = m_rowPos[r + 1];
+        m_rowPos[r + 1] += totalLogicalHeightAdded;
+    }
+
+    extraLogicalHeight -= totalLogicalHeightAdded;
+}
+
+int RenderTableSection::distributeExtraLogicalHeightToRows(int extraLogicalHeight)
+{
+    if (!extraLogicalHeight)
+        return extraLogicalHeight;
+
+    unsigned totalRows = m_grid.size();
+    if (!totalRows)
+        return extraLogicalHeight;
+
+    if (!m_rowPos[totalRows] && nextSibling())
+        return extraLogicalHeight;
+
+    unsigned autoRowsCount = 0;
+    int totalPercent = 0;
+    for (unsigned r = 0; r < totalRows; r++) {
+        if (m_grid[r].logicalHeight.isAuto())
+            ++autoRowsCount;
+        else if (m_grid[r].logicalHeight.isPercent())
+            totalPercent += m_grid[r].logicalHeight.percent();
+    }
+
+    int remainingExtraLogicalHeight = extraLogicalHeight;
+    distributeExtraLogicalHeightToPercentRows(remainingExtraLogicalHeight, totalPercent);
+    distributeExtraLogicalHeightToAutoRows(remainingExtraLogicalHeight, autoRowsCount);
+    distributeRemainingExtraLogicalHeight(remainingExtraLogicalHeight);
+    return extraLogicalHeight - remainingExtraLogicalHeight;
+}
+
+void RenderTableSection::layoutRows()
+{
+#ifndef NDEBUG
+    SetLayoutNeededForbiddenScope layoutForbiddenScope(this);
+#endif
+
+    ASSERT(!needsLayout());
+
+    unsigned totalRows = m_grid.size();
+
+    // Set the width of our section now.  The rows will also be this width.
+    setLogicalWidth(table()->contentLogicalWidth());
+    m_overflow.clear();
+    m_overflowingCells.clear();
+    m_forceSlowPaintPathWithOverflowingCell = false;
+
+    int vspacing = table()->vBorderSpacing();
+    unsigned nEffCols = table()->numEffCols();
+
+    LayoutStateMaintainer statePusher(view(), this, locationOffset(), style()->isFlippedBlocksWritingMode());
+
+    for (unsigned r = 0; r < totalRows; r++) {
+        // Set the row's x/y position and width/height.
+        if (RenderTableRow* rowRenderer = m_grid[r].rowRenderer) {
+            rowRenderer->setLocation(LayoutPoint(0, m_rowPos[r]));
+            rowRenderer->setLogicalWidth(logicalWidth());
+            rowRenderer->setLogicalHeight(m_rowPos[r + 1] - m_rowPos[r] - vspacing);
+            rowRenderer->updateLayerTransform();
+        }
+
+        int rowHeightIncreaseForPagination = 0;
+
+        for (unsigned c = 0; c < nEffCols; c++) {
+            CellStruct& cs = cellAt(r, c);
+            RenderTableCell* cell = cs.primaryCell();
+
+            if (!cell || cs.inColSpan)
+                continue;
+
+            int rowIndex = cell->rowIndex();
+            int rHeight = m_rowPos[rowIndex + cell->rowSpan()] - m_rowPos[rowIndex] - 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()->logicalHeight().isFixed()
+                || (!table()->style()->logicalHeight().isAuto() && rHeight != cell->logicalHeight());
+
+            for (RenderObject* o = cell->firstChild(); o; o = o->nextSibling()) {
+                if (!o->isText() && o->style()->logicalHeight().isPercent() && (flexAllChildren || o->isReplaced() || (o->isBox() && toRenderBox(o)->scrollsOverflow()))) {
+                    // Tables with no sections do not flex.
+                    if (!o->isTable() || toRenderTable(o)->hasSections()) {
+                        o->setNeedsLayout(true, MarkOnlyThis);
+                        cellChildrenFlex = true;
+                    }
+                }
+            }
+
+            if (TrackedRendererListHashSet* percentHeightDescendants = cell->percentHeightDescendants()) {
+                TrackedRendererListHashSet::iterator end = percentHeightDescendants->end();
+                for (TrackedRendererListHashSet::iterator it = percentHeightDescendants->begin(); it != end; ++it) {
+                    RenderBox* box = *it;
+                    if (!box->isReplaced() && !box->scrollsOverflow() && !flexAllChildren)
+                        continue;
+
+                    while (box != cell) {
+                        if (box->normalChildNeedsLayout())
+                            break;
+                        box->setChildNeedsLayout(true, MarkOnlyThis);
+                        box = box->containingBlock();
+                        ASSERT(box);
+                        if (!box)
+                            break;
+                    }
+                    cellChildrenFlex = true;
+                }
+            }
+
+            if (cellChildrenFlex) {
+                cell->setChildNeedsLayout(true, MarkOnlyThis);
+                // Alignment within a cell is based off the calculated
+                // height, which becomes irrelevant once the cell has
+                // been resized based off its percentage.
+                cell->setOverrideLogicalContentHeightFromRowHeight(rHeight);
+                cell->layoutIfNeeded();
+
+                // If the baseline moved, we may have to update the data for our row. Find out the new baseline.
+                if (cell->isBaselineAligned()) {
+                    LayoutUnit baseline = cell->cellBaselinePosition();
+                    if (baseline > cell->borderBefore() + cell->paddingBefore())
+                        m_grid[r].baseline = max(m_grid[r].baseline, baseline);
+                }
+            }
+
+            cell->computeIntrinsicPadding(rHeight);
+
+            LayoutRect oldCellRect = cell->frameRect();
+
+            setLogicalPositionForCell(cell, c);
+
+            if (!cell->needsLayout() && view()->layoutState()->pageLogicalHeight() && view()->layoutState()->pageLogicalOffset(cell, cell->logicalTop()) != cell->pageLogicalOffset())
+                cell->setChildNeedsLayout(true, MarkOnlyThis);
+
+            cell->layoutIfNeeded();
+
+            // FIXME: Make pagination work with vertical tables.
+            if (view()->layoutState()->pageLogicalHeight() && cell->logicalHeight() != rHeight) {
+                // FIXME: Pagination might have made us change size. For now just shrink or grow the cell to fit without doing a relayout.
+                // We'll also do a basic increase of the row height to accommodate the cell if it's bigger, but this isn't quite right
+                // either. It's at least stable though and won't result in an infinite # of relayouts that may never stabilize.
+                if (cell->logicalHeight() > rHeight)
+                    rowHeightIncreaseForPagination = max<int>(rowHeightIncreaseForPagination, cell->logicalHeight() - rHeight);
+                cell->setLogicalHeight(rHeight);
+            }
+
+            LayoutSize childOffset(cell->location() - oldCellRect.location());
+            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 (!table()->selfNeedsLayout() && cell->checkForRepaintDuringLayout())
+                    cell->repaintDuringLayoutIfMoved(oldCellRect);
+            }
+        }
+        if (rowHeightIncreaseForPagination) {
+            for (unsigned rowIndex = r + 1; rowIndex <= totalRows; rowIndex++)
+                m_rowPos[rowIndex] += rowHeightIncreaseForPagination;
+            for (unsigned c = 0; c < nEffCols; ++c) {
+                Vector<RenderTableCell*, 1>& cells = cellAt(r, c).cells;
+                for (size_t i = 0; i < cells.size(); ++i)
+                    cells[i]->setLogicalHeight(cells[i]->logicalHeight() + rowHeightIncreaseForPagination);
+            }
+        }
+    }
+
+    ASSERT(!needsLayout());
+
+    setLogicalHeight(m_rowPos[totalRows]);
+
+    computeOverflowFromCells(totalRows, nEffCols);
+
+    statePusher.pop();
+}
+
+void RenderTableSection::computeOverflowFromCells()
+{
+    unsigned totalRows = m_grid.size();
+    unsigned nEffCols = table()->numEffCols();
+    computeOverflowFromCells(totalRows, nEffCols);
+}
+
+void RenderTableSection::computeOverflowFromCells(unsigned totalRows, unsigned nEffCols)
+{
+    unsigned totalCellsCount = nEffCols * totalRows;
+    int maxAllowedOverflowingCellsCount = totalCellsCount < gMinTableSizeToUseFastPaintPathWithOverflowingCell ? 0 : gMaxAllowedOverflowingCellRatioForFastPaintPath * totalCellsCount;
+
+#ifndef NDEBUG
+    bool hasOverflowingCell = false;
+#endif
+    // Now that our height has been determined, add in overflow from cells.
+    for (unsigned r = 0; r < totalRows; r++) {
+        for (unsigned c = 0; c < nEffCols; c++) {
+            CellStruct& cs = cellAt(r, c);
+            RenderTableCell* cell = cs.primaryCell();
+            if (!cell || cs.inColSpan)
+                continue;
+            if (r < totalRows - 1 && cell == primaryCellAt(r + 1, c))
+                continue;
+            addOverflowFromChild(cell);
+#ifndef NDEBUG
+            hasOverflowingCell |= cell->hasVisualOverflow();
+#endif
+            if (cell->hasVisualOverflow() && !m_forceSlowPaintPathWithOverflowingCell) {
+                m_overflowingCells.add(cell);
+                if (m_overflowingCells.size() > maxAllowedOverflowingCellsCount) {
+                    // We need to set m_forcesSlowPaintPath only if there is a least one overflowing cells as the hit testing code rely on this information.
+                    m_forceSlowPaintPathWithOverflowingCell = true;
+                    // The slow path does not make any use of the overflowing cells info, don't hold on to the memory.
+                    m_overflowingCells.clear();
+                }
+            }
+        }
+    }
+
+    ASSERT(hasOverflowingCell == this->hasOverflowingCell());
+}
+
+int RenderTableSection::calcOuterBorderBefore() const
+{
+    unsigned totalCols = table()->numEffCols();
+    if (!m_grid.size() || !totalCols)
+        return 0;
+
+    unsigned borderWidth = 0;
+
+    const BorderValue& sb = style()->borderBefore();
+    if (sb.style() == BHIDDEN)
+        return -1;
+    if (sb.style() > BHIDDEN)
+        borderWidth = sb.width();
+
+    const BorderValue& rb = firstChild()->style()->borderBefore();
+    if (rb.style() == BHIDDEN)
+        return -1;
+    if (rb.style() > BHIDDEN && rb.width() > borderWidth)
+        borderWidth = rb.width();
+
+    bool allHidden = true;
+    for (unsigned c = 0; c < totalCols; c++) {
+        const CellStruct& current = cellAt(0, c);
+        if (current.inColSpan || !current.hasCells())
+            continue;
+        const BorderValue& cb = current.primaryCell()->style()->borderBefore(); // FIXME: Make this work with perpendicular and flipped cells.
+        // FIXME: Don't repeat for the same col group
+        RenderTableCol* colGroup = table()->colElement(c);
+        if (colGroup) {
+            const BorderValue& gb = colGroup->style()->borderBefore();
+            if (gb.style() == BHIDDEN || cb.style() == BHIDDEN)
+                continue;
+            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;
+            allHidden = false;
+            if (cb.style() > BHIDDEN && cb.width() > borderWidth)
+                borderWidth = cb.width();
+        }
+    }
+    if (allHidden)
+        return -1;
+
+    return borderWidth / 2;
+}
+
+int RenderTableSection::calcOuterBorderAfter() const
+{
+    unsigned totalCols = table()->numEffCols();
+    if (!m_grid.size() || !totalCols)
+        return 0;
+
+    unsigned borderWidth = 0;
+
+    const BorderValue& sb = style()->borderAfter();
+    if (sb.style() == BHIDDEN)
+        return -1;
+    if (sb.style() > BHIDDEN)
+        borderWidth = sb.width();
+
+    const BorderValue& rb = lastChild()->style()->borderAfter();
+    if (rb.style() == BHIDDEN)
+        return -1;
+    if (rb.style() > BHIDDEN && rb.width() > borderWidth)
+        borderWidth = rb.width();
+
+    bool allHidden = true;
+    for (unsigned c = 0; c < totalCols; c++) {
+        const CellStruct& current = cellAt(m_grid.size() - 1, c);
+        if (current.inColSpan || !current.hasCells())
+            continue;
+        const BorderValue& cb = current.primaryCell()->style()->borderAfter(); // FIXME: Make this work with perpendicular and flipped cells.
+        // FIXME: Don't repeat for the same col group
+        RenderTableCol* colGroup = table()->colElement(c);
+        if (colGroup) {
+            const BorderValue& gb = colGroup->style()->borderAfter();
+            if (gb.style() == BHIDDEN || cb.style() == BHIDDEN)
+                continue;
+            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;
+            allHidden = false;
+            if (cb.style() > BHIDDEN && cb.width() > borderWidth)
+                borderWidth = cb.width();
+        }
+    }
+    if (allHidden)
+        return -1;
+
+    return (borderWidth + 1) / 2;
+}
+
+int RenderTableSection::calcOuterBorderStart() const
+{
+    unsigned totalCols = table()->numEffCols();
+    if (!m_grid.size() || !totalCols)
+        return 0;
+
+    unsigned borderWidth = 0;
+
+    const BorderValue& sb = style()->borderStart();
+    if (sb.style() == BHIDDEN)
+        return -1;
+    if (sb.style() > BHIDDEN)
+        borderWidth = sb.width();
+
+    if (RenderTableCol* colGroup = table()->colElement(0)) {
+        const BorderValue& gb = colGroup->style()->borderStart();
+        if (gb.style() == BHIDDEN)
+            return -1;
+        if (gb.style() > BHIDDEN && gb.width() > borderWidth)
+            borderWidth = gb.width();
+    }
+
+    bool allHidden = true;
+    for (unsigned r = 0; r < m_grid.size(); r++) {
+        const CellStruct& current = cellAt(r, 0);
+        if (!current.hasCells())
+            continue;
+        // FIXME: Don't repeat for the same cell
+        const BorderValue& cb = current.primaryCell()->style()->borderStart(); // FIXME: Make this work with perpendicular and flipped cells.
+        const BorderValue& rb = current.primaryCell()->parent()->style()->borderStart();
+        if (cb.style() == BHIDDEN || rb.style() == BHIDDEN)
+            continue;
+        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 + (table()->style()->isLeftToRightDirection() ? 0 : 1)) / 2;
+}
+
+int RenderTableSection::calcOuterBorderEnd() const
+{
+    unsigned totalCols = table()->numEffCols();
+    if (!m_grid.size() || !totalCols)
+        return 0;
+
+    unsigned borderWidth = 0;
+
+    const BorderValue& sb = style()->borderEnd();
+    if (sb.style() == BHIDDEN)
+        return -1;
+    if (sb.style() > BHIDDEN)
+        borderWidth = sb.width();
+
+    if (RenderTableCol* colGroup = table()->colElement(totalCols - 1)) {
+        const BorderValue& gb = colGroup->style()->borderEnd();
+        if (gb.style() == BHIDDEN)
+            return -1;
+        if (gb.style() > BHIDDEN && gb.width() > borderWidth)
+            borderWidth = gb.width();
+    }
+
+    bool allHidden = true;
+    for (unsigned r = 0; r < m_grid.size(); r++) {
+        const CellStruct& current = cellAt(r, totalCols - 1);
+        if (!current.hasCells())
+            continue;
+        // FIXME: Don't repeat for the same cell
+        const BorderValue& cb = current.primaryCell()->style()->borderEnd(); // FIXME: Make this work with perpendicular and flipped cells.
+        const BorderValue& rb = current.primaryCell()->parent()->style()->borderEnd();
+        if (cb.style() == BHIDDEN || rb.style() == BHIDDEN)
+            continue;
+        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 + (table()->style()->isLeftToRightDirection() ? 1 : 0)) / 2;
+}
+
+void RenderTableSection::recalcOuterBorder()
+{
+    m_outerBorderBefore = calcOuterBorderBefore();
+    m_outerBorderAfter = calcOuterBorderAfter();
+    m_outerBorderStart = calcOuterBorderStart();
+    m_outerBorderEnd = calcOuterBorderEnd();
+}
+
+int RenderTableSection::firstLineBoxBaseline() const
+{
+    if (!m_grid.size())
+        return -1;
+
+    int firstLineBaseline = m_grid[0].baseline;
+    if (firstLineBaseline)
+        return firstLineBaseline + m_rowPos[0];
+
+    firstLineBaseline = -1;
+    const Row& firstRow = m_grid[0].row;
+    for (size_t i = 0; i < firstRow.size(); ++i) {
+        const CellStruct& cs = firstRow.at(i);
+        const RenderTableCell* cell = cs.primaryCell();
+        // Only cells with content have a baseline
+        if (cell && cell->contentLogicalHeight())
+            firstLineBaseline = max<int>(firstLineBaseline, cell->logicalTop() + cell->paddingBefore() + cell->borderBefore() + cell->contentLogicalHeight());
+    }
+
+    return firstLineBaseline;
+}
+
+void RenderTableSection::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    // 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_grid.size();
+    unsigned totalCols = table()->columns().size();
+
+    if (!totalRows || !totalCols)
+        return;
+
+    LayoutPoint adjustedPaintOffset = paintOffset + location();
+
+    PaintPhase phase = paintInfo.phase;
+    bool pushedClip = pushContentsClip(paintInfo, adjustedPaintOffset);
+    paintObject(paintInfo, adjustedPaintOffset);
+    if (pushedClip)
+        popContentsClip(paintInfo, phase, adjustedPaintOffset);
+
+    if ((phase == PaintPhaseOutline || phase == PaintPhaseSelfOutline) && style()->visibility() == VISIBLE)
+        paintOutline(paintInfo, LayoutRect(adjustedPaintOffset, size()));
+}
+
+static inline bool compareCellPositions(RenderTableCell* elem1, RenderTableCell* elem2)
+{
+    return elem1->rowIndex() < elem2->rowIndex();
+}
+
+// This comparison is used only when we have overflowing cells as we have an unsorted array to sort. We thus need
+// to sort both on rows and columns to properly repaint.
+static inline bool compareCellPositionsWithOverflowingCells(RenderTableCell* elem1, RenderTableCell* elem2)
+{
+    if (elem1->rowIndex() != elem2->rowIndex())
+        return elem1->rowIndex() < elem2->rowIndex();
+
+    return elem1->col() < elem2->col();
+}
+
+void RenderTableSection::paintCell(RenderTableCell* cell, PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    LayoutPoint cellPoint = flipForWritingModeForChild(cell, paintOffset);
+    PaintPhase paintPhase = paintInfo.phase;
+    RenderTableRow* row = toRenderTableRow(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.
+        RenderTableCol* column = table()->colElement(cell->col());
+        RenderTableCol* columnGroup = column ? column->enclosingColumnGroup() : 0;
+
+        // 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, cellPoint, columnGroup);
+        cell->paintBackgroundsBehindCell(paintInfo, cellPoint, column);
+
+        // Paint the row group next.
+        cell->paintBackgroundsBehindCell(paintInfo, cellPoint, 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->hasSelfPaintingLayer())
+            cell->paintBackgroundsBehindCell(paintInfo, cellPoint, row);
+    }
+    if ((!cell->hasSelfPaintingLayer() && !row->hasSelfPaintingLayer()))
+        cell->paint(paintInfo, cellPoint);
+}
+
+LayoutRect RenderTableSection::logicalRectForWritingModeAndDirection(const LayoutRect& rect) const
+{
+    LayoutRect tableAlignedRect(rect);
+
+    flipForWritingMode(tableAlignedRect);
+
+    if (!style()->isHorizontalWritingMode())
+        tableAlignedRect = tableAlignedRect.transposedRect();
+
+    const Vector<int>& columnPos = table()->columnPositions();
+    // FIXME: The table's direction should determine our row's direction, not the section's (see bug 96691).
+    if (!style()->isLeftToRightDirection())
+        tableAlignedRect.setX(columnPos[columnPos.size() - 1] - tableAlignedRect.maxX());
+
+    return tableAlignedRect;
+}
+
+CellSpan RenderTableSection::dirtiedRows(const LayoutRect& damageRect) const
+{
+    if (m_forceSlowPaintPathWithOverflowingCell) 
+        return fullTableRowSpan();
+
+    CellSpan coveredRows = spannedRows(damageRect);
+
+    // To repaint the border we might need to repaint first or last row even if they are not spanned themselves.
+    if (coveredRows.start() >= m_rowPos.size() - 1 && m_rowPos[m_rowPos.size() - 1] + table()->outerBorderAfter() >= damageRect.y())
+        --coveredRows.start();
+
+    if (!coveredRows.end() && m_rowPos[0] - table()->outerBorderBefore() <= damageRect.maxY())
+        ++coveredRows.end();
+
+    return coveredRows;
+}
+
+CellSpan RenderTableSection::dirtiedColumns(const LayoutRect& damageRect) const
+{
+    if (m_forceSlowPaintPathWithOverflowingCell) 
+        return fullTableColumnSpan();
+
+    CellSpan coveredColumns = spannedColumns(damageRect);
+
+    const Vector<int>& columnPos = table()->columnPositions();
+    // To repaint the border we might need to repaint first or last column even if they are not spanned themselves.
+    if (coveredColumns.start() >= columnPos.size() - 1 && columnPos[columnPos.size() - 1] + table()->outerBorderEnd() >= damageRect.x())
+        --coveredColumns.start();
+
+    if (!coveredColumns.end() && columnPos[0] - table()->outerBorderStart() <= damageRect.maxX())
+        ++coveredColumns.end();
+
+    return coveredColumns;
+}
+
+CellSpan RenderTableSection::spannedRows(const LayoutRect& flippedRect) const
+{
+    // Find the first row that starts after rect top.
+    unsigned nextRow = std::upper_bound(m_rowPos.begin(), m_rowPos.end(), flippedRect.y()) - m_rowPos.begin();
+
+    if (nextRow == m_rowPos.size())
+        return CellSpan(m_rowPos.size() - 1, m_rowPos.size() - 1); // After all rows.
+
+    unsigned startRow = nextRow > 0 ? nextRow - 1 : 0;
+
+    // Find the first row that starts after rect bottom.
+    unsigned endRow;
+    if (m_rowPos[nextRow] >= flippedRect.maxY())
+        endRow = nextRow;
+    else {
+        endRow = std::upper_bound(m_rowPos.begin() + nextRow, m_rowPos.end(), flippedRect.maxY()) - m_rowPos.begin();
+        if (endRow == m_rowPos.size())
+            endRow = m_rowPos.size() - 1;
+    }
+
+    return CellSpan(startRow, endRow);
+}
+
+CellSpan RenderTableSection::spannedColumns(const LayoutRect& flippedRect) const
+{
+    const Vector<int>& columnPos = table()->columnPositions();
+
+    // Find the first column that starts after rect left.
+    // lower_bound doesn't handle the edge between two cells properly as it would wrongly return the
+    // cell on the logical top/left.
+    // upper_bound on the other hand properly returns the cell on the logical bottom/right, which also
+    // matches the behavior of other browsers.
+    unsigned nextColumn = std::upper_bound(columnPos.begin(), columnPos.end(), flippedRect.x()) - columnPos.begin();
+
+    if (nextColumn == columnPos.size())
+        return CellSpan(columnPos.size() - 1, columnPos.size() - 1); // After all columns.
+
+    unsigned startColumn = nextColumn > 0 ? nextColumn - 1 : 0;
+
+    // Find the first column that starts after rect right.
+    unsigned endColumn;
+    if (columnPos[nextColumn] >= flippedRect.maxX())
+        endColumn = nextColumn;
+    else {
+        endColumn = std::upper_bound(columnPos.begin() + nextColumn, columnPos.end(), flippedRect.maxX()) - columnPos.begin();
+        if (endColumn == columnPos.size())
+            endColumn = columnPos.size() - 1;
+    }
+
+    return CellSpan(startColumn, endColumn);
+}
+
+
+void RenderTableSection::paintObject(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    PaintPhase paintPhase = paintInfo.phase;
+
+    LayoutRect localRepaintRect = paintInfo.rect;
+    localRepaintRect.moveBy(-paintOffset);
+    localRepaintRect.inflate(maximalOutlineSize(paintPhase));
+
+    LayoutRect tableAlignedRect = logicalRectForWritingModeAndDirection(localRepaintRect);
+
+    CellSpan dirtiedRows = this->dirtiedRows(tableAlignedRect);
+    CellSpan dirtiedColumns = this->dirtiedColumns(tableAlignedRect);
+
+    if (dirtiedColumns.start() < dirtiedColumns.end()) {
+        if (!m_hasMultipleCellLevels && !m_overflowingCells.size()) {
+            if (paintInfo.phase == PaintPhaseCollapsedTableBorders) {
+                // Collapsed borders are painted from the bottom right to the top left so that precedence
+                // due to cell position is respected.
+                for (unsigned r = dirtiedRows.end(); r > dirtiedRows.start(); r--) {
+                    unsigned row = r - 1;
+                    for (unsigned c = dirtiedColumns.end(); c > dirtiedColumns.start(); c--) {
+                        unsigned col = c - 1;
+                        CellStruct& current = cellAt(row, col);
+                        RenderTableCell* cell = current.primaryCell();
+                        if (!cell || (row > dirtiedRows.start() && primaryCellAt(row - 1, col) == cell) || (col > dirtiedColumns.start() && primaryCellAt(row, col - 1) == cell))
+                            continue;
+                        LayoutPoint cellPoint = flipForWritingModeForChild(cell, paintOffset);
+                        cell->paintCollapsedBorders(paintInfo, cellPoint);
+                    }
+                }
+            } else {
+                // Draw the dirty cells in the order that they appear.
+                for (unsigned r = dirtiedRows.start(); r < dirtiedRows.end(); r++) {
+                    RenderTableRow* row = m_grid[r].rowRenderer;
+                    if (row && !row->hasSelfPaintingLayer())
+                        row->paintOutlineForRowIfNeeded(paintInfo, paintOffset);
+                    for (unsigned c = dirtiedColumns.start(); c < dirtiedColumns.end(); c++) {
+                        CellStruct& current = cellAt(r, c);
+                        RenderTableCell* cell = current.primaryCell();
+                        if (!cell || (r > dirtiedRows.start() && primaryCellAt(r - 1, c) == cell) || (c > dirtiedColumns.start() && primaryCellAt(r, c - 1) == cell))
+                            continue;
+                        paintCell(cell, paintInfo, paintOffset);
+                    }
+                }
+            }
+        } else {
+            // The overflowing cells should be scarce to avoid adding a lot of cells to the HashSet.
+#ifndef NDEBUG
+            unsigned totalRows = m_grid.size();
+            unsigned totalCols = table()->columns().size();
+            ASSERT(m_overflowingCells.size() < totalRows * totalCols * gMaxAllowedOverflowingCellRatioForFastPaintPath);
+#endif
+
+            // To make sure we properly repaint the section, we repaint all the overflowing cells that we collected.
+            Vector<RenderTableCell*> cells;
+            copyToVector(m_overflowingCells, cells);
+
+            HashSet<RenderTableCell*> spanningCells;
+
+            for (unsigned r = dirtiedRows.start(); r < dirtiedRows.end(); r++) {
+                RenderTableRow* row = m_grid[r].rowRenderer;
+                if (row && !row->hasSelfPaintingLayer())
+                    row->paintOutlineForRowIfNeeded(paintInfo, paintOffset);
+                for (unsigned c = dirtiedColumns.start(); c < dirtiedColumns.end(); c++) {
+                    CellStruct& current = cellAt(r, c);
+                    if (!current.hasCells())
+                        continue;
+                    for (unsigned i = 0; i < current.cells.size(); ++i) {
+                        if (m_overflowingCells.contains(current.cells[i]))
+                            continue;
+
+                        if (current.cells[i]->rowSpan() > 1 || current.cells[i]->colSpan() > 1) {
+                            if (spanningCells.contains(current.cells[i]))
+                                continue;
+                            spanningCells.add(current.cells[i]);
+                        }
+
+                        cells.append(current.cells[i]);
+                    }
+                }
+            }
+
+            // Sort the dirty cells by paint order.
+            if (!m_overflowingCells.size())
+                std::stable_sort(cells.begin(), cells.end(), compareCellPositions);
+            else
+                std::sort(cells.begin(), cells.end(), compareCellPositionsWithOverflowingCells);
+
+            if (paintInfo.phase == PaintPhaseCollapsedTableBorders) {
+                for (unsigned i = cells.size(); i > 0; --i) {
+                    LayoutPoint cellPoint = flipForWritingModeForChild(cells[i - 1], paintOffset);
+                    cells[i - 1]->paintCollapsedBorders(paintInfo, cellPoint);
+                }
+            } else {
+                for (unsigned i = 0; i < cells.size(); ++i)
+                    paintCell(cells[i], paintInfo, paintOffset);
+            }
+        }
+    }
+}
+
+void RenderTableSection::imageChanged(WrappedImagePtr, const IntRect*)
+{
+    // FIXME: Examine cells and repaint only the rect the image paints in.
+    repaint();
+}
+
+void RenderTableSection::recalcCells()
+{
+    ASSERT(m_needsCellRecalc);
+    // We reset the flag here to ensure that |addCell| works. This is safe to do as
+    // fillRowsWithDefaultStartingAtPosition makes sure we match the table's columns
+    // representation.
+    m_needsCellRecalc = false;
+
+    m_cCol = 0;
+    m_cRow = 0;
+    m_grid.clear();
+
+    for (RenderObject* row = firstChild(); row; row = row->nextSibling()) {
+        if (row->isTableRow()) {
+            unsigned insertionRow = m_cRow;
+            m_cRow++;
+            m_cCol = 0;
+            ensureRows(m_cRow);
+
+            RenderTableRow* tableRow = toRenderTableRow(row);
+            m_grid[insertionRow].rowRenderer = tableRow;
+            tableRow->setRowIndex(insertionRow);
+            setRowLogicalHeightToRowStyleLogicalHeightIfNotRelative(m_grid[insertionRow]);
+
+            for (RenderObject* cell = row->firstChild(); cell; cell = cell->nextSibling()) {
+                if (!cell->isTableCell())
+                    continue;
+
+                RenderTableCell* tableCell = toRenderTableCell(cell);
+                addCell(tableCell, tableRow);
+            }
+        }
+    }
+
+    m_grid.shrinkToFit();
+    setNeedsLayout(true);
+}
+
+// FIXME: This function could be made O(1) in certain cases (like for the non-most-constrainive cells' case).
+void RenderTableSection::rowLogicalHeightChanged(unsigned rowIndex)
+{
+    if (needsCellRecalc())
+        return;
+
+    setRowLogicalHeightToRowStyleLogicalHeightIfNotRelative(m_grid[rowIndex]);
+
+    for (RenderObject* cell = m_grid[rowIndex].rowRenderer->firstChild(); cell; cell = cell->nextSibling()) {
+        if (!cell->isTableCell())
+            continue;
+
+        updateLogicalHeightForCell(m_grid[rowIndex], toRenderTableCell(cell));
+    }
+}
+
+void RenderTableSection::setNeedsCellRecalc()
+{
+    m_needsCellRecalc = true;
+    if (RenderTable* t = table())
+        t->setNeedsSectionRecalc();
+}
+
+unsigned RenderTableSection::numColumns() const
+{
+    unsigned result = 0;
+    
+    for (unsigned r = 0; r < m_grid.size(); ++r) {
+        for (unsigned c = result; c < table()->numEffCols(); ++c) {
+            const CellStruct& cell = cellAt(r, c);
+            if (cell.hasCells() || cell.inColSpan)
+                result = c;
+        }
+    }
+    
+    return result + 1;
+}
+
+const BorderValue& RenderTableSection::borderAdjoiningStartCell(const RenderTableCell* cell) const
+{
+    ASSERT(cell->isFirstOrLastCellInRow());
+    return hasSameDirectionAs(cell) ? style()->borderStart() : style()->borderEnd();
+}
+
+const BorderValue& RenderTableSection::borderAdjoiningEndCell(const RenderTableCell* cell) const
+{
+    ASSERT(cell->isFirstOrLastCellInRow());
+    return hasSameDirectionAs(cell) ? style()->borderEnd() : style()->borderStart();
+}
+
+const RenderTableCell* RenderTableSection::firstRowCellAdjoiningTableStart() const
+{
+    unsigned adjoiningStartCellColumnIndex = hasSameDirectionAs(table()) ? 0 : table()->lastColumnIndex();
+    return cellAt(0, adjoiningStartCellColumnIndex).primaryCell();
+}
+
+const RenderTableCell* RenderTableSection::firstRowCellAdjoiningTableEnd() const
+{
+    unsigned adjoiningEndCellColumnIndex = hasSameDirectionAs(table()) ? table()->lastColumnIndex() : 0;
+    return cellAt(0, adjoiningEndCellColumnIndex).primaryCell();
+}
+
+void RenderTableSection::appendColumn(unsigned pos)
+{
+    ASSERT(!m_needsCellRecalc);
+
+    for (unsigned row = 0; row < m_grid.size(); ++row)
+        m_grid[row].row.resize(pos + 1);
+}
+
+void RenderTableSection::splitColumn(unsigned pos, unsigned first)
+{
+    ASSERT(!m_needsCellRecalc);
+
+    if (m_cCol > pos)
+        m_cCol++;
+    for (unsigned row = 0; row < m_grid.size(); ++row) {
+        Row& r = m_grid[row].row;
+        r.insert(pos + 1, CellStruct());
+        if (r[pos].hasCells()) {
+            r[pos + 1].cells.append(r[pos].cells);
+            RenderTableCell* cell = r[pos].primaryCell();
+            ASSERT(cell);
+            ASSERT(cell->colSpan() >= (r[pos].inColSpan ? 1u : 0));
+            unsigned colleft = cell->colSpan() - r[pos].inColSpan;
+            if (first > colleft)
+              r[pos + 1].inColSpan = 0;
+            else
+              r[pos + 1].inColSpan = first + r[pos].inColSpan;
+        } else {
+            r[pos + 1].inColSpan = 0;
+        }
+    }
+}
+
+// Hit Testing
+bool RenderTableSection::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action)
+{
+    // If we have no children then we have nothing to do.
+    if (!firstChild())
+        return false;
+
+    // Table sections cannot ever be hit tested.  Effectively they do not exist.
+    // Just forward to our children always.
+    LayoutPoint adjustedLocation = accumulatedOffset + location();
+
+    if (hasOverflowClip() && !locationInContainer.intersects(overflowClipRect(adjustedLocation, locationInContainer.region())))
+        return false;
+
+    if (hasOverflowingCell()) {
+        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->isBox() && !toRenderBox(child)->hasSelfPaintingLayer()) {
+                LayoutPoint childPoint = flipForWritingModeForChild(toRenderBox(child), adjustedLocation);
+                if (child->nodeAtPoint(request, result, locationInContainer, childPoint, action)) {
+                    updateHitTestResult(result, toLayoutPoint(locationInContainer.point() - childPoint));
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    recalcCellsIfNeeded();
+
+    LayoutRect hitTestRect = locationInContainer.boundingBox();
+    hitTestRect.moveBy(-adjustedLocation);
+
+    LayoutRect tableAlignedRect = logicalRectForWritingModeAndDirection(hitTestRect);
+    CellSpan rowSpan = spannedRows(tableAlignedRect);
+    CellSpan columnSpan = spannedColumns(tableAlignedRect);
+
+    // Now iterate over the spanned rows and columns.
+    for (unsigned hitRow = rowSpan.start(); hitRow < rowSpan.end(); ++hitRow) {
+        for (unsigned hitColumn = columnSpan.start(); hitColumn < columnSpan.end(); ++hitColumn) {
+            CellStruct& current = cellAt(hitRow, hitColumn);
+
+            // If the cell is empty, there's nothing to do
+            if (!current.hasCells())
+                continue;
+
+            for (unsigned i = current.cells.size() ; i; ) {
+                --i;
+                RenderTableCell* cell = current.cells[i];
+                LayoutPoint cellPoint = flipForWritingModeForChild(cell, adjustedLocation);
+                if (static_cast<RenderObject*>(cell)->nodeAtPoint(request, result, locationInContainer, cellPoint, action)) {
+                    updateHitTestResult(result, locationInContainer.point() - toLayoutSize(cellPoint));
+                    return true;
+                }
+            }
+            if (!result.isRectBasedTest())
+                break;
+        }
+        if (!result.isRectBasedTest())
+            break;
+    }
+
+    return false;
+}
+
+void RenderTableSection::removeCachedCollapsedBorders(const RenderTableCell* cell)
+{
+    if (!table()->collapseBorders())
+        return;
+    
+    for (int side = CBSBefore; side <= CBSEnd; ++side)
+        m_cellsCollapsedBorders.remove(make_pair(cell, side));
+}
+
+void RenderTableSection::setCachedCollapsedBorder(const RenderTableCell* cell, CollapsedBorderSide side, CollapsedBorderValue border)
+{
+    ASSERT(table()->collapseBorders());
+    m_cellsCollapsedBorders.set(make_pair(cell, side), border);
+}
+
+CollapsedBorderValue& RenderTableSection::cachedCollapsedBorder(const RenderTableCell* cell, CollapsedBorderSide side)
+{
+    ASSERT(table()->collapseBorders());
+    HashMap<pair<const RenderTableCell*, int>, CollapsedBorderValue>::iterator it = m_cellsCollapsedBorders.find(make_pair(cell, side));
+    ASSERT(it != m_cellsCollapsedBorders.end());
+    return it->value;
+}
+
+RenderTableSection* RenderTableSection::createAnonymousWithParentRenderer(const RenderObject* parent)
+{
+    RefPtr<RenderStyle> newStyle = RenderStyle::createAnonymousStyleWithDisplay(parent->style(), TABLE_ROW_GROUP);
+    RenderTableSection* newSection = new (parent->renderArena()) RenderTableSection(0);
+    newSection->setDocumentForAnonymous(parent->document());
+    newSection->setStyle(newStyle.release());
+    return newSection;
+}
+
+void RenderTableSection::setLogicalPositionForCell(RenderTableCell* cell, unsigned effectiveColumn) const
+{
+    LayoutPoint oldCellLocation = cell->location();
+
+    LayoutPoint cellLocation(0, m_rowPos[cell->rowIndex()]);
+    int horizontalBorderSpacing = table()->hBorderSpacing();
+
+    // FIXME: The table's direction should determine our row's direction, not the section's (see bug 96691).
+    if (!style()->isLeftToRightDirection())
+        cellLocation.setX(table()->columnPositions()[table()->numEffCols()] - table()->columnPositions()[table()->colToEffCol(cell->col() + cell->colSpan())] + horizontalBorderSpacing);
+    else
+        cellLocation.setX(table()->columnPositions()[effectiveColumn] + horizontalBorderSpacing);
+
+    cell->setLogicalLocation(cellLocation);
+    view()->addLayoutDelta(oldCellLocation - cell->location());
+}
+
+void RenderTableSection::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, PlatformMemoryTypes::Rendering);
+    RenderBox::reportMemoryUsage(memoryObjectInfo);
+    info.addMember(m_children, "children");
+    info.addMember(m_grid, "grid");
+    info.addMember(m_rowPos, "rowPos");
+    info.addMember(m_overflowingCells, "overflowingCells");
+    info.addMember(m_cellsCollapsedBorders, "cellsCollapsedBorders");
+}
+
+void RenderTableSection::RowStruct::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, PlatformMemoryTypes::Rendering);
+    info.addMember(row, "row");
+    info.addMember(rowRenderer, "rowRenderer");
+    info.addMember(logicalHeight, "logicalHeight");
+}
+
+void RenderTableSection::CellStruct::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, PlatformMemoryTypes::Rendering);
+    info.addMember(cells, "cells");
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderTableSection.h b/Source/core/rendering/RenderTableSection.h
new file mode 100644
index 0000000..0a0cca3
--- /dev/null
+++ b/Source/core/rendering/RenderTableSection.h
@@ -0,0 +1,300 @@
+/*
+ * Copyright (C) 1997 Martin Jones (mjones@kde.org)
+ *           (C) 1997 Torben Weis (weis@kde.org)
+ *           (C) 1998 Waldo Bastian (bastian@kde.org)
+ *           (C) 1999 Lars Knoll (knoll@kde.org)
+ *           (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * Copyright (C) 2003, 2004, 2005, 2006, 2009 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 RenderTableSection_h
+#define RenderTableSection_h
+
+#include "core/rendering/RenderTable.h"
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+enum CollapsedBorderSide {
+    CBSBefore,
+    CBSAfter,
+    CBSStart,
+    CBSEnd
+};
+
+// Helper class for paintObject.
+class CellSpan {
+public:
+    CellSpan(unsigned start, unsigned end)
+        : m_start(start)
+        , m_end(end)
+    {
+    }
+
+    unsigned start() const { return m_start; }
+    unsigned end() const { return m_end; }
+
+    unsigned& start() { return m_start; }
+    unsigned& end() { return m_end; }
+
+private:
+    unsigned m_start;
+    unsigned m_end;
+};
+
+class RenderTableCell;
+class RenderTableRow;
+
+class RenderTableSection FINAL : public RenderBox {
+public:
+    RenderTableSection(Element*);
+    virtual ~RenderTableSection();
+
+    RenderObject* firstChild() const { ASSERT(children() == virtualChildren()); return children()->firstChild(); }
+    RenderObject* lastChild() const { ASSERT(children() == virtualChildren()); return children()->lastChild(); }
+
+    const RenderObjectChildList* children() const { return &m_children; }
+    RenderObjectChildList* children() { return &m_children; }
+
+    virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0);
+
+    virtual int firstLineBoxBaseline() const OVERRIDE;
+
+    void addCell(RenderTableCell*, RenderTableRow* row);
+
+    int calcRowLogicalHeight();
+    void layoutRows();
+    void computeOverflowFromCells();
+
+    RenderTable* table() const { return toRenderTable(parent()); }
+
+    struct CellStruct {
+        Vector<RenderTableCell*, 1> cells; 
+        bool inColSpan; // true for columns after the first in a colspan
+
+        CellStruct()
+            : inColSpan(false)
+        {
+        }
+
+        RenderTableCell* primaryCell()
+        {
+            return hasCells() ? cells[cells.size() - 1] : 0;
+        }
+
+        const RenderTableCell* primaryCell() const
+        {
+            return hasCells() ? cells[cells.size() - 1] : 0;
+        }
+
+        bool hasCells() const { return cells.size() > 0; }
+
+        void reportMemoryUsage(MemoryObjectInfo*) const;
+    };
+
+    typedef Vector<CellStruct> Row;
+
+    struct RowStruct {
+        RowStruct()
+            : rowRenderer(0)
+            , baseline()
+        {
+        }
+
+        void reportMemoryUsage(MemoryObjectInfo*) const;
+
+        Row row;
+        RenderTableRow* rowRenderer;
+        LayoutUnit baseline;
+        Length logicalHeight;
+    };
+
+    const BorderValue& borderAdjoiningTableStart() const
+    {
+        if (hasSameDirectionAs(table()))
+            return style()->borderStart();
+
+        return style()->borderEnd();
+    }
+
+    const BorderValue& borderAdjoiningTableEnd() const
+    {
+        if (hasSameDirectionAs(table()))
+            return style()->borderEnd();
+
+        return style()->borderStart();
+    }
+
+    const BorderValue& borderAdjoiningStartCell(const RenderTableCell*) const;
+    const BorderValue& borderAdjoiningEndCell(const RenderTableCell*) const;
+
+    const RenderTableCell* firstRowCellAdjoiningTableStart() const;
+    const RenderTableCell* firstRowCellAdjoiningTableEnd() const;
+
+    CellStruct& cellAt(unsigned row,  unsigned col) { return m_grid[row].row[col]; }
+    const CellStruct& cellAt(unsigned row, unsigned col) const { return m_grid[row].row[col]; }
+    RenderTableCell* primaryCellAt(unsigned row, unsigned col)
+    {
+        CellStruct& c = m_grid[row].row[col];
+        return c.primaryCell();
+    }
+
+    RenderTableRow* rowRendererAt(unsigned row) const { return m_grid[row].rowRenderer; }
+
+    void appendColumn(unsigned pos);
+    void splitColumn(unsigned pos, unsigned first);
+
+    int calcOuterBorderBefore() const;
+    int calcOuterBorderAfter() const;
+    int calcOuterBorderStart() const;
+    int calcOuterBorderEnd() const;
+    void recalcOuterBorder();
+
+    int outerBorderBefore() const { return m_outerBorderBefore; }
+    int outerBorderAfter() const { return m_outerBorderAfter; }
+    int outerBorderStart() const { return m_outerBorderStart; }
+    int outerBorderEnd() const { return m_outerBorderEnd; }
+
+    unsigned numRows() const { return m_grid.size(); }
+    unsigned numColumns() const;
+    void recalcCells();
+    void recalcCellsIfNeeded()
+    {
+        if (m_needsCellRecalc)
+            recalcCells();
+    }
+
+    bool needsCellRecalc() const { return m_needsCellRecalc; }
+    void setNeedsCellRecalc();
+
+    LayoutUnit rowBaseline(unsigned row) { return m_grid[row].baseline; }
+
+    void rowLogicalHeightChanged(unsigned rowIndex);
+
+    void removeCachedCollapsedBorders(const RenderTableCell*);
+    void setCachedCollapsedBorder(const RenderTableCell*, CollapsedBorderSide, CollapsedBorderValue);
+    CollapsedBorderValue& cachedCollapsedBorder(const RenderTableCell*, CollapsedBorderSide);
+
+    // distributeExtraLogicalHeightToRows methods return the *consumed* extra logical height.
+    // FIXME: We may want to introduce a structure holding the in-flux layout information.
+    int distributeExtraLogicalHeightToRows(int extraLogicalHeight);
+
+    static RenderTableSection* createAnonymousWithParentRenderer(const RenderObject*);
+    virtual RenderBox* createAnonymousBoxWithSameTypeAs(const RenderObject* parent) const OVERRIDE
+    {
+        return createAnonymousWithParentRenderer(parent);
+    }
+    
+    virtual void paint(PaintInfo&, const LayoutPoint&) OVERRIDE;
+
+    virtual void reportMemoryUsage(MemoryObjectInfo*) const OVERRIDE;
+
+protected:
+    virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+
+private:
+    virtual RenderObjectChildList* virtualChildren() { return children(); }
+    virtual const RenderObjectChildList* virtualChildren() const { return children(); }
+
+    virtual const char* renderName() const { return (isAnonymous() || isPseudoElement()) ? "RenderTableSection (anonymous)" : "RenderTableSection"; }
+
+    virtual bool isTableSection() const { return true; }
+
+    virtual void willBeRemovedFromTree() OVERRIDE;
+
+    virtual void layout();
+
+    virtual void paintCell(RenderTableCell*, PaintInfo&, const LayoutPoint&);
+    virtual void paintObject(PaintInfo&, const LayoutPoint&);
+
+    virtual void imageChanged(WrappedImagePtr, const IntRect* = 0);
+
+    virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
+
+    void ensureRows(unsigned);
+
+    void distributeExtraLogicalHeightToPercentRows(int& extraLogicalHeight, int totalPercent);
+    void distributeExtraLogicalHeightToAutoRows(int& extraLogicalHeight, unsigned autoRowsCount);
+    void distributeRemainingExtraLogicalHeight(int& extraLogicalHeight);
+
+    bool hasOverflowingCell() const { return m_overflowingCells.size() || m_forceSlowPaintPathWithOverflowingCell; }
+    void computeOverflowFromCells(unsigned totalRows, unsigned nEffCols);
+
+    CellSpan fullTableRowSpan() const { return CellSpan(0, m_grid.size()); }
+    CellSpan fullTableColumnSpan() const { return CellSpan(0, table()->columns().size()); }
+
+    // Flip the rect so it aligns with the coordinates used by the rowPos and columnPos vectors.
+    LayoutRect logicalRectForWritingModeAndDirection(const LayoutRect&) const;
+
+    CellSpan dirtiedRows(const LayoutRect& repaintRect) const;
+    CellSpan dirtiedColumns(const LayoutRect& repaintRect) const;
+
+    // These two functions take a rectangle as input that has been flipped by logicalRectForWritingModeAndDirection.
+    // The returned span of rows or columns is end-exclusive, and empty if start==end.
+    CellSpan spannedRows(const LayoutRect& flippedRect) const;
+    CellSpan spannedColumns(const LayoutRect& flippedRect) const;
+
+    void setLogicalPositionForCell(RenderTableCell*, unsigned effectiveColumn) const;
+
+    RenderObjectChildList m_children;
+
+    Vector<RowStruct> m_grid;
+    Vector<int> m_rowPos;
+
+    // the current insertion position
+    unsigned m_cCol;
+    unsigned m_cRow;
+
+    int m_outerBorderStart;
+    int m_outerBorderEnd;
+    int m_outerBorderBefore;
+    int m_outerBorderAfter;
+
+    bool m_needsCellRecalc;
+
+    // This HashSet holds the overflowing cells for faster painting.
+    // If we have more than gMaxAllowedOverflowingCellRatio * total cells, it will be empty
+    // and m_forceSlowPaintPathWithOverflowingCell will be set to save memory.
+    HashSet<RenderTableCell*> m_overflowingCells;
+    bool m_forceSlowPaintPathWithOverflowingCell;
+
+    bool m_hasMultipleCellLevels;
+
+    // This map holds the collapsed border values for cells with collapsed borders.
+    // It is held at RenderTableSection level to spare memory consumption by table cells.
+    HashMap<pair<const RenderTableCell*, int>, CollapsedBorderValue > m_cellsCollapsedBorders;
+};
+
+inline RenderTableSection* toRenderTableSection(RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isTableSection());
+    return static_cast<RenderTableSection*>(object);
+}
+
+inline const RenderTableSection* toRenderTableSection(const RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isTableSection());
+    return static_cast<const RenderTableSection*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderTableSection(const RenderTableSection*);
+
+} // namespace WebCore
+
+#endif // RenderTableSection_h
diff --git a/Source/core/rendering/RenderText.cpp b/Source/core/rendering/RenderText.cpp
new file mode 100644
index 0000000..c26fe49
--- /dev/null
+++ b/Source/core/rendering/RenderText.cpp
@@ -0,0 +1,1935 @@
+/*
+ * (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Andrew Wellington (proton@wiretapped.net)
+ * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com)
+ *
+ * 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 "core/rendering/RenderText.h"
+
+#include "core/accessibility/AXObjectCache.h"
+#include "core/dom/Range.h"
+#include "core/dom/Text.h"
+#include "core/dom/WebCoreMemoryInstrumentation.h"
+#include "core/editing/VisiblePosition.h"
+#include "core/loader/TextResourceDecoder.h"
+#include "core/page/FrameView.h"
+#include "core/page/Settings.h"
+#include "core/platform/graphics/FloatQuad.h"
+#include "core/platform/text/Hyphenation.h"
+#include "core/platform/text/TextBreakIterator.h"
+#include "core/platform/text/transcoder/FontTranscoder.h"
+#include "core/rendering/EllipsisBox.h"
+#include "core/rendering/InlineTextBox.h"
+#include "core/rendering/RenderArena.h"
+#include "core/rendering/RenderBlock.h"
+#include "core/rendering/RenderCombineText.h"
+#include "core/rendering/RenderLayer.h"
+#include "core/rendering/RenderView.h"
+#include "core/rendering/break_lines.h"
+#include <wtf/text/StringBuffer.h>
+#include <wtf/unicode/CharacterNames.h>
+
+using namespace std;
+using namespace WTF;
+using namespace Unicode;
+
+namespace WebCore {
+
+struct SameSizeAsRenderText : public RenderObject {
+    uint32_t bitfields : 16;
+    float widths[4];
+    String text;
+    void* pointers[2];
+};
+
+COMPILE_ASSERT(sizeof(RenderText) == sizeof(SameSizeAsRenderText), RenderText_should_stay_small);
+
+class SecureTextTimer;
+typedef HashMap<RenderText*, SecureTextTimer*> SecureTextTimerMap;
+static SecureTextTimerMap* gSecureTextTimers = 0;
+
+class SecureTextTimer : public TimerBase {
+public:
+    SecureTextTimer(RenderText* renderText)
+        : m_renderText(renderText)
+        , m_lastTypedCharacterOffset(-1)
+    {
+    }
+
+    void restartWithNewText(unsigned lastTypedCharacterOffset)
+    {
+        m_lastTypedCharacterOffset = lastTypedCharacterOffset;
+        if (Settings* settings = m_renderText->document()->settings())
+            startOneShot(settings->passwordEchoDurationInSeconds());
+    }
+    void invalidate() { m_lastTypedCharacterOffset = -1; }
+    unsigned lastTypedCharacterOffset() { return m_lastTypedCharacterOffset; }
+
+private:
+    virtual void fired()
+    {
+        ASSERT(gSecureTextTimers->contains(m_renderText));
+        m_renderText->setText(m_renderText->text(), true /* forcing setting text as it may be masked later */);
+    }
+
+    RenderText* m_renderText;
+    int m_lastTypedCharacterOffset;
+};
+
+static void makeCapitalized(String* string, UChar previous)
+{
+    if (string->isNull())
+        return;
+
+    unsigned length = string->length();
+    const UChar* characters = string->characters();
+
+    if (length >= numeric_limits<unsigned>::max())
+        CRASH();
+
+    StringBuffer<UChar> stringWithPrevious(length + 1);
+    stringWithPrevious[0] = previous == noBreakSpace ? ' ' : previous;
+    for (unsigned i = 1; i < length + 1; i++) {
+        // Replace &nbsp with a real space since ICU no longer treats &nbsp as a word separator.
+        if (characters[i - 1] == noBreakSpace)
+            stringWithPrevious[i] = ' ';
+        else
+            stringWithPrevious[i] = characters[i - 1];
+    }
+
+    TextBreakIterator* boundary = wordBreakIterator(stringWithPrevious.characters(), length + 1);
+    if (!boundary)
+        return;
+
+    StringBuffer<UChar> data(length);
+
+    int32_t endOfWord;
+    int32_t startOfWord = textBreakFirst(boundary);
+    for (endOfWord = textBreakNext(boundary); endOfWord != TextBreakDone; startOfWord = endOfWord, endOfWord = textBreakNext(boundary)) {
+        if (startOfWord) // Ignore first char of previous string
+            data[startOfWord - 1] = characters[startOfWord - 1] == noBreakSpace ? noBreakSpace : toTitleCase(stringWithPrevious[startOfWord]);
+        for (int i = startOfWord + 1; i < endOfWord; i++)
+            data[i - 1] = characters[i - 1];
+    }
+
+    *string = String::adopt(data);
+}
+
+RenderText::RenderText(Node* node, PassRefPtr<StringImpl> str)
+    : RenderObject(!node || node->isDocumentNode() ? 0 : node)
+    , m_hasTab(false)
+    , m_linesDirty(false)
+    , m_containsReversedText(false)
+    , m_knownToHaveNoOverflowAndNoFallbackFonts(false)
+    , m_needsTranscoding(false)
+    , m_minWidth(-1)
+    , m_maxWidth(-1)
+    , m_beginMinWidth(0)
+    , m_endMinWidth(0)
+    , m_text(str)
+    , m_firstTextBox(0)
+    , m_lastTextBox(0)
+{
+    ASSERT(m_text);
+    // FIXME: Some clients of RenderText (and subclasses) pass Document as node to create anonymous renderer.
+    // They should be switched to passing null and using setDocumentForAnonymous.
+    if (node && node->isDocumentNode())
+        setDocumentForAnonymous(toDocument(node));
+
+    m_isAllASCII = m_text.containsOnlyASCII();
+    m_canUseSimpleFontCodePath = computeCanUseSimpleFontCodePath();
+    setIsText();
+
+    view()->frameView()->incrementVisuallyNonEmptyCharacterCount(m_text.length());
+}
+
+#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::updateNeedsTranscoding()
+{
+    const TextEncoding* encoding = document()->decoder() ? &document()->decoder()->encoding() : 0;
+    m_needsTranscoding = fontTranscoder().needsTranscoding(style()->font().fontDescription(), encoding);
+}
+
+void RenderText::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
+{
+    // There is 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 == StyleDifferenceLayout) {
+        setNeedsLayoutAndPrefWidthsRecalc();
+        m_knownToHaveNoOverflowAndNoFallbackFonts = false;
+    }
+
+    RenderStyle* newStyle = style();
+    bool needsResetText = false;
+    if (!oldStyle) {
+        updateNeedsTranscoding();
+        needsResetText = m_needsTranscoding;
+    } else if (oldStyle->font().needsTranscoding() != newStyle->font().needsTranscoding() || (newStyle->font().needsTranscoding() && oldStyle->font().family().family() != newStyle->font().family().family())) {
+        updateNeedsTranscoding();
+        needsResetText = true;
+    }
+
+    ETextTransform oldTransform = oldStyle ? oldStyle->textTransform() : TTNONE;
+    ETextSecurity oldSecurity = oldStyle ? oldStyle->textSecurity() : TSNONE;
+    if (needsResetText || oldTransform != newStyle->textTransform() || oldSecurity != newStyle->textSecurity()) 
+        transformText();
+}
+
+void RenderText::removeAndDestroyTextBoxes()
+{
+    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();
+}
+
+void RenderText::willBeDestroyed()
+{
+    if (SecureTextTimer* secureTextTimer = gSecureTextTimers ? gSecureTextTimers->take(this) : 0)
+        delete secureTextTimer;
+
+    removeAndDestroyTextBoxes();
+    RenderObject::willBeDestroyed();
+}
+
+void RenderText::extractTextBox(InlineTextBox* box)
+{
+    checkConsistency();
+
+    m_lastTextBox = box->prevTextBox();
+    if (box == m_firstTextBox)
+        m_firstTextBox = 0;
+    if (box->prevTextBox())
+        box->prevTextBox()->setNextTextBox(0);
+    box->setPreviousTextBox(0);
+    for (InlineTextBox* curr = box; curr; curr = curr->nextTextBox())
+        curr->setExtracted();
+
+    checkConsistency();
+}
+
+void RenderText::attachTextBox(InlineTextBox* box)
+{
+    checkConsistency();
+
+    if (m_lastTextBox) {
+        m_lastTextBox->setNextTextBox(box);
+        box->setPreviousTextBox(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()->setPreviousTextBox(box->prevTextBox());
+    if (box->prevTextBox())
+        box->prevTextBox()->setNextTextBox(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 = node();
+    return (e && e->isTextNode()) ? toText(e)->dataImpl() : 0;
+}
+
+void RenderText::absoluteRects(Vector<IntRect>& rects, const LayoutPoint& accumulatedOffset) const
+{
+    for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox())
+        rects.append(enclosingIntRect(FloatRect(accumulatedOffset + box->topLeft(), box->size())));
+}
+
+static FloatRect localQuadForTextBox(InlineTextBox* box, unsigned start, unsigned end, bool useSelectionHeight)
+{
+    unsigned realEnd = min(box->end() + 1, end);
+    LayoutRect r = box->localSelectionRect(start, realEnd);
+    if (r.height()) {
+        if (!useSelectionHeight) {
+            // Change the height and y position (or width and x for vertical text)
+            // because selectionRect uses selection-specific values.
+            if (box->isHorizontal()) {
+                r.setHeight(box->logicalHeight());
+                r.setY(box->y());
+            } else {
+                r.setWidth(box->logicalWidth());
+                r.setX(box->x());
+            }
+        }
+        return FloatRect(r);
+    }
+    return FloatRect();
+}
+
+void RenderText::absoluteRectsForRange(Vector<IntRect>& rects, unsigned start, unsigned end, bool useSelectionHeight, bool* wasFixed)
+{
+    // 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));
+    
+    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) {
+            FloatRect r = box->calculateBoundaries();
+            if (useSelectionHeight) {
+                LayoutRect selectionRect = box->localSelectionRect(start, end);
+                if (box->isHorizontal()) {
+                    r.setHeight(selectionRect.height());
+                    r.setY(selectionRect.y());
+                } else {
+                    r.setWidth(selectionRect.width());
+                    r.setX(selectionRect.x());
+                }
+            }
+            rects.append(localToAbsoluteQuad(r, 0, wasFixed).enclosingBoundingBox());
+        } else {
+            // FIXME: This code is wrong. It's converting local to absolute twice. http://webkit.org/b/65722
+            FloatRect rect = localQuadForTextBox(box, start, end, useSelectionHeight);
+            if (!rect.isZero())
+                rects.append(localToAbsoluteQuad(rect, 0, wasFixed).enclosingBoundingBox());
+        }
+    }
+}
+
+static IntRect ellipsisRectForBox(InlineTextBox* box, unsigned startPos, unsigned endPos)
+{
+    if (!box)
+        return IntRect();
+    
+    unsigned short truncation = box->truncation();
+    if (truncation == cNoTruncation)
+        return IntRect();
+    
+    IntRect rect;
+    if (EllipsisBox* ellipsis = box->root()->ellipsisBox()) {
+        int ellipsisStartPosition = max<int>(startPos - box->start(), 0);
+        int ellipsisEndPosition = min<int>(endPos - box->start(), box->len());
+        
+        // The ellipsis should be considered to be selected if the end of
+        // the selection is past the beginning of the truncation and the
+        // beginning of the selection is before or at the beginning of the truncation.
+        if (ellipsisEndPosition >= truncation && ellipsisStartPosition <= truncation)
+            return ellipsis->selectionRect();
+    }
+    
+    return IntRect();
+}
+    
+void RenderText::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed, ClippingOption option) const
+{
+    for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) {
+        FloatRect boundaries = box->calculateBoundaries();
+
+        // Shorten the width of this text box if it ends in an ellipsis.
+        // FIXME: ellipsisRectForBox should switch to return FloatRect soon with the subpixellayout branch.
+        IntRect ellipsisRect = (option == ClipToEllipsis) ? ellipsisRectForBox(box, 0, textLength()) : IntRect();
+        if (!ellipsisRect.isEmpty()) {
+            if (style()->isHorizontalWritingMode())
+                boundaries.setWidth(ellipsisRect.maxX() - boundaries.x());
+            else
+                boundaries.setHeight(ellipsisRect.maxY() - boundaries.y());
+        }
+        quads.append(localToAbsoluteQuad(boundaries, 0, wasFixed));
+    }
+}
+    
+void RenderText::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed) const
+{
+    absoluteQuads(quads, wasFixed, NoClipping);
+}
+
+void RenderText::absoluteQuadsForRange(Vector<FloatQuad>& quads, unsigned start, unsigned end, bool useSelectionHeight, bool* wasFixed)
+{
+    // 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));
+    
+    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) {
+            FloatRect r = box->calculateBoundaries();
+            if (useSelectionHeight) {
+                LayoutRect selectionRect = box->localSelectionRect(start, end);
+                if (box->isHorizontal()) {
+                    r.setHeight(selectionRect.height());
+                    r.setY(selectionRect.y());
+                } else {
+                    r.setWidth(selectionRect.width());
+                    r.setX(selectionRect.x());
+                }
+            }
+            quads.append(localToAbsoluteQuad(r, 0, wasFixed));
+        } else {
+            FloatRect rect = localQuadForTextBox(box, start, end, useSelectionHeight);
+            if (!rect.isZero())
+                quads.append(localToAbsoluteQuad(rect, 0, wasFixed));
+        }
+    }
+}
+
+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->len();
+    while (offset > off && s->nextTextBox()) {
+        s = s->nextTextBox();
+        off = s->start() + s->len();
+    }
+    // we are now in the correct text run
+    pos = (offset > off ? s->len() : s->len() - (off - offset) );
+    return s;
+}
+
+enum ShouldAffinityBeDownstream { AlwaysDownstream, AlwaysUpstream, UpstreamIfPositionIsNotAtStart };
+
+static bool lineDirectionPointFitsInBox(int pointLineDirection, InlineTextBox* box, ShouldAffinityBeDownstream& shouldAffinityBeDownstream)
+{
+    shouldAffinityBeDownstream = AlwaysDownstream;
+
+    // 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
+    // except when box is the first box in the line
+    if (pointLineDirection <= box->logicalLeft()) {
+        shouldAffinityBeDownstream = !box->prevLeafChild() ? UpstreamIfPositionIsNotAtStart : AlwaysDownstream;
+        return true;
+    }
+
+    // and the x coordinate is to the left of the right edge of this box
+    // check to see if position goes in this box
+    if (pointLineDirection < box->logicalRight()) {
+        shouldAffinityBeDownstream = UpstreamIfPositionIsNotAtStart;
+        return true;
+    }
+
+    // box is first on line
+    // and the x coordinate is to the left of the first text box left edge
+    if (!box->prevLeafChildIgnoringLineBreak() && pointLineDirection < box->logicalLeft())
+        return true;
+
+    if (!box->nextLeafChildIgnoringLineBreak()) {
+        // 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
+        shouldAffinityBeDownstream = UpstreamIfPositionIsNotAtStart;
+        return true;
+    }
+
+    return false;
+}
+
+static VisiblePosition createVisiblePositionForBox(const InlineBox* box, int offset, ShouldAffinityBeDownstream shouldAffinityBeDownstream)
+{
+    EAffinity affinity = VP_DEFAULT_AFFINITY;
+    switch (shouldAffinityBeDownstream) {
+    case AlwaysDownstream:
+        affinity = DOWNSTREAM;
+        break;
+    case AlwaysUpstream:
+        affinity = VP_UPSTREAM_IF_POSSIBLE;
+        break;
+    case UpstreamIfPositionIsNotAtStart:
+        affinity = offset > box->caretMinOffset() ? VP_UPSTREAM_IF_POSSIBLE : DOWNSTREAM;
+        break;
+    }
+    return box->renderer()->createVisiblePosition(offset, affinity);
+}
+
+static VisiblePosition createVisiblePositionAfterAdjustingOffsetForBiDi(const InlineTextBox* box, int offset, ShouldAffinityBeDownstream shouldAffinityBeDownstream)
+{
+    ASSERT(box);
+    ASSERT(box->renderer());
+    ASSERT(offset >= 0);
+
+    if (offset && static_cast<unsigned>(offset) < box->len())
+        return createVisiblePositionForBox(box, box->start() + offset, shouldAffinityBeDownstream);
+
+    bool positionIsAtStartOfBox = !offset;
+    if (positionIsAtStartOfBox == box->isLeftToRightDirection()) {
+        // offset is on the left edge
+
+        const InlineBox* prevBox = box->prevLeafChildIgnoringLineBreak();
+        if ((prevBox && prevBox->bidiLevel() == box->bidiLevel())
+            || box->renderer()->containingBlock()->style()->direction() == box->direction()) // FIXME: left on 12CBA
+            return createVisiblePositionForBox(box, box->caretLeftmostOffset(), shouldAffinityBeDownstream);
+
+        if (prevBox && prevBox->bidiLevel() > box->bidiLevel()) {
+            // e.g. left of B in aDC12BAb
+            const InlineBox* leftmostBox;
+            do {
+                leftmostBox = prevBox;
+                prevBox = leftmostBox->prevLeafChildIgnoringLineBreak();
+            } while (prevBox && prevBox->bidiLevel() > box->bidiLevel());
+            return createVisiblePositionForBox(leftmostBox, leftmostBox->caretRightmostOffset(), shouldAffinityBeDownstream);
+        }
+
+        if (!prevBox || prevBox->bidiLevel() < box->bidiLevel()) {
+            // e.g. left of D in aDC12BAb
+            const InlineBox* rightmostBox;
+            const InlineBox* nextBox = box;
+            do {
+                rightmostBox = nextBox;
+                nextBox = rightmostBox->nextLeafChildIgnoringLineBreak();
+            } while (nextBox && nextBox->bidiLevel() >= box->bidiLevel());
+            return createVisiblePositionForBox(rightmostBox,
+                box->isLeftToRightDirection() ? rightmostBox->caretMaxOffset() : rightmostBox->caretMinOffset(), shouldAffinityBeDownstream);
+        }
+
+        return createVisiblePositionForBox(box, box->caretRightmostOffset(), shouldAffinityBeDownstream);
+    }
+
+    const InlineBox* nextBox = box->nextLeafChildIgnoringLineBreak();
+    if ((nextBox && nextBox->bidiLevel() == box->bidiLevel())
+        || box->renderer()->containingBlock()->style()->direction() == box->direction())
+        return createVisiblePositionForBox(box, box->caretRightmostOffset(), shouldAffinityBeDownstream);
+
+    // offset is on the right edge
+    if (nextBox && nextBox->bidiLevel() > box->bidiLevel()) {
+        // e.g. right of C in aDC12BAb
+        const InlineBox* rightmostBox;
+        do {
+            rightmostBox = nextBox;
+            nextBox = rightmostBox->nextLeafChildIgnoringLineBreak();
+        } while (nextBox && nextBox->bidiLevel() > box->bidiLevel());
+        return createVisiblePositionForBox(rightmostBox, rightmostBox->caretLeftmostOffset(), shouldAffinityBeDownstream);
+    }
+
+    if (!nextBox || nextBox->bidiLevel() < box->bidiLevel()) {
+        // e.g. right of A in aDC12BAb
+        const InlineBox* leftmostBox;
+        const InlineBox* prevBox = box;
+        do {
+            leftmostBox = prevBox;
+            prevBox = leftmostBox->prevLeafChildIgnoringLineBreak();
+        } while (prevBox && prevBox->bidiLevel() >= box->bidiLevel());
+        return createVisiblePositionForBox(leftmostBox,
+            box->isLeftToRightDirection() ? leftmostBox->caretMinOffset() : leftmostBox->caretMaxOffset(), shouldAffinityBeDownstream);
+    }
+
+    return createVisiblePositionForBox(box, box->caretLeftmostOffset(), shouldAffinityBeDownstream);
+}
+
+VisiblePosition RenderText::positionForPoint(const LayoutPoint& point)
+{
+    if (!firstTextBox() || textLength() == 0)
+        return createVisiblePosition(0, DOWNSTREAM);
+
+    LayoutUnit pointLineDirection = firstTextBox()->isHorizontal() ? point.x() : point.y();
+    LayoutUnit pointBlockDirection = firstTextBox()->isHorizontal() ? point.y() : point.x();
+    bool blocksAreFlipped = style()->isFlippedBlocksWritingMode();
+
+    InlineTextBox* lastBox = 0;
+    for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) {
+        if (box->isLineBreak() && !box->prevLeafChild() && box->nextLeafChild() && !box->nextLeafChild()->isLineBreak())
+            box = box->nextTextBox();
+
+        RootInlineBox* rootBox = box->root();
+        LayoutUnit top = min(rootBox->selectionTop(), rootBox->lineTop());
+        if (pointBlockDirection > top || (!blocksAreFlipped && pointBlockDirection == top)) {
+            LayoutUnit bottom = rootBox->selectionBottom();
+            if (rootBox->nextRootBox())
+                bottom = min(bottom, rootBox->nextRootBox()->lineTop());
+
+            if (pointBlockDirection < bottom || (blocksAreFlipped && pointBlockDirection == bottom)) {
+                ShouldAffinityBeDownstream shouldAffinityBeDownstream;
+                if (lineDirectionPointFitsInBox(pointLineDirection, box, shouldAffinityBeDownstream))
+                    return createVisiblePositionAfterAdjustingOffsetForBiDi(box, box->offsetForPosition(pointLineDirection), shouldAffinityBeDownstream);
+            }
+        }
+        lastBox = box;
+    }
+
+    if (lastBox) {
+        ShouldAffinityBeDownstream shouldAffinityBeDownstream;
+        lineDirectionPointFitsInBox(pointLineDirection, lastBox, shouldAffinityBeDownstream);
+        return createVisiblePositionAfterAdjustingOffsetForBiDi(lastBox, lastBox->offsetForPosition(pointLineDirection) + lastBox->start(), shouldAffinityBeDownstream);
+    }
+    return createVisiblePosition(0, DOWNSTREAM);
+}
+
+LayoutRect RenderText::localCaretRect(InlineBox* inlineBox, int caretOffset, LayoutUnit* extraWidthToEndOfLine)
+{
+    if (!inlineBox)
+        return LayoutRect();
+
+    ASSERT(inlineBox->isInlineTextBox());
+    if (!inlineBox->isInlineTextBox())
+        return LayoutRect();
+
+    InlineTextBox* box = toInlineTextBox(inlineBox);
+
+    int height = box->root()->selectionHeight();
+    int top = box->root()->selectionTop();
+
+    // Go ahead and round left to snap it to the nearest pixel.
+    float left = box->positionForOffset(caretOffset);
+
+    // Distribute the caret's width to either side of the offset.
+    int caretWidthLeftOfOffset = caretWidth / 2;
+    left -= caretWidthLeftOfOffset;
+    int caretWidthRightOfOffset = caretWidth - caretWidthLeftOfOffset;
+
+    left = roundf(left);
+
+    float rootLeft = box->root()->logicalLeft();
+    float rootRight = box->root()->logicalRight();
+
+    // 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()->logicalWidth() + rootLeft) - (left + 1);
+
+    RenderBlock* cb = containingBlock();
+    RenderStyle* cbStyle = cb->style();
+
+    float leftEdge;
+    float rightEdge;
+    leftEdge = min<float>(0, rootLeft);
+    rightEdge = max<float>(cb->logicalWidth(), rootRight);
+
+    bool rightAligned = false;
+    switch (cbStyle->textAlign()) {
+    case RIGHT:
+    case WEBKIT_RIGHT:
+        rightAligned = true;
+        break;
+    case LEFT:
+    case WEBKIT_LEFT:
+    case CENTER:
+    case WEBKIT_CENTER:
+        break;
+    case JUSTIFY:
+    case TASTART:
+        rightAligned = !cbStyle->isLeftToRightDirection();
+        break;
+    case TAEND:
+        rightAligned = cbStyle->isLeftToRightDirection();
+        break;
+    }
+
+    if (rightAligned) {
+        left = max(left, leftEdge);
+        left = min(left, rootRight - caretWidth);
+    } else {
+        left = min(left, rightEdge - caretWidthRightOfOffset);
+        left = max(left, rootLeft);
+    }
+
+    return style()->isHorizontalWritingMode() ? IntRect(left, top, caretWidth, height) : IntRect(top, left, height, caretWidth);
+}
+
+ALWAYS_INLINE float RenderText::widthFromCache(const Font& f, int start, int len, float xPos, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
+{
+    if (style()->hasTextCombine() && isCombineText()) {
+        const RenderCombineText* combineText = toRenderCombineText(this);
+        if (combineText->isCombined())
+            return combineText->combinedTextWidth(f);
+    }
+
+    if (f.isFixedPitch() && !f.isSmallCaps() && m_isAllASCII && (!glyphOverflow || !glyphOverflow->computeBounds)) {
+        float monospaceCharacterWidth = f.spaceWidth();
+        float w = 0;
+        bool isSpace;
+        ASSERT(m_text);
+        StringImpl& text = *m_text.impl();
+        for (int i = start; i < start + len; i++) {
+            char c = text[i];
+            if (c <= ' ') {
+                if (c == ' ' || c == '\n') {
+                    w += monospaceCharacterWidth;
+                    isSpace = true;
+                } else if (c == '\t') {
+                    if (style()->collapseWhiteSpace()) {
+                        w += monospaceCharacterWidth;
+                        isSpace = true;
+                    } else {
+                        w += f.tabWidth(style()->tabSize(), xPos + w);
+                        isSpace = false;
+                    }
+                } else
+                    isSpace = false;
+            } else {
+                w += monospaceCharacterWidth;
+                isSpace = false;
+            }
+            if (isSpace && i > start)
+                w += f.wordSpacing();
+        }
+        return w;
+    }
+
+    TextRun run = RenderBlock::constructTextRun(const_cast<RenderText*>(this), f, this, start, len, style());
+    run.setCharactersLength(textLength() - start);
+    ASSERT(run.charactersLength() >= run.length());
+
+    run.setCharacterScanForCodePath(!canUseSimpleFontCodePath());
+    run.setTabSize(!style()->collapseWhiteSpace(), style()->tabSize());
+    run.setXPos(xPos);
+    return f.width(run, fallbackFonts, glyphOverflow);
+}
+
+void RenderText::trimmedPrefWidths(float leadWidth,
+                                   float& beginMinW, bool& beginWS,
+                                   float& endMinW, bool& endWS,
+                                   bool& hasBreakableChar, bool& hasBreak,
+                                   float& beginMaxW, float& endMaxW,
+                                   float& minW, float& maxW, bool& stripFrontSpaces)
+{
+    bool collapseWhiteSpace = style()->collapseWhiteSpace();
+    if (!collapseWhiteSpace)
+        stripFrontSpaces = false;
+
+    if (m_hasTab || preferredLogicalWidthsDirty())
+        computePreferredLogicalWidths(leadWidth);
+
+    beginWS = !stripFrontSpaces && m_hasBeginWS;
+    endWS = m_hasEndWS;
+
+    int len = textLength();
+
+    if (!len || (stripFrontSpaces && 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;
+
+    ASSERT(m_text);
+    StringImpl& text = *m_text.impl();
+    if (text[0] == ' ' || (text[0] == '\n' && !style()->preserveNewline()) || text[0] == '\t') {
+        const Font& font = style()->font(); // FIXME: This ignores first-line.
+        if (stripFrontSpaces) {
+            const UChar space = ' ';
+            float spaceWidth = font.width(RenderBlock::constructTextRun(this, font, &space, 1, style()));
+            maxW -= spaceWidth;
+        } else
+            maxW += font.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 && text[i + linelen] != '\n')
+                linelen++;
+
+            if (linelen) {
+                endMaxW = widthFromCache(f, i, linelen, leadWidth + endMaxW, 0, 0);
+                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;
+        }
+    }
+}
+
+float RenderText::minLogicalWidth() const
+{
+    if (preferredLogicalWidthsDirty())
+        const_cast<RenderText*>(this)->computePreferredLogicalWidths(0);
+        
+    return m_minWidth;
+}
+
+float RenderText::maxLogicalWidth() const
+{
+    if (preferredLogicalWidthsDirty())
+        const_cast<RenderText*>(this)->computePreferredLogicalWidths(0);
+        
+    return m_maxWidth;
+}
+
+void RenderText::computePreferredLogicalWidths(float leadWidth)
+{
+    HashSet<const SimpleFontData*> fallbackFonts;
+    GlyphOverflow glyphOverflow;
+    computePreferredLogicalWidths(leadWidth, fallbackFonts, glyphOverflow);
+    if (fallbackFonts.isEmpty() && !glyphOverflow.left && !glyphOverflow.right && !glyphOverflow.top && !glyphOverflow.bottom)
+        m_knownToHaveNoOverflowAndNoFallbackFonts = true;
+}
+
+static inline float hyphenWidth(RenderText* renderer, const Font& font)
+{
+    RenderStyle* style = renderer->style();
+    return font.width(RenderBlock::constructTextRun(renderer, font, style->hyphenString().string(), style));
+}
+
+static float maxWordFragmentWidth(RenderText* renderer, RenderStyle* style, const Font& font, const UChar* word, int wordLength, int minimumPrefixLength, int minimumSuffixLength, int& suffixStart)
+{
+    suffixStart = 0;
+    if (wordLength <= minimumSuffixLength)
+        return 0;
+
+    Vector<int, 8> hyphenLocations;
+    int hyphenLocation = wordLength - minimumSuffixLength;
+    while ((hyphenLocation = lastHyphenLocation(word, wordLength, hyphenLocation, style->locale())) >= minimumPrefixLength)
+        hyphenLocations.append(hyphenLocation);
+
+    if (hyphenLocations.isEmpty())
+        return 0;
+
+    hyphenLocations.reverse();
+
+    float minimumFragmentWidthToConsider = font.pixelSize() * 5 / 4 + hyphenWidth(renderer, font);
+    float maxFragmentWidth = 0;
+    for (size_t k = 0; k < hyphenLocations.size(); ++k) {
+        int fragmentLength = hyphenLocations[k] - suffixStart;
+        StringBuilder fragmentWithHyphen;
+        fragmentWithHyphen.append(word + suffixStart, fragmentLength);
+        fragmentWithHyphen.append(style->hyphenString());
+
+        TextRun run = RenderBlock::constructTextRun(renderer, font, fragmentWithHyphen.characters(), fragmentWithHyphen.length(), style);
+        run.setCharactersLength(fragmentWithHyphen.length());
+        run.setCharacterScanForCodePath(!renderer->canUseSimpleFontCodePath());
+        float fragmentWidth = font.width(run);
+
+        // Narrow prefixes are ignored. See tryHyphenating in RenderBlockLineLayout.cpp.
+        if (fragmentWidth <= minimumFragmentWidthToConsider)
+            continue;
+
+        suffixStart += fragmentLength;
+        maxFragmentWidth = max(maxFragmentWidth, fragmentWidth);
+    }
+
+    return maxFragmentWidth;
+}
+
+void RenderText::computePreferredLogicalWidths(float leadWidth, HashSet<const SimpleFontData*>& fallbackFonts, GlyphOverflow& glyphOverflow)
+{
+    ASSERT(m_hasTab || preferredLogicalWidthsDirty() || !m_knownToHaveNoOverflowAndNoFallbackFonts);
+
+    m_minWidth = 0;
+    m_beginMinWidth = 0;
+    m_endMinWidth = 0;
+    m_maxWidth = 0;
+
+    if (isBR())
+        return;
+
+    float currMinWidth = 0;
+    float currMaxWidth = 0;
+    m_hasBreakableChar = false;
+    m_hasBreak = false;
+    m_hasTab = false;
+    m_hasBeginWS = false;
+    m_hasEndWS = false;
+
+    RenderStyle* styleToUse = style();
+    const Font& f = styleToUse->font(); // FIXME: This ignores first-line.
+    float wordSpacing = styleToUse->wordSpacing();
+    int len = textLength();
+    LazyLineBreakIterator breakIterator(m_text, styleToUse->locale());
+    bool needsWordSpacing = false;
+    bool ignoringSpaces = false;
+    bool isSpace = false;
+    bool firstWord = true;
+    bool firstLine = true;
+    int nextBreakable = -1;
+    int lastWordBoundary = 0;
+
+    // Non-zero only when kerning is enabled, in which case we measure words with their trailing
+    // space, then subtract its width.
+    float wordTrailingSpaceWidth = f.typesettingFeatures() & Kerning ? f.width(RenderBlock::constructTextRun(this, f, &space, 1, styleToUse)) + wordSpacing : 0;
+
+    // If automatic hyphenation is allowed, we keep track of the width of the widest word (or word
+    // fragment) encountered so far, and only try hyphenating words that are wider.
+    float maxWordWidth = numeric_limits<float>::max();
+    int minimumPrefixLength = 0;
+    int minimumSuffixLength = 0;
+    if (styleToUse->hyphens() == HyphensAuto && canHyphenate(styleToUse->locale())) {
+        maxWordWidth = 0;
+
+        // Map 'hyphenate-limit-{before,after}: auto;' to 2.
+        minimumPrefixLength = styleToUse->hyphenationLimitBefore();
+        if (minimumPrefixLength < 0)
+            minimumPrefixLength = 2;
+
+        minimumSuffixLength = styleToUse->hyphenationLimitAfter();
+        if (minimumSuffixLength < 0)
+            minimumSuffixLength = 2;
+    }
+
+    int firstGlyphLeftOverflow = -1;
+
+    bool breakAll = (styleToUse->wordBreak() == BreakAllWordBreak || styleToUse->wordBreak() == BreakWordBreak) && styleToUse->autoWrap();
+
+    for (int i = 0; i < len; i++) {
+        UChar c = characterAt(i);
+
+        bool previousCharacterIsSpace = isSpace;
+
+        bool isNewline = false;
+        if (c == '\n') {
+            if (styleToUse->preserveNewline()) {
+                m_hasBreak = true;
+                isNewline = true;
+                isSpace = false;
+            } else
+                isSpace = true;
+        } else if (c == '\t') {
+            if (!styleToUse->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 && styleToUse->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 && styleToUse->hyphens() != HyphensNone) {
+            currMaxWidth += widthFromCache(f, lastWordBoundary, i - lastWordBoundary, leadWidth + currMaxWidth, &fallbackFonts, &glyphOverflow);
+            if (firstGlyphLeftOverflow < 0)
+                firstGlyphLeftOverflow = glyphOverflow.left;
+            lastWordBoundary = i + 1;
+            continue;
+        }
+
+        bool hasBreak = breakAll || isBreakable(breakIterator, i, nextBreakable);
+        bool betweenWords = true;
+        int j = i;
+        while (c != '\n' && c != ' ' && c != '\t' && (c != softHyphen || styleToUse->hyphens() == HyphensNone)) {
+            j++;
+            if (j == len)
+                break;
+            c = characterAt(j);
+            if (isBreakable(breakIterator, j, nextBreakable) && characterAt(j - 1) != softHyphen)
+                break;
+            if (breakAll) {
+                betweenWords = false;
+                break;
+            }
+        }
+
+        int wordLen = j - i;
+        if (wordLen) {
+            bool isSpace = (j < len) && c == ' ';
+            float w;
+            if (wordTrailingSpaceWidth && isSpace)
+                w = widthFromCache(f, i, wordLen + 1, leadWidth + currMaxWidth, &fallbackFonts, &glyphOverflow) - wordTrailingSpaceWidth;
+            else {
+                w = widthFromCache(f, i, wordLen, leadWidth + currMaxWidth, &fallbackFonts, &glyphOverflow);
+                if (c == softHyphen && styleToUse->hyphens() != HyphensNone)
+                    currMinWidth += hyphenWidth(this, f);
+            }
+
+            if (w > maxWordWidth) {
+                int suffixStart;
+                float maxFragmentWidth = maxWordFragmentWidth(this, styleToUse, f, characters() + i, wordLen, minimumPrefixLength, minimumSuffixLength, suffixStart);
+
+                if (suffixStart) {
+                    float suffixWidth;
+                    if (wordTrailingSpaceWidth && isSpace)
+                        suffixWidth = widthFromCache(f, i + suffixStart, wordLen - suffixStart + 1, leadWidth + currMaxWidth, 0, 0) - wordTrailingSpaceWidth;
+                    else
+                        suffixWidth = widthFromCache(f, i + suffixStart, wordLen - suffixStart, leadWidth + currMaxWidth, 0, 0);
+
+                    maxFragmentWidth = max(maxFragmentWidth, suffixWidth);
+
+                    currMinWidth += maxFragmentWidth - w;
+                    maxWordWidth = max(maxWordWidth, maxFragmentWidth);
+                } else
+                    maxWordWidth = w;
+            }
+
+            if (firstGlyphLeftOverflow < 0)
+                firstGlyphLeftOverflow = glyphOverflow.left;
+            currMinWidth += w;
+            if (betweenWords) {
+                if (lastWordBoundary == i)
+                    currMaxWidth += w;
+                else
+                    currMaxWidth += widthFromCache(f, lastWordBoundary, j - lastWordBoundary, leadWidth + currMaxWidth, &fallbackFonts, &glyphOverflow);
+                lastWordBoundary = j;
+            }
+
+            bool isCollapsibleWhiteSpace = (j < len) && styleToUse->isCollapsibleWhiteSpace(c);
+            if (j < len && styleToUse->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 : currMinWidth;
+            }
+            m_endMinWidth = currMinWidth;
+
+            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 (!styleToUse->autoWrap())
+                        m_beginMinWidth = currMaxWidth;
+                }
+
+                if (currMaxWidth > m_maxWidth)
+                    m_maxWidth = currMaxWidth;
+                currMaxWidth = 0;
+            } else {
+                TextRun run = RenderBlock::constructTextRun(this, f, this, i, 1, styleToUse);
+                run.setCharactersLength(len - i);
+                ASSERT(run.charactersLength() >= run.length());
+                run.setTabSize(!style()->collapseWhiteSpace(), style()->tabSize());
+                run.setXPos(leadWidth + currMaxWidth);
+
+                currMaxWidth += f.width(run);
+                glyphOverflow.right = 0;
+                needsWordSpacing = isSpace && !previousCharacterIsSpace && i == len - 1;
+            }
+            ASSERT(lastWordBoundary == i);
+            lastWordBoundary++;
+        }
+    }
+
+    if (firstGlyphLeftOverflow > 0)
+        glyphOverflow.left = firstGlyphLeftOverflow;
+
+    if ((needsWordSpacing && len > 1) || (ignoringSpaces && !firstWord))
+        currMaxWidth += wordSpacing;
+
+    m_minWidth = max(currMinWidth, m_minWidth);
+    m_maxWidth = max(currMaxWidth, m_maxWidth);
+
+    if (!styleToUse->autoWrap())
+        m_minWidth = m_maxWidth;
+
+    if (styleToUse->whiteSpace() == PRE) {
+        if (firstLine)
+            m_beginMinWidth = m_maxWidth;
+        m_endMinWidth = currMaxWidth;
+    }
+
+    setPreferredLogicalWidthsDirty(false);
+}
+
+bool RenderText::isAllCollapsibleWhitespace()
+{
+    unsigned length = textLength();
+    if (is8Bit()) {
+        for (unsigned i = 0; i < length; ++i) {
+            if (!style()->isCollapsibleWhiteSpace(characters8()[i]))
+                return false;
+        }
+        return true;
+    }
+    for (unsigned i = 0; i < length; ++i) {
+        if (!style()->isCollapsibleWhiteSpace(characters16()[i]))
+            return false;
+    }
+    return true;
+}
+    
+bool RenderText::containsOnlyWhitespace(unsigned from, unsigned len) const
+{
+    ASSERT(m_text);
+    StringImpl& text = *m_text.impl();
+    unsigned currPos;
+    for (currPos = from;
+         currPos < from + len && (text[currPos] == '\n' || text[currPos] == ' ' || text[currPos] == '\t');
+         currPos++) { }
+    return currPos >= (from + len);
+}
+
+FloatPoint RenderText::firstRunOrigin() const
+{
+    return IntPoint(firstRunX(), firstRunY());
+}
+
+float RenderText::firstRunX() const
+{
+    return m_firstTextBox ? m_firstTextBox->x() : 0;
+}
+
+float RenderText::firstRunY() const
+{
+    return m_firstTextBox ? m_firstTextBox->y() : 0;
+}
+    
+void RenderText::setSelectionState(SelectionState state)
+{
+    RenderObject::setSelectionState(state);
+
+    if (canUpdateSelectionOnRootLineBoxes()) {
+        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 && startPos == endPos)
+                    startPos = endPos - 1;
+            } else if (selectionState() == SelectionEnd)
+                startPos = 0;
+
+            for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) {
+                if (box->isSelected(startPos, endPos)) {
+                    RootInlineBox* root = box->root();
+                    if (root)
+                        root->setHasSelectedChildren(true);
+                }
+            }
+        } else {
+            for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) {
+                RootInlineBox* root = box->root();
+                if (root)
+                    root->setHasSelectedChildren(state == SelectionInside);
+            }
+        }
+    }
+
+    // The containing block can be null in case of an orphaned tree.
+    RenderBlock* containingBlock = this->containingBlock();
+    if (containingBlock && !containingBlock->isRenderView())
+        containingBlock->setSelectionState(state);
+}
+
+void RenderText::setTextWithOffset(PassRefPtr<StringImpl> text, unsigned offset, unsigned len, bool force)
+{
+    if (!force && equal(m_text.impl(), text.get()))
+        return;
+
+    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()) {
+        // FIXME: This shouldn't rely on the end of a dirty line box. See https://bugs.webkit.org/show_bug.cgi?id=97264
+        // 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;
+    } else if (lastTextBox()) {
+        ASSERT(!lastRootBox);
+        firstRootBox = lastTextBox()->root();
+        firstRootBox->markDirty();
+        dirtiedLines = true;
+    }
+    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 || dirtiedLines);
+}
+
+void RenderText::transformText()
+{
+    if (RefPtr<StringImpl> textToTransform = originalText())
+        setText(textToTransform.release(), true);
+}
+
+static inline bool isInlineFlowOrEmptyText(const RenderObject* o)
+{
+    if (o->isRenderInline())
+        return true;
+    if (!o->isText())
+        return false;
+    StringImpl* text = toRenderText(o)->text();
+    if (!text)
+        return true;
+    return !text->length();
+}
+
+UChar RenderText::previousCharacter() const
+{
+    // find previous text renderer if one exists
+    const RenderObject* previousText = this;
+    while ((previousText = previousText->previousInPreOrder()))
+        if (!isInlineFlowOrEmptyText(previousText))
+            break;
+    UChar prev = ' ';
+    if (previousText && previousText->isText())
+        if (StringImpl* previousString = toRenderText(previousText)->text())
+            prev = (*previousString)[previousString->length() - 1];
+    return prev;
+}
+
+void applyTextTransform(const RenderStyle* style, String& text, UChar previousCharacter)
+{
+    if (!style)
+        return;
+
+    switch (style->textTransform()) {
+    case TTNONE:
+        break;
+    case CAPITALIZE:
+        makeCapitalized(&text, previousCharacter);
+        break;
+    case UPPERCASE:
+        text.makeUpper();
+        break;
+    case LOWERCASE:
+        text.makeLower();
+        break;
+    }
+}
+
+void RenderText::setTextInternal(PassRefPtr<StringImpl> text)
+{
+    ASSERT(text);
+    m_text = text;
+    if (m_needsTranscoding) {
+        const TextEncoding* encoding = document()->decoder() ? &document()->decoder()->encoding() : 0;
+        fontTranscoder().convert(m_text, style()->font().fontDescription(), encoding);
+    }
+    ASSERT(m_text);
+
+    if (style()) {
+        applyTextTransform(style(), m_text, previousCharacter());
+
+        // 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:
+            secureText(whiteBullet);
+            break;
+        case TSDISC:
+            secureText(bullet);
+            break;
+        case TSSQUARE:
+            secureText(blackSquare);
+        }
+    }
+
+    ASSERT(m_text);
+    ASSERT(!isBR() || (textLength() == 1 && m_text[0] == '\n'));
+
+    m_isAllASCII = m_text.containsOnlyASCII();
+    m_canUseSimpleFontCodePath = computeCanUseSimpleFontCodePath();
+}
+
+void RenderText::secureText(UChar mask)
+{
+    if (!m_text.length())
+        return;
+
+    int lastTypedCharacterOffsetToReveal = -1;
+    String revealedText;
+    SecureTextTimer* secureTextTimer = gSecureTextTimers ? gSecureTextTimers->get(this) : 0;
+    if (secureTextTimer && secureTextTimer->isActive()) {
+        lastTypedCharacterOffsetToReveal = secureTextTimer->lastTypedCharacterOffset();
+        if (lastTypedCharacterOffsetToReveal >= 0)
+            revealedText.append(m_text[lastTypedCharacterOffsetToReveal]);
+    }
+
+    m_text.fill(mask);
+    if (lastTypedCharacterOffsetToReveal >= 0) {
+        m_text.replace(lastTypedCharacterOffsetToReveal, 1, revealedText);
+        // m_text may be updated later before timer fires. We invalidate the lastTypedCharacterOffset to avoid inconsistency.
+        secureTextTimer->invalidate();
+    }
+}
+
+void RenderText::setText(PassRefPtr<StringImpl> text, bool force)
+{
+    ASSERT(text);
+
+    if (!force && equal(m_text.impl(), text.get()))
+        return;
+
+    setTextInternal(text);
+    setNeedsLayoutAndPrefWidthsRecalc();
+    m_knownToHaveNoOverflowAndNoFallbackFonts = false;
+    
+    if (AXObjectCache* cache = document()->existingAXObjectCache())
+        cache->textChanged(this);
+}
+
+String RenderText::textWithoutTranscoding() const
+{
+    // If m_text isn't transcoded or is secure, we can just return the modified text.
+    if (!m_needsTranscoding || style()->textSecurity() != TSNONE)
+        return text();
+
+    // Otherwise, we should use original text. If text-transform is
+    // specified, we should transform the text on the fly.
+    String text = originalText();
+    applyTextTransform(style(), text, previousCharacter());
+    return text;
+}
+
+void RenderText::dirtyLineBoxes(bool fullLayout)
+{
+    if (fullLayout)
+        deleteTextBoxes();
+    else if (!m_linesDirty) {
+        for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox())
+            box->dirtyLineBoxes();
+    }
+    m_linesDirty = false;
+}
+
+InlineTextBox* RenderText::createTextBox()
+{
+    return new (renderArena()) InlineTextBox(this);
+}
+
+InlineTextBox* RenderText::createInlineTextBox()
+{
+    InlineTextBox* textBox = createTextBox();
+    if (!m_firstTextBox)
+        m_firstTextBox = m_lastTextBox = textBox;
+    else {
+        m_lastTextBox->setNextTextBox(textBox);
+        textBox->setPreviousTextBox(m_lastTextBox);
+        m_lastTextBox = textBox;
+    }
+    textBox->setIsText(true);
+    return textBox;
+}
+
+void RenderText::positionLineBox(InlineBox* box)
+{
+    InlineTextBox* s = toInlineTextBox(box);
+
+    // FIXME: should not be needed!!!
+    if (!s->len()) {
+        // We want the box to be destroyed.
+        s->remove();
+        if (m_firstTextBox == s)
+            m_firstTextBox = s->nextTextBox();
+        else
+            s->prevTextBox()->setNextTextBox(s->nextTextBox());
+        if (m_lastTextBox == s)
+            m_lastTextBox = s->prevTextBox();
+        else
+            s->nextTextBox()->setPreviousTextBox(s->prevTextBox());
+        s->destroy(renderArena());
+        return;
+    }
+
+    m_containsReversedText |= !s->isLeftToRightDirection();
+}
+
+float RenderText::width(unsigned from, unsigned len, float xPos, bool firstLine, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
+{
+    if (from >= textLength())
+        return 0;
+
+    if (from + len > textLength())
+        len = textLength() - from;
+
+    return width(from, len, style(firstLine)->font(), xPos, fallbackFonts, glyphOverflow);
+}
+
+float RenderText::width(unsigned from, unsigned len, const Font& f, float xPos, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
+{
+    ASSERT(from + len <= textLength());
+    if (!textLength())
+        return 0;
+
+    float w;
+    if (&f == &style()->font()) {
+        if (!style()->preserveNewline() && !from && len == textLength() && (!glyphOverflow || !glyphOverflow->computeBounds)) {
+            if (fallbackFonts) {
+                ASSERT(glyphOverflow);
+                if (preferredLogicalWidthsDirty() || !m_knownToHaveNoOverflowAndNoFallbackFonts) {
+                    const_cast<RenderText*>(this)->computePreferredLogicalWidths(0, *fallbackFonts, *glyphOverflow);
+                    if (fallbackFonts->isEmpty() && !glyphOverflow->left && !glyphOverflow->right && !glyphOverflow->top && !glyphOverflow->bottom)
+                        m_knownToHaveNoOverflowAndNoFallbackFonts = true;
+                }
+                w = m_maxWidth;
+            } else
+                w = maxLogicalWidth();
+        } else
+            w = widthFromCache(f, from, len, xPos, fallbackFonts, glyphOverflow);
+    } else {
+        TextRun run = RenderBlock::constructTextRun(const_cast<RenderText*>(this), f, this, from, len, style());
+        run.setCharactersLength(textLength() - from);
+        ASSERT(run.charactersLength() >= run.length());
+
+        run.setCharacterScanForCodePath(!canUseSimpleFontCodePath());
+        run.setTabSize(!style()->collapseWhiteSpace(), style()->tabSize());
+        run.setXPos(xPos);
+        w = f.width(run, fallbackFonts, glyphOverflow);
+    }
+
+    return w;
+}
+
+IntRect RenderText::linesBoundingBox() const
+{
+    IntRect result;
+    
+    ASSERT(!firstTextBox() == !lastTextBox());  // Either both are null or both exist.
+    if (firstTextBox() && lastTextBox()) {
+        // Return the width of the minimal left side and the maximal right side.
+        float logicalLeftSide = 0;
+        float logicalRightSide = 0;
+        for (InlineTextBox* curr = firstTextBox(); curr; curr = curr->nextTextBox()) {
+            if (curr == firstTextBox() || curr->logicalLeft() < logicalLeftSide)
+                logicalLeftSide = curr->logicalLeft();
+            if (curr == firstTextBox() || curr->logicalRight() > logicalRightSide)
+                logicalRightSide = curr->logicalRight();
+        }
+        
+        bool isHorizontal = style()->isHorizontalWritingMode();
+        
+        float x = isHorizontal ? logicalLeftSide : firstTextBox()->x();
+        float y = isHorizontal ? firstTextBox()->y() : logicalLeftSide;
+        float width = isHorizontal ? logicalRightSide - logicalLeftSide : lastTextBox()->logicalBottom() - x;
+        float height = isHorizontal ? lastTextBox()->logicalBottom() - y : logicalRightSide - logicalLeftSide;
+        result = enclosingIntRect(FloatRect(x, y, width, height));
+    }
+
+    return result;
+}
+
+LayoutRect RenderText::linesVisualOverflowBoundingBox() const
+{
+    if (!firstTextBox())
+        return LayoutRect();
+
+    // Return the width of the minimal left side and the maximal right side.
+    LayoutUnit logicalLeftSide = LayoutUnit::max();
+    LayoutUnit logicalRightSide = LayoutUnit::min();
+    for (InlineTextBox* curr = firstTextBox(); curr; curr = curr->nextTextBox()) {
+        logicalLeftSide = min(logicalLeftSide, curr->logicalLeftVisualOverflow());
+        logicalRightSide = max(logicalRightSide, curr->logicalRightVisualOverflow());
+    }
+    
+    LayoutUnit logicalTop = firstTextBox()->logicalTopVisualOverflow();
+    LayoutUnit logicalWidth = logicalRightSide - logicalLeftSide;
+    LayoutUnit logicalHeight = lastTextBox()->logicalBottomVisualOverflow() - logicalTop;
+    
+    LayoutRect rect(logicalLeftSide, logicalTop, logicalWidth, logicalHeight);
+    if (!style()->isHorizontalWritingMode())
+        rect = rect.transposedRect();
+    return rect;
+}
+
+LayoutRect RenderText::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const
+{
+    RenderObject* rendererToRepaint = containingBlock();
+
+    // Do not cross self-painting layer boundaries.
+    RenderObject* enclosingLayerRenderer = enclosingLayer()->renderer();
+    if (enclosingLayerRenderer != rendererToRepaint && !rendererToRepaint->isDescendantOf(enclosingLayerRenderer))
+        rendererToRepaint = enclosingLayerRenderer;
+
+    // The renderer we chose to repaint may be an ancestor of repaintContainer, but we need to do a repaintContainer-relative repaint.
+    if (repaintContainer && repaintContainer != rendererToRepaint && !rendererToRepaint->isDescendantOf(repaintContainer))
+        return repaintContainer->clippedOverflowRectForRepaint(repaintContainer);
+
+    return rendererToRepaint->clippedOverflowRectForRepaint(repaintContainer);
+}
+
+LayoutRect RenderText::selectionRectForRepaint(const RenderLayerModelObject* repaintContainer, bool clipToVisibleContent)
+{
+    ASSERT(!needsLayout());
+
+    if (selectionState() == SelectionNone)
+        return LayoutRect();
+    RenderBlock* cb = containingBlock();
+    if (!cb)
+        return LayoutRect();
+
+    // 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 IntRect();
+
+    LayoutRect rect;
+    for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) {
+        rect.unite(box->localSelectionRect(startPos, endPos));
+        rect.unite(ellipsisRectForBox(box, startPos, endPos));
+    }
+
+    if (clipToVisibleContent)
+        computeRectForRepaint(repaintContainer, rect);
+    else {
+        if (cb->hasColumns())
+            cb->adjustRectForColumns(rect);
+
+        rect = localToContainerQuad(FloatRect(rect), repaintContainer).enclosingBoundingBox();
+    }
+
+    return rect;
+}
+
+int RenderText::caretMinOffset() const
+{
+    InlineTextBox* box = firstTextBox();
+    if (!box)
+        return 0;
+    int minOffset = box->start();
+    for (box = box->nextTextBox(); box; box = box->nextTextBox())
+        minOffset = min<int>(minOffset, box->start());
+    return minOffset;
+}
+
+int RenderText::caretMaxOffset() const
+{
+    InlineTextBox* box = lastTextBox();
+    if (!lastTextBox())
+        return textLength();
+
+    int maxOffset = box->start() + box->len();
+    for (box = box->prevTextBox(); box; box = box->prevTextBox())
+        maxOffset = max<int>(maxOffset, box->start() + box->len());
+    return maxOffset;
+}
+
+unsigned RenderText::renderedTextLength() const
+{
+    int l = 0;
+    for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox())
+        l += box->len();
+    return l;
+}
+
+int RenderText::previousOffset(int current) const
+{
+    StringImpl* si = m_text.impl();
+    TextBreakIterator* iterator = cursorMovementIterator(si->characters(), si->length());
+    if (!iterator)
+        return current - 1;
+
+    long result = textBreakPreceding(iterator, current);
+    if (result == TextBreakDone)
+        result = current - 1;
+
+
+    return result;
+}
+
+#if OS(DARWIN)
+
+#define HANGUL_CHOSEONG_START (0x1100)
+#define HANGUL_CHOSEONG_END (0x115F)
+#define HANGUL_JUNGSEONG_START (0x1160)
+#define HANGUL_JUNGSEONG_END (0x11A2)
+#define HANGUL_JONGSEONG_START (0x11A8)
+#define HANGUL_JONGSEONG_END (0x11F9)
+#define HANGUL_SYLLABLE_START (0xAC00)
+#define HANGUL_SYLLABLE_END (0xD7AF)
+#define HANGUL_JONGSEONG_COUNT (28)
+
+enum HangulState {
+    HangulStateL,
+    HangulStateV,
+    HangulStateT,
+    HangulStateLV,
+    HangulStateLVT,
+    HangulStateBreak
+};
+
+inline bool isHangulLVT(UChar32 character)
+{
+    return (character - HANGUL_SYLLABLE_START) % HANGUL_JONGSEONG_COUNT;
+}
+
+inline bool isMark(UChar32 c)
+{
+    int8_t charType = u_charType(c);
+    return charType == U_NON_SPACING_MARK || charType == U_ENCLOSING_MARK || charType == U_COMBINING_SPACING_MARK;
+}
+
+inline bool isRegionalIndicator(UChar32 c)
+{
+    // National flag emoji each consists of a pair of regional indicator symbols.
+    return 0x1F1E6 <= c && c <= 0x1F1FF;
+}
+
+#endif
+
+int RenderText::previousOffsetForBackwardDeletion(int current) const
+{
+#if OS(DARWIN)
+    ASSERT(m_text);
+    StringImpl& text = *m_text.impl();
+    UChar32 character;
+    bool sawRegionalIndicator = false;
+    while (current > 0) {
+        if (U16_IS_TRAIL(text[--current]))
+            --current;
+        if (current < 0)
+            break;
+
+        UChar32 character = text.characterStartingAt(current);
+
+        if (sawRegionalIndicator) {
+            // We don't check if the pair of regional indicator symbols before current position can actually be combined
+            // into a flag, and just delete it. This may not agree with how the pair is rendered in edge cases,
+            // but is good enough in practice.
+            if (isRegionalIndicator(character))
+                break;
+            // Don't delete a preceding character that isn't a regional indicator symbol.
+            U16_FWD_1_UNSAFE(text, current);
+        }
+
+        // We don't combine characters in Armenian ... Limbu range for backward deletion.
+        if ((character >= 0x0530) && (character < 0x1950))
+            break;
+
+        if (isRegionalIndicator(character)) {
+            sawRegionalIndicator = true;
+            continue;
+        }
+
+        if (!isMark(character) && (character != 0xFF9E) && (character != 0xFF9F))
+            break;
+    }
+
+    if (current <= 0)
+        return current;
+
+    // Hangul
+    character = text.characterStartingAt(current);
+    if (((character >= HANGUL_CHOSEONG_START) && (character <= HANGUL_JONGSEONG_END)) || ((character >= HANGUL_SYLLABLE_START) && (character <= HANGUL_SYLLABLE_END))) {
+        HangulState state;
+        HangulState initialState;
+
+        if (character < HANGUL_JUNGSEONG_START)
+            state = HangulStateL;
+        else if (character < HANGUL_JONGSEONG_START)
+            state = HangulStateV;
+        else if (character < HANGUL_SYLLABLE_START)
+            state = HangulStateT;
+        else
+            state = isHangulLVT(character) ? HangulStateLVT : HangulStateLV;
+
+        initialState = state;
+
+        while (current > 0 && ((character = text.characterStartingAt(current - 1)) >= HANGUL_CHOSEONG_START) && (character <= HANGUL_SYLLABLE_END) && ((character <= HANGUL_JONGSEONG_END) || (character >= HANGUL_SYLLABLE_START))) {
+            switch (state) {
+            case HangulStateV:
+                if (character <= HANGUL_CHOSEONG_END)
+                    state = HangulStateL;
+                else if ((character >= HANGUL_SYLLABLE_START) && (character <= HANGUL_SYLLABLE_END) && !isHangulLVT(character))
+                    state = HangulStateLV;
+                else if (character > HANGUL_JUNGSEONG_END)
+                    state = HangulStateBreak;
+                break;
+            case HangulStateT:
+                if ((character >= HANGUL_JUNGSEONG_START) && (character <= HANGUL_JUNGSEONG_END))
+                    state = HangulStateV;
+                else if ((character >= HANGUL_SYLLABLE_START) && (character <= HANGUL_SYLLABLE_END))
+                    state = (isHangulLVT(character) ? HangulStateLVT : HangulStateLV);
+                else if (character < HANGUL_JUNGSEONG_START)
+                    state = HangulStateBreak;
+                break;
+            default:
+                state = (character < HANGUL_JUNGSEONG_START) ? HangulStateL : HangulStateBreak;
+                break;
+            }
+            if (state == HangulStateBreak)
+                break;
+
+            --current;
+        }
+    }
+
+    return current;
+#else
+    // Platforms other than Mac delete by one code point.
+    if (U16_IS_TRAIL(m_text[--current]))
+        --current;
+    if (current < 0)
+        current = 0;
+    return current;
+#endif
+}
+
+int RenderText::nextOffset(int current) const
+{
+    StringImpl* si = m_text.impl();
+    TextBreakIterator* iterator = cursorMovementIterator(si->characters(), si->length());
+    if (!iterator)
+        return current + 1;
+
+    long result = textBreakFollowing(iterator, current);
+    if (result == TextBreakDone)
+        result = current + 1;
+
+
+    return result;
+}
+
+bool RenderText::computeCanUseSimpleFontCodePath() const
+{
+    if (isAllASCII() || m_text.is8Bit())
+        return true;
+    return Font::characterRangeCodePath(characters(), length()) == Font::Simple;
+}
+
+#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->renderer() == this);
+        ASSERT(child->prevTextBox() == prev);
+        prev = child;
+    }
+    ASSERT(prev == m_lastTextBox);
+#endif
+}
+
+#endif
+
+void RenderText::momentarilyRevealLastTypedCharacter(unsigned lastTypedCharacterOffset)
+{
+    if (!gSecureTextTimers)
+        gSecureTextTimers = new SecureTextTimerMap;
+
+    SecureTextTimer* secureTextTimer = gSecureTextTimers->get(this);
+    if (!secureTextTimer) {
+        secureTextTimer = new SecureTextTimer(this);
+        gSecureTextTimers->add(this, secureTextTimer);
+    }
+    secureTextTimer->restartWithNewText(lastTypedCharacterOffset);
+}
+
+void RenderText::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, PlatformMemoryTypes::Rendering);
+    RenderObject::reportMemoryUsage(memoryObjectInfo);
+    info.addMember(m_text, "text");
+    info.addMember(m_firstTextBox, "firstTextBox");
+    info.addMember(m_lastTextBox, "lastTextBox");
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderText.h b/Source/core/rendering/RenderText.h
new file mode 100644
index 0000000..400087c
--- /dev/null
+++ b/Source/core/rendering/RenderText.h
@@ -0,0 +1,231 @@
+/*
+ * (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 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 "core/rendering/RenderObject.h"
+#include "core/rendering/RenderView.h"
+#include <wtf/Forward.h>
+
+namespace WebCore {
+
+class InlineTextBox;
+
+class RenderText : public RenderObject {
+public:
+    // FIXME: If the node argument is not a Text node or the string argument is
+    // not the content of the Text node, updating text-transform property
+    // doesn't re-transform the string.
+    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*);
+
+    StringImpl* text() const { return m_text.impl(); }
+    String textWithoutTranscoding() const;
+
+    InlineTextBox* createInlineTextBox();
+    void dirtyLineBoxes(bool fullLayout);
+
+    virtual void absoluteRects(Vector<IntRect>&, const LayoutPoint& accumulatedOffset) const OVERRIDE FINAL;
+    void absoluteRectsForRange(Vector<IntRect>&, unsigned startOffset = 0, unsigned endOffset = UINT_MAX, bool useSelectionHeight = false, bool* wasFixed = 0);
+
+    virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const OVERRIDE FINAL;
+    void absoluteQuadsForRange(Vector<FloatQuad>&, unsigned startOffset = 0, unsigned endOffset = UINT_MAX, bool useSelectionHeight = false, bool* wasFixed = 0);
+
+    enum ClippingOption { NoClipping, ClipToEllipsis };
+    void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed = 0, ClippingOption = NoClipping) const;
+
+    virtual VisiblePosition positionForPoint(const LayoutPoint&);
+
+    bool is8Bit() const { return m_text.is8Bit(); }
+    const LChar* characters8() const { return m_text.impl()->characters8(); }
+    const UChar* characters16() const { return m_text.impl()->characters16(); }
+    const UChar* characters() const { return m_text.characters(); }
+    UChar characterAt(unsigned i) const { return is8Bit() ? characters8()[i] : characters16()[i]; }
+    UChar operator[](unsigned i) const { return characterAt(i); }
+    unsigned textLength() const { return m_text.length(); } // non virtual implementation of length()
+    void positionLineBox(InlineBox*);
+
+    virtual float width(unsigned from, unsigned len, const Font&, float xPos, HashSet<const SimpleFontData*>* fallbackFonts = 0, GlyphOverflow* = 0) const;
+    virtual float width(unsigned from, unsigned len, float xPos, bool firstLine = false, HashSet<const SimpleFontData*>* fallbackFonts = 0, GlyphOverflow* = 0) const;
+
+    float minLogicalWidth() const;
+    float maxLogicalWidth() const;
+
+    void trimmedPrefWidths(float leadWidth,
+                           float& beginMinW, bool& beginWS,
+                           float& endMinW, bool& endWS,
+                           bool& hasBreakableChar, bool& hasBreak,
+                           float& beginMaxW, float& endMaxW,
+                           float& minW, float& maxW, bool& stripFrontSpaces);
+
+    virtual IntRect linesBoundingBox() const;
+    LayoutRect linesVisualOverflowBoundingBox() const;
+
+    FloatPoint firstRunOrigin() const;
+    float firstRunX() const;
+    float firstRunY() const;
+
+    virtual void setText(PassRefPtr<StringImpl>, bool force = false);
+    void setTextWithOffset(PassRefPtr<StringImpl>, unsigned offset, unsigned len, bool force = false);
+
+    virtual void transformText();
+
+    virtual bool canBeSelectionLeaf() const { return true; }
+    virtual void setSelectionState(SelectionState s) OVERRIDE FINAL;
+    virtual LayoutRect selectionRectForRepaint(const RenderLayerModelObject* repaintContainer, bool clipToVisibleContent = true) OVERRIDE;
+    virtual LayoutRect localCaretRect(InlineBox*, int caretOffset, LayoutUnit* extraWidthToEndOfLine = 0);
+
+    LayoutUnit marginLeft() const { return minimumValueForLength(style()->marginLeft(), 0, view()); }
+    LayoutUnit marginRight() const { return minimumValueForLength(style()->marginRight(), 0, view()); }
+
+    virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const OVERRIDE FINAL;
+
+    InlineTextBox* firstTextBox() const { return m_firstTextBox; }
+    InlineTextBox* lastTextBox() const { return m_lastTextBox; }
+
+    virtual int caretMinOffset() const;
+    virtual int caretMaxOffset() const;
+    unsigned renderedTextLength() const;
+
+    virtual int previousOffset(int current) const OVERRIDE FINAL;
+    virtual int previousOffsetForBackwardDeletion(int current) const OVERRIDE FINAL;
+    virtual int nextOffset(int current) const OVERRIDE FINAL;
+
+    bool containsReversedText() const { return m_containsReversedText; }
+
+    bool isSecure() const { return style()->textSecurity() != TSNONE; }
+    void momentarilyRevealLastTypedCharacter(unsigned lastTypedCharacterOffset);
+
+    InlineTextBox* findNextInlineTextBox(int offset, int& pos) const;
+
+    void checkConsistency() const;
+
+    bool isAllCollapsibleWhitespace();
+
+    bool canUseSimpleFontCodePath() const { return m_canUseSimpleFontCodePath; }
+    bool knownToHaveNoOverflowAndNoFallbackFonts() const { return m_knownToHaveNoOverflowAndNoFallbackFonts; }
+
+    void removeAndDestroyTextBoxes();
+
+    virtual void reportMemoryUsage(MemoryObjectInfo*) const OVERRIDE FINAL;
+
+protected:
+    virtual void computePreferredLogicalWidths(float leadWidth);
+    virtual void willBeDestroyed();
+
+    virtual void styleWillChange(StyleDifference, const RenderStyle*) OVERRIDE FINAL { }
+    virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+
+    virtual void setTextInternal(PassRefPtr<StringImpl>);
+    virtual UChar previousCharacter() const;
+    
+    virtual InlineTextBox* createTextBox(); // Subclassed by SVG.
+
+private:
+    void computePreferredLogicalWidths(float leadWidth, HashSet<const SimpleFontData*>& fallbackFonts, GlyphOverflow&);
+
+    bool computeCanUseSimpleFontCodePath() const;
+    
+    // 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 OVERRIDE FINAL { return textLength(); }
+
+    virtual void paint(PaintInfo&, const LayoutPoint&) OVERRIDE FINAL { ASSERT_NOT_REACHED(); }
+    virtual void layout() OVERRIDE FINAL { ASSERT_NOT_REACHED(); }
+    virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation&, const LayoutPoint&, HitTestAction) OVERRIDE FINAL { ASSERT_NOT_REACHED(); return false; }
+
+    void deleteTextBoxes();
+    bool containsOnlyWhitespace(unsigned from, unsigned len) const;
+    float widthFromCache(const Font&, int start, int len, float xPos, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow*) const;
+    bool isAllASCII() const { return m_isAllASCII; }
+    void updateNeedsTranscoding();
+
+    void secureText(UChar mask);
+
+    // We put the bitfield first to minimize padding on 64-bit.
+    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;
+    bool m_canUseSimpleFontCodePath : 1;
+    mutable bool m_knownToHaveNoOverflowAndNoFallbackFonts : 1;
+    bool m_needsTranscoding : 1;
+    
+    float m_minWidth;
+    float m_maxWidth;
+    float m_beginMinWidth;
+    float m_endMinWidth;
+
+    String m_text;
+
+    InlineTextBox* m_firstTextBox;
+    InlineTextBox* m_lastTextBox;
+};
+
+inline RenderText* toRenderText(RenderObject* object)
+{ 
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isText());
+    return static_cast<RenderText*>(object);
+}
+
+inline const RenderText* toRenderText(const RenderObject* object)
+{ 
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isText());
+    return static_cast<const RenderText*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderText(const RenderText*);
+
+#ifdef NDEBUG
+inline void RenderText::checkConsistency() const
+{
+}
+#endif
+
+void applyTextTransform(const RenderStyle*, String&, UChar);
+
+} // namespace WebCore
+
+#endif // RenderText_h
diff --git a/Source/core/rendering/RenderTextControl.cpp b/Source/core/rendering/RenderTextControl.cpp
new file mode 100644
index 0000000..96608cb
--- /dev/null
+++ b/Source/core/rendering/RenderTextControl.cpp
@@ -0,0 +1,312 @@
+/**
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ *           (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)  
+ *
+ * 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 "core/rendering/RenderTextControl.h"
+
+#include "core/editing/TextIterator.h"
+#include "core/editing/VisiblePosition.h"
+#include "core/html/HTMLTextFormControlElement.h"
+#include "core/platform/ScrollbarTheme.h"
+#include "core/rendering/HitTestResult.h"
+#include "core/rendering/RenderText.h"
+#include "core/rendering/RenderTheme.h"
+#include "core/rendering/style/StyleInheritedData.h"
+#include <wtf/unicode/CharacterNames.h>
+
+using namespace std;
+
+namespace WebCore {
+
+RenderTextControl::RenderTextControl(Element* element)
+    : RenderBlock(element)
+{
+    ASSERT(isHTMLTextFormControlElement(element));
+}
+
+RenderTextControl::~RenderTextControl()
+{
+}
+
+HTMLTextFormControlElement* RenderTextControl::textFormControlElement() const
+{
+    return toHTMLTextFormControlElement(node());
+}
+
+HTMLElement* RenderTextControl::innerTextElement() const
+{
+    return textFormControlElement()->innerTextElement();
+}
+
+void RenderTextControl::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
+{
+    RenderBlock::styleDidChange(diff, oldStyle);
+    Element* innerText = innerTextElement();
+    if (!innerText)
+        return;
+    RenderBlock* innerTextRenderer = toRenderBlock(innerText->renderer());
+    if (innerTextRenderer) {
+        // 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.
+        innerTextRenderer->style()->setHeight(Length());
+        innerTextRenderer->style()->setWidth(Length());
+        innerTextRenderer->setStyle(createInnerTextStyle(style()));
+        innerText->setNeedsStyleRecalc();
+    }
+    textFormControlElement()->updatePlaceholderVisibility(false);
+}
+
+static inline bool updateUserModifyProperty(Node* node, RenderStyle* style)
+{
+    bool isDisabled = false;
+    bool isReadOnlyControl = false;
+
+    if (node->isElementNode()) {
+        Element* element = toElement(node);
+        isDisabled = element->isDisabledFormControl();
+        isReadOnlyControl = element->isTextFormControl() && toHTMLTextFormControlElement(element)->isReadOnly();
+    }
+
+    style->setUserModify((isReadOnlyControl || isDisabled) ? READ_ONLY : READ_WRITE_PLAINTEXT_ONLY);
+    return isDisabled;
+}
+
+void RenderTextControl::adjustInnerTextStyle(const RenderStyle* startStyle, RenderStyle* textBlockStyle) const
+{
+    // The inner block, if present, always has its direction set to LTR,
+    // so we need to inherit the direction and unicode-bidi style from the element.
+    textBlockStyle->setDirection(style()->direction());
+    textBlockStyle->setUnicodeBidi(style()->unicodeBidi());
+
+    bool disabled = updateUserModifyProperty(node(), textBlockStyle);
+    if (disabled)
+        textBlockStyle->setColor(theme()->disabledTextColor(textBlockStyle->visitedDependentColor(CSSPropertyColor), startStyle->visitedDependentColor(CSSPropertyBackgroundColor)));
+}
+
+int RenderTextControl::textBlockLogicalHeight() const
+{
+    return logicalHeight() - borderAndPaddingLogicalHeight();
+}
+
+int RenderTextControl::textBlockLogicalWidth() const
+{
+    Element* innerText = innerTextElement();
+    ASSERT(innerText);
+
+    LayoutUnit unitWidth = logicalWidth() - borderAndPaddingLogicalWidth();
+    if (innerText->renderer())
+        unitWidth -= innerText->renderBox()->paddingStart() + innerText->renderBox()->paddingEnd();
+
+    return unitWidth;
+}
+
+void RenderTextControl::updateFromElement()
+{
+    Element* innerText = innerTextElement();
+    if (innerText && innerText->renderer())
+        updateUserModifyProperty(node(), innerText->renderer()->style());
+}
+
+int RenderTextControl::scrollbarThickness() const
+{
+    // FIXME: We should get the size of the scrollbar from the RenderTheme instead.
+    return ScrollbarTheme::theme()->scrollbarThickness();
+}
+
+void RenderTextControl::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues& computedValues) const
+{
+    HTMLElement* innerText = innerTextElement();
+    ASSERT(innerText);
+    if (RenderBox* innerTextBox = innerText->renderBox()) {
+        LayoutUnit nonContentHeight = innerTextBox->borderAndPaddingHeight() + innerTextBox->marginHeight();
+        logicalHeight = computeControlLogicalHeight(innerTextBox->lineHeight(true, HorizontalLine, PositionOfInteriorLineBoxes), nonContentHeight) + borderAndPaddingHeight();
+
+        // 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 ((isHorizontalWritingMode() && (style()->overflowX() == OSCROLL ||  (style()->overflowX() == OAUTO && innerText->renderer()->style()->overflowWrap() == NormalOverflowWrap)))
+            || (!isHorizontalWritingMode() && (style()->overflowY() == OSCROLL ||  (style()->overflowY() == OAUTO && innerText->renderer()->style()->overflowWrap() == NormalOverflowWrap))))
+            logicalHeight += scrollbarThickness();
+    }
+
+    RenderBox::computeLogicalHeight(logicalHeight, logicalTop, computedValues);
+}
+
+void RenderTextControl::hitInnerTextElement(HitTestResult& result, const LayoutPoint& pointInContainer, const LayoutPoint& accumulatedOffset)
+{
+    HTMLElement* innerText = innerTextElement();
+    if (!innerText->renderer())
+        return;
+
+    LayoutPoint adjustedLocation = accumulatedOffset + location();
+    LayoutPoint localPoint = pointInContainer - toLayoutSize(adjustedLocation + innerText->renderBox()->location());
+    if (hasOverflowClip())
+        localPoint += scrolledContentOffset();
+    result.setInnerNode(innerText);
+    result.setInnerNonSharedNode(innerText);
+    result.setLocalPoint(localPoint);
+}
+
+static const char* fontFamiliesWithInvalidCharWidth[] = {
+    "American Typewriter",
+    "Arial Hebrew",
+    "Chalkboard",
+    "Cochin",
+    "Corsiva Hebrew",
+    "Courier",
+    "Euphemia UCAS",
+    "Geneva",
+    "Gill Sans",
+    "Hei",
+    "Helvetica",
+    "Hoefler Text",
+    "InaiMathi",
+    "Kai",
+    "Lucida Grande",
+    "Marker Felt",
+    "Monaco",
+    "Mshtakan",
+    "New Peninim MT",
+    "Osaka",
+    "Raanana",
+    "STHeiti",
+    "Symbol",
+    "Times",
+    "Apple Braille",
+    "Apple LiGothic",
+    "Apple LiSung",
+    "Apple Symbols",
+    "AppleGothic",
+    "AppleMyungjo",
+    "#GungSeo",
+    "#HeadLineA",
+    "#PCMyungjo",
+    "#PilGi",
+};
+
+// For font families where any of the fonts don't have a valid entry in the OS/2 table
+// for avgCharWidth, fallback to the legacy webkit behavior of getting the avgCharWidth
+// from the width of a '0'. This only seems to apply to a fixed number of Mac fonts,
+// but, in order to get similar rendering across platforms, we do this check for
+// all platforms.
+bool RenderTextControl::hasValidAvgCharWidth(AtomicString family)
+{
+    static HashSet<AtomicString>* fontFamiliesWithInvalidCharWidthMap = 0;
+
+    if (family.isEmpty())
+        return false;
+
+    if (!fontFamiliesWithInvalidCharWidthMap) {
+        fontFamiliesWithInvalidCharWidthMap = new HashSet<AtomicString>;
+
+        for (size_t i = 0; i < WTF_ARRAY_LENGTH(fontFamiliesWithInvalidCharWidth); ++i)
+            fontFamiliesWithInvalidCharWidthMap->add(AtomicString(fontFamiliesWithInvalidCharWidth[i]));
+    }
+
+    return !fontFamiliesWithInvalidCharWidthMap->contains(family);
+}
+
+float RenderTextControl::getAvgCharWidth(AtomicString family)
+{
+    if (hasValidAvgCharWidth(family))
+        return roundf(style()->font().primaryFont()->avgCharWidth());
+
+    const UChar ch = '0';
+    const String str = String(&ch, 1);
+    const Font& font = style()->font();
+    TextRun textRun = constructTextRun(this, font, str, style(), TextRun::AllowTrailingExpansion);
+    textRun.disableRoundingHacks();
+    return font.width(textRun);
+}
+
+float RenderTextControl::scaleEmToUnits(int x) const
+{
+    // This matches the unitsPerEm value for MS Shell Dlg and Courier New from the "head" font table.
+    float unitsPerEm = 2048.0f;
+    return roundf(style()->font().size() * x / unitsPerEm);
+}
+
+void RenderTextControl::computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const
+{
+    // Use average character width. Matches IE.
+    AtomicString family = style()->font().family().family();
+    maxLogicalWidth = preferredContentLogicalWidth(const_cast<RenderTextControl*>(this)->getAvgCharWidth(family));
+    if (RenderBox* innerTextRenderBox = innerTextElement()->renderBox())
+        maxLogicalWidth += innerTextRenderBox->paddingStart() + innerTextRenderBox->paddingEnd();
+    if (!style()->logicalWidth().isPercent())
+        minLogicalWidth = maxLogicalWidth;
+}
+
+void RenderTextControl::computePreferredLogicalWidths()
+{
+    ASSERT(preferredLogicalWidthsDirty());
+
+    m_minPreferredLogicalWidth = 0;
+    m_maxPreferredLogicalWidth = 0;
+
+    if (style()->logicalWidth().isFixed() && style()->logicalWidth().value() >= 0)
+        m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = adjustContentBoxLogicalWidthForBoxSizing(style()->logicalWidth().value());
+    else
+        computeIntrinsicLogicalWidths(m_minPreferredLogicalWidth, m_maxPreferredLogicalWidth);
+
+    if (style()->logicalMinWidth().isFixed() && style()->logicalMinWidth().value() > 0) {
+        m_maxPreferredLogicalWidth = max(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->logicalMinWidth().value()));
+        m_minPreferredLogicalWidth = max(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->logicalMinWidth().value()));
+    }
+
+    if (style()->logicalMaxWidth().isFixed()) {
+        m_maxPreferredLogicalWidth = min(m_maxPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->logicalMaxWidth().value()));
+        m_minPreferredLogicalWidth = min(m_minPreferredLogicalWidth, adjustContentBoxLogicalWidthForBoxSizing(style()->logicalMaxWidth().value()));
+    }
+
+    LayoutUnit toAdd = borderAndPaddingLogicalWidth();
+
+    m_minPreferredLogicalWidth += toAdd;
+    m_maxPreferredLogicalWidth += toAdd;
+
+    setPreferredLogicalWidthsDirty(false);
+}
+
+void RenderTextControl::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint& additionalOffset, const RenderLayerModelObject*)
+{
+    if (!size().isEmpty())
+        rects.append(pixelSnappedIntRect(additionalOffset, size()));
+}
+
+RenderObject* RenderTextControl::layoutSpecialExcludedChild(bool relayoutChildren)
+{
+    HTMLElement* placeholder = toHTMLTextFormControlElement(node())->placeholderElement();
+    RenderObject* placeholderRenderer = placeholder ? placeholder->renderer() : 0;
+    if (!placeholderRenderer)
+        return 0;
+    if (relayoutChildren) {
+        // The markParents arguments should be false because this function is
+        // called from layout() of the parent and the placeholder layout doesn't
+        // affect the parent layout.
+        placeholderRenderer->setChildNeedsLayout(true, MarkOnlyThis);
+    }
+    return placeholderRenderer;
+}
+
+bool RenderTextControl::canBeReplacedWithInlineRunIn() const
+{
+    return false;
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderTextControl.h b/Source/core/rendering/RenderTextControl.h
new file mode 100644
index 0000000..fe1194a
--- /dev/null
+++ b/Source/core/rendering/RenderTextControl.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ *           (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) 
+ *
+ * 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 "core/rendering/RenderBlock.h"
+#include "core/rendering/RenderFlexibleBox.h"
+
+namespace WebCore {
+
+class HTMLTextFormControlElement;
+
+class RenderTextControl : public RenderBlock {
+public:
+    virtual ~RenderTextControl();
+
+    HTMLTextFormControlElement* textFormControlElement() const;
+    virtual PassRefPtr<RenderStyle> createInnerTextStyle(const RenderStyle* startStyle) const = 0;
+
+protected:
+    RenderTextControl(Element*);
+
+    // This convenience function should not be made public because innerTextElement may outlive the render tree.
+    HTMLElement* innerTextElement() const;
+
+    int scrollbarThickness() const;
+    void adjustInnerTextStyle(const RenderStyle* startStyle, RenderStyle* textBlockStyle) const;
+
+    virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+
+    void hitInnerTextElement(HitTestResult&, const LayoutPoint& pointInContainer, const LayoutPoint& accumulatedOffset);
+
+    int textBlockLogicalWidth() const;
+    int textBlockLogicalHeight() const;
+
+    float scaleEmToUnits(int x) const;
+
+    static bool hasValidAvgCharWidth(AtomicString family);
+    virtual float getAvgCharWidth(AtomicString family);
+    virtual LayoutUnit preferredContentLogicalWidth(float charWidth) const = 0;
+    virtual LayoutUnit computeControlLogicalHeight(LayoutUnit lineHeight, LayoutUnit nonContentHeight) const = 0;
+    virtual RenderStyle* textBaseStyle() const = 0;
+
+    virtual void updateFromElement();
+    virtual void computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues&) const OVERRIDE;
+    virtual RenderObject* layoutSpecialExcludedChild(bool relayoutChildren);
+
+private:
+    virtual const char* renderName() const { return "RenderTextControl"; }
+    virtual bool isTextControl() const { return true; }
+    virtual void computeIntrinsicLogicalWidths(LayoutUnit& minLogicalWidth, LayoutUnit& maxLogicalWidth) const OVERRIDE;
+    virtual void computePreferredLogicalWidths() OVERRIDE;
+    virtual void removeLeftoverAnonymousBlock(RenderBlock*) { }
+    virtual bool avoidsFloats() const { return true; }
+    virtual bool canHaveGeneratedChildren() const OVERRIDE { return false; }
+    virtual bool canBeReplacedWithInlineRunIn() const OVERRIDE;
+    
+    virtual void addFocusRingRects(Vector<IntRect>&, const LayoutPoint& additionalOffset, const RenderLayerModelObject* paintContainer = 0) OVERRIDE;
+
+    virtual bool canBeProgramaticallyScrolled() const { return true; }
+
+    virtual bool requiresForcedStyleRecalcPropagation() const { return true; }
+};
+
+inline RenderTextControl* toRenderTextControl(RenderObject* object)
+{ 
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isTextControl());
+    return static_cast<RenderTextControl*>(object);
+}
+
+inline const RenderTextControl* toRenderTextControl(const RenderObject* object)
+{ 
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isTextControl());
+    return static_cast<const RenderTextControl*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderTextControl(const RenderTextControl*);
+
+// Renderer for our inner container, for <search> and others.
+// We can't use RenderFlexibleBox directly, because flexboxes have a different
+// baseline definition, and then inputs of different types wouldn't line up
+// anymore.
+class RenderTextControlInnerContainer FINAL : public RenderFlexibleBox {
+public:
+    explicit RenderTextControlInnerContainer(Element* element)
+        : RenderFlexibleBox(element)
+    { }
+    virtual ~RenderTextControlInnerContainer() { }
+
+    virtual int baselinePosition(FontBaseline baseline, bool firstLine, LineDirectionMode direction, LinePositionMode position) const OVERRIDE
+    {
+        return RenderBlock::baselinePosition(baseline, firstLine, direction, position);
+    }
+    virtual int firstLineBoxBaseline() const OVERRIDE { return RenderBlock::firstLineBoxBaseline(); }
+    virtual int inlineBlockBaseline(LineDirectionMode direction) const OVERRIDE { return RenderBlock::inlineBlockBaseline(direction); }
+
+};
+
+
+} // namespace WebCore
+
+#endif // RenderTextControl_h
diff --git a/Source/core/rendering/RenderTextControlMultiLine.cpp b/Source/core/rendering/RenderTextControlMultiLine.cpp
new file mode 100644
index 0000000..4a2fc16
--- /dev/null
+++ b/Source/core/rendering/RenderTextControlMultiLine.cpp
@@ -0,0 +1,114 @@
+/**
+ * Copyright (C) 2006, 2007 Apple Inc. All rights reserved.
+ *           (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) 
+ *
+ * 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 "core/rendering/RenderTextControlMultiLine.h"
+
+#include "HTMLNames.h"
+#include "core/dom/ShadowRoot.h"
+#include "core/html/HTMLTextAreaElement.h"
+#include "core/html/shadow/TextControlInnerElements.h"
+#include "core/page/Frame.h"
+#include "core/rendering/HitTestResult.h"
+#include "core/rendering/style/StyleInheritedData.h"
+
+namespace WebCore {
+
+RenderTextControlMultiLine::RenderTextControlMultiLine(Element* element)
+    : RenderTextControl(element)
+{
+}
+
+RenderTextControlMultiLine::~RenderTextControlMultiLine()
+{
+    if (node() && node()->inDocument())
+        static_cast<HTMLTextAreaElement*>(node())->rendererWillBeDestroyed();
+}
+
+bool RenderTextControlMultiLine::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
+{
+    if (!RenderTextControl::nodeAtPoint(request, result, locationInContainer, accumulatedOffset, hitTestAction))
+        return false;
+
+    if (result.innerNode() == node() || result.innerNode() == innerTextElement())
+        hitInnerTextElement(result, locationInContainer.point(), accumulatedOffset);
+
+    return true;
+}
+
+float RenderTextControlMultiLine::getAvgCharWidth(AtomicString family)
+{
+    // Since Lucida Grande is the default font, we want this to match the width
+    // of Courier New, the default font for textareas in IE, Firefox and Safari Win.
+    // 1229 is the avgCharWidth value in the OS/2 table for Courier New.
+    if (family == "Lucida Grande")
+        return scaleEmToUnits(1229);
+
+    return RenderTextControl::getAvgCharWidth(family);
+}
+
+LayoutUnit RenderTextControlMultiLine::preferredContentLogicalWidth(float charWidth) const
+{
+    int factor = static_cast<HTMLTextAreaElement*>(node())->cols();
+    return static_cast<LayoutUnit>(ceilf(charWidth * factor)) + scrollbarThickness();
+}
+
+LayoutUnit RenderTextControlMultiLine::computeControlLogicalHeight(LayoutUnit lineHeight, LayoutUnit nonContentHeight) const
+{
+    return lineHeight * static_cast<HTMLTextAreaElement*>(node())->rows() + nonContentHeight;
+}
+
+int RenderTextControlMultiLine::baselinePosition(FontBaseline baselineType, bool firstLine, LineDirectionMode direction, LinePositionMode linePositionMode) const
+{
+    return RenderBox::baselinePosition(baselineType, firstLine, direction, linePositionMode);
+}
+
+PassRefPtr<RenderStyle> RenderTextControlMultiLine::createInnerTextStyle(const RenderStyle* startStyle) const
+{
+    RefPtr<RenderStyle> textBlockStyle = RenderStyle::create();
+    textBlockStyle->inheritFrom(startStyle);
+    adjustInnerTextStyle(startStyle, textBlockStyle.get());
+    textBlockStyle->setDisplay(BLOCK);
+
+    return textBlockStyle.release();
+}
+
+RenderStyle* RenderTextControlMultiLine::textBaseStyle() const
+{
+    return style();
+}
+
+RenderObject* RenderTextControlMultiLine::layoutSpecialExcludedChild(bool relayoutChildren)
+{
+    RenderObject* placeholderRenderer = RenderTextControl::layoutSpecialExcludedChild(relayoutChildren);
+    if (!placeholderRenderer)
+        return 0;
+    if (!placeholderRenderer->isBox())
+        return placeholderRenderer;
+    RenderBox* placeholderBox = toRenderBox(placeholderRenderer);
+    placeholderBox->style()->setLogicalWidth(Length(contentLogicalWidth() - placeholderBox->borderAndPaddingLogicalWidth(), Fixed));
+    placeholderBox->layoutIfNeeded();
+    placeholderBox->setX(borderLeft() + paddingLeft());
+    placeholderBox->setY(borderTop() + paddingTop());
+    return placeholderRenderer;
+}
+    
+}
diff --git a/Source/core/rendering/RenderTextControlMultiLine.h b/Source/core/rendering/RenderTextControlMultiLine.h
new file mode 100644
index 0000000..f757d2f
--- /dev/null
+++ b/Source/core/rendering/RenderTextControlMultiLine.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) 
+ * Copyright (C) 2009 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 RenderTextControlMultiLine_h
+#define RenderTextControlMultiLine_h
+
+#include "core/rendering/RenderTextControl.h"
+
+namespace WebCore {
+
+class RenderTextControlMultiLine FINAL : public RenderTextControl {
+public:
+    RenderTextControlMultiLine(Element*);
+    virtual ~RenderTextControlMultiLine();
+
+private:
+    virtual bool isTextArea() const { return true; }
+
+    virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
+
+    virtual float getAvgCharWidth(AtomicString family);
+    virtual LayoutUnit preferredContentLogicalWidth(float charWidth) const;
+    virtual LayoutUnit computeControlLogicalHeight(LayoutUnit lineHeight, LayoutUnit nonContentHeight) const OVERRIDE;
+    virtual int baselinePosition(FontBaseline, bool firstLine, LineDirectionMode, LinePositionMode = PositionOnContainingLine) const;
+
+    virtual RenderStyle* textBaseStyle() const;
+    virtual PassRefPtr<RenderStyle> createInnerTextStyle(const RenderStyle* startStyle) const;
+    virtual RenderObject* layoutSpecialExcludedChild(bool relayoutChildren);
+};
+
+inline RenderTextControlMultiLine* toRenderTextControlMultiLine(RenderObject* object)
+{ 
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isTextArea());
+    return static_cast<RenderTextControlMultiLine*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderTextControlMultiLine(const RenderTextControlMultiLine*);
+
+}
+
+#endif
diff --git a/Source/core/rendering/RenderTextControlSingleLine.cpp b/Source/core/rendering/RenderTextControlSingleLine.cpp
new file mode 100644
index 0000000..86bc8ee
--- /dev/null
+++ b/Source/core/rendering/RenderTextControlSingleLine.cpp
@@ -0,0 +1,483 @@
+/**
+ * Copyright (C) 2006, 2007, 2010 Apple Inc. All rights reserved.
+ *           (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/) 
+ * Copyright (C) 2010 Google Inc. All rights reserved.
+ * Copyright (C) 2010 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 "core/rendering/RenderTextControlSingleLine.h"
+
+#include "CSSValueKeywords.h"
+#include "HTMLNames.h"
+#include "core/css/CSSFontSelector.h"
+#include "core/css/StyleResolver.h"
+#include "core/editing/FrameSelection.h"
+#include "core/html/shadow/TextControlInnerElements.h"
+#include "core/page/Chrome.h"
+#include "core/page/Frame.h"
+#include "core/page/FrameView.h"
+#include "core/page/Page.h"
+#include "core/page/Settings.h"
+#include "core/platform/LocalizedStrings.h"
+#include "core/platform/PlatformKeyboardEvent.h"
+#include "core/platform/graphics/SimpleFontData.h"
+#include "core/rendering/HitTestResult.h"
+#include "core/rendering/RenderLayer.h"
+#include "core/rendering/RenderScrollbar.h"
+#include "core/rendering/RenderTheme.h"
+
+using namespace std;
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+RenderTextControlSingleLine::RenderTextControlSingleLine(Element* element)
+    : RenderTextControl(element)
+    , m_shouldDrawCapsLockIndicator(false)
+    , m_desiredInnerTextLogicalHeight(-1)
+{
+    ASSERT(element->isHTMLElement());
+    ASSERT(element->toInputElement());
+}
+
+RenderTextControlSingleLine::~RenderTextControlSingleLine()
+{
+}
+
+inline HTMLElement* RenderTextControlSingleLine::innerSpinButtonElement() const
+{
+    return inputElement()->innerSpinButtonElement();
+}
+
+RenderStyle* RenderTextControlSingleLine::textBaseStyle() const
+{
+    HTMLElement* innerBlock = innerBlockElement();
+    return innerBlock ? innerBlock->renderer()->style() : style();
+}
+
+void RenderTextControlSingleLine::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    RenderTextControl::paint(paintInfo, paintOffset);
+
+    if (paintInfo.phase == PaintPhaseBlockBackground && m_shouldDrawCapsLockIndicator) {
+        LayoutRect contentsRect = contentBoxRect();
+
+        // Center in the block progression direction.
+        if (isHorizontalWritingMode())
+            contentsRect.setY((height() - contentsRect.height()) / 2);
+        else
+            contentsRect.setX((width() - contentsRect.width()) / 2);
+
+        // Convert the rect into the coords used for painting the content
+        contentsRect.moveBy(paintOffset + location());
+        theme()->paintCapsLockIndicator(this, paintInfo, pixelSnappedIntRect(contentsRect));
+    }
+}
+
+LayoutUnit RenderTextControlSingleLine::computeLogicalHeightLimit() const
+{
+    return containerElement() ? contentLogicalHeight() : logicalHeight();
+}
+
+void RenderTextControlSingleLine::layout()
+{
+    StackStats::LayoutCheckPoint layoutCheckPoint;
+
+    // FIXME: We should remove the height-related hacks in layout() and
+    // styleDidChange(). We need them because
+    // - Center the inner elements vertically if the input height is taller than
+    //   the intrinsic height of the inner elements.
+    // - Shrink the inner elment heights if the input height is samller than the
+    //   intrinsic heights of the inner elements.
+
+    // We don't honor paddings and borders for textfields without decorations
+    // and type=search if the text height is taller than the contentHeight()
+    // because of compability.
+
+    RenderBox* innerTextRenderer = innerTextElement()->renderBox();
+    RenderBox* innerBlockRenderer = innerBlockElement() ? innerBlockElement()->renderBox() : 0;
+
+    // To ensure consistency between layouts, we need to reset any conditionally overriden height.
+    if (innerTextRenderer && !innerTextRenderer->style()->logicalHeight().isAuto()) {
+        innerTextRenderer->style()->setLogicalHeight(Length(Auto));
+        innerTextRenderer->setNeedsLayout(true, MarkOnlyThis);
+    }
+    if (innerBlockRenderer && !innerBlockRenderer->style()->logicalHeight().isAuto()) {
+        innerBlockRenderer->style()->setLogicalHeight(Length(Auto));
+        innerBlockRenderer->setNeedsLayout(true, MarkOnlyThis);
+    }
+
+    RenderBlock::layoutBlock(false);
+
+    HTMLElement* container = containerElement();
+    RenderBox* containerRenderer = container ? container->renderBox() : 0;
+
+    // Set the text block height
+    LayoutUnit desiredLogicalHeight = textBlockLogicalHeight();
+    LayoutUnit logicalHeightLimit = computeLogicalHeightLimit();
+    if (innerTextRenderer && innerTextRenderer->logicalHeight() > logicalHeightLimit) {
+        if (desiredLogicalHeight != innerTextRenderer->logicalHeight())
+            setNeedsLayout(true, MarkOnlyThis);
+
+        m_desiredInnerTextLogicalHeight = desiredLogicalHeight;
+
+        innerTextRenderer->style()->setLogicalHeight(Length(desiredLogicalHeight, Fixed));
+        innerTextRenderer->setNeedsLayout(true, MarkOnlyThis);
+        if (innerBlockRenderer) {
+            innerBlockRenderer->style()->setLogicalHeight(Length(desiredLogicalHeight, Fixed));
+            innerBlockRenderer->setNeedsLayout(true, MarkOnlyThis);
+        }
+    }
+    // The container might be taller because of decoration elements.
+    if (containerRenderer) {
+        containerRenderer->layoutIfNeeded();
+        LayoutUnit containerLogicalHeight = containerRenderer->logicalHeight();
+        if (containerLogicalHeight > logicalHeightLimit) {
+            containerRenderer->style()->setLogicalHeight(Length(logicalHeightLimit, Fixed));
+            setNeedsLayout(true, MarkOnlyThis);
+        } else if (containerRenderer->logicalHeight() < contentLogicalHeight()) {
+            containerRenderer->style()->setLogicalHeight(Length(contentLogicalHeight(), Fixed));
+            setNeedsLayout(true, MarkOnlyThis);
+        } else
+            containerRenderer->style()->setLogicalHeight(Length(containerLogicalHeight, Fixed));
+    }
+
+    // If we need another layout pass, we have changed one of children's height so we need to relayout them.
+    if (needsLayout())
+        RenderBlock::layoutBlock(true);
+
+    // Center the child block in the block progression direction (vertical centering for horizontal text fields).
+    if (!container && innerTextRenderer && innerTextRenderer->height() != contentLogicalHeight()) {
+        LayoutUnit logicalHeightDiff = innerTextRenderer->logicalHeight() - contentLogicalHeight();
+        innerTextRenderer->setLogicalTop(innerTextRenderer->logicalTop() - (logicalHeightDiff / 2 + layoutMod(logicalHeightDiff, 2)));
+    } else
+        centerContainerIfNeeded(containerRenderer);
+
+    // Ignores the paddings for the inner spin button.
+    if (RenderBox* innerSpinBox = innerSpinButtonElement() ? innerSpinButtonElement()->renderBox() : 0) {
+        RenderBox* parentBox = innerSpinBox->parentBox();
+        if (containerRenderer && !containerRenderer->style()->isLeftToRightDirection())
+            innerSpinBox->setLogicalLocation(LayoutPoint(-paddingLogicalLeft(), -paddingBefore()));
+        else
+            innerSpinBox->setLogicalLocation(LayoutPoint(parentBox->logicalWidth() - innerSpinBox->logicalWidth() + paddingLogicalRight(), -paddingBefore()));
+        innerSpinBox->setLogicalHeight(logicalHeight() - borderBefore() - borderAfter());
+    }
+
+    HTMLElement* placeholderElement = inputElement()->placeholderElement();
+    if (RenderBox* placeholderBox = placeholderElement ? placeholderElement->renderBox() : 0) {
+        LayoutSize innerTextSize;
+        if (innerTextRenderer)
+            innerTextSize = innerTextRenderer->size();
+        placeholderBox->style()->setWidth(Length(innerTextSize.width() - placeholderBox->borderAndPaddingWidth(), Fixed));
+        placeholderBox->style()->setHeight(Length(innerTextSize.height() - placeholderBox->borderAndPaddingHeight(), Fixed));
+        bool neededLayout = placeholderBox->needsLayout();
+        bool placeholderBoxHadLayout = placeholderBox->everHadLayout();
+        placeholderBox->layoutIfNeeded();
+        LayoutPoint textOffset;
+        if (innerTextRenderer)
+            textOffset = innerTextRenderer->location();
+        if (innerBlockElement() && innerBlockElement()->renderBox())
+            textOffset += toLayoutSize(innerBlockElement()->renderBox()->location());
+        if (containerRenderer)
+            textOffset += toLayoutSize(containerRenderer->location());
+        placeholderBox->setLocation(textOffset);
+
+        if (!placeholderBoxHadLayout && placeholderBox->checkForRepaintDuringLayout()) {
+            // This assumes a shadow tree without floats. If floats are added, the
+            // logic should be shared with RenderBlock::layoutBlockChild.
+            placeholderBox->repaint();
+        }
+        // The placeholder gets layout last, after the parent text control and its other children,
+        // so in order to get the correct overflow from the placeholder we need to recompute it now.
+        if (neededLayout)
+            computeOverflow(clientLogicalBottom());
+    }
+}
+
+bool RenderTextControlSingleLine::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
+{
+    if (!RenderTextControl::nodeAtPoint(request, result, locationInContainer, accumulatedOffset, hitTestAction))
+        return false;
+
+    // Say that we hit the inner text element if
+    //  - we hit a node inside the inner text element,
+    //  - we hit the <input> element (e.g. we're over the border or padding), or
+    //  - we hit regions not in any decoration buttons.
+    HTMLElement* container = containerElement();
+    if (result.innerNode()->isDescendantOf(innerTextElement()) || result.innerNode() == node() || (container && container == result.innerNode())) {
+        LayoutPoint pointInParent = locationInContainer.point();
+        if (container && innerBlockElement()) {
+            if (innerBlockElement()->renderBox())
+                pointInParent -= toLayoutSize(innerBlockElement()->renderBox()->location());
+            if (container->renderBox())
+                pointInParent -= toLayoutSize(container->renderBox()->location());
+        }
+        hitInnerTextElement(result, pointInParent, accumulatedOffset);
+    }
+    return true;
+}
+
+void RenderTextControlSingleLine::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
+{
+    m_desiredInnerTextLogicalHeight = -1;
+    RenderTextControl::styleDidChange(diff, oldStyle);
+
+    // 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.
+    HTMLElement* innerBlock = innerBlockElement();
+    if (RenderObject* innerBlockRenderer = innerBlock ? innerBlock->renderer() : 0) {
+        innerBlockRenderer->style()->setHeight(Length());
+        innerBlockRenderer->style()->setWidth(Length());
+    }
+    HTMLElement* container = containerElement();
+    if (RenderObject* containerRenderer = container ? container->renderer() : 0) {
+        containerRenderer->style()->setHeight(Length());
+        containerRenderer->style()->setWidth(Length());
+    }
+    RenderObject* innerTextRenderer = innerTextElement()->renderer();
+    if (innerTextRenderer && diff == StyleDifferenceLayout)
+        innerTextRenderer->setNeedsLayout(true, MarkOnlyThis);
+    if (HTMLElement* placeholder = inputElement()->placeholderElement())
+        placeholder->setInlineStyleProperty(CSSPropertyTextOverflow, textShouldBeTruncated() ? CSSValueEllipsis : CSSValueClip);
+    setHasOverflowClip(false);
+}
+
+void RenderTextControlSingleLine::capsLockStateMayHaveChanged()
+{
+    if (!node() || !document())
+        return;
+
+    // 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 (Frame* frame = document()->frame())
+        shouldDrawCapsLockIndicator = inputElement()->isPasswordField()
+                                      && frame->selection()->isFocusedAndActive()
+                                      && document()->focusedNode() == node()
+                                      && PlatformKeyboardEvent::currentCapsLockState();
+
+    if (shouldDrawCapsLockIndicator != m_shouldDrawCapsLockIndicator) {
+        m_shouldDrawCapsLockIndicator = shouldDrawCapsLockIndicator;
+        repaint();
+    }
+}
+
+bool RenderTextControlSingleLine::hasControlClip() const
+{
+    // Apply control clip for text fields with decorations.
+    return !!containerElement();
+}
+
+LayoutRect RenderTextControlSingleLine::controlClipRect(const LayoutPoint& additionalOffset) const
+{
+    ASSERT(hasControlClip());
+    LayoutRect clipRect = contentBoxRect();
+    if (containerElement()->renderBox())
+        clipRect = unionRect(clipRect, containerElement()->renderBox()->frameRect());
+    clipRect.moveBy(additionalOffset);
+    return clipRect;
+}
+
+float RenderTextControlSingleLine::getAvgCharWidth(AtomicString family)
+{
+    // Since Lucida Grande is the default font, we want this to match the width
+    // of MS Shell Dlg, the default font for textareas in Firefox, Safari Win and
+    // IE for some encodings (in IE, the default font is encoding specific).
+    // 901 is the avgCharWidth value in the OS/2 table for MS Shell Dlg.
+    if (family == "Lucida Grande")
+        return scaleEmToUnits(901);
+
+    return RenderTextControl::getAvgCharWidth(family);
+}
+
+LayoutUnit RenderTextControlSingleLine::preferredContentLogicalWidth(float charWidth) const
+{
+    int factor;
+    bool includesDecoration = inputElement()->sizeShouldIncludeDecoration(factor);
+    if (factor <= 0)
+        factor = 20;
+
+    LayoutUnit result = static_cast<LayoutUnit>(ceiledLayoutUnit(charWidth * factor));
+
+    float maxCharWidth = 0.f;
+    AtomicString family = style()->font().family().family();
+    // Since Lucida Grande is the default font, we want this to match the width
+    // of MS Shell Dlg, the default font for textareas in Firefox, Safari Win and
+    // IE for some encodings (in IE, the default font is encoding specific).
+    // 4027 is the (xMax - xMin) value in the "head" font table for MS Shell Dlg.
+    if (family == "Lucida Grande")
+        maxCharWidth = scaleEmToUnits(4027);
+    else if (hasValidAvgCharWidth(family))
+        maxCharWidth = roundf(style()->font().primaryFont()->maxCharWidth());
+
+    // For text inputs, IE adds some extra width.
+    if (maxCharWidth > 0.f)
+        result += maxCharWidth - charWidth;
+
+    if (includesDecoration) {
+        HTMLElement* spinButton = innerSpinButtonElement();
+        if (RenderBox* spinRenderer = spinButton ? spinButton->renderBox() : 0) {
+            result += spinRenderer->borderAndPaddingLogicalWidth();
+            // Since the width of spinRenderer is not calculated yet, spinRenderer->logicalWidth() returns 0.
+            // So computedStyle()->logicalWidth() is used instead.
+            result += spinButton->computedStyle()->logicalWidth().value();
+        }
+    }
+
+    return result;
+}
+
+LayoutUnit RenderTextControlSingleLine::computeControlLogicalHeight(LayoutUnit lineHeight, LayoutUnit nonContentHeight) const
+{
+    return lineHeight + nonContentHeight;
+}
+
+void RenderTextControlSingleLine::updateFromElement()
+{
+    RenderTextControl::updateFromElement();
+}
+
+PassRefPtr<RenderStyle> RenderTextControlSingleLine::createInnerTextStyle(const RenderStyle* startStyle) const
+{
+    RefPtr<RenderStyle> textBlockStyle = RenderStyle::create();   
+    textBlockStyle->inheritFrom(startStyle);
+    adjustInnerTextStyle(startStyle, textBlockStyle.get());
+
+    textBlockStyle->setWhiteSpace(PRE);
+    textBlockStyle->setOverflowWrap(NormalOverflowWrap);
+    textBlockStyle->setOverflowX(OHIDDEN);
+    textBlockStyle->setOverflowY(OHIDDEN);
+    textBlockStyle->setTextOverflow(textShouldBeTruncated() ? TextOverflowEllipsis : TextOverflowClip);
+
+    if (m_desiredInnerTextLogicalHeight >= 0)
+        textBlockStyle->setLogicalHeight(Length(m_desiredInnerTextLogicalHeight, Fixed));
+    // Do not allow line-height to be smaller than our default.
+    if (textBlockStyle->fontMetrics().lineSpacing() > lineHeight(true, HorizontalLine, PositionOfInteriorLineBoxes))
+        textBlockStyle->setLineHeight(RenderStyle::initialLineHeight());
+
+    textBlockStyle->setDisplay(BLOCK);
+
+    return textBlockStyle.release();
+}
+
+PassRefPtr<RenderStyle> RenderTextControlSingleLine::createInnerBlockStyle(const RenderStyle* startStyle) const
+{
+    RefPtr<RenderStyle> innerBlockStyle = RenderStyle::create();
+    innerBlockStyle->inheritFrom(startStyle);
+
+    innerBlockStyle->setFlexGrow(1);
+    // min-width: 0; is needed for correct shrinking.
+    // FIXME: Remove this line when https://bugs.webkit.org/show_bug.cgi?id=111790 is fixed.
+    innerBlockStyle->setMinWidth(Length(0, Fixed));
+    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();
+}
+
+bool RenderTextControlSingleLine::textShouldBeTruncated() const
+{
+    return document()->focusedNode() != node()
+        && style()->textOverflow() == TextOverflowEllipsis;
+}
+
+void RenderTextControlSingleLine::autoscroll(const IntPoint& position)
+{
+    RenderBox* renderer = innerTextElement()->renderBox();
+    if (!renderer)
+        return;
+    RenderLayer* layer = renderer->layer();
+    if (layer)
+        layer->autoscroll(position);
+}
+
+int RenderTextControlSingleLine::scrollWidth() const
+{
+    if (innerTextElement())
+        return innerTextElement()->scrollWidth();
+    return RenderBlock::scrollWidth();
+}
+
+int RenderTextControlSingleLine::scrollHeight() const
+{
+    if (innerTextElement())
+        return innerTextElement()->scrollHeight();
+    return RenderBlock::scrollHeight();
+}
+
+int RenderTextControlSingleLine::scrollLeft() const
+{
+    if (innerTextElement())
+        return innerTextElement()->scrollLeft();
+    return RenderBlock::scrollLeft();
+}
+
+int RenderTextControlSingleLine::scrollTop() const
+{
+    if (innerTextElement())
+        return innerTextElement()->scrollTop();
+    return RenderBlock::scrollTop();
+}
+
+void RenderTextControlSingleLine::setScrollLeft(int newLeft)
+{
+    if (innerTextElement())
+        innerTextElement()->setScrollLeft(newLeft);
+}
+
+void RenderTextControlSingleLine::setScrollTop(int newTop)
+{
+    if (innerTextElement())
+        innerTextElement()->setScrollTop(newTop);
+}
+
+bool RenderTextControlSingleLine::scroll(ScrollDirection direction, ScrollGranularity granularity, float multiplier, Node** stopNode)
+{
+    RenderBox* renderer = innerTextElement()->renderBox();
+    if (!renderer)
+        return false;
+    RenderLayer* layer = renderer->layer();
+    if (layer && layer->scroll(direction, granularity, multiplier))
+        return true;
+    return RenderBlock::scroll(direction, granularity, multiplier, stopNode);
+}
+
+bool RenderTextControlSingleLine::logicalScroll(ScrollLogicalDirection direction, ScrollGranularity granularity, float multiplier, Node** stopNode)
+{
+    RenderLayer* layer = innerTextElement()->renderBox()->layer();
+    if (layer && layer->scroll(logicalToPhysical(direction, style()->isHorizontalWritingMode(), style()->isFlippedBlocksWritingMode()), granularity, multiplier))
+        return true;
+    return RenderBlock::logicalScroll(direction, granularity, multiplier, stopNode);
+}
+
+HTMLInputElement* RenderTextControlSingleLine::inputElement() const
+{
+    return node()->toInputElement();
+}
+
+}
diff --git a/Source/core/rendering/RenderTextControlSingleLine.h b/Source/core/rendering/RenderTextControlSingleLine.h
new file mode 100644
index 0000000..d38d854
--- /dev/null
+++ b/Source/core/rendering/RenderTextControlSingleLine.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2006, 2007, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ * Copyright (C) 2010 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 RenderTextControlSingleLine_h
+#define RenderTextControlSingleLine_h
+
+#include "core/html/HTMLInputElement.h"
+#include "core/rendering/RenderTextControl.h"
+
+namespace WebCore {
+
+class HTMLInputElement;
+
+class RenderTextControlSingleLine : public RenderTextControl {
+public:
+    RenderTextControlSingleLine(Element*);
+    virtual ~RenderTextControlSingleLine();
+    // FIXME: Move create*Style() to their classes.
+    virtual PassRefPtr<RenderStyle> createInnerTextStyle(const RenderStyle* startStyle) const;
+    PassRefPtr<RenderStyle> createInnerBlockStyle(const RenderStyle* startStyle) const;
+
+    void capsLockStateMayHaveChanged();
+
+protected:
+    virtual void centerContainerIfNeeded(RenderBox*) const { }
+    virtual LayoutUnit computeLogicalHeightLimit() const;
+    HTMLElement* containerElement() const;
+    HTMLElement* innerBlockElement() const;
+    HTMLInputElement* inputElement() const;
+    virtual void updateFromElement() OVERRIDE;
+
+private:
+    virtual bool hasControlClip() const;
+    virtual LayoutRect controlClipRect(const LayoutPoint&) const;
+    virtual bool isTextField() const { return true; }
+
+    virtual void paint(PaintInfo&, const LayoutPoint&);
+    virtual void layout();
+
+    virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
+
+    virtual void autoscroll(const IntPoint&);
+
+    // 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, Node** stopNode = 0);
+    virtual bool logicalScroll(ScrollLogicalDirection, ScrollGranularity, float multiplier = 1, Node** stopNode = 0);
+
+    int textBlockWidth() const;
+    virtual float getAvgCharWidth(AtomicString family);
+    virtual LayoutUnit preferredContentLogicalWidth(float charWidth) const;
+    virtual LayoutUnit computeControlLogicalHeight(LayoutUnit lineHeight, LayoutUnit nonContentHeight) const OVERRIDE;
+    
+    virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+
+    virtual RenderStyle* textBaseStyle() const;
+
+    bool textShouldBeTruncated() const;
+
+    HTMLElement* innerSpinButtonElement() const;
+
+    bool m_shouldDrawCapsLockIndicator;
+    LayoutUnit m_desiredInnerTextLogicalHeight;
+};
+
+inline HTMLElement* RenderTextControlSingleLine::containerElement() const
+{
+    return inputElement()->containerElement();
+}
+
+inline HTMLElement* RenderTextControlSingleLine::innerBlockElement() const
+{
+    return inputElement()->innerBlockElement();
+}
+
+inline RenderTextControlSingleLine* toRenderTextControlSingleLine(RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isTextField());
+    return static_cast<RenderTextControlSingleLine*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderTextControlSingleLine(const RenderTextControlSingleLine*);
+
+// ----------------------------
+
+class RenderTextControlInnerBlock : public RenderBlock {
+public:
+    RenderTextControlInnerBlock(Element* element) : RenderBlock(element) { }
+
+private:
+    virtual bool hasLineIfEmpty() const { return true; }
+};
+
+}
+
+#endif
diff --git a/Source/core/rendering/RenderTextFragment.cpp b/Source/core/rendering/RenderTextFragment.cpp
new file mode 100644
index 0000000..d36e9c7
--- /dev/null
+++ b/Source/core/rendering/RenderTextFragment.cpp
@@ -0,0 +1,125 @@
+/*
+ * (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 2000 Dirk Mueller (mueller@kde.org)
+ * 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 "core/rendering/RenderTextFragment.h"
+
+#include "core/dom/Text.h"
+#include "core/rendering/RenderBlock.h"
+
+namespace WebCore {
+
+RenderTextFragment::RenderTextFragment(Node* node, StringImpl* str, int startOffset, int length)
+    : RenderText(node, str ? str->substring(startOffset, length) : PassRefPtr<StringImpl>(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)
+{
+}
+
+RenderTextFragment::~RenderTextFragment()
+{
+}
+
+PassRefPtr<StringImpl> RenderTextFragment::originalText() const
+{
+    Node* e = node();
+    RefPtr<StringImpl> result = ((e && e->isTextNode()) ? toText(e)->dataImpl() : contentString());
+    if (!result)
+        return 0;
+    return result->substring(start(), end());
+}
+
+void RenderTextFragment::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
+{
+    RenderText::styleDidChange(diff, oldStyle);
+
+    if (RenderBlock* block = blockForAccompanyingFirstLetter()) {
+        block->style()->removeCachedPseudoStyle(FIRST_LETTER);
+        block->updateFirstLetter();
+    }
+}
+
+void RenderTextFragment::willBeDestroyed()
+{
+    if (m_firstLetter)
+        m_firstLetter->destroy();
+    RenderText::willBeDestroyed();
+}
+
+void RenderTextFragment::setText(PassRefPtr<StringImpl> text, bool force)
+{
+    RenderText::setText(text, force);
+
+    m_start = 0;
+    m_end = textLength();
+    if (m_firstLetter) {
+        ASSERT(!m_contentString);
+        m_firstLetter->destroy();
+        m_firstLetter = 0;
+        if (Node* t = node()) {
+            ASSERT(!t->renderer());
+            t->setRenderer(this);
+        }
+    }
+}
+
+void RenderTextFragment::transformText()
+{
+    // Don't reset first-letter here because we are only transforming the truncated fragment.
+    if (RefPtr<StringImpl> textToTransform = originalText())
+        RenderText::setText(textToTransform.release(), true);
+}
+
+UChar RenderTextFragment::previousCharacter() const
+{
+    if (start()) {
+        Node* e = node();
+        StringImpl* original = ((e && e->isTextNode()) ? toText(e)->dataImpl() : contentString());
+        if (original && start() <= original->length())
+            return (*original)[start() - 1];
+    }
+
+    return RenderText::previousCharacter();
+}
+
+RenderBlock* RenderTextFragment::blockForAccompanyingFirstLetter() const
+{
+    if (!m_firstLetter)
+        return 0;
+    for (RenderObject* block = m_firstLetter->parent(); block; block = block->parent()) {
+        if (block->style()->hasPseudoStyle(FIRST_LETTER) && block->canHaveChildren() && block->isRenderBlock())
+            return toRenderBlock(block);
+    }
+    return 0;
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderTextFragment.h b/Source/core/rendering/RenderTextFragment.h
new file mode 100644
index 0000000..e2a4cae
--- /dev/null
+++ b/Source/core/rendering/RenderTextFragment.h
@@ -0,0 +1,89 @@
+/*
+ * (C) 1999 Lars Knoll (knoll@kde.org)
+ * (C) 2000 Dirk Mueller (mueller@kde.org)
+ * 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 "core/rendering/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 FINAL : public RenderText {
+public:
+    RenderTextFragment(Node*, StringImpl*, int startOffset, int length);
+    RenderTextFragment(Node*, StringImpl*);
+    virtual ~RenderTextFragment();
+
+    virtual bool isTextFragment() const { return true; }
+
+    virtual bool canBeSelectionLeaf() const OVERRIDE { return node() && node()->rendererIsEditable(); }
+
+    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;
+
+    virtual void setText(PassRefPtr<StringImpl>, bool force = false) OVERRIDE;
+
+    virtual void transformText() OVERRIDE;
+
+protected:
+    virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+
+private:
+    virtual void willBeDestroyed();
+
+    virtual UChar previousCharacter() const;
+    RenderBlock* blockForAccompanyingFirstLetter() const;
+
+    unsigned m_start;
+    unsigned m_end;
+    RefPtr<StringImpl> m_contentString;
+    RenderObject* m_firstLetter;
+};
+
+inline RenderTextFragment* toRenderTextFragment(RenderObject* object)
+{ 
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || toRenderText(object)->isTextFragment());
+    return static_cast<RenderTextFragment*>(object);
+}
+
+inline const RenderTextFragment* toRenderTextFragment(const RenderObject* object)
+{ 
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || toRenderText(object)->isTextFragment());
+    return static_cast<const RenderTextFragment*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderTextFragment(const RenderTextFragment*);
+
+} // namespace WebCore
+
+#endif // RenderTextFragment_h
diff --git a/Source/core/rendering/RenderTextTrackCue.cpp b/Source/core/rendering/RenderTextTrackCue.cpp
new file mode 100644
index 0000000..b1f41cc
--- /dev/null
+++ b/Source/core/rendering/RenderTextTrackCue.cpp
@@ -0,0 +1,284 @@
+/*
+ * Copyright (C) 2012 Victor Carbune (victor@rosedu.org)
+ *
+ * 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 "core/rendering/RenderTextTrackCue.h"
+
+#include "core/html/track/TextTrackCue.h"
+#include "core/html/track/TextTrackCueGeneric.h"
+
+namespace WebCore {
+
+RenderTextTrackCue::RenderTextTrackCue(TextTrackCueBox* element)
+    : RenderBlock(element)
+    , m_cue(element->getCue())
+{
+}
+
+void RenderTextTrackCue::layout()
+{
+    StackStats::LayoutCheckPoint layoutCheckPoint;
+    RenderBlock::layout();
+
+    LayoutStateMaintainer statePusher(view(), this, locationOffset(), hasTransform() || hasReflection() || style()->isFlippedBlocksWritingMode());
+
+    if (m_cue->cueType()== TextTrackCue::WebVTT) {
+        if (m_cue->snapToLines())
+            repositionCueSnapToLinesSet();
+        else
+            repositionCueSnapToLinesNotSet();
+    } else
+        repositionGenericCue();
+
+    statePusher.pop();
+}
+
+bool RenderTextTrackCue::findFirstLineBox(InlineFlowBox*& firstLineBox)
+{
+    if (firstChild()->isRenderInline())
+        firstLineBox = toRenderInline(firstChild())->firstLineBox();
+    else
+        return false;
+
+    return true;
+}
+
+bool RenderTextTrackCue::initializeLayoutParameters(InlineFlowBox* firstLineBox, LayoutUnit& step, LayoutUnit& position)
+{
+    ASSERT(firstChild());
+
+    RenderBlock* parentBlock = containingBlock();
+
+    // 1. Horizontal: Let step be the height of the first line box in boxes.
+    //    Vertical: Let step be the width of the first line box in boxes.
+    step = m_cue->getWritingDirection() == TextTrackCue::Horizontal ? firstLineBox->height() : firstLineBox->width();
+
+    // 2. If step is zero, then jump to the step labeled done positioning below.
+    if (!step)
+        return false;
+
+    // 3. Let line position be the text track cue computed line position.
+    int linePosition = m_cue->calculateComputedLinePosition();
+
+    // 4. Vertical Growing Left: Add one to line position then negate it.
+    if (m_cue->getWritingDirection() == TextTrackCue::VerticalGrowingLeft)
+        linePosition = -(linePosition + 1);
+
+    // 5. Let position be the result of multiplying step and line position.
+    position = step * linePosition;
+
+    // 6. Vertical Growing Left: Decrease position by the width of the
+    // bounding box of the boxes in boxes, then increase position by step.
+    if (m_cue->getWritingDirection() == TextTrackCue::VerticalGrowingLeft) {
+        position -= width();
+        position += step;
+    }
+
+    // 7. If line position is less than zero...
+    if (linePosition < 0) {
+        // Horizontal / Vertical: ... then increase position by the
+        // height / width of the video's rendering area ...
+        position += m_cue->getWritingDirection() == TextTrackCue::Horizontal ? parentBlock->height() : parentBlock->width();
+
+        // ... and negate step.
+        step = -step;
+    }
+
+    return true;
+}
+
+void RenderTextTrackCue::placeBoxInDefaultPosition(LayoutUnit position, bool& switched)
+{
+    // 8. Move all boxes in boxes ...
+    if (m_cue->getWritingDirection() == TextTrackCue::Horizontal)
+        // Horizontal: ... down by the distance given by position
+        setY(y() + position);
+    else
+        // Vertical: ... right by the distance given by position
+        setX(x() + position);
+
+    // 9. Default: Remember the position of all the boxes in boxes as their
+    // default position.
+    m_fallbackPosition = FloatPoint(x(), y());
+
+    // 10. Let switched be false.
+    switched = false;
+}
+
+bool RenderTextTrackCue::isOutside() const
+{
+    return !containingBlock()->absoluteBoundingBoxRect().contains(absoluteContentBox());
+}
+
+bool RenderTextTrackCue::isOverlapping() const
+{
+    for (RenderObject* box = previousSibling(); box; box = box->previousSibling()) {
+        IntRect boxRect = box->absoluteBoundingBoxRect();
+
+        if (absoluteBoundingBoxRect().intersects(boxRect))
+            return true;
+    }
+
+    return false;
+}
+
+bool RenderTextTrackCue::shouldSwitchDirection(InlineFlowBox* firstLineBox, LayoutUnit step) const
+{
+    LayoutUnit top = y();
+    LayoutUnit left = x();
+    LayoutUnit bottom = top + firstLineBox->height();
+    LayoutUnit right = left + firstLineBox->width();
+
+    // 12. Horizontal: If step is negative and the top of the first line
+    // box in boxes is now above the top of the video's rendering area,
+    // or if step is positive and the bottom of the first line box in
+    // boxes is now below the bottom of the video's rendering area, jump
+    // to the step labeled switch direction.
+    LayoutUnit parentHeight = containingBlock()->height();
+    if (m_cue->getWritingDirection() == TextTrackCue::Horizontal && ((step < 0 && top < 0) || (step > 0 && bottom > parentHeight)))
+        return true;
+
+    // 12. Vertical: If step is negative and the left edge of the first line
+    // box in boxes is now to the left of the left edge of the video's
+    // rendering area, or if step is positive and the right edge of the
+    // first line box in boxes is now to the right of the right edge of
+    // the video's rendering area, jump to the step labeled switch direction.
+    LayoutUnit parentWidth = containingBlock()->width();
+    if (m_cue->getWritingDirection() != TextTrackCue::Horizontal && ((step < 0 && left < 0) || (step > 0 && right > parentWidth)))
+        return true;
+
+    return false;
+}
+
+void RenderTextTrackCue::moveBoxesByStep(LayoutUnit step)
+{
+    // 13. Horizontal: Move all the boxes in boxes down by the distance
+    // given by step. (If step is negative, then this will actually
+    // result in an upwards movement of the boxes in absolute terms.)
+    if (m_cue->getWritingDirection() == TextTrackCue::Horizontal)
+        setY(y() + step);
+
+    // 13. Vertical: Move all the boxes in boxes right by the distance
+    // given by step. (If step is negative, then this will actually
+    // result in a leftwards movement of the boxes in absolute terms.)
+    else
+        setX(x() + step);
+}
+
+bool RenderTextTrackCue::switchDirection(bool& switched, LayoutUnit& step)
+{
+    // 15. Switch direction: Move all the boxes in boxes back to their
+    // default position as determined in the step above labeled default.
+    setX(m_fallbackPosition.x());
+    setY(m_fallbackPosition.y());
+
+    // 16. If switched is true, jump to the step labeled done
+    // positioning below.
+    if (switched)
+        return false;
+
+    // 17. Negate step.
+    step = -step;
+
+    // 18. Set switched to true.
+    switched = true;
+    return true;
+}
+
+void RenderTextTrackCue::repositionCueSnapToLinesSet()
+{
+    InlineFlowBox* firstLineBox;
+    LayoutUnit step;
+    LayoutUnit position;
+
+    if (!findFirstLineBox(firstLineBox))
+        return;
+
+    if (!initializeLayoutParameters(firstLineBox, step, position))
+        return;
+
+    bool switched;
+    placeBoxInDefaultPosition(position, switched);
+
+    // 11. Step loop: If none of the boxes in boxes would overlap any of the boxes
+    // in output and all the boxes in output are within the video's rendering area
+    // then jump to the step labeled done positioning.
+    while (isOutside() || isOverlapping()) {
+        if (!shouldSwitchDirection(firstLineBox, step))
+            // 13. Move all the boxes in boxes ...
+            // 14. Jump back to the step labeled step loop.
+            moveBoxesByStep(step);
+        else if (!switchDirection(switched, step))
+            break;
+
+        // 19. Jump back to the step labeled step loop.
+    }
+
+    // Acommodate extra top and bottom padding, border or margin.
+    // Note: this is supported only for internal UA styling, not through the cue selector.
+    if (hasInlineDirectionBordersPaddingOrMargin()) {
+        IntRect containerRect = containingBlock()->absoluteBoundingBoxRect();
+        IntRect cueRect = absoluteBoundingBoxRect();
+
+        int topOverflow = cueRect.y() - containerRect.y();
+        int bottomOverflow = containerRect.y() + containerRect.height() - cueRect.y() - cueRect.height();
+
+        int adjustment = 0;
+        if (topOverflow < 0)
+            adjustment = -topOverflow;
+        else if (bottomOverflow < 0)
+            adjustment = bottomOverflow;
+
+        if (adjustment)
+            setY(y() + adjustment);
+    }
+}
+
+void RenderTextTrackCue::repositionGenericCue()
+{
+    TextTrackCueGeneric* cue = static_cast<TextTrackCueGeneric*>(m_cue);
+    if (!cue->useDefaultPosition())
+        return;
+
+    ASSERT(firstChild());
+
+    InlineFlowBox* firstLineBox;
+    if (!findFirstLineBox(firstLineBox))
+        return;
+
+    LayoutUnit parentWidth = containingBlock()->logicalWidth();
+    LayoutUnit width = firstLineBox->width();
+    LayoutUnit right = (parentWidth / 2) - (width / 2);
+    setX(right);
+}
+
+void RenderTextTrackCue::repositionCueSnapToLinesNotSet()
+{
+    // FIXME: Implement overlapping detection when snap-to-lines is not set. http://wkb.ug/84296
+}
+
+} // namespace WebCore
+
diff --git a/Source/core/rendering/RenderTextTrackCue.h b/Source/core/rendering/RenderTextTrackCue.h
new file mode 100644
index 0000000..08f106a
--- /dev/null
+++ b/Source/core/rendering/RenderTextTrackCue.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2012 Victor Carbune (victor@rosedu.org)
+ *
+ * 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 RenderTextTrackCue_h
+#define RenderTextTrackCue_h
+
+#include "core/platform/graphics/FloatPoint.h"
+#include "core/rendering/RenderBlock.h"
+#include "core/rendering/RenderInline.h"
+#include "core/rendering/RenderView.h"
+
+namespace WebCore {
+
+class TextTrackCueBox;
+
+class RenderTextTrackCue FINAL : public RenderBlock {
+public:
+    explicit RenderTextTrackCue(TextTrackCueBox*);
+
+private:
+    virtual void layout() OVERRIDE;
+
+    bool isOutside() const;
+    bool isOverlapping() const;
+    bool shouldSwitchDirection(InlineFlowBox*, LayoutUnit) const;
+
+    void moveBoxesByStep(LayoutUnit);
+    bool switchDirection(bool&, LayoutUnit&);
+
+    bool findFirstLineBox(InlineFlowBox*&);
+    bool initializeLayoutParameters(InlineFlowBox*, LayoutUnit&, LayoutUnit&);
+    void placeBoxInDefaultPosition(LayoutUnit, bool&);
+    void repositionCueSnapToLinesSet();
+    void repositionCueSnapToLinesNotSet();
+    void repositionGenericCue();
+
+    TextTrackCue* m_cue;
+    FloatPoint m_fallbackPosition;
+};
+
+} // namespace WebCore
+
+#endif // RenderTextTrackCue_h
diff --git a/Source/core/rendering/RenderTheme.cpp b/Source/core/rendering/RenderTheme.cpp
new file mode 100644
index 0000000..d160a0f
--- /dev/null
+++ b/Source/core/rendering/RenderTheme.cpp
@@ -0,0 +1,1205 @@
+/**
+ * This file is part of the theme implementation for form controls in WebCore.
+ *
+ * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2012 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 "core/rendering/RenderTheme.h"
+
+#include "CSSValueKeywords.h"
+#include "HTMLNames.h"
+#include "core/dom/Document.h"
+#include "core/editing/FrameSelection.h"
+#include "core/fileapi/FileList.h"
+#include "core/html/HTMLInputElement.h"
+#include "core/html/HTMLMeterElement.h"
+#include "core/html/shadow/MediaControlElements.h"
+#include "core/html/shadow/SpinButtonElement.h"
+#include "core/html/shadow/TextControlInnerElements.h"
+#include "core/page/FocusController.h"
+#include "core/page/Frame.h"
+#include "core/page/Page.h"
+#include "core/page/Settings.h"
+#include "core/platform/FileSystem.h"
+#include "core/platform/FloatConversion.h"
+#include "core/platform/LocalizedStrings.h"
+#include "core/platform/graphics/FontSelector.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/platform/graphics/StringTruncator.h"
+#include "core/rendering/PaintInfo.h"
+#include "core/rendering/RenderMeter.h"
+#include "core/rendering/RenderView.h"
+#include "core/rendering/style/RenderStyle.h"
+
+#if ENABLE(INPUT_SPEECH)
+#include "core/rendering/RenderInputSpeech.h"
+#endif
+
+#if ENABLE(DATALIST_ELEMENT)
+#include "core/dom/ElementShadow.h"
+#include "core/html/HTMLCollection.h"
+#include "core/html/HTMLDataListElement.h"
+#include "core/html/HTMLOptionElement.h"
+#include "core/html/parser/HTMLParserIdioms.h"
+#endif
+
+// The methods in this file are shared by all themes on every platform.
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+static Color& customFocusRingColor()
+{
+    DEFINE_STATIC_LOCAL(Color, color, ());
+    return color;
+}
+
+RenderTheme::RenderTheme()
+#if USE(NEW_THEME)
+    : m_theme(platformTheme())
+#endif
+{
+}
+
+void RenderTheme::adjustStyle(StyleResolver* styleResolver, 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 && isControlStyled(style, border, background, backgroundColor)) {
+        if (part == MenulistPart) {
+            style->setAppearance(MenulistButtonPart);
+            part = MenulistButtonPart;
+        } else
+            style->setAppearance(NoControlPart);
+    }
+
+    if (!style->hasAppearance())
+        return;
+
+#if USE(NEW_THEME)
+    switch (part) {
+    case CheckboxPart:
+    case InnerSpinButtonPart:
+    case RadioPart:
+    case PushButtonPart:
+    case SquareButtonPart:
+    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() != static_cast<int>(style->borderTopWidth())) {
+            if (borderBox.top().value())
+                style->setBorderTopWidth(borderBox.top().value());
+            else
+                style->resetBorderTop();
+        }
+        if (borderBox.right().value() != static_cast<int>(style->borderRightWidth())) {
+            if (borderBox.right().value())
+                style->setBorderRightWidth(borderBox.right().value());
+            else
+                style->resetBorderRight();
+        }
+        if (borderBox.bottom().value() != static_cast<int>(style->borderBottomWidth())) {
+            style->setBorderBottomWidth(borderBox.bottom().value());
+            if (borderBox.bottom().value())
+                style->setBorderBottomWidth(borderBox.bottom().value());
+            else
+                style->resetBorderBottom();
+        }
+        if (borderBox.left().value() != static_cast<int>(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(styleResolver, style, e);
+    case RadioPart:
+        return adjustRadioStyle(styleResolver, style, e);
+    case PushButtonPart:
+    case SquareButtonPart:
+    case ButtonPart:
+        return adjustButtonStyle(styleResolver, style, e);
+    case InnerSpinButtonPart:
+        return adjustInnerSpinButtonStyle(styleResolver, style, e);
+#endif
+    case TextFieldPart:
+        return adjustTextFieldStyle(styleResolver, style, e);
+    case TextAreaPart:
+        return adjustTextAreaStyle(styleResolver, style, e);
+    case MenulistPart:
+        return adjustMenuListStyle(styleResolver, style, e);
+    case MenulistButtonPart:
+        return adjustMenuListButtonStyle(styleResolver, style, e);
+    case MediaPlayButtonPart:
+    case MediaCurrentTimePart:
+    case MediaTimeRemainingPart:
+    case MediaEnterFullscreenButtonPart:
+    case MediaExitFullscreenButtonPart:
+    case MediaMuteButtonPart:
+    case MediaVolumeSliderContainerPart:
+        return adjustMediaControlStyle(styleResolver, style, e);
+    case MediaSliderPart:
+    case MediaVolumeSliderPart:
+    case MediaFullScreenVolumeSliderPart:
+    case SliderHorizontalPart:
+    case SliderVerticalPart:
+        return adjustSliderTrackStyle(styleResolver, style, e);
+    case SliderThumbHorizontalPart:
+    case SliderThumbVerticalPart:
+        return adjustSliderThumbStyle(styleResolver, style, e);
+    case SearchFieldPart:
+        return adjustSearchFieldStyle(styleResolver, style, e);
+    case SearchFieldCancelButtonPart:
+        return adjustSearchFieldCancelButtonStyle(styleResolver, style, e);
+    case SearchFieldDecorationPart:
+        return adjustSearchFieldDecorationStyle(styleResolver, style, e);
+    case SearchFieldResultsDecorationPart:
+        return adjustSearchFieldResultsDecorationStyle(styleResolver, style, e);
+    case SearchFieldResultsButtonPart:
+        return adjustSearchFieldResultsButtonStyle(styleResolver, style, e);
+    case ProgressBarPart:
+        return adjustProgressBarStyle(styleResolver, style, e);
+    case MeterPart:
+    case RelevancyLevelIndicatorPart:
+    case ContinuousCapacityLevelIndicatorPart:
+    case DiscreteCapacityLevelIndicatorPart:
+    case RatingLevelIndicatorPart:
+        return adjustMeterStyle(styleResolver, style, e);
+#if ENABLE(INPUT_SPEECH)
+    case InputSpeechButtonPart:
+        return adjustInputFieldSpeechButtonStyle(styleResolver, style, e);
+#endif
+    default:
+        break;
+    }
+}
+
+bool RenderTheme::paint(RenderObject* o, const 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 ButtonPart:
+    case InnerSpinButtonPart:
+        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 ButtonPart:
+        return paintButton(o, paintInfo, r);
+    case InnerSpinButtonPart:
+        return paintInnerSpinButton(o, paintInfo, r);
+#endif
+    case MenulistPart:
+        return paintMenuList(o, paintInfo, r);
+    case MeterPart:
+    case RelevancyLevelIndicatorPart:
+    case ContinuousCapacityLevelIndicatorPart:
+    case DiscreteCapacityLevelIndicatorPart:
+    case RatingLevelIndicatorPart:
+        return paintMeter(o, paintInfo, r);
+    case ProgressBarPart:
+        return paintProgressBar(o, paintInfo, r);
+    case SliderHorizontalPart:
+    case SliderVerticalPart:
+        return paintSliderTrack(o, paintInfo, r);
+    case SliderThumbHorizontalPart:
+    case SliderThumbVerticalPart:
+        return paintSliderThumb(o, paintInfo, r);
+    case MediaEnterFullscreenButtonPart:
+    case MediaExitFullscreenButtonPart:
+        return paintMediaFullscreenButton(o, paintInfo, r);
+    case MediaPlayButtonPart:
+        return paintMediaPlayButton(o, paintInfo, r);
+    case MediaOverlayPlayButtonPart:
+        return paintMediaOverlayPlayButton(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 MediaRewindButtonPart:
+        return paintMediaRewindButton(o, paintInfo, r);
+    case MediaReturnToRealtimeButtonPart:
+        return paintMediaReturnToRealtimeButton(o, paintInfo, r);
+    case MediaToggleClosedCaptionsButtonPart:
+        return paintMediaToggleClosedCaptionsButton(o, paintInfo, r);
+    case MediaSliderPart:
+        return paintMediaSliderTrack(o, paintInfo, r);
+    case MediaSliderThumbPart:
+        return paintMediaSliderThumb(o, paintInfo, r);
+    case MediaVolumeSliderMuteButtonPart:
+        return paintMediaMuteButton(o, paintInfo, r);
+    case MediaVolumeSliderContainerPart:
+        return paintMediaVolumeSliderContainer(o, paintInfo, r);
+    case MediaVolumeSliderPart:
+        return paintMediaVolumeSliderTrack(o, paintInfo, r);
+    case MediaVolumeSliderThumbPart:
+        return paintMediaVolumeSliderThumb(o, paintInfo, r);
+    case MediaFullScreenVolumeSliderPart:
+        return paintMediaFullScreenVolumeSliderTrack(o, paintInfo, r);
+    case MediaFullScreenVolumeSliderThumbPart:
+        return paintMediaFullScreenVolumeSliderThumb(o, paintInfo, r);
+    case MediaTimeRemainingPart:
+        return paintMediaTimeRemaining(o, paintInfo, r);
+    case MediaCurrentTimePart:
+        return paintMediaCurrentTime(o, paintInfo, r);
+    case MediaControlsBackgroundPart:
+        return paintMediaControlsBackground(o, paintInfo, r);
+    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);
+#if ENABLE(INPUT_SPEECH)
+    case InputSpeechButtonPart:
+        return paintInputFieldSpeechButton(o, paintInfo, r);
+#endif
+    default:
+        break;
+    }
+
+    return true; // We don't support the appearance, so let the normal background/border paint.
+}
+
+bool RenderTheme::paintBorderOnly(RenderObject* o, const 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:
+    case SearchFieldPart:
+        return true;
+    case CheckboxPart:
+    case RadioPart:
+    case PushButtonPart:
+    case SquareButtonPart:
+    case ButtonPart:
+    case MenulistPart:
+    case MeterPart:
+    case RelevancyLevelIndicatorPart:
+    case ContinuousCapacityLevelIndicatorPart:
+    case DiscreteCapacityLevelIndicatorPart:
+    case RatingLevelIndicatorPart:
+    case ProgressBarPart:
+    case SliderHorizontalPart:
+    case SliderVerticalPart:
+    case SliderThumbHorizontalPart:
+    case SliderThumbVerticalPart:
+    case SearchFieldCancelButtonPart:
+    case SearchFieldDecorationPart:
+    case SearchFieldResultsDecorationPart:
+    case SearchFieldResultsButtonPart:
+#if ENABLE(INPUT_SPEECH)
+    case InputSpeechButtonPart:
+#endif
+    default:
+        break;
+    }
+
+    return false;
+}
+
+bool RenderTheme::paintDecorations(RenderObject* o, const 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 ButtonPart:
+    case MenulistPart:
+    case MeterPart:
+    case RelevancyLevelIndicatorPart:
+    case ContinuousCapacityLevelIndicatorPart:
+    case DiscreteCapacityLevelIndicatorPart:
+    case RatingLevelIndicatorPart:
+    case ProgressBarPart:
+    case SliderHorizontalPart:
+    case SliderVerticalPart:
+    case SliderThumbHorizontalPart:
+    case SliderThumbVerticalPart:
+    case SearchFieldPart:
+    case SearchFieldCancelButtonPart:
+    case SearchFieldDecorationPart:
+    case SearchFieldResultsDecorationPart:
+    case SearchFieldResultsButtonPart:
+#if ENABLE(INPUT_SPEECH)
+    case InputSpeechButtonPart:
+#endif
+    default:
+        break;
+    }
+
+    return false;
+}
+
+String RenderTheme::formatMediaControlsTime(float time) const
+{
+    if (!std::isfinite(time))
+        time = 0;
+    int seconds = (int)fabsf(time);
+    int hours = seconds / (60 * 60);
+    int minutes = (seconds / 60) % 60;
+    seconds %= 60;
+    if (hours) {
+        if (hours > 9)
+            return String::format("%s%02d:%02d:%02d", (time < 0 ? "-" : ""), hours, minutes, seconds);
+
+        return String::format("%s%01d:%02d:%02d", (time < 0 ? "-" : ""), hours, minutes, seconds);
+    }
+
+    return String::format("%s%02d:%02d", (time < 0 ? "-" : ""), minutes, seconds);
+}
+
+String RenderTheme::formatMediaControlsCurrentTime(float currentTime, float /*duration*/) const
+{
+    return formatMediaControlsTime(currentTime);
+}
+
+Color RenderTheme::activeSelectionBackgroundColor() const
+{
+    if (!m_activeSelectionBackgroundColor.isValid())
+        m_activeSelectionBackgroundColor = platformActiveSelectionBackgroundColor().blendWithWhite();
+    return m_activeSelectionBackgroundColor;
+}
+
+Color RenderTheme::inactiveSelectionBackgroundColor() const
+{
+    if (!m_inactiveSelectionBackgroundColor.isValid())
+        m_inactiveSelectionBackgroundColor = platformInactiveSelectionBackgroundColor().blendWithWhite();
+    return m_inactiveSelectionBackgroundColor;
+}
+
+Color RenderTheme::activeSelectionForegroundColor() const
+{
+    if (!m_activeSelectionForegroundColor.isValid() && supportsSelectionForegroundColors())
+        m_activeSelectionForegroundColor = platformActiveSelectionForegroundColor();
+    return m_activeSelectionForegroundColor;
+}
+
+Color RenderTheme::inactiveSelectionForegroundColor() const
+{
+    if (!m_inactiveSelectionForegroundColor.isValid() && supportsSelectionForegroundColors())
+        m_inactiveSelectionForegroundColor = platformInactiveSelectionForegroundColor();
+    return m_inactiveSelectionForegroundColor;
+}
+
+Color RenderTheme::activeListBoxSelectionBackgroundColor() const
+{
+    if (!m_activeListBoxSelectionBackgroundColor.isValid())
+        m_activeListBoxSelectionBackgroundColor = platformActiveListBoxSelectionBackgroundColor();
+    return m_activeListBoxSelectionBackgroundColor;
+}
+
+Color RenderTheme::inactiveListBoxSelectionBackgroundColor() const
+{
+    if (!m_inactiveListBoxSelectionBackgroundColor.isValid())
+        m_inactiveListBoxSelectionBackgroundColor = platformInactiveListBoxSelectionBackgroundColor();
+    return m_inactiveListBoxSelectionBackgroundColor;
+}
+
+Color RenderTheme::activeListBoxSelectionForegroundColor() const
+{
+    if (!m_activeListBoxSelectionForegroundColor.isValid() && supportsListBoxSelectionForegroundColors())
+        m_activeListBoxSelectionForegroundColor = platformActiveListBoxSelectionForegroundColor();
+    return m_activeListBoxSelectionForegroundColor;
+}
+
+Color RenderTheme::inactiveListBoxSelectionForegroundColor() const
+{
+    if (!m_inactiveListBoxSelectionForegroundColor.isValid() && supportsListBoxSelectionForegroundColors())
+        m_inactiveListBoxSelectionForegroundColor = platformInactiveListBoxSelectionForegroundColor();
+    return m_inactiveListBoxSelectionForegroundColor;
+}
+
+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::platformActiveSelectionForegroundColor() const
+{
+    // Use a white color by default if the platform theme doesn't define anything.
+    return Color::white;
+}
+
+Color RenderTheme::platformInactiveSelectionBackgroundColor() const
+{
+    // Use a grey color by default if the platform theme doesn't define anything.
+    // This color matches Firefox's inactive color.
+    return Color(176, 176, 176);
+}
+
+Color RenderTheme::platformInactiveSelectionForegroundColor() const
+{
+    // Use a black color by default.
+    return Color::black;
+}
+
+Color RenderTheme::platformActiveListBoxSelectionBackgroundColor() const
+{
+    return platformActiveSelectionBackgroundColor();
+}
+
+Color RenderTheme::platformActiveListBoxSelectionForegroundColor() const
+{
+    return platformActiveSelectionForegroundColor();
+}
+
+Color RenderTheme::platformInactiveListBoxSelectionBackgroundColor() const
+{
+    return platformInactiveSelectionBackgroundColor();
+}
+
+Color RenderTheme::platformInactiveListBoxSelectionForegroundColor() const
+{
+    return platformInactiveSelectionForegroundColor();
+}
+
+int RenderTheme::baselinePosition(const RenderObject* o) const
+{
+    if (!o->isBox())
+        return 0;
+
+    const RenderBox* box = toRenderBox(o);
+
+#if USE(NEW_THEME)
+    return box->height() + box->marginTop() + m_theme->baselinePositionAdjustment(o->style()->appearance()) * o->style()->effectiveZoom();
+#else
+    return box->height() + box->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;
+}
+
+static bool isBackgroundOrBorderStyled(const RenderStyle& style, const BorderData& border, const FillLayer& background, const Color& backgroundColor)
+{
+    // Test the style to see if the UA border and background match.
+    return style.border() != border
+        || *style.backgroundLayers() != background
+        || style.visitedDependentColor(CSSPropertyBackgroundColor) != backgroundColor;
+}
+
+bool RenderTheme::isControlStyled(const RenderStyle* style, const BorderData& border, const FillLayer& background, const Color& backgroundColor) const
+{
+    switch (style->appearance()) {
+    case PushButtonPart:
+    case SquareButtonPart:
+    case ButtonPart:
+    case ProgressBarPart:
+    case MeterPart:
+    case RelevancyLevelIndicatorPart:
+    case ContinuousCapacityLevelIndicatorPart:
+    case DiscreteCapacityLevelIndicatorPart:
+    case RatingLevelIndicatorPart:
+        return isBackgroundOrBorderStyled(*style, border, background, backgroundColor);
+
+    case ListboxPart:
+    case MenulistPart:
+    case SearchFieldPart:
+    case TextAreaPart:
+    case TextFieldPart:
+        return isBackgroundOrBorderStyled(*style, border, background, backgroundColor) || style->boxShadow();
+
+    case SliderHorizontalPart:
+    case SliderVerticalPart:
+        return style->boxShadow();
+
+    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());
+#else
+    UNUSED_PARAM(o);
+    UNUSED_PARAM(r);
+#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 don't 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 (isSpinUpButtonPartHovered(o))
+            result |= SpinUpState;
+    }
+    if (isPressed(o)) {
+        result |= PressedState;
+        if (isSpinUpButtonPartPressed(o))
+            result |= SpinUpState;
+    }
+    if (isFocused(o) && o->style()->outlineStyleIsAuto())
+        result |= FocusState;
+    if (isEnabled(o))
+        result |= EnabledState;
+    if (isChecked(o))
+        result |= CheckedState;
+    if (isReadOnlyControl(o))
+        result |= ReadOnlyState;
+    if (!isActive(o))
+        result |= WindowInactiveState;
+    if (isIndeterminate(o))
+        result |= IndeterminateState;
+    return result;
+}
+
+bool RenderTheme::isActive(const RenderObject* o) const
+{
+    Node* node = o->node();
+    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->node())
+        return false;
+
+    HTMLInputElement* inputElement = o->node()->toInputElement();
+    if (!inputElement)
+        return false;
+
+    return inputElement->shouldAppearChecked();
+}
+
+bool RenderTheme::isIndeterminate(const RenderObject* o) const
+{
+    if (!o->node())
+        return false;
+
+    HTMLInputElement* inputElement = o->node()->toInputElement();
+    if (!inputElement)
+        return false;
+
+    return inputElement->shouldAppearIndeterminate();
+}
+
+bool RenderTheme::isEnabled(const RenderObject* o) const
+{
+    Node* node = o->node();
+    if (!node || !node->isElementNode())
+        return true;
+    return !toElement(node)->isDisabledFormControl();
+}
+
+bool RenderTheme::isFocused(const RenderObject* o) const
+{
+    Node* node = o->node();
+    if (!node)
+        return false;
+
+    node = node->focusDelegate();
+    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->node())
+        return false;
+    return o->node()->active();
+}
+
+bool RenderTheme::isSpinUpButtonPartPressed(const RenderObject* o) const
+{
+    Node* node = o->node();
+    if (!node || !node->active() || !node->isElementNode()
+        || !toElement(node)->isSpinButtonElement())
+        return false;
+    SpinButtonElement* element = static_cast<SpinButtonElement*>(node);
+    return element->upDownState() == SpinButtonElement::Up;
+}
+
+bool RenderTheme::isReadOnlyControl(const RenderObject* o) const
+{
+    Node* node = o->node();
+    if (!node || !node->isElementNode())
+        return false;
+    return toElement(node)->matchesReadOnlyPseudoClass();
+}
+
+bool RenderTheme::isHovered(const RenderObject* o) const
+{
+    Node* node = o->node();
+    if (!node)
+        return false;
+    if (!node->isElementNode() || !toElement(node)->isSpinButtonElement())
+        return node->hovered();
+    SpinButtonElement* element = static_cast<SpinButtonElement*>(node);
+    return element->hovered() && element->upDownState() != SpinButtonElement::Indeterminate;
+}
+
+bool RenderTheme::isSpinUpButtonPartHovered(const RenderObject* o) const
+{
+    Node* node = o->node();
+    if (!node || !node->isElementNode() || !toElement(node)->isSpinButtonElement())
+        return false;
+    SpinButtonElement* element = static_cast<SpinButtonElement*>(node);
+    return element->upDownState() == SpinButtonElement::Up;
+}
+
+#if !USE(NEW_THEME)
+
+void RenderTheme::adjustCheckboxStyle(StyleResolver*, RenderStyle* style, Element*) 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();
+}
+
+void RenderTheme::adjustRadioStyle(StyleResolver*, RenderStyle* style, Element*) 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();
+}
+
+void RenderTheme::adjustButtonStyle(StyleResolver*, RenderStyle* style, Element*) 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);
+}
+
+void RenderTheme::adjustInnerSpinButtonStyle(StyleResolver*, RenderStyle*, Element*) const
+{
+}
+#endif
+
+void RenderTheme::adjustTextFieldStyle(StyleResolver*, RenderStyle*, Element*) const
+{
+}
+
+void RenderTheme::adjustTextAreaStyle(StyleResolver*, RenderStyle*, Element*) const
+{
+}
+
+void RenderTheme::adjustMenuListStyle(StyleResolver*, RenderStyle*, Element*) const
+{
+}
+
+#if ENABLE(INPUT_SPEECH)
+void RenderTheme::adjustInputFieldSpeechButtonStyle(StyleResolver* styleResolver, RenderStyle* style, Element* element) const
+{
+    RenderInputSpeech::adjustInputFieldSpeechButtonStyle(styleResolver, style, element);
+}
+
+bool RenderTheme::paintInputFieldSpeechButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
+{
+    return RenderInputSpeech::paintInputFieldSpeechButton(object, paintInfo, rect);
+}
+#endif
+
+void RenderTheme::adjustMeterStyle(StyleResolver*, RenderStyle* style, Element*) const
+{
+}
+
+IntSize RenderTheme::meterSizeForBounds(const RenderMeter*, const IntRect& bounds) const
+{
+    return bounds.size();
+}
+
+bool RenderTheme::supportsMeter(ControlPart) const
+{
+    return false;
+}
+
+bool RenderTheme::paintMeter(RenderObject*, const PaintInfo&, const IntRect&)
+{
+    return true;
+}
+
+#if ENABLE(DATALIST_ELEMENT)
+LayoutUnit RenderTheme::sliderTickSnappingThreshold() const
+{
+    return 0;
+}
+
+void RenderTheme::paintSliderTicks(RenderObject* o, const PaintInfo& paintInfo, const IntRect& rect)
+{
+    Node* node = o->node();
+    if (!node)
+        return;
+
+    HTMLInputElement* input = node->toInputElement();
+    if (!input)
+        return;
+
+    HTMLDataListElement* dataList = static_cast<HTMLDataListElement*>(input->list());
+    if (!dataList)
+        return;
+
+    double min = input->minimum();
+    double max = input->maximum();
+    ControlPart part = o->style()->appearance();
+    // We don't support ticks on alternate sliders like MediaVolumeSliders.
+    if (part !=  SliderHorizontalPart && part != SliderVerticalPart)
+        return;
+    bool isHorizontal = part ==  SliderHorizontalPart;
+
+    IntSize thumbSize;
+    RenderObject* thumbRenderer = input->sliderThumbElement()->renderer();
+    if (thumbRenderer) {
+        RenderStyle* thumbStyle = thumbRenderer->style();
+        int thumbWidth = thumbStyle->width().intValue();
+        int thumbHeight = thumbStyle->height().intValue();
+        thumbSize.setWidth(isHorizontal ? thumbWidth : thumbHeight);
+        thumbSize.setHeight(isHorizontal ? thumbHeight : thumbWidth);
+    }
+
+    IntSize tickSize = sliderTickSize();
+    float zoomFactor = o->style()->effectiveZoom();
+    FloatRect tickRect;
+    int tickRegionSideMargin = 0;
+    int tickRegionWidth = 0;
+    IntRect trackBounds;
+    RenderObject* trackRenderer = input->sliderTrackElement()->renderer();
+    // We can ignoring transforms because transform is handled by the graphics context.
+    if (trackRenderer)
+        trackBounds = trackRenderer->absoluteBoundingBoxRectIgnoringTransforms();
+    IntRect sliderBounds = o->absoluteBoundingBoxRectIgnoringTransforms();
+
+    // Make position relative to the transformed ancestor element.
+    trackBounds.setX(trackBounds.x() - sliderBounds.x() + rect.x());
+    trackBounds.setY(trackBounds.y() - sliderBounds.y() + rect.y());
+
+    if (isHorizontal) {
+        tickRect.setWidth(floor(tickSize.width() * zoomFactor));
+        tickRect.setHeight(floor(tickSize.height() * zoomFactor));
+        tickRect.setY(floor(rect.y() + rect.height() / 2.0 + sliderTickOffsetFromTrackCenter() * zoomFactor));
+        tickRegionSideMargin = trackBounds.x() + (thumbSize.width() - tickSize.width() * zoomFactor) / 2.0;
+        tickRegionWidth = trackBounds.width() - thumbSize.width();
+    } else {
+        tickRect.setWidth(floor(tickSize.height() * zoomFactor));
+        tickRect.setHeight(floor(tickSize.width() * zoomFactor));
+        tickRect.setX(floor(rect.x() + rect.width() / 2.0 + sliderTickOffsetFromTrackCenter() * zoomFactor));
+        tickRegionSideMargin = trackBounds.y() + (thumbSize.width() - tickSize.width() * zoomFactor) / 2.0;
+        tickRegionWidth = trackBounds.height() - thumbSize.width();
+    }
+    RefPtr<HTMLCollection> options = dataList->options();
+    GraphicsContextStateSaver stateSaver(*paintInfo.context);
+    paintInfo.context->setFillColor(o->style()->visitedDependentColor(CSSPropertyColor), ColorSpaceDeviceRGB);
+    for (unsigned i = 0; Node* node = options->item(i); i++) {
+        ASSERT(node->hasTagName(optionTag));
+        HTMLOptionElement* optionElement = toHTMLOptionElement(node);
+        String value = optionElement->value();
+        if (!input->isValidValue(value))
+            continue;
+        double parsedValue = parseToDoubleForNumberType(input->sanitizeValue(value));
+        double tickFraction = (parsedValue - min) / (max - min);
+        double tickRatio = isHorizontal && o->style()->isLeftToRightDirection() ? tickFraction : 1.0 - tickFraction;
+        double tickPosition = round(tickRegionSideMargin + tickRegionWidth * tickRatio);
+        if (isHorizontal)
+            tickRect.setX(tickPosition);
+        else
+            tickRect.setY(tickPosition);
+        paintInfo.context->fillRect(tickRect);
+    }
+}
+#endif
+
+double RenderTheme::animationRepeatIntervalForProgressBar(RenderProgress*) const
+{
+    return 0;
+}
+
+double RenderTheme::animationDurationForProgressBar(RenderProgress*) const
+{
+    return 0;
+}
+
+void RenderTheme::adjustProgressBarStyle(StyleResolver*, RenderStyle*, Element*) const
+{
+}
+
+bool RenderTheme::shouldHaveSpinButton(HTMLInputElement* inputElement) const
+{
+    return inputElement->isSteppable() && !inputElement->isRangeControl();
+}
+
+void RenderTheme::adjustMenuListButtonStyle(StyleResolver*, RenderStyle*, Element*) const
+{
+}
+
+void RenderTheme::adjustMediaControlStyle(StyleResolver*, RenderStyle*, Element*) const
+{
+}
+
+void RenderTheme::adjustSliderTrackStyle(StyleResolver*, RenderStyle*, Element*) const
+{
+}
+
+void RenderTheme::adjustSliderThumbStyle(StyleResolver*, RenderStyle* style, Element* element) const
+{
+    adjustSliderThumbSize(style, element);
+}
+
+void RenderTheme::adjustSliderThumbSize(RenderStyle*, Element*) const
+{
+}
+
+void RenderTheme::adjustSearchFieldStyle(StyleResolver*, RenderStyle*, Element*) const
+{
+}
+
+void RenderTheme::adjustSearchFieldCancelButtonStyle(StyleResolver*, RenderStyle*, Element*) const
+{
+}
+
+void RenderTheme::adjustSearchFieldDecorationStyle(StyleResolver*, RenderStyle*, Element*) const
+{
+}
+
+void RenderTheme::adjustSearchFieldResultsDecorationStyle(StyleResolver*, RenderStyle*, Element*) const
+{
+}
+
+void RenderTheme::adjustSearchFieldResultsButtonStyle(StyleResolver*, RenderStyle*, Element*) const
+{
+}
+
+void RenderTheme::platformColorsDidChange()
+{
+    m_activeSelectionForegroundColor = Color();
+    m_inactiveSelectionForegroundColor = Color();
+    m_activeSelectionBackgroundColor = Color();
+    m_inactiveSelectionBackgroundColor = Color();
+
+    m_activeListBoxSelectionForegroundColor = Color();
+    m_inactiveListBoxSelectionForegroundColor = Color();
+    m_activeListBoxSelectionBackgroundColor = Color();
+    m_inactiveListBoxSelectionForegroundColor = Color();
+
+    Page::scheduleForcedStyleRecalcForAllPages();
+}
+
+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::platformActiveTextSearchHighlightColor() const
+{
+    return Color(255, 150, 50); // Orange.
+}
+
+Color RenderTheme::platformInactiveTextSearchHighlightColor() const
+{
+    return Color(255, 255, 0); // Yellow.
+}
+
+Color RenderTheme::tapHighlightColor()
+{
+    return defaultTheme()->platformTapHighlightColor();
+}
+
+// Value chosen by observation. This can be tweaked.
+static const int minColorContrastValue = 1300;
+// For transparent or translucent background color, use lightening.
+static const int minDisabledColorAlphaValue = 128;
+
+Color RenderTheme::disabledTextColor(const Color& textColor, const Color& backgroundColor) const
+{
+    // 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 || backgroundColor.alpha() < minDisabledColorAlphaValue || 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;
+}
+
+void RenderTheme::setCustomFocusRingColor(const Color& c)
+{
+    customFocusRingColor() = c;
+}
+
+Color RenderTheme::focusRingColor()
+{
+    return customFocusRingColor().isValid() ? customFocusRingColor() : defaultTheme()->platformFocusRingColor();
+}
+
+String RenderTheme::fileListDefaultLabel(bool multipleFilesAllowed) const
+{
+    if (multipleFilesAllowed)
+        return fileButtonNoFilesSelectedLabel();
+    return fileButtonNoFileSelectedLabel();
+}
+
+String RenderTheme::fileListNameForWidth(const FileList* fileList, const Font& font, int width, bool multipleFilesAllowed) const
+{
+    if (width <= 0)
+        return String();
+
+    String string;
+    if (fileList->isEmpty())
+        string = fileListDefaultLabel(multipleFilesAllowed);
+    else if (fileList->length() == 1)
+        string = fileList->item(0)->name();
+    else
+        return StringTruncator::rightTruncate(multipleFileUploadText(fileList->length()), width, font, StringTruncator::EnableRoundingHacks);
+
+    return StringTruncator::centerTruncate(string, width, font, StringTruncator::EnableRoundingHacks);
+}
+
+bool RenderTheme::shouldOpenPickerWithF4Key() const
+{
+    return false;
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderTheme.h b/Source/core/rendering/RenderTheme.h
new file mode 100644
index 0000000..5a3180f
--- /dev/null
+++ b/Source/core/rendering/RenderTheme.h
@@ -0,0 +1,357 @@
+/*
+ * This file is part of the theme implementation for form controls in WebCore.
+ *
+ * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2012 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
+
+#if USE(NEW_THEME)
+#include "core/platform/Theme.h"
+#else
+#include "core/platform/ThemeTypes.h"
+#endif
+#include "core/platform/ScrollTypes.h"
+#include "core/rendering/RenderObject.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class CSSStyleSheet;
+class Element;
+class FileList;
+class HTMLInputElement;
+class PopupMenu;
+class RenderMenuList;
+class RenderMeter;
+class RenderProgress;
+
+class RenderTheme : public RefCounted<RenderTheme> {
+protected:
+    RenderTheme();
+
+public:
+    virtual ~RenderTheme() { }
+
+    // This function is to be implemented in your platform-specific theme implementation to hand back the
+    // appropriate platform theme. When the theme is needed in non-page dependent code, a default theme is
+    // used as fallback, which is returned for a nulled page, so the platform code needs to account for this.
+    static PassRefPtr<RenderTheme> themeForPage(Page* page);
+
+    // When the theme is needed in non-page dependent code, the defaultTheme() is used as fallback.
+    static inline PassRefPtr<RenderTheme> defaultTheme()
+    {
+        return themeForPage(0);
+    };
+
+    // 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(StyleResolver*, RenderStyle*, Element*,  bool UAHasAppearance,
+                     const BorderData&, const FillLayer&, const Color& backgroundColor);
+
+    // 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 PaintInfo&, const IntRect&);
+    bool paintBorderOnly(RenderObject*, const PaintInfo&, const IntRect&);
+    bool paintDecorations(RenderObject*, const 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.
+
+    // These methods return the theme's extra style sheets rules, to let each platform
+    // adjust the default CSS rules in html.css, quirks.css or mediaControls.css.
+    virtual String extraDefaultStyleSheet() { return String(); }
+    virtual String extraQuirksStyleSheet() { return String(); }
+    virtual String extraMediaControlsStyleSheet() { return String(); }
+    virtual String extraFullScreenStyleSheet() { return String(); }
+
+    // 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; }
+
+    // A method asking if the platform is able to show datalist suggestions for a given input type.
+    virtual bool supportsDataListUI(const AtomicString&) const { return false; }
+
+#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
+    // A method asking if the platform is able to show a calendar picker for a given input type.
+    virtual bool supportsCalendarPicker(const AtomicString&) const { return false; }
+#endif
+
+    // Text selection colors.
+    Color activeSelectionBackgroundColor() const;
+    Color inactiveSelectionBackgroundColor() const;
+    Color activeSelectionForegroundColor() const;
+    Color inactiveSelectionForegroundColor() const;
+
+    // List box selection colors
+    Color activeListBoxSelectionBackgroundColor() const;
+    Color activeListBoxSelectionForegroundColor() const;
+    Color inactiveListBoxSelectionBackgroundColor() const;
+    Color inactiveListBoxSelectionForegroundColor() const;
+
+    // Highlighting colors for TextMatches.
+    virtual Color platformActiveTextSearchHighlightColor() const;
+    virtual Color platformInactiveTextSearchHighlightColor() const;
+
+    virtual Color disabledTextColor(const Color& textColor, const Color& backgroundColor) const;
+
+    static Color focusRingColor();
+    virtual Color platformFocusRingColor() const { return Color(0, 0, 0); }
+    static void setCustomFocusRingColor(const Color&);
+    static Color tapHighlightColor();
+    virtual Color platformTapHighlightColor() const { return RenderTheme::defaultTapHighlightColor; }
+    virtual void platformColorsDidChange();
+
+    virtual double caretBlinkInterval() 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(RenderStyle*, Element*) 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; }
+    virtual bool popupOptionSupportsTextIndent() const { return false; }
+
+    virtual ScrollbarControlSize scrollbarControlSizeForPart(ControlPart) { return RegularScrollbar; }
+
+    // Method for painting the caps lock indicator
+    virtual bool paintCapsLockIndicator(RenderObject*, const PaintInfo&, const IntRect&) { return 0; };
+
+    // Returns the repeat interval of the animation for the progress bar.
+    virtual double animationRepeatIntervalForProgressBar(RenderProgress*) const;
+    // Returns the duration of the animation for the progress bar.
+    virtual double animationDurationForProgressBar(RenderProgress*) const;
+
+    // Media controls
+    virtual bool supportsClosedCaptioning() const { return false; }
+    virtual bool hasOwnDisabledStateHandlingFor(ControlPart) const { return false; }
+    virtual bool usesMediaControlStatusDisplay() { return false; }
+    virtual bool usesMediaControlVolumeSlider() const { return true; }
+    virtual bool usesVerticalVolumeSlider() const { return true; }
+    virtual double mediaControlsFadeInDuration() { return 0.1; }
+    virtual double mediaControlsFadeOutDuration() { return 0.3; }
+    virtual String formatMediaControlsTime(float time) const;
+    virtual String formatMediaControlsCurrentTime(float currentTime, float duration) const;
+
+    virtual IntSize meterSizeForBounds(const RenderMeter*, const IntRect&) const;
+    virtual bool supportsMeter(ControlPart) const;
+
+#if ENABLE(DATALIST_ELEMENT)
+    // Returns the threshold distance for snapping to a slider tick mark.
+    virtual LayoutUnit sliderTickSnappingThreshold() const;
+    // Returns size of one slider tick mark for a horizontal track.
+    // For vertical tracks we rotate it and use it. i.e. Width is always length along the track.
+    virtual IntSize sliderTickSize() const = 0;
+    // Returns the distance of slider tick origin from the slider track center.
+    virtual int sliderTickOffsetFromTrackCenter() const = 0;
+    void paintSliderTicks(RenderObject*, const PaintInfo&, const IntRect&);
+#endif
+
+    virtual bool shouldShowPlaceholderWhenFocused() const { return false; }
+    virtual bool shouldHaveSpinButton(HTMLInputElement*) const;
+
+    // Functions for <select> elements.
+    virtual bool delegatesMenuListRendering() const { return false; }
+    virtual bool popsMenuByArrowKeys() const { return false; }
+    virtual bool popsMenuBySpaceOrReturn() const { return false; }
+
+    virtual String fileListDefaultLabel(bool multipleFilesAllowed) const;
+    virtual String fileListNameForWidth(const FileList*, const Font&, int width, bool multipleFilesAllowed) const;
+
+    virtual bool shouldOpenPickerWithF4Key() const;
+
+protected:
+    // The platform selection color.
+    virtual Color platformActiveSelectionBackgroundColor() const;
+    virtual Color platformInactiveSelectionBackgroundColor() const;
+    virtual Color platformActiveSelectionForegroundColor() const;
+    virtual Color platformInactiveSelectionForegroundColor() const;
+
+    virtual Color platformActiveListBoxSelectionBackgroundColor() const;
+    virtual Color platformInactiveListBoxSelectionBackgroundColor() const;
+    virtual Color platformActiveListBoxSelectionForegroundColor() const;
+    virtual Color platformInactiveListBoxSelectionForegroundColor() const;
+
+    virtual bool supportsSelectionForegroundColors() const { return true; }
+    virtual bool supportsListBoxSelectionForegroundColors() const { return true; }
+
+#if !USE(NEW_THEME)
+    // Methods for each appearance value.
+    virtual void adjustCheckboxStyle(StyleResolver*, RenderStyle*, Element*) const;
+    virtual bool paintCheckbox(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
+    virtual void setCheckboxSize(RenderStyle*) const { }
+
+    virtual void adjustRadioStyle(StyleResolver*, RenderStyle*, Element*) const;
+    virtual bool paintRadio(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
+    virtual void setRadioSize(RenderStyle*) const { }
+
+    virtual void adjustButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
+    virtual bool paintButton(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
+    virtual void setButtonSize(RenderStyle*) const { }
+
+    virtual void adjustInnerSpinButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
+    virtual bool paintInnerSpinButton(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
+#endif
+
+    virtual void adjustTextFieldStyle(StyleResolver*, RenderStyle*, Element*) const;
+    virtual bool paintTextField(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
+
+    virtual void adjustTextAreaStyle(StyleResolver*, RenderStyle*, Element*) const;
+    virtual bool paintTextArea(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
+
+    virtual void adjustMenuListStyle(StyleResolver*, RenderStyle*, Element*) const;
+    virtual bool paintMenuList(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
+
+    virtual void adjustMenuListButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
+    virtual bool paintMenuListButton(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
+
+    virtual void adjustMeterStyle(StyleResolver*, RenderStyle*, Element*) const;
+    virtual bool paintMeter(RenderObject*, const PaintInfo&, const IntRect&);
+
+    virtual void adjustProgressBarStyle(StyleResolver*, RenderStyle*, Element*) const;
+    virtual bool paintProgressBar(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
+
+#if ENABLE(INPUT_SPEECH)
+    virtual void adjustInputFieldSpeechButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
+    virtual bool paintInputFieldSpeechButton(RenderObject*, const PaintInfo&, const IntRect&);
+#endif
+
+    virtual void adjustSliderTrackStyle(StyleResolver*, RenderStyle*, Element*) const;
+    virtual bool paintSliderTrack(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
+
+    virtual void adjustSliderThumbStyle(StyleResolver*, RenderStyle*, Element*) const;
+    virtual bool paintSliderThumb(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
+
+    virtual void adjustSearchFieldStyle(StyleResolver*, RenderStyle*, Element*) const;
+    virtual bool paintSearchField(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
+
+    virtual void adjustSearchFieldCancelButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
+    virtual bool paintSearchFieldCancelButton(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
+
+    virtual void adjustSearchFieldDecorationStyle(StyleResolver*, RenderStyle*, Element*) const;
+    virtual bool paintSearchFieldDecoration(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
+
+    virtual void adjustSearchFieldResultsDecorationStyle(StyleResolver*, RenderStyle*, Element*) const;
+    virtual bool paintSearchFieldResultsDecoration(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
+
+    virtual void adjustSearchFieldResultsButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
+    virtual bool paintSearchFieldResultsButton(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
+
+    virtual void adjustMediaControlStyle(StyleResolver*, RenderStyle*, Element*) const;
+    virtual bool paintMediaFullscreenButton(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
+    virtual bool paintMediaPlayButton(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
+    virtual bool paintMediaOverlayPlayButton(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
+    virtual bool paintMediaMuteButton(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
+    virtual bool paintMediaSeekBackButton(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
+    virtual bool paintMediaSeekForwardButton(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
+    virtual bool paintMediaSliderTrack(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
+    virtual bool paintMediaSliderThumb(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
+    virtual bool paintMediaVolumeSliderContainer(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
+    virtual bool paintMediaVolumeSliderTrack(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
+    virtual bool paintMediaVolumeSliderThumb(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
+    virtual bool paintMediaRewindButton(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
+    virtual bool paintMediaReturnToRealtimeButton(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
+    virtual bool paintMediaToggleClosedCaptionsButton(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
+    virtual bool paintMediaControlsBackground(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
+    virtual bool paintMediaCurrentTime(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
+    virtual bool paintMediaTimeRemaining(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
+    virtual bool paintMediaFullScreenVolumeSliderTrack(RenderObject*, const PaintInfo&, const IntRect&) { return true; }
+    virtual bool paintMediaFullScreenVolumeSliderThumb(RenderObject*, const 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 isSpinUpButtonPartPressed(const RenderObject*) const;
+    bool isHovered(const RenderObject*) const;
+    bool isSpinUpButtonPartHovered(const RenderObject*) const;
+    bool isReadOnlyControl(const RenderObject*) const;
+
+private:
+    mutable Color m_activeSelectionBackgroundColor;
+    mutable Color m_inactiveSelectionBackgroundColor;
+    mutable Color m_activeSelectionForegroundColor;
+    mutable Color m_inactiveSelectionForegroundColor;
+
+    mutable Color m_activeListBoxSelectionBackgroundColor;
+    mutable Color m_inactiveListBoxSelectionBackgroundColor;
+    mutable Color m_activeListBoxSelectionForegroundColor;
+    mutable Color m_inactiveListBoxSelectionForegroundColor;
+
+    // This color is expected to be drawn on a semi-transparent overlay,
+    // making it more transparent than its alpha value indicates.
+    static const RGBA32 defaultTapHighlightColor = 0x66000000;
+
+#if USE(NEW_THEME)
+    Theme* m_theme; // The platform-specific theme.
+#endif
+};
+
+} // namespace WebCore
+
+#endif // RenderTheme_h
diff --git a/Source/core/rendering/RenderThemeChromiumAndroid.cpp b/Source/core/rendering/RenderThemeChromiumAndroid.cpp
new file mode 100644
index 0000000..e2b4679
--- /dev/null
+++ b/Source/core/rendering/RenderThemeChromiumAndroid.cpp
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2011 Google 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 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 "core/rendering/RenderThemeChromiumAndroid.h"
+
+#include "CSSValueKeywords.h"
+#include "UserAgentStyleSheets.h"
+#include "core/platform/LayoutTestSupport.h"
+#include "core/platform/ScrollbarTheme.h"
+#include "core/platform/graphics/Color.h"
+#include "core/rendering/PaintInfo.h"
+#include "core/rendering/RenderMediaControlsChromium.h"
+#include "core/rendering/RenderObject.h"
+#include "core/rendering/RenderProgress.h"
+#include "core/rendering/RenderSlider.h"
+
+#include <public/android/WebThemeEngine.h>
+#include <public/Platform.h>
+
+namespace WebCore {
+
+PassRefPtr<RenderTheme> RenderThemeChromiumAndroid::create()
+{
+    return adoptRef(new RenderThemeChromiumAndroid());
+}
+
+PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page* page)
+{
+    static RenderTheme* renderTheme = RenderThemeChromiumAndroid::create().leakRef();
+    return renderTheme;
+}
+
+RenderThemeChromiumAndroid::~RenderThemeChromiumAndroid()
+{
+}
+
+Color RenderThemeChromiumAndroid::systemColor(int cssValueId) const
+{
+    if (isRunningLayoutTest() && cssValueId == CSSValueButtonface) {
+        // Match Chromium Linux' button color in layout tests.
+        static const Color linuxButtonGrayColor(0xffdddddd);
+        return linuxButtonGrayColor;
+    }
+    return RenderTheme::systemColor(cssValueId);
+}
+
+String RenderThemeChromiumAndroid::extraMediaControlsStyleSheet()
+{
+    return String(mediaControlsChromiumAndroidUserAgentStyleSheet, sizeof(mediaControlsChromiumAndroidUserAgentStyleSheet));
+}
+
+String RenderThemeChromiumAndroid::extraDefaultStyleSheet()
+{
+    return RenderThemeChromiumDefault::extraDefaultStyleSheet() +
+        String(themeChromiumAndroidUserAgentStyleSheet, sizeof(themeChromiumAndroidUserAgentStyleSheet));
+}
+
+void RenderThemeChromiumAndroid::adjustInnerSpinButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
+{
+    if (isRunningLayoutTest()) {
+        // Match Chromium Linux spin button style in layout tests.
+        // FIXME: Consider removing the conditional if a future Android theme matches this.
+        IntSize size = WebKit::Platform::current()->themeEngine()->getSize(WebKit::WebThemeEngine::PartInnerSpinButton);
+
+        style->setWidth(Length(size.width(), Fixed));
+        style->setMinWidth(Length(size.width(), Fixed));
+    }
+}
+
+bool RenderThemeChromiumAndroid::paintMediaOverlayPlayButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
+{
+    return RenderMediaControlsChromium::paintMediaControlsPart(MediaOverlayPlayButton, object, paintInfo, rect);
+}
+
+int RenderThemeChromiumAndroid::menuListArrowPadding() const
+{
+    // We cannot use the scrollbar thickness here, as it's width is 0 on Android.
+    // Instead, use the width of the scrollbar down arrow.
+    IntSize scrollbarSize = WebKit::Platform::current()->themeEngine()->getSize(WebKit::WebThemeEngine::PartScrollbarDownArrow);
+    return scrollbarSize.width();
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderThemeChromiumAndroid.h b/Source/core/rendering/RenderThemeChromiumAndroid.h
new file mode 100644
index 0000000..c0c8ea5
--- /dev/null
+++ b/Source/core/rendering/RenderThemeChromiumAndroid.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2011 Google 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 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 RenderThemeChromiumAndroid_h
+#define RenderThemeChromiumAndroid_h
+
+#include "core/rendering/RenderThemeChromiumDefault.h"
+
+namespace WebCore {
+
+class RenderThemeChromiumAndroid : public RenderThemeChromiumDefault {
+public:
+    static PassRefPtr<RenderTheme> create();
+    virtual String extraDefaultStyleSheet() OVERRIDE;
+
+    virtual Color systemColor(int cssValidId) const OVERRIDE;
+
+    virtual void adjustInnerSpinButtonStyle(StyleResolver*, RenderStyle*, Element*) const OVERRIDE;
+
+    virtual bool delegatesMenuListRendering() const OVERRIDE { return true; }
+
+    virtual bool paintMediaOverlayPlayButton(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
+
+    virtual String extraMediaControlsStyleSheet() OVERRIDE;
+
+    virtual Color platformTapHighlightColor() const OVERRIDE
+    {
+        return RenderThemeChromiumAndroid::defaultTapHighlightColor;
+    }
+
+    virtual Color platformActiveSelectionBackgroundColor() const OVERRIDE
+    {
+        return RenderThemeChromiumAndroid::defaultActiveSelectionBackgroundColor;
+    }
+
+protected:
+    virtual int menuListArrowPadding() const OVERRIDE;
+
+private:
+    virtual ~RenderThemeChromiumAndroid();
+
+    static const RGBA32 defaultTapHighlightColor = 0x6633b5e5;
+    static const RGBA32 defaultActiveSelectionBackgroundColor = 0x6633b5e5;
+};
+
+} // namespace WebCore
+
+#endif // RenderThemeChromiumAndroid_h
diff --git a/Source/core/rendering/RenderThemeChromiumCommon.cpp b/Source/core/rendering/RenderThemeChromiumCommon.cpp
new file mode 100644
index 0000000..402720a
--- /dev/null
+++ b/Source/core/rendering/RenderThemeChromiumCommon.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2012 Google 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 "core/rendering/RenderThemeChromiumCommon.h"
+
+#include "core/html/InputTypeNames.h"
+#include "core/platform/LayoutUnit.h"
+
+namespace WebCore {
+
+bool RenderThemeChromiumCommon::supportsDataListUI(const AtomicString& type)
+{
+    return type == InputTypeNames::text() || type == InputTypeNames::search() || type == InputTypeNames::url()
+        || type == InputTypeNames::telephone() || type == InputTypeNames::email() || type == InputTypeNames::number()
+#if ENABLE(INPUT_TYPE_COLOR)
+        || type == InputTypeNames::color()
+#endif
+#if ENABLE(CALENDAR_PICKER)
+        || type == InputTypeNames::date()
+#endif
+        || type == InputTypeNames::datetime()
+        || type == InputTypeNames::datetimelocal()
+        || type == InputTypeNames::month()
+        || type == InputTypeNames::week()
+        || type == InputTypeNames::time()
+        || type == InputTypeNames::range();
+}
+
+#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
+bool RenderThemeChromiumCommon::supportsCalendarPicker(const AtomicString& type)
+{
+    return type == InputTypeNames::date()
+        || type == InputTypeNames::datetime()
+        || type == InputTypeNames::datetimelocal()
+        || type == InputTypeNames::month()
+        || type == InputTypeNames::week();
+}
+#endif
+
+LayoutUnit RenderThemeChromiumCommon::sliderTickSnappingThreshold()
+{
+    return 5;
+}
+
+}
diff --git a/Source/core/rendering/RenderThemeChromiumCommon.h b/Source/core/rendering/RenderThemeChromiumCommon.h
new file mode 100644
index 0000000..24bb2ad
--- /dev/null
+++ b/Source/core/rendering/RenderThemeChromiumCommon.h
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2012 Google 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 RenderThemeChromiumCommon_h
+#define RenderThemeChromiumCommon_h
+
+#include "core/platform/LayoutUnit.h"
+#include <wtf/text/AtomicString.h>
+
+namespace WebCore {
+
+class RenderThemeChromiumCommon {
+public:
+    static bool supportsDataListUI(const AtomicString& type);
+#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
+    static bool supportsCalendarPicker(const AtomicString& type);
+#endif
+    static LayoutUnit sliderTickSnappingThreshold();
+};
+
+}
+
+#endif // RenderThemeChromiumCommon_h
diff --git a/Source/core/rendering/RenderThemeChromiumDefault.cpp b/Source/core/rendering/RenderThemeChromiumDefault.cpp
new file mode 100644
index 0000000..11b6f36
--- /dev/null
+++ b/Source/core/rendering/RenderThemeChromiumDefault.cpp
@@ -0,0 +1,387 @@
+/*
+ * Copyright (C) 2007 Apple Inc.
+ * Copyright (C) 2007 Alp Toker <alp@atoker.com>
+ * Copyright (C) 2008 Collabora Ltd.
+ * Copyright (C) 2008, 2009 Google Inc.
+ * Copyright (C) 2009 Kenneth Rohde Christiansen
+ *
+ * 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 "core/rendering/RenderThemeChromiumDefault.h"
+
+#include "CSSValueKeywords.h"
+#include "UserAgentStyleSheets.h"
+#include "core/platform/ScrollbarTheme.h"
+#include "core/platform/graphics/Color.h"
+#include "core/platform/graphics/skia/PlatformContextSkia.h"
+#include "core/rendering/PaintInfo.h"
+#include "core/rendering/RenderObject.h"
+#include "core/rendering/RenderProgress.h"
+#include "core/rendering/RenderSlider.h"
+#include <public/default/WebThemeEngine.h>
+#include <public/Platform.h>
+#include <public/WebRect.h>
+
+namespace WebCore {
+
+unsigned RenderThemeChromiumDefault::m_activeSelectionBackgroundColor =
+    0xff1e90ff;
+unsigned RenderThemeChromiumDefault::m_activeSelectionForegroundColor =
+    Color::black;
+unsigned RenderThemeChromiumDefault::m_inactiveSelectionBackgroundColor =
+    0xffc8c8c8;
+unsigned RenderThemeChromiumDefault::m_inactiveSelectionForegroundColor =
+    0xff323232;
+
+double RenderThemeChromiumDefault::m_caretBlinkInterval;
+
+static const unsigned defaultButtonBackgroundColor = 0xffdddddd;
+
+static WebKit::WebThemeEngine::State getWebThemeState(const RenderTheme* theme, const RenderObject* o)
+{
+    if (!theme->isEnabled(o))
+        return WebKit::WebThemeEngine::StateDisabled;
+    if (theme->isPressed(o))
+        return WebKit::WebThemeEngine::StatePressed;
+    if (theme->isHovered(o))
+        return WebKit::WebThemeEngine::StateHover;
+
+    return WebKit::WebThemeEngine::StateNormal;
+}
+
+PassRefPtr<RenderTheme> RenderThemeChromiumDefault::create()
+{
+    return adoptRef(new RenderThemeChromiumDefault());
+}
+
+// RenderTheme::themeForPage for Android is defined in RenderThemeChromiumAndroid.cpp.
+#if !OS(ANDROID)
+PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page* page)
+{
+    static RenderTheme* rt = RenderThemeChromiumDefault::create().leakRef();
+    return rt;
+}
+#endif
+
+RenderThemeChromiumDefault::RenderThemeChromiumDefault()
+{
+    m_caretBlinkInterval = RenderTheme::caretBlinkInterval();
+}
+
+RenderThemeChromiumDefault::~RenderThemeChromiumDefault()
+{
+}
+
+Color RenderThemeChromiumDefault::systemColor(int cssValueId) const
+{
+    static const Color defaultButtonGrayColor(0xffdddddd);
+    static const Color defaultMenuColor(0xfff7f7f7);
+
+    if (cssValueId == CSSValueButtonface)
+        return defaultButtonGrayColor;
+    if (cssValueId == CSSValueMenu)
+        return defaultMenuColor;
+    return RenderTheme::systemColor(cssValueId);
+}
+
+String RenderThemeChromiumDefault::extraDefaultStyleSheet()
+{
+#if !OS(WINDOWS)
+    return RenderThemeChromiumSkia::extraDefaultStyleSheet() +
+           String(themeChromiumLinuxUserAgentStyleSheet, sizeof(themeChromiumLinuxUserAgentStyleSheet));
+#else
+    return RenderThemeChromiumSkia::extraDefaultStyleSheet();
+#endif
+}
+
+bool RenderThemeChromiumDefault::controlSupportsTints(const RenderObject* o) const
+{
+    return isEnabled(o);
+}
+
+Color RenderThemeChromiumDefault::activeListBoxSelectionBackgroundColor() const
+{
+    return Color(0x28, 0x28, 0x28);
+}
+
+Color RenderThemeChromiumDefault::activeListBoxSelectionForegroundColor() const
+{
+    return Color::black;
+}
+
+Color RenderThemeChromiumDefault::inactiveListBoxSelectionBackgroundColor() const
+{
+    return Color(0xc8, 0xc8, 0xc8);
+}
+
+Color RenderThemeChromiumDefault::inactiveListBoxSelectionForegroundColor() const
+{
+    return Color(0x32, 0x32, 0x32);
+}
+
+Color RenderThemeChromiumDefault::platformActiveSelectionBackgroundColor() const
+{
+    return m_activeSelectionBackgroundColor;
+}
+
+Color RenderThemeChromiumDefault::platformInactiveSelectionBackgroundColor() const
+{
+    return m_inactiveSelectionBackgroundColor;
+}
+
+Color RenderThemeChromiumDefault::platformActiveSelectionForegroundColor() const
+{
+    return m_activeSelectionForegroundColor;
+}
+
+Color RenderThemeChromiumDefault::platformInactiveSelectionForegroundColor() const
+{
+    return m_inactiveSelectionForegroundColor;
+}
+
+#if ENABLE(DATALIST_ELEMENT)
+IntSize RenderThemeChromiumDefault::sliderTickSize() const
+{
+    return IntSize(1, 6);
+}
+
+int RenderThemeChromiumDefault::sliderTickOffsetFromTrackCenter() const
+{
+    return -16;
+}
+#endif
+
+void RenderThemeChromiumDefault::adjustSliderThumbSize(RenderStyle* style, Element* element) const
+{
+    IntSize size = WebKit::Platform::current()->themeEngine()->getSize(WebKit::WebThemeEngine::PartSliderThumb);
+
+    if (style->appearance() == SliderThumbHorizontalPart) {
+        style->setWidth(Length(size.width(), Fixed));
+        style->setHeight(Length(size.height(), Fixed));
+    } else if (style->appearance() == SliderThumbVerticalPart) {
+        style->setWidth(Length(size.height(), Fixed));
+        style->setHeight(Length(size.width(), Fixed));
+    } else
+        RenderThemeChromiumSkia::adjustSliderThumbSize(style, element);
+}
+
+bool RenderThemeChromiumDefault::supportsControlTints() const
+{
+    return true;
+}
+
+void RenderThemeChromiumDefault::setCaretBlinkInterval(double interval)
+{
+    m_caretBlinkInterval = interval;
+}
+
+double RenderThemeChromiumDefault::caretBlinkIntervalInternal() const
+{
+    return m_caretBlinkInterval;
+}
+
+void RenderThemeChromiumDefault::setSelectionColors(
+    unsigned activeBackgroundColor,
+    unsigned activeForegroundColor,
+    unsigned inactiveBackgroundColor,
+    unsigned inactiveForegroundColor)
+{
+    m_activeSelectionBackgroundColor = activeBackgroundColor;
+    m_activeSelectionForegroundColor = activeForegroundColor;
+    m_inactiveSelectionBackgroundColor = inactiveBackgroundColor;
+    m_inactiveSelectionForegroundColor = inactiveForegroundColor;
+}
+
+bool RenderThemeChromiumDefault::paintCheckbox(RenderObject* o, const PaintInfo& i, const IntRect& rect)
+{
+    WebKit::WebThemeEngine::ExtraParams extraParams;
+    WebKit::WebCanvas* canvas = i.context->platformContext()->canvas();
+    extraParams.button.checked = isChecked(o);
+    extraParams.button.indeterminate = isIndeterminate(o);
+
+    WebKit::Platform::current()->themeEngine()->paint(canvas, WebKit::WebThemeEngine::PartCheckbox, getWebThemeState(this, o), WebKit::WebRect(rect), &extraParams);
+    return false;
+}
+
+void RenderThemeChromiumDefault::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;
+
+    IntSize size = WebKit::Platform::current()->themeEngine()->getSize(WebKit::WebThemeEngine::PartCheckbox);
+    setSizeIfAuto(style, size);
+}
+
+bool RenderThemeChromiumDefault::paintRadio(RenderObject* o, const PaintInfo& i, const IntRect& rect)
+{
+    WebKit::WebThemeEngine::ExtraParams extraParams;
+    WebKit::WebCanvas* canvas = i.context->platformContext()->canvas();
+    extraParams.button.checked = isChecked(o);
+
+    WebKit::Platform::current()->themeEngine()->paint(canvas, WebKit::WebThemeEngine::PartRadio, getWebThemeState(this, o), WebKit::WebRect(rect), &extraParams);
+    return false;
+}
+
+void RenderThemeChromiumDefault::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;
+
+    IntSize size = WebKit::Platform::current()->themeEngine()->getSize(WebKit::WebThemeEngine::PartRadio);
+    setSizeIfAuto(style, size);
+}
+
+bool RenderThemeChromiumDefault::paintButton(RenderObject* o, const PaintInfo& i, const IntRect& rect)
+{
+    WebKit::WebThemeEngine::ExtraParams extraParams;
+    WebKit::WebCanvas* canvas = i.context->platformContext()->canvas();
+    extraParams.button.hasBorder = true;
+    extraParams.button.backgroundColor = defaultButtonBackgroundColor;
+    if (o->hasBackground())
+        extraParams.button.backgroundColor = o->style()->visitedDependentColor(CSSPropertyBackgroundColor).rgb();
+
+    WebKit::Platform::current()->themeEngine()->paint(canvas, WebKit::WebThemeEngine::PartButton, getWebThemeState(this, o), WebKit::WebRect(rect), &extraParams);
+    return false;
+}
+
+bool RenderThemeChromiumDefault::paintTextField(RenderObject* o, const PaintInfo& i, const IntRect& rect)
+{
+    // WebThemeEngine does not handle border rounded corner and background image
+    // so return true to draw CSS border and background.
+    if (o->style()->hasBorderRadius() || o->style()->hasBackgroundImage())
+        return true;
+
+    ControlPart part = o->style()->appearance();
+
+    WebKit::WebThemeEngine::ExtraParams extraParams;
+    extraParams.textField.isTextArea = part == TextAreaPart;
+    extraParams.textField.isListbox = part == ListboxPart;
+
+    WebKit::WebCanvas* canvas = i.context->platformContext()->canvas();
+
+    // Fallback to white if the specified color object is invalid.
+    Color backgroundColor(Color::white);
+    if (o->style()->visitedDependentColor(CSSPropertyBackgroundColor).isValid())
+        backgroundColor = o->style()->visitedDependentColor(CSSPropertyBackgroundColor);
+    extraParams.textField.backgroundColor = backgroundColor.rgb();
+
+    WebKit::Platform::current()->themeEngine()->paint(canvas, WebKit::WebThemeEngine::PartTextField, getWebThemeState(this, o), WebKit::WebRect(rect), &extraParams);
+    return false;
+}
+
+bool RenderThemeChromiumDefault::paintMenuList(RenderObject* o, const PaintInfo& i, const IntRect& rect)
+{
+    if (!o->isBox())
+        return false;
+
+    const int right = rect.x() + rect.width();
+    const int middle = rect.y() + rect.height() / 2;
+
+    WebKit::WebThemeEngine::ExtraParams extraParams;
+    extraParams.menuList.arrowX = (o->style()->direction() == RTL) ? rect.x() + 7 : right - 13;
+    extraParams.menuList.arrowY = middle;
+    const RenderBox* box = toRenderBox(o);
+    // Match Chromium Win behaviour of showing all borders if any are shown.
+    extraParams.menuList.hasBorder = box->borderRight() || box->borderLeft() || box->borderTop() || box->borderBottom();
+    extraParams.menuList.hasBorderRadius = o->style()->hasBorderRadius();
+    // Fallback to transparent if the specified color object is invalid.
+    extraParams.menuList.backgroundColor = Color::transparent;
+    if (o->hasBackground())
+        extraParams.menuList.backgroundColor = o->style()->visitedDependentColor(CSSPropertyBackgroundColor).rgb();
+
+    WebKit::WebCanvas* canvas = i.context->platformContext()->canvas();
+
+    WebKit::Platform::current()->themeEngine()->paint(canvas, WebKit::WebThemeEngine::PartMenuList, getWebThemeState(this, o), WebKit::WebRect(rect), &extraParams);
+    return false;
+}
+
+bool RenderThemeChromiumDefault::paintSliderTrack(RenderObject* o, const PaintInfo& i, const IntRect& rect)
+{
+    WebKit::WebThemeEngine::ExtraParams extraParams;
+    WebKit::WebCanvas* canvas = i.context->platformContext()->canvas();
+    extraParams.slider.vertical = o->style()->appearance() == SliderVerticalPart;
+
+    WebKit::Platform::current()->themeEngine()->paint(canvas, WebKit::WebThemeEngine::PartSliderTrack, getWebThemeState(this, o), WebKit::WebRect(rect), &extraParams);
+
+#if ENABLE(DATALIST_ELEMENT)
+    paintSliderTicks(o, i, rect);
+#endif
+
+    return false;
+}
+
+bool RenderThemeChromiumDefault::paintSliderThumb(RenderObject* o, const PaintInfo& i, const IntRect& rect)
+{
+    WebKit::WebThemeEngine::ExtraParams extraParams;
+    WebKit::WebCanvas* canvas = i.context->platformContext()->canvas();
+    extraParams.slider.vertical = o->style()->appearance() == SliderThumbVerticalPart;
+    extraParams.slider.inDrag = isPressed(o);
+
+    WebKit::Platform::current()->themeEngine()->paint(canvas, WebKit::WebThemeEngine::PartSliderThumb, getWebThemeState(this, o), WebKit::WebRect(rect), &extraParams);
+    return false;
+}
+
+void RenderThemeChromiumDefault::adjustInnerSpinButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
+{
+    IntSize size = WebKit::Platform::current()->themeEngine()->getSize(WebKit::WebThemeEngine::PartInnerSpinButton);
+
+    style->setWidth(Length(size.width(), Fixed));
+    style->setMinWidth(Length(size.width(), Fixed));
+}
+
+bool RenderThemeChromiumDefault::paintInnerSpinButton(RenderObject* o, const PaintInfo& i, const IntRect& rect)
+{
+    WebKit::WebThemeEngine::ExtraParams extraParams;
+    WebKit::WebCanvas* canvas = i.context->platformContext()->canvas();
+    extraParams.innerSpin.spinUp = (controlStatesForRenderer(o) & SpinUpState);
+    extraParams.innerSpin.readOnly = isReadOnlyControl(o);
+
+    WebKit::Platform::current()->themeEngine()->paint(canvas, WebKit::WebThemeEngine::PartInnerSpinButton, getWebThemeState(this, o), WebKit::WebRect(rect), &extraParams);
+    return false;
+}
+
+bool RenderThemeChromiumDefault::paintProgressBar(RenderObject* o, const PaintInfo& i, const IntRect& rect)
+{
+    if (!o->isProgress())
+        return true;
+
+    RenderProgress* renderProgress = toRenderProgress(o);
+    IntRect valueRect = progressValueRectFor(renderProgress, rect);
+
+    WebKit::WebThemeEngine::ExtraParams extraParams;
+    extraParams.progressBar.determinate = renderProgress->isDeterminate();
+    extraParams.progressBar.valueRectX = valueRect.x();
+    extraParams.progressBar.valueRectY = valueRect.y();
+    extraParams.progressBar.valueRectWidth = valueRect.width();
+    extraParams.progressBar.valueRectHeight = valueRect.height();
+
+    DirectionFlippingScope scope(o, i, rect);
+    WebKit::WebCanvas* canvas = i.context->platformContext()->canvas();
+    WebKit::Platform::current()->themeEngine()->paint(canvas, WebKit::WebThemeEngine::PartProgressBar, getWebThemeState(this, o), WebKit::WebRect(rect), &extraParams);
+    return false;
+}
+
+bool RenderThemeChromiumDefault::shouldOpenPickerWithF4Key() const
+{
+    return true;
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderThemeChromiumDefault.h b/Source/core/rendering/RenderThemeChromiumDefault.h
new file mode 100644
index 0000000..d3b49c6
--- /dev/null
+++ b/Source/core/rendering/RenderThemeChromiumDefault.h
@@ -0,0 +1,107 @@
+/*
+ * This file is part of the WebKit project.
+ *
+ * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
+ * Copyright (C) 2007 Holger Hans Peter Freyther
+ * Copyright (C) 2007 Alp Toker <alp@atoker.com>
+ * Copyright (C) 2008, 2009 Google, Inc.
+ * All rights reserved.
+ * Copyright (C) 2009 Kenneth Rohde Christiansen
+ *
+ * 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 RenderThemeChromiumDefault_h
+#define RenderThemeChromiumDefault_h
+
+#include "core/rendering/RenderThemeChromiumSkia.h"
+
+namespace WebCore {
+
+class RenderThemeChromiumDefault : public RenderThemeChromiumSkia {
+public:
+    static PassRefPtr<RenderTheme> create();
+    virtual String extraDefaultStyleSheet();
+
+    virtual Color systemColor(int cssValidId) const;
+
+    // A method asking if the control changes its tint when the window has focus or not.
+    virtual bool controlSupportsTints(const RenderObject*) const;
+
+    // List Box selection color
+    virtual Color activeListBoxSelectionBackgroundColor() const;
+    virtual Color activeListBoxSelectionForegroundColor() const;
+    virtual Color inactiveListBoxSelectionBackgroundColor() const;
+    virtual Color inactiveListBoxSelectionForegroundColor() const;
+
+    virtual Color platformActiveSelectionBackgroundColor() const;
+    virtual Color platformInactiveSelectionBackgroundColor() const;
+    virtual Color platformActiveSelectionForegroundColor() const;
+    virtual Color platformInactiveSelectionForegroundColor() const;
+
+#if ENABLE(DATALIST_ELEMENT)
+    virtual IntSize sliderTickSize() const OVERRIDE;
+    virtual int sliderTickOffsetFromTrackCenter() const OVERRIDE;
+#endif
+    virtual void adjustSliderThumbSize(RenderStyle*, Element*) const;
+
+    static void setCaretBlinkInterval(double);
+    virtual double caretBlinkIntervalInternal() const;
+
+    virtual bool paintCheckbox(RenderObject*, const PaintInfo&, const IntRect&);
+    virtual void setCheckboxSize(RenderStyle*) const;
+
+    virtual bool paintRadio(RenderObject*, const PaintInfo&, const IntRect&);
+    virtual void setRadioSize(RenderStyle*) const;
+
+    virtual bool paintButton(RenderObject*, const PaintInfo&, const IntRect&);
+    virtual bool paintTextField(RenderObject*, const PaintInfo&, const IntRect&);
+    virtual bool paintMenuList(RenderObject*, const PaintInfo&, const IntRect&);
+    virtual bool paintSliderTrack(RenderObject*, const PaintInfo&, const IntRect&);
+    virtual bool paintSliderThumb(RenderObject*, const PaintInfo&, const IntRect&);
+
+    virtual void adjustInnerSpinButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
+    virtual bool paintInnerSpinButton(RenderObject*, const PaintInfo&, const IntRect&);
+
+    virtual bool popsMenuBySpaceOrReturn() const OVERRIDE { return true; }
+
+    virtual bool paintProgressBar(RenderObject*, const PaintInfo&, const IntRect&);
+
+    virtual bool shouldOpenPickerWithF4Key() const OVERRIDE;
+
+    static void setSelectionColors(unsigned activeBackgroundColor, unsigned activeForegroundColor, unsigned inactiveBackgroundColor, unsigned inactiveForegroundColor);
+
+protected:
+    RenderThemeChromiumDefault();
+    virtual ~RenderThemeChromiumDefault();
+
+private:
+    // A general method asking if any control tinting is supported at all.
+    virtual bool supportsControlTints() const;
+
+    static double m_caretBlinkInterval;
+
+    static unsigned m_activeSelectionBackgroundColor;
+    static unsigned m_activeSelectionForegroundColor;
+    static unsigned m_inactiveSelectionBackgroundColor;
+    static unsigned m_inactiveSelectionForegroundColor;
+};
+
+} // namespace WebCore
+
+#endif // RenderThemeChromiumDefault_h
diff --git a/Source/core/rendering/RenderThemeChromiumFontProvider.cpp b/Source/core/rendering/RenderThemeChromiumFontProvider.cpp
new file mode 100644
index 0000000..fc91a9c
--- /dev/null
+++ b/Source/core/rendering/RenderThemeChromiumFontProvider.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2012 Google 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 "core/rendering/RenderThemeChromiumFontProvider.h"
+
+#include <wtf/StdLibExtras.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+// The default variable-width font size. We use this as the default font
+// size for the "system font", and as a base size (which we then shrink) for
+// form control fonts.
+// static
+float RenderThemeChromiumFontProvider::s_defaultFontSize = 16.0;
+
+// We aim to match IE here.
+// -IE uses a font based on the encoding as the default font for form controls.
+// -Gecko uses MS Shell Dlg (actually calls GetStockObject(DEFAULT_GUI_FONT),
+// which returns MS Shell Dlg)
+// -Safari uses Lucida Grande.
+//
+// FIXME: The only case where we know we don't match IE is for ANSI encodings.
+// IE uses MS Shell Dlg there, which we render incorrectly at certain pixel
+// sizes (e.g. 15px). So, for now we just use Arial.
+const String& RenderThemeChromiumFontProvider::defaultGUIFont()
+{
+    DEFINE_STATIC_LOCAL(String, fontFace, (ASCIILiteral("Arial")));
+    return fontFace;
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderThemeChromiumFontProvider.h b/Source/core/rendering/RenderThemeChromiumFontProvider.h
new file mode 100644
index 0000000..0f7eeac
--- /dev/null
+++ b/Source/core/rendering/RenderThemeChromiumFontProvider.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2012 Google 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 RenderThemeChromiumFontProvider_h
+#define RenderThemeChromiumFontProvider_h
+
+namespace WTF {
+class String;
+}
+
+namespace WebCore {
+
+class FontDescription;
+
+class RenderThemeChromiumFontProvider {
+public:
+    static void systemFont(int propId, FontDescription&);
+    static void setDefaultFontSize(int);
+
+protected:
+    static const WTF::String& defaultGUIFont();
+
+    static float s_defaultFontSize;
+};
+
+} // namespace WebCore
+
+#endif // RenderThemeChromiumFontProvider_h
diff --git a/Source/core/rendering/RenderThemeChromiumFontProviderLinux.cpp b/Source/core/rendering/RenderThemeChromiumFontProviderLinux.cpp
new file mode 100644
index 0000000..d84505c
--- /dev/null
+++ b/Source/core/rendering/RenderThemeChromiumFontProviderLinux.cpp
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2012 Google 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 "core/rendering/RenderThemeChromiumFontProvider.h"
+
+#include "CSSValueKeywords.h"
+#include "core/platform/graphics/FontDescription.h"
+
+#include <wtf/StdLibExtras.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+// static
+void RenderThemeChromiumFontProvider::setDefaultFontSize(int fontSize)
+{
+    s_defaultFontSize = static_cast<float>(fontSize);
+}
+
+// static
+void RenderThemeChromiumFontProvider::systemFont(int propId, FontDescription& fontDescription)
+{
+    float fontSize = s_defaultFontSize;
+
+    switch (propId) {
+    case CSSValueWebkitMiniControl:
+    case CSSValueWebkitSmallControl:
+    case CSSValueWebkitControl:
+        // Why 2 points smaller? Because that's what Gecko does. Note that we
+        // are assuming a 96dpi screen, which is the default that we use on
+        // Windows.
+        static const float pointsPerInch = 72.0f;
+        static const float pixelsPerInch = 96.0f;
+        fontSize -= (2.0f / pointsPerInch) * pixelsPerInch;
+        break;
+    }
+
+    fontDescription.firstFamily().setFamily(defaultGUIFont());
+    fontDescription.setSpecifiedSize(fontSize);
+    fontDescription.setIsAbsoluteSize(true);
+    fontDescription.setGenericFamily(FontDescription::NoFamily);
+    fontDescription.setWeight(FontWeightNormal);
+    fontDescription.setItalic(false);
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderThemeChromiumFontProviderWin.cpp b/Source/core/rendering/RenderThemeChromiumFontProviderWin.cpp
new file mode 100644
index 0000000..9d4dbcc
--- /dev/null
+++ b/Source/core/rendering/RenderThemeChromiumFontProviderWin.cpp
@@ -0,0 +1,192 @@
+/*
+ * Copyright (C) 2012 Google 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 "core/rendering/RenderThemeChromiumFontProvider.h"
+
+#include "CSSValueKeywords.h"
+#include "core/platform/graphics/FontDescription.h"
+#include "core/platform/win/HWndDC.h"
+#include "core/platform/win/SystemInfo.h"
+
+#include <windows.h>
+#include <wtf/text/WTFString.h>
+
+#define SIZEOF_STRUCT_WITH_SPECIFIED_LAST_MEMBER(structName, member) \
+    offsetof(structName, member) + \
+    (sizeof static_cast<structName*>(0)->member)
+#define NONCLIENTMETRICS_SIZE_PRE_VISTA \
+    SIZEOF_STRUCT_WITH_SPECIFIED_LAST_MEMBER(NONCLIENTMETRICS, lfMessageFont)
+
+namespace WebCore {
+
+static FontDescription& smallSystemFont()
+{
+    DEFINE_STATIC_LOCAL(FontDescription, font, ());
+    return font;
+}
+
+static FontDescription& menuFont()
+{
+    DEFINE_STATIC_LOCAL(FontDescription, font, ());
+    return font;
+}
+
+static FontDescription& labelFont()
+{
+    DEFINE_STATIC_LOCAL(FontDescription, font, ());
+    return font;
+}
+
+// Converts |points| to pixels. One point is 1/72 of an inch.
+static float pointsToPixels(float points)
+{
+    static float pixelsPerInch = 0.0f;
+    if (!pixelsPerInch) {
+        HWndDC hdc(0); // What about printing? Is this the right DC?
+        if (hdc) // Can this ever actually be 0?
+            pixelsPerInch = GetDeviceCaps(hdc, LOGPIXELSY);
+        else
+            pixelsPerInch = 96.0f;
+    }
+
+    static const float pointsPerInch = 72.0f;
+    return points / pointsPerInch * pixelsPerInch;
+}
+
+static void getNonClientMetrics(NONCLIENTMETRICS* metrics)
+{
+    static UINT size = (windowsVersion() >= WindowsVista) ?
+        sizeof(NONCLIENTMETRICS) : NONCLIENTMETRICS_SIZE_PRE_VISTA;
+    metrics->cbSize = size;
+    bool success = !!SystemParametersInfo(SPI_GETNONCLIENTMETRICS, size, metrics, 0);
+    ASSERT(success);
+}
+
+// Return the height of system font |font| in pixels. We use this size by
+// default for some non-form-control elements.
+static float systemFontSize(const LOGFONT& font)
+{
+    float size = -font.lfHeight;
+    if (size < 0) {
+        HFONT hFont = CreateFontIndirect(&font);
+        if (hFont) {
+            HWndDC hdc(0); // What about printing? Is this the right DC?
+            if (hdc) {
+                HGDIOBJ hObject = SelectObject(hdc, hFont);
+                TEXTMETRIC tm;
+                GetTextMetrics(hdc, &tm);
+                SelectObject(hdc, hObject);
+                size = tm.tmAscent;
+            }
+            DeleteObject(hFont);
+        }
+    }
+
+    // The "codepage 936" bit here is from Gecko; apparently this helps make
+    // fonts more legible in Simplified Chinese where the default font size is
+    // too small.
+    //
+    // FIXME: http://b/1119883 Since this is only used for "small caption",
+    // "menu", and "status bar" objects, I'm not sure how much this even
+    // matters. Plus the Gecko patch went in back in 2002, and maybe this
+    // isn't even relevant anymore. We should investigate whether this should
+    // be removed, or perhaps broadened to be "any CJK locale".
+    //
+    return ((size < 12.0f) && (GetACP() == 936)) ? 12.0f : size;
+}
+
+// static
+void RenderThemeChromiumFontProvider::systemFont(int propId, FontDescription& fontDescription)
+{
+    // This logic owes much to RenderThemeSafari.cpp.
+    FontDescription* cachedDesc = 0;
+    AtomicString faceName;
+    float fontSize = 0;
+    switch (propId) {
+    case CSSValueSmallCaption:
+        cachedDesc = &smallSystemFont();
+        if (!smallSystemFont().isAbsoluteSize()) {
+            NONCLIENTMETRICS metrics;
+            getNonClientMetrics(&metrics);
+            faceName = AtomicString(metrics.lfSmCaptionFont.lfFaceName, wcslen(metrics.lfSmCaptionFont.lfFaceName));
+            fontSize = systemFontSize(metrics.lfSmCaptionFont);
+        }
+        break;
+    case CSSValueMenu:
+        cachedDesc = &menuFont();
+        if (!menuFont().isAbsoluteSize()) {
+            NONCLIENTMETRICS metrics;
+            getNonClientMetrics(&metrics);
+            faceName = AtomicString(metrics.lfMenuFont.lfFaceName, wcslen(metrics.lfMenuFont.lfFaceName));
+            fontSize = systemFontSize(metrics.lfMenuFont);
+        }
+        break;
+    case CSSValueStatusBar:
+        cachedDesc = &labelFont();
+        if (!labelFont().isAbsoluteSize()) {
+            NONCLIENTMETRICS metrics;
+            getNonClientMetrics(&metrics);
+            faceName = metrics.lfStatusFont.lfFaceName;
+            fontSize = systemFontSize(metrics.lfStatusFont);
+        }
+        break;
+    case CSSValueWebkitMiniControl:
+    case CSSValueWebkitSmallControl:
+    case CSSValueWebkitControl:
+        faceName = defaultGUIFont();
+        // Why 2 points smaller? Because that's what Gecko does.
+        fontSize = s_defaultFontSize - pointsToPixels(2);
+        break;
+    default:
+        faceName = defaultGUIFont();
+        fontSize = s_defaultFontSize;
+        break;
+    }
+
+    if (!cachedDesc)
+        cachedDesc = &fontDescription;
+
+    if (fontSize) {
+        cachedDesc->firstFamily().setFamily(faceName);
+        cachedDesc->setIsAbsoluteSize(true);
+        cachedDesc->setGenericFamily(FontDescription::NoFamily);
+        cachedDesc->setSpecifiedSize(fontSize);
+        cachedDesc->setWeight(FontWeightNormal);
+        cachedDesc->setItalic(false);
+    }
+    fontDescription = *cachedDesc;
+}
+
+// static
+void RenderThemeChromiumFontProvider::setDefaultFontSize(int fontSize)
+{
+    s_defaultFontSize = static_cast<float>(fontSize);
+
+    // Reset cached fonts.
+    smallSystemFont() = menuFont() = labelFont() = FontDescription();
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderThemeChromiumMac.h b/Source/core/rendering/RenderThemeChromiumMac.h
new file mode 100644
index 0000000..1f55e4f
--- /dev/null
+++ b/Source/core/rendering/RenderThemeChromiumMac.h
@@ -0,0 +1,244 @@
+/*
+ * This file is part of the theme implementation for form controls in WebCore.
+ *
+ * Copyright (C) 2005 Apple Computer, Inc.
+ * Copyright (C) 2008, 2009 Google, 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 RenderThemeChromiumMac_h
+#define RenderThemeChromiumMac_h
+
+#import "core/rendering/RenderTheme.h"
+#import "core/rendering/RenderThemeChromiumCommon.h"
+
+#import <wtf/HashMap.h>
+#import <wtf/RetainPtr.h>
+
+OBJC_CLASS WebCoreRenderThemeNotificationObserver;
+
+namespace WebCore {
+
+class RenderThemeChromiumMac : public RenderTheme {
+public:
+    static PassRefPtr<RenderTheme> create();
+
+    virtual bool supportsDataListUI(const AtomicString& type) const OVERRIDE;
+
+    // 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&) OVERRIDE;
+
+    virtual bool isControlStyled(const RenderStyle*, const BorderData&, const FillLayer&, const Color& backgroundColor) const;
+
+    virtual Color platformActiveSelectionBackgroundColor() const;
+    virtual Color platformInactiveSelectionBackgroundColor() const;
+    virtual Color platformActiveListBoxSelectionBackgroundColor() const;
+    virtual Color platformActiveListBoxSelectionForegroundColor() const;
+    virtual Color platformInactiveListBoxSelectionBackgroundColor() const;
+    virtual Color platformInactiveListBoxSelectionForegroundColor() const;
+    virtual Color platformFocusRingColor() const;
+
+    virtual ScrollbarControlSize scrollbarControlSizeForPart(ControlPart) { return SmallScrollbar; }
+
+    virtual void platformColorsDidChange();
+
+    // System fonts.
+    virtual void systemFont(int cssValueId, FontDescription&) const;
+
+    virtual int minimumMenuListSize(RenderStyle*) const;
+
+    virtual void adjustSliderThumbSize(RenderStyle*, Element*) const;
+
+#if ENABLE(DATALIST_ELEMENT)
+    virtual IntSize sliderTickSize() const OVERRIDE;
+    virtual int sliderTickOffsetFromTrackCenter() const OVERRIDE;
+#endif
+
+    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 PaintInfo&, const IntRect&) OVERRIDE;
+
+    virtual bool popsMenuByArrowKeys() const OVERRIDE { return true; }
+
+    virtual IntSize meterSizeForBounds(const RenderMeter*, const IntRect&) const OVERRIDE;
+    virtual bool paintMeter(RenderObject*, const PaintInfo&, const IntRect&);
+    virtual bool supportsMeter(ControlPart) const;
+
+    // Returns the repeat interval of the animation for the progress bar.
+    virtual double animationRepeatIntervalForProgressBar(RenderProgress*) const;
+    // Returns the duration of the animation for the progress bar.
+    virtual double animationDurationForProgressBar(RenderProgress*) const;
+
+    virtual Color systemColor(int cssValueId) const;
+
+protected:
+    RenderThemeChromiumMac();
+    virtual ~RenderThemeChromiumMac();
+
+    virtual bool supportsSelectionForegroundColors() const { return false; }
+
+    virtual bool paintTextField(RenderObject*, const PaintInfo&, const IntRect&);
+    virtual void adjustTextFieldStyle(StyleResolver*, RenderStyle*, Element*) const;
+
+    virtual bool paintTextArea(RenderObject*, const PaintInfo&, const IntRect&);
+    virtual void adjustTextAreaStyle(StyleResolver*, RenderStyle*, Element*) const;
+
+    virtual bool paintMenuList(RenderObject*, const PaintInfo&, const IntRect&);
+    virtual void adjustMenuListStyle(StyleResolver*, RenderStyle*, Element*) const;
+
+    virtual bool paintMenuListButton(RenderObject*, const PaintInfo&, const IntRect&);
+    virtual void adjustMenuListButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
+
+    virtual void adjustProgressBarStyle(StyleResolver*, RenderStyle*, Element*) const;
+    virtual bool paintProgressBar(RenderObject*, const PaintInfo&, const IntRect&);
+
+    virtual bool paintSliderTrack(RenderObject*, const PaintInfo&, const IntRect&);
+
+    virtual bool paintSliderThumb(RenderObject*, const PaintInfo&, const IntRect&);
+
+    virtual bool paintSearchField(RenderObject*, const PaintInfo&, const IntRect&);
+    virtual void adjustSearchFieldStyle(StyleResolver*, RenderStyle*, Element*) const;
+
+    virtual void adjustSearchFieldCancelButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
+    virtual bool paintSearchFieldCancelButton(RenderObject*, const PaintInfo&, const IntRect&);
+
+    virtual void adjustSearchFieldDecorationStyle(StyleResolver*, RenderStyle*, Element*) const;
+    virtual bool paintSearchFieldDecoration(RenderObject*, const PaintInfo&, const IntRect&);
+
+    virtual void adjustSearchFieldResultsDecorationStyle(StyleResolver*, RenderStyle*, Element*) const;
+    virtual bool paintSearchFieldResultsDecoration(RenderObject*, const PaintInfo&, const IntRect&);
+
+    virtual void adjustSearchFieldResultsButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
+    virtual bool paintSearchFieldResultsButton(RenderObject*, const PaintInfo&, const IntRect&);
+
+    virtual bool supportsClosedCaptioning() const { return true; }
+
+private:
+    virtual String fileListNameForWidth(const FileList*, const Font&, int width, bool multipleFilesAllowed) const OVERRIDE;
+
+    IntRect inflateRect(const IntRect&, const IntSize&, const int* margins, float zoomLevel = 1.0f) const;
+
+    FloatRect convertToPaintingRect(const RenderObject* inputRenderer, const RenderObject* partRenderer, const FloatRect& inputRect, const IntRect&) 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(StyleResolver*, 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 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;
+    NSTextFieldCell* textField() const;
+
+    NSLevelIndicatorStyle levelIndicatorStyleFor(ControlPart) const;
+    NSLevelIndicatorCell* levelIndicatorFor(const RenderMeter*) const;
+
+    int minimumProgressBarHeight(RenderStyle*) const;
+    const IntSize* progressBarSizes() const;
+    const int* progressBarMargins(NSControlSize) const;
+
+protected:
+    virtual void adjustMediaSliderThumbSize(RenderStyle*) const;
+    virtual bool paintMediaPlayButton(RenderObject*, const PaintInfo&, const IntRect&);
+    virtual bool paintMediaMuteButton(RenderObject*, const PaintInfo&, const IntRect&);
+    virtual bool paintMediaSliderTrack(RenderObject*, const PaintInfo&, const IntRect&);
+    virtual String extraMediaControlsStyleSheet();
+    virtual String extraFullScreenStyleSheet();
+  
+    virtual bool paintMediaSliderThumb(RenderObject*, const PaintInfo&, const IntRect&);
+    virtual bool paintMediaVolumeSliderContainer(RenderObject*, const PaintInfo&, const IntRect&);
+    virtual bool paintMediaVolumeSliderTrack(RenderObject*, const PaintInfo&, const IntRect&);
+    virtual bool paintMediaVolumeSliderThumb(RenderObject*, const PaintInfo&, const IntRect&);
+    virtual bool usesMediaControlStatusDisplay() { return false; }
+    virtual bool hasOwnDisabledStateHandlingFor(ControlPart) const { return true; }
+    virtual bool usesVerticalVolumeSlider() const { return false; }
+    virtual String formatMediaControlsTime(float time) const;
+    virtual String formatMediaControlsCurrentTime(float currentTime, float duration) const;
+    virtual bool paintMediaFullscreenButton(RenderObject*, const PaintInfo&, const IntRect&);
+    virtual bool paintMediaToggleClosedCaptionsButton(RenderObject*, const PaintInfo&, const IntRect&);
+
+    // Controls color values returned from platformFocusRingColor(). systemColor() will be used when false.
+    bool usesTestModeFocusRingColor() const;
+    // A view associated to the contained document. Subclasses may not have such a view and return a fake.
+    NSView* documentViewFor(RenderObject*) const;
+
+private:
+    virtual Color disabledTextColor(const Color& textColor, const Color&) const OVERRIDE { return textColor; }
+    virtual void updateActiveState(NSCell*, const RenderObject*);
+    virtual String extraDefaultStyleSheet();
+#if ENABLE(DATALIST_ELEMENT)
+    virtual LayoutUnit sliderTickSnappingThreshold() const OVERRIDE;
+#endif
+#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
+    virtual bool supportsCalendarPicker(const AtomicString& type) const OVERRIDE;
+#endif
+    virtual bool shouldShowPlaceholderWhenFocused() const OVERRIDE;
+
+    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;
+    mutable RetainPtr<NSLevelIndicatorCell> m_levelIndicator;
+    mutable RetainPtr<NSTextFieldCell> m_textField;
+
+    bool m_isSliderThumbHorizontalPressed;
+    bool m_isSliderThumbVerticalPressed;
+
+    mutable HashMap<int, RGBA32> m_systemColorCache;
+
+    RetainPtr<WebCoreRenderThemeNotificationObserver> m_notificationObserver;
+};
+
+} // namespace WebCore
+
+#endif // RenderThemeChromiumMac_h
diff --git a/Source/core/rendering/RenderThemeChromiumMac.mm b/Source/core/rendering/RenderThemeChromiumMac.mm
new file mode 100644
index 0000000..8576657
--- /dev/null
+++ b/Source/core/rendering/RenderThemeChromiumMac.mm
@@ -0,0 +1,2035 @@
+/*
+ * Copyright (C) 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2008, 2009 Google, 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.
+ */
+
+#import "config.h"
+#import "core/rendering/RenderThemeChromiumMac.h"
+
+#import "CSSValueKeywords.h"
+#import "HTMLNames.h"
+#import "UserAgentStyleSheets.h"
+#import "core/css/CSSValueList.h"
+#import "core/css/StyleResolver.h"
+#import "core/dom/Document.h"
+#import "core/dom/Element.h"
+#import "core/fileapi/FileList.h"
+#import "core/html/HTMLInputElement.h"
+#import "core/html/HTMLMediaElement.h"
+#import "core/html/HTMLMeterElement.h"
+#import "core/html/HTMLPlugInImageElement.h"
+#import "core/html/TimeRanges.h"
+#import "core/html/shadow/MediaControlElements.h"
+#import "core/page/FrameView.h"
+#import "core/platform/LayoutTestSupport.h"
+#import "core/platform/LocalizedStrings.h"
+#import "core/platform/SharedBuffer.h"
+#import "core/platform/graphics/BitmapImage.h"
+#import "core/platform/graphics/Image.h"
+#import "core/platform/graphics/ImageBuffer.h"
+#import "core/platform/graphics/StringTruncator.h"
+#import "core/platform/graphics/cg/GraphicsContextCG.h"
+#import "core/platform/graphics/mac/ColorMac.h"
+#import "core/platform/mac/LocalCurrentGraphicsContext.h"
+#import "core/platform/mac/ThemeMac.h"
+#import "core/platform/mac/WebCoreNSCellExtras.h"
+#import "core/rendering/PaintInfo.h"
+#import "core/rendering/RenderLayer.h"
+#import "core/rendering/RenderMedia.h"
+#import "core/rendering/RenderMediaControls.h"
+#import "core/rendering/RenderMediaControlsChromium.h"
+#import "core/rendering/RenderMeter.h"
+#import "core/rendering/RenderProgress.h"
+#import "core/rendering/RenderSlider.h"
+#import "core/rendering/RenderView.h"
+
+#import <Carbon/Carbon.h>
+#import <Cocoa/Cocoa.h>
+#import <math.h>
+#import <wtf/RetainPtr.h>
+#import <wtf/StdLibExtras.h>
+
+using namespace std;
+
+// The methods in this file are specific to the Mac OS X platform.
+
+// We estimate the animation rate of a Mac OS X progress bar is 33 fps.
+// Hard code the value here because we haven't found API for it.
+const double progressAnimationFrameRate = 0.033;
+
+// Mac OS X progress bar animation seems to have 256 frames.
+const double progressAnimationNumFrames = 256;
+
+@interface WebCoreRenderThemeNotificationObserver : NSObject
+{
+    WebCore::RenderTheme *_theme;
+}
+
+- (id)initWithTheme:(WebCore::RenderTheme *)theme;
+- (void)systemColorsDidChange:(NSNotification *)notification;
+
+@end
+
+@implementation WebCoreRenderThemeNotificationObserver
+
+- (id)initWithTheme:(WebCore::RenderTheme *)theme
+{
+    if (!(self = [super init]))
+        return nil;
+
+    _theme = theme;
+    return self;
+}
+
+- (void)systemColorsDidChange:(NSNotification *)unusedNotification
+{
+    ASSERT_UNUSED(unusedNotification, [[unusedNotification name] isEqualToString:NSSystemColorsDidChangeNotification]);
+    _theme->platformColorsDidChange();
+}
+
+@end
+
+@interface NSTextFieldCell (WKDetails)
+- (CFDictionaryRef)_coreUIDrawOptionsWithFrame:(NSRect)cellFrame inView:(NSView *)controlView includeFocus:(BOOL)includeFocus;
+@end
+
+
+@interface WebCoreTextFieldCell : NSTextFieldCell
+- (CFDictionaryRef)_coreUIDrawOptionsWithFrame:(NSRect)cellFrame inView:(NSView *)controlView includeFocus:(BOOL)includeFocus;
+@end
+
+@implementation WebCoreTextFieldCell
+- (CFDictionaryRef)_coreUIDrawOptionsWithFrame:(NSRect)cellFrame inView:(NSView *)controlView includeFocus:(BOOL)includeFocus
+{
+    // FIXME: This is a post-Lion-only workaround for <rdar://problem/11385461>. When that bug is resolved, we should remove this code.
+    CFMutableDictionaryRef coreUIDrawOptions = CFDictionaryCreateMutableCopy(NULL, 0, [super _coreUIDrawOptionsWithFrame:cellFrame inView:controlView includeFocus:includeFocus]);
+    CFDictionarySetValue(coreUIDrawOptions, @"borders only", kCFBooleanTrue);
+    return (CFDictionaryRef)[NSMakeCollectable(coreUIDrawOptions) autorelease];
+}
+@end
+
+@interface RTCMFlippedView : NSView
+{}
+
+- (BOOL)isFlipped;
+- (NSText *)currentEditor;
+
+@end
+
+@implementation RTCMFlippedView
+
+- (BOOL)isFlipped {
+    return [[NSGraphicsContext currentContext] isFlipped];
+}
+
+- (NSText *)currentEditor {
+    return nil;
+}
+
+@end
+
+// Forward declare Mac SPIs.
+extern "C" {
+void _NSDrawCarbonThemeBezel(NSRect frame, BOOL enabled, BOOL flipped);
+// Request for public API: rdar://13787640
+void _NSDrawCarbonThemeListBox(NSRect frame, BOOL enabled, BOOL flipped, BOOL always_yes);
+}
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+enum {
+    topMargin,
+    rightMargin,
+    bottomMargin,
+    leftMargin
+};
+
+enum {
+    topPadding,
+    rightPadding,
+    bottomPadding,
+    leftPadding
+};
+
+RenderThemeChromiumMac::RenderThemeChromiumMac()
+    : 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];
+}
+
+RenderThemeChromiumMac::~RenderThemeChromiumMac()
+{
+    [[NSNotificationCenter defaultCenter] removeObserver:m_notificationObserver.get()];
+}
+
+Color RenderThemeChromiumMac::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 RenderThemeChromiumMac::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 RenderThemeChromiumMac::platformActiveListBoxSelectionBackgroundColor() 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]));
+}
+
+Color RenderThemeChromiumMac::platformActiveListBoxSelectionForegroundColor() const
+{
+    return Color::white;
+}
+
+Color RenderThemeChromiumMac::platformInactiveListBoxSelectionForegroundColor() const
+{
+    return Color::black;
+}
+
+Color RenderThemeChromiumMac::platformFocusRingColor() const
+{
+    if (usesTestModeFocusRingColor())
+        return oldAquaFocusRingColor();
+
+    return systemColor(CSSValueWebkitFocusRingColor);
+}
+
+Color RenderThemeChromiumMac::platformInactiveListBoxSelectionBackgroundColor() const
+{
+    return platformInactiveSelectionBackgroundColor();
+}
+
+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 RenderThemeChromiumMac::systemFont(int cssValueId, FontDescription& fontDescription) const
+{
+    DEFINE_STATIC_LOCAL(FontDescription, systemFont, ());
+    DEFINE_STATIC_LOCAL(FontDescription, smallSystemFont, ());
+    DEFINE_STATIC_LOCAL(FontDescription, menuFont, ());
+    DEFINE_STATIC_LOCAL(FontDescription, labelFont, ());
+    DEFINE_STATIC_LOCAL(FontDescription, miniControlFont, ());
+    DEFINE_STATIC_LOCAL(FontDescription, smallControlFont, ());
+    DEFINE_STATIC_LOCAL(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 webCoreFamilyName]);
+        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:NSDeviceRGBColorSpace];
+    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:NSDeviceRGBColorSpace
+                                                                            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:NSDeviceRGBColorSpace
+                                                                            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 RenderThemeChromiumMac::platformColorsDidChange()
+{
+    m_systemColorCache.clear();
+    RenderTheme::platformColorsDidChange();
+}
+
+Color RenderThemeChromiumMac::systemColor(int cssValueId) const
+{
+    {
+        HashMap<int, RGBA32>::iterator it = m_systemColorCache.find(cssValueId);
+        if (it != m_systemColorCache.end())
+            return it->value;
+    }
+
+    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 CSSValueWebkitFocusRingColor:
+            color = convertNSColorToColor([NSColor keyboardFocusIndicatorColor]);
+            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 RenderThemeChromiumMac::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 || style->boxShadow();
+
+    // FIXME: This is horrible, but there is not much else that can be done.  Menu lists cannot draw properly when
+    // scaled.  They can't really draw properly when transformed either.  We can't detect the transform case at style
+    // adjustment time so that will just have to stay broken.  We can however detect that we're zooming.  If zooming
+    // is in effect we treat it like the control is styled.
+    if (style->appearance() == MenulistPart && style->effectiveZoom() != 1.0f)
+        return true;
+    // FIXME: NSSearchFieldCell doesn't work well when scaled.
+    if (style->appearance() == SearchFieldPart && style->effectiveZoom() != 1)
+        return true;
+
+    return RenderTheme::isControlStyled(style, border, background, backgroundColor);
+}
+
+void RenderThemeChromiumMac::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 ButtonPart:
+        case InnerSpinButtonPart:
+            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 RenderThemeChromiumMac::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;
+}
+
+FloatRect RenderThemeChromiumMac::convertToPaintingRect(const RenderObject* inputRenderer, const RenderObject* partRenderer, const FloatRect& inputRect, const IntRect& r) const
+{
+    FloatRect partRect(inputRect);
+
+    // Compute an offset between the part renderer and the input renderer
+    FloatSize offsetFromInputRenderer;
+    const RenderObject* renderer = partRenderer;
+    while (renderer && renderer != inputRenderer) {
+        RenderObject* containingRenderer = renderer->container();
+        offsetFromInputRenderer -= roundedIntSize(renderer->offsetFromContainer(containingRenderer, LayoutPoint()));
+        renderer = containingRenderer;
+    }
+    // If the input renderer was not a container, something went wrong
+    ASSERT(renderer == inputRenderer);
+    // Move the rect into partRenderer's coords
+    partRect.move(offsetFromInputRenderer);
+    // Account for the local drawing offset (tx, ty)
+    partRect.move(r.x(), r.y());
+
+    return partRect;
+}
+
+void RenderThemeChromiumMac::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 RenderThemeChromiumMac::updateEnabledState(NSCell* cell, const RenderObject* o)
+{
+    bool oldEnabled = [cell isEnabled];
+    bool enabled = isEnabled(o);
+    if (enabled != oldEnabled)
+        [cell setEnabled:enabled];
+}
+
+void RenderThemeChromiumMac::updateFocusedState(NSCell* cell, const RenderObject* o)
+{
+    bool oldFocused = [cell showsFirstResponder];
+    bool focused = isFocused(o) && o->style()->outlineStyleIsAuto();
+    if (focused != oldFocused)
+        [cell setShowsFirstResponder:focused];
+}
+
+void RenderThemeChromiumMac::updatePressedState(NSCell* cell, const RenderObject* o)
+{
+    bool oldPressed = [cell isHighlighted];
+    bool pressed = (o->node() && o->node()->active());
+    if (pressed != oldPressed)
+        [cell setHighlighted:pressed];
+}
+
+bool RenderThemeChromiumMac::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 RenderThemeChromiumMac::controlSizeForFont(RenderStyle* style) const
+{
+    int fontSize = style->fontSize();
+    if (fontSize >= 16)
+        return NSRegularControlSize;
+    if (fontSize >= 11)
+        return NSSmallControlSize;
+    return NSMiniControlSize;
+}
+
+void RenderThemeChromiumMac::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 RenderThemeChromiumMac::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 RenderThemeChromiumMac::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 RenderThemeChromiumMac::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 RenderThemeChromiumMac::setFontFromControlSize(StyleResolver*, 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 webCoreFamilyName]);
+    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 RenderThemeChromiumMac::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 RenderThemeChromiumMac::paintTextField(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
+{
+    LocalCurrentGraphicsContext localContext(paintInfo.context);
+
+#if __MAC_OS_X_VERSION_MIN_REQUIRED <= 1070
+    bool useNSTextFieldCell = o->style()->hasAppearance()
+        && o->style()->visitedDependentColor(CSSPropertyBackgroundColor) == Color::white
+        && !o->style()->hasBackgroundImage();
+
+    // We do not use NSTextFieldCell to draw styled text fields on Lion and SnowLeopard because
+    // there are a number of bugs on those platforms that require NSTextFieldCell to be in charge
+    // of painting its own background. We need WebCore to paint styled backgrounds, so we'll use
+    // this AppKit SPI function instead.
+    if (!useNSTextFieldCell) {
+        _NSDrawCarbonThemeBezel(r, isEnabled(o) && !isReadOnlyControl(o), YES);
+        return false;
+    }
+#endif
+
+    NSTextFieldCell *textField = this->textField();
+
+    GraphicsContextStateSaver stateSaver(*paintInfo.context);
+
+    [textField setEnabled:(isEnabled(o) && !isReadOnlyControl(o))];
+    [textField drawWithFrame:NSRect(r) inView:documentViewFor(o)];
+
+    [textField setControlView:nil];
+
+    return false;
+}
+
+void RenderThemeChromiumMac::adjustTextFieldStyle(StyleResolver*, RenderStyle*, Element*) const
+{
+}
+
+bool RenderThemeChromiumMac::paintCapsLockIndicator(RenderObject*, const PaintInfo& paintInfo, const IntRect& r)
+{
+    if (paintInfo.context->paintingDisabled())
+        return true;
+
+    // This draws the caps lock indicator as it was done by WKDrawCapsLockIndicator.
+    LocalCurrentGraphicsContext localContext(paintInfo.context);
+    CGContextRef c = localContext.cgContext();
+    CGMutablePathRef shape = CGPathCreateMutable();
+
+    // To draw the caps lock indicator, draw the shape into a small
+    // square that is then scaled to the size of r.
+    const CGFloat kSquareSize = 17;
+
+    // Create a rounted square shape.
+    CGPathMoveToPoint(shape, NULL, 16.5, 4.5);
+    CGPathAddArc(shape, NULL, 12.5, 12.5, 4, 0,        M_PI_2,   false);
+    CGPathAddArc(shape, NULL, 4.5,  12.5, 4, M_PI_2,   M_PI,     false);
+    CGPathAddArc(shape, NULL, 4.5,  4.5,  4, M_PI,     3*M_PI/2, false);
+    CGPathAddArc(shape, NULL, 12.5, 4.5,  4, 3*M_PI/2, 0,        false);
+
+    // Draw the arrow - note this is drawing in a flipped coordinate system, so the
+    // arrow is pointing down.
+    CGPathMoveToPoint(shape, NULL, 8.5, 2);  // Tip point.
+    CGPathAddLineToPoint(shape, NULL, 4,     7);
+    CGPathAddLineToPoint(shape, NULL, 6.25,  7);
+    CGPathAddLineToPoint(shape, NULL, 6.25,  10.25);
+    CGPathAddLineToPoint(shape, NULL, 10.75, 10.25);
+    CGPathAddLineToPoint(shape, NULL, 10.75, 7);
+    CGPathAddLineToPoint(shape, NULL, 13,    7);
+    CGPathAddLineToPoint(shape, NULL, 8.5,   2);
+
+    // Draw the rectangle that underneath (or above in the flipped system) the arrow.
+    CGPathAddLineToPoint(shape, NULL, 10.75, 12);
+    CGPathAddLineToPoint(shape, NULL, 6.25,  12);
+    CGPathAddLineToPoint(shape, NULL, 6.25,  14.25);
+    CGPathAddLineToPoint(shape, NULL, 10.75, 14.25);
+    CGPathAddLineToPoint(shape, NULL, 10.75, 12);
+
+    // Scale and translate the shape.
+    CGRect cgr = r;
+    CGFloat maxX = CGRectGetMaxX(cgr);
+    CGFloat minY = CGRectGetMinY(cgr);
+    CGFloat heightScale = r.height() / kSquareSize;
+    CGAffineTransform transform = CGAffineTransformMake(
+        heightScale, 0,  // A  B
+        0, heightScale,  // C  D
+        maxX - r.height(), minY);  // Tx Ty
+
+    CGMutablePathRef paintPath = CGPathCreateMutable();
+    CGPathAddPath(paintPath, &transform, shape);
+    CGPathRelease(shape);
+
+    CGContextSetRGBFillColor(c, 0, 0, 0, 0.4);
+    CGContextBeginPath(c);
+    CGContextAddPath(c, paintPath);
+    CGContextFillPath(c);
+    CGPathRelease(paintPath);
+
+    return false;
+}
+
+bool RenderThemeChromiumMac::paintTextArea(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
+{
+    LocalCurrentGraphicsContext localContext(paintInfo.context);
+    _NSDrawCarbonThemeListBox(r, isEnabled(o) && !isReadOnlyControl(o), YES, YES);
+    return false;
+}
+
+void RenderThemeChromiumMac::adjustTextAreaStyle(StyleResolver*, RenderStyle*, Element*) const
+{
+}
+
+const int* RenderThemeChromiumMac::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* RenderThemeChromiumMac::popupButtonSizes() const
+{
+    static const IntSize sizes[3] = { IntSize(0, 21), IntSize(0, 18), IntSize(0, 15) };
+    return sizes;
+}
+
+const int* RenderThemeChromiumMac::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 RenderThemeChromiumMac::paintMenuList(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
+{
+    LocalCurrentGraphicsContext localContext(paintInfo.context);
+    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);
+
+    GraphicsContextStateSaver stateSaver(*paintInfo.context);
+
+    // On Leopard, the cell will draw outside of the given rect, so we have to clip to the rect
+    paintInfo.context->clip(inflatedRect);
+
+    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());
+    }
+
+    NSView *view = documentViewFor(o);
+    [popupButton drawWithFrame:inflatedRect inView:view];
+#if !BUTTON_CELL_DRAW_WITH_FRAME_DRAWS_FOCUS_RING
+    if (isFocused(o) && o->style()->outlineStyleIsAuto())
+        [popupButton _web_drawFocusRingWithFrame:inflatedRect inView:view];
+#endif
+    [popupButton setControlView:nil];
+
+    return false;
+}
+
+IntSize RenderThemeChromiumMac::meterSizeForBounds(const RenderMeter* renderMeter, const IntRect& bounds) const
+{
+    if (NoControlPart == renderMeter->style()->appearance())
+        return bounds.size();
+
+    NSLevelIndicatorCell* cell = levelIndicatorFor(renderMeter);
+    // Makes enough room for cell's intrinsic size.
+    NSSize cellSize = [cell cellSizeForBounds:IntRect(IntPoint(), bounds.size())];
+    return IntSize(bounds.width() < cellSize.width ? cellSize.width : bounds.width(),
+                   bounds.height() < cellSize.height ? cellSize.height : bounds.height());
+}
+
+bool RenderThemeChromiumMac::paintMeter(RenderObject* renderObject, const PaintInfo& paintInfo, const IntRect& rect)
+{
+    if (!renderObject->isMeter())
+        return true;
+
+    LocalCurrentGraphicsContext localContext(paintInfo.context);
+
+    NSLevelIndicatorCell* cell = levelIndicatorFor(toRenderMeter(renderObject));
+    GraphicsContextStateSaver stateSaver(*paintInfo.context);
+
+    [cell drawWithFrame:rect inView:documentViewFor(renderObject)];
+    [cell setControlView:nil];
+    return false;
+}
+
+bool RenderThemeChromiumMac::supportsMeter(ControlPart part) const
+{
+    switch (part) {
+    case RelevancyLevelIndicatorPart:
+    case DiscreteCapacityLevelIndicatorPart:
+    case RatingLevelIndicatorPart:
+    case MeterPart:
+    case ContinuousCapacityLevelIndicatorPart:
+        return true;
+    default:
+        return false;
+    }
+}
+
+NSLevelIndicatorStyle RenderThemeChromiumMac::levelIndicatorStyleFor(ControlPart part) const
+{
+    switch (part) {
+    case RelevancyLevelIndicatorPart:
+        return NSRelevancyLevelIndicatorStyle;
+    case DiscreteCapacityLevelIndicatorPart:
+        return NSDiscreteCapacityLevelIndicatorStyle;
+    case RatingLevelIndicatorPart:
+        return NSRatingLevelIndicatorStyle;
+    case MeterPart:
+    case ContinuousCapacityLevelIndicatorPart:
+    default:
+        return NSContinuousCapacityLevelIndicatorStyle;
+    }
+
+}
+
+NSLevelIndicatorCell* RenderThemeChromiumMac::levelIndicatorFor(const RenderMeter* renderMeter) const
+{
+    RenderStyle* style = renderMeter->style();
+    ASSERT(style->appearance() != NoControlPart);
+
+    if (!m_levelIndicator)
+        m_levelIndicator.adoptNS([[NSLevelIndicatorCell alloc] initWithLevelIndicatorStyle:NSContinuousCapacityLevelIndicatorStyle]);
+    NSLevelIndicatorCell* cell = m_levelIndicator.get();
+
+    HTMLMeterElement* element = renderMeter->meterElement();
+    double value = element->value();
+
+    // Because NSLevelIndicatorCell does not support optimum-in-the-middle type coloring,
+    // we explicitly control the color instead giving low and high value to NSLevelIndicatorCell as is.
+    switch (element->gaugeRegion()) {
+    case HTMLMeterElement::GaugeRegionOptimum:
+        // Make meter the green
+        [cell setWarningValue:value + 1];
+        [cell setCriticalValue:value + 2];
+        break;
+    case HTMLMeterElement::GaugeRegionSuboptimal:
+        // Make the meter yellow
+        [cell setWarningValue:value - 1];
+        [cell setCriticalValue:value + 1];
+        break;
+    case HTMLMeterElement::GaugeRegionEvenLessGood:
+        // Make the meter red
+        [cell setWarningValue:value - 2];
+        [cell setCriticalValue:value - 1];
+        break;
+    }
+
+    [cell setLevelIndicatorStyle:levelIndicatorStyleFor(style->appearance())];
+    [cell setBaseWritingDirection:style->isLeftToRightDirection() ? NSWritingDirectionLeftToRight : NSWritingDirectionRightToLeft];
+    [cell setMinValue:element->min()];
+    [cell setMaxValue:element->max()];
+    RetainPtr<NSNumber> valueObject = [NSNumber numberWithDouble:value];
+    [cell setObjectValue:valueObject.get()];
+
+    return cell;
+}
+
+const IntSize* RenderThemeChromiumMac::progressBarSizes() const
+{
+    static const IntSize sizes[3] = { IntSize(0, 20), IntSize(0, 12), IntSize(0, 12) };
+    return sizes;
+}
+
+const int* RenderThemeChromiumMac::progressBarMargins(NSControlSize controlSize) const
+{
+    static const int margins[3][4] =
+    {
+        { 0, 0, 1, 0 },
+        { 0, 0, 1, 0 },
+        { 0, 0, 1, 0 },
+    };
+    return margins[controlSize];
+}
+
+int RenderThemeChromiumMac::minimumProgressBarHeight(RenderStyle* style) const
+{
+    return sizeForSystemFont(style, progressBarSizes()).height();
+}
+
+double RenderThemeChromiumMac::animationRepeatIntervalForProgressBar(RenderProgress*) const
+{
+    return progressAnimationFrameRate;
+}
+
+double RenderThemeChromiumMac::animationDurationForProgressBar(RenderProgress*) const
+{
+    return progressAnimationNumFrames * progressAnimationFrameRate;
+}
+
+void RenderThemeChromiumMac::adjustProgressBarStyle(StyleResolver*, RenderStyle*, Element*) const
+{
+}
+
+bool RenderThemeChromiumMac::paintProgressBar(RenderObject* renderObject, const PaintInfo& paintInfo, const IntRect& rect)
+{
+    if (!renderObject->isProgress())
+        return true;
+
+    float zoomLevel = renderObject->style()->effectiveZoom();
+    int controlSize = controlSizeForFont(renderObject->style());
+    IntSize size = progressBarSizes()[controlSize];
+    size.setHeight(size.height() * zoomLevel);
+    size.setWidth(rect.width());
+
+    // Now inflate it to account for the shadow.
+    IntRect inflatedRect = rect;
+    if (rect.height() <= minimumProgressBarHeight(renderObject->style()))
+        inflatedRect = inflateRect(inflatedRect, size, progressBarMargins(controlSize), zoomLevel);
+
+    RenderProgress* renderProgress = toRenderProgress(renderObject);
+    HIThemeTrackDrawInfo trackInfo;
+    trackInfo.version = 0;
+    if (controlSize == NSRegularControlSize)
+        trackInfo.kind = renderProgress->position() < 0 ? kThemeLargeIndeterminateBar : kThemeLargeProgressBar;
+    else
+        trackInfo.kind = renderProgress->position() < 0 ? kThemeMediumIndeterminateBar : kThemeMediumProgressBar;
+
+    trackInfo.bounds = IntRect(IntPoint(), inflatedRect.size());
+    trackInfo.min = 0;
+    trackInfo.max = numeric_limits<SInt32>::max();
+    trackInfo.value = lround(renderProgress->position() * nextafter(trackInfo.max, 0));
+    trackInfo.trackInfo.progress.phase = lround(renderProgress->animationProgress() * nextafter(progressAnimationNumFrames, 0));
+    trackInfo.attributes = kThemeTrackHorizontal;
+    trackInfo.enableState = isActive(renderObject) ? kThemeTrackActive : kThemeTrackInactive;
+    trackInfo.reserved = 0;
+    trackInfo.filler1 = 0;
+
+    OwnPtr<ImageBuffer> imageBuffer = ImageBuffer::create(inflatedRect.size(), 1);
+    if (!imageBuffer)
+        return true;
+
+    ContextContainer cgContextContainer(imageBuffer->context());
+    CGContextRef cgContext = cgContextContainer.context();
+    HIThemeDrawTrack(&trackInfo, 0, cgContext, kHIThemeOrientationNormal);
+
+    GraphicsContextStateSaver stateSaver(*paintInfo.context);
+
+    if (!renderProgress->style()->isLeftToRightDirection()) {
+        paintInfo.context->translate(2 * inflatedRect.x() + inflatedRect.width(), 0);
+        paintInfo.context->scale(FloatSize(-1, 1));
+    }
+
+    paintInfo.context->drawImageBuffer(imageBuffer.get(), ColorSpaceDeviceRGB, inflatedRect.location());
+    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*, 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*, 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*, 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*, 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 RenderThemeChromiumMac::paintMenuListButtonGradients(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
+{
+    if (r.isEmpty())
+        return;
+
+    ContextContainer cgContextContainer(paintInfo.context);
+    CGContextRef context = cgContextContainer.context();
+
+    GraphicsContextStateSaver stateSaver(*paintInfo.context);
+
+    RoundedRect border = o->style()->getRoundedBorderFor(r, o->view());
+    int radius = border.radii().topLeft().width();
+
+    CGColorSpaceRef cspace = deviceRGBColorSpaceRef();
+
+    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, CGPointMake(topGradient.x(), topGradient.y()), CGPointMake(topGradient.x(), topGradient.maxY()), 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, CGPointMake(bottomGradient.x(),  bottomGradient.y()), CGPointMake(bottomGradient.x(), bottomGradient.maxY()), 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, CGPointMake(r.x(),  r.y()), CGPointMake(r.x(), r.maxY()), mainFunction.get(), false, false));
+
+    RetainPtr<CGShadingRef> leftShading(AdoptCF, CGShadingCreateAxial(cspace, CGPointMake(r.x(),  r.y()), CGPointMake(r.x() + radius, r.y()), mainFunction.get(), false, false));
+
+    RetainPtr<CGShadingRef> rightShading(AdoptCF, CGShadingCreateAxial(cspace, CGPointMake(r.maxX(),  r.y()), CGPointMake(r.maxX() - radius, r.y()), mainFunction.get(), false, false));
+
+    {
+        GraphicsContextStateSaver stateSaver(*paintInfo.context);
+        CGContextClipToRect(context, r);
+        paintInfo.context->clipRoundedRect(border);
+        context = cgContextContainer.context();
+        CGContextDrawShading(context, mainShading.get());
+    }
+
+    {
+        GraphicsContextStateSaver stateSaver(*paintInfo.context);
+        CGContextClipToRect(context, topGradient);
+        paintInfo.context->clipRoundedRect(RoundedRect(enclosingIntRect(topGradient), border.radii().topLeft(), border.radii().topRight(), IntSize(), IntSize()));
+        context = cgContextContainer.context();
+        CGContextDrawShading(context, topShading.get());
+    }
+
+    if (!bottomGradient.isEmpty()) {
+        GraphicsContextStateSaver stateSaver(*paintInfo.context);
+        CGContextClipToRect(context, bottomGradient);
+        paintInfo.context->clipRoundedRect(RoundedRect(enclosingIntRect(bottomGradient), IntSize(), IntSize(), border.radii().bottomLeft(), border.radii().bottomRight()));
+        context = cgContextContainer.context();
+        CGContextDrawShading(context, bottomShading.get());
+    }
+
+    {
+        GraphicsContextStateSaver stateSaver(*paintInfo.context);
+        CGContextClipToRect(context, r);
+        paintInfo.context->clipRoundedRect(border);
+        context = cgContextContainer.context();
+        CGContextDrawShading(context, leftShading.get());
+        CGContextDrawShading(context, rightShading.get());
+    }
+}
+
+bool RenderThemeChromiumMac::paintMenuListButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
+{
+    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.maxX() - arrowPaddingRight * o->style()->effectiveZoom() - arrowWidth;
+    float spaceBetweenArrows = baseSpaceBetweenArrows * fontScale;
+
+    if (bounds.width() < arrowWidth + arrowPaddingLeft * o->style()->effectiveZoom())
+        return false;
+
+    GraphicsContextStateSaver stateSaver(*paintInfo.context);
+
+    paintInfo.context->setFillColor(o->style()->visitedDependentColor(CSSPropertyColor), o->style()->colorSpace());
+    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, ColorSpaceDeviceRGB);
+    paintInfo.context->drawLine(IntPoint(leftEdgeOfSeparator, bounds.y()),
+                                IntPoint(leftEdgeOfSeparator, bounds.maxY()));
+
+    paintInfo.context->setStrokeColor(rightSeparatorColor, ColorSpaceDeviceRGB);
+    paintInfo.context->drawLine(IntPoint(leftEdgeOfSeparator + separatorSpace, bounds.y()),
+                                IntPoint(leftEdgeOfSeparator + separatorSpace, bounds.maxY()));
+    return false;
+}
+
+static const IntSize* menuListButtonSizes()
+{
+    static const IntSize sizes[3] = { IntSize(0, 21), IntSize(0, 18), IntSize(0, 15) };
+    return sizes;
+}
+
+void RenderThemeChromiumMac::adjustMenuListStyle(StyleResolver* styleResolver, 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 && !e->isDisabledFormControl() ? 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(styleResolver, style, controlSize);
+}
+
+const int autofillPopupHorizontalPadding = 4;
+
+// These functions are called with MenuListPart or MenulistButtonPart appearance by RenderMenuList, or with TextFieldPart appearance by AutofillPopupMenuClient.
+// We assume only AutofillPopupMenuClient gives TexfieldPart appearance here.
+// We want to change only Autofill padding.
+// In the future, we have to separate Autofill popup window logic from WebKit to Chromium.
+int RenderThemeChromiumMac::popupInternalPaddingLeft(RenderStyle* style) const
+{
+    if (style->appearance() == TextFieldPart)
+        return autofillPopupHorizontalPadding;
+
+    if (style->appearance() == MenulistPart)
+        return popupButtonPadding(controlSizeForFont(style))[leftPadding] * style->effectiveZoom();
+    if (style->appearance() == MenulistButtonPart)
+        return styledPopupPaddingLeft * style->effectiveZoom();
+    return 0;
+}
+
+int RenderThemeChromiumMac::popupInternalPaddingRight(RenderStyle* style) const
+{
+    if (style->appearance() == TextFieldPart)
+        return autofillPopupHorizontalPadding;
+
+    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 RenderThemeChromiumMac::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 RenderThemeChromiumMac::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 RenderThemeChromiumMac::adjustMenuListButtonStyle(StyleResolver*, RenderStyle* style, Element*) 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 RenderThemeChromiumMac::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.
+    updateActiveState(popupButton, o);
+    updateCheckedState(popupButton, o);
+    updateEnabledState(popupButton, o);
+    updatePressedState(popupButton, o);
+#if BUTTON_CELL_DRAW_WITH_FRAME_DRAWS_FOCUS_RING
+    updateFocusedState(popupButton, o);
+#endif
+}
+
+const IntSize* RenderThemeChromiumMac::menuListSizes() const
+{
+    static const IntSize sizes[3] = { IntSize(9, 0), IntSize(5, 0), IntSize(0, 0) };
+    return sizes;
+}
+
+int RenderThemeChromiumMac::minimumMenuListSize(RenderStyle* style) const
+{
+    return sizeForSystemFont(style, menuListSizes()).width();
+}
+
+const int trackWidth = 5;
+const int trackRadius = 2;
+
+bool RenderThemeChromiumMac::paintSliderTrack(RenderObject* o, const 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 = localContext.cgContext();
+    CGColorSpaceRef cspace = deviceRGBColorSpaceRef();
+
+#if ENABLE(DATALIST_ELEMENT)
+    paintSliderTicks(o, paintInfo, r);
+#endif
+
+    GraphicsContextStateSaver stateSaver(*paintInfo.context);
+    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, CGPointMake(bounds.x(),  bounds.maxY()), CGPointMake(bounds.maxX(), bounds.maxY()), mainFunction.get(), false, false));
+    else
+        mainShading.adoptCF(CGShadingCreateAxial(cspace, CGPointMake(bounds.x(),  bounds.y()), CGPointMake(bounds.x(), bounds.maxY()), mainFunction.get(), false, false));
+
+    IntSize radius(trackRadius, trackRadius);
+    paintInfo.context->clipRoundedRect(RoundedRect(bounds, radius, radius, radius, radius));
+    context = localContext.cgContext();
+    CGContextDrawShading(context, mainShading.get());
+
+    return false;
+}
+
+const float verticalSliderHeightPadding = 0.1f;
+
+bool RenderThemeChromiumMac::paintSliderThumb(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
+{
+    NSSliderCell* sliderThumbCell = o->style()->appearance() == SliderThumbVerticalPart
+        ? sliderThumbVertical()
+        : sliderThumbHorizontal();
+
+    LocalCurrentGraphicsContext localContext(paintInfo.context);
+
+    // Update the various states we respond to.
+    updateActiveState(sliderThumbCell, o);
+    updateEnabledState(sliderThumbCell, o);
+    updateFocusedState(sliderThumbCell, (o->node() && o->node()->focusDelegate()->renderer()) ? o->node()->focusDelegate()->renderer() : o);
+
+    // 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 = isPressed(o);
+
+    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());
+
+    GraphicsContextStateSaver stateSaver(*paintInfo.context);
+    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());
+    }
+
+    paintInfo.context->translate(0, unzoomedRect.y());
+    paintInfo.context->scale(FloatSize(1, -1));
+    paintInfo.context->translate(0, -(unzoomedRect.y() + unzoomedRect.height()));
+
+    [sliderThumbCell drawInteriorWithFrame:unzoomedRect inView:documentViewFor(o)];
+    [sliderThumbCell setControlView:nil];
+
+    return false;
+}
+
+bool RenderThemeChromiumMac::paintSearchField(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
+{
+    LocalCurrentGraphicsContext localContext(paintInfo.context);
+    NSSearchFieldCell* search = this->search();
+
+    setSearchCellState(o, r);
+
+    GraphicsContextStateSaver stateSaver(*paintInfo.context);
+
+    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:documentViewFor(o)];
+
+    [search setControlView:nil];
+    [search resetSearchButtonCell];
+
+    return false;
+}
+
+void RenderThemeChromiumMac::setSearchCellState(RenderObject* o, const IntRect&)
+{
+    NSSearchFieldCell* search = this->search();
+
+    [search setControlSize:controlSizeForFont(o->style())];
+
+    // Update the various states we respond to.
+    updateActiveState(search, o);
+    updateEnabledState(search, o);
+    updateFocusedState(search, o);
+}
+
+const IntSize* RenderThemeChromiumMac::searchFieldSizes() const
+{
+    static const IntSize sizes[3] = { IntSize(0, 22), IntSize(0, 19), IntSize(0, 17) };
+    return sizes;
+}
+
+void RenderThemeChromiumMac::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 RenderThemeChromiumMac::adjustSearchFieldStyle(StyleResolver* styleResolver, RenderStyle* style, Element*) 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(styleResolver, style, controlSize);
+
+    style->setBoxShadow(nullptr);
+}
+
+bool RenderThemeChromiumMac::paintSearchFieldCancelButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
+{
+    Element* input = o->node()->shadowHost();
+    if (!input)
+        input = toElement(o->node());
+
+    if (!input->renderer()->isBox())
+        return false;
+
+    LocalCurrentGraphicsContext localContext(paintInfo.context);
+    setSearchCellState(input->renderer(), r);
+
+    NSSearchFieldCell* search = this->search();
+
+    if (!input->isDisabledFormControl() && (input->isTextFormControl() && !toHTMLTextFormControlElement(input)->isReadOnly())) {
+        updateActiveState([search cancelButtonCell], o);
+        updatePressedState([search cancelButtonCell], o);
+    }
+    else if ([[search cancelButtonCell] isHighlighted])
+        [[search cancelButtonCell] setHighlighted:NO];
+
+    GraphicsContextStateSaver stateSaver(*paintInfo.context);
+
+    float zoomLevel = o->style()->effectiveZoom();
+
+    FloatRect localBounds = [search cancelButtonRectForBounds:NSRect(input->renderBox()->pixelSnappedBorderBoxRect())];
+
+#if ENABLE(INPUT_SPEECH)
+    // Take care of cases where the cancel button was not aligned with the right border of the input element (for e.g.
+    // when speech input is enabled for the input element.
+    IntRect absBoundingBox = input->renderer()->absoluteBoundingBoxRect();
+    int absRight = absBoundingBox.x() + absBoundingBox.width() - input->renderBox()->paddingRight() - input->renderBox()->borderRight();
+    int spaceToRightOfCancelButton = absRight - (r.x() + r.width());
+    localBounds.setX(localBounds.x() - spaceToRightOfCancelButton);
+#endif
+
+    localBounds = convertToPaintingRect(input->renderer(), o, localBounds, r);
+
+    FloatRect unzoomedRect(localBounds);
+    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:documentViewFor(o)];
+    [[search cancelButtonCell] setControlView:nil];
+    return false;
+}
+
+const IntSize* RenderThemeChromiumMac::cancelButtonSizes() const
+{
+    static const IntSize sizes[3] = { IntSize(16, 13), IntSize(13, 11), IntSize(13, 9) };
+    return sizes;
+}
+
+void RenderThemeChromiumMac::adjustSearchFieldCancelButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
+{
+    IntSize size = sizeForSystemFont(style, cancelButtonSizes());
+    style->setWidth(Length(size.width(), Fixed));
+    style->setHeight(Length(size.height(), Fixed));
+    style->setBoxShadow(nullptr);
+}
+
+const IntSize* RenderThemeChromiumMac::resultsButtonSizes() const
+{
+    static const IntSize sizes[3] = { IntSize(19, 13), IntSize(17, 11), IntSize(17, 9) };
+    return sizes;
+}
+
+const int emptyResultsOffset = 9;
+void RenderThemeChromiumMac::adjustSearchFieldDecorationStyle(StyleResolver*, RenderStyle* style, Element*) const
+{
+    IntSize size = sizeForSystemFont(style, resultsButtonSizes());
+    style->setWidth(Length(size.width() - emptyResultsOffset, Fixed));
+    style->setHeight(Length(size.height(), Fixed));
+    style->setBoxShadow(nullptr);
+}
+
+bool RenderThemeChromiumMac::paintSearchFieldDecoration(RenderObject*, const PaintInfo&, const IntRect&)
+{
+    return false;
+}
+
+void RenderThemeChromiumMac::adjustSearchFieldResultsDecorationStyle(StyleResolver*, RenderStyle* style, Element*) const
+{
+    IntSize size = sizeForSystemFont(style, resultsButtonSizes());
+    style->setWidth(Length(size.width(), Fixed));
+    style->setHeight(Length(size.height(), Fixed));
+    style->setBoxShadow(nullptr);
+}
+
+bool RenderThemeChromiumMac::paintSearchFieldResultsDecoration(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
+{
+    Node* input = o->node()->shadowHost();
+    if (!input)
+        input = o->node();
+    if (!input->renderer()->isBox())
+        return false;
+
+    LocalCurrentGraphicsContext localContext(paintInfo.context);
+    setSearchCellState(input->renderer(), r);
+
+    NSSearchFieldCell* search = this->search();
+
+    if ([search searchMenuTemplate] != nil)
+        [search setSearchMenuTemplate:nil];
+
+    updateActiveState([search searchButtonCell], o);
+
+    FloatRect localBounds = [search searchButtonRectForBounds:NSRect(input->renderBox()->pixelSnappedBorderBoxRect())];
+    localBounds = convertToPaintingRect(input->renderer(), o, localBounds, r);
+
+    [[search searchButtonCell] drawWithFrame:localBounds inView:documentViewFor(o)];
+    [[search searchButtonCell] setControlView:nil];
+    return false;
+}
+
+const int resultsArrowWidth = 5;
+void RenderThemeChromiumMac::adjustSearchFieldResultsButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
+{
+    IntSize size = sizeForSystemFont(style, resultsButtonSizes());
+    style->setWidth(Length(size.width() + resultsArrowWidth, Fixed));
+    style->setHeight(Length(size.height(), Fixed));
+    style->setBoxShadow(nullptr);
+}
+
+bool RenderThemeChromiumMac::paintSearchFieldResultsButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
+{
+    Node* input = o->node()->shadowHost();
+    if (!input)
+        input = o->node();
+    if (!input->renderer()->isBox())
+        return false;
+
+    LocalCurrentGraphicsContext localContext(paintInfo.context);
+    setSearchCellState(input->renderer(), r);
+
+    NSSearchFieldCell* search = this->search();
+
+    updateActiveState([search searchButtonCell], o);
+
+    if (![search searchMenuTemplate])
+        [search setSearchMenuTemplate:searchMenuTemplate()];
+
+    GraphicsContextStateSaver stateSaver(*paintInfo.context);
+    float zoomLevel = o->style()->effectiveZoom();
+
+    FloatRect localBounds = [search searchButtonRectForBounds:NSRect(input->renderBox()->pixelSnappedBorderBoxRect())];
+    localBounds = convertToPaintingRect(input->renderer(), o, localBounds, r);
+
+    IntRect unzoomedRect(localBounds);
+    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:documentViewFor(o)];
+    [[search searchButtonCell] setControlView:nil];
+
+    return false;
+}
+
+#if ENABLE(DATALIST_ELEMENT)
+IntSize RenderThemeChromiumMac::sliderTickSize() const
+{
+    return IntSize(1, 3);
+}
+
+int RenderThemeChromiumMac::sliderTickOffsetFromTrackCenter() const
+{
+    return -9;
+}
+#endif
+
+const int sliderThumbWidth = 15;
+const int sliderThumbHeight = 15;
+
+void RenderThemeChromiumMac::adjustSliderThumbSize(RenderStyle* style, Element*) const
+{
+    float zoomLevel = style->effectiveZoom();
+    if (style->appearance() == SliderThumbHorizontalPart || style->appearance() == SliderThumbVerticalPart) {
+        style->setWidth(Length(static_cast<int>(sliderThumbWidth * zoomLevel), Fixed));
+        style->setHeight(Length(static_cast<int>(sliderThumbHeight * zoomLevel), Fixed));
+    }
+
+    adjustMediaSliderThumbSize(style);
+}
+
+NSPopUpButtonCell* RenderThemeChromiumMac::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* RenderThemeChromiumMac::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* RenderThemeChromiumMac::searchMenuTemplate() const
+{
+    if (!m_searchMenuTemplate)
+        m_searchMenuTemplate.adoptNS([[NSMenu alloc] initWithTitle:@""]);
+
+    return m_searchMenuTemplate.get();
+}
+
+NSSliderCell* RenderThemeChromiumMac::sliderThumbHorizontal() const
+{
+    if (!m_sliderThumbHorizontal) {
+        m_sliderThumbHorizontal.adoptNS([[NSSliderCell alloc] init]);
+        [m_sliderThumbHorizontal.get() setSliderType:NSLinearSlider];
+        [m_sliderThumbHorizontal.get() setControlSize:NSSmallControlSize];
+        [m_sliderThumbHorizontal.get() setFocusRingType:NSFocusRingTypeExterior];
+    }
+
+    return m_sliderThumbHorizontal.get();
+}
+
+NSSliderCell* RenderThemeChromiumMac::sliderThumbVertical() const
+{
+    if (!m_sliderThumbVertical) {
+        m_sliderThumbVertical.adoptNS([[NSSliderCell alloc] init]);
+        [m_sliderThumbVertical.get() setSliderType:NSLinearSlider];
+        [m_sliderThumbVertical.get() setControlSize:NSSmallControlSize];
+        [m_sliderThumbVertical.get() setFocusRingType:NSFocusRingTypeExterior];
+    }
+
+    return m_sliderThumbVertical.get();
+}
+
+NSTextFieldCell* RenderThemeChromiumMac::textField() const
+{
+    if (!m_textField) {
+        m_textField.adoptNS([[WebCoreTextFieldCell alloc] initTextCell:@""]);
+        [m_textField.get() setBezeled:YES];
+        [m_textField.get() setEditable:YES];
+        [m_textField.get() setFocusRingType:NSFocusRingTypeExterior];
+#if __MAC_OS_X_VERSION_MIN_REQUIRED <= 1070
+        [m_textField.get() setDrawsBackground:YES];
+        [m_textField.get() setBackgroundColor:[NSColor whiteColor]];
+#else
+        // Post-Lion, WebCore can be in charge of paintinng the background thanks to
+        // the workaround in place for <rdar://problem/11385461>, which is implemented
+        // above as _coreUIDrawOptionsWithFrame.
+        [m_textField.get() setDrawsBackground:NO];
+#endif
+    }
+
+    return m_textField.get();
+}
+
+String RenderThemeChromiumMac::fileListNameForWidth(const FileList* fileList, const Font& font, int width, bool multipleFilesAllowed) const
+{
+    if (width <= 0)
+        return String();
+
+    String strToTruncate;
+    if (fileList->isEmpty())
+        strToTruncate = fileListDefaultLabel(multipleFilesAllowed);
+    else if (fileList->length() == 1)
+        strToTruncate = [[NSFileManager defaultManager] displayNameAtPath:(fileList->item(0)->path())];
+    else
+        return StringTruncator::rightTruncate(multipleFileUploadText(fileList->length()), width, font, StringTruncator::EnableRoundingHacks);
+
+    return StringTruncator::centerTruncate(strToTruncate, width, font, StringTruncator::EnableRoundingHacks);
+}
+
+NSView* FlippedView()
+{
+    static NSView* view = [[RTCMFlippedView alloc] init];
+    return view;
+}
+
+PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page*)
+{
+    static RenderTheme* rt = RenderThemeChromiumMac::create().leakRef();
+    return rt;
+}
+
+PassRefPtr<RenderTheme> RenderThemeChromiumMac::create()
+{
+    return adoptRef(new RenderThemeChromiumMac);
+}
+
+bool RenderThemeChromiumMac::supportsDataListUI(const AtomicString& type) const
+{
+    return RenderThemeChromiumCommon::supportsDataListUI(type);
+}
+
+bool RenderThemeChromiumMac::usesTestModeFocusRingColor() const
+{
+    return isRunningLayoutTest();
+}
+
+NSView* RenderThemeChromiumMac::documentViewFor(RenderObject*) const
+{
+    return FlippedView();
+}
+
+// Updates the control tint (a.k.a. active state) of |cell| (from |o|).
+// In the Chromium port, the renderer runs as a background process and controls'
+// NSCell(s) lack a parent NSView. Therefore controls don't have their tint
+// color updated correctly when the application is activated/deactivated.
+// FocusController's setActive() is called when the application is
+// activated/deactivated, which causes a repaint at which time this code is
+// called.
+// This function should be called before drawing any NSCell-derived controls,
+// unless you're sure it isn't needed.
+void RenderThemeChromiumMac::updateActiveState(NSCell* cell, const RenderObject* o)
+{
+    NSControlTint oldTint = [cell controlTint];
+    NSControlTint tint = isActive(o) ? [NSColor currentControlTint] :
+                                       static_cast<NSControlTint>(NSClearControlTint);
+
+    if (tint != oldTint)
+        [cell setControlTint:tint];
+}
+
+bool RenderThemeChromiumMac::shouldShowPlaceholderWhenFocused() const
+{
+    return true;
+}
+
+void RenderThemeChromiumMac::adjustMediaSliderThumbSize(RenderStyle* style) const
+{
+    RenderMediaControlsChromium::adjustMediaSliderThumbSize(style);
+}
+
+bool RenderThemeChromiumMac::paintMediaPlayButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
+{
+    return RenderMediaControlsChromium::paintMediaControlsPart(MediaPlayButton, object, paintInfo, rect);
+}
+
+bool RenderThemeChromiumMac::paintMediaMuteButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
+{
+    return RenderMediaControlsChromium::paintMediaControlsPart(MediaMuteButton, object, paintInfo, rect);
+}
+
+bool RenderThemeChromiumMac::paintMediaSliderTrack(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
+{
+    return RenderMediaControlsChromium::paintMediaControlsPart(MediaSlider, object, paintInfo, rect);
+}
+
+String RenderThemeChromiumMac::extraMediaControlsStyleSheet()
+{
+    return String(mediaControlsChromiumUserAgentStyleSheet, sizeof(mediaControlsChromiumUserAgentStyleSheet));
+}
+
+String RenderThemeChromiumMac::extraFullScreenStyleSheet()
+{
+    // FIXME: Chromium may wish to style its default media controls differently in fullscreen.
+    return String();
+}
+
+String RenderThemeChromiumMac::extraDefaultStyleSheet()
+{
+    return RenderTheme::extraDefaultStyleSheet() +
+           String(themeChromiumUserAgentStyleSheet, sizeof(themeChromiumUserAgentStyleSheet));
+}
+
+#if ENABLE(DATALIST_ELEMENT)
+LayoutUnit RenderThemeChromiumMac::sliderTickSnappingThreshold() const
+{
+    return RenderThemeChromiumCommon::sliderTickSnappingThreshold();
+}
+#endif
+
+#if ENABLE(INPUT_MULTIPLE_FIELDS_UI) && ENABLE(CALENDAR_PICKER)
+bool RenderThemeChromiumMac::supportsCalendarPicker(const AtomicString& type) const
+{
+    return RenderThemeChromiumCommon::supportsCalendarPicker(type);
+}
+#endif
+
+bool RenderThemeChromiumMac::paintMediaVolumeSliderContainer(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
+{
+    return true;
+}
+
+bool RenderThemeChromiumMac::paintMediaVolumeSliderTrack(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
+{
+    return RenderMediaControlsChromium::paintMediaControlsPart(MediaVolumeSlider, object, paintInfo, rect);
+}
+
+bool RenderThemeChromiumMac::paintMediaVolumeSliderThumb(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
+{
+    return RenderMediaControlsChromium::paintMediaControlsPart(MediaVolumeSliderThumb, object, paintInfo, rect);
+}
+
+bool RenderThemeChromiumMac::paintMediaSliderThumb(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
+{
+    return RenderMediaControlsChromium::paintMediaControlsPart(MediaSliderThumb, object, paintInfo, rect);
+}
+
+String RenderThemeChromiumMac::formatMediaControlsTime(float time) const
+{
+    return RenderMediaControlsChromium::formatMediaControlsTime(time);
+}
+
+String RenderThemeChromiumMac::formatMediaControlsCurrentTime(float currentTime, float duration) const
+{
+    return RenderMediaControlsChromium::formatMediaControlsCurrentTime(currentTime, duration);
+}
+
+bool RenderThemeChromiumMac::paintMediaFullscreenButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
+{
+    return RenderMediaControlsChromium::paintMediaControlsPart(MediaEnterFullscreenButton, object, paintInfo, rect);
+}
+
+bool RenderThemeChromiumMac::paintMediaToggleClosedCaptionsButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
+{
+    return RenderMediaControlsChromium::paintMediaControlsPart(MediaShowClosedCaptionsButton, object, paintInfo, rect);
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderThemeChromiumSkia.cpp b/Source/core/rendering/RenderThemeChromiumSkia.cpp
new file mode 100644
index 0000000..db04d93
--- /dev/null
+++ b/Source/core/rendering/RenderThemeChromiumSkia.cpp
@@ -0,0 +1,567 @@
+/*
+ * Copyright (C) 2007 Apple Inc.
+ * Copyright (C) 2007 Alp Toker <alp@atoker.com>
+ * Copyright (C) 2008 Collabora Ltd.
+ * Copyright (C) 2008, 2009 Google 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 "core/rendering/RenderThemeChromiumSkia.h"
+
+#include "CSSValueKeywords.h"
+#include "HTMLNames.h"
+#include "UserAgentStyleSheets.h"
+#include "core/html/HTMLMediaElement.h"
+#include "core/html/TimeRanges.h"
+#include "core/html/shadow/MediaControlElements.h"
+#include "core/platform/LayoutTestSupport.h"
+#include "core/platform/ScrollbarTheme.h"
+#include "core/platform/graphics/Font.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/platform/graphics/Image.h"
+#include "core/platform/graphics/skia/PlatformContextSkia.h"
+#include "core/platform/graphics/transforms/TransformationMatrix.h"
+#include "core/rendering/PaintInfo.h"
+#include "core/rendering/RenderBox.h"
+#include "core/rendering/RenderMediaControlsChromium.h"
+#include "core/rendering/RenderObject.h"
+#include "core/rendering/RenderProgress.h"
+#include "core/rendering/RenderSlider.h"
+#include "core/rendering/RenderThemeChromiumFontProvider.h"
+
+#include <wtf/CurrentTime.h>
+
+#include "SkGradientShader.h"
+#include "SkShader.h"
+
+namespace WebCore {
+
+enum PaddingType {
+    TopPadding,
+    RightPadding,
+    BottomPadding,
+    LeftPadding
+};
+
+static const int styledMenuListInternalPadding[4] = { 1, 4, 1, 4 };
+
+// These values all match Safari/Win.
+static const float defaultControlFontPixelSize = 13;
+static const float defaultCancelButtonSize = 9;
+static const float minCancelButtonSize = 5;
+static const float maxCancelButtonSize = 21;
+static const float defaultSearchFieldResultsDecorationSize = 13;
+static const float minSearchFieldResultsDecorationSize = 9;
+static const float maxSearchFieldResultsDecorationSize = 30;
+static const float defaultSearchFieldResultsButtonWidth = 18;
+
+RenderThemeChromiumSkia::RenderThemeChromiumSkia()
+{
+}
+
+RenderThemeChromiumSkia::~RenderThemeChromiumSkia()
+{
+}
+
+// Use the Windows style sheets to match their metrics.
+String RenderThemeChromiumSkia::extraDefaultStyleSheet()
+{
+    return String(themeWinUserAgentStyleSheet, sizeof(themeWinUserAgentStyleSheet)) +
+           String(themeChromiumSkiaUserAgentStyleSheet, sizeof(themeChromiumSkiaUserAgentStyleSheet)) +
+           String(themeChromiumUserAgentStyleSheet, sizeof(themeChromiumUserAgentStyleSheet));
+}
+
+String RenderThemeChromiumSkia::extraQuirksStyleSheet()
+{
+    return String(themeWinQuirksUserAgentStyleSheet, sizeof(themeWinQuirksUserAgentStyleSheet));
+}
+
+String RenderThemeChromiumSkia::extraMediaControlsStyleSheet()
+{
+    return String(mediaControlsChromiumUserAgentStyleSheet, sizeof(mediaControlsChromiumUserAgentStyleSheet));
+}
+
+bool RenderThemeChromiumSkia::supportsHover(const RenderStyle* style) const
+{
+    return true;
+}
+
+bool RenderThemeChromiumSkia::supportsFocusRing(const RenderStyle* style) const
+{
+    // This causes WebKit to draw the focus rings for us.
+    return false;
+}
+
+bool RenderThemeChromiumSkia::supportsDataListUI(const AtomicString& type) const
+{
+    return RenderThemeChromiumCommon::supportsDataListUI(type);
+}
+
+#if ENABLE(INPUT_MULTIPLE_FIELDS_UI) && ENABLE(CALENDAR_PICKER)
+bool RenderThemeChromiumSkia::supportsCalendarPicker(const AtomicString& type) const
+{
+    return RenderThemeChromiumCommon::supportsCalendarPicker(type);
+}
+#endif
+
+bool RenderThemeChromiumSkia::supportsClosedCaptioning() const
+{
+    return true;
+}
+
+Color RenderThemeChromiumSkia::platformActiveSelectionBackgroundColor() const
+{
+    return Color(0x1e, 0x90, 0xff);
+}
+
+Color RenderThemeChromiumSkia::platformInactiveSelectionBackgroundColor() const
+{
+    return Color(0xc8, 0xc8, 0xc8);
+}
+
+Color RenderThemeChromiumSkia::platformActiveSelectionForegroundColor() const
+{
+    return Color::black;
+}
+
+Color RenderThemeChromiumSkia::platformInactiveSelectionForegroundColor() const
+{
+    return Color(0x32, 0x32, 0x32);
+}
+
+Color RenderThemeChromiumSkia::platformFocusRingColor() const
+{
+    static Color focusRingColor(229, 151, 0, 255);
+    return focusRingColor;
+}
+
+double RenderThemeChromiumSkia::caretBlinkInterval() const
+{
+    // Disable the blinking caret in layout test mode, as it introduces
+    // a race condition for the pixel tests. http://b/1198440
+    if (isRunningLayoutTest())
+        return 0;
+
+    return caretBlinkIntervalInternal();
+}
+
+void RenderThemeChromiumSkia::systemFont(int propId, FontDescription& fontDescription) const
+{
+    RenderThemeChromiumFontProvider::systemFont(propId, fontDescription);
+}
+
+int RenderThemeChromiumSkia::minimumMenuListSize(RenderStyle* style) const
+{
+    return 0;
+}
+
+// These are the default dimensions of radio buttons and checkboxes.
+static const int widgetStandardWidth = 13;
+static const int widgetStandardHeight = 13;
+
+// Return a rectangle that has the same center point as |original|, but with a
+// size capped at |width| by |height|.
+IntRect center(const IntRect& original, int width, int height)
+{
+    width = std::min(original.width(), width);
+    height = std::min(original.height(), height);
+    int x = original.x() + (original.width() - width) / 2;
+    int y = original.y() + (original.height() - height) / 2;
+
+    return IntRect(x, y, width, height);
+}
+
+void RenderThemeChromiumSkia::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.
+    const IntSize size(widgetStandardWidth, widgetStandardHeight);
+    setSizeIfAuto(style, size);
+}
+
+void RenderThemeChromiumSkia::setRadioSize(RenderStyle* style) const
+{
+    // Use same sizing for radio box as checkbox.
+    setCheckboxSize(style);
+}
+
+void RenderThemeChromiumSkia::adjustButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
+{
+    if (style->appearance() == PushButtonPart) {
+        // Ignore line-height.
+        style->setLineHeight(RenderStyle::initialLineHeight());
+    }
+}
+
+bool RenderThemeChromiumSkia::paintTextArea(RenderObject* o, const PaintInfo& i, const IntRect& r)
+{
+    return paintTextField(o, i, r);
+}
+
+void RenderThemeChromiumSkia::adjustSearchFieldStyle(StyleResolver*, RenderStyle* style, Element*) const
+{
+     // Ignore line-height.
+     style->setLineHeight(RenderStyle::initialLineHeight());
+}
+
+bool RenderThemeChromiumSkia::paintSearchField(RenderObject* o, const PaintInfo& i, const IntRect& r)
+{
+    return paintTextField(o, i, r);
+}
+
+void RenderThemeChromiumSkia::adjustSearchFieldCancelButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
+{
+    // Scale the button size based on the font size
+    float fontScale = style->fontSize() / defaultControlFontPixelSize;
+    int cancelButtonSize = lroundf(std::min(std::max(minCancelButtonSize, defaultCancelButtonSize * fontScale), maxCancelButtonSize));
+    style->setWidth(Length(cancelButtonSize, Fixed));
+    style->setHeight(Length(cancelButtonSize, Fixed));
+}
+
+IntRect RenderThemeChromiumSkia::convertToPaintingRect(RenderObject* inputRenderer, const RenderObject* partRenderer, LayoutRect partRect, const IntRect& localOffset) const
+{
+    // Compute an offset between the part renderer and the input renderer.
+    LayoutSize offsetFromInputRenderer = -partRenderer->offsetFromAncestorContainer(inputRenderer);
+    // Move the rect into partRenderer's coords.
+    partRect.move(offsetFromInputRenderer);
+    // Account for the local drawing offset.
+    partRect.move(localOffset.x(), localOffset.y());
+
+    return pixelSnappedIntRect(partRect);
+}
+
+bool RenderThemeChromiumSkia::paintSearchFieldCancelButton(RenderObject* cancelButtonObject, const PaintInfo& paintInfo, const IntRect& r)
+{
+    // Get the renderer of <input> element.
+    Node* input = cancelButtonObject->node()->shadowHost();
+    RenderObject* baseRenderer = input ? input->renderer() : cancelButtonObject;
+    if (!baseRenderer->isBox())
+        return false;
+    RenderBox* inputRenderBox = toRenderBox(baseRenderer);
+    LayoutRect inputContentBox = inputRenderBox->contentBoxRect();
+
+    // Make sure the scaled button stays square and will fit in its parent's box.
+    LayoutUnit cancelButtonSize = std::min(inputContentBox.width(), std::min<LayoutUnit>(inputContentBox.height(), r.height()));
+    // Calculate cancel button's coordinates relative to the input element.
+    // Center the button vertically.  Round up though, so if it has to be one pixel off-center, it will
+    // be one pixel closer to the bottom of the field.  This tends to look better with the text.
+    LayoutRect cancelButtonRect(cancelButtonObject->offsetFromAncestorContainer(inputRenderBox).width(),
+                                inputContentBox.y() + (inputContentBox.height() - cancelButtonSize + 1) / 2,
+                                cancelButtonSize, cancelButtonSize);
+    IntRect paintingRect = convertToPaintingRect(inputRenderBox, cancelButtonObject, cancelButtonRect, r);
+
+    static Image* cancelImage = Image::loadPlatformResource("searchCancel").leakRef();
+    static Image* cancelPressedImage = Image::loadPlatformResource("searchCancelPressed").leakRef();
+    paintInfo.context->drawImage(isPressed(cancelButtonObject) ? cancelPressedImage : cancelImage,
+                                 cancelButtonObject->style()->colorSpace(), paintingRect);
+    return false;
+}
+
+void RenderThemeChromiumSkia::adjustSearchFieldDecorationStyle(StyleResolver*, RenderStyle* style, Element*) const
+{
+    IntSize emptySize(1, 11);
+    style->setWidth(Length(emptySize.width(), Fixed));
+    style->setHeight(Length(emptySize.height(), Fixed));
+}
+
+void RenderThemeChromiumSkia::adjustSearchFieldResultsDecorationStyle(StyleResolver*, RenderStyle* style, Element*) const
+{
+    // Scale the decoration size based on the font size
+    float fontScale = style->fontSize() / defaultControlFontPixelSize;
+    int magnifierSize = lroundf(std::min(std::max(minSearchFieldResultsDecorationSize, defaultSearchFieldResultsDecorationSize * fontScale),
+                                         maxSearchFieldResultsDecorationSize));
+    style->setWidth(Length(magnifierSize, Fixed));
+    style->setHeight(Length(magnifierSize, Fixed));
+}
+
+bool RenderThemeChromiumSkia::paintSearchFieldResultsDecoration(RenderObject* magnifierObject, const PaintInfo& paintInfo, const IntRect& r)
+{
+    // Get the renderer of <input> element.
+    Node* input = magnifierObject->node()->shadowHost();
+    RenderObject* baseRenderer = input ? input->renderer() : magnifierObject;
+    if (!baseRenderer->isBox())
+        return false;
+    RenderBox* inputRenderBox = toRenderBox(baseRenderer);
+    LayoutRect inputContentBox = inputRenderBox->contentBoxRect();
+
+    // Make sure the scaled decoration stays square and will fit in its parent's box.
+    LayoutUnit magnifierSize = std::min(inputContentBox.width(), std::min<LayoutUnit>(inputContentBox.height(), r.height()));
+    // Calculate decoration's coordinates relative to the input element.
+    // Center the decoration vertically.  Round up though, so if it has to be one pixel off-center, it will
+    // be one pixel closer to the bottom of the field.  This tends to look better with the text.
+    LayoutRect magnifierRect(magnifierObject->offsetFromAncestorContainer(inputRenderBox).width(),
+                             inputContentBox.y() + (inputContentBox.height() - magnifierSize + 1) / 2,
+                             magnifierSize, magnifierSize);
+    IntRect paintingRect = convertToPaintingRect(inputRenderBox, magnifierObject, magnifierRect, r);
+
+    static Image* magnifierImage = Image::loadPlatformResource("searchMagnifier").leakRef();
+    paintInfo.context->drawImage(magnifierImage, magnifierObject->style()->colorSpace(), paintingRect);
+    return false;
+}
+
+void RenderThemeChromiumSkia::adjustSearchFieldResultsButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
+{
+    // Scale the button size based on the font size
+    float fontScale = style->fontSize() / defaultControlFontPixelSize;
+    int magnifierHeight = lroundf(std::min(std::max(minSearchFieldResultsDecorationSize, defaultSearchFieldResultsDecorationSize * fontScale),
+                                           maxSearchFieldResultsDecorationSize));
+    int magnifierWidth = lroundf(magnifierHeight * defaultSearchFieldResultsButtonWidth / defaultSearchFieldResultsDecorationSize);
+    style->setWidth(Length(magnifierWidth, Fixed));
+    style->setHeight(Length(magnifierHeight, Fixed));
+}
+
+bool RenderThemeChromiumSkia::paintSearchFieldResultsButton(RenderObject* magnifierObject, const PaintInfo& paintInfo, const IntRect& r)
+{
+    // Get the renderer of <input> element.
+    Node* input = magnifierObject->node()->shadowHost();
+    RenderObject* baseRenderer = input ? input->renderer() : magnifierObject;
+    if (!baseRenderer->isBox())
+        return false;
+    RenderBox* inputRenderBox = toRenderBox(baseRenderer);
+    LayoutRect inputContentBox = inputRenderBox->contentBoxRect();
+
+    // Make sure the scaled decoration will fit in its parent's box.
+    LayoutUnit magnifierHeight = std::min<LayoutUnit>(inputContentBox.height(), r.height());
+    LayoutUnit magnifierWidth = std::min<LayoutUnit>(inputContentBox.width(), magnifierHeight * defaultSearchFieldResultsButtonWidth / defaultSearchFieldResultsDecorationSize);
+    LayoutRect magnifierRect(magnifierObject->offsetFromAncestorContainer(inputRenderBox).width(),
+                             inputContentBox.y() + (inputContentBox.height() - magnifierHeight + 1) / 2,
+                             magnifierWidth, magnifierHeight);
+    IntRect paintingRect = convertToPaintingRect(inputRenderBox, magnifierObject, magnifierRect, r);
+
+    static Image* magnifierImage = Image::loadPlatformResource("searchMagnifierResults").leakRef();
+    paintInfo.context->drawImage(magnifierImage, magnifierObject->style()->colorSpace(), paintingRect);
+    return false;
+}
+
+bool RenderThemeChromiumSkia::paintMediaSliderTrack(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
+{
+    return RenderMediaControlsChromium::paintMediaControlsPart(MediaSlider, object, paintInfo, rect);
+}
+
+bool RenderThemeChromiumSkia::paintMediaVolumeSliderTrack(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
+{
+    return RenderMediaControlsChromium::paintMediaControlsPart(MediaVolumeSlider, object, paintInfo, rect);
+}
+
+void RenderThemeChromiumSkia::adjustSliderThumbSize(RenderStyle* style, Element*) const
+{
+    RenderMediaControlsChromium::adjustMediaSliderThumbSize(style);
+}
+
+bool RenderThemeChromiumSkia::paintMediaSliderThumb(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
+{
+    return RenderMediaControlsChromium::paintMediaControlsPart(MediaSliderThumb, object, paintInfo, rect);
+}
+
+bool RenderThemeChromiumSkia::paintMediaToggleClosedCaptionsButton(RenderObject* o, const PaintInfo& paintInfo, const IntRect& r)
+{
+    return RenderMediaControlsChromium::paintMediaControlsPart(MediaShowClosedCaptionsButton, o, paintInfo, r);
+}
+
+bool RenderThemeChromiumSkia::paintMediaVolumeSliderThumb(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
+{
+    return RenderMediaControlsChromium::paintMediaControlsPart(MediaVolumeSliderThumb, object, paintInfo, rect);
+}
+
+bool RenderThemeChromiumSkia::paintMediaPlayButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
+{
+    return RenderMediaControlsChromium::paintMediaControlsPart(MediaPlayButton, object, paintInfo, rect);
+}
+
+bool RenderThemeChromiumSkia::paintMediaMuteButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
+{
+    return RenderMediaControlsChromium::paintMediaControlsPart(MediaMuteButton, object, paintInfo, rect);
+}
+
+String RenderThemeChromiumSkia::formatMediaControlsTime(float time) const
+{
+    return RenderMediaControlsChromium::formatMediaControlsTime(time);
+}
+
+String RenderThemeChromiumSkia::formatMediaControlsCurrentTime(float currentTime, float duration) const
+{
+    return RenderMediaControlsChromium::formatMediaControlsCurrentTime(currentTime, duration);
+}
+
+bool RenderThemeChromiumSkia::paintMediaFullscreenButton(RenderObject* object, const PaintInfo& paintInfo, const IntRect& rect)
+{
+    return RenderMediaControlsChromium::paintMediaControlsPart(MediaEnterFullscreenButton, object, paintInfo, rect);
+}
+
+void RenderThemeChromiumSkia::adjustMenuListStyle(StyleResolver*, RenderStyle* style, WebCore::Element*) const
+{
+    // Height is locked to auto on all browsers.
+    style->setLineHeight(RenderStyle::initialLineHeight());
+}
+
+void RenderThemeChromiumSkia::adjustMenuListButtonStyle(StyleResolver* styleResolver, RenderStyle* style, Element* e) const
+{
+    adjustMenuListStyle(styleResolver, style, e);
+}
+
+// Used to paint styled menulists (i.e. with a non-default border)
+bool RenderThemeChromiumSkia::paintMenuListButton(RenderObject* o, const PaintInfo& i, const IntRect& rect)
+{
+    return paintMenuList(o, i, rect);
+}
+
+int RenderThemeChromiumSkia::popupInternalPaddingLeft(RenderStyle* style) const
+{
+    return menuListInternalPadding(style, LeftPadding);
+}
+
+int RenderThemeChromiumSkia::popupInternalPaddingRight(RenderStyle* style) const
+{
+    return menuListInternalPadding(style, RightPadding);
+}
+
+int RenderThemeChromiumSkia::popupInternalPaddingTop(RenderStyle* style) const
+{
+    return menuListInternalPadding(style, TopPadding);
+}
+
+int RenderThemeChromiumSkia::popupInternalPaddingBottom(RenderStyle* style) const
+{
+    return menuListInternalPadding(style, BottomPadding);
+}
+
+// static
+void RenderThemeChromiumSkia::setDefaultFontSize(int fontSize)
+{
+    RenderThemeChromiumFontProvider::setDefaultFontSize(fontSize);
+}
+
+double RenderThemeChromiumSkia::caretBlinkIntervalInternal() const
+{
+    return RenderTheme::caretBlinkInterval();
+}
+
+int RenderThemeChromiumSkia::menuListArrowPadding() const
+{
+    return ScrollbarTheme::theme()->scrollbarThickness();
+}
+
+// static
+void RenderThemeChromiumSkia::setSizeIfAuto(RenderStyle* style, const IntSize& size)
+{
+    if (style->width().isIntrinsicOrAuto())
+        style->setWidth(Length(size.width(), Fixed));
+    if (style->height().isAuto())
+        style->setHeight(Length(size.height(), Fixed));
+}
+
+int RenderThemeChromiumSkia::menuListInternalPadding(RenderStyle* style, int paddingType) const
+{
+    // This internal padding is in addition to the user-supplied padding.
+    // Matches the FF behavior.
+    int padding = styledMenuListInternalPadding[paddingType];
+
+    // Reserve the space for right arrow here. The rest of the padding is
+    // set by adjustMenuListStyle, since PopMenuWin.cpp uses the padding from
+    // RenderMenuList to lay out the individual items in the popup.
+    // If the MenuList actually has appearance "NoAppearance", then that means
+    // we don't draw a button, so don't reserve space for it.
+    const int barType = style->direction() == LTR ? RightPadding : LeftPadding;
+    if (paddingType == barType && style->appearance() != NoControlPart)
+        padding += menuListArrowPadding();
+
+    return padding;
+}
+
+bool RenderThemeChromiumSkia::shouldShowPlaceholderWhenFocused() const
+{
+    return true;
+}
+
+#if ENABLE(DATALIST_ELEMENT)
+LayoutUnit RenderThemeChromiumSkia::sliderTickSnappingThreshold() const
+{
+    return RenderThemeChromiumCommon::sliderTickSnappingThreshold();
+}
+#endif
+
+//
+// Following values are come from default of GTK+
+//
+static const int progressDeltaPixelsPerSecond = 100;
+static const int progressActivityBlocks = 5;
+static const int progressAnimationFrmaes = 10;
+static const double progressAnimationInterval = 0.125;
+
+IntRect RenderThemeChromiumSkia::determinateProgressValueRectFor(RenderProgress* renderProgress, const IntRect& rect) const
+{
+    int dx = rect.width() * renderProgress->position();
+    return IntRect(rect.x(), rect.y(), dx, rect.height());
+}
+
+IntRect RenderThemeChromiumSkia::indeterminateProgressValueRectFor(RenderProgress* renderProgress, const IntRect& rect) const
+{
+
+    int valueWidth = rect.width() / progressActivityBlocks;
+    int movableWidth = rect.width() - valueWidth;
+    if (movableWidth <= 0)
+        return IntRect();
+
+    double progress = renderProgress->animationProgress();
+    if (progress < 0.5)
+        return IntRect(rect.x() + progress * 2 * movableWidth, rect.y(), valueWidth, rect.height());
+    return IntRect(rect.x() + (1.0 - progress) * 2 * movableWidth, rect.y(), valueWidth, rect.height());
+}
+
+double RenderThemeChromiumSkia::animationRepeatIntervalForProgressBar(RenderProgress*) const
+{
+    return progressAnimationInterval;
+}
+
+double RenderThemeChromiumSkia::animationDurationForProgressBar(RenderProgress* renderProgress) const
+{
+    return progressAnimationInterval * progressAnimationFrmaes * 2; // "2" for back and forth
+}
+
+IntRect RenderThemeChromiumSkia::progressValueRectFor(RenderProgress* renderProgress, const IntRect& rect) const
+{
+    return renderProgress->isDeterminate() ? determinateProgressValueRectFor(renderProgress, rect) : indeterminateProgressValueRectFor(renderProgress, rect);
+}
+
+RenderThemeChromiumSkia::DirectionFlippingScope::DirectionFlippingScope(RenderObject* renderer, const PaintInfo& paintInfo, const IntRect& rect)
+    : m_needsFlipping(!renderer->style()->isLeftToRightDirection())
+    , m_paintInfo(paintInfo)
+{
+    if (!m_needsFlipping)
+        return;
+    m_paintInfo.context->save();
+    m_paintInfo.context->translate(2 * rect.x() + rect.width(), 0);
+    m_paintInfo.context->scale(FloatSize(-1, 1));
+}
+
+RenderThemeChromiumSkia::DirectionFlippingScope::~DirectionFlippingScope()
+{
+    if (!m_needsFlipping)
+        return;
+    m_paintInfo.context->restore();
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderThemeChromiumSkia.h b/Source/core/rendering/RenderThemeChromiumSkia.h
new file mode 100644
index 0000000..624d690
--- /dev/null
+++ b/Source/core/rendering/RenderThemeChromiumSkia.h
@@ -0,0 +1,184 @@
+/*
+ * This file is part of the WebKit project.
+ *
+ * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
+ * Copyright (C) 2007 Holger Hans Peter Freyther
+ * Copyright (C) 2007 Alp Toker <alp@atoker.com>
+ * Copyright (C) 2008, 2009 Google, 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 RenderThemeChromiumSkia_h
+#define RenderThemeChromiumSkia_h
+
+#include "core/rendering/RenderTheme.h"
+#include "core/rendering/RenderThemeChromiumCommon.h"
+
+namespace WebCore {
+
+class RenderProgress;
+
+class RenderThemeChromiumSkia : public RenderTheme {
+public:
+    RenderThemeChromiumSkia();
+    virtual ~RenderThemeChromiumSkia();
+
+    virtual String extraDefaultStyleSheet();
+    virtual String extraQuirksStyleSheet();
+    virtual String extraMediaControlsStyleSheet();
+
+    virtual Color platformTapHighlightColor() const OVERRIDE
+    {
+        return Color(defaultTapHighlightColor);
+    }
+
+    // A method asking if the theme's controls actually care about redrawing when hovered.
+    virtual bool supportsHover(const RenderStyle*) const;
+
+    // A method asking if the theme is able to draw the focus ring.
+    virtual bool supportsFocusRing(const RenderStyle*) const;
+
+    virtual bool supportsDataListUI(const AtomicString& type) const OVERRIDE;
+
+    virtual bool supportsClosedCaptioning() const OVERRIDE;
+    // The platform selection color.
+    virtual Color platformActiveSelectionBackgroundColor() const;
+    virtual Color platformInactiveSelectionBackgroundColor() const;
+    virtual Color platformActiveSelectionForegroundColor() const;
+    virtual Color platformInactiveSelectionForegroundColor() const;
+    virtual Color platformFocusRingColor() const;
+
+    // To change the blink interval, override caretBlinkIntervalInternal instead of this one so that we may share layout test code an intercepts.
+    virtual double caretBlinkInterval() const;
+
+    // System fonts.
+    virtual void systemFont(int propId, FontDescription&) const;
+
+    virtual int minimumMenuListSize(RenderStyle*) const;
+
+    virtual void setCheckboxSize(RenderStyle*) const;
+
+    virtual void setRadioSize(RenderStyle*) const;
+
+    virtual void adjustButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
+
+    virtual bool paintTextArea(RenderObject*, const PaintInfo&, const IntRect&);
+
+    virtual void adjustSearchFieldStyle(StyleResolver*, RenderStyle*, Element*) const;
+    virtual bool paintSearchField(RenderObject*, const PaintInfo&, const IntRect&);
+
+    virtual void adjustSearchFieldCancelButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
+    virtual bool paintSearchFieldCancelButton(RenderObject*, const PaintInfo&, const IntRect&);
+
+    virtual void adjustSearchFieldDecorationStyle(StyleResolver*, RenderStyle*, Element*) const;
+
+    virtual void adjustSearchFieldResultsDecorationStyle(StyleResolver*, RenderStyle*, Element*) const;
+    virtual bool paintSearchFieldResultsDecoration(RenderObject*, const PaintInfo&, const IntRect&);
+
+    virtual void adjustSearchFieldResultsButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
+    virtual bool paintSearchFieldResultsButton(RenderObject*, const PaintInfo&, const IntRect&);
+
+    virtual bool paintMediaSliderTrack(RenderObject*, const PaintInfo&, const IntRect&);
+    virtual bool paintMediaVolumeSliderTrack(RenderObject*, const PaintInfo&, const IntRect&);
+    virtual void adjustSliderThumbSize(RenderStyle*, Element*) const;
+    virtual bool paintMediaSliderThumb(RenderObject*, const PaintInfo&, const IntRect&);
+    virtual bool paintMediaToggleClosedCaptionsButton(RenderObject*, const PaintInfo&, const IntRect&);
+    virtual bool paintMediaVolumeSliderThumb(RenderObject*, const PaintInfo&, const IntRect&);
+    virtual bool paintMediaPlayButton(RenderObject*, const PaintInfo&, const IntRect&);
+    virtual bool paintMediaMuteButton(RenderObject*, const PaintInfo&, const IntRect&);
+    virtual String formatMediaControlsTime(float time) const;
+    virtual String formatMediaControlsCurrentTime(float currentTime, float duration) const;
+    virtual bool paintMediaFullscreenButton(RenderObject*, const PaintInfo&, const IntRect&);
+
+    // MenuList refers to an unstyled menulist (meaning a menulist without
+    // background-color or border set) and MenuListButton refers to a styled
+    // menulist (a menulist with background-color or border set). They have
+    // this distinction to support showing aqua style themes whenever they
+    // possibly can, which is something we don't want to replicate.
+    //
+    // In short, we either go down the MenuList code path or the MenuListButton
+    // codepath. We never go down both. And in both cases, they render the
+    // entire menulist.
+    virtual void adjustMenuListStyle(StyleResolver*, RenderStyle*, Element*) const;
+    virtual void adjustMenuListButtonStyle(StyleResolver*, RenderStyle*, Element*) const;
+    virtual bool paintMenuListButton(RenderObject*, const PaintInfo&, const IntRect&);
+
+    virtual double animationRepeatIntervalForProgressBar(RenderProgress*) const;
+    virtual double animationDurationForProgressBar(RenderProgress*) const;
+
+    // These methods define the padding for the MenuList's inner block.
+    virtual int popupInternalPaddingLeft(RenderStyle*) const;
+    virtual int popupInternalPaddingRight(RenderStyle*) const;
+    virtual int popupInternalPaddingTop(RenderStyle*) const;
+    virtual int popupInternalPaddingBottom(RenderStyle*) const;
+
+    // Media controls
+    virtual bool hasOwnDisabledStateHandlingFor(ControlPart) const { return true; }
+    virtual bool usesVerticalVolumeSlider() const { return false; }
+
+    // Provide a way to pass the default font size from the Settings object
+    // to the render theme. FIXME: http://b/1129186 A cleaner way would be
+    // to remove the default font size from this object and have callers
+    // that need the value to get it directly from the appropriate Settings
+    // object.
+    static void setDefaultFontSize(int);
+
+protected:
+    virtual double caretBlinkIntervalInternal() const;
+
+    virtual int menuListArrowPadding() const;
+
+    static void setSizeIfAuto(RenderStyle*, const IntSize&);
+
+    IntRect determinateProgressValueRectFor(RenderProgress*, const IntRect&) const;
+    IntRect indeterminateProgressValueRectFor(RenderProgress*, const IntRect&) const;
+    IntRect progressValueRectFor(RenderProgress*, const IntRect&) const;
+
+    class DirectionFlippingScope {
+    public:
+        DirectionFlippingScope(RenderObject*, const PaintInfo&, const IntRect&);
+        ~DirectionFlippingScope();
+
+    private:
+        bool m_needsFlipping;
+        const PaintInfo& m_paintInfo;
+    };
+
+private:
+    virtual Color disabledTextColor(const Color& textColor, const Color&) const OVERRIDE { return textColor; }
+    virtual bool shouldShowPlaceholderWhenFocused() const OVERRIDE;
+
+#if ENABLE(DATALIST_ELEMENT)
+    virtual LayoutUnit sliderTickSnappingThreshold() const OVERRIDE;
+#endif
+#if ENABLE(INPUT_MULTIPLE_FIELDS_UI)
+    virtual bool supportsCalendarPicker(const AtomicString& type) const OVERRIDE;
+#endif
+
+    int menuListInternalPadding(RenderStyle*, int paddingType) const;
+    bool paintMediaButtonInternal(GraphicsContext*, const IntRect&, Image*);
+    IntRect convertToPaintingRect(RenderObject* inputRenderer, const RenderObject* partRenderer, LayoutRect partRect, const IntRect& localOffset) const;
+
+    static const RGBA32 defaultTapHighlightColor = 0x2e000000; // 18% black.
+};
+
+} // namespace WebCore
+
+#endif // RenderThemeChromiumSkia_h
diff --git a/Source/core/rendering/RenderThemeChromiumWin.cpp b/Source/core/rendering/RenderThemeChromiumWin.cpp
new file mode 100644
index 0000000..5f67d03
--- /dev/null
+++ b/Source/core/rendering/RenderThemeChromiumWin.cpp
@@ -0,0 +1,663 @@
+/*
+ * This file is part of the WebKit project.
+ *
+ * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2008, 2009 Google, Inc.
+ * Copyright (C) 2009 Kenneth Rohde Christiansen
+ *
+ * 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 "core/rendering/RenderThemeChromiumWin.h"
+
+#include <windows.h>
+#include <uxtheme.h>
+#include <vssym32.h>
+
+#include "CSSValueKeywords.h"
+#include "HTMLNames.h"
+#include "core/html/HTMLMediaElement.h"
+#include "core/html/shadow/MediaControlElements.h"
+#include "core/platform/LayoutTestSupport.h"
+#include "core/platform/ScrollbarTheme.h"
+#include "core/platform/graphics/FontSelector.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/platform/graphics/chromium/FontUtilsChromiumWin.h"
+#include "core/platform/graphics/chromium/TransparencyWin.h"
+#include "core/platform/graphics/skia/PlatformContextSkia.h"
+#include "core/platform/win/SystemInfo.h"
+#include "core/rendering/PaintInfo.h"
+#include "core/rendering/RenderBox.h"
+#include "core/rendering/RenderProgress.h"
+#include "core/rendering/RenderSlider.h"
+#include "core/rendering/RenderThemeChromiumCommon.h"
+#include <public/Platform.h>
+#include <public/WebColor.h>
+#include <public/WebRect.h>
+#include <public/win/WebThemeEngine.h>
+#include <wtf/CurrentTime.h>
+
+
+// FIXME: This dependency should eventually be removed.
+#include <skia/ext/skia_utils_win.h>
+
+namespace WebCore {
+
+// The standard width for the menu list drop-down button when run under
+// layout test mode. Use the value that's currently captured in most baselines.
+static const int kStandardMenuListButtonWidth = 17;
+
+namespace {
+// We must not create multiple ThemePainter instances.
+class ThemePainter {
+public:
+    ThemePainter(GraphicsContext* context, const IntRect& r)
+    {
+#ifndef NDEBUG
+        ASSERT(!s_hasInstance);
+        s_hasInstance = true;
+#endif
+        TransparencyWin::TransformMode transformMode = getTransformMode(context->getCTM());
+        m_helper.init(context, getLayerMode(context, transformMode), transformMode, r);
+
+        if (!m_helper.context()) {
+            // TransparencyWin doesn't have well-defined copy-ctor nor op=()
+            // so we re-initialize it instead of assigning a fresh istance.
+            // On the reinitialization, we fallback to use NoLayer mode.
+            // Note that the original initialization failure can be caused by
+            // a failure of an internal buffer allocation and NoLayer mode
+            // does not have such buffer allocations.
+            m_helper.~TransparencyWin();
+            new (&m_helper) TransparencyWin();
+            m_helper.init(context, TransparencyWin::NoLayer, transformMode, r);
+        }
+    }
+
+    ~ThemePainter()
+    {
+        m_helper.composite();
+#ifndef NDEBUG
+        s_hasInstance = false;
+#endif
+    }
+
+    GraphicsContext* context() { return m_helper.context(); }
+    const IntRect& drawRect() { return m_helper.drawRect(); }
+
+private:
+
+    static TransparencyWin::LayerMode getLayerMode(GraphicsContext* context, TransparencyWin::TransformMode transformMode)
+    {
+        if (!context->isCertainlyOpaque()) // Might have transparent background.
+            return TransparencyWin::WhiteLayer;
+        if (context->platformContext()->canvas()->isDrawingToLayer()) // Needs antialiasing help.
+            return TransparencyWin::OpaqueCompositeLayer;
+        // Nothing interesting.
+        return transformMode == TransparencyWin::KeepTransform ? TransparencyWin::NoLayer : TransparencyWin::OpaqueCompositeLayer;
+    }
+
+    static TransparencyWin::TransformMode getTransformMode(const AffineTransform& matrix)
+    {
+        if (matrix.b() || matrix.c()) // Skew.
+            return TransparencyWin::Untransform;
+        if (matrix.a() != 1.0 || matrix.d() != 1.0) // Scale.
+            return TransparencyWin::ScaleTransform;
+        // Nothing interesting.
+        return TransparencyWin::KeepTransform;
+    }
+
+    TransparencyWin m_helper;
+#ifndef NDEBUG
+    static bool s_hasInstance;
+#endif
+};
+
+#ifndef NDEBUG
+bool ThemePainter::s_hasInstance = false;
+#endif
+
+} // namespace
+
+// Internal static helper functions.  We don't put them in an anonymous
+// namespace so they have easier access to the WebCore namespace.
+
+static bool supportsFocus(ControlPart appearance)
+{
+    switch (appearance) {
+    case SquareButtonPart:
+    case PushButtonPart:
+    case ButtonPart:
+    case SearchFieldPart:
+    case TextFieldPart:
+    case TextAreaPart:
+        return true;
+    }
+    return false;
+}
+
+static double querySystemBlinkInterval(double defaultInterval)
+{
+    UINT blinkTime = GetCaretBlinkTime();
+    if (!blinkTime)
+        return defaultInterval;
+    if (blinkTime == INFINITE)
+        return 0;
+    return blinkTime / 1000.0;
+}
+
+PassRefPtr<RenderTheme> RenderThemeChromiumWin::create()
+{
+    return adoptRef(new RenderThemeChromiumWin);
+}
+
+PassRefPtr<RenderTheme> RenderTheme::themeForPage(Page* page)
+{
+    static RenderTheme* rt = RenderThemeChromiumWin::create().leakRef();
+    return rt;
+}
+
+bool RenderThemeChromiumWin::supportsFocusRing(const RenderStyle* style) const
+{
+    // Let webkit draw one of its halo rings around any focused element,
+    // except push buttons. For buttons we use the windows PBS_DEFAULTED
+    // styling to give it a blue border.
+    return style->appearance() == ButtonPart
+            || style->appearance() == PushButtonPart
+            || style->appearance() == SquareButtonPart;
+}
+
+Color RenderThemeChromiumWin::platformActiveSelectionBackgroundColor() const
+{
+    if (isRunningLayoutTest())
+        return Color(0x00, 0x00, 0xff); // Royal blue.
+    COLORREF color = GetSysColor(COLOR_HIGHLIGHT);
+    return Color(GetRValue(color), GetGValue(color), GetBValue(color), 0xff);
+}
+
+Color RenderThemeChromiumWin::platformInactiveSelectionBackgroundColor() const
+{
+    if (isRunningLayoutTest())
+        return Color(0x99, 0x99, 0x99); // Medium gray.
+    COLORREF color = GetSysColor(COLOR_GRAYTEXT);
+    return Color(GetRValue(color), GetGValue(color), GetBValue(color), 0xff);
+}
+
+Color RenderThemeChromiumWin::platformActiveSelectionForegroundColor() const
+{
+    if (isRunningLayoutTest())
+        return Color(0xff, 0xff, 0xcc); // Pale yellow.
+    COLORREF color = GetSysColor(COLOR_HIGHLIGHTTEXT);
+    return Color(GetRValue(color), GetGValue(color), GetBValue(color), 0xff);
+}
+
+Color RenderThemeChromiumWin::platformInactiveSelectionForegroundColor() const
+{
+    return Color::white;
+}
+
+Color RenderThemeChromiumWin::platformActiveTextSearchHighlightColor() const
+{
+    return Color(0xff, 0x96, 0x32); // Orange.
+}
+
+Color RenderThemeChromiumWin::platformInactiveTextSearchHighlightColor() const
+{
+    return Color(0xff, 0xff, 0x96); // Yellow.
+}
+
+// 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 RenderThemeChromiumWin::systemColor(int cssValueId) const
+{
+    int sysColorIndex = cssValueIdToSysColorIndex(cssValueId);
+    if (isRunningLayoutTest() || (sysColorIndex == -1))
+        return RenderTheme::systemColor(cssValueId);
+
+    COLORREF color = GetSysColor(sysColorIndex);
+    return Color(GetRValue(color), GetGValue(color), GetBValue(color));
+}
+
+#if ENABLE(DATALIST_ELEMENT)
+IntSize RenderThemeChromiumWin::sliderTickSize() const
+{
+    return IntSize(1, 3);
+}
+
+int RenderThemeChromiumWin::sliderTickOffsetFromTrackCenter() const
+{
+    return 11;
+}
+#endif
+
+void RenderThemeChromiumWin::adjustSliderThumbSize(RenderStyle* style, Element* element) const
+{
+    // These sizes match what WinXP draws for various menus.
+    const int sliderThumbAlongAxis = 11;
+    const int sliderThumbAcrossAxis = 21;
+    if (style->appearance() == SliderThumbHorizontalPart) {
+        style->setWidth(Length(sliderThumbAlongAxis, Fixed));
+        style->setHeight(Length(sliderThumbAcrossAxis, Fixed));
+    } else if (style->appearance() == SliderThumbVerticalPart) {
+        style->setWidth(Length(sliderThumbAcrossAxis, Fixed));
+        style->setHeight(Length(sliderThumbAlongAxis, Fixed));
+    } else
+        RenderThemeChromiumSkia::adjustSliderThumbSize(style, element);
+}
+
+bool RenderThemeChromiumWin::paintCheckbox(RenderObject* o, const PaintInfo& i, const IntRect& r)
+{
+    return paintButton(o, i, r);
+}
+bool RenderThemeChromiumWin::paintRadio(RenderObject* o, const PaintInfo& i, const IntRect& r)
+{
+    return paintButton(o, i, r);
+}
+
+bool RenderThemeChromiumWin::paintButton(RenderObject* o, const PaintInfo& i, const IntRect& r)
+{
+    const ThemeData& themeData = getThemeData(o);
+
+    ThemePainter painter(i.context, r);
+    WebKit::WebCanvas* canvas = painter.context()->platformContext()->canvas();
+    WebKit::Platform::current()->themeEngine()->paintButton(canvas, themeData.m_part, themeData.m_state, themeData.m_classicState, WebKit::WebRect(painter.drawRect()));
+    return false;
+}
+
+bool RenderThemeChromiumWin::paintTextField(RenderObject* o, const PaintInfo& i, const IntRect& r)
+{
+    return paintTextFieldInternal(o, i, r, true);
+}
+
+bool RenderThemeChromiumWin::paintSliderTrack(RenderObject* o, const PaintInfo& i, const IntRect& r)
+{
+    const ThemeData& themeData = getThemeData(o);
+
+    ThemePainter painter(i.context, r);
+    WebKit::WebCanvas* canvas = painter.context()->platformContext()->canvas();
+    WebKit::Platform::current()->themeEngine()->paintTrackbar(canvas, themeData.m_part, themeData.m_state, themeData.m_classicState, WebKit::WebRect(painter.drawRect()));
+
+#if ENABLE(DATALIST_ELEMENT)
+    paintSliderTicks(o, i, r);
+#endif
+
+    return false;
+}
+
+bool RenderThemeChromiumWin::paintSliderThumb(RenderObject* o, const PaintInfo& i, const IntRect& r)
+{
+    const ThemeData& themeData = getThemeData(o);
+
+    ThemePainter painter(i.context, r);
+    WebKit::WebCanvas* canvas = painter.context()->platformContext()->canvas();
+    WebKit::Platform::current()->themeEngine()->paintTrackbar(canvas, themeData.m_part, themeData.m_state, themeData.m_classicState, WebKit::WebRect(painter.drawRect()));
+
+    return false;
+}
+
+static int menuListButtonWidth()
+{
+    static int width = isRunningLayoutTest() ? kStandardMenuListButtonWidth : 
+        IntSize(WebKit::Platform::current()->themeEngine()->getSize(SBP_ARROWBTN)).width();
+    return width;
+}
+
+// Used to paint unstyled menulists (i.e. with the default border)
+bool RenderThemeChromiumWin::paintMenuList(RenderObject* o, const PaintInfo& i, const IntRect& r)
+{
+    if (!o->isBox())
+        return false;
+
+    const RenderBox* box = toRenderBox(o);
+    int borderRight = box->borderRight();
+    int borderLeft = box->borderLeft();
+    int borderTop = box->borderTop();
+    int borderBottom = box->borderBottom();
+
+    // If all the borders are 0, then tell skia not to paint the border on the
+    // textfield.  FIXME: http://b/1210017 Figure out how to get Windows to not
+    // draw individual borders and then pass that to skia so we can avoid
+    // drawing any borders that are set to 0. For non-zero borders, we draw the
+    // border, but webkit just draws over it.
+    bool drawEdges = !(!borderRight && !borderLeft && !borderTop && !borderBottom);
+
+    paintTextFieldInternal(o, i, r, drawEdges);
+    return paintMenuListButton(o, i, r);
+}
+
+bool RenderThemeChromiumWin::paintMenuListButton(RenderObject* o, const PaintInfo& i, const IntRect& r)
+{
+    if (!o->isBox())
+        return false;
+
+    const RenderBox* box = toRenderBox(o);
+    // Take padding and border into account.  If the MenuList is smaller than
+    // the size of a button, make sure to shrink it appropriately and not put
+    // its x position to the left of the menulist.
+    const int buttonWidth = menuListButtonWidth();
+    int spacingLeft = box->borderLeft() + box->paddingLeft();
+    int spacingRight = box->borderRight() + box->paddingRight();
+    int spacingTop = box->borderTop() + box->paddingTop();
+    int spacingBottom = box->borderBottom() + box->paddingBottom();
+
+    int buttonX;
+    if (r.maxX() - r.x() < buttonWidth)
+        buttonX = r.x();
+    else
+        buttonX = o->style()->direction() == LTR ? r.maxX() - spacingRight - buttonWidth : r.x() + spacingLeft;
+
+    // Compute the rectangle of the button in the destination image.
+    IntRect rect(buttonX,
+                 r.y() + spacingTop,
+                 std::min(buttonWidth, r.maxX() - r.x()),
+                 r.height() - (spacingTop + spacingBottom));
+
+    // Get the correct theme data for a textfield and paint the menu.
+    ThemePainter painter(i.context, rect);
+    WebKit::WebCanvas* canvas = painter.context()->platformContext()->canvas();
+    WebKit::Platform::current()->themeEngine()->paintMenuList(canvas, CP_DROPDOWNBUTTON, determineState(o), determineClassicState(o), WebKit::WebRect(painter.drawRect()));
+    return false;
+}
+
+double RenderThemeChromiumWin::caretBlinkIntervalInternal() const
+{
+    // This involves a system call, so we cache the result.
+    static double blinkInterval = querySystemBlinkInterval(RenderTheme::caretBlinkInterval());
+    return blinkInterval;
+}
+
+unsigned RenderThemeChromiumWin::determineState(RenderObject* o, ControlSubPart subPart)
+{
+    unsigned result = TS_NORMAL;
+    ControlPart appearance = o->style()->appearance();
+    if (!isEnabled(o))
+        result = TS_DISABLED;
+    else if (isReadOnlyControl(o))
+        result = (appearance == TextFieldPart || appearance == TextAreaPart || appearance == SearchFieldPart) ? ETS_READONLY : TS_DISABLED;
+    // Active overrides hover and focused.
+    else if (isPressed(o) && (subPart == SpinButtonUp) == isSpinUpButtonPartPressed(o))
+        result = TS_PRESSED;
+    else if (supportsFocus(appearance) && isFocused(o))
+        result = ETS_FOCUSED;
+    else if (isHovered(o) && (subPart == SpinButtonUp) == isSpinUpButtonPartHovered(o))
+        result = TS_HOT;
+
+    // CBS_UNCHECKED*: 1-4
+    // CBS_CHECKED*: 5-8
+    // CBS_MIXED*: 9-12
+    if (isIndeterminate(o))
+        result += 8;
+    else if (isChecked(o))
+        result += 4;
+    return result;
+}
+
+unsigned RenderThemeChromiumWin::determineSliderThumbState(RenderObject* o)
+{
+    unsigned result = TUS_NORMAL;
+    if (!isEnabled(o))
+        result = TUS_DISABLED;
+    else if (supportsFocus(o->style()->appearance()) && isFocused(o))
+        result = TUS_FOCUSED;
+    else if (isPressed(o))
+        result = TUS_PRESSED;
+    else if (isHovered(o))
+        result = TUS_HOT;
+    return result;
+}
+
+unsigned RenderThemeChromiumWin::determineClassicState(RenderObject* o, ControlSubPart subPart)
+{
+    unsigned result = 0;
+
+    ControlPart part = o->style()->appearance();
+
+    // Sliders are always in the normal state.
+    if (part == SliderHorizontalPart || part == SliderVerticalPart)
+        return result;
+
+    // So are readonly text fields.
+    if (isReadOnlyControl(o) && (part == TextFieldPart || part == TextAreaPart || part == SearchFieldPart))
+        return result;
+
+    if (part == SliderThumbHorizontalPart || part == SliderThumbVerticalPart) {
+        if (!isEnabled(o))
+            result = DFCS_INACTIVE;
+        else if (isPressed(o)) // Active supersedes hover
+            result = DFCS_PUSHED;
+        else if (isHovered(o))
+            result = DFCS_HOT;
+    } else {
+        if (!isEnabled(o) || isReadOnlyControl(o))
+            result = DFCS_INACTIVE;
+        // Active supersedes hover
+        else if (isPressed(o) && (subPart == SpinButtonUp) == isSpinUpButtonPartPressed(o))
+            result = DFCS_PUSHED;
+        else if (supportsFocus(part) && isFocused(o)) // So does focused
+            result = 0;
+        else if (isHovered(o) && (subPart == SpinButtonUp) == isSpinUpButtonPartHovered(o))
+            result = DFCS_HOT;
+        // Classic theme can't represent indeterminate states. Use unchecked appearance.
+        if (isChecked(o) && !isIndeterminate(o))
+            result |= DFCS_CHECKED;
+    }
+    return result;
+}
+
+ThemeData RenderThemeChromiumWin::getThemeData(RenderObject* o, ControlSubPart subPart)
+{
+    ThemeData result;
+    switch (o->style()->appearance()) {
+    case CheckboxPart:
+        result.m_part = BP_CHECKBOX;
+        result.m_state = determineState(o);
+        result.m_classicState = DFCS_BUTTONCHECK;
+        break;
+    case RadioPart:
+        result.m_part = BP_RADIOBUTTON;
+        result.m_state = determineState(o);
+        result.m_classicState = DFCS_BUTTONRADIO;
+        break;
+    case SquareButtonPart:
+    case PushButtonPart:
+    case ButtonPart:
+        result.m_part = BP_PUSHBUTTON;
+        result.m_state = determineState(o);
+        result.m_classicState = DFCS_BUTTONPUSH;
+        break;
+    case SliderHorizontalPart:
+        result.m_part = TKP_TRACK;
+        result.m_state = TRS_NORMAL;
+        break;
+    case SliderVerticalPart:
+        result.m_part = TKP_TRACKVERT;
+        result.m_state = TRVS_NORMAL;
+        break;
+    case SliderThumbHorizontalPart:
+        result.m_part = TKP_THUMBBOTTOM;
+        result.m_state = determineSliderThumbState(o);
+        break;
+    case SliderThumbVerticalPart:
+        result.m_part = TKP_THUMBVERT;
+        result.m_state = determineSliderThumbState(o);
+        break;
+    case ListboxPart:
+    case MenulistPart:
+    case MenulistButtonPart:
+    case SearchFieldPart:
+    case TextFieldPart:
+    case TextAreaPart:
+        result.m_part = EP_EDITTEXT;
+        result.m_state = determineState(o);
+        break;
+    case InnerSpinButtonPart:
+        result.m_part = subPart == SpinButtonUp ? SPNP_UP : SPNP_DOWN;
+        result.m_state = determineState(o, subPart);
+        result.m_classicState = subPart == SpinButtonUp ? DFCS_SCROLLUP : DFCS_SCROLLDOWN;
+        break;
+    }
+
+    result.m_classicState |= determineClassicState(o, subPart);
+
+    return result;
+}
+
+bool RenderThemeChromiumWin::paintTextFieldInternal(RenderObject* o,
+                                                    const PaintInfo& i,
+                                                    const IntRect& r,
+                                                    bool drawEdges)
+{
+    // Fallback to white if the specified color object is invalid.
+    Color backgroundColor(Color::white);
+    if (o->style()->visitedDependentColor(CSSPropertyBackgroundColor).isValid())
+        backgroundColor = o->style()->visitedDependentColor(CSSPropertyBackgroundColor);
+
+    // If we have background-image, don't fill the content area to expose the
+    // parent's background. Also, we shouldn't fill the content area if the
+    // alpha of the color is 0. The API of Windows GDI ignores the alpha.
+    //
+    // Note that we should paint the content area white if we have neither the
+    // background color nor background image explicitly specified to keep the
+    // appearance of select element consistent with other browsers.
+    bool fillContentArea = !o->style()->hasBackgroundImage() && backgroundColor.alpha();
+
+    if (o->style()->hasBorderRadius()) {
+        // If the style has rounded borders, setup the context to clip the
+        // background (themed or filled) appropriately.
+        // FIXME: make sure we do the right thing if css background-clip is set.
+        i.context->save();
+        i.context->clipRoundedRect(o->style()->getRoundedBorderFor(r));
+    }
+    {
+        const ThemeData& themeData = getThemeData(o);
+        ThemePainter painter(i.context, r);
+        WebKit::WebCanvas* canvas = painter.context()->platformContext()->canvas();
+        WebKit::Platform::current()->themeEngine()->paintTextField(canvas, themeData.m_part, themeData.m_state, themeData.m_classicState, WebKit::WebRect(painter.drawRect()), backgroundColor.rgb(), fillContentArea, drawEdges);
+        // End of block commits the painter before restoring context.
+    }
+    if (o->style()->hasBorderRadius())
+        i.context->restore();
+    return false;
+}
+
+void RenderThemeChromiumWin::adjustInnerSpinButtonStyle(StyleResolver*, RenderStyle* style, Element*) const
+{
+    int width = ScrollbarTheme::theme()->scrollbarThickness();
+    style->setWidth(Length(width, Fixed));
+    style->setMinWidth(Length(width, Fixed));
+}
+
+bool RenderThemeChromiumWin::paintInnerSpinButton(RenderObject* object, const PaintInfo& info, const IntRect& rect)
+{
+    IntRect half = rect;
+
+    // Need explicit blocks to avoid to create multiple ThemePainter instances.
+    {
+        half.setHeight(rect.height() / 2);
+        const ThemeData& upThemeData = getThemeData(object, SpinButtonUp);
+        ThemePainter upPainter(info.context, half);
+        WebKit::WebCanvas* canvas = upPainter.context()->platformContext()->canvas();
+        WebKit::Platform::current()->themeEngine()->paintSpinButton(canvas, upThemeData.m_part, upThemeData.m_state, upThemeData.m_classicState, WebKit::WebRect(upPainter.drawRect()));
+    }
+
+    {
+        half.setY(rect.y() + rect.height() / 2);
+        const ThemeData& downThemeData = getThemeData(object, SpinButtonDown);
+        ThemePainter downPainter(info.context, half);
+        WebKit::WebCanvas* canvas = downPainter.context()->platformContext()->canvas();
+        WebKit::Platform::current()->themeEngine()->paintSpinButton(canvas, downThemeData.m_part, downThemeData.m_state, downThemeData.m_classicState, WebKit::WebRect(downPainter.drawRect()));
+    }
+    return false;
+}
+
+// MSDN says that update intervals for the bar is 30ms.
+// http://msdn.microsoft.com/en-us/library/bb760842(v=VS.85).aspx
+static const double progressAnimationFrameRate = 0.033;
+
+double RenderThemeChromiumWin::animationRepeatIntervalForProgressBar(RenderProgress*) const
+{
+    return progressAnimationFrameRate;
+}
+
+double RenderThemeChromiumWin::animationDurationForProgressBar(RenderProgress* renderProgress) const
+{
+    // On Chromium Windows port, animationProgress() and associated values aren't used.
+    // So here we can return arbitrary positive value.
+    return progressAnimationFrameRate;
+}
+
+void RenderThemeChromiumWin::adjustProgressBarStyle(StyleResolver*, RenderStyle*, Element*) const
+{
+}
+
+bool RenderThemeChromiumWin::paintProgressBar(RenderObject* o, const PaintInfo& i, const IntRect& r)
+{
+    if (!o->isProgress())
+        return true;
+
+    RenderProgress* renderProgress = toRenderProgress(o);
+    // For indeterminate bar, valueRect is ignored and it is computed by the theme engine
+    // because the animation is a platform detail and WebKit doesn't need to know how.
+    IntRect valueRect = renderProgress->isDeterminate() ? determinateProgressValueRectFor(renderProgress, r) : IntRect(0, 0, 0, 0);
+    double animatedSeconds = renderProgress->animationStartTime() ?  WTF::currentTime() - renderProgress->animationStartTime() : 0;
+    ThemePainter painter(i.context, r);
+    DirectionFlippingScope scope(o, i, r);
+    WebKit::WebCanvas* canvas = painter.context()->platformContext()->canvas();
+    WebKit::Platform::current()->themeEngine()->paintProgressBar(canvas, WebKit::WebRect(r), WebKit::WebRect(valueRect), renderProgress->isDeterminate(), animatedSeconds);
+    return false;
+}
+
+bool RenderThemeChromiumWin::shouldOpenPickerWithF4Key() const
+{
+    return true;
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderThemeChromiumWin.h b/Source/core/rendering/RenderThemeChromiumWin.h
new file mode 100644
index 0000000..71fcf52
--- /dev/null
+++ b/Source/core/rendering/RenderThemeChromiumWin.h
@@ -0,0 +1,116 @@
+/*
+ * This file is part of the WebKit project.
+ *
+ * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2008, 2009 Google, 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 RenderThemeChromiumWin_h
+#define RenderThemeChromiumWin_h
+
+#include "core/rendering/RenderThemeChromiumSkia.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) { }
+
+    unsigned m_part;
+    unsigned m_state;
+    unsigned m_classicState;
+};
+
+class RenderThemeChromiumWin : public RenderThemeChromiumSkia {
+public:
+    static PassRefPtr<RenderTheme> create();
+
+    // A method asking if the theme is able to draw the focus ring.
+    virtual bool supportsFocusRing(const RenderStyle*) const OVERRIDE;
+
+    // The platform selection color.
+    virtual Color platformActiveSelectionBackgroundColor() const OVERRIDE;
+    virtual Color platformInactiveSelectionBackgroundColor() const OVERRIDE;
+    virtual Color platformActiveSelectionForegroundColor() const OVERRIDE;
+    virtual Color platformInactiveSelectionForegroundColor() const OVERRIDE;
+    virtual Color platformActiveTextSearchHighlightColor() const OVERRIDE;
+    virtual Color platformInactiveTextSearchHighlightColor() const OVERRIDE;
+
+    virtual Color systemColor(int cssValueId) const OVERRIDE;
+
+#if ENABLE(DATALIST_ELEMENT)
+    virtual IntSize sliderTickSize() const OVERRIDE;
+    virtual int sliderTickOffsetFromTrackCenter() const OVERRIDE;
+#endif
+    virtual void adjustSliderThumbSize(RenderStyle*, Element*) const OVERRIDE;
+
+    // Various paint functions.
+    virtual bool paintCheckbox(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
+    virtual bool paintRadio(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
+    virtual bool paintButton(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
+    virtual bool paintTextField(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
+    virtual bool paintSliderTrack(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
+    virtual bool paintSliderThumb(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
+
+    // MenuList refers to an unstyled menulist (meaning a menulist without
+    // background-color or border set) and MenuListButton refers to a styled
+    // menulist (a menulist with background-color or border set).
+    virtual bool paintMenuList(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
+    virtual bool paintMenuListButton(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
+
+    virtual void adjustInnerSpinButtonStyle(StyleResolver*, RenderStyle*, Element*) const OVERRIDE;
+    virtual bool paintInnerSpinButton(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
+
+    virtual double animationRepeatIntervalForProgressBar(RenderProgress*) const OVERRIDE;
+    virtual double animationDurationForProgressBar(RenderProgress*) const OVERRIDE;
+    virtual void adjustProgressBarStyle(StyleResolver*, RenderStyle*, Element*) const OVERRIDE;
+    virtual bool paintProgressBar(RenderObject*, const PaintInfo&, const IntRect&) OVERRIDE;
+
+    virtual bool shouldOpenPickerWithF4Key() const OVERRIDE;
+
+protected:
+    virtual double caretBlinkIntervalInternal() const OVERRIDE;
+
+private:
+    enum ControlSubPart {
+        None,
+        SpinButtonDown,
+        SpinButtonUp,
+    };
+
+    RenderThemeChromiumWin() { }
+    virtual ~RenderThemeChromiumWin() { }
+
+    unsigned determineState(RenderObject*, ControlSubPart = None);
+    unsigned determineSliderThumbState(RenderObject*);
+    unsigned determineClassicState(RenderObject*, ControlSubPart = None);
+
+    ThemeData getThemeData(RenderObject*, ControlSubPart = None);
+
+    bool paintTextFieldInternal(RenderObject*, const PaintInfo&, const IntRect&, bool);
+};
+
+} // namespace WebCore
+
+#endif
diff --git a/Source/core/rendering/RenderTreeAsText.cpp b/Source/core/rendering/RenderTreeAsText.cpp
new file mode 100644
index 0000000..4ce6561
--- /dev/null
+++ b/Source/core/rendering/RenderTreeAsText.cpp
@@ -0,0 +1,878 @@
+/*
+ * 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 "core/rendering/RenderTreeAsText.h"
+
+#include "HTMLNames.h"
+#include "core/css/StylePropertySet.h"
+#include "core/dom/Document.h"
+#include "core/editing/FrameSelection.h"
+#include "core/html/HTMLElement.h"
+#include "core/page/Frame.h"
+#include "core/page/FrameView.h"
+#include "core/page/PrintContext.h"
+#include "core/rendering/FlowThreadController.h"
+#include "core/rendering/InlineTextBox.h"
+#include "core/rendering/RenderBR.h"
+#include "core/rendering/RenderDetailsMarker.h"
+#include "core/rendering/RenderFileUploadControl.h"
+#include "core/rendering/RenderInline.h"
+#include "core/rendering/RenderLayer.h"
+#include "core/rendering/RenderLayerBacking.h"
+#include "core/rendering/RenderListItem.h"
+#include "core/rendering/RenderListMarker.h"
+#include "core/rendering/RenderNamedFlowThread.h"
+#include "core/rendering/RenderPart.h"
+#include "core/rendering/RenderRegion.h"
+#include "core/rendering/RenderTableCell.h"
+#include "core/rendering/RenderView.h"
+#include "core/rendering/RenderWidget.h"
+#include <wtf/HexNumber.h>
+#include <wtf/unicode/CharacterNames.h>
+#include <wtf/UnusedParam.h>
+#include <wtf/Vector.h>
+
+#if ENABLE(SVG)
+#include "core/rendering/svg/RenderSVGContainer.h"
+#include "core/rendering/svg/RenderSVGGradientStop.h"
+#include "core/rendering/svg/RenderSVGImage.h"
+#include "core/rendering/svg/RenderSVGInlineText.h"
+#include "core/rendering/svg/RenderSVGPath.h"
+#include "core/rendering/svg/RenderSVGRoot.h"
+#include "core/rendering/svg/RenderSVGText.h"
+#include "core/rendering/svg/SVGRenderTreeAsText.h"
+#endif
+
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+static void writeLayers(TextStream&, const RenderLayer* rootLayer, RenderLayer*, const LayoutRect& paintDirtyRect, int indent = 0, RenderAsTextBehavior = RenderAsTextBehaviorNormal);
+
+TextStream& operator<<(TextStream& ts, const IntRect& r)
+{
+    return ts << "at (" << r.x() << "," << r.y() << ") size " << r.width() << "x" << r.height();
+}
+
+TextStream& operator<<(TextStream& ts, const IntPoint& p)
+{
+    return ts << "(" << p.x() << "," << p.y() << ")";
+}
+
+TextStream& operator<<(TextStream& ts, const LayoutPoint& p)
+{
+    // FIXME: These should be printed as floats. Keeping them ints for consistency with pervious test expectations.
+    return ts << "(" << p.x().toInt() << "," << p.y().toInt() << ")";
+}
+
+TextStream& operator<<(TextStream& ts, const FloatPoint& p)
+{
+    ts << "(" << TextStream::FormatNumberRespectingIntegers(p.x());
+    ts << "," << TextStream::FormatNumberRespectingIntegers(p.y());
+    ts << ")";
+    return ts;
+}
+
+TextStream& operator<<(TextStream& ts, const FloatSize& s)
+{
+    ts << "width=" << TextStream::FormatNumberRespectingIntegers(s.width());
+    ts << " height=" << TextStream::FormatNumberRespectingIntegers(s.height());
+    return ts;
+}
+
+void writeIndent(TextStream& ts, int indent)
+{
+    for (int i = 0; i != indent; ++i)
+        ts << "  ";
+}
+
+static void printBorderStyle(TextStream& ts, 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->nodeType() == Node::COMMENT_NODE)
+        return "COMMENT";
+    return n->nodeName();
+}
+
+static bool isEmptyOrUnstyledAppleStyleSpan(const Node* node)
+{
+    if (!node || !node->isHTMLElement() || !node->hasTagName(spanTag))
+        return false;
+
+    const HTMLElement* elem = toHTMLElement(node);
+    if (elem->getAttribute(classAttr) != "Apple-style-span")
+        return false;
+
+    if (!node->hasChildNodes())
+        return true;
+
+    const StylePropertySet* inlineStyleDecl = elem->inlineStyle();
+    return (!inlineStyleDecl || inlineStyleDecl->isEmpty());
+}
+
+String quoteAndEscapeNonPrintables(const String& s)
+{
+    StringBuilder 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 {
+                result.append('\\');
+                result.append('x');
+                result.append('{');
+                appendUnsignedAsHex(c, result); 
+                result.append('}');
+            }
+        }
+    }
+    result.append('"');
+    return result.toString();
+}
+
+void RenderTreeAsText::writeRenderObject(TextStream& ts, const RenderObject& o, RenderAsTextBehavior behavior)
+{
+    ts << o.renderName();
+
+    if (behavior & RenderAsTextShowAddresses)
+        ts << " " << static_cast<const void*>(&o);
+
+    if (o.style() && o.style()->zIndex())
+        ts << " zI: " << o.style()->zIndex();
+
+    if (o.node()) {
+        String tagName = getTagName(o.node());
+        // FIXME: Temporary hack to make tests pass by simulating the old generated content output.
+        if (o.isPseudoElement() || (o.parent() && o.parent()->isPseudoElement()))
+            tagName = emptyAtom;
+        if (!tagName.isEmpty()) {
+            ts << " {" << tagName << "}";
+            // flag empty or unstyled AppleStyleSpan because we never
+            // want to leave them in the DOM
+            if (isEmptyOrUnstyledAppleStyleSpan(o.node()))
+                ts << " *empty or unstyled AppleStyleSpan*";
+        }
+    }
+    
+    RenderBlock* cb = o.containingBlock();
+    bool adjustForTableCells = cb ? cb->isTableCell() : false;
+
+    LayoutRect r;
+    if (o.isText()) {
+        // FIXME: Would be better to dump the bounding box x and y rather than the first run's x and y, but that would involve updating
+        // many test results.
+        const RenderText& text = *toRenderText(&o);
+        IntRect linesBox = text.linesBoundingBox();
+        r = IntRect(text.firstRunX(), text.firstRunY(), linesBox.width(), linesBox.height());
+        if (adjustForTableCells && !text.firstTextBox())
+            adjustForTableCells = false;
+    } else if (o.isRenderInline()) {
+        // FIXME: Would be better not to just dump 0, 0 as the x and y here.
+        const RenderInline& inlineFlow = *toRenderInline(&o);
+        r = IntRect(0, 0, inlineFlow.linesBoundingBox().width(), inlineFlow.linesBoundingBox().height());
+        adjustForTableCells = false;
+    } else if (o.isTableCell()) {
+        // FIXME: Deliberately dump the "inner" box of table cells, since that is what current results reflect.  We'd like
+        // to clean up the results to dump both the outer box and the intrinsic padding so that both bits of information are
+        // captured by the results.
+        const RenderTableCell& cell = *toRenderTableCell(&o);
+        r = LayoutRect(cell.x(), cell.y() + cell.intrinsicPaddingBefore(), cell.width(), cell.height() - cell.intrinsicPaddingBefore() - cell.intrinsicPaddingAfter());
+    } else if (o.isBox())
+        r = toRenderBox(&o)->frameRect();
+
+    // FIXME: Temporary in order to ensure compatibility with existing layout test results.
+    if (adjustForTableCells)
+        r.move(0, -toRenderTableCell(o.containingBlock())->intrinsicPaddingBefore());
+
+    // FIXME: Convert layout test results to report sub-pixel values, in the meantime using enclosingIntRect
+    // for consistency with old results.
+    ts << " " << enclosingIntRect(r);
+
+    if (!(o.isText() && !o.isBR())) {
+        if (o.isFileUploadControl())
+            ts << " " << quoteAndEscapeNonPrintables(toRenderFileUploadControl(&o)->fileTextValue());
+
+        if (o.parent()) {
+            Color color = o.style()->visitedDependentColor(CSSPropertyColor);
+            if (o.parent()->style()->visitedDependentColor(CSSPropertyColor) != color)
+                ts << " [color=" << color.nameForRenderTreeAsText() << "]";
+
+            // Do not dump invalid or transparent backgrounds, since that is the default.
+            Color backgroundColor = o.style()->visitedDependentColor(CSSPropertyBackgroundColor);
+            if (o.parent()->style()->visitedDependentColor(CSSPropertyBackgroundColor) != backgroundColor
+                && backgroundColor.isValid() && backgroundColor.rgb())
+                ts << " [bgcolor=" << backgroundColor.nameForRenderTreeAsText() << "]";
+            
+            Color textFillColor = o.style()->visitedDependentColor(CSSPropertyWebkitTextFillColor);
+            if (o.parent()->style()->visitedDependentColor(CSSPropertyWebkitTextFillColor) != textFillColor
+                && textFillColor.isValid() && textFillColor != color && textFillColor.rgb())
+                ts << " [textFillColor=" << textFillColor.nameForRenderTreeAsText() << "]";
+
+            Color textStrokeColor = o.style()->visitedDependentColor(CSSPropertyWebkitTextStrokeColor);
+            if (o.parent()->style()->visitedDependentColor(CSSPropertyWebkitTextStrokeColor) != textStrokeColor
+                && textStrokeColor.isValid() && textStrokeColor != color && textStrokeColor.rgb())
+                ts << " [textStrokeColor=" << textStrokeColor.nameForRenderTreeAsText() << "]";
+
+            if (o.parent()->style()->textStrokeWidth() != o.style()->textStrokeWidth() && o.style()->textStrokeWidth() > 0)
+                ts << " [textStrokeWidth=" << o.style()->textStrokeWidth() << "]";
+        }
+
+        if (!o.isBoxModelObject())
+            return;
+
+        const RenderBoxModelObject& box = *toRenderBoxModelObject(&o);
+        if (box.borderTop() || box.borderRight() || box.borderBottom() || box.borderLeft()) {
+            ts << " [border:";
+
+            BorderValue prevBorder = o.style()->borderTop();
+            if (!box.borderTop())
+                ts << " none";
+            else {
+                ts << " (" << box.borderTop() << "px ";
+                printBorderStyle(ts, o.style()->borderTopStyle());
+                Color col = o.style()->borderTopColor();
+                if (!col.isValid())
+                    col = o.style()->color();
+                ts << col.nameForRenderTreeAsText() << ")";
+            }
+
+            if (o.style()->borderRight() != prevBorder) {
+                prevBorder = o.style()->borderRight();
+                if (!box.borderRight())
+                    ts << " none";
+                else {
+                    ts << " (" << box.borderRight() << "px ";
+                    printBorderStyle(ts, o.style()->borderRightStyle());
+                    Color col = o.style()->borderRightColor();
+                    if (!col.isValid())
+                        col = o.style()->color();
+                    ts << col.nameForRenderTreeAsText() << ")";
+                }
+            }
+
+            if (o.style()->borderBottom() != prevBorder) {
+                prevBorder = box.style()->borderBottom();
+                if (!box.borderBottom())
+                    ts << " none";
+                else {
+                    ts << " (" << box.borderBottom() << "px ";
+                    printBorderStyle(ts, o.style()->borderBottomStyle());
+                    Color col = o.style()->borderBottomColor();
+                    if (!col.isValid())
+                        col = o.style()->color();
+                    ts << col.nameForRenderTreeAsText() << ")";
+                }
+            }
+
+            if (o.style()->borderLeft() != prevBorder) {
+                prevBorder = o.style()->borderLeft();
+                if (!box.borderLeft())
+                    ts << " none";
+                else {
+                    ts << " (" << box.borderLeft() << "px ";
+                    printBorderStyle(ts, o.style()->borderLeftStyle());
+                    Color col = o.style()->borderLeftColor();
+                    if (!col.isValid())
+                        col = o.style()->color();
+                    ts << col.nameForRenderTreeAsText() << ")";
+                }
+            }
+
+            ts << "]";
+        }
+    }
+
+    if (o.isTableCell()) {
+        const RenderTableCell& c = *toRenderTableCell(&o);
+        ts << " [r=" << c.rowIndex() << " c=" << c.col() << " rs=" << c.rowSpan() << " cs=" << c.colSpan() << "]";
+    }
+
+    if (o.isDetailsMarker()) {
+        ts << ": ";
+        switch (toRenderDetailsMarker(&o)->orientation()) {
+        case RenderDetailsMarker::Left:
+            ts << "left";
+            break;
+        case RenderDetailsMarker::Right:
+            ts << "right";
+            break;
+        case RenderDetailsMarker::Up:
+            ts << "up";
+            break;
+        case RenderDetailsMarker::Down:
+            ts << "down";
+            break;
+        }
+    }
+
+    if (o.isListMarker()) {
+        String text = toRenderListMarker(&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;
+        }
+    }
+    
+    if (behavior & RenderAsTextShowIDAndClass) {
+        if (Node* node = o.node()) {
+            if (node->hasID())
+                ts << " id=\"" + toElement(node)->getIdAttribute() + "\"";
+
+            if (node->hasClass()) {
+                ts << " class=\"";
+                StyledElement* styledElement = static_cast<StyledElement*>(node);
+                for (size_t i = 0; i < styledElement->classNames().size(); ++i) {
+                    if (i > 0)
+                        ts << " ";
+                    ts << styledElement->classNames()[i];
+                }
+                ts << "\"";
+            }
+        }
+    }
+    
+    if (behavior & RenderAsTextShowLayoutState) {
+        bool needsLayout = o.selfNeedsLayout() || o.needsPositionedMovementLayout() || o.posChildNeedsLayout() || o.normalChildNeedsLayout();
+        if (needsLayout)
+            ts << " (needs layout:";
+        
+        bool havePrevious = false;
+        if (o.selfNeedsLayout()) {
+            ts << " self";
+            havePrevious = true;
+        }
+
+        if (o.needsPositionedMovementLayout()) {
+            if (havePrevious)
+                ts << ",";
+            havePrevious = true;
+            ts << " positioned movement";
+        }
+
+        if (o.normalChildNeedsLayout()) {
+            if (havePrevious)
+                ts << ",";
+            havePrevious = true;
+            ts << " child";
+        }
+
+        if (o.posChildNeedsLayout()) {
+            if (havePrevious)
+                ts << ",";
+            ts << " positioned child";
+        }
+
+        if (needsLayout)
+            ts << ")";
+    }
+}
+
+static void writeTextRun(TextStream& ts, const RenderText& o, const InlineTextBox& run)
+{
+    // FIXME: For now use an "enclosingIntRect" model for x, y and logicalWidth, although this makes it harder
+    // to detect any changes caused by the conversion to floating point. :(
+    int x = run.x();
+    int y = run.y();
+    int logicalWidth = ceilf(run.left() + run.logicalWidth()) - x;
+
+    // FIXME: Table cell adjustment is temporary until results can be updated.
+    if (o.containingBlock()->isTableCell())
+        y -= toRenderTableCell(o.containingBlock())->intrinsicPaddingBefore();
+        
+    ts << "text run at (" << x << "," << y << ") width " << logicalWidth;
+    if (!run.isLeftToRightDirection() || run.dirOverride()) {
+        ts << (!run.isLeftToRightDirection() ? " RTL" : " LTR");
+        if (run.dirOverride())
+            ts << " override";
+    }
+    ts << ": "
+        << quoteAndEscapeNonPrintables(String(o.text()).substring(run.start(), run.len()));
+    if (run.hasHyphen())
+        ts << " + hyphen string " << quoteAndEscapeNonPrintables(o.style()->hyphenString());
+    ts << "\n";
+}
+
+void write(TextStream& ts, const RenderObject& o, int indent, RenderAsTextBehavior behavior)
+{
+#if ENABLE(SVG)
+    if (o.isSVGShape()) {
+        write(ts, *toRenderSVGShape(&o), indent);
+        return;
+    }
+    if (o.isSVGGradientStop()) {
+        writeSVGGradientStop(ts, *toRenderSVGGradientStop(&o), indent);
+        return;
+    }
+    if (o.isSVGResourceContainer()) {
+        writeSVGResourceContainer(ts, o, indent);
+        return;
+    }
+    if (o.isSVGContainer()) {
+        writeSVGContainer(ts, o, indent);
+        return;
+    }
+    if (o.isSVGRoot()) {
+        write(ts, *toRenderSVGRoot(&o), indent);
+        return;
+    }
+    if (o.isSVGText()) {
+        writeSVGText(ts, *toRenderSVGText(&o), indent);
+        return;
+    }
+    if (o.isSVGInlineText()) {
+        writeSVGInlineText(ts, *toRenderSVGInlineText(&o), indent);
+        return;
+    }
+    if (o.isSVGImage()) {
+        writeSVGImage(ts, *toRenderSVGImage(&o), indent);
+        return;
+    }
+#endif
+
+    writeIndent(ts, indent);
+
+    RenderTreeAsText::writeRenderObject(ts, o, behavior);
+    ts << "\n";
+
+    if (o.isText() && !o.isBR()) {
+        const RenderText& text = *toRenderText(&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, behavior);
+    }
+
+    if (o.isWidget()) {
+        Widget* widget = toRenderWidget(&o)->widget();
+        if (widget && widget->isFrameView()) {
+            FrameView* view = toFrameView(widget);
+            RenderView* root = view->frame()->contentRenderer();
+            if (root) {
+                view->layout();
+                RenderLayer* l = root->layer();
+                if (l)
+                    writeLayers(ts, l, l, l->rect(), indent + 1, behavior);
+            }
+        }
+    }
+}
+
+enum LayerPaintPhase {
+    LayerPaintPhaseAll = 0,
+    LayerPaintPhaseBackground = -1,
+    LayerPaintPhaseForeground = 1
+};
+
+static void write(TextStream& ts, RenderLayer& l,
+                  const LayoutRect& layerBounds, const LayoutRect& backgroundClipRect, const LayoutRect& clipRect, const LayoutRect& outlineClipRect,
+                  LayerPaintPhase paintPhase = LayerPaintPhaseAll, int indent = 0, RenderAsTextBehavior behavior = RenderAsTextBehaviorNormal)
+{
+    IntRect adjustedLayoutBounds = pixelSnappedIntRect(layerBounds);
+    IntRect adjustedBackgroundClipRect = pixelSnappedIntRect(backgroundClipRect);
+    IntRect adjustedClipRect = pixelSnappedIntRect(clipRect);
+    IntRect adjustedOutlineClipRect = pixelSnappedIntRect(outlineClipRect);
+
+    writeIndent(ts, indent);
+
+    ts << "layer ";
+    
+    if (behavior & RenderAsTextShowAddresses)
+        ts << static_cast<const void*>(&l) << " ";
+      
+    ts << adjustedLayoutBounds;
+
+    if (!adjustedLayoutBounds.isEmpty()) {
+        if (!adjustedBackgroundClipRect.contains(adjustedLayoutBounds))
+            ts << " backgroundClip " << adjustedBackgroundClipRect;
+        if (!adjustedClipRect.contains(adjustedLayoutBounds))
+            ts << " clip " << adjustedClipRect;
+        if (!adjustedOutlineClipRect.contains(adjustedLayoutBounds))
+            ts << " outlineClip " << adjustedOutlineClipRect;
+    }
+
+    if (l.renderer()->hasOverflowClip()) {
+        if (l.scrollXOffset())
+            ts << " scrollX " << l.scrollXOffset();
+        if (l.scrollYOffset())
+            ts << " scrollY " << l.scrollYOffset();
+        if (l.renderBox() && l.renderBox()->pixelSnappedClientWidth() != l.scrollWidth())
+            ts << " scrollWidth " << l.scrollWidth();
+        if (l.renderBox() && l.renderBox()->pixelSnappedClientHeight() != l.scrollHeight())
+            ts << " scrollHeight " << l.scrollHeight();
+    }
+
+    if (paintPhase == LayerPaintPhaseBackground)
+        ts << " layerType: background only";
+    else if (paintPhase == LayerPaintPhaseForeground)
+        ts << " layerType: foreground only";
+    
+    if (behavior & RenderAsTextShowCompositedLayers) {
+        if (l.isComposited())
+            ts << " (composited, bounds=" << l.backing()->compositedBounds() << ", drawsContent=" << l.backing()->graphicsLayer()->drawsContent() << ", paints into ancestor=" << l.backing()->paintsIntoCompositedAncestor() << ")";
+    }
+
+    ts << "\n";
+
+    if (paintPhase != LayerPaintPhaseBackground)
+        write(ts, *l.renderer(), indent + 1, behavior);
+}
+
+static void writeRenderRegionList(const RenderRegionList& flowThreadRegionList, TextStream& ts, int indent)
+{
+    for (RenderRegionList::const_iterator itRR = flowThreadRegionList.begin(); itRR != flowThreadRegionList.end(); ++itRR) {
+        RenderRegion* renderRegion = *itRR;
+        writeIndent(ts, indent + 2);
+        ts << "RenderRegion";
+        if (renderRegion->generatingNode()) {
+            String tagName = getTagName(renderRegion->generatingNode());
+            if (!tagName.isEmpty())
+                ts << " {" << tagName << "}";
+            if (renderRegion->generatingNode()->isElementNode() && renderRegion->generatingNode()->hasID()) {
+                Element* element = toElement(renderRegion->generatingNode());
+                ts << " #" << element->idForStyleResolution();
+            }
+            if (renderRegion->hasCustomRegionStyle())
+                ts << " region style: 1";
+            if (renderRegion->hasAutoLogicalHeight())
+                ts << " hasAutoLogicalHeight";
+        }
+        if (!renderRegion->isValid())
+            ts << " invalid";
+        ts << "\n";
+    }
+}
+
+static void writeRenderNamedFlowThreads(TextStream& ts, RenderView* renderView, const RenderLayer* rootLayer,
+                        const LayoutRect& paintRect, int indent, RenderAsTextBehavior behavior)
+{
+    if (!renderView->hasRenderNamedFlowThreads())
+        return;
+
+    const RenderNamedFlowThreadList* list = renderView->flowThreadController()->renderNamedFlowThreadList();
+
+    writeIndent(ts, indent);
+    ts << "Flow Threads\n";
+
+    for (RenderNamedFlowThreadList::const_iterator iter = list->begin(); iter != list->end(); ++iter) {
+        const RenderNamedFlowThread* renderFlowThread = *iter;
+
+        writeIndent(ts, indent + 1);
+        ts << "Thread with flow-name '" << renderFlowThread->flowThreadName() << "'\n";
+
+        RenderLayer* layer = renderFlowThread->layer();
+        writeLayers(ts, rootLayer, layer, paintRect, indent + 2, behavior);
+
+        // Display the valid and invalid render regions attached to this flow thread.
+        const RenderRegionList& validRegionsList = renderFlowThread->renderRegionList();
+        const RenderRegionList& invalidRegionsList = renderFlowThread->invalidRenderRegionList();
+        if (!validRegionsList.isEmpty() || !invalidRegionsList.isEmpty()) {
+            writeIndent(ts, indent + 1);
+            ts << "Regions for flow '"<< renderFlowThread->flowThreadName() << "'\n";
+            writeRenderRegionList(validRegionsList, ts, indent);
+            writeRenderRegionList(invalidRegionsList, ts, indent);
+        }
+    }
+}
+
+static void writeLayers(TextStream& ts, const RenderLayer* rootLayer, RenderLayer* l,
+                        const LayoutRect& paintRect, int indent, RenderAsTextBehavior behavior)
+{
+    // FIXME: Apply overflow to the root layer to not break every test.  Complete hack.  Sigh.
+    LayoutRect paintDirtyRect(paintRect);
+    if (rootLayer == l) {
+        paintDirtyRect.setWidth(max<LayoutUnit>(paintDirtyRect.width(), rootLayer->renderBox()->layoutOverflowRect().maxX()));
+        paintDirtyRect.setHeight(max<LayoutUnit>(paintDirtyRect.height(), rootLayer->renderBox()->layoutOverflowRect().maxY()));
+        l->setSize(l->size().expandedTo(pixelSnappedIntSize(l->renderBox()->maxLayoutOverflow(), LayoutPoint(0, 0))));
+    }
+    
+    // Calculate the clip rects we should use.
+    LayoutRect layerBounds;
+    ClipRect damageRect, clipRectToApply, outlineRect;
+    l->calculateRects(RenderLayer::ClipRectsContext(rootLayer, 0, TemporaryClipRects), paintDirtyRect, layerBounds, damageRect, clipRectToApply, outlineRect);
+
+    // Ensure our lists are up-to-date.
+    l->updateLayerListsIfNeeded();
+
+    bool shouldPaint = (behavior & RenderAsTextShowAllLayers) ? true : l->intersectsDamageRect(layerBounds, damageRect.rect(), rootLayer);
+    Vector<RenderLayer*>* negList = l->negZOrderList();
+    bool paintsBackgroundSeparately = negList && negList->size() > 0;
+    if (shouldPaint && paintsBackgroundSeparately)
+        write(ts, *l, layerBounds, damageRect.rect(), clipRectToApply.rect(), outlineRect.rect(), LayerPaintPhaseBackground, indent, behavior);
+
+    if (negList) {
+        int currIndent = indent;
+        if (behavior & RenderAsTextShowLayerNesting) {
+            writeIndent(ts, indent);
+            ts << " negative z-order list(" << negList->size() << ")\n";
+            ++currIndent;
+        }
+        for (unsigned i = 0; i != negList->size(); ++i)
+            writeLayers(ts, rootLayer, negList->at(i), paintDirtyRect, currIndent, behavior);
+    }
+
+    if (shouldPaint)
+        write(ts, *l, layerBounds, damageRect.rect(), clipRectToApply.rect(), outlineRect.rect(), paintsBackgroundSeparately ? LayerPaintPhaseForeground : LayerPaintPhaseAll, indent, behavior);
+
+    if (Vector<RenderLayer*>* normalFlowList = l->normalFlowList()) {
+        int currIndent = indent;
+        if (behavior & RenderAsTextShowLayerNesting) {
+            writeIndent(ts, indent);
+            ts << " normal flow list(" << normalFlowList->size() << ")\n";
+            ++currIndent;
+        }
+        for (unsigned i = 0; i != normalFlowList->size(); ++i)
+            writeLayers(ts, rootLayer, normalFlowList->at(i), paintDirtyRect, currIndent, behavior);
+    }
+
+    if (Vector<RenderLayer*>* posList = l->posZOrderList()) {
+        int currIndent = indent;
+        if (behavior & RenderAsTextShowLayerNesting) {
+            writeIndent(ts, indent);
+            ts << " positive z-order list(" << posList->size() << ")\n";
+            ++currIndent;
+        }
+        for (unsigned i = 0; i != posList->size(); ++i)
+            writeLayers(ts, rootLayer, posList->at(i), paintDirtyRect, currIndent, behavior);
+    }
+    
+    // Altough the RenderFlowThread requires a layer, it is not collected by its parent,
+    // so we have to treat it as a special case.
+    if (l->renderer()->isRenderView()) {
+        RenderView* renderView = toRenderView(l->renderer());
+        writeRenderNamedFlowThreads(ts, renderView, rootLayer, paintDirtyRect, indent, behavior);
+    }
+}
+
+static String nodePosition(Node* node)
+{
+    StringBuilder result;
+
+    Element* body = node->document()->body();
+    Node* parent;
+    for (Node* n = node; n; n = parent) {
+        parent = n->parentOrShadowHostNode();
+        if (n != node)
+            result.appendLiteral(" of ");
+        if (parent) {
+            if (body && n == body) {
+                // We don't care what offset body may be in the document.
+                result.appendLiteral("body");
+                break;
+            }
+            if (n->isShadowRoot()) {
+                result.append('{');
+                result.append(getTagName(n));
+                result.append('}');
+            } else {
+                result.appendLiteral("child ");
+                result.appendNumber(n->nodeIndex());
+                result.appendLiteral(" {");
+                result.append(getTagName(n));
+                result.append('}');
+            }
+        } else
+            result.appendLiteral("document");
+    }
+
+    return result.toString();
+}
+
+static void writeSelection(TextStream& ts, const RenderObject* o)
+{
+    Node* n = o->node();
+    if (!n || !n->isDocumentNode())
+        return;
+
+    Document* doc = toDocument(n);
+    Frame* frame = doc->frame();
+    if (!frame)
+        return;
+
+    VisibleSelection selection = frame->selection()->selection();
+    if (selection.isCaret()) {
+        ts << "caret: position " << selection.start().deprecatedEditingOffset() << " of " << nodePosition(selection.start().deprecatedNode());
+        if (selection.affinity() == UPSTREAM)
+            ts << " (upstream affinity)";
+        ts << "\n";
+    } else if (selection.isRange())
+        ts << "selection start: position " << selection.start().deprecatedEditingOffset() << " of " << nodePosition(selection.start().deprecatedNode()) << "\n"
+           << "selection end:   position " << selection.end().deprecatedEditingOffset() << " of " << nodePosition(selection.end().deprecatedNode()) << "\n";
+}
+
+static String externalRepresentation(RenderBox* renderer, RenderAsTextBehavior behavior)
+{
+    TextStream ts;
+    if (!renderer->hasLayer())
+        return ts.release();
+        
+    RenderLayer* layer = renderer->layer();
+    writeLayers(ts, layer, layer, layer->rect(), 0, behavior);
+    writeSelection(ts, renderer);
+    return ts.release();
+}
+
+String externalRepresentation(Frame* frame, RenderAsTextBehavior behavior)
+{
+    RenderObject* renderer = frame->contentRenderer();
+    if (!renderer || !renderer->isBox())
+        return String();
+
+    PrintContext printContext(frame);
+    if (behavior & RenderAsTextPrintingMode)
+        printContext.begin(toRenderBox(renderer)->width());
+    if (!(behavior & RenderAsTextDontUpdateLayout))
+        frame->document()->updateLayout();
+
+    return externalRepresentation(toRenderBox(renderer), behavior);
+}
+
+String externalRepresentation(Element* element, RenderAsTextBehavior behavior)
+{
+    RenderObject* renderer = element->renderer();
+    if (!renderer || !renderer->isBox())
+        return String();
+    // Doesn't support printing mode.
+    ASSERT(!(behavior & RenderAsTextPrintingMode));
+    if (!(behavior & RenderAsTextDontUpdateLayout) && element->document())
+        element->document()->updateLayout();
+    
+    return externalRepresentation(toRenderBox(renderer), behavior | RenderAsTextShowAllLayers);
+}
+
+static void writeCounterValuesFromChildren(TextStream& stream, RenderObject* parent, bool& isFirstCounter)
+{
+    for (RenderObject* child = parent->firstChild(); child; child = child->nextSibling()) {
+        if (child->isCounter()) {
+            if (!isFirstCounter)
+                stream << " ";
+            isFirstCounter = false;
+            String str(toRenderText(child)->text());
+            stream << str;
+        }
+    }
+}
+
+String counterValueForElement(Element* element)
+{
+    // Make sure the element is not freed during the layout.
+    RefPtr<Element> elementRef(element);
+    element->document()->updateLayout();
+    TextStream stream;
+    bool isFirstCounter = true;
+    // The counter renderers should be children of :before or :after pseudo-elements.
+    if (RenderObject* before = element->pseudoElementRenderer(BEFORE))
+        writeCounterValuesFromChildren(stream, before, isFirstCounter);
+    if (RenderObject* after = element->pseudoElementRenderer(AFTER))
+        writeCounterValuesFromChildren(stream, after, isFirstCounter);
+    return stream.release();
+}
+
+String markerTextForListItem(Element* element)
+{
+    // Make sure the element is not freed during the layout.
+    RefPtr<Element> elementRef(element);
+    element->document()->updateLayout();
+
+    RenderObject* renderer = element->renderer();
+    if (!renderer || !renderer->isListItem())
+        return String();
+
+    return toRenderListItem(renderer)->markerText();
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderTreeAsText.h b/Source/core/rendering/RenderTreeAsText.h
new file mode 100644
index 0000000..8a24ccd
--- /dev/null
+++ b/Source/core/rendering/RenderTreeAsText.h
@@ -0,0 +1,102 @@
+/*
+ * 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
+#include "core/platform/text/TextStream.h"
+
+#include <wtf/Forward.h>
+
+namespace WebCore {
+
+class Element;
+class FloatPoint;
+class FloatSize;
+class Frame;
+class IntPoint;
+class IntRect;
+class LayoutPoint;
+class RenderObject;
+class TextStream;
+
+enum RenderAsTextBehaviorFlags {
+    RenderAsTextBehaviorNormal = 0,
+    RenderAsTextShowAllLayers = 1 << 0, // Dump all layers, not just those that would paint.
+    RenderAsTextShowLayerNesting = 1 << 1, // Annotate the layer lists.
+    RenderAsTextShowCompositedLayers = 1 << 2, // Show which layers are composited.
+    RenderAsTextShowAddresses = 1 << 3, // Show layer and renderer addresses.
+    RenderAsTextShowIDAndClass = 1 << 4, // Show id and class attributes
+    RenderAsTextPrintingMode = 1 << 5, // Dump the tree in printing mode.
+    RenderAsTextDontUpdateLayout = 1 << 6, // Don't update layout, to make it safe to call showLayerTree() from the debugger inside layout or painting code.
+    RenderAsTextShowLayoutState = 1 << 7 // Print the various 'needs layout' bits on renderers.
+};
+typedef unsigned RenderAsTextBehavior;
+
+// You don't need pageWidthInPixels if you don't specify RenderAsTextInPrintingMode.
+String externalRepresentation(Frame*, RenderAsTextBehavior = RenderAsTextBehaviorNormal);
+String externalRepresentation(Element*, RenderAsTextBehavior = RenderAsTextBehaviorNormal);
+void write(TextStream&, const RenderObject&, int indent = 0, RenderAsTextBehavior = RenderAsTextBehaviorNormal);
+void writeIndent(TextStream&, int indent);
+
+class RenderTreeAsText {
+// FIXME: This is a cheesy hack to allow easy access to RenderStyle colors.  It won't be needed if we convert
+// it to use visitedDependentColor instead. (This just involves rebaselining many results though, so for now it's
+// not being done).
+public:
+static void writeRenderObject(TextStream& ts, const RenderObject& o, RenderAsTextBehavior behavior);
+};
+
+TextStream& operator<<(TextStream&, const IntPoint&);
+TextStream& operator<<(TextStream&, const IntRect&);
+TextStream& operator<<(TextStream&, const LayoutPoint&);
+TextStream& operator<<(TextStream&, const FloatPoint&);
+TextStream& operator<<(TextStream&, const FloatSize&);
+
+template<typename Item>
+TextStream& operator<<(TextStream& ts, const Vector<Item>& vector)
+{
+    ts << "[";
+
+    unsigned size = vector.size();
+    for (unsigned i = 0; i < size; ++i) {
+        ts << vector[i];
+        if (i < size - 1)
+            ts << ", ";
+    }
+
+    ts << "]";
+    return ts;
+}
+
+// Helper function shared with SVGRenderTreeAsText
+String quoteAndEscapeNonPrintables(const String&);
+
+String counterValueForElement(Element*);
+
+String markerTextForListItem(Element*);
+
+} // namespace WebCore
+
+#endif // RenderTreeAsText_h
diff --git a/Source/core/rendering/RenderVideo.cpp b/Source/core/rendering/RenderVideo.cpp
new file mode 100644
index 0000000..89e38b4
--- /dev/null
+++ b/Source/core/rendering/RenderVideo.cpp
@@ -0,0 +1,331 @@
+/*
+ * Copyright (C) 2007, 2008, 2009, 2010 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 "core/rendering/RenderVideo.h"
+
+#include "HTMLNames.h"
+#include "core/dom/Document.h"
+#include "core/html/HTMLVideoElement.h"
+#include "core/page/Frame.h"
+#include "core/page/FrameView.h"
+#include "core/page/Page.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/platform/graphics/MediaPlayer.h"
+#include "core/rendering/PaintInfo.h"
+#include "core/rendering/RenderFullScreen.h"
+#include "core/rendering/RenderView.h"
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+RenderVideo::RenderVideo(HTMLVideoElement* video)
+    : RenderMedia(video)
+{
+    setIntrinsicSize(calculateIntrinsicSize());
+}
+
+RenderVideo::~RenderVideo()
+{
+    if (MediaPlayer* p = mediaElement()->player()) {
+        p->setVisible(false);
+        p->setFrameView(0);
+    }
+}
+
+IntSize RenderVideo::defaultSize()
+{
+    // These values are specified in the spec.
+    static const int cDefaultWidth = 300;
+    static const int cDefaultHeight = 150;
+
+    return IntSize(cDefaultWidth, cDefaultHeight);
+}
+
+void RenderVideo::intrinsicSizeChanged()
+{
+    if (videoElement()->shouldDisplayPosterImage())
+        RenderMedia::intrinsicSizeChanged();
+    updateIntrinsicSize(); 
+}
+
+void RenderVideo::updateIntrinsicSize()
+{
+    LayoutSize size = calculateIntrinsicSize();
+    size.scale(style()->effectiveZoom());
+
+    // Never set the element size to zero when in a media document.
+    if (size.isEmpty() && node()->ownerDocument() && node()->ownerDocument()->isMediaDocument())
+        return;
+
+    if (size == intrinsicSize())
+        return;
+
+    setIntrinsicSize(size);
+    setPreferredLogicalWidthsDirty(true);
+    setNeedsLayout(true);
+}
+    
+LayoutSize RenderVideo::calculateIntrinsicSize()
+{
+    HTMLVideoElement* video = videoElement();
+    
+    // Spec text from 4.8.6
+    //
+    // The intrinsic width of a video element's playback area is the intrinsic width 
+    // of the video resource, if that is available; otherwise it is the intrinsic 
+    // width of the poster frame, if that is available; otherwise it is 300 CSS pixels.
+    //
+    // The intrinsic height of a video element's playback area is the intrinsic height 
+    // of the video resource, if that is available; otherwise it is the intrinsic 
+    // height of the poster frame, if that is available; otherwise it is 150 CSS pixels.
+    MediaPlayer* player = mediaElement()->player();
+    if (player && video->readyState() >= HTMLVideoElement::HAVE_METADATA) {
+        LayoutSize size = player->naturalSize();
+        if (!size.isEmpty())
+            return size;
+    }
+
+    if (video->shouldDisplayPosterImage() && !m_cachedImageSize.isEmpty() && !imageResource()->errorOccurred())
+        return m_cachedImageSize;
+
+    // When the natural size of the video is unavailable, we use the provided
+    // width and height attributes of the video element as the intrinsic size until
+    // better values become available. 
+    if (video->hasAttribute(widthAttr) && video->hasAttribute(heightAttr))
+        return LayoutSize(video->width(), video->height());
+
+    // <video> in standalone media documents should not use the default 300x150
+    // size since they also have audio-only files. By setting the intrinsic
+    // size to 300x1 the video will resize itself in these cases, and audio will
+    // have the correct height (it needs to be > 0 for controls to render properly).
+    if (video->ownerDocument() && video->ownerDocument()->isMediaDocument())
+        return LayoutSize(defaultSize().width(), 1);
+
+    return defaultSize();
+}
+
+void RenderVideo::imageChanged(WrappedImagePtr newImage, const IntRect* rect)
+{
+    RenderMedia::imageChanged(newImage, rect);
+
+    // Cache the image intrinsic size so we can continue to use it to draw the image correctly
+    // even if we know the video intrinsic size but aren't able to draw video frames yet
+    // (we don't want to scale the poster to the video size without keeping aspect ratio).
+    if (videoElement()->shouldDisplayPosterImage())
+        m_cachedImageSize = intrinsicSize();
+
+    // The intrinsic size is now that of the image, but in case we already had the
+    // intrinsic size of the video we call this here to restore the video size.
+    updateIntrinsicSize();
+}
+
+IntRect RenderVideo::videoBox() const
+{
+    if (m_cachedImageSize.isEmpty() && videoElement()->shouldDisplayPosterImage())
+        return IntRect();
+
+    LayoutSize elementSize;
+    if (videoElement()->shouldDisplayPosterImage())
+        elementSize = m_cachedImageSize;
+    else
+        elementSize = intrinsicSize();
+
+    IntRect contentRect = pixelSnappedIntRect(contentBoxRect());
+    if (elementSize.isEmpty() || contentRect.isEmpty())
+        return IntRect();
+
+    LayoutRect renderBox = contentRect;
+    LayoutUnit ratio = renderBox.width() * elementSize.height() - renderBox.height() * elementSize.width();
+    if (ratio > 0) {
+        LayoutUnit newWidth = renderBox.height() * elementSize.width() / elementSize.height();
+        // Just fill the whole area if the difference is one pixel or less (in both sides)
+        if (renderBox.width() - newWidth > 2)
+            renderBox.setWidth(newWidth);
+        renderBox.move((contentRect.width() - renderBox.width()) / 2, 0);
+    } else if (ratio < 0) {
+        LayoutUnit newHeight = renderBox.width() * elementSize.height() / elementSize.width();
+        if (renderBox.height() - newHeight > 2)
+            renderBox.setHeight(newHeight);
+        renderBox.move(0, (contentRect.height() - renderBox.height()) / 2);
+    }
+
+    return pixelSnappedIntRect(renderBox);
+}
+
+bool RenderVideo::shouldDisplayVideo() const
+{
+    return !videoElement()->shouldDisplayPosterImage();
+}
+
+void RenderVideo::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    MediaPlayer* mediaPlayer = mediaElement()->player();
+    bool displayingPoster = videoElement()->shouldDisplayPosterImage();
+
+    Page* page = 0;
+    if (Frame* frame = this->frame())
+        page = frame->page();
+
+    if (!displayingPoster && !mediaPlayer) {
+        if (page && paintInfo.phase == PaintPhaseForeground)
+            page->addRelevantUnpaintedObject(this, visualOverflowRect());
+        return;
+    }
+
+    LayoutRect rect = videoBox();
+    if (rect.isEmpty()) {
+        if (page && paintInfo.phase == PaintPhaseForeground)
+            page->addRelevantUnpaintedObject(this, visualOverflowRect());
+        return;
+    }
+    rect.moveBy(paintOffset);
+
+    if (page && paintInfo.phase == PaintPhaseForeground)
+        page->addRelevantRepaintedObject(this, rect);
+
+    if (displayingPoster)
+        paintIntoRect(paintInfo.context, rect);
+    else if (document()->view() && document()->view()->paintBehavior() & PaintBehaviorFlattenCompositingLayers)
+        mediaPlayer->paintCurrentFrameInContext(paintInfo.context, pixelSnappedIntRect(rect));
+    else
+        mediaPlayer->paint(paintInfo.context, pixelSnappedIntRect(rect));
+}
+
+void RenderVideo::layout()
+{
+    StackStats::LayoutCheckPoint layoutCheckPoint;
+    RenderMedia::layout();
+    updatePlayer();
+}
+    
+HTMLVideoElement* RenderVideo::videoElement() const
+{
+    ASSERT(node()->hasTagName(videoTag));
+    return static_cast<HTMLVideoElement*>(node()); 
+}
+
+void RenderVideo::updateFromElement()
+{
+    RenderMedia::updateFromElement();
+    updatePlayer();
+}
+
+void RenderVideo::updatePlayer()
+{
+    updateIntrinsicSize();
+
+    MediaPlayer* mediaPlayer = mediaElement()->player();
+    if (!mediaPlayer)
+        return;
+
+    if (!videoElement()->inActiveDocument()) {
+        mediaPlayer->setVisible(false);
+        return;
+    }
+
+    contentChanged(VideoChanged);
+    
+    IntRect videoBounds = videoBox(); 
+    mediaPlayer->setFrameView(document()->view());
+    mediaPlayer->setSize(IntSize(videoBounds.width(), videoBounds.height()));
+    mediaPlayer->setVisible(true);
+}
+
+LayoutUnit RenderVideo::computeReplacedLogicalWidth(ShouldComputePreferred shouldComputePreferred) const
+{
+    return RenderReplaced::computeReplacedLogicalWidth(shouldComputePreferred);
+}
+
+LayoutUnit RenderVideo::computeReplacedLogicalHeight() const
+{
+    return RenderReplaced::computeReplacedLogicalHeight();
+}
+
+LayoutUnit RenderVideo::minimumReplacedHeight() const 
+{
+    return RenderReplaced::minimumReplacedHeight(); 
+}
+
+bool RenderVideo::supportsAcceleratedRendering() const
+{
+    MediaPlayer* p = mediaElement()->player();
+    if (p)
+        return p->supportsAcceleratedRendering();
+
+    return false;
+}
+
+void RenderVideo::acceleratedRenderingStateChanged()
+{
+    MediaPlayer* p = mediaElement()->player();
+    if (p)
+        p->acceleratedRenderingStateChanged();
+}
+
+static const RenderBlock* rendererPlaceholder(const RenderObject* renderer)
+{
+    RenderObject* parent = renderer->parent();
+    if (!parent)
+        return 0;
+    
+    RenderFullScreen* fullScreen = parent->isRenderFullScreen() ? toRenderFullScreen(parent) : 0;
+    if (!fullScreen)
+        return 0;
+    
+    return fullScreen->placeholder();
+}
+
+LayoutUnit RenderVideo::offsetLeft() const
+{
+    if (const RenderBlock* block = rendererPlaceholder(this))
+        return block->offsetLeft();
+    return RenderMedia::offsetLeft();
+}
+
+LayoutUnit RenderVideo::offsetTop() const
+{
+    if (const RenderBlock* block = rendererPlaceholder(this))
+        return block->offsetTop();
+    return RenderMedia::offsetTop();
+}
+
+LayoutUnit RenderVideo::offsetWidth() const
+{
+    if (const RenderBlock* block = rendererPlaceholder(this))
+        return block->offsetWidth();
+    return RenderMedia::offsetWidth();
+}
+
+LayoutUnit RenderVideo::offsetHeight() const
+{
+    if (const RenderBlock* block = rendererPlaceholder(this))
+        return block->offsetHeight();
+    return RenderMedia::offsetHeight();
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderVideo.h b/Source/core/rendering/RenderVideo.h
new file mode 100644
index 0000000..17e2d91
--- /dev/null
+++ b/Source/core/rendering/RenderVideo.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2007, 2009, 2010 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
+
+#include "core/rendering/RenderMedia.h"
+
+namespace WebCore {
+    
+class HTMLMediaElement;
+class HTMLVideoElement;
+
+class RenderVideo FINAL : public RenderMedia {
+public:
+    RenderVideo(HTMLVideoElement*);
+    virtual ~RenderVideo();
+
+    IntRect videoBox() const;
+
+    static IntSize defaultSize();
+
+    bool supportsAcceleratedRendering() const;
+    void acceleratedRenderingStateChanged();
+
+    virtual bool shouldDisplayVideo() const;
+
+private:
+    virtual void updateFromElement();
+    inline HTMLVideoElement* videoElement() const;
+
+    virtual void intrinsicSizeChanged();
+    LayoutSize calculateIntrinsicSize();
+    void updateIntrinsicSize();
+
+    virtual void imageChanged(WrappedImagePtr, const IntRect*);
+
+    virtual const char* renderName() const { return "RenderVideo"; }
+
+    virtual bool requiresLayer() const { return true; }
+    virtual bool isVideo() const { return true; }
+
+    virtual void paintReplaced(PaintInfo&, const LayoutPoint&);
+
+    virtual void layout();
+
+    virtual LayoutUnit computeReplacedLogicalWidth(ShouldComputePreferred  = ComputeActual) const OVERRIDE;
+    virtual LayoutUnit computeReplacedLogicalHeight() const;
+    virtual LayoutUnit minimumReplacedHeight() const OVERRIDE;
+
+    virtual LayoutUnit offsetLeft() const;
+    virtual LayoutUnit offsetTop() const;
+    virtual LayoutUnit offsetWidth() const;
+    virtual LayoutUnit offsetHeight() const;
+
+    void updatePlayer();
+
+    LayoutSize m_cachedImageSize;
+};
+
+inline RenderVideo* toRenderVideo(RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isVideo());
+    return static_cast<RenderVideo*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderVideo(const RenderVideo*);
+
+} // namespace WebCore
+
+#endif // RenderVideo_h
diff --git a/Source/core/rendering/RenderView.cpp b/Source/core/rendering/RenderView.cpp
new file mode 100644
index 0000000..5cb83ee
--- /dev/null
+++ b/Source/core/rendering/RenderView.cpp
@@ -0,0 +1,1164 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 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 "core/rendering/RenderView.h"
+
+#include "core/dom/Document.h"
+#include "core/dom/Element.h"
+#include "core/dom/WebCoreMemoryInstrumentation.h"
+#include "core/html/HTMLFrameOwnerElement.h"
+#include "core/html/HTMLIFrameElement.h"
+#include "core/page/Frame.h"
+#include "core/page/FrameView.h"
+#include "core/page/Page.h"
+#include "core/platform/graphics/filters/custom/CustomFilterGlobalContext.h"
+#include "core/platform/graphics/FloatQuad.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/platform/graphics/transforms/TransformState.h"
+#include "core/rendering/ColumnInfo.h"
+#include "core/rendering/FlowThreadController.h"
+#include "core/rendering/HitTestResult.h"
+#include "core/rendering/RenderGeometryMap.h"
+#include "core/rendering/RenderLayer.h"
+#include "core/rendering/RenderLayerBacking.h"
+#include "core/rendering/RenderLayerCompositor.h"
+#include "core/rendering/RenderLazyBlock.h"
+#include "core/rendering/RenderNamedFlowThread.h"
+#include "core/rendering/RenderSelectionInfo.h"
+#include "core/rendering/RenderWidget.h"
+#include "core/rendering/RenderWidgetProtector.h"
+#include "core/rendering/style/StyleInheritedData.h"
+
+namespace WebCore {
+
+RenderView::RenderView(Document* document)
+    : RenderBlock(document)
+    , m_frameView(document->view())
+    , m_selectionStart(0)
+    , m_selectionEnd(0)
+    , m_selectionStartPos(-1)
+    , m_selectionEndPos(-1)
+    , m_maximalOutlineSize(0)
+    , m_pageLogicalHeight(0)
+    , m_pageLogicalHeightChanged(false)
+    , m_layoutState(0)
+    , m_layoutStateDisableCount(0)
+    , m_firstLazyBlock(0)
+    , m_renderQuoteHead(0)
+    , m_renderCounterCount(0)
+{
+    // init RenderObject attributes
+    setInline(false);
+    
+    m_minPreferredLogicalWidth = 0;
+    m_maxPreferredLogicalWidth = 0;
+
+    setPreferredLogicalWidthsDirty(true, MarkOnlyThis);
+    
+    setPositionState(AbsolutePosition); // to 0,0 :)
+}
+
+RenderView::~RenderView()
+{
+}
+
+bool RenderView::hitTest(const HitTestRequest& request, HitTestResult& result)
+{
+    return hitTest(request, result.hitTestLocation(), result);
+}
+
+bool RenderView::hitTest(const HitTestRequest& request, const HitTestLocation& location, HitTestResult& result)
+{
+    return layer()->hitTest(request, location, result);
+}
+
+void RenderView::computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit, LogicalExtentComputedValues& computedValues) const
+{
+    computedValues.m_extent = (!shouldUsePrintingLayout() && m_frameView) ? LayoutUnit(viewLogicalHeight()) : logicalHeight;
+}
+
+void RenderView::updateLogicalWidth()
+{
+    if (!shouldUsePrintingLayout() && m_frameView)
+        setLogicalWidth(viewLogicalWidth());
+}
+
+LayoutUnit RenderView::availableLogicalHeight(AvailableLogicalHeightType heightType) const
+{
+    // If we have columns, then the available logical height is reduced to the column height.
+    if (hasColumns())
+        return columnInfo()->columnHeight();
+    return RenderBlock::availableLogicalHeight(heightType);
+}
+
+bool RenderView::isChildAllowed(RenderObject* child, RenderStyle*) const
+{
+    return child->isBox();
+}
+
+void RenderView::markLazyBlocksForLayout()
+{
+    for (RenderLazyBlock* block = m_firstLazyBlock; block; block = block->next())
+        block->setNeedsLayout(true);
+}
+
+void RenderView::layoutContent(const LayoutState& state)
+{
+    UNUSED_PARAM(state);
+    ASSERT(needsLayout());
+
+    RenderBlock::layout();
+    if (hasRenderNamedFlowThreads())
+        flowThreadController()->layoutRenderNamedFlowThreads();
+#ifndef NDEBUG
+    checkLayoutState(state);
+#endif
+}
+
+#ifndef NDEBUG
+void RenderView::checkLayoutState(const LayoutState& state)
+{
+    ASSERT(layoutDeltaMatches(LayoutSize()));
+    ASSERT(!m_layoutStateDisableCount);
+    ASSERT(m_layoutState == &state);
+}
+#endif
+
+static RenderBox* enclosingSeamlessRenderer(Document* doc)
+{
+    if (!doc)
+        return 0;
+    Element* ownerElement = doc->seamlessParentIFrame();
+    if (!ownerElement)
+        return 0;
+    return ownerElement->renderBox();
+}
+
+void RenderView::addChild(RenderObject* newChild, RenderObject* beforeChild)
+{
+    // Seamless iframes are considered part of an enclosing render flow thread from the parent document. This is necessary for them to look
+    // up regions in the parent document during layout.
+    if (newChild && !newChild->isRenderFlowThread()) {
+        RenderBox* seamlessBox = enclosingSeamlessRenderer(document());
+        if (seamlessBox && seamlessBox->flowThreadContainingBlock())
+            newChild->setFlowThreadState(seamlessBox->flowThreadState());
+    }
+    RenderBlock::addChild(newChild, beforeChild);
+}
+
+bool RenderView::initializeLayoutState(LayoutState& state)
+{
+    bool isSeamlessAncestorInFlowThread = false;
+
+    // FIXME: May be better to push a clip and avoid issuing offscreen repaints.
+    state.m_clipped = false;
+    
+    // Check the writing mode of the seamless ancestor. It has to match our document's writing mode, or we won't inherit any
+    // pagination information.
+    RenderBox* seamlessAncestor = enclosingSeamlessRenderer(document());
+    LayoutState* seamlessLayoutState = seamlessAncestor ? seamlessAncestor->view()->layoutState() : 0;
+    bool shouldInheritPagination = seamlessLayoutState && !m_pageLogicalHeight && seamlessAncestor->style()->writingMode() == style()->writingMode();
+    
+    state.m_pageLogicalHeight = shouldInheritPagination ? seamlessLayoutState->m_pageLogicalHeight : m_pageLogicalHeight;
+    state.m_pageLogicalHeightChanged = shouldInheritPagination ? seamlessLayoutState->m_pageLogicalHeightChanged : m_pageLogicalHeightChanged;
+    state.m_isPaginated = state.m_pageLogicalHeight;
+    if (state.m_isPaginated && shouldInheritPagination) {
+        // Set up the correct pagination offset. We can use a negative offset in order to push the top of the RenderView into its correct place
+        // on a page. We can take the iframe's offset from the logical top of the first page and make the negative into the pagination offset within the child
+        // view.
+        bool isFlipped = seamlessAncestor->style()->isFlippedBlocksWritingMode();
+        LayoutSize layoutOffset = seamlessLayoutState->layoutOffset();
+        LayoutSize iFrameOffset(layoutOffset.width() + seamlessAncestor->x() + (!isFlipped ? seamlessAncestor->borderLeft() + seamlessAncestor->paddingLeft() :
+            seamlessAncestor->borderRight() + seamlessAncestor->paddingRight()),
+            layoutOffset.height() + seamlessAncestor->y() + (!isFlipped ? seamlessAncestor->borderTop() + seamlessAncestor->paddingTop() :
+            seamlessAncestor->borderBottom() + seamlessAncestor->paddingBottom()));
+        
+        LayoutSize offsetDelta = seamlessLayoutState->m_pageOffset - iFrameOffset;
+        state.m_pageOffset = offsetDelta;
+        
+        // Set the current render flow thread to point to our ancestor. This will allow the seamless document to locate the correct
+        // regions when doing a layout.
+        if (seamlessAncestor->flowThreadContainingBlock()) {
+            flowThreadController()->setCurrentRenderFlowThread(seamlessAncestor->view()->flowThreadController()->currentRenderFlowThread());
+            isSeamlessAncestorInFlowThread = true;
+        }
+    }
+
+    // FIXME: We need to make line grids and exclusions work with seamless iframes as well here. Basically all layout state information needs
+    // to propagate here and not just pagination information.
+    return isSeamlessAncestorInFlowThread;
+}
+
+// The algorithm below assumes this is a full layout. In case there are previously computed values for regions, supplemental steps are taken
+// to ensure the results are the same as those obtained from a full layout (i.e. the auto-height regions from all the flows are marked as needing
+// layout).
+// 1. The flows are laid out from the outer flow to the inner flow. This successfully computes the outer non-auto-height regions size so the 
+// inner flows have the necessary information to correctly fragment the content.
+// 2. The flows are laid out from the inner flow to the outer flow. After an inner flow is laid out it goes into the constrained layout phase
+// and marks the auto-height regions they need layout. This means the outer flows will relayout if they depend on regions with auto-height regions
+// belonging to inner flows. This step will correctly compute the overrideLogicalHeights for the auto-height regions. It's possible for non-auto-height
+// regions to relayout if they depend on auto-height regions. This will invalidate the inner flow threads and mark them as needing layout.
+// 3. The last step is to do one last layout if there are pathological dependencies between non-auto-height regions and auto-height regions
+// as detected in the previous step.
+void RenderView::layoutContentInAutoLogicalHeightRegions(const LayoutState& state)
+{
+    // We need to invalidate all the flows with auto-height regions if one such flow needs layout.
+    // If none is found we do a layout a check back again afterwards.
+    if (!flowThreadController()->updateFlowThreadsNeedingLayout()) {
+        // Do a first layout of the content. In some cases more layouts are not needed (e.g. only flows with non-auto-height regions have changed).
+        layoutContent(state);
+
+        // If we find no named flow needing a two step layout after the first layout, exit early.
+        // Otherwise, initiate the two step layout algorithm and recompute all the flows.
+        if (!flowThreadController()->updateFlowThreadsNeedingTwoStepLayout())
+            return;
+    }
+
+    // Layout to recompute all the named flows with auto-height regions.
+    layoutContent(state);
+
+    // Propagate the computed auto-height values upwards.
+    // Non-auto-height regions may invalidate the flow thread because they depended on auto-height regions, but that's ok.
+    flowThreadController()->updateFlowThreadsIntoConstrainedPhase();
+
+    // Do one last layout that should update the auto-height regions found in the main flow
+    // and solve pathological dependencies between regions (e.g. a non-auto-height region depending
+    // on an auto-height one).
+    if (needsLayout())
+        layoutContent(state);
+}
+
+void RenderView::layout()
+{
+    StackStats::LayoutCheckPoint layoutCheckPoint;
+    if (!document()->paginated())
+        setPageLogicalHeight(0);
+
+    if (shouldUsePrintingLayout())
+        m_minPreferredLogicalWidth = m_maxPreferredLogicalWidth = logicalWidth();
+
+    // Use calcWidth/Height to get the new width/height, since this will take the full page zoom factor into account.
+    bool relayoutChildren = !shouldUsePrintingLayout() && (!m_frameView || width() != viewWidth() || height() != viewHeight());
+    if (relayoutChildren) {
+        setChildNeedsLayout(true, MarkOnlyThis);
+        for (RenderObject* child = firstChild(); child; child = child->nextSibling()) {
+            if ((child->isBox() && (toRenderBox(child)->hasRelativeLogicalHeight() || toRenderBox(child)->hasViewportPercentageLogicalHeight()))
+                    || child->style()->logicalHeight().isPercent()
+                    || child->style()->logicalMinHeight().isPercent()
+                    || child->style()->logicalMaxHeight().isPercent()
+                    || child->style()->logicalHeight().isViewportPercentage()
+                    || child->style()->logicalMinHeight().isViewportPercentage()
+                    || child->style()->logicalMaxHeight().isViewportPercentage())
+                child->setChildNeedsLayout(true, MarkOnlyThis);
+        }
+    }
+
+    ASSERT(!m_layoutState);
+    if (!needsLayout())
+        return;
+
+    LayoutState state;
+    bool isSeamlessAncestorInFlowThread = initializeLayoutState(state);
+
+    m_pageLogicalHeightChanged = false;
+    m_layoutState = &state;
+
+    if (checkTwoPassLayoutForAutoHeightRegions())
+        layoutContentInAutoLogicalHeightRegions(state);
+    else
+        layoutContent(state);
+
+#ifndef NDEBUG
+    checkLayoutState(state);
+#endif
+    m_layoutState = 0;
+    setNeedsLayout(false);
+    
+    if (isSeamlessAncestorInFlowThread)
+        flowThreadController()->setCurrentRenderFlowThread(0);
+}
+
+void RenderView::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags mode, bool* wasFixed) const
+{
+    // If a container was specified, and was not 0 or the RenderView,
+    // then we should have found it by now.
+    ASSERT_ARG(repaintContainer, !repaintContainer || repaintContainer == this);
+    ASSERT_UNUSED(wasFixed, !wasFixed || *wasFixed == (mode & IsFixed));
+
+    if (!repaintContainer && mode & UseTransforms && shouldUseTransformFromContainer(0)) {
+        TransformationMatrix t;
+        getTransformFromContainer(0, LayoutSize(), t);
+        transformState.applyTransform(t);
+    }
+    
+    if (mode & IsFixed && m_frameView)
+        transformState.move(m_frameView->scrollOffsetForFixedPosition());
+}
+
+const RenderObject* RenderView::pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const
+{
+    // If a container was specified, and was not 0 or the RenderView,
+    // then we should have found it by now.
+    ASSERT_ARG(ancestorToStopAt, !ancestorToStopAt || ancestorToStopAt == this);
+
+    LayoutSize scrollOffset;
+
+    if (m_frameView)
+        scrollOffset = m_frameView->scrollOffsetForFixedPosition();
+
+    if (!ancestorToStopAt && shouldUseTransformFromContainer(0)) {
+        TransformationMatrix t;
+        getTransformFromContainer(0, LayoutSize(), t);
+        geometryMap.pushView(this, scrollOffset, &t);
+    } else
+        geometryMap.pushView(this, scrollOffset);
+
+    return 0;
+}
+
+void RenderView::mapAbsoluteToLocalPoint(MapCoordinatesFlags mode, TransformState& transformState) const
+{
+    if (mode & IsFixed && m_frameView)
+        transformState.move(m_frameView->scrollOffsetForFixedPosition());
+
+    if (mode & UseTransforms && shouldUseTransformFromContainer(0)) {
+        TransformationMatrix t;
+        getTransformFromContainer(0, LayoutSize(), t);
+        transformState.applyTransform(t);
+    }
+}
+
+bool RenderView::requiresColumns(int desiredColumnCount) const
+{
+    if (m_frameView)
+        return m_frameView->pagination().mode != Pagination::Unpaginated;
+
+    return RenderBlock::requiresColumns(desiredColumnCount);
+}
+
+void RenderView::calcColumnWidth()
+{
+    int columnWidth = contentLogicalWidth();
+    if (m_frameView && style()->hasInlineColumnAxis()) {
+        if (int pageLength = m_frameView->pagination().pageLength)
+            columnWidth = pageLength;
+    }
+    setDesiredColumnCountAndWidth(1, columnWidth);
+}
+
+ColumnInfo::PaginationUnit RenderView::paginationUnit() const
+{
+    if (m_frameView)
+        return m_frameView->pagination().behavesLikeColumns ? ColumnInfo::Column : ColumnInfo::Page;
+
+    return ColumnInfo::Page;
+}
+
+void RenderView::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    // If we ever require layout but receive a paint anyway, something has gone horribly wrong.
+    ASSERT(!needsLayout());
+    // RenderViews should never be called to paint with an offset not on device pixels.
+    ASSERT(LayoutPoint(IntPoint(paintOffset.x(), paintOffset.y())) == paintOffset);
+
+    // This avoids painting garbage between columns if there is a column gap.
+    if (m_frameView && m_frameView->pagination().mode != Pagination::Unpaginated)
+        paintInfo.context->fillRect(paintInfo.rect, m_frameView->baseBackgroundColor(), ColorSpaceDeviceRGB);
+
+    paintObject(paintInfo, paintOffset);
+}
+
+static inline bool isComposited(RenderObject* object)
+{
+    return object->hasLayer() && toRenderLayerModelObject(object)->layer()->isComposited();
+}
+
+static inline bool rendererObscuresBackground(RenderObject* rootObject)
+{
+    if (!rootObject)
+        return false;
+    
+    RenderStyle* style = rootObject->style();
+    if (style->visibility() != VISIBLE
+        || style->opacity() != 1
+        || style->hasTransform())
+        return false;
+    
+    if (isComposited(rootObject))
+        return false;
+
+    const RenderObject* rootRenderer = rootObject->rendererForRootBackground();
+    if (rootRenderer->style()->backgroundClip() == TextFillBox)
+        return false;
+
+    return true;
+}
+
+void RenderView::paintBoxDecorations(PaintInfo& paintInfo, const LayoutPoint&)
+{
+    // 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->cannotBlitToWindow()) {
+            frameView()->setCannotBlitToWindow();
+            break;
+        }
+
+        if (RenderLayer* compositingLayer = layer->enclosingCompositingLayerForRepaint()) {
+            if (!compositingLayer->backing()->paintsIntoWindow()) {
+                frameView()->setCannotBlitToWindow();
+                break;
+            }
+        }
+    }
+
+    if (document()->ownerElement() || !view())
+        return;
+
+    if (paintInfo.skipRootBackground())
+        return;
+
+    bool rootFillsViewport = false;
+    bool rootObscuresBackground = false;
+    Node* documentElement = document()->documentElement();
+    if (RenderObject* rootRenderer = documentElement ? documentElement->renderer() : 0) {
+        // The document element's renderer is currently forced to be a block, but may not always be.
+        RenderBox* rootBox = rootRenderer->isBox() ? toRenderBox(rootRenderer) : 0;
+        rootFillsViewport = rootBox && !rootBox->x() && !rootBox->y() && rootBox->width() >= width() && rootBox->height() >= height();
+        rootObscuresBackground = rendererObscuresBackground(rootRenderer);
+    }
+    
+    Page* page = document()->page();
+    float pageScaleFactor = page ? page->pageScaleFactor() : 1;
+
+    // If painting will entirely fill the view, no need to fill the background.
+    if (rootFillsViewport && rootObscuresBackground && pageScaleFactor >= 1)
+        return;
+
+    // This code typically only executes if the root element's visibility has been set to hidden,
+    // if there is a transform on the <html>, or if there is a page scale factor less than 1.
+    // 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 (frameView()->isTransparent()) // FIXME: This needs to be dynamic.  We should be able to go back to blitting if we ever stop being transparent.
+        frameView()->setCannotBlitToWindow(); // The parent must show behind the child.
+    else {
+        Color baseColor = frameView()->baseBackgroundColor();
+        if (baseColor.alpha()) {
+            CompositeOperator previousOperator = paintInfo.context->compositeOperation();
+            paintInfo.context->setCompositeOperation(CompositeCopy);
+            paintInfo.context->fillRect(paintInfo.rect, baseColor, style()->colorSpace());
+            paintInfo.context->setCompositeOperation(previousOperator);
+        } else
+            paintInfo.context->clearRect(paintInfo.rect);
+    }
+}
+
+bool RenderView::shouldRepaint(const LayoutRect& r) const
+{
+    if (printing() || r.width() == 0 || r.height() == 0)
+        return false;
+
+    if (!m_frameView)
+        return false;
+
+    if (m_frameView->repaintsDisabled())
+        return false;
+
+    return true;
+}
+
+void RenderView::repaintViewRectangle(const LayoutRect& ur) const
+{
+    if (!shouldRepaint(ur))
+        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(pixelSnappedIntRect(ur));
+    else if (RenderBox* obj = elt->renderBox()) {
+        LayoutRect vr = viewRect();
+        LayoutRect r = intersection(ur, vr);
+        
+        // Subtract out the contentsX and contentsY offsets to get our coords within the viewing
+        // rectangle.
+        r.moveBy(-vr.location());
+
+        // FIXME: Hardcoded offsets here are not good.
+        r.moveBy(obj->contentBoxRect().location());
+        obj->repaintRectangle(r);
+    }
+}
+
+void RenderView::repaintRectangleInViewAndCompositedLayers(const LayoutRect& ur)
+{
+    if (!shouldRepaint(ur))
+        return;
+
+    repaintViewRectangle(ur);
+    
+    if (compositor()->inCompositingMode()) {
+        IntRect repaintRect = pixelSnappedIntRect(ur);
+        compositor()->repaintCompositedLayers(&repaintRect);
+    }
+}
+
+void RenderView::repaintViewAndCompositedLayers()
+{
+    repaint();
+    
+    if (compositor()->inCompositingMode())
+        compositor()->repaintCompositedLayers();
+}
+
+void RenderView::computeRectForRepaint(const RenderLayerModelObject* repaintContainer, LayoutRect& rect, bool fixed) const
+{
+    // If a container was specified, and was not 0 or the RenderView,
+    // then we should have found it by now.
+    ASSERT_ARG(repaintContainer, !repaintContainer || repaintContainer == this);
+
+    if (printing())
+        return;
+
+    if (style()->isFlippedBlocksWritingMode()) {
+        // We have to flip by hand since the view's logical height has not been determined.  We
+        // can use the viewport width and height.
+        if (style()->isHorizontalWritingMode())
+            rect.setY(viewHeight() - rect.maxY());
+        else
+            rect.setX(viewWidth() - rect.maxX());
+    }
+
+    if (fixed && m_frameView)
+        rect.move(m_frameView->scrollOffsetForFixedPosition());
+        
+    // Apply our transform if we have one (because of full page zooming).
+    if (!repaintContainer && layer() && layer()->transform())
+        rect = layer()->transform()->mapRect(rect);
+}
+
+void RenderView::absoluteRects(Vector<IntRect>& rects, const LayoutPoint& accumulatedOffset) const
+{
+    rects.append(pixelSnappedIntRect(accumulatedOffset, layer()->size()));
+}
+
+void RenderView::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed) const
+{
+    if (wasFixed)
+        *wasFixed = false;
+    quads.append(FloatRect(FloatPoint(), layer()->size()));
+}
+
+static RenderObject* rendererAfterPosition(RenderObject* object, unsigned offset)
+{
+    if (!object)
+        return 0;
+
+    RenderObject* child = object->childAt(offset);
+    return child ? child : object->nextInPreOrderAfterChildren();
+}
+
+IntRect RenderView::selectionBounds(bool clipToVisibleContent) const
+{
+    document()->updateStyleIfNeeded();
+
+    typedef HashMap<RenderObject*, OwnPtr<RenderSelectionInfo> > 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, adoptPtr(new RenderSelectionInfo(os, clipToVisibleContent)));
+            RenderBlock* cb = os->containingBlock();
+            while (cb && !cb->isRenderView()) {
+                OwnPtr<RenderSelectionInfo>& blockInfo = selectedObjects.add(cb, nullptr).iterator->value;
+                if (blockInfo)
+                    break;
+                blockInfo = adoptPtr(new RenderSelectionInfo(cb, clipToVisibleContent));
+                cb = cb->containingBlock();
+            }
+        }
+
+        os = os->nextInPreOrder();
+    }
+
+    // Now create a single bounding box rect that encloses the whole selection.
+    LayoutRect selRect;
+    SelectionMap::iterator end = selectedObjects.end();
+    for (SelectionMap::iterator i = selectedObjects.begin(); i != end; ++i) {
+        RenderSelectionInfo* info = i->value.get();
+        // RenderSelectionInfo::rect() is in the coordinates of the repaintContainer, so map to page coordinates.
+        LayoutRect currRect = info->rect();
+        if (RenderLayerModelObject* repaintContainer = info->repaintContainer()) {
+            FloatQuad absQuad = repaintContainer->localToAbsoluteQuad(FloatRect(currRect));
+            currRect = absQuad.enclosingBoundingBox(); 
+        }
+        selRect.unite(currRect);
+    }
+    return pixelSnappedIntRect(selRect);
+}
+
+void RenderView::repaintSelection() const
+{
+    document()->updateStyleIfNeeded();
+
+    HashSet<RenderBlock*> processedBlocks;
+
+    RenderObject* end = rendererAfterPosition(m_selectionEnd, m_selectionEndPos);
+    for (RenderObject* o = m_selectionStart; o && o != end; o = o->nextInPreOrder()) {
+        if (!o->canBeSelectionLeaf() && o != m_selectionStart && o != m_selectionEnd)
+            continue;
+        if (o->selectionState() == SelectionNone)
+            continue;
+
+        RenderSelectionInfo(o, true).repaint();
+
+        // Blocks are responsible for painting line gaps and margin gaps. They must be examined as well.
+        for (RenderBlock* block = o->containingBlock(); block && !block->isRenderView(); block = block->containingBlock()) {
+            if (processedBlocks.contains(block))
+                break;
+            processedBlocks.add(block);
+            RenderSelectionInfo(block, true).repaint();
+        }
+    }
+}
+
+// Compositing layer dimensions take outline size into account, so we have to recompute layer
+// bounds when it changes.
+// FIXME: This is ugly; it would be nice to have a better way to do this.
+void RenderView::setMaximalOutlineSize(int o)
+{
+    if (o != m_maximalOutlineSize) {
+        m_maximalOutlineSize = o;
+
+        // maximalOutlineSize affects compositing layer dimensions.
+        compositor()->setCompositingLayersNeedRebuild();    // FIXME: this really just needs to be a geometry update.
+    }
+}
+
+void RenderView::setSelection(RenderObject* start, int startPos, RenderObject* end, int endPos, SelectionRepaintMode blockRepaintMode)
+{
+    // 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;
+
+    if ((start && end) && (start->flowThreadContainingBlock() != end->flowThreadContainingBlock()))
+        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*, OwnPtr<RenderSelectionInfo> > 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*, OwnPtr<RenderBlockSelectionInfo> > 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, adoptPtr(new RenderSelectionInfo(os, true)));
+            if (blockRepaintMode == RepaintNewXOROld) {
+                RenderBlock* cb = os->containingBlock();
+                while (cb && !cb->isRenderView()) {
+                    OwnPtr<RenderBlockSelectionInfo>& blockInfo = oldSelectedBlocks.add(cb, nullptr).iterator->value;
+                    if (blockInfo)
+                        break;
+                    blockInfo = adoptPtr(new RenderBlockSelectionInfo(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->key->setSelectionStateIfNeeded(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->setSelectionStateIfNeeded(SelectionBoth);
+    else {
+        if (start)
+            start->setSelectionStateIfNeeded(SelectionStart);
+        if (end)
+            end->setSelectionStateIfNeeded(SelectionEnd);
+    }
+
+    RenderObject* o = start;
+    stop = rendererAfterPosition(end, endPos);
+
+    while (o && o != stop) {
+        if (o != start && o != end && o->canBeSelectionLeaf())
+            o->setSelectionStateIfNeeded(SelectionInside);
+        o = o->nextInPreOrder();
+    }
+
+    if (blockRepaintMode != RepaintNothing)
+        layer()->clearBlockSelectionGapsBounds();
+
+    // 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, adoptPtr(new RenderSelectionInfo(o, true)));
+            RenderBlock* cb = o->containingBlock();
+            while (cb && !cb->isRenderView()) {
+                OwnPtr<RenderBlockSelectionInfo>& blockInfo = newSelectedBlocks.add(cb, nullptr).iterator->value;
+                if (blockInfo)
+                    break;
+                blockInfo = adoptPtr(new RenderBlockSelectionInfo(cb));
+                cb = cb->containingBlock();
+            }
+        }
+
+        o = o->nextInPreOrder();
+    }
+
+    if (!m_frameView || blockRepaintMode == RepaintNothing)
+        return;
+
+    m_frameView->beginDeferredRepaints();
+
+    // 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->key;
+        RenderSelectionInfo* newInfo = newSelectedObjects.get(obj);
+        RenderSelectionInfo* oldInfo = i->value.get();
+        if (!newInfo || oldInfo->rect() != newInfo->rect() || oldInfo->state() != newInfo->state() ||
+            (m_selectionStart == obj && oldStartPos != m_selectionStartPos) ||
+            (m_selectionEnd == obj && oldEndPos != m_selectionEndPos)) {
+            oldInfo->repaint();
+            if (newInfo) {
+                newInfo->repaint();
+                newSelectedObjects.remove(obj);
+            }
+        }
+    }
+
+    // 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)
+        i->value->repaint();
+
+    // Have any of the old blocks changed?
+    SelectedBlockMap::iterator oldBlocksEnd = oldSelectedBlocks.end();
+    for (SelectedBlockMap::iterator i = oldSelectedBlocks.begin(); i != oldBlocksEnd; ++i) {
+        RenderBlock* block = i->key;
+        RenderBlockSelectionInfo* newInfo = newSelectedBlocks.get(block);
+        RenderBlockSelectionInfo* oldInfo = i->value.get();
+        if (!newInfo || oldInfo->rects() != newInfo->rects() || oldInfo->state() != newInfo->state()) {
+            oldInfo->repaint();
+            if (newInfo) {
+                newInfo->repaint();
+                newSelectedBlocks.remove(block);
+            }
+        }
+    }
+
+    // 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)
+        i->value->repaint();
+
+    m_frameView->endDeferredRepaints();
+}
+
+void RenderView::getSelection(RenderObject*& startRenderer, int& startOffset, RenderObject*& endRenderer, int& endOffset) const
+{
+    startRenderer = m_selectionStart;
+    startOffset = m_selectionStartPos;
+    endRenderer = m_selectionEnd;
+    endOffset = m_selectionEndPos;
+}
+
+void RenderView::clearSelection()
+{
+    layer()->repaintBlockSelectionGaps();
+    setSelection(0, -1, 0, -1, RepaintNewMinusOld);
+}
+
+void RenderView::selectionStartEnd(int& startPos, int& endPos) const
+{
+    startPos = m_selectionStartPos;
+    endPos = m_selectionEndPos;
+}
+
+bool RenderView::printing() const
+{
+    return document()->printing();
+}
+
+bool RenderView::shouldUsePrintingLayout() const
+{
+    if (!printing() || !m_frameView)
+        return false;
+    Frame* frame = m_frameView->frame();
+    return frame && frame->shouldUsePrintingLayout();
+}
+
+size_t RenderView::getRetainedWidgets(Vector<RenderWidget*>& renderWidgets)
+{
+    size_t size = m_widgets.size();
+
+    renderWidgets.reserveCapacity(size);
+
+    RenderWidgetSet::const_iterator end = m_widgets.end();
+    for (RenderWidgetSet::const_iterator it = m_widgets.begin(); it != end; ++it) {
+        renderWidgets.uncheckedAppend(*it);
+        (*it)->ref();
+    }
+    
+    return size;
+}
+
+void RenderView::releaseWidgets(Vector<RenderWidget*>& renderWidgets)
+{
+    size_t size = renderWidgets.size();
+
+    for (size_t i = 0; i < size; ++i)
+        renderWidgets[i]->deref(renderArena());
+}
+
+void RenderView::updateWidgetPositions()
+{
+    // updateWidgetPosition() can possibly cause layout to be re-entered (via plug-ins running
+    // scripts in response to NPP_SetWindow, for example), so we need to keep the Widgets
+    // alive during enumeration.    
+
+    Vector<RenderWidget*> renderWidgets;
+    size_t size = getRetainedWidgets(renderWidgets);
+    
+    for (size_t i = 0; i < size; ++i)
+        renderWidgets[i]->updateWidgetPosition();
+
+    for (size_t i = 0; i < size; ++i)
+        renderWidgets[i]->widgetPositionsUpdated();
+
+    releaseWidgets(renderWidgets);
+}
+
+void RenderView::addWidget(RenderWidget* o)
+{
+    m_widgets.add(o);
+}
+
+void RenderView::removeWidget(RenderWidget* o)
+{
+    m_widgets.remove(o);
+}
+
+LayoutRect RenderView::viewRect() const
+{
+    if (shouldUsePrintingLayout())
+        return LayoutRect(LayoutPoint(), size());
+    if (m_frameView)
+        return m_frameView->visibleContentRect();
+    return LayoutRect();
+}
+
+IntRect RenderView::unscaledDocumentRect() const
+{
+    LayoutRect overflowRect(layoutOverflowRect());
+    flipForWritingMode(overflowRect);
+    return pixelSnappedIntRect(overflowRect);
+}
+
+bool RenderView::rootBackgroundIsEntirelyFixed() const
+{
+    RenderObject* rootObject = document()->documentElement() ? document()->documentElement()->renderer() : 0;
+    if (!rootObject)
+        return false;
+
+    RenderObject* rootRenderer = rootObject->rendererForRootBackground();
+    return rootRenderer->hasEntirelyFixedBackground();
+}
+
+LayoutRect RenderView::backgroundRect(RenderBox* backgroundRenderer) const
+{
+    if (!hasColumns())
+        return unscaledDocumentRect();
+
+    ColumnInfo* columnInfo = this->columnInfo();
+    LayoutRect backgroundRect(0, 0, columnInfo->desiredColumnWidth(), columnInfo->columnHeight() * columnInfo->columnCount());
+    if (!isHorizontalWritingMode())
+        backgroundRect = backgroundRect.transposedRect();
+    backgroundRenderer->flipForWritingMode(backgroundRect);
+
+    return backgroundRect;
+}
+
+IntRect RenderView::documentRect() const
+{
+    FloatRect overflowRect(unscaledDocumentRect());
+    if (hasTransform())
+        overflowRect = layer()->currentTransform().mapRect(overflowRect);
+    return IntRect(overflowRect);
+}
+
+int RenderView::viewHeight() const
+{
+    int height = 0;
+    if (!shouldUsePrintingLayout() && m_frameView) {
+        height = m_frameView->layoutHeight();
+        height = m_frameView->useFixedLayout() ? ceilf(style()->effectiveZoom() * float(height)) : height;
+    }
+    return height;
+}
+
+int RenderView::viewWidth() const
+{
+    int width = 0;
+    if (!shouldUsePrintingLayout() && m_frameView) {
+        width = m_frameView->layoutWidth();
+        width = m_frameView->useFixedLayout() ? ceilf(style()->effectiveZoom() * float(width)) : width;
+    }
+    return width;
+}
+
+int RenderView::viewLogicalHeight() const
+{
+    int height = style()->isHorizontalWritingMode() ? viewHeight() : viewWidth();
+
+    if (hasColumns() && !style()->hasInlineColumnAxis()) {
+        if (int pageLength = m_frameView->pagination().pageLength)
+            height = pageLength;
+    }
+
+    return height;
+}
+
+float RenderView::zoomFactor() const
+{
+    Frame* frame = m_frameView->frame();
+    return frame ? frame->pageZoomFactor() : 1;
+}
+
+void RenderView::pushLayoutState(RenderObject* root)
+{
+    ASSERT(m_layoutStateDisableCount == 0);
+    ASSERT(m_layoutState == 0);
+
+    m_layoutState = new (renderArena()) LayoutState(root);
+}
+
+bool RenderView::shouldDisableLayoutStateForSubtree(RenderObject* renderer) const
+{
+    RenderObject* o = renderer;
+    while (o) {
+        if (o->hasColumns() || o->hasTransform() || o->hasReflection())
+            return true;
+        o = o->container();
+    }
+    return false;
+}
+
+void RenderView::updateHitTestResult(HitTestResult& result, const LayoutPoint& point)
+{
+    if (result.innerNode())
+        return;
+
+    Node* node = document()->documentElement();
+    if (node) {
+        result.setInnerNode(node);
+        if (!result.innerNonSharedNode())
+            result.setInnerNonSharedNode(node);
+
+        LayoutPoint adjustedPoint = point;
+        offsetForContents(adjustedPoint);
+
+        result.setLocalPoint(adjustedPoint);
+    }
+}
+
+// FIXME: This function is obsolete and only used by embedded WebViews inside AppKit NSViews.
+// Do not add callers of this function!
+// 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, RenderBoxModelObject* forRenderer, bool forcedBreak)
+{
+    // Nobody else can set a page break once we have a forced break.
+    if (m_legacyPrinting.m_forcedPageBreak)
+        return;
+
+    // Forced breaks always win over unforced breaks.
+    if (forcedBreak) {
+        m_legacyPrinting.m_forcedPageBreak = true;
+        m_legacyPrinting.m_bestTruncatedAt = y;
+        return;
+    }
+
+    // Prefer the widest object that tries to move the pagination point
+    IntRect boundingBox = forRenderer->borderBoundingBox();
+    if (boundingBox.width() > m_legacyPrinting.m_truncatorWidth) {
+        m_legacyPrinting.m_truncatorWidth = boundingBox.width();
+        m_legacyPrinting.m_bestTruncatedAt = y;
+    }
+}
+
+bool RenderView::usesCompositing() const
+{
+    return m_compositor && m_compositor->inCompositingMode();
+}
+
+RenderLayerCompositor* RenderView::compositor()
+{
+    if (!m_compositor)
+        m_compositor = adoptPtr(new RenderLayerCompositor(this));
+
+    return m_compositor.get();
+}
+
+void RenderView::setIsInWindow(bool isInWindow)
+{
+    if (m_compositor)
+        m_compositor->setIsInWindow(isInWindow);
+}
+
+CustomFilterGlobalContext* RenderView::customFilterGlobalContext()
+{
+    if (!m_customFilterGlobalContext)
+        m_customFilterGlobalContext = adoptPtr(new CustomFilterGlobalContext());
+    return m_customFilterGlobalContext.get();
+}
+
+void RenderView::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
+{
+    RenderBlock::styleDidChange(diff, oldStyle);
+    if (hasRenderNamedFlowThreads())
+        flowThreadController()->styleDidChange();
+}
+
+bool RenderView::hasRenderNamedFlowThreads() const
+{
+    return m_flowThreadController && m_flowThreadController->hasRenderNamedFlowThreads();
+}
+
+bool RenderView::checkTwoPassLayoutForAutoHeightRegions() const
+{
+    return hasRenderNamedFlowThreads() && m_flowThreadController->hasFlowThreadsWithAutoLogicalHeightRegions();
+}
+
+FlowThreadController* RenderView::flowThreadController()
+{
+    if (!m_flowThreadController)
+        m_flowThreadController = FlowThreadController::create(this);
+
+    return m_flowThreadController.get();
+}
+
+RenderBlock::IntervalArena* RenderView::intervalArena()
+{
+    if (!m_intervalArena)
+        m_intervalArena = IntervalArena::create();
+    return m_intervalArena.get();
+}
+
+void RenderView::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, PlatformMemoryTypes::Rendering);
+    RenderBlock::reportMemoryUsage(memoryObjectInfo);
+    info.addWeakPointer(m_frameView);
+    info.addWeakPointer(m_selectionStart);
+    info.addWeakPointer(m_selectionEnd);
+    info.addMember(m_widgets, "widgets");
+    info.addMember(m_layoutState, "layoutState");
+    info.addMember(m_compositor, "compositor");
+    info.addMember(m_customFilterGlobalContext, "customFilterGlobalContext");
+    info.addMember(m_flowThreadController, "flowThreadController");
+    info.addMember(m_intervalArena, "intervalArena");
+    info.addWeakPointer(m_renderQuoteHead);
+    info.addMember(m_legacyPrinting, "legacyPrinting");
+}
+
+FragmentationDisabler::FragmentationDisabler(RenderObject* root)
+{
+    RenderView* renderView = root->view();
+    ASSERT(renderView);
+
+    LayoutState* layoutState = renderView->layoutState();
+
+    m_root = root;
+    m_fragmenting = layoutState && layoutState->isPaginated();
+    m_flowThreadState = m_root->flowThreadState();
+#ifndef NDEBUG
+    m_layoutState = layoutState;
+#endif
+
+    if (layoutState)
+        layoutState->m_isPaginated = false;
+        
+    if (m_flowThreadState != RenderObject::NotInsideFlowThread)
+        m_root->setFlowThreadStateIncludingDescendants(RenderObject::NotInsideFlowThread);
+}
+
+FragmentationDisabler::~FragmentationDisabler()
+{
+    RenderView* renderView = m_root->view();
+    ASSERT(renderView);
+
+    LayoutState* layoutState = renderView->layoutState();
+#ifndef NDEBUG
+    ASSERT(m_layoutState == layoutState);
+#endif
+
+    if (layoutState)
+        layoutState->m_isPaginated = m_fragmenting;
+        
+    if (m_flowThreadState != RenderObject::NotInsideFlowThread)
+        m_root->setFlowThreadStateIncludingDescendants(m_flowThreadState);
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderView.h b/Source/core/rendering/RenderView.h
new file mode 100644
index 0000000..857305f
--- /dev/null
+++ b/Source/core/rendering/RenderView.h
@@ -0,0 +1,439 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * 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 "core/page/FrameView.h"
+#include "core/platform/PODFreeListArena.h"
+#include "core/rendering/LayoutState.h"
+#include "core/rendering/RenderBlock.h"
+#include <wtf/OwnPtr.h>
+
+namespace WebCore {
+
+class CustomFilterGlobalContext;
+class FlowThreadController;
+class RenderLayerCompositor;
+class RenderLazyBlock;
+class RenderQuote;
+class RenderWidget;
+
+class RenderView FINAL : public RenderBlock {
+public:
+    explicit RenderView(Document*);
+    virtual ~RenderView();
+
+    bool hitTest(const HitTestRequest&, HitTestResult&);
+    bool hitTest(const HitTestRequest&, const HitTestLocation&, HitTestResult&);
+
+    virtual const char* renderName() const OVERRIDE { return "RenderView"; }
+
+    virtual bool isRenderView() const OVERRIDE { return true; }
+
+    virtual bool requiresLayer() const OVERRIDE { return true; }
+
+    virtual bool isChildAllowed(RenderObject*, RenderStyle*) const OVERRIDE;
+
+    virtual void layout() OVERRIDE;
+    virtual void updateLogicalWidth() OVERRIDE;
+    virtual void computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues&) const OVERRIDE;
+
+    virtual LayoutUnit availableLogicalHeight(AvailableLogicalHeightType) const OVERRIDE;
+
+    // The same as the FrameView's layoutHeight/layoutWidth but with null check guards.
+    int viewHeight() const;
+    int viewWidth() const;
+    int viewLogicalWidth() const { return style()->isHorizontalWritingMode() ? viewWidth() : viewHeight(); }
+    int viewLogicalHeight() const;
+
+    float zoomFactor() const;
+
+    FrameView* frameView() const { return m_frameView; }
+
+    virtual void computeRectForRepaint(const RenderLayerModelObject* repaintContainer, LayoutRect&, bool fixed = false) const OVERRIDE;
+    void repaintViewRectangle(const LayoutRect&) const;
+    // Repaint the view, and all composited layers that intersect the given absolute rectangle.
+    // FIXME: ideally we'd never have to do this, if all repaints are container-relative.
+    void repaintRectangleInViewAndCompositedLayers(const LayoutRect&);
+    void repaintViewAndCompositedLayers();
+
+    virtual void paint(PaintInfo&, const LayoutPoint&);
+    virtual void paintBoxDecorations(PaintInfo&, const LayoutPoint&) OVERRIDE;
+
+    enum SelectionRepaintMode { RepaintNewXOROld, RepaintNewMinusOld, RepaintNothing };
+    void setSelection(RenderObject* start, int startPos, RenderObject* end, int endPos, SelectionRepaintMode = RepaintNewXOROld);
+    void getSelection(RenderObject*& startRenderer, int& startOffset, RenderObject*& endRenderer, int& endOffset) const;
+    void clearSelection();
+    RenderObject* selectionStart() const { return m_selectionStart; }
+    RenderObject* selectionEnd() const { return m_selectionEnd; }
+    IntRect selectionBounds(bool clipToVisibleContent = true) const;
+    void selectionStartEnd(int& startPos, int& endPos) const;
+    void repaintSelection() const;
+
+    bool printing() const;
+
+    virtual void absoluteRects(Vector<IntRect>&, const LayoutPoint& accumulatedOffset) const;
+    virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const;
+
+    void setMaximalOutlineSize(int o);
+    int maximalOutlineSize() const { return m_maximalOutlineSize; }
+
+    virtual LayoutRect viewRect() const OVERRIDE;
+
+    void updateWidgetPositions();
+    void addWidget(RenderWidget*);
+    void removeWidget(RenderWidget*);
+    
+    // layoutDelta is used transiently during layout to store how far an object has moved from its
+    // last layout location, in order to repaint correctly.
+    // If we're doing a full repaint m_layoutState will be 0, but in that case layoutDelta doesn't matter.
+    LayoutSize layoutDelta() const
+    {
+        return m_layoutState ? m_layoutState->m_layoutDelta : LayoutSize();
+    }
+    void addLayoutDelta(const LayoutSize& delta) 
+    {
+        if (m_layoutState) {
+            m_layoutState->m_layoutDelta += delta;
+#if !ASSERT_DISABLED
+            m_layoutState->m_layoutDeltaXSaturated |= m_layoutState->m_layoutDelta.width() == LayoutUnit::max() || m_layoutState->m_layoutDelta.width() == LayoutUnit::min();
+            m_layoutState->m_layoutDeltaYSaturated |= m_layoutState->m_layoutDelta.height() == LayoutUnit::max() || m_layoutState->m_layoutDelta.height() == LayoutUnit::min();
+#endif
+        }
+    }
+    
+#if !ASSERT_DISABLED
+    bool layoutDeltaMatches(const LayoutSize& delta)
+    {
+        if (!m_layoutState)
+            return false;
+        return (delta.width() == m_layoutState->m_layoutDelta.width() || m_layoutState->m_layoutDeltaXSaturated) && (delta.height() == m_layoutState->m_layoutDelta.height() || m_layoutState->m_layoutDeltaYSaturated);
+    }
+#endif
+
+    bool doingFullRepaint() const { return m_frameView->needsFullRepaint(); }
+
+    // Subtree push/pop
+    void pushLayoutState(RenderObject*);
+    void popLayoutState(RenderObject*) { return popLayoutState(); } // Just doing this to keep popLayoutState() private and to make the subtree calls symmetrical.
+
+    bool shouldDisableLayoutStateForSubtree(RenderObject*) const;
+
+    // Returns true if layoutState should be used for its cached offset and clip.
+    bool layoutStateEnabled() const { return m_layoutStateDisableCount == 0 && m_layoutState; }
+    LayoutState* layoutState() const { return m_layoutState; }
+
+    virtual void updateHitTestResult(HitTestResult&, const LayoutPoint&);
+
+    LayoutUnit pageLogicalHeight() const { return m_pageLogicalHeight; }
+    void setPageLogicalHeight(LayoutUnit height)
+    {
+        if (m_pageLogicalHeight != height) {
+            m_pageLogicalHeight = height;
+            m_pageLogicalHeightChanged = true;
+        }
+    }
+
+    // FIXME: These functions are deprecated. No code should be added that uses these.
+    int bestTruncatedAt() const { return m_legacyPrinting.m_bestTruncatedAt; }
+    void setBestTruncatedAt(int y, RenderBoxModelObject* forRenderer, bool forcedBreak = false);
+    int truncatedAt() const { return m_legacyPrinting.m_truncatedAt; }
+    void setTruncatedAt(int y)
+    { 
+        m_legacyPrinting.m_truncatedAt = y;
+        m_legacyPrinting.m_bestTruncatedAt = 0;
+        m_legacyPrinting.m_truncatorWidth = 0;
+        m_legacyPrinting.m_forcedPageBreak = false;
+    }
+    const IntRect& printRect() const { return m_legacyPrinting.m_printRect; }
+    void setPrintRect(const IntRect& r) { m_legacyPrinting.m_printRect = r; }
+    // End deprecated functions.
+
+    // Notification that this view moved into or out of a native window.
+    void setIsInWindow(bool);
+
+    RenderLayerCompositor* compositor();
+    bool usesCompositing() const;
+
+    CustomFilterGlobalContext* customFilterGlobalContext();
+
+    IntRect unscaledDocumentRect() const;
+    LayoutRect backgroundRect(RenderBox* backgroundRenderer) const;
+
+    IntRect documentRect() const;
+
+    // Renderer that paints the root background has background-images which all have background-attachment: fixed.
+    bool rootBackgroundIsEntirelyFixed() const;
+    
+    bool hasRenderNamedFlowThreads() const;
+    bool checkTwoPassLayoutForAutoHeightRegions() const;
+    FlowThreadController* flowThreadController();
+
+    void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+
+    IntervalArena* intervalArena();
+
+    IntSize viewportSize() const { return document()->viewportSize(); }
+
+    void setRenderQuoteHead(RenderQuote* head) { m_renderQuoteHead = head; }
+    RenderQuote* renderQuoteHead() const { return m_renderQuoteHead; }
+
+    void setFirstLazyBlock(RenderLazyBlock* block) { m_firstLazyBlock = block; }
+    RenderLazyBlock* firstLazyBlock() const { return m_firstLazyBlock; }
+    void markLazyBlocksForLayout();
+
+    // FIXME: This is a work around because the current implementation of counters
+    // requires walking the entire tree repeatedly and most pages don't actually use either
+    // feature so we shouldn't take the performance hit when not needed. Long term we should
+    // rewrite the counter and quotes code.
+    void addRenderCounter() { m_renderCounterCount++; }
+    void removeRenderCounter() { ASSERT(m_renderCounterCount > 0); m_renderCounterCount--; }
+    bool hasRenderCounters() { return m_renderCounterCount; }
+    
+    virtual void addChild(RenderObject* newChild, RenderObject* beforeChild = 0) OVERRIDE;
+
+protected:
+    virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = 0) const OVERRIDE;
+    virtual const RenderObject* pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap&) const OVERRIDE;
+    virtual void mapAbsoluteToLocalPoint(MapCoordinatesFlags, TransformState&) const;
+    virtual bool requiresColumns(int desiredColumnCount) const OVERRIDE;
+    
+private:
+    bool initializeLayoutState(LayoutState&);
+
+    virtual void calcColumnWidth() OVERRIDE;
+    virtual ColumnInfo::PaginationUnit paginationUnit() const OVERRIDE;
+
+    bool shouldRepaint(const LayoutRect&) const;
+
+    // These functions may only be accessed by LayoutStateMaintainer.
+    bool pushLayoutState(RenderBox* renderer, const LayoutSize& offset, LayoutUnit pageHeight = 0, bool pageHeightChanged = false, ColumnInfo* colInfo = 0)
+    {
+        // We push LayoutState even if layoutState is disabled because it stores layoutDelta too.
+        if (!doingFullRepaint() || m_layoutState->isPaginated() || renderer->hasColumns() || renderer->flowThreadContainingBlock()
+            || m_layoutState->lineGrid() || (renderer->style()->lineGrid() != RenderStyle::initialLineGrid() && renderer->isBlockFlow())
+            || (renderer->isRenderBlock() && toRenderBlock(renderer)->exclusionShapeInsideInfo())
+            || (m_layoutState->exclusionShapeInsideInfo() && renderer->isRenderBlock() && !toRenderBlock(renderer)->allowsExclusionShapeInsideInfoSharing())
+            ) {
+            m_layoutState = new (renderArena()) LayoutState(m_layoutState, renderer, offset, pageHeight, pageHeightChanged, colInfo);
+            return true;
+        }
+        return false;
+    }
+
+    void popLayoutState()
+    {
+        LayoutState* state = m_layoutState;
+        m_layoutState = state->m_next;
+        state->destroy(renderArena());
+    }
+
+    // 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).
+    // Note that even when disabled, LayoutState is still used to store layoutDelta.
+    // These functions may only be accessed by LayoutStateMaintainer or LayoutStateDisabler.
+    void disableLayoutState() { m_layoutStateDisableCount++; }
+    void enableLayoutState() { ASSERT(m_layoutStateDisableCount > 0); m_layoutStateDisableCount--; }
+
+    void layoutContent(const LayoutState&);
+    void layoutContentInAutoLogicalHeightRegions(const LayoutState&);
+#ifndef NDEBUG
+    void checkLayoutState(const LayoutState&);
+#endif
+
+    size_t getRetainedWidgets(Vector<RenderWidget*>&);
+    void releaseWidgets(Vector<RenderWidget*>&);
+    
+    friend class LayoutStateMaintainer;
+    friend class LayoutStateDisabler;
+
+    virtual void reportMemoryUsage(MemoryObjectInfo*) const OVERRIDE;
+
+protected:
+    FrameView* m_frameView;
+
+    RenderObject* m_selectionStart;
+    RenderObject* m_selectionEnd;
+    int m_selectionStartPos;
+    int m_selectionEndPos;
+
+    // FIXME: Only used by embedded WebViews inside AppKit NSViews.  Find a way to remove.
+    struct LegacyPrinting {
+        LegacyPrinting()
+            : m_bestTruncatedAt(0)
+            , m_truncatedAt(0)
+            , m_truncatorWidth(0)
+            , m_forcedPageBreak(false)
+        { }
+
+        int m_bestTruncatedAt;
+        int m_truncatedAt;
+        int m_truncatorWidth;
+        IntRect m_printRect;
+        bool m_forcedPageBreak;
+    };
+    LegacyPrinting m_legacyPrinting;
+    // End deprecated members.
+
+    int m_maximalOutlineSize; // Used to apply a fudge factor to dirty-rect checks on blocks/tables.
+
+    typedef HashSet<RenderWidget*> RenderWidgetSet;
+    RenderWidgetSet m_widgets;
+
+private:
+    bool shouldUsePrintingLayout() const;
+
+    LayoutUnit m_pageLogicalHeight;
+    bool m_pageLogicalHeightChanged;
+    LayoutState* m_layoutState;
+    unsigned m_layoutStateDisableCount;
+    OwnPtr<RenderLayerCompositor> m_compositor;
+    OwnPtr<CustomFilterGlobalContext> m_customFilterGlobalContext;
+    OwnPtr<FlowThreadController> m_flowThreadController;
+    RefPtr<IntervalArena> m_intervalArena;
+
+    RenderLazyBlock* m_firstLazyBlock;
+    RenderQuote* m_renderQuoteHead;
+    unsigned m_renderCounterCount;
+};
+
+inline RenderView* toRenderView(RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isRenderView());
+    return static_cast<RenderView*>(object);
+}
+
+inline const RenderView* toRenderView(const RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isRenderView());
+    return static_cast<const RenderView*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderView(const RenderView*);
+
+ALWAYS_INLINE RenderView* Document::renderView() const
+{
+    return toRenderView(renderer());
+}
+
+// Stack-based class to assist with LayoutState push/pop
+class LayoutStateMaintainer {
+    WTF_MAKE_NONCOPYABLE(LayoutStateMaintainer);
+public:
+    // ctor to push now
+    LayoutStateMaintainer(RenderView* view, RenderBox* root, LayoutSize offset, bool disableState = false, LayoutUnit pageHeight = 0, bool pageHeightChanged = false, ColumnInfo* colInfo = 0)
+        : m_view(view)
+        , m_disabled(disableState)
+        , m_didStart(false)
+        , m_didEnd(false)
+        , m_didCreateLayoutState(false)
+    {
+        push(root, offset, pageHeight, pageHeightChanged, colInfo);
+    }
+    
+    // ctor to maybe push later
+    LayoutStateMaintainer(RenderView* view)
+        : m_view(view)
+        , m_disabled(false)
+        , m_didStart(false)
+        , m_didEnd(false)
+        , m_didCreateLayoutState(false)
+    {
+    }
+
+    ~LayoutStateMaintainer()
+    {
+        ASSERT(m_didStart == m_didEnd);   // if this fires, it means that someone did a push(), but forgot to pop().
+    }
+
+    void push(RenderBox* root, LayoutSize offset, LayoutUnit pageHeight = 0, bool pageHeightChanged = false, ColumnInfo* colInfo = 0)
+    {
+        ASSERT(!m_didStart);
+        // We push state even if disabled, because we still need to store layoutDelta
+        m_didCreateLayoutState = m_view->pushLayoutState(root, offset, pageHeight, pageHeightChanged, colInfo);
+        if (m_disabled && m_didCreateLayoutState)
+            m_view->disableLayoutState();
+        m_didStart = true;
+    }
+
+    void pop()
+    {
+        if (m_didStart) {
+            ASSERT(!m_didEnd);
+            if (m_didCreateLayoutState) {
+                m_view->popLayoutState();
+                if (m_disabled)
+                    m_view->enableLayoutState();
+            }
+            
+            m_didEnd = true;
+        }
+    }
+
+    bool didPush() const { return m_didStart; }
+
+private:
+    RenderView* m_view;
+    bool m_disabled : 1;        // true if the offset and clip part of layoutState is disabled
+    bool m_didStart : 1;        // true if we did a push or disable
+    bool m_didEnd : 1;          // true if we popped or re-enabled
+    bool m_didCreateLayoutState : 1; // true if we actually made a layout state.
+};
+
+class LayoutStateDisabler {
+    WTF_MAKE_NONCOPYABLE(LayoutStateDisabler);
+public:
+    LayoutStateDisabler(RenderView* view)
+        : m_view(view)
+    {
+        if (m_view)
+            m_view->disableLayoutState();
+    }
+
+    ~LayoutStateDisabler()
+    {
+        if (m_view)
+            m_view->enableLayoutState();
+    }
+private:
+    RenderView* m_view;
+};
+
+class FragmentationDisabler {
+    WTF_MAKE_NONCOPYABLE(FragmentationDisabler);
+public:
+    FragmentationDisabler(RenderObject* root);
+    ~FragmentationDisabler();
+private:
+    RenderObject* m_root;
+    RenderObject::FlowThreadState m_flowThreadState;
+    bool m_fragmenting;
+#ifndef NDEBUG
+    LayoutState* m_layoutState;
+#endif
+};
+
+} // namespace WebCore
+
+#endif // RenderView_h
diff --git a/Source/core/rendering/RenderWidget.cpp b/Source/core/rendering/RenderWidget.cpp
new file mode 100644
index 0000000..936d7db
--- /dev/null
+++ b/Source/core/rendering/RenderWidget.cpp
@@ -0,0 +1,386 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2004, 2006, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2013 Google 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 "core/rendering/RenderWidget.h"
+
+#include "core/accessibility/AXObjectCache.h"
+#include "core/page/Frame.h"
+#include "core/page/animation/AnimationController.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/rendering/HitTestResult.h"
+#include "core/rendering/RenderCounter.h"
+#include "core/rendering/RenderLayer.h"
+#include "core/rendering/RenderLayerBacking.h"
+#include "core/rendering/RenderView.h"
+#include "core/rendering/RenderWidgetProtector.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;
+}
+
+unsigned WidgetHierarchyUpdatesSuspensionScope::s_widgetHierarchyUpdateSuspendCount = 0;
+
+WidgetHierarchyUpdatesSuspensionScope::WidgetToParentMap& WidgetHierarchyUpdatesSuspensionScope::widgetNewParentMap()
+{
+    DEFINE_STATIC_LOCAL(WidgetToParentMap, map, ());
+    return map;
+}
+
+void WidgetHierarchyUpdatesSuspensionScope::moveWidgets()
+{
+    WidgetToParentMap map = widgetNewParentMap();
+    widgetNewParentMap().clear();
+    WidgetToParentMap::iterator end = map.end();
+    for (WidgetToParentMap::iterator it = map.begin(); it != end; ++it) {
+        Widget* child = it->key.get();
+        ScrollView* currentParent = child->parent();
+        FrameView* newParent = it->value;
+        if (newParent != currentParent) {
+            if (currentParent)
+                currentParent->removeChild(child);
+            if (newParent)
+                newParent->addChild(child);
+        }
+    }
+}
+
+static void moveWidgetToParentSoon(Widget* child, FrameView* parent)
+{
+    if (!WidgetHierarchyUpdatesSuspensionScope::isSuspended()) {
+        if (parent)
+            parent->addChild(child);
+        else
+            child->removeFromParent();
+        return;
+    }
+    WidgetHierarchyUpdatesSuspensionScope::scheduleWidgetToMove(child, parent);
+}
+
+RenderWidget::RenderWidget(Element* element)
+    : RenderReplaced(element)
+    , m_widget(0)
+    , m_frameView(element->document()->view())
+    // Reference counting is used to prevent the widget from being
+    // destroyed while inside the Widget code, which might not be
+    // able to handle that.
+    , m_refCount(1)
+{
+    view()->addWidget(this);
+}
+
+void RenderWidget::willBeDestroyed()
+{
+    if (RenderView* v = view())
+        v->removeWidget(this);
+    
+    if (AXObjectCache* cache = document()->existingAXObjectCache()) {
+        cache->childrenChanged(this->parent());
+        cache->remove(this);
+    }
+
+    setWidget(0);
+
+    RenderReplaced::willBeDestroyed();
+}
+
+void RenderWidget::destroy()
+{
+    willBeDestroyed();
+
+    // Grab the arena from node()->document()->renderArena() before clearing the node pointer.
+    // Clear the node before deref-ing, as this may be deleted when deref is called.
+    RenderArena* arena = renderArena();
+    clearNode();
+    deref(arena);
+}
+
+RenderWidget::~RenderWidget()
+{
+    ASSERT(m_refCount <= 0);
+    clearWidget();
+}
+
+// Widgets are always placed on integer boundaries, so rounding the size is actually
+// the desired behavior. This function is here because it's otherwise seldom what we
+// want to do with a LayoutRect.
+static inline IntRect roundedIntRect(const LayoutRect& rect)
+{
+    return IntRect(roundedIntPoint(rect.location()), roundedIntSize(rect.size()));
+}
+
+bool RenderWidget::setWidgetGeometry(const LayoutRect& frame)
+{
+    if (!node())
+        return false;
+
+    IntRect clipRect = roundedIntRect(enclosingLayer()->childrenClipRect());
+    IntRect newFrame = roundedIntRect(frame);
+    bool clipChanged = m_clipRect != clipRect;
+    bool boundsChanged = m_widget->frameRect() != newFrame;
+
+    if (!boundsChanged && !clipChanged)
+        return false;
+
+    m_clipRect = clipRect;
+
+    RenderWidgetProtector protector(this);
+    RefPtr<Node> protectedNode(node());
+    m_widget->setFrameRect(newFrame);
+
+    if (clipChanged && !boundsChanged)
+        m_widget->clipRectChanged();
+    
+    if (hasLayer() && layer()->isComposited())
+        layer()->backing()->updateAfterWidgetResize();
+
+    return boundsChanged;
+}
+
+bool RenderWidget::updateWidgetGeometry()
+{
+    LayoutRect contentBox = contentBoxRect();
+    LayoutRect absoluteContentBox(localToAbsoluteQuad(FloatQuad(contentBox)).boundingBox());
+    if (m_widget->isFrameView()) {
+        contentBox.setLocation(absoluteContentBox.location());
+        return setWidgetGeometry(contentBox);
+    }
+
+    return setWidgetGeometry(absoluteContentBox);
+}
+
+void RenderWidget::setWidget(PassRefPtr<Widget> widget)
+{
+    if (widget == m_widget)
+        return;
+
+    if (m_widget) {
+        moveWidgetToParentSoon(m_widget.get(), 0);
+        widgetRendererMap().remove(m_widget.get());
+        clearWidget();
+    }
+    m_widget = widget;
+    if (m_widget) {
+        widgetRendererMap().add(m_widget.get(), this);
+        // If we've already received a layout, apply the calculated space to the
+        // widget immediately, but we have to have really been fully constructed (with a non-null
+        // style pointer).
+        if (style()) {
+            if (!needsLayout())
+                updateWidgetGeometry();
+
+            if (style()->visibility() != VISIBLE)
+                m_widget->hide();
+            else {
+                m_widget->show();
+                repaint();
+            }
+        }
+        moveWidgetToParentSoon(m_widget.get(), m_frameView);
+    }
+}
+
+void RenderWidget::layout()
+{
+    StackStats::LayoutCheckPoint layoutCheckPoint;
+    ASSERT(needsLayout());
+
+    setNeedsLayout(false);
+}
+
+void RenderWidget::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
+{
+    RenderReplaced::styleDidChange(diff, oldStyle);
+    if (m_widget) {
+        if (style()->visibility() != VISIBLE)
+            m_widget->hide();
+        else
+            m_widget->show();
+    }
+}
+
+void RenderWidget::paintContents(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    LayoutPoint adjustedPaintOffset = paintOffset + location();
+
+    // 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.
+    IntPoint widgetLocation = m_widget->frameRect().location();
+    IntPoint paintLocation(roundToInt(adjustedPaintOffset.x() + borderLeft() + paddingLeft()),
+        roundToInt(adjustedPaintOffset.y() + borderTop() + paddingTop()));
+    IntRect paintRect = paintInfo.rect;
+
+    IntSize widgetPaintOffset = paintLocation - widgetLocation;
+    // When painting widgets into compositing layers, tx and ty are relative to the enclosing compositing layer,
+    // not the root. In this case, shift the CTM and adjust the paintRect to be root-relative to fix plug-in drawing.
+    if (!widgetPaintOffset.isZero()) {
+        paintInfo.context->translate(widgetPaintOffset);
+        paintRect.move(-widgetPaintOffset);
+    }
+    m_widget->paint(paintInfo.context, paintRect);
+
+    if (!widgetPaintOffset.isZero())
+        paintInfo.context->translate(-widgetPaintOffset);
+
+    if (m_widget->isFrameView()) {
+        FrameView* frameView = toFrameView(m_widget.get());
+        bool runOverlapTests = !frameView->useSlowRepaintsIfNotOverlapped() || frameView->hasCompositedContent();
+        if (paintInfo.overlapTestRequests && runOverlapTests) {
+            ASSERT(!paintInfo.overlapTestRequests->contains(this));
+            paintInfo.overlapTestRequests->set(this, m_widget->frameRect());
+        }
+    }
+}
+
+void RenderWidget::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    if (!shouldPaint(paintInfo, paintOffset))
+        return;
+
+    LayoutPoint adjustedPaintOffset = paintOffset + location();
+
+    if (hasBoxDecorations() && (paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection))
+        paintBoxDecorations(paintInfo, adjustedPaintOffset);
+
+    if (paintInfo.phase == PaintPhaseMask) {
+        paintMask(paintInfo, adjustedPaintOffset);
+        return;
+    }
+
+    if ((paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) && hasOutline())
+        paintOutline(paintInfo, LayoutRect(adjustedPaintOffset, size()));
+
+    if (!m_frameView || paintInfo.phase != PaintPhaseForeground)
+        return;
+
+    if (style()->hasBorderRadius()) {
+        LayoutRect borderRect = LayoutRect(adjustedPaintOffset, size());
+
+        if (borderRect.isEmpty())
+            return;
+
+        // Push a clip if we have a border radius, since we want to round the foreground content that gets painted.
+        paintInfo.context->save();
+        RoundedRect roundedInnerRect = style()->getRoundedInnerBorderFor(borderRect,
+            paddingTop() + borderTop(), paddingBottom() + borderBottom(), paddingLeft() + borderLeft(), paddingRight() + borderRight(), true, true);
+        clipRoundedInnerRect(paintInfo.context, borderRect, roundedInnerRect);
+    }
+
+    if (m_widget)
+        paintContents(paintInfo, paintOffset);
+
+    if (style()->hasBorderRadius())
+        paintInfo.context->restore();
+
+    // Paint a partially transparent wash over selected widgets.
+    if (isSelected() && !document()->printing()) {
+        // FIXME: selectionRect() is in absolute, not painting coordinates.
+        paintInfo.context->fillRect(pixelSnappedIntRect(selectionRect()), selectionBackgroundColor(), style()->colorSpace());
+    }
+
+    if (hasLayer() && layer()->canResize())
+        layer()->paintResizer(paintInfo.context, roundedIntPoint(adjustedPaintOffset), paintInfo.rect);
+}
+
+void RenderWidget::setOverlapTestResult(bool isOverlapped)
+{
+    ASSERT(m_widget);
+    ASSERT(m_widget->isFrameView());
+    toFrameView(m_widget.get())->setIsOverlapped(isOverlapped);
+}
+
+void RenderWidget::deref(RenderArena *arena)
+{
+    if (--m_refCount <= 0)
+        arenaDelete(arena, this);
+}
+
+void RenderWidget::updateWidgetPosition()
+{
+    if (!m_widget || !node()) // Check the node in case destroy() has been called.
+        return;
+
+    bool boundsChanged = updateWidgetGeometry();
+    
+    // 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 = toFrameView(m_widget.get());
+        // Check the frame's page to make sure that the frame isn't in the process of being destroyed.
+        if ((boundsChanged || frameView->needsLayout()) && frameView->frame()->page())
+            frameView->layout();
+    }
+}
+
+void RenderWidget::widgetPositionsUpdated()
+{
+    if (!m_widget)
+        return;
+    m_widget->widgetPositionsUpdated();
+}
+
+IntRect RenderWidget::windowClipRect() const
+{
+    if (!m_frameView)
+        return IntRect();
+
+    return intersection(m_frameView->contentsToWindow(m_clipRect), m_frameView->windowClipRect());
+}
+
+void RenderWidget::clearWidget()
+{
+    m_widget = 0;
+}
+
+RenderWidget* RenderWidget::find(const Widget* widget)
+{
+    return widgetRendererMap().get(widget);
+}
+
+bool RenderWidget::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction action)
+{
+    bool hadResult = result.innerNode();
+    bool inside = RenderReplaced::nodeAtPoint(request, result, locationInContainer, accumulatedOffset, action);
+
+    // Check to see if we are really over the widget itself (and not just in the border/padding area).
+    if ((inside || result.isRectBasedTest()) && !hadResult && result.innerNode() == node())
+        result.setIsOverWidget(contentBoxRect().contains(result.localPoint()));
+    return inside;
+}
+
+CursorDirective RenderWidget::getCursor(const LayoutPoint& point, Cursor& cursor) const
+{
+    if (widget() && widget()->isPluginView()) {
+        // A plug-in is responsible for setting the cursor when the pointer is over it.
+        return DoNotSetCursor;
+    }
+    return RenderReplaced::getCursor(point, cursor);
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RenderWidget.h b/Source/core/rendering/RenderWidget.h
new file mode 100644
index 0000000..3e6d1a3
--- /dev/null
+++ b/Source/core/rendering/RenderWidget.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 1999 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2009, 2010 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 RenderWidget_h
+#define RenderWidget_h
+
+#include "core/platform/Widget.h"
+#include "core/rendering/OverlapTestRequestClient.h"
+#include "core/rendering/RenderReplaced.h"
+
+namespace WebCore {
+
+class WidgetHierarchyUpdatesSuspensionScope {
+public:
+    WidgetHierarchyUpdatesSuspensionScope()
+    {
+        s_widgetHierarchyUpdateSuspendCount++;
+    }
+    ~WidgetHierarchyUpdatesSuspensionScope()
+    {
+        ASSERT(s_widgetHierarchyUpdateSuspendCount);
+        if (s_widgetHierarchyUpdateSuspendCount == 1)
+            moveWidgets();
+        s_widgetHierarchyUpdateSuspendCount--;
+    }
+
+    static bool isSuspended() { return s_widgetHierarchyUpdateSuspendCount; }
+    static void scheduleWidgetToMove(Widget* widget, FrameView* frame) { widgetNewParentMap().set(widget, frame); }
+
+private:
+    typedef HashMap<RefPtr<Widget>, FrameView*> WidgetToParentMap;
+    static WidgetToParentMap& widgetNewParentMap();
+
+    void moveWidgets();
+
+    static unsigned s_widgetHierarchyUpdateSuspendCount;
+};
+    
+class RenderWidget : public RenderReplaced, private OverlapTestRequestClient {
+public:
+    virtual ~RenderWidget();
+
+    Widget* widget() const { return m_widget.get(); }
+    virtual void setWidget(PassRefPtr<Widget>);
+
+    static RenderWidget* find(const Widget*);
+
+    void updateWidgetPosition();
+    void widgetPositionsUpdated();
+    IntRect windowClipRect() const;
+
+    RenderArena* ref() { ++m_refCount; return renderArena(); }
+    void deref(RenderArena*);
+
+protected:
+    RenderWidget(Element*);
+
+    FrameView* frameView() const { return m_frameView; }
+
+    void clearWidget();
+
+    virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE FINAL;
+    virtual void layout();
+    virtual void paint(PaintInfo&, const LayoutPoint&);
+    virtual CursorDirective getCursor(const LayoutPoint&, Cursor&) const;
+    virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
+
+    virtual void paintContents(PaintInfo&, const LayoutPoint&);
+
+private:
+    virtual bool isWidget() const OVERRIDE FINAL { return true; }
+
+    virtual void willBeDestroyed() OVERRIDE FINAL;
+    virtual void destroy() OVERRIDE FINAL;
+    virtual void setOverlapTestResult(bool) OVERRIDE FINAL;
+
+    bool setWidgetGeometry(const LayoutRect&);
+    bool updateWidgetGeometry();
+
+    RefPtr<Widget> m_widget;
+    FrameView* m_frameView;
+    IntRect m_clipRect; // The rectangle needs to remain correct after scrolling, so it is stored in content view coordinates, and not clipped to window.
+    int m_refCount;
+};
+
+inline RenderWidget* toRenderWidget(RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isWidget());
+    return static_cast<RenderWidget*>(object);
+}
+
+inline const RenderWidget* toRenderWidget(const RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isWidget());
+    return static_cast<const RenderWidget*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderWidget(const RenderWidget*);
+
+} // namespace WebCore
+
+#endif // RenderWidget_h
diff --git a/Source/core/rendering/RenderWidgetProtector.h b/Source/core/rendering/RenderWidgetProtector.h
new file mode 100644
index 0000000..2a65ab4
--- /dev/null
+++ b/Source/core/rendering/RenderWidgetProtector.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2009 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 RenderWidgetProtector_h
+#define RenderWidgetProtector_h
+
+#include "core/rendering/RenderWidget.h"
+
+namespace WebCore {
+
+class RenderWidgetProtector {
+    WTF_MAKE_NONCOPYABLE(RenderWidgetProtector);
+public:
+    explicit RenderWidgetProtector(RenderWidget* object)
+        : m_object(object)
+        , m_arena(object->ref())
+    {
+    }
+
+    ~RenderWidgetProtector()
+    {
+        m_object->deref(m_arena);
+    }
+
+private:
+    RenderWidget* m_object;
+    RenderArena* m_arena;
+};
+
+}
+
+#endif // RenderWidgetProtector_h
diff --git a/Source/core/rendering/RenderWordBreak.cpp b/Source/core/rendering/RenderWordBreak.cpp
new file mode 100644
index 0000000..297c4d6
--- /dev/null
+++ b/Source/core/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 "core/rendering/RenderWordBreak.h"
+
+#include "core/html/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/Source/core/rendering/RenderWordBreak.h b/Source/core/rendering/RenderWordBreak.h
new file mode 100644
index 0000000..24f3773
--- /dev/null
+++ b/Source/core/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 "core/rendering/RenderText.h"
+
+namespace WebCore {
+
+class HTMLElement;
+
+class RenderWordBreak FINAL : public RenderText {
+public:
+    explicit RenderWordBreak(HTMLElement*);
+
+    virtual const char* renderName() const;
+    virtual bool isWordBreak() const;
+};
+
+}
+
+#endif
diff --git a/Source/core/rendering/RootInlineBox.cpp b/Source/core/rendering/RootInlineBox.cpp
new file mode 100644
index 0000000..edeb3e0
--- /dev/null
+++ b/Source/core/rendering/RootInlineBox.cpp
@@ -0,0 +1,995 @@
+/*
+ * 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 "core/rendering/RootInlineBox.h"
+
+#include "core/dom/Document.h"
+#include "core/page/Chrome.h"
+#include "core/page/ChromeClient.h"
+#include "core/page/Frame.h"
+#include "core/page/Page.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/platform/text/BidiResolver.h"
+#include "core/rendering/EllipsisBox.h"
+#include "core/rendering/HitTestResult.h"
+#include "core/rendering/InlineTextBox.h"
+#include "core/rendering/PaintInfo.h"
+#include "core/rendering/RenderArena.h"
+#include "core/rendering/RenderBlock.h"
+#include "core/rendering/RenderFlowThread.h"
+#include "core/rendering/RenderView.h"
+#include "core/rendering/VerticalPositionCache.h"
+#include <wtf/unicode/Unicode.h>
+
+using namespace std;
+
+namespace WebCore {
+    
+typedef WTF::HashMap<const RootInlineBox*, EllipsisBox*> EllipsisBoxMap;
+static EllipsisBoxMap* gEllipsisBoxMap = 0;
+
+RootInlineBox::RootInlineBox(RenderBlock* block)
+    : InlineFlowBox(block)
+    , m_lineBreakPos(0)
+    , m_lineBreakObj(0)
+    , m_lineTop(0)
+    , m_lineBottom(0)
+    , m_lineTopWithLeading(0)
+    , m_lineBottomWithLeading(0)
+#if ENABLE(CSS3_TEXT)
+    , m_maxLogicalTop(0)
+#endif // CSS3_TEXT
+{
+    setIsHorizontal(block->isHorizontalWritingMode());
+}
+
+
+void RootInlineBox::destroy(RenderArena* arena)
+{
+    detachEllipsisBox(arena);
+    InlineFlowBox::destroy(arena);
+}
+
+void RootInlineBox::detachEllipsisBox(RenderArena* arena)
+{
+    if (hasEllipsisBox()) {
+        EllipsisBox* box = gEllipsisBoxMap->take(this);
+        box->setParent(0);
+        box->destroy(arena);
+        setHasEllipsisBox(false);
+    }
+}
+
+RenderLineBoxList* RootInlineBox::rendererLineBoxes() const
+{
+    return block()->lineBoxes();
+}
+
+void RootInlineBox::clearTruncation()
+{
+    if (hasEllipsisBox()) {
+        detachEllipsisBox(renderer()->renderArena());
+        InlineFlowBox::clearTruncation();
+    }
+}
+
+bool RootInlineBox::isHyphenated() const
+{
+    for (InlineBox* box = firstLeafChild(); box; box = box->nextLeafChild()) {
+        if (box->isInlineTextBox()) {
+            if (toInlineTextBox(box)->hasHyphen())
+                return true;
+        }
+    }
+
+    return false;
+}
+
+int RootInlineBox::baselinePosition(FontBaseline baselineType) const
+{
+    return boxModelObject()->baselinePosition(baselineType, isFirstLineStyle(), isHorizontal() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes);
+}
+
+LayoutUnit RootInlineBox::lineHeight() const
+{
+    return boxModelObject()->lineHeight(isFirstLineStyle(), isHorizontal() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes);
+}
+
+bool RootInlineBox::lineCanAccommodateEllipsis(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 (logicalWidth() - 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);
+}
+
+float RootInlineBox::placeEllipsis(const AtomicString& ellipsisStr,  bool ltr, float blockLeftEdge, float blockRightEdge, float ellipsisWidth,
+                                  InlineBox* markupBox)
+{
+    // Create an ellipsis box.
+    EllipsisBox* ellipsisBox = new (renderer()->renderArena()) EllipsisBox(renderer(), ellipsisStr, this,
+                                                              ellipsisWidth - (markupBox ? markupBox->logicalWidth() : 0), logicalHeight(),
+                                                              y(), !prevRootBox(), isHorizontal(), markupBox);
+    
+    if (!gEllipsisBoxMap)
+        gEllipsisBoxMap = new EllipsisBoxMap();
+    gEllipsisBoxMap->add(this, ellipsisBox);
+    setHasEllipsisBox(true);
+
+    // FIXME: Do we need an RTL version of this?
+    if (ltr && (x() + logicalWidth() + ellipsisWidth) <= blockRightEdge) {
+        ellipsisBox->setX(x() + logicalWidth());
+        return logicalWidth() + ellipsisWidth;
+    }
+
+    // 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;
+    float truncatedWidth = 0;
+    float position = placeEllipsisBox(ltr, blockLeftEdge, blockRightEdge, ellipsisWidth, truncatedWidth, foundBox);
+    ellipsisBox->setX(position);
+    return truncatedWidth;
+}
+
+float RootInlineBox::placeEllipsisBox(bool ltr, float blockLeftEdge, float blockRightEdge, float ellipsisWidth, float &truncatedWidth, bool& foundBox)
+{
+    float result = InlineFlowBox::placeEllipsisBox(ltr, blockLeftEdge, blockRightEdge, ellipsisWidth, truncatedWidth, foundBox);
+    if (result == -1) {
+        result = ltr ? blockRightEdge - ellipsisWidth : blockLeftEdge;
+        truncatedWidth = blockRightEdge - blockLeftEdge;
+    }
+    return result;
+}
+
+void RootInlineBox::paintEllipsisBox(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit lineTop, LayoutUnit lineBottom) const
+{
+    if (hasEllipsisBox() && paintInfo.shouldPaintWithinRoot(renderer()) && renderer()->style()->visibility() == VISIBLE
+            && paintInfo.phase == PaintPhaseForeground)
+        ellipsisBox()->paint(paintInfo, paintOffset, lineTop, lineBottom);
+}
+
+void RootInlineBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit lineTop, LayoutUnit lineBottom)
+{
+    InlineFlowBox::paint(paintInfo, paintOffset, lineTop, lineBottom);
+    paintEllipsisBox(paintInfo, paintOffset, lineTop, lineBottom);
+}
+
+bool RootInlineBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom)
+{
+    if (hasEllipsisBox() && visibleToHitTestRequest(request)) {
+        if (ellipsisBox()->nodeAtPoint(request, result, locationInContainer, accumulatedOffset, lineTop, lineBottom)) {
+            renderer()->updateHitTestResult(result, locationInContainer.point() - toLayoutSize(accumulatedOffset));
+            return true;
+        }
+    }
+    return InlineFlowBox::nodeAtPoint(request, result, locationInContainer, accumulatedOffset, lineTop, lineBottom);
+}
+
+void RootInlineBox::adjustPosition(float dx, float dy)
+{
+    InlineFlowBox::adjustPosition(dx, dy);
+    LayoutUnit blockDirectionDelta = isHorizontal() ? dy : dx; // The block direction delta is a LayoutUnit.
+    m_lineTop += blockDirectionDelta;
+    m_lineBottom += blockDirectionDelta;
+    m_lineTopWithLeading += blockDirectionDelta;
+    m_lineBottomWithLeading += blockDirectionDelta;
+    if (hasEllipsisBox())
+        ellipsisBox()->adjustPosition(dx, dy);
+}
+
+void RootInlineBox::childRemoved(InlineBox* box)
+{
+    if (box->renderer() == m_lineBreakObj)
+        setLineBreakInfo(0, 0, BidiStatus());
+
+    for (RootInlineBox* prev = prevRootBox(); prev && prev->lineBreakObj() == box->renderer(); prev = prev->prevRootBox()) {
+        prev->setLineBreakInfo(0, 0, BidiStatus());
+        prev->markDirty();
+    }
+}
+
+RenderRegion* RootInlineBox::containingRegion() const
+{
+    RenderRegion* region = m_fragmentationData ? m_fragmentationData->m_containingRegion : 0;
+
+#ifndef NDEBUG
+    if (region) {
+        RenderFlowThread* flowThread = block()->flowThreadContainingBlock();
+        const RenderRegionList& regionList = flowThread->renderRegionList();
+        ASSERT(regionList.contains(region));
+    }
+#endif
+
+    return region;
+}
+
+void RootInlineBox::setContainingRegion(RenderRegion* region)
+{
+    ASSERT(!isDirty());
+    ASSERT(block()->flowThreadContainingBlock());
+    LineFragmentationData* fragmentationData  = ensureLineFragmentationData();
+    fragmentationData->m_containingRegion = region;
+}
+
+LayoutUnit RootInlineBox::alignBoxesInBlockDirection(LayoutUnit heightOfBlock, GlyphOverflowAndFallbackFontsMap& textBoxDataMap, VerticalPositionCache& verticalPositionCache)
+{
+#if ENABLE(SVG)
+    // SVG will handle vertical alignment on its own.
+    if (isSVGRootInlineBox())
+        return 0;
+
+    // FIXME: figure out how to call computeMaxLogicalTop() when SVG is enabled.
+#endif
+
+    LayoutUnit maxPositionTop = 0;
+    LayoutUnit maxPositionBottom = 0;
+    int maxAscent = 0;
+    int maxDescent = 0;
+    bool setMaxAscent = false;
+    bool setMaxDescent = false;
+
+    // Figure out if we're in no-quirks mode.
+    bool noQuirksMode = renderer()->document()->inNoQuirksMode();
+
+    m_baselineType = requiresIdeographicBaseline(textBoxDataMap) ? IdeographicBaseline : AlphabeticBaseline;
+
+    computeLogicalBoxHeights(this, maxPositionTop, maxPositionBottom, maxAscent, maxDescent, setMaxAscent, setMaxDescent, noQuirksMode,
+                             textBoxDataMap, baselineType(), verticalPositionCache);
+
+    if (maxAscent + maxDescent < max(maxPositionTop, maxPositionBottom))
+        adjustMaxAscentAndDescent(maxAscent, maxDescent, maxPositionTop, maxPositionBottom);
+
+    LayoutUnit maxHeight = maxAscent + maxDescent;
+    LayoutUnit lineTop = heightOfBlock;
+    LayoutUnit lineBottom = heightOfBlock;
+    LayoutUnit lineTopIncludingMargins = heightOfBlock;
+    LayoutUnit lineBottomIncludingMargins = heightOfBlock;
+    bool setLineTop = false;
+    bool hasAnnotationsBefore = false;
+    bool hasAnnotationsAfter = false;
+    placeBoxesInBlockDirection(heightOfBlock, maxHeight, maxAscent, noQuirksMode, lineTop, lineBottom, setLineTop,
+                               lineTopIncludingMargins, lineBottomIncludingMargins, hasAnnotationsBefore, hasAnnotationsAfter, baselineType());
+    m_hasAnnotationsBefore = hasAnnotationsBefore;
+    m_hasAnnotationsAfter = hasAnnotationsAfter;
+    
+    maxHeight = max<LayoutUnit>(0, maxHeight); // FIXME: Is this really necessary?
+
+    setLineTopBottomPositions(lineTop, lineBottom, heightOfBlock, heightOfBlock + maxHeight);
+    setPaginatedLineWidth(block()->availableLogicalWidthForContent(heightOfBlock));
+
+    LayoutUnit annotationsAdjustment = beforeAnnotationsAdjustment();
+    if (annotationsAdjustment) {
+        // FIXME: Need to handle pagination here. We might have to move to the next page/column as a result of the
+        // ruby expansion.
+        adjustBlockDirectionPosition(annotationsAdjustment);
+        heightOfBlock += annotationsAdjustment;
+    }
+
+    LayoutUnit gridSnapAdjustment = lineSnapAdjustment();
+    if (gridSnapAdjustment) {
+        adjustBlockDirectionPosition(gridSnapAdjustment);
+        heightOfBlock += gridSnapAdjustment;
+    }
+
+#if ENABLE(CSS3_TEXT)
+    m_maxLogicalTop = 0;
+    computeMaxLogicalTop(m_maxLogicalTop);
+#endif // CSS3_TEXT
+
+    return heightOfBlock + maxHeight;
+}
+
+LayoutUnit RootInlineBox::beforeAnnotationsAdjustment() const
+{
+    LayoutUnit result = 0;
+
+    if (!renderer()->style()->isFlippedLinesWritingMode()) {
+        // Annotations under the previous line may push us down.
+        if (prevRootBox() && prevRootBox()->hasAnnotationsAfter())
+            result = prevRootBox()->computeUnderAnnotationAdjustment(lineTop());
+
+        if (!hasAnnotationsBefore())
+            return result;
+
+        // Annotations over this line may push us further down.
+        LayoutUnit highestAllowedPosition = prevRootBox() ? min(prevRootBox()->lineBottom(), lineTop()) + result : static_cast<LayoutUnit>(block()->borderBefore());
+        result = computeOverAnnotationAdjustment(highestAllowedPosition);
+    } else {
+        // Annotations under this line may push us up.
+        if (hasAnnotationsBefore())
+            result = computeUnderAnnotationAdjustment(prevRootBox() ? prevRootBox()->lineBottom() : static_cast<LayoutUnit>(block()->borderBefore()));
+
+        if (!prevRootBox() || !prevRootBox()->hasAnnotationsAfter())
+            return result;
+
+        // We have to compute the expansion for annotations over the previous line to see how much we should move.
+        LayoutUnit lowestAllowedPosition = max(prevRootBox()->lineBottom(), lineTop()) - result;
+        result = prevRootBox()->computeOverAnnotationAdjustment(lowestAllowedPosition);
+    }
+
+    return result;
+}
+
+LayoutUnit RootInlineBox::lineSnapAdjustment(LayoutUnit delta) const
+{
+    // If our block doesn't have snapping turned on, do nothing.
+    // FIXME: Implement bounds snapping.
+    if (block()->style()->lineSnap() == LineSnapNone)
+        return 0;
+
+    // Get the current line grid and offset.
+    LayoutState* layoutState = block()->view()->layoutState();
+    RenderBlock* lineGrid = layoutState->lineGrid();
+    LayoutSize lineGridOffset = layoutState->lineGridOffset();
+    if (!lineGrid || lineGrid->style()->writingMode() != block()->style()->writingMode())
+        return 0;
+
+    // Get the hypothetical line box used to establish the grid.
+    RootInlineBox* lineGridBox = lineGrid->lineGridBox();
+    if (!lineGridBox)
+        return 0;
+    
+    LayoutUnit lineGridBlockOffset = lineGrid->isHorizontalWritingMode() ? lineGridOffset.height() : lineGridOffset.width();
+    LayoutUnit blockOffset = block()->isHorizontalWritingMode() ? layoutState->layoutOffset().height() : layoutState->layoutOffset().width();
+
+    // Now determine our position on the grid. Our baseline needs to be adjusted to the nearest baseline multiple
+    // as established by the line box.
+    // FIXME: Need to handle crazy line-box-contain values that cause the root line box to not be considered. I assume
+    // the grid should honor line-box-contain.
+    LayoutUnit gridLineHeight = lineGridBox->lineBottomWithLeading() - lineGridBox->lineTopWithLeading();
+    if (!gridLineHeight)
+        return 0;
+
+    LayoutUnit lineGridFontAscent = lineGrid->style()->fontMetrics().ascent(baselineType());
+    LayoutUnit lineGridFontHeight = lineGridBox->logicalHeight();
+    LayoutUnit firstTextTop = lineGridBlockOffset + lineGridBox->logicalTop();
+    LayoutUnit firstLineTopWithLeading = lineGridBlockOffset + lineGridBox->lineTopWithLeading();
+    LayoutUnit firstBaselinePosition = firstTextTop + lineGridFontAscent;
+
+    LayoutUnit currentTextTop = blockOffset + logicalTop() + delta;
+    LayoutUnit currentFontAscent = block()->style()->fontMetrics().ascent(baselineType());
+    LayoutUnit currentBaselinePosition = currentTextTop + currentFontAscent;
+
+    LayoutUnit lineGridPaginationOrigin = isHorizontal() ? layoutState->lineGridPaginationOrigin().height() : layoutState->lineGridPaginationOrigin().width();
+
+    // If we're paginated, see if we're on a page after the first one. If so, the grid resets on subsequent pages.
+    // FIXME: If the grid is an ancestor of the pagination establisher, then this is incorrect.
+    LayoutUnit pageLogicalTop = 0;
+    if (layoutState->isPaginated() && layoutState->pageLogicalHeight()) {
+        pageLogicalTop = block()->pageLogicalTopForOffset(lineTopWithLeading() + delta);
+        if (pageLogicalTop > firstLineTopWithLeading)
+            firstTextTop = pageLogicalTop + lineGridBox->logicalTop() - lineGrid->borderBefore() - lineGrid->paddingBefore() + lineGridPaginationOrigin;
+    }
+
+    if (block()->style()->lineSnap() == LineSnapContain) {
+        // Compute the desired offset from the text-top of a grid line.
+        // Look at our height (logicalHeight()).
+        // Look at the total available height. It's going to be (textBottom - textTop) + (n-1)*(multiple with leading)
+        // where n is number of grid lines required to enclose us.
+        if (logicalHeight() <= lineGridFontHeight)
+            firstTextTop += (lineGridFontHeight - logicalHeight()) / 2;
+        else {
+            LayoutUnit numberOfLinesWithLeading = ceilf(static_cast<float>(logicalHeight() - lineGridFontHeight) / gridLineHeight);
+            LayoutUnit totalHeight = lineGridFontHeight + numberOfLinesWithLeading * gridLineHeight;
+            firstTextTop += (totalHeight - logicalHeight()) / 2;
+        }
+        firstBaselinePosition = firstTextTop + currentFontAscent;
+    } else
+        firstBaselinePosition = firstTextTop + lineGridFontAscent;
+
+    // If we're above the first line, just push to the first line.
+    if (currentBaselinePosition < firstBaselinePosition)
+        return delta + firstBaselinePosition - currentBaselinePosition;
+
+    // Otherwise we're in the middle of the grid somewhere. Just push to the next line.
+    LayoutUnit baselineOffset = currentBaselinePosition - firstBaselinePosition;
+    LayoutUnit remainder = roundToInt(baselineOffset) % roundToInt(gridLineHeight);
+    LayoutUnit result = delta;
+    if (remainder)
+        result += gridLineHeight - remainder;
+
+    // If we aren't paginated we can return the result.
+    if (!layoutState->isPaginated() || !layoutState->pageLogicalHeight() || result == delta)
+        return result;
+    
+    // We may end up shifted to a new page. We need to do a re-snap when that happens.
+    LayoutUnit newPageLogicalTop = block()->pageLogicalTopForOffset(lineBottomWithLeading() + result);
+    if (newPageLogicalTop == pageLogicalTop)
+        return result;
+    
+    // Put ourselves at the top of the next page to force a snap onto the new grid established by that page.
+    return lineSnapAdjustment(newPageLogicalTop - (blockOffset + lineTopWithLeading()));
+}
+
+GapRects RootInlineBox::lineSelectionGap(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock, 
+                                         LayoutUnit selTop, LayoutUnit selHeight, const PaintInfo* paintInfo)
+{
+    RenderObject::SelectionState lineState = selectionState();
+
+    bool leftGap, rightGap;
+    block()->getSelectionGapInfo(lineState, leftGap, rightGap);
+
+    GapRects result;
+
+    InlineBox* firstBox = firstSelectedBox();
+    InlineBox* lastBox = lastSelectedBox();
+    if (leftGap)
+        result.uniteLeft(block()->logicalLeftSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock,
+                                                          firstBox->parent()->renderer(), firstBox->logicalLeft(), selTop, selHeight, paintInfo));
+    if (rightGap)
+        result.uniteRight(block()->logicalRightSelectionGap(rootBlock, rootBlockPhysicalPosition, offsetFromRootBlock,
+                                                            lastBox->parent()->renderer(), lastBox->logicalRight(), selTop, selHeight, paintInfo));
+
+    // When dealing with bidi text, a non-contiguous selection region is possible.
+    // e.g. The logical text aaaAAAbbb (capitals denote RTL text and non-capitals LTR) is layed out
+    // visually as 3 text runs |aaa|bbb|AAA| if we select 4 characters from the start of the text the
+    // selection will look like (underline denotes selection):
+    // |aaa|bbb|AAA|
+    //  ___       _
+    // We can see that the |bbb| run is not part of the selection while the runs around it are.
+    if (firstBox && firstBox != lastBox) {
+        // Now fill in any gaps on the line that occurred between two selected elements.
+        LayoutUnit lastLogicalLeft = firstBox->logicalRight();
+        bool isPreviousBoxSelected = firstBox->selectionState() != RenderObject::SelectionNone;
+        for (InlineBox* box = firstBox->nextLeafChild(); box; box = box->nextLeafChild()) {
+            if (box->selectionState() != RenderObject::SelectionNone) {
+                LayoutRect logicalRect(lastLogicalLeft, selTop, box->logicalLeft() - lastLogicalLeft, selHeight);
+                logicalRect.move(renderer()->isHorizontalWritingMode() ? offsetFromRootBlock : LayoutSize(offsetFromRootBlock.height(), offsetFromRootBlock.width()));
+                LayoutRect gapRect = rootBlock->logicalRectToPhysicalRect(rootBlockPhysicalPosition, logicalRect);
+                if (isPreviousBoxSelected && gapRect.width() > 0 && gapRect.height() > 0) {
+                    if (paintInfo && box->parent()->renderer()->style()->visibility() == VISIBLE)
+                        paintInfo->context->fillRect(gapRect, box->parent()->renderer()->selectionBackgroundColor(), box->parent()->renderer()->style()->colorSpace());
+                    // VisibleSelection may be non-contiguous, see comment above.
+                    result.uniteCenter(gapRect);
+                }
+                lastLogicalLeft = box->logicalRight();
+            }
+            if (box == lastBox)
+                break;
+            isPreviousBoxSelected = box->selectionState() != RenderObject::SelectionNone;
+        }
+    }
+
+    return result;
+}
+
+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;
+        else if (boxState == RenderObject::SelectionNone && state == RenderObject::SelectionStart) {
+            // We are past the end of the selection.
+            state = RenderObject::SelectionBoth;
+        }
+        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;
+}
+
+LayoutUnit RootInlineBox::selectionTop() const
+{
+    LayoutUnit selectionTop = m_lineTop;
+
+    if (m_hasAnnotationsBefore)
+        selectionTop -= !renderer()->style()->isFlippedLinesWritingMode() ? computeOverAnnotationAdjustment(m_lineTop) : computeUnderAnnotationAdjustment(m_lineTop);
+
+    if (renderer()->style()->isFlippedLinesWritingMode())
+        return selectionTop;
+
+    LayoutUnit prevBottom = prevRootBox() ? prevRootBox()->selectionBottom() : block()->borderBefore() + block()->paddingBefore();
+    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 if the offsets are greater on both sides.
+        LayoutUnit prevLeft = block()->logicalLeftOffsetForLine(prevBottom, false);
+        LayoutUnit prevRight = block()->logicalRightOffsetForLine(prevBottom, false);
+        LayoutUnit newLeft = block()->logicalLeftOffsetForLine(selectionTop, false);
+        LayoutUnit newRight = block()->logicalRightOffsetForLine(selectionTop, false);
+        if (prevLeft > newLeft || prevRight < newRight)
+            return selectionTop;
+    }
+
+    return prevBottom;
+}
+
+LayoutUnit RootInlineBox::selectionTopAdjustedForPrecedingBlock() const
+{
+    LayoutUnit top = selectionTop();
+
+    RenderObject::SelectionState blockSelectionState = root()->block()->selectionState();
+    if (blockSelectionState != RenderObject::SelectionInside && blockSelectionState != RenderObject::SelectionEnd)
+        return top;
+
+    LayoutSize offsetToBlockBefore;
+    if (RenderBlock* block = root()->block()->blockBeforeWithinSelectionRoot(offsetToBlockBefore)) {
+        if (RootInlineBox* lastLine = block->lastRootBox()) {
+            RenderObject::SelectionState lastLineSelectionState = lastLine->selectionState();
+            if (lastLineSelectionState != RenderObject::SelectionInside && lastLineSelectionState != RenderObject::SelectionStart)
+                return top;
+
+            LayoutUnit lastLineSelectionBottom = lastLine->selectionBottom() + offsetToBlockBefore.height();
+            top = max(top, lastLineSelectionBottom);
+        }
+    }
+
+    return top;
+}
+
+LayoutUnit RootInlineBox::selectionBottom() const
+{
+    LayoutUnit selectionBottom = m_lineBottom;
+
+    if (m_hasAnnotationsAfter)
+        selectionBottom += !renderer()->style()->isFlippedLinesWritingMode() ? computeUnderAnnotationAdjustment(m_lineBottom) : computeOverAnnotationAdjustment(m_lineBottom);
+
+    if (!renderer()->style()->isFlippedLinesWritingMode() || !nextRootBox())
+        return selectionBottom;
+
+    LayoutUnit nextTop = nextRootBox()->selectionTop();
+    if (nextTop > selectionBottom && block()->containsFloats()) {
+        // The next line has actually been moved further over, 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 next
+        // line's top if the offsets are greater on both sides.
+        LayoutUnit nextLeft = block()->logicalLeftOffsetForLine(nextTop, false);
+        LayoutUnit nextRight = block()->logicalRightOffsetForLine(nextTop, false);
+        LayoutUnit newLeft = block()->logicalLeftOffsetForLine(selectionBottom, false);
+        LayoutUnit newRight = block()->logicalRightOffsetForLine(selectionBottom, false);
+        if (nextLeft > newLeft || nextRight < newRight)
+            return selectionBottom;
+    }
+
+    return nextTop;
+}
+
+int RootInlineBox::blockDirectionPointInLine() const
+{
+    return !block()->style()->isFlippedBlocksWritingMode() ? max(lineTop(), selectionTop()) : min(lineBottom(), selectionBottom());
+}
+
+RenderBlock* RootInlineBox::block() const
+{
+    return toRenderBlock(renderer());
+}
+
+static bool isEditableLeaf(InlineBox* leaf)
+{
+    return leaf && leaf->renderer() && leaf->renderer()->node() && leaf->renderer()->node()->rendererIsEditable();
+}
+
+InlineBox* RootInlineBox::closestLeafChildForPoint(const IntPoint& pointInContents, bool onlyEditableLeaves)
+{
+    return closestLeafChildForLogicalLeftPosition(block()->isHorizontalWritingMode() ? pointInContents.x() : pointInContents.y(), onlyEditableLeaves);
+}
+
+InlineBox* RootInlineBox::closestLeafChildForLogicalLeftPosition(int leftPosition, bool onlyEditableLeaves)
+{
+    InlineBox* firstLeaf = firstLeafChild();
+    InlineBox* lastLeaf = lastLeafChild();
+
+    if (firstLeaf != lastLeaf) {
+        if (firstLeaf->isLineBreak())
+            firstLeaf = firstLeaf->nextLeafChildIgnoringLineBreak();
+        else if (lastLeaf->isLineBreak())
+            lastLeaf = lastLeaf->prevLeafChildIgnoringLineBreak();
+    }
+
+    if (firstLeaf == lastLeaf && (!onlyEditableLeaves || isEditableLeaf(firstLeaf)))
+        return firstLeaf;
+
+    // Avoid returning a list marker when possible.
+    if (leftPosition <= firstLeaf->logicalLeft() && !firstLeaf->renderer()->isListMarker() && (!onlyEditableLeaves || isEditableLeaf(firstLeaf)))
+        // The leftPosition coordinate is less or equal to left edge of the firstLeaf.
+        // Return it.
+        return firstLeaf;
+
+    if (leftPosition >= lastLeaf->logicalRight() && !lastLeaf->renderer()->isListMarker() && (!onlyEditableLeaves || isEditableLeaf(lastLeaf)))
+        // The leftPosition 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->nextLeafChildIgnoringLineBreak()) {
+        if (!leaf->renderer()->isListMarker() && (!onlyEditableLeaves || isEditableLeaf(leaf))) {
+            closestLeaf = leaf;
+            if (leftPosition < leaf->logicalRight())
+                // 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(static_cast<WTF::Unicode::Direction>(m_lineBreakBidiStatusEor), static_cast<WTF::Unicode::Direction>(m_lineBreakBidiStatusLastStrong), static_cast<WTF::Unicode::Direction>(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 (!hasEllipsisBox())
+        return 0;
+    return gEllipsisBoxMap->get(this);
+}
+
+void RootInlineBox::removeLineBoxFromRenderObject()
+{
+    block()->lineBoxes()->removeLineBox(this);
+}
+
+void RootInlineBox::extractLineBoxFromRenderObject()
+{
+    block()->lineBoxes()->extractLineBox(this);
+}
+
+void RootInlineBox::attachLineBoxToRenderObject()
+{
+    block()->lineBoxes()->attachLineBox(this);
+}
+
+LayoutRect RootInlineBox::paddedLayoutOverflowRect(LayoutUnit endPadding) const
+{
+    LayoutRect lineLayoutOverflow = layoutOverflowRect(lineTop(), lineBottom());
+    if (!endPadding)
+        return lineLayoutOverflow;
+    
+    // FIXME: Audit whether to use pixel snapped values when not using integers for layout: https://bugs.webkit.org/show_bug.cgi?id=63656
+    if (isHorizontal()) {
+        if (isLeftToRightDirection())
+            lineLayoutOverflow.shiftMaxXEdgeTo(max<LayoutUnit>(lineLayoutOverflow.maxX(), pixelSnappedLogicalRight() + endPadding));
+        else
+            lineLayoutOverflow.shiftXEdgeTo(min<LayoutUnit>(lineLayoutOverflow.x(), pixelSnappedLogicalLeft() - endPadding));
+    } else {
+        if (isLeftToRightDirection())
+            lineLayoutOverflow.shiftMaxYEdgeTo(max<LayoutUnit>(lineLayoutOverflow.maxY(), pixelSnappedLogicalRight() + endPadding));
+        else
+            lineLayoutOverflow.shiftYEdgeTo(min<LayoutUnit>(lineLayoutOverflow.y(), pixelSnappedLogicalLeft() - endPadding));
+    }
+    
+    return lineLayoutOverflow;
+}
+
+static void setAscentAndDescent(int& ascent, int& descent, int newAscent, int newDescent, bool& ascentDescentSet)
+{
+    if (!ascentDescentSet) {
+        ascentDescentSet = true;
+        ascent = newAscent;
+        descent = newDescent;
+    } else {
+        ascent = max(ascent, newAscent);
+        descent = max(descent, newDescent);
+    }
+}
+
+void RootInlineBox::ascentAndDescentForBox(InlineBox* box, GlyphOverflowAndFallbackFontsMap& textBoxDataMap, int& ascent, int& descent,
+                                           bool& affectsAscent, bool& affectsDescent) const
+{
+    bool ascentDescentSet = false;
+
+    // Replaced boxes will return 0 for the line-height if line-box-contain says they are
+    // not to be included.
+    if (box->renderer()->isReplaced()) {
+        if (renderer()->style(isFirstLineStyle())->lineBoxContain() & LineBoxContainReplaced) {
+            ascent = box->baselinePosition(baselineType());
+            descent = box->lineHeight() - ascent;
+            
+            // Replaced elements always affect both the ascent and descent.
+            affectsAscent = true;
+            affectsDescent = true;
+        }
+        return;
+    }
+
+    Vector<const SimpleFontData*>* usedFonts = 0;
+    GlyphOverflow* glyphOverflow = 0;
+    if (box->isText()) {
+        GlyphOverflowAndFallbackFontsMap::iterator it = textBoxDataMap.find(toInlineTextBox(box));
+        usedFonts = it == textBoxDataMap.end() ? 0 : &it->value.first;
+        glyphOverflow = it == textBoxDataMap.end() ? 0 : &it->value.second;
+    }
+        
+    bool includeLeading = includeLeadingForBox(box);
+    bool includeFont = includeFontForBox(box);
+    
+    bool setUsedFont = false;
+    bool setUsedFontWithLeading = false;
+
+    if (usedFonts && !usedFonts->isEmpty() && (includeFont || (box->renderer()->style(isFirstLineStyle())->lineHeight().isNegative() && includeLeading))) {
+        usedFonts->append(box->renderer()->style(isFirstLineStyle())->font().primaryFont());
+        for (size_t i = 0; i < usedFonts->size(); ++i) {
+            const FontMetrics& fontMetrics = usedFonts->at(i)->fontMetrics();
+            int usedFontAscent = fontMetrics.ascent(baselineType());
+            int usedFontDescent = fontMetrics.descent(baselineType());
+            int halfLeading = (fontMetrics.lineSpacing() - fontMetrics.height()) / 2;
+            int usedFontAscentAndLeading = usedFontAscent + halfLeading;
+            int usedFontDescentAndLeading = fontMetrics.lineSpacing() - usedFontAscentAndLeading;
+            if (includeFont) {
+                setAscentAndDescent(ascent, descent, usedFontAscent, usedFontDescent, ascentDescentSet);
+                setUsedFont = true;
+            }
+            if (includeLeading) {
+                setAscentAndDescent(ascent, descent, usedFontAscentAndLeading, usedFontDescentAndLeading, ascentDescentSet);
+                setUsedFontWithLeading = true;
+            }
+            if (!affectsAscent)
+                affectsAscent = usedFontAscent - box->logicalTop() > 0;
+            if (!affectsDescent)
+                affectsDescent = usedFontDescent + box->logicalTop() > 0;
+        }
+    }
+
+    // If leading is included for the box, then we compute that box.
+    if (includeLeading && !setUsedFontWithLeading) {
+        int ascentWithLeading = box->baselinePosition(baselineType());
+        int descentWithLeading = box->lineHeight() - ascentWithLeading;
+        setAscentAndDescent(ascent, descent, ascentWithLeading, descentWithLeading, ascentDescentSet);
+        
+        // Examine the font box for inline flows and text boxes to see if any part of it is above the baseline.
+        // If the top of our font box relative to the root box baseline is above the root box baseline, then
+        // we are contributing to the maxAscent value. Descent is similar. If any part of our font box is below
+        // the root box's baseline, then we contribute to the maxDescent value.
+        affectsAscent = ascentWithLeading - box->logicalTop() > 0;
+        affectsDescent = descentWithLeading + box->logicalTop() > 0; 
+    }
+    
+    if (includeFontForBox(box) && !setUsedFont) {
+        int fontAscent = box->renderer()->style(isFirstLineStyle())->fontMetrics().ascent(baselineType());
+        int fontDescent = box->renderer()->style(isFirstLineStyle())->fontMetrics().descent(baselineType());
+        setAscentAndDescent(ascent, descent, fontAscent, fontDescent, ascentDescentSet);
+        affectsAscent = fontAscent - box->logicalTop() > 0;
+        affectsDescent = fontDescent + box->logicalTop() > 0; 
+    }
+
+    if (includeGlyphsForBox(box) && glyphOverflow && glyphOverflow->computeBounds) {
+        setAscentAndDescent(ascent, descent, glyphOverflow->top, glyphOverflow->bottom, ascentDescentSet);
+        affectsAscent = glyphOverflow->top - box->logicalTop() > 0;
+        affectsDescent = glyphOverflow->bottom + box->logicalTop() > 0; 
+        glyphOverflow->top = min(glyphOverflow->top, max(0, glyphOverflow->top - box->renderer()->style(isFirstLineStyle())->fontMetrics().ascent(baselineType())));
+        glyphOverflow->bottom = min(glyphOverflow->bottom, max(0, glyphOverflow->bottom - box->renderer()->style(isFirstLineStyle())->fontMetrics().descent(baselineType())));
+    }
+
+    if (includeMarginForBox(box)) {
+        LayoutUnit ascentWithMargin = box->renderer()->style(isFirstLineStyle())->fontMetrics().ascent(baselineType());
+        LayoutUnit descentWithMargin = box->renderer()->style(isFirstLineStyle())->fontMetrics().descent(baselineType());
+        if (box->parent() && !box->renderer()->isText()) {
+            ascentWithMargin += box->boxModelObject()->borderBefore() + box->boxModelObject()->paddingBefore() + box->boxModelObject()->marginBefore();
+            descentWithMargin += box->boxModelObject()->borderAfter() + box->boxModelObject()->paddingAfter() + box->boxModelObject()->marginAfter();
+        }
+        setAscentAndDescent(ascent, descent, ascentWithMargin, descentWithMargin, ascentDescentSet);
+        
+        // Treat like a replaced element, since we're using the margin box.
+        affectsAscent = true;
+        affectsDescent = true;
+    }
+}
+
+LayoutUnit RootInlineBox::verticalPositionForBox(InlineBox* box, VerticalPositionCache& verticalPositionCache)
+{
+    if (box->renderer()->isText())
+        return box->parent()->logicalTop();
+    
+    RenderBoxModelObject* renderer = box->boxModelObject();
+    ASSERT(renderer->isInline());
+    if (!renderer->isInline())
+        return 0;
+
+    // This method determines the vertical position for inline elements.
+    bool firstLine = isFirstLineStyle();
+    if (firstLine && !renderer->document()->styleSheetCollection()->usesFirstLineRules())
+        firstLine = false;
+
+    // Check the cache.
+    bool isRenderInline = renderer->isRenderInline();
+    if (isRenderInline && !firstLine) {
+        LayoutUnit verticalPosition = verticalPositionCache.get(renderer, baselineType());
+        if (verticalPosition != PositionUndefined)
+            return verticalPosition;
+    }
+
+    LayoutUnit verticalPosition = 0;
+    EVerticalAlign verticalAlign = renderer->style()->verticalAlign();
+    if (verticalAlign == TOP || verticalAlign == BOTTOM)
+        return 0;
+   
+    RenderObject* parent = renderer->parent();
+    if (parent->isRenderInline() && parent->style()->verticalAlign() != TOP && parent->style()->verticalAlign() != BOTTOM)
+        verticalPosition = box->parent()->logicalTop();
+    
+    if (verticalAlign != BASELINE) {
+        const Font& font = parent->style(firstLine)->font();
+        const FontMetrics& fontMetrics = font.fontMetrics();
+        int fontSize = font.pixelSize();
+
+        LineDirectionMode lineDirection = parent->isHorizontalWritingMode() ? HorizontalLine : VerticalLine;
+
+        if (verticalAlign == SUB)
+            verticalPosition += fontSize / 5 + 1;
+        else if (verticalAlign == SUPER)
+            verticalPosition -= fontSize / 3 + 1;
+        else if (verticalAlign == TEXT_TOP)
+            verticalPosition += renderer->baselinePosition(baselineType(), firstLine, lineDirection) - fontMetrics.ascent(baselineType());
+        else if (verticalAlign == MIDDLE)
+            verticalPosition = (verticalPosition - static_cast<LayoutUnit>(fontMetrics.xHeight() / 2) - renderer->lineHeight(firstLine, lineDirection) / 2 + renderer->baselinePosition(baselineType(), firstLine, lineDirection)).round();
+        else if (verticalAlign == TEXT_BOTTOM) {
+            verticalPosition += fontMetrics.descent(baselineType());
+            // lineHeight - baselinePosition is always 0 for replaced elements (except inline blocks), so don't bother wasting time in that case.
+            if (!renderer->isReplaced() || renderer->isInlineBlockOrInlineTable())
+                verticalPosition -= (renderer->lineHeight(firstLine, lineDirection) - renderer->baselinePosition(baselineType(), firstLine, lineDirection));
+        } else if (verticalAlign == BASELINE_MIDDLE)
+            verticalPosition += -renderer->lineHeight(firstLine, lineDirection) / 2 + renderer->baselinePosition(baselineType(), firstLine, lineDirection);
+        else if (verticalAlign == LENGTH) {
+            LayoutUnit lineHeight;
+            //Per http://www.w3.org/TR/CSS21/visudet.html#propdef-vertical-align: 'Percentages: refer to the 'line-height' of the element itself'.
+            if (renderer->style()->verticalAlignLength().isPercent())
+                lineHeight = renderer->style()->computedLineHeight();
+            else
+                lineHeight = renderer->lineHeight(firstLine, lineDirection);
+            verticalPosition -= valueForLength(renderer->style()->verticalAlignLength(), lineHeight, renderer->view());
+        }
+    }
+
+    // Store the cached value.
+    if (isRenderInline && !firstLine)
+        verticalPositionCache.set(renderer, baselineType(), verticalPosition);
+
+    return verticalPosition;
+}
+
+bool RootInlineBox::includeLeadingForBox(InlineBox* box) const
+{
+    if (box->renderer()->isReplaced() || (box->renderer()->isText() && !box->isText()))
+        return false;
+
+    LineBoxContain lineBoxContain = renderer()->style()->lineBoxContain();
+    return (lineBoxContain & LineBoxContainInline) || (box == this && (lineBoxContain & LineBoxContainBlock));
+}
+
+bool RootInlineBox::includeFontForBox(InlineBox* box) const
+{
+    if (box->renderer()->isReplaced() || (box->renderer()->isText() && !box->isText()))
+        return false;
+    
+    if (!box->isText() && box->isInlineFlowBox() && !toInlineFlowBox(box)->hasTextChildren())
+        return false;
+
+    // For now map "glyphs" to "font" in vertical text mode until the bounds returned by glyphs aren't garbage.
+    LineBoxContain lineBoxContain = renderer()->style()->lineBoxContain();
+    return (lineBoxContain & LineBoxContainFont) || (!isHorizontal() && (lineBoxContain & LineBoxContainGlyphs));
+}
+
+bool RootInlineBox::includeGlyphsForBox(InlineBox* box) const
+{
+    if (box->renderer()->isReplaced() || (box->renderer()->isText() && !box->isText()))
+        return false;
+    
+    if (!box->isText() && box->isInlineFlowBox() && !toInlineFlowBox(box)->hasTextChildren())
+        return false;
+
+    // FIXME: We can't fit to glyphs yet for vertical text, since the bounds returned are garbage.
+    LineBoxContain lineBoxContain = renderer()->style()->lineBoxContain();
+    return isHorizontal() && (lineBoxContain & LineBoxContainGlyphs);
+}
+
+bool RootInlineBox::includeMarginForBox(InlineBox* box) const
+{
+    if (box->renderer()->isReplaced() || (box->renderer()->isText() && !box->isText()))
+        return false;
+
+    LineBoxContain lineBoxContain = renderer()->style()->lineBoxContain();
+    return lineBoxContain & LineBoxContainInlineBox;
+}
+
+
+bool RootInlineBox::fitsToGlyphs() const
+{
+    // FIXME: We can't fit to glyphs yet for vertical text, since the bounds returned are garbage.
+    LineBoxContain lineBoxContain = renderer()->style()->lineBoxContain();
+    return isHorizontal() && (lineBoxContain & LineBoxContainGlyphs);
+}
+
+bool RootInlineBox::includesRootLineBoxFontOrLeading() const
+{
+    LineBoxContain lineBoxContain = renderer()->style()->lineBoxContain();
+    return (lineBoxContain & LineBoxContainBlock) || (lineBoxContain & LineBoxContainInline) || (lineBoxContain & LineBoxContainFont);
+}
+
+Node* RootInlineBox::getLogicalStartBoxWithNode(InlineBox*& startBox) const
+{
+    Vector<InlineBox*> leafBoxesInLogicalOrder;
+    collectLeafBoxesInLogicalOrder(leafBoxesInLogicalOrder);
+    for (size_t i = 0; i < leafBoxesInLogicalOrder.size(); ++i) {
+        if (leafBoxesInLogicalOrder[i]->renderer()->node()) {
+            startBox = leafBoxesInLogicalOrder[i];
+            return startBox->renderer()->node();
+        }
+    }
+    startBox = 0;
+    return 0;
+}
+    
+Node* RootInlineBox::getLogicalEndBoxWithNode(InlineBox*& endBox) const
+{
+    Vector<InlineBox*> leafBoxesInLogicalOrder;
+    collectLeafBoxesInLogicalOrder(leafBoxesInLogicalOrder);
+    for (size_t i = leafBoxesInLogicalOrder.size(); i > 0; --i) { 
+        if (leafBoxesInLogicalOrder[i - 1]->renderer()->node()) {
+            endBox = leafBoxesInLogicalOrder[i - 1];
+            return endBox->renderer()->node();
+        }
+    }
+    endBox = 0;
+    return 0;
+}
+
+#ifndef NDEBUG
+const char* RootInlineBox::boxName() const
+{
+    return "RootInlineBox";
+}
+#endif
+
+} // namespace WebCore
diff --git a/Source/core/rendering/RootInlineBox.h b/Source/core/rendering/RootInlineBox.h
new file mode 100644
index 0000000..abbfaa1
--- /dev/null
+++ b/Source/core/rendering/RootInlineBox.h
@@ -0,0 +1,258 @@
+/*
+ * 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 "core/platform/text/BidiContext.h"
+#include "core/rendering/InlineFlowBox.h"
+
+namespace WebCore {
+
+class EllipsisBox;
+class HitTestResult;
+class RenderRegion;
+
+struct BidiStatus;
+struct GapRects;
+
+class RootInlineBox : public InlineFlowBox {
+public:
+    explicit RootInlineBox(RenderBlock*);
+
+    virtual void destroy(RenderArena*) OVERRIDE FINAL;
+
+    virtual bool isRootInlineBox() const OVERRIDE FINAL { return true; }
+
+    void detachEllipsisBox(RenderArena*);
+
+    RootInlineBox* nextRootBox() const { return static_cast<RootInlineBox*>(m_nextLineBox); }
+    RootInlineBox* prevRootBox() const { return static_cast<RootInlineBox*>(m_prevLineBox); }
+
+    virtual void adjustPosition(float dx, float dy) OVERRIDE FINAL;
+
+    LayoutUnit lineTop() const { return m_lineTop; }
+    LayoutUnit lineBottom() const { return m_lineBottom; }
+
+    LayoutUnit lineTopWithLeading() const { return m_lineTopWithLeading; }
+    LayoutUnit lineBottomWithLeading() const { return m_lineBottomWithLeading; }
+    
+    LayoutUnit paginationStrut() const { return m_fragmentationData ? m_fragmentationData->m_paginationStrut : LayoutUnit(0); }
+    void setPaginationStrut(LayoutUnit strut) { ensureLineFragmentationData()->m_paginationStrut = strut; }
+
+    bool isFirstAfterPageBreak() const { return m_fragmentationData ? m_fragmentationData->m_isFirstAfterPageBreak : false; }
+    void setIsFirstAfterPageBreak(bool isFirstAfterPageBreak) { ensureLineFragmentationData()->m_isFirstAfterPageBreak = isFirstAfterPageBreak; }
+
+    LayoutUnit paginatedLineWidth() const { return m_fragmentationData ? m_fragmentationData->m_paginatedLineWidth : LayoutUnit(0); }
+    void setPaginatedLineWidth(LayoutUnit width) { ensureLineFragmentationData()->m_paginatedLineWidth = width; }
+
+    RenderRegion* containingRegion() const;
+    void setContainingRegion(RenderRegion*);
+
+    LayoutUnit selectionTop() const;
+    LayoutUnit selectionBottom() const;
+    LayoutUnit selectionHeight() const { return max<LayoutUnit>(0, selectionBottom() - selectionTop()); }
+
+    LayoutUnit selectionTopAdjustedForPrecedingBlock() const;
+    LayoutUnit selectionHeightAdjustedForPrecedingBlock() const { return max<LayoutUnit>(0, selectionBottom() - selectionTopAdjustedForPrecedingBlock()); }
+
+    int blockDirectionPointInLine() const;
+
+    LayoutUnit alignBoxesInBlockDirection(LayoutUnit heightOfBlock, GlyphOverflowAndFallbackFontsMap&, VerticalPositionCache&);
+    void setLineTopBottomPositions(LayoutUnit top, LayoutUnit bottom, LayoutUnit topWithLeading, LayoutUnit bottomWithLeading)
+    { 
+        m_lineTop = top; 
+        m_lineBottom = bottom;
+        m_lineTopWithLeading = topWithLeading;
+        m_lineBottomWithLeading = bottomWithLeading;
+    }
+
+    virtual RenderLineBoxList* rendererLineBoxes() const OVERRIDE FINAL;
+
+    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; }
+
+    using InlineBox::endsWithBreak;
+    using InlineBox::setEndsWithBreak;
+
+    void childRemoved(InlineBox* box);
+
+    bool lineCanAccommodateEllipsis(bool ltr, int blockEdge, int lineBoxEdge, int ellipsisWidth);
+    // Return the truncatedWidth, the width of the truncated text + ellipsis.
+    float placeEllipsis(const AtomicString& ellipsisStr, bool ltr, float blockLeftEdge, float blockRightEdge, float ellipsisWidth, InlineBox* markupBox = 0);
+    // Return the position of the EllipsisBox or -1.
+    virtual float placeEllipsisBox(bool ltr, float blockLeftEdge, float blockRightEdge, float ellipsisWidth, float &truncatedWidth, bool& foundBox) OVERRIDE FINAL;
+
+    using InlineBox::hasEllipsisBox;
+    EllipsisBox* ellipsisBox() const;
+
+    void paintEllipsisBox(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom) const;
+
+    virtual void clearTruncation() OVERRIDE FINAL;
+
+    bool isHyphenated() const;
+
+    virtual int baselinePosition(FontBaseline baselineType) const OVERRIDE FINAL;
+    virtual LayoutUnit lineHeight() const OVERRIDE FINAL;
+
+    virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom);
+    virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom) OVERRIDE FINAL;
+
+    using InlineBox::hasSelectedChildren;
+    using InlineBox::setHasSelectedChildren;
+
+    virtual RenderObject::SelectionState selectionState() OVERRIDE FINAL;
+    InlineBox* firstSelectedBox();
+    InlineBox* lastSelectedBox();
+
+    GapRects lineSelectionGap(RenderBlock* rootBlock, const LayoutPoint& rootBlockPhysicalPosition, const LayoutSize& offsetFromRootBlock, LayoutUnit selTop, LayoutUnit selHeight, const PaintInfo*);
+
+    RenderBlock* block() const;
+
+    InlineBox* closestLeafChildForPoint(const IntPoint&, bool onlyEditableLeaves);
+    InlineBox* closestLeafChildForLogicalLeftPosition(int, bool onlyEditableLeaves = false);
+
+    void appendFloat(RenderBox* floatingBox)
+    {
+        ASSERT(!isDirty());
+        if (m_floats)
+            m_floats->append(floatingBox);
+        else
+            m_floats= adoptPtr(new Vector<RenderBox*>(1, floatingBox));
+    }
+
+    Vector<RenderBox*>* floatsPtr() { ASSERT(!isDirty()); return m_floats.get(); }
+
+    virtual void extractLineBoxFromRenderObject() OVERRIDE FINAL;
+    virtual void attachLineBoxToRenderObject() OVERRIDE FINAL;
+    virtual void removeLineBoxFromRenderObject() OVERRIDE FINAL;
+    
+    FontBaseline baselineType() const { return static_cast<FontBaseline>(m_baselineType); }
+
+    bool hasAnnotationsBefore() const { return m_hasAnnotationsBefore; }
+    bool hasAnnotationsAfter() const { return m_hasAnnotationsAfter; }
+
+    LayoutRect paddedLayoutOverflowRect(LayoutUnit endPadding) const;
+
+    void ascentAndDescentForBox(InlineBox*, GlyphOverflowAndFallbackFontsMap&, int& ascent, int& descent, bool& affectsAscent, bool& affectsDescent) const;
+    LayoutUnit verticalPositionForBox(InlineBox*, VerticalPositionCache&);
+    bool includeLeadingForBox(InlineBox*) const;
+    bool includeFontForBox(InlineBox*) const;
+    bool includeGlyphsForBox(InlineBox*) const;
+    bool includeMarginForBox(InlineBox*) const;
+    bool fitsToGlyphs() const;
+    bool includesRootLineBoxFontOrLeading() const;
+    
+    LayoutUnit logicalTopVisualOverflow() const
+    {
+        return InlineFlowBox::logicalTopVisualOverflow(lineTop());
+    }
+    LayoutUnit logicalBottomVisualOverflow() const
+    {
+        return InlineFlowBox::logicalBottomVisualOverflow(lineBottom());
+    }
+    LayoutUnit logicalTopLayoutOverflow() const
+    {
+        return InlineFlowBox::logicalTopLayoutOverflow(lineTop());
+    }
+    LayoutUnit logicalBottomLayoutOverflow() const
+    {
+        return InlineFlowBox::logicalBottomLayoutOverflow(lineBottom());
+    }
+
+#if ENABLE(CSS3_TEXT)
+    // Used to calculate the underline offset for TextUnderlinePositionUnder.
+    float maxLogicalTop() const { return m_maxLogicalTop; }
+#endif // CSS3_TEXT
+
+    Node* getLogicalStartBoxWithNode(InlineBox*&) const;
+    Node* getLogicalEndBoxWithNode(InlineBox*&) const;
+
+#ifndef NDEBUG
+    virtual const char* boxName() const;
+#endif
+private:
+    LayoutUnit lineSnapAdjustment(LayoutUnit delta = 0) const;
+
+    LayoutUnit beforeAnnotationsAdjustment() const;
+
+    struct LineFragmentationData;
+    LineFragmentationData* ensureLineFragmentationData()
+    {
+        if (!m_fragmentationData)
+            m_fragmentationData = adoptPtr(new LineFragmentationData());
+
+        return m_fragmentationData.get();
+    }
+
+    // This folds into the padding at the end of InlineFlowBox on 64-bit.
+    unsigned m_lineBreakPos;
+
+    // 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;
+    RefPtr<BidiContext> m_lineBreakContext;
+
+    LayoutUnit m_lineTop;
+    LayoutUnit m_lineBottom;
+
+    LayoutUnit m_lineTopWithLeading;
+    LayoutUnit m_lineBottomWithLeading;
+
+#if ENABLE(CSS3_TEXT)
+    // Maximum logicalTop among all children of an InlineFlowBox. Used to
+    // calculate the offset for TextUnderlinePositionUnder.
+    float m_maxLogicalTop;
+#endif // CSS3_TEXT
+
+    struct LineFragmentationData {
+        WTF_MAKE_NONCOPYABLE(LineFragmentationData); WTF_MAKE_FAST_ALLOCATED;
+    public:
+        LineFragmentationData()
+            : m_containingRegion(0)
+            , m_paginationStrut(0)
+            , m_paginatedLineWidth(0)
+            , m_isFirstAfterPageBreak(false)
+        {
+
+        }
+
+        // It should not be assumed the |containingRegion| is always valid.
+        // It can also be 0 if the flow has no region chain.
+        RenderRegion* m_containingRegion;
+        LayoutUnit m_paginationStrut;
+        LayoutUnit m_paginatedLineWidth;
+        bool m_isFirstAfterPageBreak;
+    };
+
+    OwnPtr<LineFragmentationData> m_fragmentationData;
+
+    // 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.
+    OwnPtr<Vector<RenderBox*> > m_floats;
+};
+
+} // namespace WebCore
+
+#endif // RootInlineBox_h
diff --git a/Source/core/rendering/ScrollBehavior.cpp b/Source/core/rendering/ScrollBehavior.cpp
new file mode 100644
index 0000000..d28c8e0
--- /dev/null
+++ b/Source/core/rendering/ScrollBehavior.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * Portions are Copyright (C) 1998 Netscape Communications Corporation.
+ *
+ * Other contributors:
+ *   Robert O'Callahan <roc+@cs.cmu.edu>
+ *   David Baron <dbaron@fas.harvard.edu>
+ *   Christian Biesinger <cbiesinger@web.de>
+ *   Randall Jesup <rjesup@wgate.com>
+ *   Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
+ *   Josh Soref <timeless@mac.com>
+ *   Boris Zbarsky <bzbarsky@mit.edu>
+ *
+ * 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 "core/rendering/ScrollBehavior.h"
+
+namespace WebCore {
+
+const ScrollAlignment ScrollAlignment::alignCenterIfNeeded = { noScroll, alignCenter, alignToClosestEdge };
+const ScrollAlignment ScrollAlignment::alignToEdgeIfNeeded = { noScroll, alignToClosestEdge, alignToClosestEdge };
+const ScrollAlignment ScrollAlignment::alignCenterAlways = { alignCenter, alignCenter, alignCenter };
+const ScrollAlignment ScrollAlignment::alignTopAlways = { alignTop, alignTop, alignTop };
+const ScrollAlignment ScrollAlignment::alignBottomAlways = { alignBottom, alignBottom, alignBottom };
+
+}; // namespace WebCore
diff --git a/Source/core/rendering/ScrollBehavior.h b/Source/core/rendering/ScrollBehavior.h
new file mode 100644
index 0000000..390c68a
--- /dev/null
+++ b/Source/core/rendering/ScrollBehavior.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2003, 2009 Apple Inc.  All rights reserved.
+ *
+ * Portions are Copyright (C) 1998 Netscape Communications Corporation.
+ *
+ * Other contributors:
+ *   Robert O'Callahan <roc+@cs.cmu.edu>
+ *   David Baron <dbaron@fas.harvard.edu>
+ *   Christian Biesinger <cbiesinger@web.de>
+ *   Randall Jesup <rjesup@wgate.com>
+ *   Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
+ *   Josh Soref <timeless@mac.com>
+ *   Boris Zbarsky <bzbarsky@mit.edu>
+ *
+ * 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 ScrollBehavior_h
+#define ScrollBehavior_h
+
+namespace WebCore {
+
+enum ScrollBehavior {
+    noScroll,
+    alignCenter,
+    alignTop,
+    alignBottom, 
+    alignLeft,
+    alignRight,
+    alignToClosestEdge
+};
+
+struct ScrollAlignment {
+    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; }
+
+    static const ScrollAlignment alignCenterIfNeeded;
+    static const ScrollAlignment alignToEdgeIfNeeded;
+    static const ScrollAlignment alignCenterAlways;
+    static const ScrollAlignment alignTopAlways;
+    static const ScrollAlignment alignBottomAlways;
+
+    ScrollBehavior m_rectVisible;
+    ScrollBehavior m_rectHidden;
+    ScrollBehavior m_rectPartial;
+};
+
+
+}; // namespace WebCore
+
+#endif // ScrollBehavior_h
diff --git a/Source/core/rendering/TableLayout.h b/Source/core/rendering/TableLayout.h
new file mode 100644
index 0000000..9b6e1e2
--- /dev/null
+++ b/Source/core/rendering/TableLayout.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2002 Lars Knoll (knoll@kde.org)
+ *           (C) 2002 Dirk Mueller (mueller@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef TableLayout_h
+#define TableLayout_h
+
+#include <wtf/FastAllocBase.h>
+#include <wtf/Noncopyable.h>
+
+namespace WebCore {
+
+class LayoutUnit;
+class RenderTable;
+
+class TableLayout {
+    WTF_MAKE_NONCOPYABLE(TableLayout); WTF_MAKE_FAST_ALLOCATED;
+public:
+    explicit TableLayout(RenderTable* table)
+        : m_table(table)
+    {
+    }
+
+    virtual ~TableLayout() { }
+
+    virtual void computeIntrinsicLogicalWidths(LayoutUnit& minWidth, LayoutUnit& maxWidth) = 0;
+    virtual void applyPreferredLogicalWidthQuirks(LayoutUnit& minWidth, LayoutUnit& maxWidth) const = 0;
+    virtual void layout() = 0;
+
+protected:
+    // FIXME: Once we enable SATURATED_LAYOUT_ARITHMETHIC, this should just be LayoutUnit::nearlyMax().
+    // Until then though, using nearlyMax causes overflow in some tests, so we just pick a large number.
+    const static int tableMaxWidth = 1000000;
+
+    RenderTable* m_table;
+};
+
+} // namespace WebCore
+
+#endif // TableLayout_h
diff --git a/Source/core/rendering/TextAutosizer.cpp b/Source/core/rendering/TextAutosizer.cpp
new file mode 100644
index 0000000..953f9bd
--- /dev/null
+++ b/Source/core/rendering/TextAutosizer.cpp
@@ -0,0 +1,623 @@
+/*
+ * Copyright (C) 2012 Google Inc. All rights reserved.
+ * Copyright (C) 2012 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 "core/rendering/TextAutosizer.h"
+
+#include "core/dom/Document.h"
+#include "core/html/HTMLElement.h"
+#include "core/inspector/InspectorInstrumentation.h"
+#include "core/page/Settings.h"
+#include "core/platform/graphics/IntSize.h"
+#include "core/rendering/RenderObject.h"
+#include "core/rendering/RenderText.h"
+#include "core/rendering/RenderView.h"
+#include "core/rendering/style/RenderStyle.h"
+#include "core/rendering/style/StyleInheritedData.h"
+
+#include <algorithm>
+#include <wtf/StdLibExtras.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+using namespace HTMLNames;
+
+struct TextAutosizingWindowInfo {
+    IntSize windowSize;
+    IntSize minLayoutSize;
+};
+
+// Represents cluster related data. Instances should not persist between calls to processSubtree.
+struct TextAutosizingClusterInfo {
+    explicit TextAutosizingClusterInfo(RenderBlock* root)
+        : root(root)
+        , blockContainingAllText(0)
+        , maxAllowedDifferenceFromTextWidth(150)
+    {
+    }
+
+    RenderBlock* root;
+    const RenderBlock* blockContainingAllText;
+
+    // Upper limit on the difference between the width of the cluster's block containing all
+    // text and that of a narrow child before the child becomes a separate cluster.
+    float maxAllowedDifferenceFromTextWidth;
+
+    // Descendants of the cluster that are narrower than the block containing all text and must be
+    // processed together.
+    Vector<TextAutosizingClusterInfo> narrowDescendants;
+};
+
+
+static const Vector<QualifiedName>& formInputTags()
+{
+    // Returns the tags for the form input elements.
+    DEFINE_STATIC_LOCAL(Vector<QualifiedName>, formInputTags, ());
+    if (formInputTags.isEmpty()) {
+        formInputTags.append(inputTag);
+        formInputTags.append(buttonTag);
+        formInputTags.append(selectTag);
+    }
+    return formInputTags;
+}
+
+TextAutosizer::TextAutosizer(Document* document)
+    : m_document(document)
+{
+}
+
+TextAutosizer::~TextAutosizer()
+{
+}
+
+void TextAutosizer::recalculateMultipliers()
+{
+    RenderObject* renderer = m_document->renderer();
+    while (renderer) {
+        if (renderer->style() && renderer->style()->textAutosizingMultiplier() != 1)
+            setMultiplier(renderer, 1);
+        renderer = renderer->nextInPreOrder();
+    }
+}
+
+bool TextAutosizer::processSubtree(RenderObject* layoutRoot)
+{
+    // FIXME: Text Autosizing should only be enabled when m_document->page()->mainFrame()->view()->useFixedLayout()
+    // is true, but for now it's useful to ignore this so that it can be tested on desktop.
+    if (!m_document->settings() || !m_document->settings()->textAutosizingEnabled() || layoutRoot->view()->printing() || !m_document->page())
+        return false;
+
+    Frame* mainFrame = m_document->page()->mainFrame();
+
+    TextAutosizingWindowInfo windowInfo;
+
+    // Window area, in logical (density-independent) pixels.
+    windowInfo.windowSize = m_document->settings()->textAutosizingWindowSizeOverride();
+    if (windowInfo.windowSize.isEmpty()) {
+        bool includeScrollbars = !InspectorInstrumentation::shouldApplyScreenWidthOverride(mainFrame);
+        windowInfo.windowSize = mainFrame->view()->unscaledVisibleContentSize(includeScrollbars ? ScrollableArea::IncludeScrollbars : ScrollableArea::ExcludeScrollbars);
+    }
+
+    // Largest area of block that can be visible at once (assuming the main
+    // frame doesn't get scaled to less than overview scale), in CSS pixels.
+    windowInfo.minLayoutSize = mainFrame->view()->layoutSize();
+    for (Frame* frame = m_document->frame(); frame; frame = frame->tree()->parent()) {
+        if (!frame->view()->isInChildFrameWithFrameFlattening())
+            windowInfo.minLayoutSize = windowInfo.minLayoutSize.shrunkTo(frame->view()->layoutSize());
+    }
+
+    // The layoutRoot could be neither a container nor a cluster, so walk up the tree till we find each of these.
+    RenderBlock* container = layoutRoot->isRenderBlock() ? toRenderBlock(layoutRoot) : layoutRoot->containingBlock();
+    while (container && !isAutosizingContainer(container))
+        container = container->containingBlock();
+
+    RenderBlock* cluster = container;
+    while (cluster && (!isAutosizingContainer(cluster) || !isIndependentDescendant(cluster)))
+        cluster = cluster->containingBlock();
+
+    TextAutosizingClusterInfo clusterInfo(cluster);
+    processCluster(clusterInfo, container, layoutRoot, windowInfo);
+    return true;
+}
+
+float TextAutosizer::clusterMultiplier(WritingMode writingMode, const TextAutosizingWindowInfo& windowInfo, float textWidth) const
+{
+    int logicalWindowWidth = isHorizontalWritingMode(writingMode) ? windowInfo.windowSize.width() : windowInfo.windowSize.height();
+    int logicalLayoutWidth = isHorizontalWritingMode(writingMode) ? windowInfo.minLayoutSize.width() : windowInfo.minLayoutSize.height();
+    // Ignore box width in excess of the layout width, to avoid extreme multipliers.
+    float logicalClusterWidth = std::min<float>(textWidth, logicalLayoutWidth);
+
+    float multiplier = logicalClusterWidth / logicalWindowWidth;
+    multiplier *= m_document->settings()->textAutosizingFontScaleFactor();
+    return std::max(1.0f, multiplier);
+}
+
+void TextAutosizer::processClusterInternal(TextAutosizingClusterInfo& clusterInfo, RenderBlock* container, RenderObject* subtreeRoot, const TextAutosizingWindowInfo& windowInfo, float multiplier)
+{
+    processContainer(multiplier, container, clusterInfo, subtreeRoot, windowInfo);
+
+    Vector<Vector<TextAutosizingClusterInfo> > narrowDescendantsGroups;
+    getNarrowDescendantsGroupedByWidth(clusterInfo, narrowDescendantsGroups);
+    for (size_t i = 0; i < narrowDescendantsGroups.size(); ++i)
+        processCompositeCluster(narrowDescendantsGroups[i], windowInfo);
+}
+
+void TextAutosizer::processCluster(TextAutosizingClusterInfo& clusterInfo, RenderBlock* container, RenderObject* subtreeRoot, const TextAutosizingWindowInfo& windowInfo)
+{
+    // Many pages set a max-width on their content. So especially for the RenderView, instead of
+    // just taking the width of |cluster| we find the lowest common ancestor of the first and last
+    // descendant text node of the cluster (i.e. the deepest wrapper block that contains all the
+    // text), and use its width instead.
+    clusterInfo.blockContainingAllText = findDeepestBlockContainingAllText(clusterInfo.root);
+    float textWidth = clusterInfo.blockContainingAllText->contentLogicalWidth();
+    float multiplier =  1.0;
+    if (clusterShouldBeAutosized(clusterInfo, textWidth))
+        multiplier = clusterMultiplier(clusterInfo.root->style()->writingMode(), windowInfo, textWidth);
+    processClusterInternal(clusterInfo, container, subtreeRoot, windowInfo, multiplier);
+}
+
+void TextAutosizer::processCompositeCluster(Vector<TextAutosizingClusterInfo>& clusterInfos, const TextAutosizingWindowInfo& windowInfo)
+{
+    if (clusterInfos.isEmpty())
+        return;
+
+    float maxTextWidth = 0;
+    for (size_t i = 0; i < clusterInfos.size(); ++i) {
+        TextAutosizingClusterInfo& clusterInfo = clusterInfos[i];
+        clusterInfo.blockContainingAllText = findDeepestBlockContainingAllText(clusterInfo.root);
+        maxTextWidth = max<float>(maxTextWidth, clusterInfo.blockContainingAllText->contentLogicalWidth());
+    }
+
+    float multiplier = 1.0;
+    if (compositeClusterShouldBeAutosized(clusterInfos, maxTextWidth))
+        multiplier = clusterMultiplier(clusterInfos[0].root->style()->writingMode(), windowInfo, maxTextWidth);
+    for (size_t i = 0; i < clusterInfos.size(); ++i) {
+        ASSERT(clusterInfos[i].root->style()->writingMode() == clusterInfos[0].root->style()->writingMode());
+        processClusterInternal(clusterInfos[i], clusterInfos[i].root, clusterInfos[i].root, windowInfo, multiplier);
+    }
+}
+
+void TextAutosizer::processContainer(float multiplier, RenderBlock* container, TextAutosizingClusterInfo& clusterInfo, RenderObject* subtreeRoot, const TextAutosizingWindowInfo& windowInfo)
+{
+    ASSERT(isAutosizingContainer(container));
+
+    float localMultiplier = containerShouldBeAutosized(container) ? multiplier: 1;
+
+    RenderObject* descendant = nextInPreOrderSkippingDescendantsOfContainers(subtreeRoot, subtreeRoot);
+    while (descendant) {
+        if (descendant->isText()) {
+            if (localMultiplier != 1 && descendant->style()->textAutosizingMultiplier() == 1) {
+                setMultiplier(descendant, localMultiplier);
+                setMultiplier(descendant->parent(), localMultiplier); // Parent does line spacing.
+            }
+            // FIXME: Increase list marker size proportionately.
+        } else if (isAutosizingContainer(descendant)) {
+            RenderBlock* descendantBlock = toRenderBlock(descendant);
+            TextAutosizingClusterInfo descendantClusterInfo(descendantBlock);
+            if (isWiderDescendant(descendantBlock, clusterInfo) || isIndependentDescendant(descendantBlock))
+                processCluster(descendantClusterInfo, descendantBlock, descendantBlock, windowInfo);
+            else if (isNarrowDescendant(descendantBlock, clusterInfo)) {
+                // Narrow descendants are processed together later to be able to apply the same multiplier
+                // to each of them if necessary.
+                clusterInfo.narrowDescendants.append(descendantClusterInfo);
+            } else
+                processContainer(multiplier, descendantBlock, clusterInfo, descendantBlock, windowInfo);
+        }
+        descendant = nextInPreOrderSkippingDescendantsOfContainers(descendant, subtreeRoot);
+    }
+}
+
+void TextAutosizer::setMultiplier(RenderObject* renderer, float multiplier)
+{
+    RefPtr<RenderStyle> newStyle = RenderStyle::clone(renderer->style());
+    newStyle->setTextAutosizingMultiplier(multiplier);
+    renderer->setStyle(newStyle.release());
+}
+
+float TextAutosizer::computeAutosizedFontSize(float specifiedSize, float multiplier)
+{
+    // Somewhat arbitrary "pleasant" font size.
+    const float pleasantSize = 16;
+
+    // Multiply fonts that the page author has specified to be larger than
+    // pleasantSize by less and less, until huge fonts are not increased at all.
+    // For specifiedSize between 0 and pleasantSize we directly apply the
+    // multiplier; hence for specifiedSize == pleasantSize, computedSize will be
+    // multiplier * pleasantSize. For greater specifiedSizes we want to
+    // gradually fade out the multiplier, so for every 1px increase in
+    // specifiedSize beyond pleasantSize we will only increase computedSize
+    // by gradientAfterPleasantSize px until we meet the
+    // computedSize = specifiedSize line, after which we stay on that line (so
+    // then every 1px increase in specifiedSize increases computedSize by 1px).
+    const float gradientAfterPleasantSize = 0.5;
+
+    float computedSize;
+    if (specifiedSize <= pleasantSize)
+        computedSize = multiplier * specifiedSize;
+    else {
+        computedSize = multiplier * pleasantSize + gradientAfterPleasantSize * (specifiedSize - pleasantSize);
+        if (computedSize < specifiedSize)
+            computedSize = specifiedSize;
+    }
+    return computedSize;
+}
+
+bool TextAutosizer::isAutosizingContainer(const RenderObject* renderer)
+{
+    // "Autosizing containers" are the smallest unit for which we can
+    // enable/disable Text Autosizing.
+    // - Must not be inline, as different multipliers on one line looks terrible.
+    //   Exceptions are inline-block and alike elements (inline-table, -webkit-inline-*),
+    //   as they often contain entire multi-line columns of text.
+    // - Must not be list items, as items in the same list should look consistent (*).
+    // - Must not be normal list items, as items in the same list should look
+    //   consistent, unless they are floating or position:absolute/fixed.
+    if (!renderer->isRenderBlock() || (renderer->isInline() && !renderer->style()->isDisplayReplacedType()))
+        return false;
+    if (renderer->isListItem())
+        return renderer->isFloating() || renderer->isOutOfFlowPositioned();
+    // Avoid creating containers for text within text controls, buttons, or <select> buttons.
+    Node* parentNode = renderer->parent() ? renderer->parent()->generatingNode() : 0;
+    if (parentNode && parentNode->isElementNode() && formInputTags().contains(toElement(parentNode)->tagQName()))
+        return false;
+
+    return true;
+}
+
+bool TextAutosizer::isNarrowDescendant(const RenderBlock* renderer, TextAutosizingClusterInfo& parentClusterInfo)
+{
+    ASSERT(isAutosizingContainer(renderer));
+
+    // Autosizing containers that are significantly narrower than the |blockContainingAllText| of
+    // their enclosing cluster may be acting as separate columns, hence must be autosized
+    // separately. For example the 2nd div in:
+    // <body>
+    //     <div style="float: right; width: 50%"></div>
+    //     <div style="width: 50%"></div>
+    // <body>
+    // is the left column, and should be autosized differently from the body.
+    // If however the container is only narrower by 150px or less, it's considered part of
+    // the enclosing cluster. This 150px limit is adjusted whenever a descendant container is
+    // less than 50px narrower than the current limit.
+    const float differenceFromMaxWidthDifference = 50;
+    float contentWidth = renderer->contentLogicalWidth();
+    float clusterTextWidth = parentClusterInfo.blockContainingAllText->contentLogicalWidth();
+    float widthDifference = clusterTextWidth - contentWidth;
+
+    if (widthDifference - parentClusterInfo.maxAllowedDifferenceFromTextWidth > differenceFromMaxWidthDifference)
+        return true;
+
+    parentClusterInfo.maxAllowedDifferenceFromTextWidth = std::max(widthDifference, parentClusterInfo.maxAllowedDifferenceFromTextWidth);
+    return false;
+}
+
+bool TextAutosizer::isWiderDescendant(const RenderBlock* renderer, const TextAutosizingClusterInfo& parentClusterInfo)
+{
+    ASSERT(isAutosizingContainer(renderer));
+
+    // Autosizing containers that are wider than the |blockContainingAllText| of their enclosing
+    // cluster are treated the same way as autosizing clusters to be autosized separately.
+    float contentWidth = renderer->contentLogicalWidth();
+    float clusterTextWidth = parentClusterInfo.blockContainingAllText->contentLogicalWidth();
+    return contentWidth > clusterTextWidth;
+}
+
+bool TextAutosizer::isIndependentDescendant(const RenderBlock* renderer)
+{
+    ASSERT(isAutosizingContainer(renderer));
+
+    // "Autosizing clusters" are special autosizing containers within which we
+    // want to enforce a uniform text size multiplier, in the hopes of making
+    // the major sections of the page look internally consistent.
+    // All their descendants (including other autosizing containers) must share
+    // the same multiplier, except for subtrees which are themselves clusters,
+    // and some of their descendant containers might not be autosized at all
+    // (for example if their height is constrained).
+    // Additionally, clusterShouldBeAutosized requires each cluster to contain a
+    // minimum amount of text, without which it won't be autosized.
+    //
+    // Clusters are chosen using very similar criteria to CSS flow roots, aka
+    // block formatting contexts (http://w3.org/TR/css3-box/#flow-root), since
+    // flow roots correspond to box containers that behave somewhat
+    // independently from their parent (for example they don't overlap floats).
+    // The definition of a flow root also conveniently includes most of the
+    // ways that a box and its children can have significantly different width
+    // from the box's parent (we want to avoid having significantly different
+    // width blocks within a cluster, since the narrower blocks would end up
+    // larger than would otherwise be necessary).
+    return renderer->isRenderView()
+        || renderer->isFloating()
+        || renderer->isOutOfFlowPositioned()
+        || renderer->isTableCell()
+        || renderer->isTableCaption()
+        || renderer->isFlexibleBoxIncludingDeprecated()
+        || renderer->hasColumns()
+        || renderer->containingBlock()->isHorizontalWritingMode() != renderer->isHorizontalWritingMode()
+        || renderer->style()->isDisplayReplacedType()
+        || renderer->isTextArea();
+    // FIXME: Tables need special handling to multiply all their columns by
+    // the same amount even if they're different widths; so do hasColumns()
+    // containers, and probably flexboxes...
+}
+
+bool TextAutosizer::isAutosizingCluster(const RenderBlock* renderer, TextAutosizingClusterInfo& parentClusterInfo)
+{
+    ASSERT(isAutosizingContainer(renderer));
+
+    return isNarrowDescendant(renderer, parentClusterInfo)
+        || isWiderDescendant(renderer, parentClusterInfo)
+        || isIndependentDescendant(renderer);
+}
+
+bool TextAutosizer::containerShouldBeAutosized(const RenderBlock* container)
+{
+    if (containerContainsOneOfTags(container, formInputTags()))
+        return false;
+
+    if (containerIsRowOfLinks(container))
+        return false;
+
+    // Don't autosize block-level text that can't wrap (as it's likely to
+    // expand sideways and break the page's layout).
+    if (!container->style()->autoWrap())
+        return false;
+
+    return !contentHeightIsConstrained(container);
+}
+
+bool TextAutosizer::containerContainsOneOfTags(const RenderBlock* container, const Vector<QualifiedName>& tags)
+{
+    const RenderObject* renderer = container;
+    while (renderer) {
+        const Node* rendererNode = renderer->node();
+        if (rendererNode && rendererNode->isElementNode()) {
+            if (tags.contains(toElement(rendererNode)->tagQName()))
+                return true;
+        }
+        renderer = nextInPreOrderSkippingDescendantsOfContainers(renderer, container);
+    }
+
+    return false;
+}
+
+bool TextAutosizer::containerIsRowOfLinks(const RenderObject* container)
+{
+    // A "row of links" is a container for which holds:
+    //  1. it should not contain non-link text elements longer than 3 characters
+    //  2. it should contain min. 3 inline links and all links should
+    //     have the same specified font size
+    //  3. it should not contain <br> elements
+    //  4. it should contain only inline elements unless they are containers,
+    //     children of link elements or children of sub-containers.
+    int linkCount = 0;
+    RenderObject* renderer = container->nextInPreOrder(container);
+    float matchingFontSize = -1;
+
+    while (renderer) {
+        if (!isAutosizingContainer(renderer)) {
+            if (renderer->isText() && toRenderText(renderer)->text()->stripWhiteSpace()->length() > 3)
+                return false;
+            if (!renderer->isInline())
+                return false;
+            if (renderer->isBR())
+                return false;
+        }
+        if (renderer->style()->isLink()) {
+            if (matchingFontSize < 0)
+                matchingFontSize = renderer->style()->specifiedFontSize();
+            else {
+                if (matchingFontSize != renderer->style()->specifiedFontSize())
+                    return false;
+            }
+
+            linkCount++;
+            // Skip traversing descendants of the link.
+            renderer = renderer->nextInPreOrderAfterChildren(container);
+        } else
+            renderer = nextInPreOrderSkippingDescendantsOfContainers(renderer, container);
+    }
+
+    return (linkCount >= 3);
+}
+
+bool TextAutosizer::contentHeightIsConstrained(const RenderBlock* container)
+{
+    // FIXME: Propagate constrainedness down the tree, to avoid inefficiently walking back up from each box.
+    // FIXME: This code needs to take into account vertical writing modes.
+    // FIXME: Consider additional heuristics, such as ignoring fixed heights if the content is already overflowing before autosizing kicks in.
+    for (; container; container = container->containingBlock()) {
+        RenderStyle* style = container->style();
+        if (style->overflowY() >= OSCROLL)
+            return false;
+        if (style->height().isSpecified() || style->maxHeight().isSpecified()) {
+            // Some sites (e.g. wikipedia) set their html and/or body elements to height:100%,
+            // without intending to constrain the height of the content within them.
+            return !container->isRoot() && !container->isBody();
+        }
+        if (container->isFloatingOrOutOfFlowPositioned())
+            return false;
+    }
+    return false;
+}
+
+bool TextAutosizer::clusterShouldBeAutosized(TextAutosizingClusterInfo& clusterInfo, float blockWidth)
+{
+    Vector<TextAutosizingClusterInfo> clusterInfos(1, clusterInfo);
+    return compositeClusterShouldBeAutosized(clusterInfos, blockWidth);
+}
+
+bool TextAutosizer::compositeClusterShouldBeAutosized(Vector<TextAutosizingClusterInfo>& clusterInfos, float blockWidth)
+{
+    // Don't autosize clusters that contain less than 4 lines of text (in
+    // practice less lines are required, since measureDescendantTextWidth
+    // assumes that characters are 1em wide, but most characters are narrower
+    // than that, so we're overestimating their contribution to the linecount).
+    //
+    // This is to reduce the likelihood of autosizing things like headers and
+    // footers, which can be quite visually distracting. The rationale is that
+    // if a cluster contains very few lines of text then it's ok to have to zoom
+    // in and pan from side to side to read each line, since if there are very
+    // few lines of text you'll only need to pan across once or twice.
+    //
+    // An exception to the 4 lines of text are the textarea clusters, which are
+    // always autosized by default (i.e. threated as if they contain more than 4
+    // lines of text). This is to ensure that the text does not suddenly get
+    // autosized when the user enters more than 4 lines of text.
+    float totalTextWidth = 0;
+    const float minLinesOfText = 4;
+    float minTextWidth = blockWidth * minLinesOfText;
+    for (size_t i = 0; i < clusterInfos.size(); ++i) {
+        if (clusterInfos[i].root->isTextArea())
+            return true;
+        measureDescendantTextWidth(clusterInfos[i].blockContainingAllText, clusterInfos[i], minTextWidth, totalTextWidth);
+        if (totalTextWidth >= minTextWidth)
+            return true;
+    }
+    return false;
+}
+
+void TextAutosizer::measureDescendantTextWidth(const RenderBlock* container, TextAutosizingClusterInfo& clusterInfo, float minTextWidth, float& textWidth)
+{
+    bool skipLocalText = !containerShouldBeAutosized(container);
+
+    RenderObject* descendant = nextInPreOrderSkippingDescendantsOfContainers(container, container);
+    while (descendant) {
+        if (!skipLocalText && descendant->isText()) {
+            textWidth += toRenderText(descendant)->renderedTextLength() * descendant->style()->specifiedFontSize();
+        } else if (isAutosizingContainer(descendant)) {
+            RenderBlock* descendantBlock = toRenderBlock(descendant);
+            if (!isAutosizingCluster(descendantBlock, clusterInfo))
+                measureDescendantTextWidth(descendantBlock, clusterInfo, minTextWidth, textWidth);
+        }
+        if (textWidth >= minTextWidth)
+            return;
+        descendant = nextInPreOrderSkippingDescendantsOfContainers(descendant, container);
+    }
+}
+
+RenderObject* TextAutosizer::nextInPreOrderSkippingDescendantsOfContainers(const RenderObject* current, const RenderObject* stayWithin)
+{
+    if (current == stayWithin || !isAutosizingContainer(current))
+        return current->nextInPreOrder(stayWithin);
+    return current->nextInPreOrderAfterChildren(stayWithin);
+}
+
+const RenderBlock* TextAutosizer::findDeepestBlockContainingAllText(const RenderBlock* cluster)
+{
+    size_t firstDepth = 0;
+    const RenderObject* firstTextLeaf = findFirstTextLeafNotInCluster(cluster, firstDepth, FirstToLast);
+    if (!firstTextLeaf)
+        return cluster;
+
+    size_t lastDepth = 0;
+    const RenderObject* lastTextLeaf = findFirstTextLeafNotInCluster(cluster, lastDepth, LastToFirst);
+    ASSERT(lastTextLeaf);
+
+    // Equalize the depths if necessary. Only one of the while loops below will get executed.
+    const RenderObject* firstNode = firstTextLeaf;
+    const RenderObject* lastNode = lastTextLeaf;
+    while (firstDepth > lastDepth) {
+        firstNode = firstNode->parent();
+        --firstDepth;
+    }
+    while (lastDepth > firstDepth) {
+        lastNode = lastNode->parent();
+        --lastDepth;
+    }
+
+    // Go up from both nodes until the parent is the same. Both pointers will point to the LCA then.
+    while (firstNode != lastNode) {
+        firstNode = firstNode->parent();
+        lastNode = lastNode->parent();
+    }
+
+    if (firstNode->isRenderBlock())
+        return toRenderBlock(firstNode);
+
+    // containingBlock() should never leave the cluster, since it only skips ancestors when finding the
+    // container of position:absolute/fixed blocks, and those cannot exist between a cluster and its text
+    // nodes lowest common ancestor as isAutosizingCluster would have made them into their own independent
+    // cluster.
+    RenderBlock* containingBlock = firstNode->containingBlock();
+    ASSERT(containingBlock->isDescendantOf(cluster));
+
+    return containingBlock;
+}
+
+const RenderObject* TextAutosizer::findFirstTextLeafNotInCluster(const RenderObject* parent, size_t& depth, TraversalDirection direction)
+{
+    if (parent->isEmpty())
+        return parent->isText() ? parent : 0;
+
+    ++depth;
+    const RenderObject* child = (direction == FirstToLast) ? parent->firstChild() : parent->lastChild();
+    while (child) {
+        if (!isAutosizingContainer(child) || !isIndependentDescendant(toRenderBlock(child))) {
+            const RenderObject* leaf = findFirstTextLeafNotInCluster(child, depth, direction);
+            if (leaf)
+                return leaf;
+        }
+        child = (direction == FirstToLast) ? child->nextSibling() : child->previousSibling();
+    }
+    --depth;
+
+    return 0;
+}
+
+namespace {
+
+// Compares the width of the specified cluster's roots in descending order.
+bool clusterWiderThanComparisonFn(const TextAutosizingClusterInfo& first, const TextAutosizingClusterInfo& second)
+{
+    return first.root->contentLogicalWidth() > second.root->contentLogicalWidth();
+}
+
+} // namespace
+
+void TextAutosizer::getNarrowDescendantsGroupedByWidth(const TextAutosizingClusterInfo& parentClusterInfo, Vector<Vector<TextAutosizingClusterInfo> >& groups)
+{
+    ASSERT(parentClusterInfo.blockContainingAllText);
+    ASSERT(groups.isEmpty());
+
+    Vector<TextAutosizingClusterInfo> clusterInfos(parentClusterInfo.narrowDescendants);
+    if (clusterInfos.isEmpty())
+        return;
+
+    std::sort(clusterInfos.begin(), clusterInfos.end(), &clusterWiderThanComparisonFn);
+    groups.grow(1);
+
+    // If the width difference between two consecutive elements of |clusterInfos| is greater than
+    // this empirically determined value, the next element should start a new group.
+    const float maxWidthDifferenceWithinGroup = 100;
+    for (size_t i = 0; i < clusterInfos.size(); ++i) {
+        groups.last().append(clusterInfos[i]);
+
+        if (i + 1 < clusterInfos.size()) {
+            float currentWidth = clusterInfos[i].root->contentLogicalWidth();
+            float nextWidth = clusterInfos[i + 1].root->contentLogicalWidth();
+            if (currentWidth - nextWidth > maxWidthDifferenceWithinGroup)
+                groups.grow(groups.size() + 1);
+        }
+    }
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/TextAutosizer.h b/Source/core/rendering/TextAutosizer.h
new file mode 100644
index 0000000..5b38d07
--- /dev/null
+++ b/Source/core/rendering/TextAutosizer.h
@@ -0,0 +1,106 @@
+/*
+ * Copyright (C) 2012 Google 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 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 TextAutosizer_h
+#define TextAutosizer_h
+
+#include "HTMLNames.h"
+#include "core/platform/text/WritingMode.h"
+#include <wtf/Noncopyable.h>
+#include <wtf/PassOwnPtr.h>
+
+namespace WebCore {
+
+class Document;
+class RenderBlock;
+class RenderObject;
+class RenderText;
+struct TextAutosizingWindowInfo;
+struct TextAutosizingClusterInfo;
+
+class TextAutosizer {
+    WTF_MAKE_NONCOPYABLE(TextAutosizer);
+
+public:
+    static PassOwnPtr<TextAutosizer> create(Document* document) { return adoptPtr(new TextAutosizer(document)); }
+
+    virtual ~TextAutosizer();
+
+    bool processSubtree(RenderObject* layoutRoot);
+    void recalculateMultipliers();
+
+    static float computeAutosizedFontSize(float specifiedSize, float multiplier);
+
+private:
+    enum TraversalDirection {
+        FirstToLast,
+        LastToFirst
+    };
+
+    explicit TextAutosizer(Document*);
+
+    float clusterMultiplier(WritingMode, const TextAutosizingWindowInfo&, float textWidth) const;
+
+    void processClusterInternal(TextAutosizingClusterInfo&, RenderBlock* container, RenderObject* subtreeRoot, const TextAutosizingWindowInfo&, float multiplier);
+    void processCluster(TextAutosizingClusterInfo&, RenderBlock* container, RenderObject* subtreeRoot, const TextAutosizingWindowInfo&);
+    void processCompositeCluster(Vector<TextAutosizingClusterInfo>&, const TextAutosizingWindowInfo&);
+    void processContainer(float multiplier, RenderBlock* container, TextAutosizingClusterInfo&, RenderObject* subtreeRoot, const TextAutosizingWindowInfo&);
+
+    void setMultiplier(RenderObject*, float);
+
+    static bool isAutosizingContainer(const RenderObject*);
+    static bool isNarrowDescendant(const RenderBlock*, TextAutosizingClusterInfo& parentClusterInfo);
+    static bool isWiderDescendant(const RenderBlock*, const TextAutosizingClusterInfo& parentClusterInfo);
+    static bool isIndependentDescendant(const RenderBlock*);
+    static bool isAutosizingCluster(const RenderBlock*, TextAutosizingClusterInfo& parentClusterInfo);
+
+    static bool containerShouldBeAutosized(const RenderBlock* container);
+    static bool containerContainsOneOfTags(const RenderBlock* cluster, const Vector<QualifiedName>& tags);
+    static bool containerIsRowOfLinks(const RenderObject* container);
+    static bool contentHeightIsConstrained(const RenderBlock* container);
+    static bool clusterShouldBeAutosized(TextAutosizingClusterInfo&, float blockWidth);
+    static bool compositeClusterShouldBeAutosized(Vector<TextAutosizingClusterInfo>&, float blockWidth);
+    static void measureDescendantTextWidth(const RenderBlock* container, TextAutosizingClusterInfo&, float minTextWidth, float& textWidth);
+
+    // Use to traverse the tree of descendants, excluding descendants of containers (but returning the containers themselves).
+    static RenderObject* nextInPreOrderSkippingDescendantsOfContainers(const RenderObject*, const RenderObject* stayWithin);
+
+    static const RenderBlock* findDeepestBlockContainingAllText(const RenderBlock* cluster);
+
+    // Depending on the traversal direction specified, finds the first or the last leaf text node child that doesn't
+    // belong to any cluster.
+    static const RenderObject* findFirstTextLeafNotInCluster(const RenderObject*, size_t& depth, TraversalDirection);
+
+    // Returns groups of narrow descendants of a given autosizing cluster. The groups are combined
+    // by the difference between the width of the descendant and the width of the parent cluster's
+    // |blockContainingAllText|.
+    static void getNarrowDescendantsGroupedByWidth(const TextAutosizingClusterInfo& parentClusterInfo, Vector<Vector<TextAutosizingClusterInfo> >&);
+
+    Document* m_document;
+};
+
+} // namespace WebCore
+
+#endif // TextAutosizer_h
diff --git a/Source/core/rendering/TrailingFloatsRootInlineBox.h b/Source/core/rendering/TrailingFloatsRootInlineBox.h
new file mode 100644
index 0000000..9bd0530
--- /dev/null
+++ b/Source/core/rendering/TrailingFloatsRootInlineBox.h
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2010 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. 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 INC. 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 TrailingFloatsRootInlineBox_h
+#define TrailingFloatsRootInlineBox_h
+
+#include "core/rendering/RootInlineBox.h"
+
+namespace WebCore {
+
+class TrailingFloatsRootInlineBox FINAL : public RootInlineBox {
+public:
+    TrailingFloatsRootInlineBox(RenderBlock* block)
+        : RootInlineBox(block)
+    {
+        setHasVirtualLogicalHeight();
+    }
+
+private:
+    virtual float virtualLogicalHeight() const { return 0; }
+};
+
+} // namespace WebCore
+
+#endif // TrailingFloatsRootInlineBox_h
diff --git a/Source/core/rendering/VerticalPositionCache.h b/Source/core/rendering/VerticalPositionCache.h
new file mode 100644
index 0000000..d853ca8
--- /dev/null
+++ b/Source/core/rendering/VerticalPositionCache.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2010 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. 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 INC. 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 VerticalPositionCache_h
+#define VerticalPositionCache_h
+
+#include "core/platform/graphics/FontBaseline.h"
+#include <wtf/HashMap.h>
+
+namespace WebCore {
+
+class RenderObject;
+
+// Values for vertical alignment.
+const int PositionUndefined = 0x80000000;
+
+class VerticalPositionCache {
+    WTF_MAKE_NONCOPYABLE(VerticalPositionCache);
+public:
+    VerticalPositionCache()
+    { }
+    
+    int get(RenderObject* renderer, FontBaseline baselineType) const
+    {
+        const HashMap<RenderObject*, int>& mapToCheck = baselineType == AlphabeticBaseline ? m_alphabeticPositions : m_ideographicPositions;
+        const HashMap<RenderObject*, int>::const_iterator it = mapToCheck.find(renderer);
+        if (it == mapToCheck.end())
+            return PositionUndefined;
+        return it->value;
+    }
+    
+    void set(RenderObject* renderer, FontBaseline baselineType, int position)
+    {
+        if (baselineType == AlphabeticBaseline)
+            m_alphabeticPositions.set(renderer, position);
+        else
+            m_ideographicPositions.set(renderer, position);
+    }
+
+private:
+    HashMap<RenderObject*, int> m_alphabeticPositions;
+    HashMap<RenderObject*, int> m_ideographicPositions;
+};
+
+} // namespace WebCore
+
+#endif // VerticalPositionCache_h
diff --git a/Source/core/rendering/break_lines.cpp b/Source/core/rendering/break_lines.cpp
new file mode 100644
index 0000000..90dbffb
--- /dev/null
+++ b/Source/core/rendering/break_lines.cpp
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2005, 2007, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2011 Google 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. 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 INC. 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 "core/rendering/break_lines.h"
+
+#include "core/platform/text/TextBreakIterator.h"
+#include <wtf/ASCIICType.h>
+#include <wtf/StdLibExtras.h>
+#include <wtf/unicode/CharacterNames.h>
+
+namespace WebCore {
+
+template<bool treatNoBreakSpaceAsBreak>
+static inline bool isBreakableSpace(UChar ch)
+{
+    switch (ch) {
+    case ' ':
+    case '\n':
+    case '\t':
+        return true;
+    case noBreakSpace:
+        return treatNoBreakSpaceAsBreak;
+    default:
+        return false;
+    }
+}
+
+static const UChar asciiLineBreakTableFirstChar = '!';
+static const UChar asciiLineBreakTableLastChar = 127;
+
+// Pack 8 bits into one byte
+#define B(a, b, c, d, e, f, g, h) \
+    ((a) | ((b) << 1) | ((c) << 2) | ((d) << 3) | ((e) << 4) | ((f) << 5) | ((g) << 6) | ((h) << 7))
+
+// Line breaking table row for each digit (0-9)
+#define DI { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+
+// Line breaking table row for ascii letters (a-z A-Z)
+#define AL { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
+
+#define F 0xFF
+
+// Line breaking table for printable ASCII characters. Line breaking opportunities in this table are as below:
+// - before opening punctuations such as '(', '<', '[', '{' after certain characters (compatible with Firefox 3.6);
+// - after '-' and '?' (backward-compatible, and compatible with Internet Explorer).
+// Please refer to <https://bugs.webkit.org/show_bug.cgi?id=37698> for line breaking matrixes of different browsers
+// and the ICU standard.
+static const unsigned char asciiLineBreakTable[][(asciiLineBreakTableLastChar - asciiLineBreakTableFirstChar) / 8 + 1] = {
+    //  !  "  #  $  %  &  '  (     )  *  +  ,  -  .  /  0  1-8   9  :  ;  <  =  >  ?  @     A-X      Y  Z  [  \  ]  ^  _  `     a-x      y  z  {  |  }  ~  DEL
+    { B(0, 0, 0, 0, 0, 0, 0, 1), B(0, 0, 0, 0, 0, 0, 0, 0), 0, B(0, 0, 0, 1, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 1, 0, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 1, 0, 0, 0, 0, 0) }, // !
+    { B(0, 0, 0, 0, 0, 0, 0, 1), B(0, 0, 0, 0, 0, 0, 0, 0), 0, B(0, 0, 0, 1, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 1, 0, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 1, 0, 0, 0, 0, 0) }, // "
+    { B(0, 0, 0, 0, 0, 0, 0, 1), B(0, 0, 0, 0, 0, 0, 0, 0), 0, B(0, 0, 0, 1, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 1, 0, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 1, 0, 0, 0, 0, 0) }, // #
+    { B(0, 0, 0, 0, 0, 0, 0, 0), B(0, 0, 0, 0, 0, 0, 0, 0), 0, B(0, 0, 0, 0, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 0, 0, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 0, 0, 0, 0, 0, 0) }, // $
+    { B(0, 0, 0, 0, 0, 0, 0, 1), B(0, 0, 0, 0, 0, 0, 0, 0), 0, B(0, 0, 0, 1, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 1, 0, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 1, 0, 0, 0, 0, 0) }, // %
+    { B(0, 0, 0, 0, 0, 0, 0, 1), B(0, 0, 0, 0, 0, 0, 0, 0), 0, B(0, 0, 0, 1, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 1, 0, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 1, 0, 0, 0, 0, 0) }, // &
+    { B(0, 0, 0, 0, 0, 0, 0, 0), B(0, 0, 0, 0, 0, 0, 0, 0), 0, B(0, 0, 0, 0, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 0, 0, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 0, 0, 0, 0, 0, 0) }, // '
+    { B(0, 0, 0, 0, 0, 0, 0, 0), B(0, 0, 0, 0, 0, 0, 0, 0), 0, B(0, 0, 0, 0, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 0, 0, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 0, 0, 0, 0, 0, 0) }, // (
+    { B(0, 0, 0, 0, 0, 0, 0, 1), B(0, 0, 0, 0, 0, 0, 0, 0), 0, B(0, 0, 0, 1, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 1, 0, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 1, 0, 0, 0, 0, 0) }, // )
+    { B(0, 0, 0, 0, 0, 0, 0, 1), B(0, 0, 0, 0, 0, 0, 0, 0), 0, B(0, 0, 0, 1, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 1, 0, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 1, 0, 0, 0, 0, 0) }, // *
+    { B(0, 0, 0, 0, 0, 0, 0, 1), B(0, 0, 0, 0, 0, 0, 0, 0), 0, B(0, 0, 0, 1, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 1, 0, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 1, 0, 0, 0, 0, 0) }, // +
+    { B(0, 0, 0, 0, 0, 0, 0, 1), B(0, 0, 0, 0, 0, 0, 0, 0), 0, B(0, 0, 0, 1, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 1, 0, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 1, 0, 0, 0, 0, 0) }, // ,
+    { B(1, 1, 1, 1, 1, 1, 1, 1), B(1, 1, 1, 1, 1, 0, 1, 0), 0, B(0, 1, 1, 1, 1, 1, 1, 1), F, F, F, B(1, 1, 1, 1, 1, 1, 1, 1), F, F, F, B(1, 1, 1, 1, 1, 1, 1, 1) }, // - Note: breaking before '0'-'9' is handled hard-coded in shouldBreakAfter().
+    { B(0, 0, 0, 0, 0, 0, 0, 1), B(0, 0, 0, 0, 0, 0, 0, 0), 0, B(0, 0, 0, 1, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 1, 0, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 1, 0, 0, 0, 0, 0) }, // .
+    { B(0, 0, 0, 0, 0, 0, 0, 0), B(0, 0, 0, 0, 0, 0, 0, 0), 0, B(0, 0, 0, 0, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 0, 0, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 0, 0, 0, 0, 0, 0) }, // /
+    DI,  DI,  DI,  DI,  DI,  DI,  DI,  DI,  DI,  DI, // 0-9
+    { B(0, 0, 0, 0, 0, 0, 0, 1), B(0, 0, 0, 0, 0, 0, 0, 0), 0, B(0, 0, 0, 1, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 1, 0, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 1, 0, 0, 0, 0, 0) }, // :
+    { B(0, 0, 0, 0, 0, 0, 0, 1), B(0, 0, 0, 0, 0, 0, 0, 0), 0, B(0, 0, 0, 1, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 1, 0, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 1, 0, 0, 0, 0, 0) }, // ;
+    { B(0, 0, 0, 0, 0, 0, 0, 0), B(0, 0, 0, 0, 0, 0, 0, 0), 0, B(0, 0, 0, 0, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 0, 0, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 0, 0, 0, 0, 0, 0) }, // <
+    { B(0, 0, 0, 0, 0, 0, 0, 1), B(0, 0, 0, 0, 0, 0, 0, 0), 0, B(0, 0, 0, 1, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 1, 0, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 1, 0, 0, 0, 0, 0) }, // =
+    { B(0, 0, 0, 0, 0, 0, 0, 1), B(0, 0, 0, 0, 0, 0, 0, 0), 0, B(0, 0, 0, 1, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 1, 0, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 1, 0, 0, 0, 0, 0) }, // >
+    { B(0, 0, 1, 1, 1, 1, 0, 1), B(0, 1, 1, 0, 1, 0, 0, 1), F, B(1, 0, 0, 1, 1, 1, 0, 1), F, F, F, B(1, 1, 1, 1, 0, 1, 1, 1), F, F, F, B(1, 1, 1, 1, 0, 1, 1, 0) }, // ?
+    { B(0, 0, 0, 0, 0, 0, 0, 0), B(0, 0, 0, 0, 0, 0, 0, 0), 0, B(0, 0, 0, 0, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 0, 0, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 0, 0, 0, 0, 0, 0) }, // @
+    AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL, // A-Z
+    { B(0, 0, 0, 0, 0, 0, 0, 0), B(0, 0, 0, 0, 0, 0, 0, 0), 0, B(0, 0, 0, 0, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 0, 0, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 0, 0, 0, 0, 0, 0) }, // [
+    { B(0, 0, 0, 0, 0, 0, 0, 1), B(0, 0, 0, 0, 0, 0, 0, 0), 0, B(0, 0, 0, 1, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 1, 0, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 1, 0, 0, 0, 0, 0) }, // '\'
+    { B(0, 0, 0, 0, 0, 0, 0, 1), B(0, 0, 0, 0, 0, 0, 0, 0), 0, B(0, 0, 0, 1, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 1, 0, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 1, 0, 0, 0, 0, 0) }, // ]
+    { B(0, 0, 0, 0, 0, 0, 0, 0), B(0, 0, 0, 0, 0, 0, 0, 0), 0, B(0, 0, 0, 0, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 0, 0, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 0, 0, 0, 0, 0, 0) }, // ^
+    { B(0, 0, 0, 0, 0, 0, 0, 0), B(0, 0, 0, 0, 0, 0, 0, 0), 0, B(0, 0, 0, 0, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 0, 0, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 0, 0, 0, 0, 0, 0) }, // _
+    { B(0, 0, 0, 0, 0, 0, 0, 0), B(0, 0, 0, 0, 0, 0, 0, 0), 0, B(0, 0, 0, 0, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 0, 0, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 0, 0, 0, 0, 0, 0) }, // `
+    AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL,  AL, // a-z
+    { B(0, 0, 0, 0, 0, 0, 0, 0), B(0, 0, 0, 0, 0, 0, 0, 0), 0, B(0, 0, 0, 0, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 0, 0, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 0, 0, 0, 0, 0, 0) }, // {
+    { B(0, 0, 0, 0, 0, 0, 0, 1), B(0, 0, 0, 0, 0, 0, 0, 0), 0, B(0, 0, 0, 1, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 1, 0, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 1, 0, 0, 0, 0, 0) }, // |
+    { B(0, 0, 0, 0, 0, 0, 0, 1), B(0, 0, 0, 0, 0, 0, 0, 0), 0, B(0, 0, 0, 1, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 1, 0, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 1, 0, 0, 0, 0, 0) }, // }
+    { B(0, 0, 0, 0, 0, 0, 0, 1), B(0, 0, 0, 0, 0, 0, 0, 0), 0, B(0, 0, 0, 1, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 1, 0, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 1, 0, 0, 0, 0, 0) }, // ~
+    { B(0, 0, 0, 0, 0, 0, 0, 0), B(0, 0, 0, 0, 0, 0, 0, 0), 0, B(0, 0, 0, 0, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 0, 0, 0, 0, 0, 0), 0, 0, 0, B(0, 0, 0, 0, 0, 0, 0, 0) }, // DEL
+};
+
+#undef B
+#undef F
+#undef DI
+#undef AL
+
+COMPILE_ASSERT(WTF_ARRAY_LENGTH(asciiLineBreakTable) == asciiLineBreakTableLastChar - asciiLineBreakTableFirstChar + 1, TestLineBreakTableConsistency);
+
+static inline bool shouldBreakAfter(UChar lastCh, UChar ch, UChar nextCh)
+{
+    // Don't allow line breaking between '-' and a digit if the '-' may mean a minus sign in the context,
+    // while allow breaking in 'ABCD-1234' and '1234-5678' which may be in long URLs.
+    if (ch == '-' && isASCIIDigit(nextCh))
+        return isASCIIAlphanumeric(lastCh);
+
+    // If both ch and nextCh are ASCII characters, use a lookup table for enhanced speed and for compatibility
+    // with other browsers (see comments for asciiLineBreakTable for details).
+    if (ch >= asciiLineBreakTableFirstChar && ch <= asciiLineBreakTableLastChar
+            && nextCh >= asciiLineBreakTableFirstChar && nextCh <= asciiLineBreakTableLastChar) {
+        const unsigned char* tableRow = asciiLineBreakTable[ch - asciiLineBreakTableFirstChar];
+        int nextChIndex = nextCh - asciiLineBreakTableFirstChar;
+        return tableRow[nextChIndex / 8] & (1 << (nextChIndex % 8));
+    }
+    // Otherwise defer to the Unicode algorithm by returning false.
+    return false;
+}
+
+template<bool treatNoBreakSpaceAsBreak>
+inline bool needsLineBreakIterator(UChar ch)
+{
+    if (treatNoBreakSpaceAsBreak)
+        return ch > asciiLineBreakTableLastChar;
+    return ch > asciiLineBreakTableLastChar && ch != noBreakSpace;
+}
+
+template<typename CharacterType, bool treatNoBreakSpaceAsBreak>
+static inline int nextBreakablePosition(LazyLineBreakIterator& lazyBreakIterator, const CharacterType* str, unsigned length, int pos)
+{
+    int len = static_cast<int>(length);
+    int nextBreak = -1;
+
+    CharacterType lastLastCh = pos > 1 ? str[pos - 2] : static_cast<CharacterType>(lazyBreakIterator.secondToLastCharacter());
+    CharacterType lastCh = pos > 0 ? str[pos - 1] : static_cast<CharacterType>(lazyBreakIterator.lastCharacter());
+    for (int i = pos; i < len; i++) {
+        CharacterType ch = str[i];
+
+        if (isBreakableSpace<treatNoBreakSpaceAsBreak>(ch) || shouldBreakAfter(lastLastCh, lastCh, ch))
+            return i;
+
+        if (needsLineBreakIterator<treatNoBreakSpaceAsBreak>(ch) || needsLineBreakIterator<treatNoBreakSpaceAsBreak>(lastCh)) {
+            if (nextBreak < i && i) {
+                TextBreakIterator* breakIterator = lazyBreakIterator.get();
+                if (breakIterator)
+                    nextBreak = textBreakFollowing(breakIterator, i - 1);
+            }
+            if (i == nextBreak && !isBreakableSpace<treatNoBreakSpaceAsBreak>(lastCh))
+                return i;
+        }
+
+        lastLastCh = lastCh;
+        lastCh = ch;
+    }
+
+    return len;
+}
+
+int nextBreakablePositionIgnoringNBSP(LazyLineBreakIterator& lazyBreakIterator, int pos)
+{
+    String string = lazyBreakIterator.string();
+    if (string.is8Bit())
+        return nextBreakablePosition<LChar, false>(lazyBreakIterator, string.characters8(), string.length(), pos);
+    return nextBreakablePosition<UChar, false>(lazyBreakIterator, string.characters16(), string.length(), pos);
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/break_lines.h b/Source/core/rendering/break_lines.h
new file mode 100644
index 0000000..072bc8d
--- /dev/null
+++ b/Source/core/rendering/break_lines.h
@@ -0,0 +1,41 @@
+/*
+ * 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 {
+
+class LazyLineBreakIterator;
+
+int nextBreakablePositionIgnoringNBSP(LazyLineBreakIterator&, int pos);
+
+inline bool isBreakable(LazyLineBreakIterator& lazyBreakIterator, int pos, int& nextBreakable)
+{
+    if (pos > nextBreakable)
+        nextBreakable = nextBreakablePositionIgnoringNBSP(lazyBreakIterator, pos);
+    return pos == nextBreakable;
+}
+
+} // namespace WebCore
+
+#endif // break_lines_h
diff --git a/Source/core/rendering/exclusions/ExclusionInterval.cpp b/Source/core/rendering/exclusions/ExclusionInterval.cpp
new file mode 100644
index 0000000..35fa2fa
--- /dev/null
+++ b/Source/core/rendering/exclusions/ExclusionInterval.cpp
@@ -0,0 +1,166 @@
+/*
+ * Copyright (C) 2012 Adobe Systems Incorporated. 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 THE COPYRIGHT HOLDERS AND 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 THE
+ * COPYRIGHT HOLDER 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 "core/rendering/exclusions/ExclusionInterval.h"
+
+#include <wtf/MathExtras.h>
+
+namespace WebCore {
+
+struct IntervalX1Comparator {
+    bool operator() (const ExclusionInterval& i1, const ExclusionInterval& i2) const
+    {
+        return i1.x1 < i2.x1;
+    }
+};
+
+bool ExclusionInterval::intersect(const ExclusionInterval& i, ExclusionInterval& rv) const
+{
+    if (x2 < i.x1 || x1 > i.x2)
+        return false;
+    rv.x1 = std::max(x1, i.x1);
+    rv.x2 = std::min(x2, i.x2);
+    return true;
+}
+
+void sortExclusionIntervals(Vector<ExclusionInterval>& v)
+{
+    std::sort(v.begin(), v.end(), IntervalX1Comparator());
+}
+
+void mergeExclusionIntervals(const Vector<ExclusionInterval>& v1, const Vector<ExclusionInterval>& v2, Vector<ExclusionInterval>& rv)
+{
+    if (!v1.size())
+        rv.appendRange(v2.begin(), v2.end());
+    else if (!v2.size())
+        rv.appendRange(v1.begin(), v1.end());
+    else {
+        Vector<ExclusionInterval> v(v1.size() + v2.size());
+        ExclusionInterval* interval = 0;
+
+        std::merge(v1.begin(), v1.end(), v2.begin(), v2.end(), v.begin(), IntervalX1Comparator());
+
+        for (size_t i = 0; i < v.size(); i++) {
+            if (!interval)
+                interval = &v[i];
+            else if (v[i].x1 >= interval->x1 && v[i].x1 <= interval->x2) // FIXME: 1st <= test not needed?
+                interval->x2 = std::max(interval->x2, v[i].x2);
+            else {
+                rv.append(*interval);
+                interval = &v[i];
+            }
+        }
+
+        if (interval)
+            rv.append(*interval);
+    }
+}
+
+void intersectExclusionIntervals(const Vector<ExclusionInterval>& v1, const Vector<ExclusionInterval>& v2, Vector<ExclusionInterval>& rv)
+{
+    size_t v1Size = v1.size();
+    size_t v2Size = v2.size();
+
+    if (!v1Size || !v2Size)
+        return;
+
+    ExclusionInterval interval;
+    bool overlap = false;
+    size_t i1 = 0;
+    size_t i2 = 0;
+
+    while (i1 < v1Size && i2 < v2Size) {
+        ExclusionInterval v12;
+        if (v1[i1].intersect(v2[i2], v12)) {
+            if (!overlap || !v12.intersect(interval, interval)) {
+                if (overlap)
+                    rv.append(interval);
+                interval = v12;
+                overlap = true;
+            }
+            if (v1[i1].x2 < v2[i2].x2)
+                i1++;
+            else
+                i2++;
+        } else {
+            if (overlap)
+                rv.append(interval);
+            overlap = false;
+            if (v1[i1].x1 < v2[i2].x1)
+                i1++;
+            else
+                i2++;
+        }
+    }
+
+    if (overlap)
+        rv.append(interval);
+}
+
+void subtractExclusionIntervals(const Vector<ExclusionInterval>& v1, const Vector<ExclusionInterval>& v2, Vector<ExclusionInterval>& rv)
+{
+    size_t v1Size = v1.size();
+    size_t v2Size = v2.size();
+
+    if (!v1Size)
+        return;
+
+    if (!v2Size)
+        rv.appendRange(v1.begin(), v1.end());
+    else {
+        size_t i1 = 0, i2 = 0;
+        rv.appendRange(v1.begin(), v1.end());
+
+        while (i1 < rv.size() && i2 < v2Size) {
+            ExclusionInterval& interval1 = rv[i1];
+            const ExclusionInterval& interval2 = v2[i2];
+
+            if (interval2.x1 <= interval1.x1 && interval2.x2 >= interval1.x2)
+                rv.remove(i1);
+            else if (interval2.x2 < interval1.x1)
+                i2 += 1;
+            else if (interval2.x1 > interval1.x2)
+                i1 += 1;
+            else if (interval2.x1 > interval1.x1 && interval2.x2 < interval1.x2) {
+                rv.insert(i1, ExclusionInterval(interval1.x1, interval2.x1));
+                interval1.x1 = interval2.x2;
+                i2 += 1;
+            } else if (interval2.x1 <= interval1.x1) {
+                interval1.x1 = interval2.x2;
+                i2 += 1;
+            } else  { // (interval2.x2 >= interval1.x2)
+                interval1.x2 = interval2.x1;
+                i1 += 1;
+            }
+        }
+    }
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/exclusions/ExclusionInterval.h b/Source/core/rendering/exclusions/ExclusionInterval.h
new file mode 100644
index 0000000..1e8e59f
--- /dev/null
+++ b/Source/core/rendering/exclusions/ExclusionInterval.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2012 Adobe Systems Incorporated. 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 THE COPYRIGHT HOLDERS AND 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 THE
+ * COPYRIGHT HOLDER 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 ExclusionInterval_h
+#define ExclusionInterval_h
+
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+struct ExclusionInterval {
+public:
+    float x1;
+    float x2;
+
+    ExclusionInterval(float x1 = 0, float x2 = 0)
+        : x1(x1)
+        , x2(x2)
+    {
+    }
+
+    bool intersect(const ExclusionInterval&, ExclusionInterval&) const;
+};
+
+void sortExclusionIntervals(Vector<ExclusionInterval>&);
+void mergeExclusionIntervals(const Vector<ExclusionInterval>&, const Vector<ExclusionInterval>&, Vector<ExclusionInterval>&);
+void intersectExclusionIntervals(const Vector<ExclusionInterval>&, const Vector<ExclusionInterval>&, Vector<ExclusionInterval>&);
+void subtractExclusionIntervals(const Vector<ExclusionInterval>&, const Vector<ExclusionInterval>&, Vector<ExclusionInterval>&);
+
+} // namespace WebCore
+
+#endif // ExclusionInterval_h
diff --git a/Source/core/rendering/exclusions/ExclusionPolygon.cpp b/Source/core/rendering/exclusions/ExclusionPolygon.cpp
new file mode 100644
index 0000000..b89d1e5
--- /dev/null
+++ b/Source/core/rendering/exclusions/ExclusionPolygon.cpp
@@ -0,0 +1,510 @@
+/*
+ * Copyright (C) 2012 Adobe Systems Incorporated. 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 THE COPYRIGHT HOLDERS AND 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 THE
+ * COPYRIGHT HOLDER 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 "core/rendering/exclusions/ExclusionPolygon.h"
+
+#include "core/platform/graphics/LayoutPoint.h"
+
+#include <wtf/MathExtras.h>
+
+namespace WebCore {
+
+enum EdgeIntersectionType {
+    Normal,
+    VertexMinY,
+    VertexMaxY,
+    VertexYBoth
+};
+
+struct EdgeIntersection {
+    const FloatPolygonEdge* edge;
+    FloatPoint point;
+    EdgeIntersectionType type;
+};
+
+static inline float leftSide(const FloatPoint& vertex1, const FloatPoint& vertex2, const FloatPoint& point)
+{
+    return ((point.x() - vertex1.x()) * (vertex2.y() - vertex1.y())) - ((vertex2.x() - vertex1.x()) * (point.y() - vertex1.y()));
+}
+
+static inline bool isReflexVertex(const FloatPoint& prevVertex, const FloatPoint& vertex, const FloatPoint& nextVertex)
+{
+    return leftSide(prevVertex, nextVertex, vertex) < 0;
+}
+
+static bool computeXIntersection(const FloatPolygonEdge* edgePointer, float y, EdgeIntersection& result)
+{
+    const FloatPolygonEdge& edge = *edgePointer;
+
+    if (edge.minY() > y || edge.maxY() < y)
+        return false;
+
+    const FloatPoint& vertex1 = edge.vertex1();
+    const FloatPoint& vertex2 = edge.vertex2();
+    float dy = vertex2.y() - vertex1.y();
+
+    float intersectionX;
+    EdgeIntersectionType intersectionType;
+
+    if (!dy) {
+        intersectionType = VertexYBoth;
+        intersectionX = edge.minX();
+    } else if (y == edge.minY()) {
+        intersectionType = VertexMinY;
+        intersectionX = (vertex1.y() < vertex2.y()) ? vertex1.x() : vertex2.x();
+    } else if (y == edge.maxY()) {
+        intersectionType = VertexMaxY;
+        intersectionX = (vertex1.y() > vertex2.y()) ? vertex1.x() : vertex2.x();
+    } else {
+        intersectionType = Normal;
+        intersectionX = ((y - vertex1.y()) * (vertex2.x() - vertex1.x()) / dy) + vertex1.x();
+    }
+
+    result.edge = edgePointer;
+    result.type = intersectionType;
+    result.point.set(intersectionX, y);
+
+    return true;
+}
+
+static inline FloatSize inwardEdgeNormal(const FloatPolygonEdge& edge)
+{
+    FloatSize edgeDelta = edge.vertex2() - edge.vertex1();
+    if (!edgeDelta.width())
+        return FloatSize((edgeDelta.height() > 0 ? -1 : 1), 0);
+    if (!edgeDelta.height())
+        return FloatSize(0, (edgeDelta.width() > 0 ? 1 : -1));
+    float edgeLength = edgeDelta.diagonalLength();
+    return FloatSize(-edgeDelta.height() / edgeLength, edgeDelta.width() / edgeLength);
+}
+
+static inline FloatSize outwardEdgeNormal(const FloatPolygonEdge& edge)
+{
+    return -inwardEdgeNormal(edge);
+}
+
+static inline void appendArc(Vector<FloatPoint>& vertices, const FloatPoint& arcCenter, float arcRadius, const FloatPoint& startArcVertex, const FloatPoint& endArcVertex, bool padding)
+{
+    float startAngle = atan2(startArcVertex.y() - arcCenter.y(), startArcVertex.x() - arcCenter.x());
+    float endAngle = atan2(endArcVertex.y() - arcCenter.y(), endArcVertex.x() - arcCenter.x());
+    const float twoPI = piFloat * 2;
+    if (startAngle < 0)
+        startAngle += twoPI;
+    if (endAngle < 0)
+        endAngle += twoPI;
+    float angle = (startAngle > endAngle) ? (startAngle - endAngle) : (startAngle + twoPI - endAngle);
+    const float arcSegmentCount = 5; // An odd number so that one arc vertex will be eactly arcRadius from arcCenter.
+    float angle5 =  ((padding) ? -angle : twoPI - angle) / arcSegmentCount;
+
+    vertices.append(startArcVertex);
+    for (unsigned i = 1; i < arcSegmentCount; ++i) {
+        float angle = startAngle + angle5 * i;
+        vertices.append(arcCenter + FloatPoint(cos(angle) * arcRadius, sin(angle) * arcRadius));
+    }
+    vertices.append(endArcVertex);
+}
+
+static inline void snapVerticesToLayoutUnitGrid(Vector<FloatPoint>& vertices)
+{
+    for (unsigned i = 0; i < vertices.size(); ++i)
+        vertices[i] = flooredLayoutPoint(vertices[i]);
+}
+
+static inline PassOwnPtr<FloatPolygon> computeShapePaddingBounds(const FloatPolygon& polygon, float padding, WindRule fillRule)
+{
+    OwnPtr<Vector<FloatPoint> > paddedVertices = adoptPtr(new Vector<FloatPoint>());
+    FloatPoint intersection;
+
+    for (unsigned i = 0; i < polygon.numberOfEdges(); ++i) {
+        const FloatPolygonEdge& thisEdge = polygon.edgeAt(i);
+        const FloatPolygonEdge& prevEdge = thisEdge.previousEdge();
+        OffsetPolygonEdge thisOffsetEdge(thisEdge, inwardEdgeNormal(thisEdge) * padding);
+        OffsetPolygonEdge prevOffsetEdge(prevEdge, inwardEdgeNormal(prevEdge) * padding);
+
+        if (prevOffsetEdge.intersection(thisOffsetEdge, intersection))
+            paddedVertices->append(intersection);
+        else if (isReflexVertex(prevEdge.vertex1(), thisEdge.vertex1(), thisEdge.vertex2()))
+            appendArc(*paddedVertices, thisEdge.vertex1(), padding, prevOffsetEdge.vertex2(), thisOffsetEdge.vertex1(), true);
+    }
+
+    snapVerticesToLayoutUnitGrid(*paddedVertices);
+    return adoptPtr(new FloatPolygon(paddedVertices.release(), fillRule));
+}
+
+static inline PassOwnPtr<FloatPolygon> computeShapeMarginBounds(const FloatPolygon& polygon, float margin, WindRule fillRule)
+{
+    OwnPtr<Vector<FloatPoint> > marginVertices = adoptPtr(new Vector<FloatPoint>());
+    FloatPoint intersection;
+
+    for (unsigned i = 0; i < polygon.numberOfEdges(); ++i) {
+        const FloatPolygonEdge& thisEdge = polygon.edgeAt(i);
+        const FloatPolygonEdge& prevEdge = thisEdge.previousEdge();
+        OffsetPolygonEdge thisOffsetEdge(thisEdge, outwardEdgeNormal(thisEdge) * margin);
+        OffsetPolygonEdge prevOffsetEdge(prevEdge, outwardEdgeNormal(prevEdge) * margin);
+
+        if (prevOffsetEdge.intersection(thisOffsetEdge, intersection))
+            marginVertices->append(intersection);
+        else
+            appendArc(*marginVertices, thisEdge.vertex1(), margin, prevOffsetEdge.vertex2(), thisOffsetEdge.vertex1(), false);
+    }
+
+    snapVerticesToLayoutUnitGrid(*marginVertices);
+    return adoptPtr(new FloatPolygon(marginVertices.release(), fillRule));
+}
+
+const FloatPolygon& ExclusionPolygon::shapePaddingBounds() const
+{
+    ASSERT(shapePadding() >= 0);
+    if (!shapePadding())
+        return m_polygon;
+
+    if (!m_paddingBounds)
+        m_paddingBounds = computeShapePaddingBounds(m_polygon, shapePadding(), m_polygon.fillRule());
+
+    return *m_paddingBounds;
+}
+
+const FloatPolygon& ExclusionPolygon::shapeMarginBounds() const
+{
+    ASSERT(shapeMargin() >= 0);
+    if (!shapeMargin())
+        return m_polygon;
+
+    if (!m_marginBounds)
+        m_marginBounds = computeShapeMarginBounds(m_polygon, shapeMargin(), m_polygon.fillRule());
+
+    return *m_marginBounds;
+}
+
+static inline bool getVertexIntersectionVertices(const EdgeIntersection& intersection, FloatPoint& prevVertex, FloatPoint& thisVertex, FloatPoint& nextVertex)
+{
+    if (intersection.type != VertexMinY && intersection.type != VertexMaxY)
+        return false;
+
+    ASSERT(intersection.edge && intersection.edge->polygon());
+    const FloatPolygon& polygon = *(intersection.edge->polygon());
+    const FloatPolygonEdge& thisEdge = *(intersection.edge);
+
+    if ((intersection.type == VertexMinY && (thisEdge.vertex1().y() < thisEdge.vertex2().y()))
+        || (intersection.type == VertexMaxY && (thisEdge.vertex1().y() > thisEdge.vertex2().y()))) {
+        prevVertex = polygon.vertexAt(thisEdge.previousEdge().vertexIndex1());
+        thisVertex = polygon.vertexAt(thisEdge.vertexIndex1());
+        nextVertex = polygon.vertexAt(thisEdge.vertexIndex2());
+    } else {
+        prevVertex = polygon.vertexAt(thisEdge.vertexIndex1());
+        thisVertex = polygon.vertexAt(thisEdge.vertexIndex2());
+        nextVertex = polygon.vertexAt(thisEdge.nextEdge().vertexIndex2());
+    }
+
+    return true;
+}
+
+static inline bool appendIntervalX(float x, bool inside, Vector<ExclusionInterval>& result)
+{
+    if (!inside)
+        result.append(ExclusionInterval(x));
+    else
+        result[result.size() - 1].x2 = x;
+
+    return !inside;
+}
+
+static bool compareEdgeIntersectionX(const EdgeIntersection& intersection1, const EdgeIntersection& intersection2)
+{
+    float x1 = intersection1.point.x();
+    float x2 = intersection2.point.x();
+    return (x1 == x2) ? intersection1.type < intersection2.type : x1 < x2;
+}
+
+static void computeXIntersections(const FloatPolygon& polygon, float y, bool isMinY, Vector<ExclusionInterval>& result)
+{
+    Vector<const FloatPolygonEdge*> edges;
+    if (!polygon.overlappingEdges(y, y, edges))
+        return;
+
+    Vector<EdgeIntersection> intersections;
+    EdgeIntersection intersection;
+    for (unsigned i = 0; i < edges.size(); ++i) {
+        if (computeXIntersection(edges[i], y, intersection) && intersection.type != VertexYBoth)
+            intersections.append(intersection);
+    }
+
+    if (intersections.size() < 2)
+        return;
+
+    std::sort(intersections.begin(), intersections.end(), WebCore::compareEdgeIntersectionX);
+
+    unsigned index = 0;
+    int windCount = 0;
+    bool inside = false;
+
+    while (index < intersections.size()) {
+        const EdgeIntersection& thisIntersection = intersections[index];
+        if (index + 1 < intersections.size()) {
+            const EdgeIntersection& nextIntersection = intersections[index + 1];
+            if ((thisIntersection.point.x() == nextIntersection.point.x()) && (thisIntersection.type == VertexMinY || thisIntersection.type == VertexMaxY)) {
+                if (thisIntersection.type == nextIntersection.type) {
+                    // Skip pairs of intersections whose types are VertexMaxY,VertexMaxY and VertexMinY,VertexMinY.
+                    index += 2;
+                } else {
+                    // Replace pairs of intersections whose types are VertexMinY,VertexMaxY or VertexMaxY,VertexMinY with one intersection.
+                    ++index;
+                }
+                continue;
+            }
+        }
+
+        const FloatPolygonEdge& thisEdge = *thisIntersection.edge;
+        bool evenOddCrossing = !windCount;
+
+        if (polygon.fillRule() == RULE_EVENODD) {
+            windCount += (thisEdge.vertex2().y() > thisEdge.vertex1().y()) ? 1 : -1;
+            evenOddCrossing = evenOddCrossing || !windCount;
+        }
+
+        if (evenOddCrossing) {
+            bool edgeCrossing = thisIntersection.type == Normal;
+            if (!edgeCrossing) {
+                FloatPoint prevVertex;
+                FloatPoint thisVertex;
+                FloatPoint nextVertex;
+
+                if (getVertexIntersectionVertices(thisIntersection, prevVertex, thisVertex, nextVertex)) {
+                    if (nextVertex.y() == y)
+                        edgeCrossing = (isMinY) ? prevVertex.y() > y : prevVertex.y() < y;
+                    else if (prevVertex.y() == y)
+                        edgeCrossing = (isMinY) ? nextVertex.y() > y : nextVertex.y() < y;
+                    else
+                        edgeCrossing = true;
+                }
+            }
+            if (edgeCrossing)
+                inside = appendIntervalX(thisIntersection.point.x(), inside, result);
+        }
+
+        ++index;
+    }
+}
+
+static void computeOverlappingEdgeXProjections(const FloatPolygon& polygon, float y1, float y2, Vector<ExclusionInterval>& result)
+{
+    Vector<const FloatPolygonEdge*> edges;
+    if (!polygon.overlappingEdges(y1, y2, edges))
+        return;
+
+    EdgeIntersection intersection;
+    for (unsigned i = 0; i < edges.size(); ++i) {
+        const FloatPolygonEdge *edge = edges[i];
+        float x1;
+        float x2;
+
+        if (edge->minY() < y1) {
+            computeXIntersection(edge, y1, intersection);
+            x1 = intersection.point.x();
+        } else
+            x1 = (edge->vertex1().y() < edge->vertex2().y()) ? edge->vertex1().x() : edge->vertex2().x();
+
+        if (edge->maxY() > y2) {
+            computeXIntersection(edge, y2, intersection);
+            x2 = intersection.point.x();
+        } else
+            x2 = (edge->vertex1().y() > edge->vertex2().y()) ? edge->vertex1().x() : edge->vertex2().x();
+
+        if (x1 > x2)
+            std::swap(x1, x2);
+
+        if (x2 > x1)
+            result.append(ExclusionInterval(x1, x2));
+    }
+
+    sortExclusionIntervals(result);
+}
+
+void ExclusionPolygon::getExcludedIntervals(float logicalTop, float logicalHeight, SegmentList& result) const
+{
+    const FloatPolygon& polygon = shapeMarginBounds();
+    if (polygon.isEmpty())
+        return;
+
+    float y1 = logicalTop;
+    float y2 = y1 + logicalHeight;
+
+    Vector<ExclusionInterval> y1XIntervals, y2XIntervals;
+    computeXIntersections(polygon, y1, true, y1XIntervals);
+    computeXIntersections(polygon, y2, false, y2XIntervals);
+
+    Vector<ExclusionInterval> mergedIntervals;
+    mergeExclusionIntervals(y1XIntervals, y2XIntervals, mergedIntervals);
+
+    Vector<ExclusionInterval> edgeIntervals;
+    computeOverlappingEdgeXProjections(polygon, y1, y2, edgeIntervals);
+
+    Vector<ExclusionInterval> excludedIntervals;
+    mergeExclusionIntervals(mergedIntervals, edgeIntervals, excludedIntervals);
+
+    for (unsigned i = 0; i < excludedIntervals.size(); ++i) {
+        ExclusionInterval interval = excludedIntervals[i];
+        result.append(LineSegment(interval.x1, interval.x2));
+    }
+}
+
+void ExclusionPolygon::getIncludedIntervals(float logicalTop, float logicalHeight, SegmentList& result) const
+{
+    const FloatPolygon& polygon = shapePaddingBounds();
+    if (polygon.isEmpty())
+        return;
+
+    float y1 = logicalTop;
+    float y2 = y1 + logicalHeight;
+
+    Vector<ExclusionInterval> y1XIntervals, y2XIntervals;
+    computeXIntersections(polygon, y1, true, y1XIntervals);
+    computeXIntersections(polygon, y2, false, y2XIntervals);
+
+    Vector<ExclusionInterval> commonIntervals;
+    intersectExclusionIntervals(y1XIntervals, y2XIntervals, commonIntervals);
+
+    Vector<ExclusionInterval> edgeIntervals;
+    computeOverlappingEdgeXProjections(polygon, y1, y2, edgeIntervals);
+
+    Vector<ExclusionInterval> includedIntervals;
+    subtractExclusionIntervals(commonIntervals, edgeIntervals, includedIntervals);
+
+    for (unsigned i = 0; i < includedIntervals.size(); ++i) {
+        ExclusionInterval interval = includedIntervals[i];
+        result.append(LineSegment(interval.x1, interval.x2));
+    }
+}
+
+static inline bool firstFitRectInPolygon(const FloatPolygon& polygon, const FloatRect& rect, unsigned offsetEdgeIndex1, unsigned offsetEdgeIndex2)
+{
+    Vector<const FloatPolygonEdge*> edges;
+    if (!polygon.overlappingEdges(rect.y(), rect.maxY(), edges))
+        return true;
+
+    for (unsigned i = 0; i < edges.size(); ++i) {
+        const FloatPolygonEdge* edge = edges[i];
+        if (edge->edgeIndex() != offsetEdgeIndex1 && edge->edgeIndex() != offsetEdgeIndex2 && edge->overlapsRect(rect))
+            return false;
+    }
+
+    return true;
+}
+
+static inline bool aboveOrToTheLeft(const FloatRect& r1, const FloatRect& r2)
+{
+    if (r1.y() < r2.y())
+        return true;
+    if (r1.y() == r2.y())
+        return r1.x() < r2.x();
+    return false;
+}
+
+bool ExclusionPolygon::firstIncludedIntervalLogicalTop(float minLogicalIntervalTop, const FloatSize& minLogicalIntervalSize, float& result) const
+{
+    const FloatPolygon& polygon = shapePaddingBounds();
+    const FloatRect boundingBox = polygon.boundingBox();
+    if (minLogicalIntervalSize.width() > boundingBox.width())
+        return false;
+
+    float minY = std::max(boundingBox.y(), minLogicalIntervalTop);
+    float maxY = minY + minLogicalIntervalSize.height();
+
+    if (maxY > boundingBox.maxY())
+        return false;
+
+    Vector<const FloatPolygonEdge*> edges;
+    polygon.overlappingEdges(minLogicalIntervalTop, boundingBox.maxY(), edges);
+
+    float dx = minLogicalIntervalSize.width() / 2;
+    float dy = minLogicalIntervalSize.height() / 2;
+    Vector<OffsetPolygonEdge> offsetEdges;
+
+    for (unsigned i = 0; i < edges.size(); ++i) {
+        const FloatPolygonEdge& edge = *(edges[i]);
+        const FloatPoint& vertex0 = edge.previousEdge().vertex1();
+        const FloatPoint& vertex1 = edge.vertex1();
+        const FloatPoint& vertex2 = edge.vertex2();
+        Vector<OffsetPolygonEdge> offsetEdgeBuffer;
+
+        if (vertex2.y() > vertex1.y() ? vertex2.x() >= vertex1.x() : vertex1.x() >= vertex2.x()) {
+            offsetEdgeBuffer.append(OffsetPolygonEdge(edge, FloatSize(dx, -dy)));
+            offsetEdgeBuffer.append(OffsetPolygonEdge(edge, FloatSize(-dx, dy)));
+        } else {
+            offsetEdgeBuffer.append(OffsetPolygonEdge(edge, FloatSize(dx, dy)));
+            offsetEdgeBuffer.append(OffsetPolygonEdge(edge, FloatSize(-dx, -dy)));
+        }
+
+        if (isReflexVertex(vertex0, vertex1, vertex2)) {
+            if (vertex2.x() <= vertex1.x() && vertex0.x() <= vertex1.x())
+                offsetEdgeBuffer.append(OffsetPolygonEdge(vertex1, FloatSize(dx, -dy), FloatSize(dx, dy)));
+            else if (vertex2.x() >= vertex1.x() && vertex0.x() >= vertex1.x())
+                offsetEdgeBuffer.append(OffsetPolygonEdge(vertex1, FloatSize(-dx, -dy), FloatSize(-dx, dy)));
+            if (vertex2.y() <= vertex1.y() && vertex0.y() <= vertex1.y())
+                offsetEdgeBuffer.append(OffsetPolygonEdge(vertex1, FloatSize(-dx, dy), FloatSize(dx, dy)));
+            else if (vertex2.y() >= vertex1.y() && vertex0.y() >= vertex1.y())
+                offsetEdgeBuffer.append(OffsetPolygonEdge(vertex1, FloatSize(-dx, -dy), FloatSize(dx, -dy)));
+        }
+
+        for (unsigned j = 0; j < offsetEdgeBuffer.size(); ++j)
+            if (offsetEdgeBuffer[j].maxY() >= minY)
+                offsetEdges.append(offsetEdgeBuffer[j]);
+    }
+
+    offsetEdges.append(OffsetPolygonEdge(polygon, minLogicalIntervalTop, FloatSize(0, dy)));
+
+    FloatPoint offsetEdgesIntersection;
+    FloatRect firstFitRect;
+    bool firstFitFound = false;
+
+    for (unsigned i = 0; i < offsetEdges.size() - 1; ++i) {
+        for (unsigned j = i + 1; j < offsetEdges.size(); ++j) {
+            if (offsetEdges[i].intersection(offsetEdges[j], offsetEdgesIntersection)) {
+                FloatPoint potentialFirstFitLocation(offsetEdgesIntersection.x() - dx, offsetEdgesIntersection.y() - dy);
+                FloatRect potentialFirstFitRect(potentialFirstFitLocation, minLogicalIntervalSize);
+                if ((offsetEdges[i].basis() == OffsetPolygonEdge::LineTop
+                    || offsetEdges[j].basis() == OffsetPolygonEdge::LineTop
+                    || potentialFirstFitLocation.y() >= minLogicalIntervalTop)
+                    && (!firstFitFound || aboveOrToTheLeft(potentialFirstFitRect, firstFitRect))
+                    && polygon.contains(offsetEdgesIntersection)
+                    && firstFitRectInPolygon(polygon, potentialFirstFitRect, offsetEdges[i].edgeIndex(), offsetEdges[j].edgeIndex())) {
+                    firstFitFound = true;
+                    firstFitRect = potentialFirstFitRect;
+                }
+            }
+        }
+    }
+
+    if (firstFitFound)
+        result = firstFitRect.y();
+    return firstFitFound;
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/exclusions/ExclusionPolygon.h b/Source/core/rendering/exclusions/ExclusionPolygon.h
new file mode 100644
index 0000000..7fbc4f0
--- /dev/null
+++ b/Source/core/rendering/exclusions/ExclusionPolygon.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2012 Adobe Systems Incorporated. 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 THE COPYRIGHT HOLDERS AND 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 THE
+ * COPYRIGHT HOLDER 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 ExclusionPolygon_h
+#define ExclusionPolygon_h
+
+#include "core/platform/graphics/FloatPolygon.h"
+#include "core/rendering/exclusions/ExclusionInterval.h"
+#include "core/rendering/exclusions/ExclusionShape.h"
+
+namespace WebCore {
+
+class OffsetPolygonEdge : public VertexPair {
+public:
+    enum Basis {
+        Edge,
+        Vertex,
+        LineTop
+    };
+
+    OffsetPolygonEdge(const FloatPolygonEdge& edge, const FloatSize& offset)
+        : m_vertex1(edge.vertex1() + offset)
+        , m_vertex2(edge.vertex2() + offset)
+        , m_edgeIndex(edge.edgeIndex())
+        , m_basis(Edge)
+    {
+    }
+
+    OffsetPolygonEdge(const FloatPoint& reflexVertex, const FloatSize& offset1, const FloatSize& offset2)
+        : m_vertex1(reflexVertex + offset1)
+        , m_vertex2(reflexVertex + offset2)
+        , m_edgeIndex(-1)
+        , m_basis(Vertex)
+    {
+    }
+
+    OffsetPolygonEdge(const FloatPolygon& polygon, float minLogicalIntervalTop, const FloatSize& offset)
+        : m_vertex1(FloatPoint(polygon.boundingBox().x(), minLogicalIntervalTop) + offset)
+        , m_vertex2(FloatPoint(polygon.boundingBox().maxX(), minLogicalIntervalTop) + offset)
+        , m_edgeIndex(-1)
+        , m_basis(LineTop)
+    {
+    }
+
+    virtual const FloatPoint& vertex1() const OVERRIDE { return m_vertex1; }
+    virtual const FloatPoint& vertex2() const OVERRIDE { return m_vertex2; }
+    int edgeIndex() const { return m_edgeIndex; }
+    Basis basis() const { return m_basis; }
+
+private:
+    FloatPoint m_vertex1;
+    FloatPoint m_vertex2;
+    int m_edgeIndex;
+    Basis m_basis;
+};
+
+class ExclusionPolygon : public ExclusionShape {
+    WTF_MAKE_NONCOPYABLE(ExclusionPolygon);
+public:
+    ExclusionPolygon(PassOwnPtr<Vector<FloatPoint> > vertices, WindRule fillRule)
+        : ExclusionShape()
+        , m_polygon(vertices, fillRule)
+        , m_marginBounds(nullptr)
+        , m_paddingBounds(nullptr)
+    {
+    }
+
+    virtual FloatRect shapeMarginLogicalBoundingBox() const OVERRIDE { return shapeMarginBounds().boundingBox(); }
+    virtual FloatRect shapePaddingLogicalBoundingBox() const OVERRIDE { return shapePaddingBounds().boundingBox(); }
+    virtual bool isEmpty() const OVERRIDE { return m_polygon.isEmpty(); }
+    virtual void getExcludedIntervals(float logicalTop, float logicalHeight, SegmentList&) const OVERRIDE;
+    virtual void getIncludedIntervals(float logicalTop, float logicalHeight, SegmentList&) const OVERRIDE;
+    virtual bool firstIncludedIntervalLogicalTop(float minLogicalIntervalTop, const FloatSize& minLogicalIntervalSize, float&) const OVERRIDE;
+
+    const FloatPolygon& shapeMarginBounds() const;
+    const FloatPolygon& shapePaddingBounds() const;
+
+private:
+    FloatPolygon m_polygon;
+    mutable OwnPtr<FloatPolygon> m_marginBounds;
+    mutable OwnPtr<FloatPolygon> m_paddingBounds;
+};
+
+} // namespace WebCore
+
+#endif // ExclusionPolygon_h
diff --git a/Source/core/rendering/exclusions/ExclusionRectangle.cpp b/Source/core/rendering/exclusions/ExclusionRectangle.cpp
new file mode 100644
index 0000000..02c887b
--- /dev/null
+++ b/Source/core/rendering/exclusions/ExclusionRectangle.cpp
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) 2012 Adobe Systems Incorporated. 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 THE COPYRIGHT HOLDERS AND 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 THE
+ * COPYRIGHT HOLDER 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 "core/rendering/exclusions/ExclusionRectangle.h"
+
+#include <wtf/MathExtras.h>
+
+namespace WebCore {
+
+static inline float ellipseXIntercept(float y, float rx, float ry)
+{
+    ASSERT(ry > 0);
+    return rx * sqrt(1 - (y * y) / (ry * ry));
+}
+
+static inline float ellipseYIntercept(float x, float rx, float ry)
+{
+    ASSERT(rx > 0);
+    return ry * sqrt(1 - (x * x) / (rx * rx));
+}
+
+FloatRoundedRect FloatRoundedRect::paddingBounds(float padding) const
+{
+    ASSERT(padding >= 0);
+    if (!padding || isEmpty())
+        return *this;
+
+    float boundsX = x() + std::min(width() / 2, padding);
+    float boundsY = y() + std::min(height() / 2, padding);
+    float boundsWidth = std::max(0.0f, width() - padding * 2);
+    float boundsHeight = std::max(0.0f, height() - padding * 2);
+    float boundsRadiusX = std::max(0.0f, rx() - padding);
+    float boundsRadiusY = std::max(0.0f, ry() - padding);
+    return FloatRoundedRect(FloatRect(boundsX, boundsY, boundsWidth, boundsHeight), FloatSize(boundsRadiusX, boundsRadiusY));
+}
+
+FloatRoundedRect FloatRoundedRect::marginBounds(float margin) const
+{
+    ASSERT(margin >= 0);
+    if (!margin)
+        return *this;
+
+    float boundsX = x() - margin;
+    float boundsY = y() - margin;
+    float boundsWidth = width() + margin * 2;
+    float boundsHeight = height() + margin * 2;
+    float boundsRadiusX = rx() + margin;
+    float boundsRadiusY = ry() + margin;
+    return FloatRoundedRect(FloatRect(boundsX, boundsY, boundsWidth, boundsHeight), FloatSize(boundsRadiusX, boundsRadiusY));
+}
+
+FloatPoint FloatRoundedRect::cornerInterceptForWidth(float widthAtIntercept) const
+{
+    float xi = (width() - widthAtIntercept) / 2;
+    float yi = ry() - ellipseYIntercept(rx() - xi, rx(), ry());
+    return FloatPoint(xi, yi);
+}
+
+FloatRoundedRect ExclusionRectangle::shapePaddingBounds() const
+{
+    if (!m_haveInitializedPaddingBounds) {
+        m_haveInitializedPaddingBounds = true;
+        m_paddingBounds = m_bounds.paddingBounds(shapePadding());
+    }
+    return m_paddingBounds;
+}
+
+FloatRoundedRect ExclusionRectangle::shapeMarginBounds() const
+{
+    if (!m_haveInitializedMarginBounds) {
+        m_haveInitializedMarginBounds = true;
+        m_marginBounds = m_bounds.marginBounds(shapeMargin());
+    }
+    return m_marginBounds;
+}
+
+void ExclusionRectangle::getExcludedIntervals(float logicalTop, float logicalHeight, SegmentList& result) const
+{
+    const FloatRoundedRect& bounds = shapeMarginBounds();
+    if (bounds.isEmpty())
+        return;
+
+    float y1 = logicalTop;
+    float y2 = y1 + logicalHeight;
+
+    if (y2 < bounds.y() || y1 >= bounds.maxY())
+        return;
+
+    float x1 = bounds.x();
+    float x2 = bounds.maxX();
+
+    if (bounds.ry() > 0) {
+        if (y2 < bounds.y() + bounds.ry()) {
+            float yi = y2 - bounds.y() - bounds.ry();
+            float xi = ellipseXIntercept(yi, bounds.rx(), bounds.ry());
+            x1 = bounds.x() + bounds.rx() - xi;
+            x2 = bounds.maxX() - bounds.rx() + xi;
+        } else if (y1 > bounds.maxY() - bounds.ry()) {
+            float yi =  y1 - (bounds.maxY() - bounds.ry());
+            float xi = ellipseXIntercept(yi, bounds.rx(), bounds.ry());
+            x1 = bounds.x() + bounds.rx() - xi;
+            x2 = bounds.maxX() - bounds.rx() + xi;
+        }
+    }
+
+    result.append(LineSegment(x1, x2));
+}
+
+void ExclusionRectangle::getIncludedIntervals(float logicalTop, float logicalHeight, SegmentList& result) const
+{
+    const FloatRoundedRect& bounds = shapePaddingBounds();
+    if (bounds.isEmpty())
+        return;
+
+    float y1 = logicalTop;
+    float y2 = y1 + logicalHeight;
+
+    if (y1 < bounds.y() || y2 > bounds.maxY())
+        return;
+
+    float x1 = bounds.x();
+    float x2 = bounds.maxX();
+
+    if (bounds.ry() > 0) {
+        bool y1InterceptsCorner = y1 < bounds.y() + bounds.ry();
+        bool y2InterceptsCorner = y2 > bounds.maxY() - bounds.ry();
+        float xi = 0;
+
+        if (y1InterceptsCorner && y2InterceptsCorner) {
+            if  (y1 < bounds.height() + 2 * bounds.y() - y2) {
+                float yi = y1 - bounds.y() - bounds.ry();
+                xi = ellipseXIntercept(yi, bounds.rx(), bounds.ry());
+            } else {
+                float yi =  y2 - (bounds.maxY() - bounds.ry());
+                xi = ellipseXIntercept(yi, bounds.rx(), bounds.ry());
+            }
+        } else if (y1InterceptsCorner) {
+            float yi = y1 - bounds.y() - bounds.ry();
+            xi = ellipseXIntercept(yi, bounds.rx(), bounds.ry());
+        } else if (y2InterceptsCorner) {
+            float yi =  y2 - (bounds.maxY() - bounds.ry());
+            xi = ellipseXIntercept(yi, bounds.rx(), bounds.ry());
+        }
+
+        if (y1InterceptsCorner || y2InterceptsCorner) {
+            x1 = bounds.x() + bounds.rx() - xi;
+            x2 = bounds.maxX() - bounds.rx() + xi;
+        }
+    }
+
+    result.append(LineSegment(x1, x2));
+}
+
+bool ExclusionRectangle::firstIncludedIntervalLogicalTop(float minLogicalIntervalTop, const FloatSize& minLogicalIntervalSize, float& result) const
+{
+    const FloatRoundedRect& bounds = shapePaddingBounds();
+    if (bounds.isEmpty() || minLogicalIntervalSize.width() > bounds.width())
+        return false;
+
+    float minY = std::max(bounds.y(), minLogicalIntervalTop);
+    float maxY = minY + minLogicalIntervalSize.height();
+
+    if (maxY > bounds.maxY())
+        return false;
+
+    bool intervalOverlapsMinCorner = minY < bounds.y() + bounds.ry();
+    bool intervalOverlapsMaxCorner = maxY > bounds.maxY() - bounds.ry();
+
+    if (!intervalOverlapsMinCorner && !intervalOverlapsMaxCorner) {
+        result = minY;
+        return true;
+    }
+
+    float centerY = bounds.y() + bounds.height() / 2;
+    bool minCornerDefinesX = fabs(centerY - minY) > fabs(centerY - maxY);
+    bool intervalFitsWithinCorners = minLogicalIntervalSize.width() + 2 * bounds.rx() <= bounds.width();
+    FloatPoint cornerIntercept = bounds.cornerInterceptForWidth(minLogicalIntervalSize.width());
+
+    if (intervalOverlapsMinCorner && (!intervalOverlapsMaxCorner || minCornerDefinesX)) {
+        if (intervalFitsWithinCorners || bounds.y() + cornerIntercept.y() < minY) {
+            result = minY;
+            return true;
+        }
+        if (minLogicalIntervalSize.height() < bounds.height() - (2 * cornerIntercept.y())) {
+            result = bounds.y() + cornerIntercept.y();
+            return true;
+        }
+    }
+
+    if (intervalOverlapsMaxCorner && (!intervalOverlapsMinCorner || !minCornerDefinesX)) {
+        if (intervalFitsWithinCorners || minY <=  bounds.maxY() - cornerIntercept.y() - minLogicalIntervalSize.height()) {
+            result = minY;
+            return true;
+        }
+    }
+
+    return false;
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/exclusions/ExclusionRectangle.h b/Source/core/rendering/exclusions/ExclusionRectangle.h
new file mode 100644
index 0000000..72eb8dc
--- /dev/null
+++ b/Source/core/rendering/exclusions/ExclusionRectangle.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2012 Adobe Systems Incorporated. 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 THE COPYRIGHT HOLDERS AND 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 THE
+ * COPYRIGHT HOLDER 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 ExclusionRectangle_h
+#define ExclusionRectangle_h
+
+#include "core/platform/graphics/FloatPoint.h"
+#include "core/platform/graphics/FloatRect.h"
+#include "core/platform/graphics/FloatSize.h"
+#include "core/rendering/exclusions/ExclusionShape.h"
+#include <wtf/Assertions.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class FloatRoundedRect : public FloatRect {
+public:
+    FloatRoundedRect() { }
+    FloatRoundedRect(const FloatRect& bounds, const FloatSize& radii)
+        : FloatRect(bounds)
+        , m_radii(radii)
+    {
+    }
+
+    float rx() const { return m_radii.width(); }
+    float ry() const { return m_radii.height(); }
+    FloatRoundedRect marginBounds(float margin) const;
+    FloatRoundedRect paddingBounds(float padding) const;
+    FloatPoint cornerInterceptForWidth(float width) const;
+
+private:
+    FloatSize m_radii;
+};
+
+class ExclusionRectangle : public ExclusionShape {
+public:
+    ExclusionRectangle(const FloatRect& bounds, const FloatSize& radii)
+        : ExclusionShape()
+        , m_bounds(bounds, radii)
+        , m_haveInitializedMarginBounds(false)
+        , m_haveInitializedPaddingBounds(false)
+    {
+    }
+
+    virtual FloatRect shapeMarginLogicalBoundingBox() const OVERRIDE { return shapeMarginBounds(); }
+    virtual FloatRect shapePaddingLogicalBoundingBox() const OVERRIDE { return shapePaddingBounds(); }
+    virtual bool isEmpty() const OVERRIDE { return m_bounds.isEmpty(); }
+    virtual void getExcludedIntervals(float logicalTop, float logicalHeight, SegmentList&) const OVERRIDE;
+    virtual void getIncludedIntervals(float logicalTop, float logicalHeight, SegmentList&) const OVERRIDE;
+    virtual bool firstIncludedIntervalLogicalTop(float minLogicalIntervalTop, const FloatSize& minLogicalIntervalSize, float&) const OVERRIDE;
+
+    FloatRoundedRect shapeMarginBounds() const;
+    FloatRoundedRect shapePaddingBounds() const;
+
+private:
+    FloatRoundedRect m_bounds;
+    mutable FloatRoundedRect m_marginBounds;
+    mutable FloatRoundedRect m_paddingBounds;
+    mutable bool m_haveInitializedMarginBounds : 1;
+    mutable bool m_haveInitializedPaddingBounds : 1;
+};
+
+} // namespace WebCore
+
+#endif // ExclusionRectangle_h
diff --git a/Source/core/rendering/exclusions/ExclusionShape.cpp b/Source/core/rendering/exclusions/ExclusionShape.cpp
new file mode 100644
index 0000000..271d308
--- /dev/null
+++ b/Source/core/rendering/exclusions/ExclusionShape.cpp
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2012 Adobe Systems Incorporated. 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 THE COPYRIGHT HOLDERS AND 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 THE
+ * COPYRIGHT HOLDER 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 "core/rendering/exclusions/ExclusionShape.h"
+
+#include "core/css/BasicShapeFunctions.h"
+#include "core/css/LengthFunctions.h"
+#include "core/platform/graphics/FloatSize.h"
+#include "core/platform/graphics/WindRule.h"
+#include "core/rendering/exclusions/ExclusionPolygon.h"
+#include "core/rendering/exclusions/ExclusionRectangle.h"
+#include <wtf/MathExtras.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+
+namespace WebCore {
+
+static PassOwnPtr<ExclusionShape> createExclusionRectangle(const FloatRect& bounds, const FloatSize& radii)
+{
+    ASSERT(bounds.width() >= 0 && bounds.height() >= 0 && radii.width() >= 0 && radii.height() >= 0);
+    return adoptPtr(new ExclusionRectangle(bounds, radii));
+}
+
+static PassOwnPtr<ExclusionShape> createExclusionCircle(const FloatPoint& center, float radius)
+{
+    ASSERT(radius >= 0);
+    return adoptPtr(new ExclusionRectangle(FloatRect(center.x() - radius, center.y() - radius, radius*2, radius*2), FloatSize(radius, radius)));
+}
+
+static PassOwnPtr<ExclusionShape> createExclusionEllipse(const FloatPoint& center, const FloatSize& radii)
+{
+    ASSERT(radii.width() >= 0 && radii.height() >= 0);
+    return adoptPtr(new ExclusionRectangle(FloatRect(center.x() - radii.width(), center.y() - radii.height(), radii.width()*2, radii.height()*2), radii));
+}
+
+static PassOwnPtr<ExclusionShape> createExclusionPolygon(PassOwnPtr<Vector<FloatPoint> > vertices, WindRule fillRule)
+{
+    return adoptPtr(new ExclusionPolygon(vertices, fillRule));
+}
+
+static inline FloatRect physicalRectToLogical(const FloatRect& rect, float logicalBoxHeight, WritingMode writingMode)
+{
+    if (isHorizontalWritingMode(writingMode))
+        return rect;
+    if (isFlippedBlocksWritingMode(writingMode))
+        return FloatRect(rect.y(), logicalBoxHeight - rect.maxX(), rect.height(), rect.width());
+    return rect.transposedRect();
+}
+
+static inline FloatPoint physicalPointToLogical(const FloatPoint& point, float logicalBoxHeight, WritingMode writingMode)
+{
+    if (isHorizontalWritingMode(writingMode))
+        return point;
+    if (isFlippedBlocksWritingMode(writingMode))
+        return FloatPoint(point.y(), logicalBoxHeight - point.x());
+    return point.transposedPoint();
+}
+
+static inline FloatSize physicalSizeToLogical(const FloatSize& size, WritingMode writingMode)
+{
+    if (isHorizontalWritingMode(writingMode))
+        return size;
+    return size.transposedSize();
+}
+
+PassOwnPtr<ExclusionShape> ExclusionShape::createExclusionShape(const BasicShape* basicShape, float logicalBoxWidth, float logicalBoxHeight, WritingMode writingMode, Length margin, Length padding)
+{
+    ASSERT(basicShape);
+
+    bool horizontalWritingMode = isHorizontalWritingMode(writingMode);
+    float boxWidth = horizontalWritingMode ? logicalBoxWidth : logicalBoxHeight;
+    float boxHeight = horizontalWritingMode ? logicalBoxHeight : logicalBoxWidth;
+    OwnPtr<ExclusionShape> exclusionShape;
+
+    switch (basicShape->type()) {
+
+    case BasicShape::BASIC_SHAPE_RECTANGLE: {
+        const BasicShapeRectangle* rectangle = static_cast<const BasicShapeRectangle*>(basicShape);
+        FloatRect bounds(
+            floatValueForLength(rectangle->x(), boxWidth),
+            floatValueForLength(rectangle->y(), boxHeight),
+            floatValueForLength(rectangle->width(), boxWidth),
+            floatValueForLength(rectangle->height(), boxHeight));
+        Length radiusXLength = rectangle->cornerRadiusX();
+        Length radiusYLength = rectangle->cornerRadiusY();
+        FloatSize cornerRadii(
+            radiusXLength.isUndefined() ? 0 : floatValueForLength(radiusXLength, boxWidth),
+            radiusYLength.isUndefined() ? 0 : floatValueForLength(radiusYLength, boxHeight));
+        FloatRect logicalBounds = physicalRectToLogical(bounds, logicalBoxHeight, writingMode);
+
+        exclusionShape = createExclusionRectangle(logicalBounds, physicalSizeToLogical(cornerRadii, writingMode));
+        break;
+    }
+
+    case BasicShape::BASIC_SHAPE_CIRCLE: {
+        const BasicShapeCircle* circle = static_cast<const BasicShapeCircle*>(basicShape);
+        float centerX = floatValueForLength(circle->centerX(), boxWidth);
+        float centerY = floatValueForLength(circle->centerY(), boxHeight);
+        float radius = floatValueForLength(circle->radius(), std::min(boxHeight, boxWidth));
+        FloatPoint logicalCenter = physicalPointToLogical(FloatPoint(centerX, centerY), logicalBoxHeight, writingMode);
+
+        exclusionShape = createExclusionCircle(logicalCenter, radius);
+        break;
+    }
+
+    case BasicShape::BASIC_SHAPE_ELLIPSE: {
+        const BasicShapeEllipse* ellipse = static_cast<const BasicShapeEllipse*>(basicShape);
+        float centerX = floatValueForLength(ellipse->centerX(), boxWidth);
+        float centerY = floatValueForLength(ellipse->centerY(), boxHeight);
+        float radiusX = floatValueForLength(ellipse->radiusX(), boxWidth);
+        float radiusY = floatValueForLength(ellipse->radiusY(), boxHeight);
+        FloatPoint logicalCenter = physicalPointToLogical(FloatPoint(centerX, centerY), logicalBoxHeight, writingMode);
+        FloatSize logicalRadii = physicalSizeToLogical(FloatSize(radiusX, radiusY), writingMode);
+
+        exclusionShape = createExclusionEllipse(logicalCenter, logicalRadii);
+        break;
+    }
+
+    case BasicShape::BASIC_SHAPE_POLYGON: {
+        const BasicShapePolygon* polygon = static_cast<const BasicShapePolygon*>(basicShape);
+        const Vector<Length>& values = polygon->values();
+        size_t valuesSize = values.size();
+        ASSERT(!(valuesSize % 2));
+        OwnPtr<Vector<FloatPoint> > vertices = adoptPtr(new Vector<FloatPoint>(valuesSize / 2));
+        for (unsigned i = 0; i < valuesSize; i += 2) {
+            FloatPoint vertex(
+                floatValueForLength(values.at(i), boxWidth),
+                floatValueForLength(values.at(i + 1), boxHeight));
+            (*vertices)[i / 2] = physicalPointToLogical(vertex, logicalBoxHeight, writingMode);
+        }
+        exclusionShape = createExclusionPolygon(vertices.release(), polygon->windRule());
+        break;
+    }
+
+    default:
+        ASSERT_NOT_REACHED();
+    }
+
+    exclusionShape->m_logicalBoxWidth = logicalBoxWidth;
+    exclusionShape->m_logicalBoxHeight = logicalBoxHeight;
+    exclusionShape->m_writingMode = writingMode;
+    exclusionShape->m_margin = floatValueForLength(margin, 0);
+    exclusionShape->m_padding = floatValueForLength(padding, 0);
+
+    return exclusionShape.release();
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/exclusions/ExclusionShape.h b/Source/core/rendering/exclusions/ExclusionShape.h
new file mode 100644
index 0000000..177d404
--- /dev/null
+++ b/Source/core/rendering/exclusions/ExclusionShape.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2012 Adobe Systems Incorporated. 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 THE COPYRIGHT HOLDERS AND 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 THE
+ * COPYRIGHT HOLDER 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 ExclusionShape_h
+#define ExclusionShape_h
+
+#include "core/platform/graphics/FloatRect.h"
+#include "core/platform/text/WritingMode.h"
+#include "core/rendering/style/BasicShapes.h"
+#include <wtf/PassOwnPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+struct LineSegment {
+    LineSegment(float logicalLeft, float logicalRight)
+        : logicalLeft(logicalLeft)
+        , logicalRight(logicalRight)
+    {
+    }
+
+    float logicalLeft;
+    float logicalRight;
+};
+
+typedef Vector<LineSegment> SegmentList;
+
+
+// A representation of a BasicShape that enables layout code to determine how to break a line up into segments
+// that will fit within or around a shape. The line is defined by a pair of logical Y coordinates and the
+// computed segments are returned as pairs of logical X coordinates. The BasicShape itself is defined in
+// physical coordinates.
+
+class ExclusionShape {
+public:
+    static PassOwnPtr<ExclusionShape> createExclusionShape(const BasicShape*, float logicalBoxWidth, float logicalBoxHeight, WritingMode, Length margin, Length padding);
+
+    virtual ~ExclusionShape() { }
+
+    float shapeMargin() const { return m_margin; }
+    float shapePadding() const { return m_padding; }
+    virtual FloatRect shapeMarginLogicalBoundingBox() const = 0;
+    virtual FloatRect shapePaddingLogicalBoundingBox() const = 0;
+    virtual bool isEmpty() const = 0;
+    virtual void getIncludedIntervals(float logicalTop, float logicalHeight, SegmentList&) const = 0;
+    virtual void getExcludedIntervals(float logicalTop, float logicalHeight, SegmentList&) const = 0;
+    virtual bool firstIncludedIntervalLogicalTop(float minLogicalIntervalTop, const FloatSize& minLogicalIntervalSize, float& result) const = 0;
+
+private:
+    WritingMode m_writingMode;
+    float m_logicalBoxWidth;
+    float m_logicalBoxHeight;
+    float m_margin;
+    float m_padding;
+};
+
+} // namespace WebCore
+
+#endif // ExclusionShape_h
diff --git a/Source/core/rendering/exclusions/ExclusionShapeInfo.cpp b/Source/core/rendering/exclusions/ExclusionShapeInfo.cpp
new file mode 100644
index 0000000..65b615d
--- /dev/null
+++ b/Source/core/rendering/exclusions/ExclusionShapeInfo.cpp
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2012 Adobe Systems Incorporated. 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 THE COPYRIGHT HOLDER "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 THE COPYRIGHT HOLDER 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 "core/rendering/exclusions/ExclusionShapeInfo.h"
+
+#include "core/rendering/exclusions/ExclusionShape.h"
+#include "core/rendering/RenderBlock.h"
+#include "core/rendering/RenderBox.h"
+#include "core/rendering/RenderRegion.h"
+#include "core/rendering/style/RenderStyle.h"
+
+namespace WebCore {
+template<class RenderType, ExclusionShapeValue* (RenderStyle::*shapeGetter)() const, void (ExclusionShape::*intervalGetter)(float, float, SegmentList&) const>
+const ExclusionShape* ExclusionShapeInfo<RenderType, shapeGetter, intervalGetter>::computedShape() const
+{
+    if (ExclusionShape* exclusionShape = m_shape.get())
+        return exclusionShape;
+
+    ExclusionShapeValue* shapeValue = (m_renderer->style()->*shapeGetter)();
+    BasicShape* shape = (shapeValue && shapeValue->type() == ExclusionShapeValue::SHAPE) ? shapeValue->shape() : 0;
+
+    ASSERT(shape);
+
+    m_shape = ExclusionShape::createExclusionShape(shape, m_shapeLogicalWidth, m_shapeLogicalHeight, m_renderer->style()->writingMode(), m_renderer->style()->shapeMargin(), m_renderer->style()->shapePadding());
+    ASSERT(m_shape);
+    return m_shape.get();
+}
+
+template<class RenderType, ExclusionShapeValue* (RenderStyle::*shapeGetter)() const, void (ExclusionShape::*intervalGetter)(float, float, SegmentList&) const>
+LayoutUnit ExclusionShapeInfo<RenderType, shapeGetter, intervalGetter>::logicalTopOffset() const
+{
+    LayoutUnit logicalTopOffset = m_renderer->style()->boxSizing() == CONTENT_BOX ? m_renderer->borderBefore() + m_renderer->paddingBefore() : LayoutUnit();
+    // Content in a flow thread is relative to the beginning of the thread, but the shape calculation should be relative to the current region.
+    if (m_renderer->isRenderRegion())
+        logicalTopOffset += toRenderRegion(m_renderer)->logicalTopForFlowThreadContent();
+    return logicalTopOffset;
+}
+
+template<class RenderType, ExclusionShapeValue* (RenderStyle::*shapeGetter)() const, void (ExclusionShape::*intervalGetter)(float, float, SegmentList&) const>
+bool ExclusionShapeInfo<RenderType, shapeGetter, intervalGetter>::computeSegmentsForLine(LayoutUnit lineTop, LayoutUnit lineHeight)
+{
+    ASSERT(lineHeight >= 0);
+    m_shapeLineTop = lineTop - logicalTopOffset();
+    m_lineHeight = lineHeight;
+    m_segments.clear();
+
+    if (lineOverlapsShapeBounds())
+        (computedShape()->*intervalGetter)(m_shapeLineTop, std::min(m_lineHeight, shapeLogicalBottom() - lineTop), m_segments);
+
+    LayoutUnit logicalLeftOffset = this->logicalLeftOffset();
+    for (size_t i = 0; i < m_segments.size(); i++) {
+        m_segments[i].logicalLeft += logicalLeftOffset;
+        m_segments[i].logicalRight += logicalLeftOffset;
+    }
+
+    return m_segments.size();
+}
+
+template class ExclusionShapeInfo<RenderBlock, &RenderStyle::resolvedShapeInside, &ExclusionShape::getIncludedIntervals>;
+template class ExclusionShapeInfo<RenderBox, &RenderStyle::shapeOutside, &ExclusionShape::getExcludedIntervals>;
+}
diff --git a/Source/core/rendering/exclusions/ExclusionShapeInfo.h b/Source/core/rendering/exclusions/ExclusionShapeInfo.h
new file mode 100644
index 0000000..c81aab8
--- /dev/null
+++ b/Source/core/rendering/exclusions/ExclusionShapeInfo.h
@@ -0,0 +1,128 @@
+/*
+* Copyright (C) 2012 Adobe Systems Incorporated. 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 THE COPYRIGHT HOLDER "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 THE COPYRIGHT HOLDER 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 ExclusionShapeInfo_h
+#define ExclusionShapeInfo_h
+
+#include "core/platform/LayoutUnit.h"
+#include "core/platform/graphics/FloatRect.h"
+#include "core/rendering/exclusions/ExclusionShape.h"
+#include "core/rendering/style/ExclusionShapeValue.h"
+#include "core/rendering/style/RenderStyle.h"
+#include <wtf/OwnPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+template<class KeyType, class InfoType>
+class MappedInfo {
+public:
+    static InfoType* ensureInfo(const KeyType* key)
+    {
+        InfoMap& infoMap = MappedInfo<KeyType, InfoType>::infoMap();
+        if (InfoType* info = infoMap.get(key))
+            return info;
+        typename InfoMap::AddResult result = infoMap.add(key, InfoType::createInfo(key));
+        return result.iterator->value.get();
+    }
+    static void removeInfo(const KeyType* key) { infoMap().remove(key); }
+    static InfoType* info(const KeyType* key) { return infoMap().get(key); }
+private:
+    typedef HashMap<const KeyType*, OwnPtr<InfoType> > InfoMap;
+    static InfoMap& infoMap()
+    {
+        DEFINE_STATIC_LOCAL(InfoMap, staticInfoMap, ());
+        return staticInfoMap;
+    }
+};
+
+template<class RenderType, ExclusionShapeValue* (RenderStyle::*shapeGetter)() const, void (ExclusionShape::*intervalGetter)(float, float, SegmentList&) const>
+class ExclusionShapeInfo {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    virtual ~ExclusionShapeInfo() { }
+
+    void setShapeSize(LayoutUnit logicalWidth, LayoutUnit logicalHeight)
+    {
+        if (m_renderer->style()->boxSizing() == CONTENT_BOX) {
+            logicalWidth -= m_renderer->borderAndPaddingLogicalWidth();
+            logicalHeight -= m_renderer->borderAndPaddingLogicalHeight();
+        }
+
+        if (m_shapeLogicalWidth == logicalWidth && m_shapeLogicalHeight == logicalHeight)
+            return;
+        dirtyShapeSize();
+        m_shapeLogicalWidth = logicalWidth;
+        m_shapeLogicalHeight = logicalHeight;
+    }
+
+    virtual bool computeSegmentsForLine(LayoutUnit lineTop, LayoutUnit lineHeight);
+
+    LayoutUnit shapeLogicalTop() const { return floatLogicalTopToLayoutUnit(computedShapeLogicalBoundingBox().y()) + logicalTopOffset(); }
+    LayoutUnit shapeLogicalBottom() const { return floatLogicalBottomToLayoutUnit(computedShapeLogicalBoundingBox().maxY()) + logicalTopOffset(); }
+    LayoutUnit shapeLogicalLeft() const { return computedShapeLogicalBoundingBox().x() + logicalLeftOffset(); }
+    LayoutUnit shapeLogicalRight() const { return computedShapeLogicalBoundingBox().maxX() + logicalLeftOffset(); }
+    LayoutUnit shapeLogicalWidth() const { return computedShapeLogicalBoundingBox().width(); }
+    LayoutUnit shapeLogicalHeight() const { return computedShapeLogicalBoundingBox().height(); }
+
+    LayoutUnit logicalLineTop() const { return m_shapeLineTop + logicalTopOffset(); }
+    LayoutUnit logicalLineBottom() const { return m_shapeLineTop + m_lineHeight + logicalTopOffset(); }
+
+    bool lineOverlapsShapeBounds() const { return logicalLineTop() < shapeLogicalBottom() && logicalLineBottom() >= shapeLogicalTop(); }
+
+    void dirtyShapeSize() { m_shape.clear(); }
+    bool shapeSizeDirty() { return !m_shape.get(); }
+    const RenderType* owner() const { return m_renderer; }
+
+protected:
+    ExclusionShapeInfo(const RenderType* renderer): m_renderer(renderer) { }
+
+    const ExclusionShape* computedShape() const;
+    virtual FloatRect computedShapeLogicalBoundingBox() const = 0;
+
+    // Use ceil and floor to ensure that the returned LayoutUnit value is within the shape's bounds.
+    LayoutUnit floatLogicalTopToLayoutUnit(float logicalTop) const { return LayoutUnit::fromFloatCeil(logicalTop); }
+    LayoutUnit floatLogicalBottomToLayoutUnit(float logicalBottom) const { return LayoutUnit::fromFloatFloor(logicalBottom); }
+
+    LayoutUnit logicalTopOffset() const;
+    LayoutUnit logicalLeftOffset() const { return m_renderer->style()->boxSizing() == CONTENT_BOX ? m_renderer->borderStart() + m_renderer->paddingStart() : LayoutUnit(); }
+
+    LayoutUnit m_shapeLineTop;
+    LayoutUnit m_lineHeight;
+    SegmentList m_segments;
+
+private:
+    mutable OwnPtr<ExclusionShape> m_shape;
+
+    LayoutUnit m_shapeLogicalWidth;
+    LayoutUnit m_shapeLogicalHeight;
+    const RenderType* m_renderer;
+};
+}
+#endif
diff --git a/Source/core/rendering/exclusions/ExclusionShapeInsideInfo.cpp b/Source/core/rendering/exclusions/ExclusionShapeInsideInfo.cpp
new file mode 100644
index 0000000..f20265f
--- /dev/null
+++ b/Source/core/rendering/exclusions/ExclusionShapeInsideInfo.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2012 Adobe Systems Incorporated. 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 THE COPYRIGHT HOLDER “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 THE COPYRIGHT HOLDER 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 "core/rendering/exclusions/ExclusionShapeInsideInfo.h"
+
+#include "core/rendering/InlineIterator.h"
+#include "core/rendering/RenderBlock.h"
+
+namespace WebCore {
+
+LineSegmentRange::LineSegmentRange(const InlineIterator& start, const InlineIterator& end)
+    : start(start.root(), start.object(), start.offset())
+    , end(end.root(), end.object(), end.offset())
+    {
+    }
+
+bool ExclusionShapeInsideInfo::isEnabledFor(const RenderBlock* renderer)
+{
+    ExclusionShapeValue* shapeValue = renderer->style()->resolvedShapeInside();
+    return (shapeValue && shapeValue->type() == ExclusionShapeValue::SHAPE) ? shapeValue->shape() : 0;
+}
+
+bool ExclusionShapeInsideInfo::adjustLogicalLineTop(float minSegmentWidth)
+{
+    const ExclusionShape* shape = computedShape();
+    if (!shape || m_lineHeight <= 0 || logicalLineTop() > shapeLogicalBottom())
+        return false;
+
+    float floatNewLineTop;
+    if (shape->firstIncludedIntervalLogicalTop(m_shapeLineTop, FloatSize(minSegmentWidth, m_lineHeight), floatNewLineTop)) {
+        LayoutUnit newLineTop = floatLogicalTopToLayoutUnit(floatNewLineTop);
+        if (newLineTop > m_shapeLineTop) {
+            m_shapeLineTop = newLineTop;
+            return true;
+        }
+    }
+
+    return false;
+}
+
+}
diff --git a/Source/core/rendering/exclusions/ExclusionShapeInsideInfo.h b/Source/core/rendering/exclusions/ExclusionShapeInsideInfo.h
new file mode 100644
index 0000000..abaa5a8
--- /dev/null
+++ b/Source/core/rendering/exclusions/ExclusionShapeInsideInfo.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) 2012 Adobe Systems Incorporated. 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 THE COPYRIGHT HOLDER "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 THE COPYRIGHT HOLDER 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 ExclusionShapeInsideInfo_h
+#define ExclusionShapeInsideInfo_h
+
+#include "core/rendering/exclusions/ExclusionShapeInfo.h"
+#include <wtf/PassOwnPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class InlineIterator;
+class RenderBlock;
+class RenderObject;
+
+struct LineSegmentIterator {
+    RenderObject* root;
+    RenderObject* object;
+    unsigned offset;
+    LineSegmentIterator(RenderObject* root, RenderObject* object, unsigned offset)
+        : root(root)
+        , object(object)
+        , offset(offset)
+    {
+    }
+};
+
+struct LineSegmentRange {
+    LineSegmentIterator start;
+    LineSegmentIterator end;
+    LineSegmentRange(const InlineIterator& start, const InlineIterator& end);
+};
+
+typedef Vector<LineSegmentRange> SegmentRangeList;
+
+class ExclusionShapeInsideInfo : public ExclusionShapeInfo<RenderBlock, &RenderStyle::resolvedShapeInside, &ExclusionShape::getIncludedIntervals> {
+public:
+    static PassOwnPtr<ExclusionShapeInsideInfo> createInfo(const RenderBlock* renderer) { return adoptPtr(new ExclusionShapeInsideInfo(renderer)); }
+
+    static bool isEnabledFor(const RenderBlock* renderer);
+
+    virtual bool computeSegmentsForLine(LayoutUnit lineTop, LayoutUnit lineHeight) OVERRIDE
+    {
+        m_segmentRanges.clear();
+        return ExclusionShapeInfo<RenderBlock, &RenderStyle::resolvedShapeInside, &ExclusionShape::getIncludedIntervals>::computeSegmentsForLine(lineTop, lineHeight);
+    }
+
+    bool hasSegments() const
+    {
+        return lineOverlapsShapeBounds() && m_segments.size();
+    }
+    const SegmentList& segments() const
+    {
+        ASSERT(hasSegments());
+        return m_segments;
+    }
+    SegmentRangeList& segmentRanges() { return m_segmentRanges; }
+    const SegmentRangeList& segmentRanges() const { return m_segmentRanges; }
+    const LineSegment* currentSegment() const
+    {
+        if (!hasSegments())
+            return 0;
+        ASSERT(m_segmentRanges.size() < m_segments.size());
+        return &m_segments[m_segmentRanges.size()];
+    }
+    bool adjustLogicalLineTop(float minSegmentWidth);
+
+    void setNeedsLayout(bool value) { m_needsLayout = value; }
+    bool needsLayout() { return m_needsLayout; }
+
+protected:
+    virtual FloatRect computedShapeLogicalBoundingBox() const OVERRIDE { return computedShape()->shapePaddingLogicalBoundingBox(); }
+
+private:
+    ExclusionShapeInsideInfo(const RenderBlock* renderer)
+    : ExclusionShapeInfo<RenderBlock, &RenderStyle::resolvedShapeInside, &ExclusionShape::getIncludedIntervals> (renderer)
+    , m_needsLayout(false)
+    { }
+
+    SegmentRangeList m_segmentRanges;
+    bool m_needsLayout;
+};
+
+}
+#endif
diff --git a/Source/core/rendering/exclusions/ExclusionShapeOutsideInfo.cpp b/Source/core/rendering/exclusions/ExclusionShapeOutsideInfo.cpp
new file mode 100644
index 0000000..89d1fc1
--- /dev/null
+++ b/Source/core/rendering/exclusions/ExclusionShapeOutsideInfo.cpp
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2012 Adobe Systems Incorporated. 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 THE COPYRIGHT HOLDER “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 THE COPYRIGHT HOLDER 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 "core/rendering/exclusions/ExclusionShapeOutsideInfo.h"
+
+#include "core/rendering/RenderBox.h"
+
+namespace WebCore {
+bool ExclusionShapeOutsideInfo::isEnabledFor(const RenderBox* box)
+{
+    ExclusionShapeValue* value = box->style()->shapeOutside();
+    return (box->isFloatingWithShapeOutside() && value->type() == ExclusionShapeValue::SHAPE) ? value->shape() : 0;
+}
+
+bool ExclusionShapeOutsideInfo::computeSegmentsForLine(LayoutUnit lineTop, LayoutUnit lineHeight)
+{
+    if (shapeSizeDirty() || m_lineTop != lineTop || m_lineHeight != lineHeight) {
+        if (ExclusionShapeInfo<RenderBox, &RenderStyle::shapeOutside, &ExclusionShape::getExcludedIntervals>::computeSegmentsForLine(lineTop, lineHeight)) {
+            m_leftSegmentShapeBoundingBoxDelta = m_segments[0].logicalLeft - shapeLogicalLeft();
+            m_rightSegmentShapeBoundingBoxDelta = m_segments[m_segments.size()-1].logicalRight - shapeLogicalRight();
+        } else {
+            m_leftSegmentShapeBoundingBoxDelta = 0;
+            m_rightSegmentShapeBoundingBoxDelta = 0;
+        }
+        m_lineTop = lineTop;
+    }
+
+    return m_segments.size();
+}
+
+}
diff --git a/Source/core/rendering/exclusions/ExclusionShapeOutsideInfo.h b/Source/core/rendering/exclusions/ExclusionShapeOutsideInfo.h
new file mode 100644
index 0000000..378c88d
--- /dev/null
+++ b/Source/core/rendering/exclusions/ExclusionShapeOutsideInfo.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2012 Adobe Systems Incorporated. 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 THE COPYRIGHT HOLDER “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 THE COPYRIGHT HOLDER 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 ExclusionShapeOutsideInfo_h
+#define ExclusionShapeOutsideInfo_h
+
+#include "core/platform/graphics/LayoutSize.h"
+#include "core/rendering/exclusions/ExclusionShapeInfo.h"
+
+namespace WebCore {
+
+class RenderBox;
+
+class ExclusionShapeOutsideInfo : public ExclusionShapeInfo<RenderBox, &RenderStyle::shapeOutside, &ExclusionShape::getExcludedIntervals>, public MappedInfo<RenderBox, ExclusionShapeOutsideInfo> {
+public:
+    LayoutSize shapeLogicalOffset() const { return LayoutSize(shapeLogicalLeft(), shapeLogicalTop()); }
+
+    LayoutUnit leftSegmentShapeBoundingBoxDelta() const { return m_leftSegmentShapeBoundingBoxDelta; }
+    LayoutUnit rightSegmentShapeBoundingBoxDelta() const { return m_rightSegmentShapeBoundingBoxDelta; }
+
+    virtual bool computeSegmentsForLine(LayoutUnit lineTop, LayoutUnit lineHeight) OVERRIDE;
+
+    static PassOwnPtr<ExclusionShapeOutsideInfo> createInfo(const RenderBox* renderer) { return adoptPtr(new ExclusionShapeOutsideInfo(renderer)); }
+    static bool isEnabledFor(const RenderBox*);
+
+protected:
+    virtual FloatRect computedShapeLogicalBoundingBox() const OVERRIDE { return computedShape()->shapeMarginLogicalBoundingBox(); }
+
+private:
+    ExclusionShapeOutsideInfo(const RenderBox* renderer) : ExclusionShapeInfo<RenderBox, &RenderStyle::shapeOutside, &ExclusionShape::getExcludedIntervals>(renderer) { }
+
+    LayoutUnit m_leftSegmentShapeBoundingBoxDelta;
+    LayoutUnit m_rightSegmentShapeBoundingBoxDelta;
+    LayoutUnit m_lineTop;
+};
+
+}
+#endif
diff --git a/Source/core/rendering/style/BasicShapes.cpp b/Source/core/rendering/style/BasicShapes.cpp
new file mode 100644
index 0000000..efef136
--- /dev/null
+++ b/Source/core/rendering/style/BasicShapes.cpp
@@ -0,0 +1,172 @@
+/*
+ * Copyright (C) 2012 Adobe Systems Incorporated. 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 THE COPYRIGHT HOLDER "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 THE COPYRIGHT HOLDER 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 "core/css/LengthFunctions.h"
+#include "core/platform/graphics/FloatRect.h"
+#include "core/platform/graphics/Path.h"
+#include "core/rendering/style/BasicShapes.h"
+
+namespace WebCore {
+
+bool BasicShape::canBlend(const BasicShape* other) const
+{
+    // FIXME: Support animations between different shapes in the future.
+    if (type() != other->type())
+        return false;
+
+    // Just polygons with same number of vertices can be animated.
+    if (type() == BasicShape::BASIC_SHAPE_POLYGON
+        && static_cast<const BasicShapePolygon*>(this)->values().size() != static_cast<const BasicShapePolygon*>(other)->values().size())
+        return false;
+
+    return true;
+}
+
+void BasicShapeRectangle::path(Path& path, const FloatRect& boundingBox)
+{
+    ASSERT(path.isEmpty());
+    path.addRoundedRect(FloatRect(floatValueForLength(m_x, boundingBox.width()) + boundingBox.x(),
+                                  floatValueForLength(m_y, boundingBox.height()) + boundingBox.y(),
+                                  floatValueForLength(m_width, boundingBox.width()),
+                                  floatValueForLength(m_height, boundingBox.height())),
+                        FloatSize(m_cornerRadiusX.isUndefined() ? 0 : floatValueForLength(m_cornerRadiusX, boundingBox.width()),
+                                  m_cornerRadiusY.isUndefined() ? 0 : floatValueForLength(m_cornerRadiusY, boundingBox.height())));
+}
+
+PassRefPtr<BasicShape> BasicShapeRectangle::blend(const BasicShape* other, double progress) const
+{
+    ASSERT(type() == other->type());
+
+    const BasicShapeRectangle* o = static_cast<const BasicShapeRectangle*>(other);
+    RefPtr<BasicShapeRectangle> result =  BasicShapeRectangle::create();
+    result->setX(m_x.blend(o->x(), progress));
+    result->setY(m_y.blend(o->y(), progress));
+    result->setWidth(m_width.blend(o->width(), progress));
+    result->setHeight(m_height.blend(o->height(), progress));
+    if (!m_cornerRadiusX.isUndefined() && !o->cornerRadiusX().isUndefined())
+        result->setCornerRadiusX(m_cornerRadiusX.blend(o->cornerRadiusX(), progress));
+    if (!m_cornerRadiusY.isUndefined() && !o->cornerRadiusY().isUndefined())
+        result->setCornerRadiusY(m_cornerRadiusY.blend(o->cornerRadiusY(), progress));
+    return result.release();
+}
+
+void BasicShapeCircle::path(Path& path, const FloatRect& boundingBox)
+{
+    ASSERT(path.isEmpty());
+    float diagonal = sqrtf((boundingBox.width() * boundingBox.width() + boundingBox.height() * boundingBox.height()) / 2);
+    float centerX = floatValueForLength(m_centerX, boundingBox.width());
+    float centerY = floatValueForLength(m_centerY, boundingBox.height());
+    float radius = floatValueForLength(m_radius, diagonal);
+    path.addEllipse(FloatRect(centerX - radius + boundingBox.x(),
+                              centerY - radius + boundingBox.y(),
+                              radius * 2,
+                              radius * 2));
+}
+
+PassRefPtr<BasicShape> BasicShapeCircle::blend(const BasicShape* other, double progress) const
+{
+    ASSERT(type() == other->type());
+
+    const BasicShapeCircle* o = static_cast<const BasicShapeCircle*>(other);
+    RefPtr<BasicShapeCircle> result =  BasicShapeCircle::create();
+    result->setCenterX(m_centerX.blend(o->centerX(), progress));
+    result->setCenterY(m_centerY.blend(o->centerY(), progress));
+    result->setRadius(m_radius.blend(o->radius(), progress));
+    return result.release();
+}
+
+void BasicShapeEllipse::path(Path& path, const FloatRect& boundingBox)
+{
+    ASSERT(path.isEmpty());
+    float centerX = floatValueForLength(m_centerX, boundingBox.width());
+    float centerY = floatValueForLength(m_centerY, boundingBox.height());
+    float radiusX = floatValueForLength(m_radiusX, boundingBox.width());
+    float radiusY = floatValueForLength(m_radiusY, boundingBox.height());
+    path.addEllipse(FloatRect(centerX - radiusX + boundingBox.x(),
+                              centerY - radiusY + boundingBox.y(),
+                              radiusX * 2,
+                              radiusY * 2));
+}
+
+PassRefPtr<BasicShape> BasicShapeEllipse::blend(const BasicShape* other, double progress) const
+{
+    ASSERT(type() == other->type());
+
+    const BasicShapeEllipse* o = static_cast<const BasicShapeEllipse*>(other);
+    RefPtr<BasicShapeEllipse> result =  BasicShapeEllipse::create();
+    result->setCenterX(m_centerX.blend(o->centerX(), progress));
+    result->setCenterY(m_centerY.blend(o->centerY(), progress));
+    result->setRadiusX(m_radiusX.blend(o->radiusX(), progress));
+    result->setRadiusY(m_radiusY.blend(o->radiusY(), progress));
+    return result.release();
+}
+
+void BasicShapePolygon::path(Path& path, const FloatRect& boundingBox)
+{
+    ASSERT(path.isEmpty());
+    ASSERT(!(m_values.size() % 2));
+    size_t length = m_values.size();
+    
+    if (!length)
+        return;
+
+    path.moveTo(FloatPoint(floatValueForLength(m_values.at(0), boundingBox.width()) + boundingBox.x(),
+        floatValueForLength(m_values.at(1), boundingBox.height()) + boundingBox.y()));
+    for (size_t i = 2; i < length; i = i + 2) {
+        path.addLineTo(FloatPoint(floatValueForLength(m_values.at(i), boundingBox.width()) + boundingBox.x(),
+            floatValueForLength(m_values.at(i + 1), boundingBox.height()) + boundingBox.y()));
+    }
+    path.closeSubpath();
+}
+
+PassRefPtr<BasicShape> BasicShapePolygon::blend(const BasicShape* other, double progress) const
+{
+    ASSERT(type() == other->type());
+
+    const BasicShapePolygon* o = static_cast<const BasicShapePolygon*>(other);
+    ASSERT(m_values.size() == o->values().size());
+    ASSERT(!(m_values.size() % 2));
+
+    size_t length = m_values.size();
+    RefPtr<BasicShapePolygon> result = BasicShapePolygon::create();
+    if (!length)
+        return result.release();
+
+    result->setWindRule(o->windRule());
+
+    for (size_t i = 0; i < length; i = i + 2) {
+        result->appendPoint(m_values.at(i).blend(o->values().at(i), progress),
+            m_values.at(i + 1).blend(o->values().at(i + 1), progress));
+    }
+
+    return result.release();
+}
+}
diff --git a/Source/core/rendering/style/BasicShapes.h b/Source/core/rendering/style/BasicShapes.h
new file mode 100644
index 0000000..656f523
--- /dev/null
+++ b/Source/core/rendering/style/BasicShapes.h
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2012 Adobe Systems Incorporated. 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 THE COPYRIGHT HOLDER "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 THE COPYRIGHT HOLDER 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 BasicShapes_h
+#define BasicShapes_h
+
+#include "core/platform/Length.h"
+#include "core/platform/graphics/WindRule.h"
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class FloatRect;
+class Path;
+
+class BasicShape : public RefCounted<BasicShape> {
+public:
+    virtual ~BasicShape() { }
+
+    enum Type {
+        BASIC_SHAPE_RECTANGLE = 1,
+        BASIC_SHAPE_CIRCLE = 2,
+        BASIC_SHAPE_ELLIPSE = 3,
+        BASIC_SHAPE_POLYGON = 4
+    };
+
+    bool canBlend(const BasicShape*) const;
+
+    virtual void path(Path&, const FloatRect&) = 0;
+    virtual WindRule windRule() const { return RULE_NONZERO; }
+    virtual PassRefPtr<BasicShape> blend(const BasicShape*, double) const = 0;
+
+    virtual Type type() const = 0;
+protected:
+    BasicShape() { }
+};
+
+class BasicShapeRectangle : public BasicShape {
+public:
+    static PassRefPtr<BasicShapeRectangle> create() { return adoptRef(new BasicShapeRectangle); }
+
+    Length x() const { return m_x; }
+    Length y() const { return m_y; }
+    Length width() const { return m_width; }
+    Length height() const { return m_height; }
+    Length cornerRadiusX() const { return m_cornerRadiusX; }
+    Length cornerRadiusY() const { return m_cornerRadiusY; }
+
+    void setX(Length x) { m_x = x; }
+    void setY(Length y) { m_y = y; }
+    void setWidth(Length width) { m_width = width; }
+    void setHeight(Length height) { m_height = height; }
+    void setCornerRadiusX(Length radiusX) { m_cornerRadiusX = radiusX; }
+    void setCornerRadiusY(Length radiusY) { m_cornerRadiusY = radiusY; }
+
+    virtual void path(Path&, const FloatRect&) OVERRIDE;
+    virtual PassRefPtr<BasicShape> blend(const BasicShape*, double) const OVERRIDE;
+
+    virtual Type type() const { return BASIC_SHAPE_RECTANGLE; }
+private:
+    BasicShapeRectangle()
+        : m_cornerRadiusX(Undefined)
+        , m_cornerRadiusY(Undefined)
+    { }
+
+    Length m_y;
+    Length m_x;
+    Length m_width;
+    Length m_height;
+    Length m_cornerRadiusX;
+    Length m_cornerRadiusY;
+};
+
+class BasicShapeCircle : public BasicShape {
+public:
+    static PassRefPtr<BasicShapeCircle> create() { return adoptRef(new BasicShapeCircle); }
+
+    Length centerX() const { return m_centerX; }
+    Length centerY() const { return m_centerY; }
+    Length radius() const { return m_radius; }
+
+    void setCenterX(Length centerX) { m_centerX = centerX; }
+    void setCenterY(Length centerY) { m_centerY = centerY; }
+    void setRadius(Length radius) { m_radius = radius; }
+
+    virtual void path(Path&, const FloatRect&) OVERRIDE;
+    virtual PassRefPtr<BasicShape> blend(const BasicShape*, double) const OVERRIDE;
+
+    virtual Type type() const { return BASIC_SHAPE_CIRCLE; }
+private:
+    BasicShapeCircle() { }
+
+    Length m_centerX;
+    Length m_centerY;
+    Length m_radius;
+};
+
+class BasicShapeEllipse : public BasicShape {
+public:
+    static PassRefPtr<BasicShapeEllipse> create() { return adoptRef(new BasicShapeEllipse); }
+
+    Length centerX() const { return m_centerX; }
+    Length centerY() const { return m_centerY; }
+    Length radiusX() const { return m_radiusX; }
+    Length radiusY() const { return m_radiusY; }
+
+    void setCenterX(Length centerX) { m_centerX = centerX; }
+    void setCenterY(Length centerY) { m_centerY = centerY; }
+    void setRadiusX(Length radiusX) { m_radiusX = radiusX; }
+    void setRadiusY(Length radiusY) { m_radiusY = radiusY; }
+
+    virtual void path(Path&, const FloatRect&) OVERRIDE;
+    virtual PassRefPtr<BasicShape> blend(const BasicShape*, double) const OVERRIDE;
+
+    virtual Type type() const { return BASIC_SHAPE_ELLIPSE; } 
+private:
+    BasicShapeEllipse() { }
+
+    Length m_centerX;
+    Length m_centerY;
+    Length m_radiusX;
+    Length m_radiusY;
+};
+
+class BasicShapePolygon : public BasicShape {
+public:
+    static PassRefPtr<BasicShapePolygon> create() { return adoptRef(new BasicShapePolygon); }
+
+    const Vector<Length>& values() const { return m_values; }
+    Length getXAt(unsigned i) const { return m_values.at(2 * i); }
+    Length getYAt(unsigned i) const { return m_values.at(2 * i + 1); }
+
+    void setWindRule(WindRule windRule) { m_windRule = windRule; }
+    void appendPoint(Length x, Length y) { m_values.append(x); m_values.append(y); }
+
+    virtual void path(Path&, const FloatRect&) OVERRIDE;
+    virtual PassRefPtr<BasicShape> blend(const BasicShape*, double) const OVERRIDE;
+
+    virtual WindRule windRule() const { return m_windRule; }
+
+    virtual Type type() const { return BASIC_SHAPE_POLYGON; }
+private:
+    BasicShapePolygon()
+        : m_windRule(RULE_NONZERO)
+    { }
+
+    WindRule m_windRule;
+    Vector<Length> m_values;
+};
+}
+#endif
diff --git a/Source/core/rendering/style/BorderData.h b/Source/core/rendering/style/BorderData.h
new file mode 100644
index 0000000..4ae8ee4
--- /dev/null
+++ b/Source/core/rendering/style/BorderData.h
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ *           (C) 2000 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com)
+ *
+ * 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 "core/platform/LengthSize.h"
+#include "core/platform/graphics/IntRect.h"
+#include "core/rendering/style/BorderValue.h"
+#include "core/rendering/style/NinePieceImage.h"
+
+namespace WebCore {
+
+class BorderData {
+friend class RenderStyle;
+public:
+    BorderData() : m_topLeft(Length(0, Fixed), Length(0, Fixed))
+                 , m_topRight(Length(0, Fixed), Length(0, Fixed))
+                 , m_bottomLeft(Length(0, Fixed), Length(0, Fixed))
+                 , m_bottomRight(Length(0, Fixed), Length(0, Fixed))
+    {
+    }
+    bool hasBorder() const
+    {
+        bool haveImage = m_image.hasImage();
+        return m_left.nonZero(!haveImage) || m_right.nonZero(!haveImage) || m_top.nonZero(!haveImage) || m_bottom.nonZero(!haveImage);
+    }
+
+    bool hasBorderRadius() const
+    {
+        if (!m_topLeft.width().isZero())
+            return true;
+        if (!m_topRight.width().isZero())
+            return true;
+        if (!m_bottomLeft.width().isZero())
+            return true;
+        if (!m_bottomRight.width().isZero())
+            return true;
+        return false;
+    }
+    
+    unsigned borderLeftWidth() const
+    {
+        if (!m_image.hasImage() && (m_left.style() == BNONE || m_left.style() == BHIDDEN))
+            return 0; 
+        return m_left.width();
+    }
+    
+    unsigned borderRightWidth() const
+    {
+        if (!m_image.hasImage() && (m_right.style() == BNONE || m_right.style() == BHIDDEN))
+            return 0;
+        return m_right.width();
+    }
+    
+    unsigned borderTopWidth() const
+    {
+        if (!m_image.hasImage() && (m_top.style() == BNONE || m_top.style() == BHIDDEN))
+            return 0;
+        return m_top.width();
+    }
+    
+    unsigned borderBottomWidth() const
+    {
+        if (!m_image.hasImage() && (m_bottom.style() == BNONE || m_bottom.style() == BHIDDEN))
+            return 0;
+        return m_bottom.width();
+    }
+    
+    bool operator==(const BorderData& o) const
+    {
+        return m_left == o.m_left && m_right == o.m_right && m_top == o.m_top && m_bottom == o.m_bottom && m_image == o.m_image
+               && m_topLeft == o.m_topLeft && m_topRight == o.m_topRight && m_bottomLeft == o.m_bottomLeft && m_bottomRight == o.m_bottomRight;
+    }
+    
+    bool operator!=(const BorderData& o) const
+    {
+        return !(*this == o);
+    }
+    
+    const BorderValue& left() const { return m_left; }
+    const BorderValue& right() const { return m_right; }
+    const BorderValue& top() const { return m_top; }
+    const BorderValue& bottom() const { return m_bottom; }
+    
+    const NinePieceImage& image() const { return m_image; }
+    
+    const LengthSize& topLeft() const { return m_topLeft; }
+    const LengthSize& topRight() const { return m_topRight; }
+    const LengthSize& bottomLeft() const { return m_bottomLeft; }
+    const LengthSize& bottomRight() const { return m_bottomRight; }
+
+private:
+    BorderValue m_left;
+    BorderValue m_right;
+    BorderValue m_top;
+    BorderValue m_bottom;
+
+    NinePieceImage m_image;
+
+    LengthSize m_topLeft;
+    LengthSize m_topRight;
+    LengthSize m_bottomLeft;
+    LengthSize m_bottomRight;
+};
+
+} // namespace WebCore
+
+#endif // BorderData_h
diff --git a/Source/core/rendering/style/BorderValue.h b/Source/core/rendering/style/BorderValue.h
new file mode 100644
index 0000000..fb8c61c
--- /dev/null
+++ b/Source/core/rendering/style/BorderValue.h
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ *           (C) 2000 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com)
+ *
+ * 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 "core/platform/graphics/Color.h"
+#include "core/rendering/style/RenderStyleConstants.h"
+
+namespace WebCore {
+
+class BorderValue {
+friend class RenderStyle;
+public:
+    BorderValue()
+        : m_color(0)
+        , m_colorIsValid(false)
+        , m_width(3)
+        , m_style(BNONE)
+        , m_isAuto(AUTO_OFF)
+    {
+    }
+
+    bool nonZero(bool checkStyle = true) const
+    {
+        return width() && (!checkStyle || m_style != BNONE);
+    }
+
+    bool isTransparent() const
+    {
+        return m_colorIsValid && !alphaChannel(m_color);
+    }
+
+    bool isVisible(bool checkStyle = true) const
+    {
+        return nonZero(checkStyle) && !isTransparent() && (!checkStyle || m_style != BHIDDEN);
+    }
+
+    bool operator==(const BorderValue& o) const
+    {
+        return m_width == o.m_width && m_style == o.m_style && m_color == o.m_color && m_colorIsValid == o.m_colorIsValid;
+    }
+
+    bool operator!=(const BorderValue& o) const
+    {
+        return !(*this == o);
+    }
+
+    void setColor(const Color& color)
+    {
+        m_color = color.rgb();
+        m_colorIsValid = color.isValid();
+    }
+
+    Color color() const { return Color(m_color, m_colorIsValid); }
+
+    unsigned width() const { return m_width; }
+    EBorderStyle style() const { return static_cast<EBorderStyle>(m_style); }
+
+protected:
+    RGBA32 m_color;
+    unsigned m_colorIsValid : 1;
+
+    unsigned m_width : 26;
+    unsigned m_style : 4; // EBorderStyle
+
+    // This is only used by OutlineValue but moved here to keep the bits packed.
+    unsigned m_isAuto : 1; // OutlineIsAuto
+};
+
+} // namespace WebCore
+
+#endif // BorderValue_h
diff --git a/Source/core/rendering/style/CollapsedBorderValue.h b/Source/core/rendering/style/CollapsedBorderValue.h
new file mode 100644
index 0000000..ef16dba
--- /dev/null
+++ b/Source/core/rendering/style/CollapsedBorderValue.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ *           (C) 2000 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com)
+ *
+ * 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 "core/rendering/style/BorderValue.h"
+
+namespace WebCore {
+
+class CollapsedBorderValue {
+public:
+    CollapsedBorderValue()
+        : m_color(0)
+        , m_colorIsValid(false)
+        , m_width(0)
+        , m_style(BNONE)
+        , m_precedence(BOFF)
+        , m_transparent(false)
+    {
+    }
+
+    CollapsedBorderValue(const BorderValue& border, const Color& color, EBorderPrecedence precedence)
+        : m_color(color.rgb())
+        , m_colorIsValid(color.isValid())
+        , m_width(border.nonZero() ? border.width() : 0)
+        , m_style(border.style())
+        , m_precedence(precedence)
+        , m_transparent(border.isTransparent())
+    {
+    }
+
+    unsigned width() const { return m_style > BHIDDEN ? m_width : 0; }
+    EBorderStyle style() const { return static_cast<EBorderStyle>(m_style); }
+    bool exists() const { return m_precedence != BOFF; }
+    Color color() const { return Color(m_color, m_colorIsValid); }
+    bool isTransparent() const { return m_transparent; }
+    EBorderPrecedence precedence() const { return static_cast<EBorderPrecedence>(m_precedence); }
+
+    bool isSameIgnoringColor(const CollapsedBorderValue& o) const
+    {
+        return width() == o.width() && style() == o.style() && precedence() == o.precedence();
+    }
+
+private:
+    RGBA32 m_color;
+    unsigned m_colorIsValid : 1;
+    unsigned m_width : 23;
+    unsigned m_style : 4; // EBorderStyle
+    unsigned m_precedence : 3; // EBorderPrecedence
+    unsigned m_transparent : 1;
+};
+
+} // namespace WebCore
+
+#endif // CollapsedBorderValue_h
diff --git a/Source/core/rendering/style/ContentData.cpp b/Source/core/rendering/style/ContentData.cpp
new file mode 100644
index 0000000..38d4d56
--- /dev/null
+++ b/Source/core/rendering/style/ContentData.cpp
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 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 "core/rendering/style/ContentData.h"
+
+#include "core/rendering/RenderCounter.h"
+#include "core/rendering/RenderImage.h"
+#include "core/rendering/RenderImageResource.h"
+#include "core/rendering/RenderImageResourceStyleImage.h"
+#include "core/rendering/RenderQuote.h"
+#include "core/rendering/RenderTextFragment.h"
+#include "core/rendering/style/RenderStyle.h"
+#include "core/rendering/style/StyleInheritedData.h"
+
+namespace WebCore {
+
+PassOwnPtr<ContentData> ContentData::create(PassRefPtr<StyleImage> image)
+{
+    return adoptPtr(new ImageContentData(image));
+}
+
+PassOwnPtr<ContentData> ContentData::create(const String& text)
+{
+    return adoptPtr(new TextContentData(text));
+}
+
+PassOwnPtr<ContentData> ContentData::create(PassOwnPtr<CounterContent> counter)
+{
+    return adoptPtr(new CounterContentData(counter));
+}
+
+PassOwnPtr<ContentData> ContentData::create(QuoteType quote)
+{
+    return adoptPtr(new QuoteContentData(quote));
+}
+
+PassOwnPtr<ContentData> ContentData::clone() const
+{
+    OwnPtr<ContentData> result = cloneInternal();
+    
+    ContentData* lastNewData = result.get();
+    for (const ContentData* contentData = next(); contentData; contentData = contentData->next()) {
+        OwnPtr<ContentData> newData = contentData->cloneInternal();
+        lastNewData->setNext(newData.release());
+        lastNewData = lastNewData->next();
+    }
+        
+    return result.release();
+}
+
+RenderObject* ImageContentData::createRenderer(Document* doc, RenderStyle* pseudoStyle) const
+{
+    RenderImage* image = RenderImage::createAnonymous(doc);
+    image->setPseudoStyle(pseudoStyle);
+    if (m_image)
+        image->setImageResource(RenderImageResourceStyleImage::create(m_image.get()));
+    else
+        image->setImageResource(RenderImageResource::create());
+    return image;
+}
+
+RenderObject* TextContentData::createRenderer(Document* doc, RenderStyle* pseudoStyle) const
+{
+    RenderObject* renderer = new (doc->renderArena()) RenderTextFragment(doc, m_text.impl());
+    renderer->setPseudoStyle(pseudoStyle);
+    return renderer;
+}
+
+RenderObject* CounterContentData::createRenderer(Document* doc, RenderStyle* pseudoStyle) const
+{
+    RenderObject* renderer = new (doc->renderArena()) RenderCounter(doc, *m_counter);
+    renderer->setPseudoStyle(pseudoStyle);
+    return renderer;
+}
+
+RenderObject* QuoteContentData::createRenderer(Document* doc, RenderStyle* pseudoStyle) const
+{
+    RenderObject* renderer = new (doc->renderArena()) RenderQuote(doc, m_quote);
+    renderer->setPseudoStyle(pseudoStyle);
+    return renderer;
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/style/ContentData.h b/Source/core/rendering/style/ContentData.h
new file mode 100644
index 0000000..e93bff3
--- /dev/null
+++ b/Source/core/rendering/style/ContentData.h
@@ -0,0 +1,198 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ *           (C) 2000 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com)
+ *
+ * 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 "core/rendering/style/CounterContent.h"
+#include "core/rendering/style/StyleImage.h"
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+
+namespace WebCore {
+
+class Document;
+class RenderObject;
+class RenderStyle;
+
+class ContentData {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    static PassOwnPtr<ContentData> create(PassRefPtr<StyleImage>);
+    static PassOwnPtr<ContentData> create(const String&);
+    static PassOwnPtr<ContentData> create(PassOwnPtr<CounterContent>);
+    static PassOwnPtr<ContentData> create(QuoteType);
+    
+    virtual ~ContentData() { }
+
+    virtual bool isCounter() const { return false; }
+    virtual bool isImage() const { return false; }
+    virtual bool isQuote() const { return false; }
+    virtual bool isText() const { return false; }
+
+    virtual RenderObject* createRenderer(Document*, RenderStyle*) const = 0;
+
+    virtual PassOwnPtr<ContentData> clone() const;
+
+    ContentData* next() const { return m_next.get(); }
+    void setNext(PassOwnPtr<ContentData> next) { m_next = next; }
+
+    virtual bool equals(const ContentData&) const = 0;
+
+private:
+    virtual PassOwnPtr<ContentData> cloneInternal() const = 0;
+
+    OwnPtr<ContentData> m_next;
+};
+
+class ImageContentData : public ContentData {
+    friend class ContentData;
+public:
+    const StyleImage* image() const { return m_image.get(); }
+    StyleImage* image() { return m_image.get(); }
+    void setImage(PassRefPtr<StyleImage> image) { m_image = image; }
+
+    virtual bool isImage() const OVERRIDE { return true; }
+    virtual RenderObject* createRenderer(Document*, RenderStyle*) const OVERRIDE;
+
+    virtual bool equals(const ContentData& data) const OVERRIDE
+    {
+        if (!data.isImage())
+            return false;
+        return *static_cast<const ImageContentData&>(data).image() == *image();
+    }
+
+private:
+    ImageContentData(PassRefPtr<StyleImage> image)
+        : m_image(image)
+    {
+    }
+
+    virtual PassOwnPtr<ContentData> cloneInternal() const
+    {
+        RefPtr<StyleImage> image = const_cast<StyleImage*>(this->image());
+        return create(image.release());
+    }
+
+    RefPtr<StyleImage> m_image;
+};
+
+class TextContentData : public ContentData {
+    friend class ContentData;
+public:
+    const String& text() const { return m_text; }
+    void setText(const String& text) { m_text = text; }
+
+    virtual bool isText() const OVERRIDE { return true; }
+    virtual RenderObject* createRenderer(Document*, RenderStyle*) const OVERRIDE;
+
+    virtual bool equals(const ContentData& data) const OVERRIDE
+    {
+        if (!data.isText())
+            return false;
+        return static_cast<const TextContentData&>(data).text() == text();
+    }
+
+private:
+    TextContentData(const String& text)
+        : m_text(text)
+    {
+    }
+
+    virtual PassOwnPtr<ContentData> cloneInternal() const { return create(text()); }
+
+    String m_text;
+};
+
+class CounterContentData : public ContentData {
+    friend class ContentData;
+public:
+    const CounterContent* counter() const { return m_counter.get(); }
+    void setCounter(PassOwnPtr<CounterContent> counter) { m_counter = counter; }
+
+    virtual bool isCounter() const OVERRIDE { return true; }
+    virtual RenderObject* createRenderer(Document*, RenderStyle*) const OVERRIDE;
+
+private:
+    CounterContentData(PassOwnPtr<CounterContent> counter)
+        : m_counter(counter)
+    {
+    }
+
+    virtual PassOwnPtr<ContentData> cloneInternal() const
+    {
+        OwnPtr<CounterContent> counterData = adoptPtr(new CounterContent(*counter()));
+        return create(counterData.release());
+    }
+
+    virtual bool equals(const ContentData& data) const OVERRIDE
+    {
+        if (!data.isCounter())
+            return false;
+        return *static_cast<const CounterContentData&>(data).counter() == *counter();
+    }
+
+    OwnPtr<CounterContent> m_counter;
+};
+
+class QuoteContentData : public ContentData {
+    friend class ContentData;
+public:
+    QuoteType quote() const { return m_quote; }
+    void setQuote(QuoteType quote) { m_quote = quote; }
+
+    virtual bool isQuote() const OVERRIDE { return true; }
+    virtual RenderObject* createRenderer(Document*, RenderStyle*) const OVERRIDE;
+
+    virtual bool equals(const ContentData& data) const OVERRIDE
+    {
+        if (!data.isQuote())
+            return false;
+        return static_cast<const QuoteContentData&>(data).quote() == quote();
+    }
+
+private:
+    QuoteContentData(QuoteType quote)
+        : m_quote(quote)
+    {
+    }
+
+    virtual PassOwnPtr<ContentData> cloneInternal() const { return create(quote()); }
+
+    QuoteType m_quote;
+};
+
+inline bool operator==(const ContentData& a, const ContentData& b)
+{
+    return a.equals(b);
+}
+
+inline bool operator!=(const ContentData& a, const ContentData& b)
+{
+    return !(a == b);
+}
+
+} // namespace WebCore
+
+#endif // ContentData_h
diff --git a/Source/core/rendering/style/CounterContent.h b/Source/core/rendering/style/CounterContent.h
new file mode 100644
index 0000000..571956e
--- /dev/null
+++ b/Source/core/rendering/style/CounterContent.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ *           (C) 2000 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com)
+ *
+ * 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 "core/rendering/style/RenderStyleConstants.h"
+#include <wtf/text/AtomicString.h>
+
+namespace WebCore {
+
+class CounterContent {
+    WTF_MAKE_FAST_ALLOCATED;
+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/Source/core/rendering/style/CounterDirectives.cpp b/Source/core/rendering/style/CounterDirectives.cpp
new file mode 100644
index 0000000..a2913be
--- /dev/null
+++ b/Source/core/rendering/style/CounterDirectives.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * 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 "core/rendering/style/CounterDirectives.h"
+#include <wtf/PassOwnPtr.h>
+
+namespace WebCore {
+
+bool operator==(const CounterDirectives& a, const CounterDirectives& b)
+{
+    return a.isIncrement() == b.isIncrement()
+      && a.incrementValue() == b.incrementValue()
+      && a.isReset() == b.isReset()
+      && a.resetValue() == b.resetValue();
+}
+
+PassOwnPtr<CounterDirectiveMap> clone(const CounterDirectiveMap& counterDirectives)
+{
+    OwnPtr<CounterDirectiveMap> result = adoptPtr(new CounterDirectiveMap);
+    *result = counterDirectives;
+    return result.release();
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/style/CounterDirectives.h b/Source/core/rendering/style/CounterDirectives.h
new file mode 100644
index 0000000..cf793bb
--- /dev/null
+++ b/Source/core/rendering/style/CounterDirectives.h
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ *           (C) 2000 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com)
+ *
+ * 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 <wtf/HashMap.h>
+#include <wtf/MathExtras.h>
+#include <wtf/RefPtr.h>
+#include <wtf/text/AtomicString.h>
+#include <wtf/text/AtomicStringHash.h>
+
+namespace WebCore {
+
+class CounterDirectives {
+public:
+    CounterDirectives()
+        : m_isResetSet(false)
+        , m_isIncrementSet(false)
+        , m_resetValue(0)
+        , m_incrementValue(0)
+    {
+    }
+
+    // FIXME: The code duplication here could possibly be replaced by using two
+    // maps, or by using a container that held two generic Directive objects.
+
+    bool isReset() const { return m_isResetSet; }
+    int resetValue() const { return m_resetValue; }
+    void setResetValue(int value)
+    {
+        m_resetValue = value;
+        m_isResetSet = true;
+    }
+    void clearReset()
+    {
+        m_resetValue = 0;
+        m_isResetSet = false;
+    }
+    void inheritReset(CounterDirectives& parent)
+    {
+        m_resetValue = parent.m_resetValue;
+        m_isResetSet = parent.m_isResetSet;
+    }
+
+    bool isIncrement() const { return m_isIncrementSet; }
+    int incrementValue() const { return m_incrementValue; }
+    void addIncrementValue(int value)
+    {
+        m_incrementValue = clampToInteger((double)m_incrementValue + value);
+        m_isIncrementSet = true;
+    }
+    void clearIncrement()
+    {
+        m_incrementValue = 0;
+        m_isIncrementSet = false;
+    }
+    void inheritIncrement(CounterDirectives& parent)
+    {
+        m_incrementValue = parent.m_incrementValue;
+        m_isIncrementSet = parent.m_isIncrementSet;
+    }
+
+    bool isDefined() const { return isReset() || isIncrement(); }
+
+    int combinedValue() const
+    {
+        ASSERT(m_isResetSet || !m_resetValue);
+        ASSERT(m_isIncrementSet || !m_incrementValue);
+        // FIXME: Shouldn't allow overflow here.
+        return m_resetValue + m_incrementValue;
+    }
+
+private:
+    bool m_isResetSet;
+    bool m_isIncrementSet;
+    int m_resetValue;
+    int m_incrementValue;
+};
+
+bool operator==(const CounterDirectives&, const CounterDirectives&);
+inline bool operator!=(const CounterDirectives& a, const CounterDirectives& b) { return !(a == b); }
+
+typedef HashMap<AtomicString, CounterDirectives> CounterDirectiveMap;
+
+PassOwnPtr<CounterDirectiveMap> clone(const CounterDirectiveMap&);
+
+} // namespace WebCore
+
+#endif // CounterDirectives_h
diff --git a/Source/core/rendering/style/CursorData.h b/Source/core/rendering/style/CursorData.h
new file mode 100644
index 0000000..e2f2ea0
--- /dev/null
+++ b/Source/core/rendering/style/CursorData.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ *           (C) 2000 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com)
+ *
+ * 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 "core/platform/graphics/IntPoint.h"
+#include "core/rendering/style/StyleImage.h"
+
+namespace WebCore {
+
+class CursorData {
+public:
+    CursorData(PassRefPtr<StyleImage> image, const IntPoint& hotSpot)
+        : m_image(image)
+        , m_hotSpot(hotSpot)
+    {
+    }
+
+    bool operator==(const CursorData& o) const
+    {
+        return m_hotSpot == o.m_hotSpot && m_image == o.m_image;
+    }
+
+    bool operator!=(const CursorData& o) const
+    {
+        return !(*this == o);
+    }
+
+    StyleImage* image() const { return m_image.get(); }    
+    void setImage(PassRefPtr<StyleImage> image) { m_image = image; }    
+
+    // Hot spot in the image in logical pixels.
+    const IntPoint& hotSpot() const { return m_hotSpot; }
+    
+private:
+    RefPtr<StyleImage> m_image;
+    IntPoint m_hotSpot; // for CSS3 support
+};
+
+} // namespace WebCore
+
+#endif // CursorData_h
diff --git a/Source/core/rendering/style/CursorList.h b/Source/core/rendering/style/CursorList.h
new file mode 100644
index 0000000..fe7cfb6
--- /dev/null
+++ b/Source/core/rendering/style/CursorList.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ *           (C) 2000 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com)
+ *
+ * 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 "core/rendering/style/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]; }
+    CursorData& operator[](int i) { return m_vector[i]; }
+    const CursorData& at(size_t i) const { return m_vector.at(i); }
+    CursorData& at(size_t i) { return m_vector.at(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/Source/core/rendering/style/DataRef.h b/Source/core/rendering/style/DataRef.h
new file mode 100644
index 0000000..cac8987
--- /dev/null
+++ b/Source/core/rendering/style/DataRef.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ *           (C) 2000 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2000 Dirk Mueller (mueller@kde.org)
+ * 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;
+    }
+
+    // Template helps us to write the implementation without MemoryInstrumentation.h include.
+    template<typename MemoryObjectInfo>
+    void reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+    {
+        typename MemoryObjectInfo::ClassInfo info(memoryObjectInfo, this);
+        info.addMember(m_data, "data");
+    }
+
+private:
+    RefPtr<T> m_data;
+};
+
+} // namespace WebCore
+
+#endif // DataRef_h
diff --git a/Source/core/rendering/style/ExclusionShapeValue.h b/Source/core/rendering/style/ExclusionShapeValue.h
new file mode 100644
index 0000000..874ad3c
--- /dev/null
+++ b/Source/core/rendering/style/ExclusionShapeValue.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2012 Adobe Systems Incorporated. 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 THE COPYRIGHT HOLDER "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 THE COPYRIGHT HOLDER 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 ExclusionShapeValue_h
+#define ExclusionShapeValue_h
+
+#include "core/rendering/style/BasicShapes.h"
+#include <wtf/PassRefPtr.h>
+
+namespace WebCore {
+
+class ExclusionShapeValue : public RefCounted<ExclusionShapeValue> {
+public:
+    enum ExclusionShapeValueType {
+        // The AUTO value is defined by a null ExclusionShapeValue*
+        SHAPE,
+        OUTSIDE
+    };
+
+    static PassRefPtr<ExclusionShapeValue> createShapeValue(PassRefPtr<BasicShape> shape)
+    {
+        return adoptRef(new ExclusionShapeValue(shape));
+    }
+
+    static PassRefPtr<ExclusionShapeValue> createOutsideValue()
+    {
+        return adoptRef(new ExclusionShapeValue(OUTSIDE));
+    }
+
+    ExclusionShapeValueType type() const { return m_type; }
+    BasicShape* shape() const { return m_shape.get(); }
+    bool operator==(const ExclusionShapeValue& other) const { return type() == other.type(); }
+
+private:
+    ExclusionShapeValue(PassRefPtr<BasicShape> shape) : m_type(SHAPE), m_shape(shape) { }
+    ExclusionShapeValue(ExclusionShapeValueType type) : m_type(type) { }
+    ExclusionShapeValueType m_type;
+    RefPtr<BasicShape> m_shape;
+};
+
+}
+
+#endif
diff --git a/Source/core/rendering/style/FillLayer.cpp b/Source/core/rendering/style/FillLayer.cpp
new file mode 100644
index 0000000..5d6aa23
--- /dev/null
+++ b/Source/core/rendering/style/FillLayer.cpp
@@ -0,0 +1,365 @@
+/*
+ * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * 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 "core/rendering/style/FillLayer.h"
+
+namespace WebCore {
+
+struct SameSizeAsFillLayer {
+    FillLayer* m_next;
+
+    RefPtr<StyleImage> m_image;
+
+    Length m_xPosition;
+    Length m_yPosition;
+
+    LengthSize m_sizeLength;
+
+    unsigned m_bitfields: 32;
+    unsigned m_bitfields2: 1;
+};
+
+COMPILE_ASSERT(sizeof(FillLayer) == sizeof(SameSizeAsFillLayer), FillLayer_should_stay_small);
+
+FillLayer::FillLayer(EFillLayerType type)
+    : m_next(0)
+    , m_image(FillLayer::initialFillImage(type))
+    , m_xPosition(FillLayer::initialFillXPosition(type))
+    , m_yPosition(FillLayer::initialFillYPosition(type))
+    , m_sizeLength(FillLayer::initialFillSizeLength(type))
+    , m_attachment(FillLayer::initialFillAttachment(type))
+    , m_clip(FillLayer::initialFillClip(type))
+    , m_origin(FillLayer::initialFillOrigin(type))
+    , m_repeatX(FillLayer::initialFillRepeatX(type))
+    , m_repeatY(FillLayer::initialFillRepeatY(type))
+    , m_composite(FillLayer::initialFillComposite(type))
+    , m_sizeType(FillLayer::initialFillSizeType(type))
+    , m_blendMode(FillLayer::initialFillBlendMode(type))
+    , m_imageSet(false)
+    , m_attachmentSet(false)
+    , m_clipSet(false)
+    , m_originSet(false)
+    , m_repeatXSet(false)
+    , m_repeatYSet(false)
+    , m_xPosSet(false)
+    , m_yPosSet(false)
+    , m_backgroundOriginSet(false)
+    , m_backgroundXOrigin(LeftEdge)
+    , m_backgroundYOrigin(TopEdge)
+    , m_compositeSet(type == MaskFillLayer)
+    , m_blendModeSet(false)
+    , m_type(type)
+{
+}
+
+FillLayer::FillLayer(const FillLayer& o)
+    : 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_sizeLength(o.m_sizeLength)
+    , m_attachment(o.m_attachment)
+    , m_clip(o.m_clip)
+    , m_origin(o.m_origin)
+    , m_repeatX(o.m_repeatX)
+    , m_repeatY(o.m_repeatY)
+    , m_composite(o.m_composite)
+    , m_sizeType(o.m_sizeType)
+    , m_blendMode(o.m_blendMode)
+    , m_imageSet(o.m_imageSet)
+    , m_attachmentSet(o.m_attachmentSet)
+    , m_clipSet(o.m_clipSet)
+    , m_originSet(o.m_originSet)
+    , m_repeatXSet(o.m_repeatXSet)
+    , m_repeatYSet(o.m_repeatYSet)
+    , m_xPosSet(o.m_xPosSet)
+    , m_yPosSet(o.m_yPosSet)
+    , m_backgroundOriginSet(o.m_backgroundOriginSet)
+    , m_backgroundXOrigin(o.m_backgroundXOrigin)
+    , m_backgroundYOrigin(o.m_backgroundYOrigin)
+    , m_compositeSet(o.m_compositeSet)
+    , m_blendModeSet(o.m_blendModeSet)
+    , m_type(o.m_type)
+{
+}
+
+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_backgroundXOrigin = o.m_backgroundXOrigin;
+    m_backgroundYOrigin = o.m_backgroundYOrigin;
+    m_backgroundOriginSet = o.m_backgroundOriginSet;
+    m_sizeLength = o.m_sizeLength;
+    m_attachment = o.m_attachment;
+    m_clip = o.m_clip;
+    m_composite = o.m_composite;
+    m_blendMode = o.m_blendMode;
+    m_origin = o.m_origin;
+    m_repeatX = o.m_repeatX;
+    m_repeatY = o.m_repeatY;
+    m_sizeType = o.m_sizeType;
+
+    m_imageSet = o.m_imageSet;
+    m_attachmentSet = o.m_attachmentSet;
+    m_clipSet = o.m_clipSet;
+    m_compositeSet = o.m_compositeSet;
+    m_blendModeSet = o.m_blendModeSet;
+    m_originSet = o.m_originSet;
+    m_repeatXSet = o.m_repeatXSet;
+    m_repeatYSet = o.m_repeatYSet;
+    m_xPosSet = o.m_xPosSet;
+    m_yPosSet = o.m_yPosSet;
+    
+    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_backgroundXOrigin == o.m_backgroundXOrigin && m_backgroundYOrigin == o.m_backgroundYOrigin
+            && m_attachment == o.m_attachment && m_clip == o.m_clip && m_composite == o.m_composite
+            && m_blendModeSet == o.m_blendModeSet && m_origin == o.m_origin && m_repeatX == o.m_repeatX
+            && m_repeatY == o.m_repeatY && m_sizeType == o.m_sizeType && m_sizeLength == o.m_sizeLength
+            && 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->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;
+            if (pattern->isBackgroundOriginSet()) {
+                curr->m_backgroundXOrigin = pattern->m_backgroundXOrigin;
+                curr->m_backgroundYOrigin = pattern->m_backgroundYOrigin;
+            }
+            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;
+            if (pattern->isBackgroundOriginSet()) {
+                curr->m_backgroundXOrigin = pattern->m_backgroundXOrigin;
+                curr->m_backgroundYOrigin = pattern->m_backgroundYOrigin;
+            }
+            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->isBlendModeSet(); 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_blendMode = pattern->m_blendMode;
+            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->isRepeatXSet(); 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_repeatX = pattern->m_repeatX;
+            pattern = pattern->next();
+            if (pattern == curr || !pattern)
+                pattern = this;
+        }
+    }
+
+    for (curr = this; curr && curr->isRepeatYSet(); 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_repeatY = pattern->m_repeatY;
+            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_sizeType = pattern->m_sizeType;
+            curr->m_sizeLength = pattern->m_sizeLength;
+            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()) {
+            delete next;
+            p->m_next = 0;
+            break;
+        }
+    }
+}
+
+static EFillBox clipMax(EFillBox clipA, EFillBox clipB)
+{
+    if (clipA == BorderFillBox || clipB == BorderFillBox)
+        return BorderFillBox;
+    if (clipA == PaddingFillBox || clipB == PaddingFillBox)
+        return PaddingFillBox;
+    if (clipA == ContentFillBox || clipB == ContentFillBox)
+        return ContentFillBox;
+    return TextFillBox;
+}
+
+void FillLayer::computeClipMax() const
+{
+    if (m_next) {
+        m_next->computeClipMax();
+        m_clipMax = clipMax(clip(), m_next->clip());
+    } else
+        m_clipMax = m_clip;
+}
+
+bool FillLayer::clipOccludesNextLayers(bool firstLayer) const
+{
+    if (firstLayer)
+        computeClipMax();
+    return m_clip == m_clipMax;
+}
+
+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;
+}
+
+bool FillLayer::imagesAreLoaded() const
+{
+    const FillLayer* curr;
+    for (curr = this; curr; curr = curr->next()) {
+        if (curr->m_image && !curr->m_image->isLoaded())
+            return false;
+    }
+
+    return true;
+}
+
+bool FillLayer::hasOpaqueImage(const RenderObject* renderer) const
+{
+    if (!m_image)
+        return false;
+
+    if (m_composite == CompositeClear || m_composite == CompositeCopy)
+        return true;
+
+    if (m_composite == CompositeSourceOver)
+        return m_image->knownToBeOpaque(renderer);
+
+    return false;
+}
+
+bool FillLayer::hasRepeatXY() const
+{
+    return m_repeatX == RepeatFill && m_repeatY == RepeatFill;
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/style/FillLayer.h b/Source/core/rendering/style/FillLayer.h
new file mode 100644
index 0000000..a3b0092
--- /dev/null
+++ b/Source/core/rendering/style/FillLayer.h
@@ -0,0 +1,234 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ *           (C) 2000 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com)
+ *
+ * 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 "core/platform/Length.h"
+#include "core/platform/LengthSize.h"
+#include "core/platform/graphics/GraphicsTypes.h"
+#include "core/rendering/style/RenderStyleConstants.h"
+#include "core/rendering/style/StyleImage.h"
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+struct FillSize {
+    FillSize()
+        : type(SizeLength)
+    {
+    }
+
+    FillSize(EFillSizeType t, LengthSize l)
+        : type(t)
+        , size(l)
+    {
+    }
+
+    bool operator==(const FillSize& o) const
+    {
+        return type == o.type && size == o.size;
+    }
+    bool operator!=(const FillSize& o) const
+    {
+        return !(*this == o);
+    }
+
+    EFillSizeType type;
+    LengthSize size;
+};
+
+class FillLayer {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    FillLayer(EFillLayerType);
+    ~FillLayer();
+
+    StyleImage* image() const { return m_image.get(); }
+    Length xPosition() const { return m_xPosition; }
+    Length yPosition() const { return m_yPosition; }
+    BackgroundEdgeOrigin backgroundXOrigin() const { return static_cast<BackgroundEdgeOrigin>(m_backgroundXOrigin); }
+    BackgroundEdgeOrigin backgroundYOrigin() const { return static_cast<BackgroundEdgeOrigin>(m_backgroundYOrigin); }
+    EFillAttachment attachment() const { return static_cast<EFillAttachment>(m_attachment); }
+    EFillBox clip() const { return static_cast<EFillBox>(m_clip); }
+    EFillBox origin() const { return static_cast<EFillBox>(m_origin); }
+    EFillRepeat repeatX() const { return static_cast<EFillRepeat>(m_repeatX); }
+    EFillRepeat repeatY() const { return static_cast<EFillRepeat>(m_repeatY); }
+    CompositeOperator composite() const { return static_cast<CompositeOperator>(m_composite); }
+    BlendMode blendMode() const { return static_cast<BlendMode>(m_blendMode); }
+    LengthSize sizeLength() const { return m_sizeLength; }
+    EFillSizeType sizeType() const { return static_cast<EFillSizeType>(m_sizeType); }
+    FillSize size() const { return FillSize(static_cast<EFillSizeType>(m_sizeType), m_sizeLength); }
+
+    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 isBackgroundOriginSet() const { return m_backgroundOriginSet; }
+    bool isAttachmentSet() const { return m_attachmentSet; }
+    bool isClipSet() const { return m_clipSet; }
+    bool isOriginSet() const { return m_originSet; }
+    bool isRepeatXSet() const { return m_repeatXSet; }
+    bool isRepeatYSet() const { return m_repeatYSet; }
+    bool isCompositeSet() const { return m_compositeSet; }
+    bool isBlendModeSet() const { return m_blendModeSet; }
+    bool isSizeSet() const { return m_sizeType != SizeNone; }
+    
+    void setImage(PassRefPtr<StyleImage> i) { m_image = i; m_imageSet = true; }
+    void setXPosition(Length l) { m_xPosition = l; m_xPosSet = true; }
+    void setYPosition(Length l) { m_yPosition = l; m_yPosSet = true; }
+    void setBackgroundXOrigin(BackgroundEdgeOrigin o) { m_backgroundXOrigin = o; m_backgroundOriginSet = true; }
+    void setBackgroundYOrigin(BackgroundEdgeOrigin o) { m_backgroundYOrigin = o; m_backgroundOriginSet = true; }
+    void setAttachment(EFillAttachment attachment) { m_attachment = attachment; m_attachmentSet = true; }
+    void setClip(EFillBox b) { m_clip = b; m_clipSet = true; }
+    void setOrigin(EFillBox b) { m_origin = b; m_originSet = true; }
+    void setRepeatX(EFillRepeat r) { m_repeatX = r; m_repeatXSet = true; }
+    void setRepeatY(EFillRepeat r) { m_repeatY = r; m_repeatYSet = true; }
+    void setComposite(CompositeOperator c) { m_composite = c; m_compositeSet = true; }
+    void setBlendMode(BlendMode b) { m_blendMode = b; m_blendModeSet = true; }
+    void setSizeType(EFillSizeType b) { m_sizeType = b; }
+    void setSizeLength(LengthSize l) { m_sizeLength = l; }
+    void setSize(FillSize f) { m_sizeType = f.type; m_sizeLength = f.size; }
+    
+    void clearImage() { m_image.clear(); m_imageSet = false; }
+    void clearXPosition()
+    {
+        m_xPosSet = false;
+        m_backgroundOriginSet = false;
+    }
+    void clearYPosition()
+    {
+        m_yPosSet = false;
+        m_backgroundOriginSet = false;
+    }
+
+    void clearAttachment() { m_attachmentSet = false; }
+    void clearClip() { m_clipSet = false; }
+    void clearOrigin() { m_originSet = false; }
+    void clearRepeatX() { m_repeatXSet = false; }
+    void clearRepeatY() { m_repeatYSet = false; }
+    void clearComposite() { m_compositeSet = false; }
+    void clearBlendMode() { m_blendModeSet = false; }
+    void clearSize() { m_sizeType = SizeNone; }
+
+    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 imagesAreLoaded() const;
+
+    bool hasImage() const
+    {
+        if (m_image)
+            return true;
+        return m_next ? m_next->hasImage() : false;
+    }
+
+    bool hasFixedImage() const
+    {
+        if (m_image && m_attachment == FixedBackgroundAttachment)
+            return true;
+        return m_next ? m_next->hasFixedImage() : false;
+    }
+
+    bool hasOpaqueImage(const RenderObject*) const;
+    bool hasRepeatXY() const;
+    bool clipOccludesNextLayers(bool firstLayer) const;
+
+    EFillLayerType type() const { return static_cast<EFillLayerType>(m_type); }
+
+    void fillUnsetProperties();
+    void cullEmptyLayers();
+
+    static EFillAttachment initialFillAttachment(EFillLayerType) { return ScrollBackgroundAttachment; }
+    static EFillBox initialFillClip(EFillLayerType) { return BorderFillBox; }
+    static EFillBox initialFillOrigin(EFillLayerType type) { return type == BackgroundFillLayer ? PaddingFillBox : BorderFillBox; }
+    static EFillRepeat initialFillRepeatX(EFillLayerType) { return RepeatFill; }
+    static EFillRepeat initialFillRepeatY(EFillLayerType) { return RepeatFill; }
+    static CompositeOperator initialFillComposite(EFillLayerType) { return CompositeSourceOver; }
+    static BlendMode initialFillBlendMode(EFillLayerType) { return BlendModeNormal; }
+    static EFillSizeType initialFillSizeType(EFillLayerType) { return SizeNone; }
+    static LengthSize initialFillSizeLength(EFillLayerType) { return LengthSize(); }
+    static FillSize initialFillSize(EFillLayerType type) { return FillSize(initialFillSizeType(type), initialFillSizeLength(type)); }
+    static Length initialFillXPosition(EFillLayerType) { return Length(0.0, Percent); }
+    static Length initialFillYPosition(EFillLayerType) { return Length(0.0, Percent); }
+    static StyleImage* initialFillImage(EFillLayerType) { return 0; }
+
+private:
+    friend class RenderStyle;
+
+    void computeClipMax() const;
+
+    FillLayer() { }
+
+    FillLayer* m_next;
+
+    RefPtr<StyleImage> m_image;
+
+    Length m_xPosition;
+    Length m_yPosition;
+
+    LengthSize m_sizeLength;
+
+    unsigned m_attachment : 2; // EFillAttachment
+    unsigned m_clip : 2; // EFillBox
+    unsigned m_origin : 2; // EFillBox
+    unsigned m_repeatX : 3; // EFillRepeat
+    unsigned m_repeatY : 3; // EFillRepeat
+    unsigned m_composite : 4; // CompositeOperator
+    unsigned m_sizeType : 2; // EFillSizeType
+    unsigned m_blendMode : 5; // BlendMode
+    
+    unsigned m_imageSet : 1;
+    unsigned m_attachmentSet : 1;
+    unsigned m_clipSet : 1;
+    unsigned m_originSet : 1;
+    unsigned m_repeatXSet : 1;
+    unsigned m_repeatYSet : 1;
+    unsigned m_xPosSet : 1;
+    unsigned m_yPosSet : 1;
+    unsigned m_backgroundOriginSet : 1;
+    unsigned m_backgroundXOrigin : 2; // BackgroundEdgeOrigin
+    unsigned m_backgroundYOrigin : 2; // BackgroundEdgeOrigin
+    unsigned m_compositeSet : 1;
+    unsigned m_blendModeSet : 1;
+    
+    unsigned m_type : 1; // EFillLayerType
+
+    mutable unsigned m_clipMax : 2; // EFillBox, maximum m_clip value from this to bottom layer
+};
+
+} // namespace WebCore
+
+#endif // FillLayer_h
diff --git a/Source/core/rendering/style/GridLength.h b/Source/core/rendering/style/GridLength.h
new file mode 100644
index 0000000..6ba26b9
--- /dev/null
+++ b/Source/core/rendering/style/GridLength.h
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2013 Google 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:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+ * OWNER 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 GridLength_h
+#define GridLength_h
+
+#include "core/platform/Length.h"
+
+namespace WebCore {
+
+// This class wraps the <track-breadth> which can be either a <percentage>, <length>, min-content, max-content
+// or <flex>. This class avoids spreading the knowledge of <flex> throughout the rendering directory by adding
+// an new unit to Length.h.
+class GridLength {
+public:
+    GridLength()
+        : m_length(Undefined)
+        , m_flex(0)
+        , m_type(LengthType)
+    {
+    }
+
+    GridLength(const Length& length)
+        : m_length(length)
+        , m_flex(0)
+        , m_type(LengthType)
+    {
+    }
+
+    bool isLength() const { return m_type == LengthType; }
+    bool isFlex() const { return m_type == FlexType; }
+
+    const Length& length() const { ASSERT(isLength()); return m_length; }
+    Length& length() { ASSERT(isLength()); return m_length; }
+
+    double flex() const { ASSERT(isFlex()); return m_flex; }
+    void setFlex(double flex)
+    {
+        m_type = FlexType;
+        m_flex = flex;
+    }
+
+    bool operator==(const GridLength& o) const
+    {
+        return m_length == o.m_length;
+    }
+
+private:
+    // Ideally we would put the 2 following fields in a union, but Length has a constructor,
+    // a destructor and a copy assignment which isn't allowed.
+    Length m_length;
+    double m_flex;
+    enum GridLengthType {
+        LengthType,
+        FlexType
+    };
+    GridLengthType m_type;
+};
+
+} // namespace WebCore
+
+#endif // GridLength_h
diff --git a/Source/core/rendering/style/GridPosition.h b/Source/core/rendering/style/GridPosition.h
new file mode 100644
index 0000000..a099c4f
--- /dev/null
+++ b/Source/core/rendering/style/GridPosition.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2012 Google 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:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+ * OWNER 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 GridPosition_h
+#define GridPosition_h
+
+namespace WebCore {
+
+enum GridPositionType {
+    AutoPosition,
+    IntegerPosition,
+    SpanPosition
+};
+
+class GridPosition {
+public:
+    GridPosition()
+        : m_type(AutoPosition)
+        , m_integerPosition(0)
+    {
+    }
+
+    bool isPositive() const { return integerPosition() > 0; }
+
+    GridPositionType type() const { return m_type; }
+    bool isAuto() const { return m_type == AutoPosition; }
+    bool isInteger() const { return m_type == IntegerPosition; }
+    bool isSpan() const { return m_type == SpanPosition; }
+
+    void setIntegerPosition(int position)
+    {
+        m_type = IntegerPosition;
+        m_integerPosition = position;
+    }
+
+    // 'span' values cannot be negative, yet we reuse the <integer> position which can
+    // be. This means that we have to convert the span position to an integer, losing
+    // some precision here. It shouldn't be an issue in practice though.
+    void setSpanPosition(int position)
+    {
+        m_type = SpanPosition;
+        m_integerPosition = position;
+    }
+
+    int integerPosition() const
+    {
+        ASSERT(type() == IntegerPosition);
+        return m_integerPosition;
+    }
+
+    int spanPosition() const
+    {
+        ASSERT(type() == SpanPosition);
+        return m_integerPosition;
+    }
+
+    bool operator==(const GridPosition& other) const
+    {
+        return m_type == other.m_type && m_integerPosition == other.m_integerPosition;
+    }
+
+    bool shouldBeResolvedAgainstOppositePosition() const
+    {
+        return isAuto() || isSpan();
+    }
+private:
+    GridPositionType m_type;
+    int m_integerPosition;
+};
+
+} // namespace WebCore
+
+#endif // GridPosition_h
diff --git a/Source/core/rendering/style/GridTrackSize.h b/Source/core/rendering/style/GridTrackSize.h
new file mode 100644
index 0000000..55f0ca3
--- /dev/null
+++ b/Source/core/rendering/style/GridTrackSize.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2012 Google 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:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+ * OWNER 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 GridTrackSize_h
+#define GridTrackSize_h
+
+#include "core/rendering/style/GridLength.h"
+
+namespace WebCore {
+
+enum GridTrackSizeType {
+    LengthTrackSizing,
+    MinMaxTrackSizing
+};
+
+class GridTrackSize {
+public:
+    GridTrackSize(LengthType type = Undefined)
+        : m_type(LengthTrackSizing)
+        , m_minTrackBreadth(type)
+        , m_maxTrackBreadth(type)
+    {
+    }
+
+    const GridLength& length() const
+    {
+        ASSERT(m_type == LengthTrackSizing);
+        ASSERT(m_minTrackBreadth == m_maxTrackBreadth);
+        const GridLength& minTrackBreadth = m_minTrackBreadth;
+        ASSERT(!minTrackBreadth.isLength() || !minTrackBreadth.length().isUndefined());
+        return minTrackBreadth;
+    }
+
+    void setLength(const GridLength& length)
+    {
+        m_type = LengthTrackSizing;
+        m_minTrackBreadth = length;
+        m_maxTrackBreadth = length;
+    }
+
+    const GridLength& minTrackBreadth() const
+    {
+        ASSERT(!m_minTrackBreadth.isLength() || !m_minTrackBreadth.length().isUndefined());
+        if (m_minTrackBreadth.isLength() && m_minTrackBreadth.length().isAuto()) {
+            DEFINE_STATIC_LOCAL(GridLength, minContent, (MinContent));
+            return minContent;
+        }
+        return m_minTrackBreadth;
+    }
+
+    const GridLength& maxTrackBreadth() const
+    {
+        ASSERT(!m_maxTrackBreadth.isLength() || !m_maxTrackBreadth.length().isUndefined());
+        if (m_maxTrackBreadth.isLength() && m_maxTrackBreadth.length().isAuto()) {
+            DEFINE_STATIC_LOCAL(GridLength, maxContent, (MaxContent));
+            return maxContent;
+        }
+        return m_maxTrackBreadth;
+    }
+
+    void setMinMax(const GridLength& minTrackBreadth, const GridLength& maxTrackBreadth)
+    {
+        m_type = MinMaxTrackSizing;
+        m_minTrackBreadth = minTrackBreadth;
+        m_maxTrackBreadth = maxTrackBreadth;
+    }
+
+    GridTrackSizeType type() const { return m_type; }
+
+    bool operator==(const GridTrackSize& other) const
+    {
+        return m_type == other.m_type && m_minTrackBreadth == other.m_minTrackBreadth && m_maxTrackBreadth == other.m_maxTrackBreadth;
+    }
+
+    bool hasMinOrMaxContentMinTrackBreadth() const { return minTrackBreadth().isLength() && (minTrackBreadth().length().isMinContent() || minTrackBreadth().length().isMaxContent()); }
+    bool hasMaxContentMinTrackBreadth() const { return minTrackBreadth().isLength() && minTrackBreadth().length().isMaxContent(); }
+    bool hasMinOrMaxContentMaxTrackBreadth() const { return maxTrackBreadth().isLength() && (maxTrackBreadth().length().isMinContent() || maxTrackBreadth().length().isMaxContent()); }
+    bool hasMaxContentMaxTrackBreadth() const { return maxTrackBreadth().isLength() && maxTrackBreadth().length().isMaxContent(); }
+
+private:
+    GridTrackSizeType m_type;
+    GridLength m_minTrackBreadth;
+    GridLength m_maxTrackBreadth;
+};
+
+} // namespace WebCore
+
+#endif // GridTrackSize_h
diff --git a/Source/core/rendering/style/KeyframeList.cpp b/Source/core/rendering/style/KeyframeList.cpp
new file mode 100644
index 0000000..241be06
--- /dev/null
+++ b/Source/core/rendering/style/KeyframeList.cpp
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * 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 "core/rendering/RenderObject.h"
+#include "core/rendering/style/KeyframeList.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->key() != it2->key())
+            return false;
+        const RenderStyle& style1 = *it1->style();
+        const RenderStyle& style2 = *it2->style();
+        if (style1 != style2)
+            return false;
+        ++it2;
+    }
+
+    return true;
+}
+
+void KeyframeList::insert(const KeyframeValue& keyframe)
+{
+    if (keyframe.key() < 0 || keyframe.key() > 1)
+        return;
+
+    bool inserted = false;
+    bool replaced = false;
+    for (size_t i = 0; i < m_keyframes.size(); ++i) {
+        if (m_keyframes[i].key() == keyframe.key()) {
+            m_keyframes[i] = keyframe;
+            replaced = true;
+            break;
+        }
+
+        if (m_keyframes[i].key() > keyframe.key()) {
+            // insert before
+            m_keyframes.insert(i, keyframe);
+            inserted = true;
+            break;
+        }
+    }
+    
+    if (!replaced && !inserted)
+        m_keyframes.append(keyframe);
+
+    if (replaced) {
+        // We have to rebuild the properties list from scratch.
+        m_properties.clear();
+        for (Vector<KeyframeValue>::const_iterator it = m_keyframes.begin(); it != m_keyframes.end(); ++it) {
+            const KeyframeValue& currKeyframe = *it;
+            for (HashSet<CSSPropertyID>::const_iterator it = currKeyframe.properties().begin(); it != currKeyframe.properties().end(); ++it)
+                m_properties.add(*it);
+        }
+    } else {
+        for (HashSet<CSSPropertyID>::const_iterator it = keyframe.properties().begin(); it != keyframe.properties().end(); ++it)
+            m_properties.add(*it);
+    }
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/style/KeyframeList.h b/Source/core/rendering/style/KeyframeList.h
new file mode 100644
index 0000000..37eb316
--- /dev/null
+++ b/Source/core/rendering/style/KeyframeList.h
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ *           (C) 2000 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com)
+ *
+ * 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 "CSSPropertyNames.h"
+#include "core/rendering/style/StyleInheritedData.h"
+#include <wtf/HashSet.h>
+#include <wtf/RefPtr.h>
+#include <wtf/text/AtomicString.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class RenderObject;
+class RenderStyle;
+
+class KeyframeValue {
+public:
+    KeyframeValue(float key, PassRefPtr<RenderStyle> style)
+        : m_key(key)
+        , m_style(style)
+    {
+    }
+
+    void addProperty(CSSPropertyID prop) { m_properties.add(prop); }
+    bool containsProperty(CSSPropertyID prop) const { return m_properties.contains(prop); }
+    const HashSet<CSSPropertyID>& properties() const { return m_properties; }
+
+    float key() const { return m_key; }
+    void setKey(float key) { m_key = key; }
+
+    const RenderStyle* style() const { return m_style.get(); }
+    void setStyle(PassRefPtr<RenderStyle> style) { m_style = style; }
+
+private:
+    float m_key;
+    HashSet<CSSPropertyID> m_properties; // The properties specified in this keyframe.
+    RefPtr<RenderStyle> m_style;
+};
+
+class KeyframeList {
+public:
+    KeyframeList(RenderObject*, const AtomicString& animationName)
+        : m_animationName(animationName)
+    {
+        insert(KeyframeValue(0, 0));
+        insert(KeyframeValue(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(const KeyframeValue& keyframe);
+    
+    void addProperty(CSSPropertyID prop) { m_properties.add(prop); }
+    bool containsProperty(CSSPropertyID prop) const { return m_properties.contains(prop); }
+    HashSet<CSSPropertyID>::const_iterator beginProperties() const { return m_properties.begin(); }
+    HashSet<CSSPropertyID>::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(); }
+    const KeyframeValue& operator[](size_t index) const { return m_keyframes[index]; }
+
+private:
+    AtomicString m_animationName;
+    Vector<KeyframeValue> m_keyframes; // Kept sorted by key.
+    HashSet<CSSPropertyID> m_properties; // The properties being animated.
+};
+
+} // namespace WebCore
+
+#endif // KeyframeList_h
diff --git a/Source/core/rendering/style/LineClampValue.h b/Source/core/rendering/style/LineClampValue.h
new file mode 100644
index 0000000..e4b6249
--- /dev/null
+++ b/Source/core/rendering/style/LineClampValue.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2009 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. 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 INC. 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 LineClampValue_h
+#define LineClampValue_h
+
+#include "core/rendering/style/RenderStyleConstants.h"
+
+namespace WebCore {
+    
+class LineClampValue {
+public:
+    LineClampValue()
+        : m_type(LineClampLineCount)
+        , m_value(-1)
+    {
+    }
+    
+    LineClampValue(int value, ELineClampType type)
+        : m_type(type)
+        , m_value(value)
+    {
+    }
+    
+    int value() const { return m_value; }
+    
+    bool isPercentage() const { return m_type == LineClampPercentage; }
+
+    bool isNone() const { return m_value == -1; }
+
+    bool operator==(const LineClampValue& o) const
+    {
+        return value() == o.value() && isPercentage() == o.isPercentage();
+    }
+    
+    bool operator!=(const LineClampValue& o) const
+    {
+        return !(*this == o);
+    }
+    
+private:
+    ELineClampType m_type;
+    int m_value;
+};
+    
+} // namespace WebCore
+
+#endif // LineClampValue_h
diff --git a/Source/core/rendering/style/NinePieceImage.cpp b/Source/core/rendering/style/NinePieceImage.cpp
new file mode 100644
index 0000000..afe320e
--- /dev/null
+++ b/Source/core/rendering/style/NinePieceImage.cpp
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ *           (C) 2000 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008, 2013 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 "core/rendering/style/NinePieceImage.h"
+
+namespace WebCore {
+
+static DataRef<NinePieceImageData>& defaultData()
+{
+    static DataRef<NinePieceImageData>* data = new DataRef<NinePieceImageData>;
+    if (!data->get())
+        data->init();
+    return *data;
+}
+
+NinePieceImage::NinePieceImage()
+    : m_data(defaultData())
+{
+}
+
+NinePieceImage::NinePieceImage(PassRefPtr<StyleImage> image, LengthBox imageSlices, bool fill, LengthBox borderSlices, LengthBox outset, ENinePieceImageRule horizontalRule, ENinePieceImageRule verticalRule)
+{
+    m_data.init();
+    m_data.access()->image = image;
+    m_data.access()->imageSlices = imageSlices;
+    m_data.access()->borderSlices = borderSlices;
+    m_data.access()->outset = outset;
+    m_data.access()->fill = fill;
+    m_data.access()->horizontalRule = horizontalRule;
+    m_data.access()->verticalRule = verticalRule;
+}
+
+NinePieceImageData::NinePieceImageData()
+    : fill(false)
+    , horizontalRule(StretchImageRule)
+    , verticalRule(StretchImageRule)
+    , image(0)
+    , imageSlices(Length(100, Percent), Length(100, Percent), Length(100, Percent), Length(100, Percent))
+    , borderSlices(Length(1, Relative), Length(1, Relative), Length(1, Relative), Length(1, Relative))
+    , outset(0)
+{
+}
+
+NinePieceImageData::NinePieceImageData(const NinePieceImageData& other)
+    : RefCounted<NinePieceImageData>()
+    , fill(other.fill)
+    , horizontalRule(other.horizontalRule)
+    , verticalRule(other.verticalRule)
+    , image(other.image)
+    , imageSlices(other.imageSlices)
+    , borderSlices(other.borderSlices)
+    , outset(other.outset)
+{
+}
+
+bool NinePieceImageData::operator==(const NinePieceImageData& other) const
+{
+    return StyleImage::imagesEquivalent(image.get(), other.image.get())
+        && imageSlices == other.imageSlices
+        && fill == other.fill
+        && borderSlices == other.borderSlices
+        && outset == other.outset
+        && horizontalRule == other.horizontalRule
+        && verticalRule == other.verticalRule;
+}
+
+}
diff --git a/Source/core/rendering/style/NinePieceImage.h b/Source/core/rendering/style/NinePieceImage.h
new file mode 100644
index 0000000..f3cd38d
--- /dev/null
+++ b/Source/core/rendering/style/NinePieceImage.h
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ *           (C) 2000 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008, 2013 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 "core/platform/LayoutUnit.h"
+#include "core/platform/LengthBox.h"
+#include "core/rendering/style/DataRef.h"
+#include "core/rendering/style/StyleImage.h"
+
+namespace WebCore {
+
+enum ENinePieceImageRule {
+    StretchImageRule, RoundImageRule, SpaceImageRule, RepeatImageRule
+};
+
+class NinePieceImageData : public RefCounted<NinePieceImageData> {
+public:
+    static PassRefPtr<NinePieceImageData> create() { return adoptRef(new NinePieceImageData); }
+    PassRefPtr<NinePieceImageData> copy() const { return adoptRef(new NinePieceImageData(*this)); }
+
+    bool operator==(const NinePieceImageData&) const;
+    bool operator!=(const NinePieceImageData& o) const { return !(*this == o); }
+
+    bool fill : 1;
+    unsigned horizontalRule : 2; // ENinePieceImageRule
+    unsigned verticalRule : 2; // ENinePieceImageRule
+    RefPtr<StyleImage> image;
+    LengthBox imageSlices;
+    LengthBox borderSlices;
+    LengthBox outset;
+
+private:
+    NinePieceImageData();
+    NinePieceImageData(const NinePieceImageData&);
+};
+
+class NinePieceImage {
+public:
+    NinePieceImage();
+    NinePieceImage(PassRefPtr<StyleImage>, LengthBox imageSlices, bool fill, LengthBox borderSlices, LengthBox outset, ENinePieceImageRule horizontalRule, ENinePieceImageRule verticalRule);
+
+    bool operator==(const NinePieceImage& other) const { return m_data == other.m_data; }
+    bool operator!=(const NinePieceImage& other) const { return m_data != other.m_data; }
+
+    bool hasImage() const { return m_data->image; }
+    StyleImage* image() const { return m_data->image.get(); }
+    void setImage(PassRefPtr<StyleImage> image) { m_data.access()->image = image; }
+    
+    const LengthBox& imageSlices() const { return m_data->imageSlices; }
+    void setImageSlices(const LengthBox& slices) { m_data.access()->imageSlices = slices; }
+
+    bool fill() const { return m_data->fill; }
+    void setFill(bool fill) { m_data.access()->fill = fill; }
+
+    const LengthBox& borderSlices() const { return m_data->borderSlices; }
+    void setBorderSlices(const LengthBox& slices) { m_data.access()->borderSlices = slices; }
+
+    const LengthBox& outset() const { return m_data->outset; }
+    void setOutset(const LengthBox& outset) { m_data.access()->outset = outset; }
+
+    ENinePieceImageRule horizontalRule() const { return static_cast<ENinePieceImageRule>(m_data->horizontalRule); }
+    void setHorizontalRule(ENinePieceImageRule rule) { m_data.access()->horizontalRule = rule; }
+    
+    ENinePieceImageRule verticalRule() const { return static_cast<ENinePieceImageRule>(m_data->verticalRule); }
+    void setVerticalRule(ENinePieceImageRule rule) { m_data.access()->verticalRule = rule; }
+
+    void copyImageSlicesFrom(const NinePieceImage& other)
+    {
+        m_data.access()->imageSlices = other.m_data->imageSlices;
+        m_data.access()->fill = other.m_data->fill;
+    }
+
+    void copyBorderSlicesFrom(const NinePieceImage& other)
+    {
+        m_data.access()->borderSlices = other.m_data->borderSlices;
+    }
+    
+    void copyOutsetFrom(const NinePieceImage& other)
+    {
+        m_data.access()->outset = other.m_data->outset;
+    }
+
+    void copyRepeatFrom(const NinePieceImage& other)
+    {
+        m_data.access()->horizontalRule = other.m_data->horizontalRule;
+        m_data.access()->verticalRule = other.m_data->verticalRule;
+    }
+
+    void setMaskDefaults()
+    {
+        m_data.access()->imageSlices = LengthBox(0);
+        m_data.access()->fill = true;
+        m_data.access()->borderSlices = LengthBox();
+    }
+
+    static LayoutUnit computeOutset(Length outsetSide, LayoutUnit borderSide)
+    {
+        if (outsetSide.isRelative())
+            return outsetSide.value() * borderSide;
+        return outsetSide.value();
+    }
+
+private:
+    DataRef<NinePieceImageData> m_data;
+};
+
+} // namespace WebCore
+
+#endif // NinePieceImage_h
diff --git a/Source/core/rendering/style/OutlineValue.h b/Source/core/rendering/style/OutlineValue.h
new file mode 100644
index 0000000..df7775b
--- /dev/null
+++ b/Source/core/rendering/style/OutlineValue.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ *           (C) 2000 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com)
+ *
+ * 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 "core/rendering/style/BorderValue.h"
+
+namespace WebCore {
+
+class OutlineValue : public BorderValue {
+friend class RenderStyle;
+public:
+    OutlineValue()
+        : m_offset(0)
+    {
+    }
+    
+    bool operator==(const OutlineValue& o) const
+    {
+        return m_width == o.m_width && m_style == o.m_style && m_color == o.m_color && m_colorIsValid == o.m_colorIsValid && m_offset == o.m_offset && m_isAuto == o.m_isAuto;
+    }
+    
+    bool operator!=(const OutlineValue& o) const
+    {
+        return !(*this == o);
+    }
+    
+    int offset() const { return m_offset; }
+    OutlineIsAuto isAuto() const { return static_cast<OutlineIsAuto>(m_isAuto); }
+
+private:
+    int m_offset;
+};
+
+} // namespace WebCore
+
+#endif // OutlineValue_h
diff --git a/Source/core/rendering/style/QuotesData.cpp b/Source/core/rendering/style/QuotesData.cpp
new file mode 100644
index 0000000..876824d
--- /dev/null
+++ b/Source/core/rendering/style/QuotesData.cpp
@@ -0,0 +1,76 @@
+/**
+ * Copyright (C) 2011 Nokia Inc.  All rights reserved.
+ * Copyright (C) 2012 Google 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 "core/rendering/style/QuotesData.h"
+
+namespace WebCore {
+
+PassRefPtr<QuotesData> QuotesData::create(String open, String close)
+{
+    RefPtr<QuotesData> data = QuotesData::create();
+    data->addPair(std::make_pair(open, close));
+    return data;
+}
+
+PassRefPtr<QuotesData> QuotesData::create(String open1, String close1, String open2, String close2)
+{
+    RefPtr<QuotesData> data = QuotesData::create();
+    data->addPair(std::make_pair(open1, close1));
+    data->addPair(std::make_pair(open2, close2));
+    return data;
+}
+
+void QuotesData::addPair(std::pair<String, String> quotePair)
+{
+    m_quotePairs.append(quotePair);
+}
+
+const String QuotesData::getOpenQuote(int index) const
+{
+    ASSERT(index >= 0);
+    if (!m_quotePairs.size() || index < 0)
+        return emptyString();
+    if ((size_t)index >= m_quotePairs.size())
+        return m_quotePairs.last().first;
+    return m_quotePairs.at(index).first;
+}
+
+const String QuotesData::getCloseQuote(int index) const
+{
+    ASSERT(index >= -1);
+    if (!m_quotePairs.size() || index < 0)
+        return emptyString();
+    if ((size_t)index >= m_quotePairs.size())
+        return m_quotePairs.last().second;
+    return m_quotePairs.at(index).second;
+}
+
+bool QuotesData::equals(const QuotesData* a, const QuotesData* b)
+{
+    if (a == b)
+        return true;
+    if (!a || !b)
+        return false;
+    return a->m_quotePairs == b->m_quotePairs;
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/style/QuotesData.h b/Source/core/rendering/style/QuotesData.h
new file mode 100644
index 0000000..5699f32
--- /dev/null
+++ b/Source/core/rendering/style/QuotesData.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2011 Nokia Inc. All rights reserved.
+ * Copyright (C) 2012 Google 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 QuotesData_h
+#define QuotesData_h
+
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/Vector.h>
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class QuotesData : public RefCounted<QuotesData> {
+public:
+    static PassRefPtr<QuotesData> create() { return adoptRef(new QuotesData()); }
+    static PassRefPtr<QuotesData> create(const String open, const String close);
+    static PassRefPtr<QuotesData> create(const String open1, const String close1, const String open2, const String close2);
+
+    // FIXME: this should be an operator==.
+    static bool equals(const QuotesData*, const QuotesData*);
+
+    void addPair(const std::pair<String, String> quotePair);
+    const String getOpenQuote(int index) const;
+    const String getCloseQuote(int index) const;
+
+private:
+    QuotesData() { }
+
+    Vector<std::pair<String, String> > m_quotePairs;
+};
+
+} // namespace WebCore
+
+#endif // QuotesData_h
diff --git a/Source/core/rendering/style/RenderStyle.cpp b/Source/core/rendering/style/RenderStyle.cpp
new file mode 100644
index 0000000..deb6981
--- /dev/null
+++ b/Source/core/rendering/style/RenderStyle.cpp
@@ -0,0 +1,1592 @@
+/*
+ * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2011 Adobe Systems Incorporated. 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 "core/rendering/style/RenderStyle.h"
+
+#include <algorithm>
+#include "CSSPropertyNames.h"
+#include "core/css/StyleResolver.h"
+#include "core/dom/WebCoreMemoryInstrumentation.h"
+#include "core/platform/graphics/Font.h"
+#include "core/platform/graphics/FontSelector.h"
+#include "core/platform/graphics/transforms/ScaleTransformOperation.h"
+#include "core/rendering/RenderArena.h"
+#include "core/rendering/RenderObject.h"
+#include "core/rendering/RenderTheme.h"
+#include "core/rendering/TextAutosizer.h"
+#include "core/rendering/style/ContentData.h"
+#include "core/rendering/style/CursorList.h"
+#include "core/rendering/style/QuotesData.h"
+#include "core/rendering/style/ShadowData.h"
+#include "core/rendering/style/StyleImage.h"
+#include "core/rendering/style/StyleInheritedData.h"
+#include <wtf/MathExtras.h>
+#include <wtf/MemoryInstrumentationVector.h>
+#include <wtf/MemoryObjectInfo.h>
+#include <wtf/StdLibExtras.h>
+
+using namespace std;
+
+namespace WebCore {
+
+struct SameSizeAsBorderValue {
+    RGBA32 m_color;
+    unsigned m_width;
+};
+
+COMPILE_ASSERT(sizeof(BorderValue) == sizeof(SameSizeAsBorderValue), BorderValue_should_not_grow);
+
+struct SameSizeAsRenderStyle : public RefCounted<SameSizeAsRenderStyle> {
+    void* dataRefs[7];
+    void* ownPtrs[1];
+#if ENABLE(SVG)
+    void* dataRefSvgStyle;
+#endif
+    struct InheritedFlags {
+        unsigned m_bitfields[2];
+    } inherited_flags;
+
+    struct NonInheritedFlags {
+        unsigned m_bitfields[2];
+    } noninherited_flags;
+};
+
+COMPILE_ASSERT(sizeof(RenderStyle) == sizeof(SameSizeAsRenderStyle), RenderStyle_should_stay_small);
+
+inline RenderStyle* defaultStyle()
+{
+    static RenderStyle* s_defaultStyle = RenderStyle::createDefaultStyle().leakRef();
+    return s_defaultStyle;
+}
+
+PassRefPtr<RenderStyle> RenderStyle::create()
+{
+    return adoptRef(new RenderStyle());
+}
+
+PassRefPtr<RenderStyle> RenderStyle::createDefaultStyle()
+{
+    return adoptRef(new RenderStyle(true));
+}
+
+PassRefPtr<RenderStyle> RenderStyle::createAnonymousStyleWithDisplay(const RenderStyle* parentStyle, EDisplay display)
+{
+    RefPtr<RenderStyle> newStyle = RenderStyle::create();
+    newStyle->inheritFrom(parentStyle);
+    newStyle->inheritUnicodeBidiFrom(parentStyle);
+    newStyle->setDisplay(display);
+    return newStyle;
+}
+
+PassRefPtr<RenderStyle> RenderStyle::clone(const RenderStyle* other)
+{
+    return adoptRef(new RenderStyle(*other));
+}
+
+ALWAYS_INLINE RenderStyle::RenderStyle()
+    : m_box(defaultStyle()->m_box)
+    , visual(defaultStyle()->visual)
+    , m_background(defaultStyle()->m_background)
+    , surround(defaultStyle()->surround)
+    , rareNonInheritedData(defaultStyle()->rareNonInheritedData)
+    , rareInheritedData(defaultStyle()->rareInheritedData)
+    , inherited(defaultStyle()->inherited)
+#if ENABLE(SVG)
+    , m_svgStyle(defaultStyle()->m_svgStyle)
+#endif
+{
+    setBitDefaults(); // Would it be faster to copy this from the default style?
+    COMPILE_ASSERT((sizeof(InheritedFlags) <= 8), InheritedFlags_does_not_grow);
+    COMPILE_ASSERT((sizeof(NonInheritedFlags) <= 8), NonInheritedFlags_does_not_grow);
+}
+
+ALWAYS_INLINE RenderStyle::RenderStyle(bool)
+{
+    setBitDefaults();
+
+    m_box.init();
+    visual.init();
+    m_background.init();
+    surround.init();
+    rareNonInheritedData.init();
+    rareNonInheritedData.access()->m_deprecatedFlexibleBox.init();
+    rareNonInheritedData.access()->m_flexibleBox.init();
+    rareNonInheritedData.access()->m_marquee.init();
+    rareNonInheritedData.access()->m_multiCol.init();
+    rareNonInheritedData.access()->m_transform.init();
+    rareNonInheritedData.access()->m_filter.init();
+    rareNonInheritedData.access()->m_grid.init();
+    rareNonInheritedData.access()->m_gridItem.init();
+    rareInheritedData.init();
+    inherited.init();
+#if ENABLE(SVG)
+    m_svgStyle.init();
+#endif
+}
+
+ALWAYS_INLINE RenderStyle::RenderStyle(const RenderStyle& o)
+    : RefCounted<RenderStyle>()
+    , m_box(o.m_box)
+    , visual(o.visual)
+    , m_background(o.m_background)
+    , surround(o.surround)
+    , rareNonInheritedData(o.rareNonInheritedData)
+    , rareInheritedData(o.rareInheritedData)
+    , inherited(o.inherited)
+#if ENABLE(SVG)
+    , m_svgStyle(o.m_svgStyle)
+#endif
+    , inherited_flags(o.inherited_flags)
+    , noninherited_flags(o.noninherited_flags)
+{
+}
+
+void RenderStyle::inheritFrom(const RenderStyle* inheritParent, IsAtShadowBoundary isAtShadowBoundary)
+{
+    if (isAtShadowBoundary == AtShadowBoundary) {
+        // Even if surrounding content is user-editable, shadow DOM should act as a single unit, and not necessarily be editable
+        EUserModify currentUserModify = userModify();
+        rareInheritedData = inheritParent->rareInheritedData;
+        setUserModify(currentUserModify);
+    } else
+        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
+}
+
+void RenderStyle::copyNonInheritedFrom(const RenderStyle* other)
+{
+    m_box = other->m_box;
+    visual = other->visual;
+    m_background = other->m_background;
+    surround = other->surround;
+    rareNonInheritedData = other->rareNonInheritedData;
+    // The flags are copied one-by-one because noninherited_flags contains a bunch of stuff other than real style data.
+    noninherited_flags._effectiveDisplay = other->noninherited_flags._effectiveDisplay;
+    noninherited_flags._originalDisplay = other->noninherited_flags._originalDisplay;
+    noninherited_flags._overflowX = other->noninherited_flags._overflowX;
+    noninherited_flags._overflowY = other->noninherited_flags._overflowY;
+    noninherited_flags._vertical_align = other->noninherited_flags._vertical_align;
+    noninherited_flags._clear = other->noninherited_flags._clear;
+    noninherited_flags._position = other->noninherited_flags._position;
+    noninherited_flags._floating = other->noninherited_flags._floating;
+    noninherited_flags._table_layout = other->noninherited_flags._table_layout;
+    noninherited_flags._unicodeBidi = other->noninherited_flags._unicodeBidi;
+    noninherited_flags._page_break_before = other->noninherited_flags._page_break_before;
+    noninherited_flags._page_break_after = other->noninherited_flags._page_break_after;
+    noninherited_flags._page_break_inside = other->noninherited_flags._page_break_inside;
+    noninherited_flags.explicitInheritance = other->noninherited_flags.explicitInheritance;
+#if ENABLE(SVG)
+    if (m_svgStyle != other->m_svgStyle)
+        m_svgStyle.access()->copyNonInheritedFrom(other->m_svgStyle.get());
+#endif
+    ASSERT(zoom() == initialZoom());
+}
+
+bool RenderStyle::operator==(const RenderStyle& o) const
+{
+    // compare everything except the pseudoStyle pointer
+    return inherited_flags == o.inherited_flags
+        && noninherited_flags == o.noninherited_flags
+        && m_box == o.m_box
+        && visual == o.visual
+        && m_background == o.m_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 != StyleResolver::styleNotYetAvailable();
+}
+
+static inline int pseudoBit(PseudoId pseudo)
+{
+    return 1 << (pseudo - 1);
+}
+
+bool RenderStyle::hasAnyPublicPseudoStyles() const
+{
+    return PUBLIC_PSEUDOID_MASK & noninherited_flags._pseudoBits;
+}
+
+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);
+}
+
+bool RenderStyle::hasUniquePseudoStyle() const
+{
+    if (!m_cachedPseudoStyles || styleType() != NOPSEUDO)
+        return false;
+
+    for (size_t i = 0; i < m_cachedPseudoStyles->size(); ++i) {
+        RenderStyle* pseudoStyle = m_cachedPseudoStyles->at(i).get();
+        if (pseudoStyle->unique())
+            return true;
+    }
+
+    return false;
+}
+
+RenderStyle* RenderStyle::getCachedPseudoStyle(PseudoId pid) const
+{
+    if (!m_cachedPseudoStyles || !m_cachedPseudoStyles->size())
+        return 0;
+
+    if (styleType() != NOPSEUDO) 
+        return 0;
+
+    for (size_t i = 0; i < m_cachedPseudoStyles->size(); ++i) {
+        RenderStyle* pseudoStyle = m_cachedPseudoStyles->at(i).get();
+        if (pseudoStyle->styleType() == pid)
+            return pseudoStyle;
+    }
+
+    return 0;
+}
+
+RenderStyle* RenderStyle::addCachedPseudoStyle(PassRefPtr<RenderStyle> pseudo)
+{
+    if (!pseudo)
+        return 0;
+
+    ASSERT(pseudo->styleType() > NOPSEUDO);
+
+    RenderStyle* result = pseudo.get();
+
+    if (!m_cachedPseudoStyles)
+        m_cachedPseudoStyles = adoptPtr(new PseudoStyleCache);
+
+    m_cachedPseudoStyles->append(pseudo);
+
+    return result;
+}
+
+void RenderStyle::removeCachedPseudoStyle(PseudoId pid)
+{
+    if (!m_cachedPseudoStyles)
+        return;
+    for (size_t i = 0; i < m_cachedPseudoStyles->size(); ++i) {
+        RenderStyle* pseudoStyle = m_cachedPseudoStyles->at(i).get();
+        if (pseudoStyle->styleType() == pid) {
+            m_cachedPseudoStyles->remove(i);
+            return;
+        }
+    }
+}
+
+bool RenderStyle::inheritedNotEqual(const 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 RenderStyle::inheritedDataShared(const RenderStyle* other) const
+{
+    // This is a fast check that only looks if the data structures are shared.
+    return inherited_flags == other->inherited_flags
+        && inherited.get() == other->inherited.get()
+#if ENABLE(SVG)
+        && m_svgStyle.get() == other->m_svgStyle.get()
+#endif
+        && rareInheritedData.get() == other->rareInheritedData.get();
+}
+
+static bool positionedObjectMoved(const LengthBox& a, const LengthBox& b, const Length& width)
+{
+    // 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;
+    // If our width is auto and left or right is specified then this 
+    // is not just a movement - we need to resize to our container.
+    if ((!a.left().isIntrinsicOrAuto() || !a.right().isIntrinsicOrAuto()) && width.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;
+}
+
+StyleDifference RenderStyle::diff(const RenderStyle* other, unsigned& changedContextSensitiveProperties) const
+{
+    changedContextSensitiveProperties = ContextSensitivePropertyNone;
+
+#if ENABLE(SVG)
+    StyleDifference svgChange = StyleDifferenceEqual;
+    if (m_svgStyle != other->m_svgStyle) {
+        svgChange = m_svgStyle->diff(other->m_svgStyle.get());
+        if (svgChange == StyleDifferenceLayout)
+            return svgChange;
+    }
+#endif
+
+    if (m_box->width() != other->m_box->width()
+        || m_box->minWidth() != other->m_box->minWidth()
+        || m_box->maxWidth() != other->m_box->maxWidth()
+        || m_box->height() != other->m_box->height()
+        || m_box->minHeight() != other->m_box->minHeight()
+        || m_box->maxHeight() != other->m_box->maxHeight())
+        return StyleDifferenceLayout;
+
+    if (m_box->verticalAlign() != other->m_box->verticalAlign() || noninherited_flags._vertical_align != other->noninherited_flags._vertical_align)
+        return StyleDifferenceLayout;
+
+    if (m_box->boxSizing() != other->m_box->boxSizing())
+        return StyleDifferenceLayout;
+
+    if (surround->margin != other->surround->margin)
+        return StyleDifferenceLayout;
+
+    if (surround->padding != other->surround->padding)
+        return StyleDifferenceLayout;
+
+    if (rareNonInheritedData.get() != other->rareNonInheritedData.get()) {
+        if (rareNonInheritedData->m_appearance != other->rareNonInheritedData->m_appearance 
+            || rareNonInheritedData->marginBeforeCollapse != other->rareNonInheritedData->marginBeforeCollapse
+            || rareNonInheritedData->marginAfterCollapse != other->rareNonInheritedData->marginAfterCollapse
+            || rareNonInheritedData->lineClamp != other->rareNonInheritedData->lineClamp
+            || rareNonInheritedData->textOverflow != other->rareNonInheritedData->textOverflow)
+            return StyleDifferenceLayout;
+
+        if (rareNonInheritedData->m_regionOverflow != other->rareNonInheritedData->m_regionOverflow)
+            return StyleDifferenceLayout;
+
+        if (rareNonInheritedData->m_wrapFlow != other->rareNonInheritedData->m_wrapFlow
+            || rareNonInheritedData->m_wrapThrough != other->rareNonInheritedData->m_wrapThrough
+            || rareNonInheritedData->m_shapeMargin != other->rareNonInheritedData->m_shapeMargin
+            || rareNonInheritedData->m_shapePadding != other->rareNonInheritedData->m_shapePadding)
+            return StyleDifferenceLayout;
+
+        if (rareNonInheritedData->m_deprecatedFlexibleBox.get() != other->rareNonInheritedData->m_deprecatedFlexibleBox.get()
+            && *rareNonInheritedData->m_deprecatedFlexibleBox.get() != *other->rareNonInheritedData->m_deprecatedFlexibleBox.get())
+            return StyleDifferenceLayout;
+
+        if (rareNonInheritedData->m_flexibleBox.get() != other->rareNonInheritedData->m_flexibleBox.get()
+            && *rareNonInheritedData->m_flexibleBox.get() != *other->rareNonInheritedData->m_flexibleBox.get())
+            return StyleDifferenceLayout;
+        if (rareNonInheritedData->m_order != other->rareNonInheritedData->m_order
+            || rareNonInheritedData->m_alignContent != other->rareNonInheritedData->m_alignContent
+            || rareNonInheritedData->m_alignItems != other->rareNonInheritedData->m_alignItems
+            || rareNonInheritedData->m_alignSelf != other->rareNonInheritedData->m_alignSelf
+            || rareNonInheritedData->m_justifyContent != other->rareNonInheritedData->m_justifyContent)
+            return StyleDifferenceLayout;
+
+        // FIXME: We should add an optimized form of layout that just recomputes visual overflow.
+        if (!rareNonInheritedData->shadowDataEquivalent(*other->rareNonInheritedData.get()))
+            return StyleDifferenceLayout;
+
+        if (!rareNonInheritedData->reflectionDataEquivalent(*other->rareNonInheritedData.get()))
+            return StyleDifferenceLayout;
+
+        if (rareNonInheritedData->m_multiCol.get() != other->rareNonInheritedData->m_multiCol.get()
+            && *rareNonInheritedData->m_multiCol.get() != *other->rareNonInheritedData->m_multiCol.get())
+            return StyleDifferenceLayout;
+
+        if (rareNonInheritedData->m_transform.get() != other->rareNonInheritedData->m_transform.get()
+            && *rareNonInheritedData->m_transform.get() != *other->rareNonInheritedData->m_transform.get()) {
+            // Don't return early here; instead take note of the type of
+            // change, and deal with it when looking at compositing.
+            changedContextSensitiveProperties |= ContextSensitivePropertyTransform;
+        }
+
+        if (rareNonInheritedData->m_grid.get() != other->rareNonInheritedData->m_grid.get()
+            || rareNonInheritedData->m_gridItem.get() != other->rareNonInheritedData->m_gridItem.get())
+            return StyleDifferenceLayout;
+
+        if (rareNonInheritedData->m_shapeInside != other->rareNonInheritedData->m_shapeInside)
+            return StyleDifferenceLayout;
+    }
+
+    if (rareInheritedData.get() != other->rareInheritedData.get()) {
+        if (rareInheritedData->highlight != other->rareInheritedData->highlight
+            || rareInheritedData->indent != other->rareInheritedData->indent
+#if ENABLE(CSS3_TEXT)
+            || rareInheritedData->m_textIndentLine != other->rareInheritedData->m_textIndentLine
+#endif
+            || rareInheritedData->m_effectiveZoom != other->rareInheritedData->m_effectiveZoom
+            || rareInheritedData->wordBreak != other->rareInheritedData->wordBreak
+            || rareInheritedData->overflowWrap != other->rareInheritedData->overflowWrap
+            || rareInheritedData->lineBreak != other->rareInheritedData->lineBreak
+            || rareInheritedData->textSecurity != other->rareInheritedData->textSecurity
+            || rareInheritedData->hyphens != other->rareInheritedData->hyphens
+            || rareInheritedData->hyphenationLimitBefore != other->rareInheritedData->hyphenationLimitBefore
+            || rareInheritedData->hyphenationLimitAfter != other->rareInheritedData->hyphenationLimitAfter
+            || rareInheritedData->hyphenationString != other->rareInheritedData->hyphenationString
+            || rareInheritedData->locale != other->rareInheritedData->locale
+            || rareInheritedData->m_rubyPosition != other->rareInheritedData->m_rubyPosition
+            || rareInheritedData->textEmphasisMark != other->rareInheritedData->textEmphasisMark
+            || rareInheritedData->textEmphasisPosition != other->rareInheritedData->textEmphasisPosition
+            || rareInheritedData->textEmphasisCustomMark != other->rareInheritedData->textEmphasisCustomMark
+            || rareInheritedData->m_textOrientation != other->rareInheritedData->m_textOrientation
+            || rareInheritedData->m_tabSize != other->rareInheritedData->m_tabSize
+            || rareInheritedData->m_lineBoxContain != other->rareInheritedData->m_lineBoxContain
+            || rareInheritedData->m_lineGrid != other->rareInheritedData->m_lineGrid
+            || rareInheritedData->m_lineSnap != other->rareInheritedData->m_lineSnap
+            || rareInheritedData->m_lineAlign != other->rareInheritedData->m_lineAlign
+            || rareInheritedData->listStyleImage != other->rareInheritedData->listStyleImage)
+            return StyleDifferenceLayout;
+
+        if (!rareInheritedData->shadowDataEquivalent(*other->rareInheritedData.get()))
+            return StyleDifferenceLayout;
+
+        if (textStrokeWidth() != other->textStrokeWidth())
+            return StyleDifferenceLayout;
+    }
+
+    if (visual->m_textAutosizingMultiplier != other->visual->m_textAutosizingMultiplier)
+        return StyleDifferenceLayout;
+
+    if (inherited->line_height != other->inherited->line_height
+        || 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.m_rtlOrdering != other->inherited_flags.m_rtlOrdering
+        || noninherited_flags._position != other->noninherited_flags._position
+        || noninherited_flags._floating != other->noninherited_flags._floating
+        || noninherited_flags._originalDisplay != other->noninherited_flags._originalDisplay)
+        return StyleDifferenceLayout;
+
+
+    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 StyleDifferenceLayout;
+
+        // 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 StyleDifferenceLayout;
+    }
+
+    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 StyleDifferenceLayout;
+    }
+
+    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
+        || noninherited_flags._unicodeBidi != other->noninherited_flags._unicodeBidi)
+        return StyleDifferenceLayout;
+
+    // Check block flow direction.
+    if (inherited_flags.m_writingMode != other->inherited_flags.m_writingMode)
+        return StyleDifferenceLayout;
+
+    // Check text combine mode.
+    if (rareNonInheritedData->m_textCombine != other->rareNonInheritedData->m_textCombine)
+        return StyleDifferenceLayout;
+
+    // Overflow returns a layout hint.
+    if (noninherited_flags._overflowX != other->noninherited_flags._overflowX
+        || noninherited_flags._overflowY != other->noninherited_flags._overflowY)
+        return StyleDifferenceLayout;
+
+    // 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 StyleDifferenceLayout;
+
+    // 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 StyleDifferenceLayout;
+
+    if ((visibility() == COLLAPSE) != (other->visibility() == COLLAPSE))
+        return StyleDifferenceLayout;
+
+    if ((rareNonInheritedData->opacity == 1 && other->rareNonInheritedData->opacity < 1)
+        || (rareNonInheritedData->opacity < 1 && other->rareNonInheritedData->opacity == 1)) {
+        // FIXME: We would like to use SimplifiedLayout here, but we can't quite do that yet.
+        // We need to make sure SimplifiedLayout can operate correctly on RenderInlines (we will need
+        // to add a selfNeedsSimplifiedLayout bit in order to not get confused and taint every line).
+        // In addition we need to solve the floating object issue when layers come and go. Right now
+        // a full layout is necessary to keep floating object lists sane.
+        return StyleDifferenceLayout;
+    }
+
+    if (!QuotesData::equals(rareInheritedData->quotes.get(), other->rareInheritedData->quotes.get()))
+        return StyleDifferenceLayout;
+
+#if ENABLE(SVG)
+    // SVGRenderStyle::diff() might have returned StyleDifferenceRepaint, eg. if fill changes.
+    // If eg. the font-size changed at the same time, we're not allowed to return StyleDifferenceRepaint,
+    // but have to return StyleDifferenceLayout, that's why  this if branch comes after all branches
+    // that are relevant for SVG and might return StyleDifferenceLayout.
+    if (svgChange != StyleDifferenceEqual)
+        return svgChange;
+#endif
+
+    // 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, m_box->width()))
+
+                return StyleDifferenceLayoutPositionedMovementOnly;
+
+            // FIXME: We would like to use SimplifiedLayout for relative positioning, but we can't quite do that yet.
+            // We need to make sure SimplifiedLayout can operate correctly on RenderInlines (we will need
+            // to add a selfNeedsSimplifiedLayout bit in order to not get confused and taint every line).
+            return StyleDifferenceLayout;
+        } else if (m_box->zIndex() != other->m_box->zIndex() || m_box->hasAutoZIndex() != other->m_box->hasAutoZIndex()
+                 || visual->clip != other->visual->clip || visual->hasClip != other->visual->hasClip)
+            return StyleDifferenceRepaintLayer;
+    }
+    
+#if ENABLE(CSS_COMPOSITING)
+    if (rareNonInheritedData->m_effectiveBlendMode != other->rareNonInheritedData->m_effectiveBlendMode)
+        return StyleDifferenceRepaintLayer;
+#endif
+
+    if (rareNonInheritedData->opacity != other->rareNonInheritedData->opacity) {
+        // Don't return early here; instead take note of the type of change,
+        // and deal with it when looking at compositing.
+        changedContextSensitiveProperties |= ContextSensitivePropertyOpacity;
+    }
+
+    if (rareNonInheritedData->m_filter.get() != other->rareNonInheritedData->m_filter.get()
+        && *rareNonInheritedData->m_filter.get() != *other->rareNonInheritedData->m_filter.get()) {
+        // Don't return early here; instead take note of the type of change,
+        // and deal with it when looking at compositing.
+        changedContextSensitiveProperties |= ContextSensitivePropertyFilter;
+    }
+
+    if (rareNonInheritedData->m_mask != other->rareNonInheritedData->m_mask
+        || rareNonInheritedData->m_maskBoxImage != other->rareNonInheritedData->m_maskBoxImage)
+        return StyleDifferenceRepaintLayer;
+
+    if (inherited->color != other->inherited->color
+        || inherited_flags._visibility != other->inherited_flags._visibility
+        || inherited_flags._text_decorations != other->inherited_flags._text_decorations
+        || inherited_flags.m_printColorAdjust != other->inherited_flags.m_printColorAdjust
+        || inherited_flags._insideLink != other->inherited_flags._insideLink
+        || surround->border != other->surround->border
+        || *m_background.get() != *other->m_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
+#if ENABLE(CSS3_TEXT)
+        || rareNonInheritedData->m_textDecorationStyle != other->rareNonInheritedData->m_textDecorationStyle
+        || rareNonInheritedData->m_textDecorationColor != other->rareNonInheritedData->m_textDecorationColor
+#endif // CSS3_TEXT
+        || rareInheritedData->textFillColor != other->rareInheritedData->textFillColor
+        || rareInheritedData->textStrokeColor != other->rareInheritedData->textStrokeColor
+        || rareInheritedData->textEmphasisColor != other->rareInheritedData->textEmphasisColor
+        || rareInheritedData->textEmphasisFill != other->rareInheritedData->textEmphasisFill
+        || rareInheritedData->m_imageRendering != other->rareInheritedData->m_imageRendering)
+        return StyleDifferenceRepaint;
+        
+        // FIXME: The current spec is being reworked to remove dependencies between exclusions and affected 
+        // content. There's a proposal to use floats instead. In that case, wrap-shape should actually relayout 
+        // the parent container. For sure, I will have to revisit this code, but for now I've added this in order 
+        // to avoid having diff() == StyleDifferenceEqual where wrap-shapes actually differ.
+        // Tracking bug: https://bugs.webkit.org/show_bug.cgi?id=62991
+        if (rareNonInheritedData->m_shapeOutside != other->rareNonInheritedData->m_shapeOutside)
+            return StyleDifferenceRepaint;
+
+        if (rareNonInheritedData->m_clipPath != other->rareNonInheritedData->m_clipPath)
+            return StyleDifferenceRepaint;
+
+    if (rareNonInheritedData.get() != other->rareNonInheritedData.get()) {
+        if (rareNonInheritedData->m_transformStyle3D != other->rareNonInheritedData->m_transformStyle3D
+            || rareNonInheritedData->m_backfaceVisibility != other->rareNonInheritedData->m_backfaceVisibility
+            || rareNonInheritedData->m_perspective != other->rareNonInheritedData->m_perspective
+            || rareNonInheritedData->m_perspectiveOriginX != other->rareNonInheritedData->m_perspectiveOriginX
+            || rareNonInheritedData->m_perspectiveOriginY != other->rareNonInheritedData->m_perspectiveOriginY)
+            return StyleDifferenceRecompositeLayer;
+    }
+
+    // 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 StyleDifferenceEqual;
+}
+
+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(PassRefPtr<StyleImage> image, const IntPoint& hotSpot)
+{
+    if (!rareInheritedData.access()->cursorData)
+        rareInheritedData.access()->cursorData = CursorList::create();
+    rareInheritedData.access()->cursorData->append(CursorData(image, hotSpot));
+}
+
+void RenderStyle::setCursorList(PassRefPtr<CursorList> other)
+{
+    rareInheritedData.access()->cursorData = other;
+}
+
+void RenderStyle::setQuotes(PassRefPtr<QuotesData> q)
+{
+    if (QuotesData::equals(rareInheritedData->quotes.get(), q.get()))
+        return;
+    rareInheritedData.access()->quotes = q;
+}
+
+void RenderStyle::clearCursorList()
+{
+    if (rareInheritedData->cursorData)
+        rareInheritedData.access()->cursorData = 0;
+}
+
+void RenderStyle::clearContent()
+{
+    if (rareNonInheritedData->m_content)
+        rareNonInheritedData.access()->m_content = nullptr;
+}
+
+void RenderStyle::appendContent(PassOwnPtr<ContentData> contentData)
+{
+    OwnPtr<ContentData>& content = rareNonInheritedData.access()->m_content;
+    ContentData* lastContent = content.get();
+    while (lastContent && lastContent->next())
+        lastContent = lastContent->next();
+
+    if (lastContent)
+        lastContent->setNext(contentData);
+    else
+        content = contentData;
+}
+
+void RenderStyle::setContent(PassRefPtr<StyleImage> image, bool add)
+{
+    if (!image)
+        return;
+        
+    if (add) {
+        appendContent(ContentData::create(image));
+        return;
+    }
+
+    rareNonInheritedData.access()->m_content = ContentData::create(image);
+}
+
+void RenderStyle::setContent(const String& string, bool add)
+{
+    OwnPtr<ContentData>& content = rareNonInheritedData.access()->m_content;
+    if (add) {
+        ContentData* lastContent = content.get();
+        while (lastContent && lastContent->next())
+            lastContent = lastContent->next();
+
+        if (lastContent) {
+            // We attempt to merge with the last ContentData if possible.
+            if (lastContent->isText()) {
+                TextContentData* textContent = static_cast<TextContentData*>(lastContent);
+                textContent->setText(textContent->text() + string);
+            } else
+                lastContent->setNext(ContentData::create(string));
+
+            return;
+        }
+    }
+
+    content = ContentData::create(string);
+}
+
+void RenderStyle::setContent(PassOwnPtr<CounterContent> counter, bool add)
+{
+    if (!counter)
+        return;
+
+    if (add) {
+        appendContent(ContentData::create(counter));
+        return;
+    }
+
+    rareNonInheritedData.access()->m_content = ContentData::create(counter);
+}
+
+void RenderStyle::setContent(QuoteType quote, bool add)
+{
+    if (add) {
+        appendContent(ContentData::create(quote));
+        return;
+    }
+
+    rareNonInheritedData.access()->m_content = ContentData::create(quote);
+}
+    
+inline bool requireTransformOrigin(const Vector<RefPtr<TransformOperation> >& transformOperations, RenderStyle::ApplyTransformOrigin applyOrigin)
+{
+    // 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.
+    if (applyOrigin != RenderStyle::IncludeTransformOrigin)
+        return false;
+
+    unsigned size = transformOperations.size();
+    for (unsigned i = 0; i < size; ++i) {
+        TransformOperation::OperationType type = transformOperations[i]->getOperationType();
+        if (type != TransformOperation::TRANSLATE_X
+            && type != TransformOperation::TRANSLATE_Y
+            && type != TransformOperation::TRANSLATE 
+            && type != TransformOperation::TRANSLATE_Z
+            && type != TransformOperation::TRANSLATE_3D)
+            return true;
+    }
+    
+    return false;
+}
+
+void RenderStyle::applyTransform(TransformationMatrix& transform, const LayoutSize& borderBoxSize, ApplyTransformOrigin applyOrigin) const
+{
+    applyTransform(transform, FloatRect(FloatPoint(), borderBoxSize), applyOrigin);
+}
+
+void RenderStyle::applyTransform(TransformationMatrix& transform, const FloatRect& boundingBox, ApplyTransformOrigin applyOrigin) const
+{
+    const Vector<RefPtr<TransformOperation> >& transformOperations = rareNonInheritedData->m_transform->m_operations.operations();
+    bool applyTransformOrigin = requireTransformOrigin(transformOperations, applyOrigin);
+    
+    float offsetX = transformOriginX().type() == Percent ? boundingBox.x() : 0;
+    float offsetY = transformOriginY().type() == Percent ? boundingBox.y() : 0;
+    
+    if (applyTransformOrigin) {
+        transform.translate3d(floatValueForLength(transformOriginX(), boundingBox.width()) + offsetX,
+                              floatValueForLength(transformOriginY(), boundingBox.height()) + offsetY,
+                              transformOriginZ());
+    }
+    
+    unsigned size = transformOperations.size();
+    for (unsigned i = 0; i < size; ++i)
+        transformOperations[i]->apply(transform, boundingBox.size());
+    
+    if (applyTransformOrigin) {
+        transform.translate3d(-floatValueForLength(transformOriginX(), boundingBox.width()) - offsetX,
+                              -floatValueForLength(transformOriginY(), boundingBox.height()) - offsetY,
+                              -transformOriginZ());
+    }
+}
+
+void RenderStyle::setTextShadow(PassOwnPtr<ShadowData> shadowData, bool add)
+{
+    ASSERT(!shadowData || (!shadowData->spread() && shadowData->style() == Normal));
+
+    StyleRareInheritedData* rareData = rareInheritedData.access();
+    if (!add) {
+        rareData->textShadow = shadowData;
+        return;
+    }
+
+    shadowData->setNext(rareData->textShadow.release());
+    rareData->textShadow = shadowData;
+}
+
+void RenderStyle::setBoxShadow(PassOwnPtr<ShadowData> shadowData, bool add)
+{
+    StyleRareNonInheritedData* rareData = rareNonInheritedData.access();
+    if (!add) {
+        rareData->m_boxShadow = shadowData;
+        return;
+    }
+
+    shadowData->setNext(rareData->m_boxShadow.release());
+    rareData->m_boxShadow = shadowData;
+}
+
+static RoundedRect::Radii calcRadiiFor(const BorderData& border, IntSize size, RenderView* renderView)
+{
+    return RoundedRect::Radii(
+        IntSize(valueForLength(border.topLeft().width(), size.width(), renderView), 
+                valueForLength(border.topLeft().height(), size.height(), renderView)),
+        IntSize(valueForLength(border.topRight().width(), size.width(), renderView),
+                valueForLength(border.topRight().height(), size.height(), renderView)),
+        IntSize(valueForLength(border.bottomLeft().width(), size.width(), renderView), 
+                valueForLength(border.bottomLeft().height(), size.height(), renderView)),
+        IntSize(valueForLength(border.bottomRight().width(), size.width(), renderView), 
+                valueForLength(border.bottomRight().height(), size.height(), renderView)));
+}
+
+static float calcConstraintScaleFor(const IntRect& rect, const RoundedRect::Radii& radii)
+{
+    // Constrain corner radii using CSS3 rules:
+    // http://www.w3.org/TR/css3-background/#the-border-radius
+    
+    float factor = 1;
+    unsigned radiiSum;
+
+    // top
+    radiiSum = static_cast<unsigned>(radii.topLeft().width()) + static_cast<unsigned>(radii.topRight().width()); // Casts to avoid integer overflow.
+    if (radiiSum > static_cast<unsigned>(rect.width()))
+        factor = min(static_cast<float>(rect.width()) / radiiSum, factor);
+
+    // bottom
+    radiiSum = static_cast<unsigned>(radii.bottomLeft().width()) + static_cast<unsigned>(radii.bottomRight().width());
+    if (radiiSum > static_cast<unsigned>(rect.width()))
+        factor = min(static_cast<float>(rect.width()) / radiiSum, factor);
+    
+    // left
+    radiiSum = static_cast<unsigned>(radii.topLeft().height()) + static_cast<unsigned>(radii.bottomLeft().height());
+    if (radiiSum > static_cast<unsigned>(rect.height()))
+        factor = min(static_cast<float>(rect.height()) / radiiSum, factor);
+    
+    // right
+    radiiSum = static_cast<unsigned>(radii.topRight().height()) + static_cast<unsigned>(radii.bottomRight().height());
+    if (radiiSum > static_cast<unsigned>(rect.height()))
+        factor = min(static_cast<float>(rect.height()) / radiiSum, factor);
+    
+    ASSERT(factor <= 1);
+    return factor;
+}
+
+StyleImage* RenderStyle::listStyleImage() const { return rareInheritedData->listStyleImage.get(); }
+void RenderStyle::setListStyleImage(PassRefPtr<StyleImage> v)
+{
+    if (rareInheritedData->listStyleImage != v)
+        rareInheritedData.access()->listStyleImage = v;
+}
+
+Color RenderStyle::color() const { return inherited->color; }
+Color RenderStyle::visitedLinkColor() const { return inherited->visitedLinkColor; }
+void RenderStyle::setColor(const Color& v) { SET_VAR(inherited, color, v); }
+void RenderStyle::setVisitedLinkColor(const Color& v) { SET_VAR(inherited, visitedLinkColor, v); }
+
+short RenderStyle::horizontalBorderSpacing() const { return inherited->horizontal_border_spacing; }
+short RenderStyle::verticalBorderSpacing() const { return inherited->vertical_border_spacing; }
+void RenderStyle::setHorizontalBorderSpacing(short v) { SET_VAR(inherited, horizontal_border_spacing, v); }
+void RenderStyle::setVerticalBorderSpacing(short v) { SET_VAR(inherited, vertical_border_spacing, v); }
+
+RoundedRect RenderStyle::getRoundedBorderFor(const LayoutRect& borderRect, RenderView* renderView, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
+{
+    IntRect snappedBorderRect(pixelSnappedIntRect(borderRect));
+    RoundedRect roundedRect(snappedBorderRect);
+    if (hasBorderRadius()) {
+        RoundedRect::Radii radii = calcRadiiFor(surround->border, snappedBorderRect.size(), renderView);
+        radii.scale(calcConstraintScaleFor(snappedBorderRect, radii));
+        roundedRect.includeLogicalEdges(radii, isHorizontalWritingMode(), includeLogicalLeftEdge, includeLogicalRightEdge);
+    }
+    return roundedRect;
+}
+
+RoundedRect RenderStyle::getRoundedInnerBorderFor(const LayoutRect& borderRect, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
+{
+    bool horizontal = isHorizontalWritingMode();
+
+    int leftWidth = (!horizontal || includeLogicalLeftEdge) ? borderLeftWidth() : 0;
+    int rightWidth = (!horizontal || includeLogicalRightEdge) ? borderRightWidth() : 0;
+    int topWidth = (horizontal || includeLogicalLeftEdge) ? borderTopWidth() : 0;
+    int bottomWidth = (horizontal || includeLogicalRightEdge) ? borderBottomWidth() : 0;
+
+    return getRoundedInnerBorderFor(borderRect, topWidth, bottomWidth, leftWidth, rightWidth, includeLogicalLeftEdge, includeLogicalRightEdge);
+}
+
+RoundedRect RenderStyle::getRoundedInnerBorderFor(const LayoutRect& borderRect,
+    int topWidth, int bottomWidth, int leftWidth, int rightWidth, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const
+{
+    LayoutRect innerRect(borderRect.x() + leftWidth, 
+               borderRect.y() + topWidth, 
+               borderRect.width() - leftWidth - rightWidth, 
+               borderRect.height() - topWidth - bottomWidth);
+
+    RoundedRect roundedRect(pixelSnappedIntRect(innerRect));
+
+    if (hasBorderRadius()) {
+        RoundedRect::Radii radii = getRoundedBorderFor(borderRect).radii();
+        radii.shrink(topWidth, bottomWidth, leftWidth, rightWidth);
+        roundedRect.includeLogicalEdges(radii, isHorizontalWritingMode(), includeLogicalLeftEdge, includeLogicalRightEdge);
+    }
+    return roundedRect;
+}
+
+static bool allLayersAreFixed(const FillLayer* layer)
+{
+    bool allFixed = true;
+    
+    for (const FillLayer* currLayer = layer; currLayer; currLayer = currLayer->next())
+        allFixed &= (currLayer->image() && currLayer->attachment() == FixedBackgroundAttachment);
+
+    return layer && allFixed;
+}
+
+bool RenderStyle::hasEntirelyFixedBackground() const
+{
+    return allLayersAreFixed(backgroundLayers());
+}
+
+const CounterDirectiveMap* RenderStyle::counterDirectives() const
+{
+    return rareNonInheritedData->m_counterDirectives.get();
+}
+
+CounterDirectiveMap& RenderStyle::accessCounterDirectives()
+{
+    OwnPtr<CounterDirectiveMap>& map = rareNonInheritedData.access()->m_counterDirectives;
+    if (!map)
+        map = adoptPtr(new CounterDirectiveMap);
+    return *map;
+}
+
+const CounterDirectives RenderStyle::getCounterDirectives(const AtomicString& identifier) const
+{
+    if (const CounterDirectiveMap* directives = counterDirectives())
+        return directives->get(identifier);
+    return CounterDirectives();
+}
+
+const AtomicString& RenderStyle::hyphenString() const
+{
+    ASSERT(hyphens() != HyphensNone);
+
+    const AtomicString& hyphenationString = rareInheritedData.get()->hyphenationString;
+    if (!hyphenationString.isNull())
+        return hyphenationString;
+
+    // FIXME: This should depend on locale.
+    DEFINE_STATIC_LOCAL(AtomicString, hyphenMinusString, (&hyphenMinus, 1));
+    DEFINE_STATIC_LOCAL(AtomicString, hyphenString, (&hyphen, 1));
+    return font().primaryFontHasGlyphForCharacter(hyphen) ? hyphenString : hyphenMinusString;
+}
+
+const AtomicString& RenderStyle::textEmphasisMarkString() const
+{
+    switch (textEmphasisMark()) {
+    case TextEmphasisMarkNone:
+        return nullAtom;
+    case TextEmphasisMarkCustom:
+        return textEmphasisCustomMark();
+    case TextEmphasisMarkDot: {
+        DEFINE_STATIC_LOCAL(AtomicString, filledDotString, (&bullet, 1));
+        DEFINE_STATIC_LOCAL(AtomicString, openDotString, (&whiteBullet, 1));
+        return textEmphasisFill() == TextEmphasisFillFilled ? filledDotString : openDotString;
+    }
+    case TextEmphasisMarkCircle: {
+        DEFINE_STATIC_LOCAL(AtomicString, filledCircleString, (&blackCircle, 1));
+        DEFINE_STATIC_LOCAL(AtomicString, openCircleString, (&whiteCircle, 1));
+        return textEmphasisFill() == TextEmphasisFillFilled ? filledCircleString : openCircleString;
+    }
+    case TextEmphasisMarkDoubleCircle: {
+        DEFINE_STATIC_LOCAL(AtomicString, filledDoubleCircleString, (&fisheye, 1));
+        DEFINE_STATIC_LOCAL(AtomicString, openDoubleCircleString, (&bullseye, 1));
+        return textEmphasisFill() == TextEmphasisFillFilled ? filledDoubleCircleString : openDoubleCircleString;
+    }
+    case TextEmphasisMarkTriangle: {
+        DEFINE_STATIC_LOCAL(AtomicString, filledTriangleString, (&blackUpPointingTriangle, 1));
+        DEFINE_STATIC_LOCAL(AtomicString, openTriangleString, (&whiteUpPointingTriangle, 1));
+        return textEmphasisFill() == TextEmphasisFillFilled ? filledTriangleString : openTriangleString;
+    }
+    case TextEmphasisMarkSesame: {
+        DEFINE_STATIC_LOCAL(AtomicString, filledSesameString, (&sesameDot, 1));
+        DEFINE_STATIC_LOCAL(AtomicString, openSesameString, (&whiteSesameDot, 1));
+        return textEmphasisFill() == TextEmphasisFillFilled ? filledSesameString : openSesameString;
+    }
+    case TextEmphasisMarkAuto:
+        ASSERT_NOT_REACHED();
+        return nullAtom;
+    }
+
+    ASSERT_NOT_REACHED();
+    return nullAtom;
+}
+
+void RenderStyle::adjustAnimations()
+{
+    CSSAnimationDataList* animationList = rareNonInheritedData->m_animations.get();
+    if (!animationList)
+        return;
+
+    // Get rid of empty animations 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()
+{
+    CSSAnimationDataList* 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;
+            }
+        }
+    }
+}
+
+CSSAnimationDataList* RenderStyle::accessAnimations()
+{
+    if (!rareNonInheritedData.access()->m_animations)
+        rareNonInheritedData.access()->m_animations = adoptPtr(new CSSAnimationDataList());
+    return rareNonInheritedData->m_animations.get();
+}
+
+CSSAnimationDataList* RenderStyle::accessTransitions()
+{
+    if (!rareNonInheritedData.access()->m_transitions)
+        rareNonInheritedData.access()->m_transitions = adoptPtr(new CSSAnimationDataList());
+    return rareNonInheritedData->m_transitions.get();
+}
+
+const CSSAnimationData* RenderStyle::transitionForProperty(CSSPropertyID property) const
+{
+    if (transitions()) {
+        for (size_t i = 0; i < transitions()->size(); ++i) {
+            const CSSAnimationData* p = transitions()->animation(i);
+            if (p->animationMode() == CSSAnimationData::AnimateAll || p->property() == property) {
+                return p;
+            }
+        }
+    }
+    return 0;
+}
+
+const Font& RenderStyle::font() const { return inherited->font; }
+const FontMetrics& RenderStyle::fontMetrics() const { return inherited->font.fontMetrics(); }
+const FontDescription& RenderStyle::fontDescription() const { return inherited->font.fontDescription(); }
+float RenderStyle::specifiedFontSize() const { return fontDescription().specifiedSize(); }
+float RenderStyle::computedFontSize() const { return fontDescription().computedSize(); }
+int RenderStyle::fontSize() const { return inherited->font.pixelSize(); }
+
+int RenderStyle::wordSpacing() const { return inherited->font.wordSpacing(); }
+int RenderStyle::letterSpacing() const { return inherited->font.letterSpacing(); }
+
+bool RenderStyle::setFontDescription(const FontDescription& v)
+{
+    if (inherited->font.fontDescription() != v) {
+        inherited.access()->font = Font(v, inherited->font.letterSpacing(), inherited->font.wordSpacing());
+        return true;
+    }
+    return false;
+}
+
+Length RenderStyle::specifiedLineHeight() const { return inherited->line_height; }
+Length RenderStyle::lineHeight() const
+{
+    const Length& lh = inherited->line_height;
+    // Unlike fontDescription().computedSize() and hence fontSize(), this is
+    // recalculated on demand as we only store the specified line height.
+    // FIXME: Should consider scaling the fixed part of any calc expressions
+    // too, though this involves messily poking into CalcExpressionLength.
+    float multiplier = textAutosizingMultiplier();
+    if (multiplier > 1 && lh.isFixed())
+        return Length(TextAutosizer::computeAutosizedFontSize(lh.value(), multiplier), Fixed);
+
+    return lh;
+}
+void RenderStyle::setLineHeight(Length specifiedLineHeight) { SET_VAR(inherited, line_height, specifiedLineHeight); }
+
+int RenderStyle::computedLineHeight(RenderView* renderView) const
+{
+    const Length& lh = lineHeight();
+
+    // Negative value means the line height is not set. Use the font's built-in spacing.
+    if (lh.isNegative())
+        return fontMetrics().lineSpacing();
+
+    if (lh.isPercent())
+        return minimumValueForLength(lh, fontSize());
+
+    if (lh.isViewportPercentage())
+        return valueForLength(lh, 0, renderView);
+
+    return lh.value();
+}
+
+void RenderStyle::setWordSpacing(int v) { inherited.access()->font.setWordSpacing(v); }
+void RenderStyle::setLetterSpacing(int v) { inherited.access()->font.setLetterSpacing(v); }
+
+void RenderStyle::setFontSize(float size)
+{
+    // size must be specifiedSize if Text Autosizing is enabled, but computedSize if text
+    // zoom is enabled (if neither is enabled it's irrelevant as they're probably the same).
+
+    ASSERT(std::isfinite(size));
+    if (!std::isfinite(size) || size < 0)
+        size = 0;
+    else
+        size = min(maximumAllowedFontSize, size);
+
+    FontSelector* currentFontSelector = font().fontSelector();
+    FontDescription desc(fontDescription());
+    desc.setSpecifiedSize(size);
+    desc.setComputedSize(size);
+
+    float multiplier = textAutosizingMultiplier();
+    if (multiplier > 1) {
+        float autosizedFontSize = TextAutosizer::computeAutosizedFontSize(size, multiplier);
+        desc.setComputedSize(min(maximumAllowedFontSize, autosizedFontSize));
+    }
+
+    setFontDescription(desc);
+    font().update(currentFontSelector);
+}
+
+void RenderStyle::getShadowExtent(const ShadowData* shadow, LayoutUnit &top, LayoutUnit &right, LayoutUnit &bottom, LayoutUnit &left) const
+{
+    top = 0;
+    right = 0;
+    bottom = 0;
+    left = 0;
+
+    for ( ; shadow; shadow = shadow->next()) {
+        if (shadow->style() == Inset)
+            continue;
+        int blurAndSpread = shadow->blur() + shadow->spread();
+
+        top = min<LayoutUnit>(top, shadow->y() - blurAndSpread);
+        right = max<LayoutUnit>(right, shadow->x() + blurAndSpread);
+        bottom = max<LayoutUnit>(bottom, shadow->y() + blurAndSpread);
+        left = min<LayoutUnit>(left, shadow->x() - blurAndSpread);
+    }
+}
+
+LayoutBoxExtent RenderStyle::getShadowInsetExtent(const ShadowData* shadow) const
+{
+    LayoutUnit top = 0;
+    LayoutUnit right = 0;
+    LayoutUnit bottom = 0;
+    LayoutUnit left = 0;
+
+    for ( ; shadow; shadow = shadow->next()) {
+        if (shadow->style() == Normal)
+            continue;
+        int blurAndSpread = shadow->blur() + shadow->spread();
+        top = max<LayoutUnit>(top, shadow->y() + blurAndSpread);
+        right = min<LayoutUnit>(right, shadow->x() - blurAndSpread);
+        bottom = min<LayoutUnit>(bottom, shadow->y() - blurAndSpread);
+        left = max<LayoutUnit>(left, shadow->x() + blurAndSpread);
+    }
+
+    return LayoutBoxExtent(top, right, bottom, left);
+}
+
+void RenderStyle::getShadowHorizontalExtent(const ShadowData* shadow, LayoutUnit &left, LayoutUnit &right) const
+{
+    left = 0;
+    right = 0;
+
+    for ( ; shadow; shadow = shadow->next()) {
+        if (shadow->style() == Inset)
+            continue;
+        int blurAndSpread = shadow->blur() + shadow->spread();
+
+        left = min<LayoutUnit>(left, shadow->x() - blurAndSpread);
+        right = max<LayoutUnit>(right, shadow->x() + blurAndSpread);
+    }
+}
+
+void RenderStyle::getShadowVerticalExtent(const ShadowData* shadow, LayoutUnit &top, LayoutUnit &bottom) const
+{
+    top = 0;
+    bottom = 0;
+
+    for ( ; shadow; shadow = shadow->next()) {
+        if (shadow->style() == Inset)
+            continue;
+        int blurAndSpread = shadow->blur() + shadow->spread();
+
+        top = min<LayoutUnit>(top, shadow->y() - blurAndSpread);
+        bottom = max<LayoutUnit>(bottom, shadow->y() + blurAndSpread);
+    }
+}
+
+Color RenderStyle::colorIncludingFallback(int colorProperty, bool visitedLink) const
+{
+    Color result;
+    EBorderStyle borderStyle = BNONE;
+    switch (colorProperty) {
+    case CSSPropertyBackgroundColor:
+        return visitedLink ? visitedLinkBackgroundColor() : backgroundColor(); // Background color doesn't fall back.
+    case CSSPropertyBorderLeftColor:
+        result = visitedLink ? visitedLinkBorderLeftColor() : borderLeftColor();
+        borderStyle = borderLeftStyle();
+        break;
+    case CSSPropertyBorderRightColor:
+        result = visitedLink ? visitedLinkBorderRightColor() : borderRightColor();
+        borderStyle = borderRightStyle();
+        break;
+    case CSSPropertyBorderTopColor:
+        result = visitedLink ? visitedLinkBorderTopColor() : borderTopColor();
+        borderStyle = borderTopStyle();
+        break;
+    case CSSPropertyBorderBottomColor:
+        result = visitedLink ? visitedLinkBorderBottomColor() : borderBottomColor();
+        borderStyle = borderBottomStyle();
+        break;
+    case CSSPropertyColor:
+        result = visitedLink ? visitedLinkColor() : color();
+        break;
+    case CSSPropertyOutlineColor:
+        result = visitedLink ? visitedLinkOutlineColor() : outlineColor();
+        break;
+    case CSSPropertyWebkitColumnRuleColor:
+        result = visitedLink ? visitedLinkColumnRuleColor() : columnRuleColor();
+        break;
+#if ENABLE(CSS3_TEXT)
+    case CSSPropertyWebkitTextDecorationColor:
+        // Text decoration color fallback is handled in RenderObject::decorationColor.
+        return visitedLink ? visitedLinkTextDecorationColor() : textDecorationColor();
+#endif // CSS3_TEXT
+    case CSSPropertyWebkitTextEmphasisColor:
+        result = visitedLink ? visitedLinkTextEmphasisColor() : textEmphasisColor();
+        break;
+    case CSSPropertyWebkitTextFillColor:
+        result = visitedLink ? visitedLinkTextFillColor() : textFillColor();
+        break;
+    case CSSPropertyWebkitTextStrokeColor:
+        result = visitedLink ? visitedLinkTextStrokeColor() : textStrokeColor();
+        break;
+    default:
+        ASSERT_NOT_REACHED();
+        break;
+    }
+
+    if (!result.isValid()) {
+        if (!visitedLink && (borderStyle == INSET || borderStyle == OUTSET || borderStyle == RIDGE || borderStyle == GROOVE))
+            result.setRGB(238, 238, 238);
+        else
+            result = visitedLink ? visitedLinkColor() : color();
+    }
+    return result;
+}
+
+Color RenderStyle::visitedDependentColor(int colorProperty) const
+{
+    Color unvisitedColor = colorIncludingFallback(colorProperty, false);
+    if (insideLink() != InsideVisitedLink)
+        return unvisitedColor;
+
+    Color visitedColor = colorIncludingFallback(colorProperty, true);
+
+#if ENABLE(CSS3_TEXT)
+    // Text decoration color validity is preserved (checked in RenderObject::decorationColor).
+    if (colorProperty == CSSPropertyWebkitTextDecorationColor)
+        return visitedColor;
+#endif // CSS3_TEXT
+
+    // FIXME: Technically someone could explicitly specify the color transparent, but for now we'll just
+    // assume that if the background color is transparent that it wasn't set. Note that it's weird that
+    // we're returning unvisited info for a visited link, but given our restriction that the alpha values
+    // have to match, it makes more sense to return the unvisited background color if specified than it
+    // does to return black. This behavior matches what Firefox 4 does as well.
+    if (colorProperty == CSSPropertyBackgroundColor && visitedColor == Color::transparent)
+        return unvisitedColor;
+
+    // Take the alpha from the unvisited color, but get the RGB values from the visited color.
+    return Color(visitedColor.red(), visitedColor.green(), visitedColor.blue(), unvisitedColor.alpha());
+}
+
+const BorderValue& RenderStyle::borderBefore() const
+{
+    switch (writingMode()) {
+    case TopToBottomWritingMode:
+        return borderTop();
+    case BottomToTopWritingMode:
+        return borderBottom();
+    case LeftToRightWritingMode:
+        return borderLeft();
+    case RightToLeftWritingMode:
+        return borderRight();
+    }
+    ASSERT_NOT_REACHED();
+    return borderTop();
+}
+
+const BorderValue& RenderStyle::borderAfter() const
+{
+    switch (writingMode()) {
+    case TopToBottomWritingMode:
+        return borderBottom();
+    case BottomToTopWritingMode:
+        return borderTop();
+    case LeftToRightWritingMode:
+        return borderRight();
+    case RightToLeftWritingMode:
+        return borderLeft();
+    }
+    ASSERT_NOT_REACHED();
+    return borderBottom();
+}
+
+const BorderValue& RenderStyle::borderStart() const
+{
+    if (isHorizontalWritingMode())
+        return isLeftToRightDirection() ? borderLeft() : borderRight();
+    return isLeftToRightDirection() ? borderTop() : borderBottom();
+}
+
+const BorderValue& RenderStyle::borderEnd() const
+{
+    if (isHorizontalWritingMode())
+        return isLeftToRightDirection() ? borderRight() : borderLeft();
+    return isLeftToRightDirection() ? borderBottom() : borderTop();
+}
+
+unsigned short RenderStyle::borderBeforeWidth() const
+{
+    switch (writingMode()) {
+    case TopToBottomWritingMode:
+        return borderTopWidth();
+    case BottomToTopWritingMode:
+        return borderBottomWidth();
+    case LeftToRightWritingMode:
+        return borderLeftWidth();
+    case RightToLeftWritingMode:
+        return borderRightWidth();
+    }
+    ASSERT_NOT_REACHED();
+    return borderTopWidth();
+}
+
+unsigned short RenderStyle::borderAfterWidth() const
+{
+    switch (writingMode()) {
+    case TopToBottomWritingMode:
+        return borderBottomWidth();
+    case BottomToTopWritingMode:
+        return borderTopWidth();
+    case LeftToRightWritingMode:
+        return borderRightWidth();
+    case RightToLeftWritingMode:
+        return borderLeftWidth();
+    }
+    ASSERT_NOT_REACHED();
+    return borderBottomWidth();
+}
+
+unsigned short RenderStyle::borderStartWidth() const
+{
+    if (isHorizontalWritingMode())
+        return isLeftToRightDirection() ? borderLeftWidth() : borderRightWidth();
+    return isLeftToRightDirection() ? borderTopWidth() : borderBottomWidth();
+}
+
+unsigned short RenderStyle::borderEndWidth() const
+{
+    if (isHorizontalWritingMode())
+        return isLeftToRightDirection() ? borderRightWidth() : borderLeftWidth();
+    return isLeftToRightDirection() ? borderBottomWidth() : borderTopWidth();
+}
+
+void RenderStyle::setMarginStart(Length margin)
+{
+    if (isHorizontalWritingMode()) {
+        if (isLeftToRightDirection())
+            setMarginLeft(margin);
+        else
+            setMarginRight(margin);
+    } else {
+        if (isLeftToRightDirection())
+            setMarginTop(margin);
+        else
+            setMarginBottom(margin);
+    }
+}
+
+void RenderStyle::setMarginEnd(Length margin)
+{
+    if (isHorizontalWritingMode()) {
+        if (isLeftToRightDirection())
+            setMarginRight(margin);
+        else
+            setMarginLeft(margin);
+    } else {
+        if (isLeftToRightDirection())
+            setMarginBottom(margin);
+        else
+            setMarginTop(margin);
+    }
+}
+
+TextEmphasisMark RenderStyle::textEmphasisMark() const
+{
+    TextEmphasisMark mark = static_cast<TextEmphasisMark>(rareInheritedData->textEmphasisMark);
+    if (mark != TextEmphasisMarkAuto)
+        return mark;
+
+    if (isHorizontalWritingMode())
+        return TextEmphasisMarkDot;
+
+    return TextEmphasisMarkSesame;
+}
+
+Color RenderStyle::initialTapHighlightColor()
+{
+    return RenderTheme::tapHighlightColor();
+}
+
+LayoutBoxExtent RenderStyle::imageOutsets(const NinePieceImage& image) const
+{
+    return LayoutBoxExtent(NinePieceImage::computeOutset(image.outset().top(), borderTopWidth()),
+                           NinePieceImage::computeOutset(image.outset().right(), borderRightWidth()),
+                           NinePieceImage::computeOutset(image.outset().bottom(), borderBottomWidth()),
+                           NinePieceImage::computeOutset(image.outset().left(), borderLeftWidth()));
+}
+
+void RenderStyle::setBorderImageSource(PassRefPtr<StyleImage> image)
+{
+    if (surround->border.m_image.image() == image.get())
+        return;
+    surround.access()->border.m_image.setImage(image);
+}
+
+void RenderStyle::setBorderImageSlices(LengthBox slices)
+{
+    if (surround->border.m_image.imageSlices() == slices)
+        return;
+    surround.access()->border.m_image.setImageSlices(slices);
+}
+
+void RenderStyle::setBorderImageWidth(LengthBox slices)
+{
+    if (surround->border.m_image.borderSlices() == slices)
+        return;
+    surround.access()->border.m_image.setBorderSlices(slices);
+}
+
+void RenderStyle::setBorderImageOutset(LengthBox outset)
+{
+    if (surround->border.m_image.outset() == outset)
+        return;
+    surround.access()->border.m_image.setOutset(outset);
+}
+
+ExclusionShapeValue* RenderStyle::initialShapeInside()
+{
+    DEFINE_STATIC_LOCAL(RefPtr<ExclusionShapeValue>, sOutsideValue, (ExclusionShapeValue::createOutsideValue()));
+    return sOutsideValue.get();
+}
+
+void RenderStyle::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS);
+    info.addMember(m_box, "box");
+    info.addMember(visual, "visual");
+    // FIXME: m_background contains RefPtr<StyleImage> that might need to be instrumented.
+    info.addMember(m_background, "background");
+    // FIXME: surrond contains some fields e.g. BorderData that might need to be instrumented.
+    info.addMember(surround, "surround");
+    info.addMember(rareNonInheritedData, "rareNonInheritedData");
+    info.addMember(rareInheritedData, "rareInheritedData");
+    // FIXME: inherited contains StyleImage and Font fields that might need to be instrumented.
+    info.addMember(inherited, "inherited");
+    info.addMember(m_cachedPseudoStyles, "cachedPseudoStyles");
+#if ENABLE(SVG)
+    info.addMember(m_svgStyle, "svgStyle");
+#endif
+    info.addMember(inherited_flags, "inherited_flags");
+    info.addMember(noninherited_flags, "noninherited_flags");
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/style/RenderStyle.h b/Source/core/rendering/style/RenderStyle.h
new file mode 100644
index 0000000..50131b2
--- /dev/null
+++ b/Source/core/rendering/style/RenderStyle.h
@@ -0,0 +1,1788 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ *           (C) 2000 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com)
+ *
+ * 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 "CSSPropertyNames.h"
+#include "core/css/CSSLineBoxContainValue.h"
+#include "core/css/CSSPrimitiveValue.h"
+#include "core/css/LengthFunctions.h"
+#include "core/platform/Length.h"
+#include "core/platform/LengthBox.h"
+#include "core/platform/LengthSize.h"
+#include "core/platform/ThemeTypes.h"
+#include "core/platform/animation/CSSAnimationDataList.h"
+#include "core/platform/graphics/Color.h"
+#include "core/platform/graphics/ColorSpace.h"
+#include "core/platform/graphics/FontBaseline.h"
+#include "core/platform/graphics/FontDescription.h"
+#include "core/platform/graphics/GraphicsTypes.h"
+#include "core/platform/graphics/LayoutBoxExtent.h"
+#include "core/platform/graphics/RoundedRect.h"
+#include "core/platform/graphics/transforms/TransformOperations.h"
+#include "core/platform/text/TextDirection.h"
+#include "core/platform/text/UnicodeBidi.h"
+#include "core/rendering/style/BorderValue.h"
+#include "core/rendering/style/CounterDirectives.h"
+#include "core/rendering/style/DataRef.h"
+#include "core/rendering/style/ExclusionShapeValue.h"
+#include "core/rendering/style/LineClampValue.h"
+#include "core/rendering/style/NinePieceImage.h"
+#include "core/rendering/style/OutlineValue.h"
+#include "core/rendering/style/RenderStyleConstants.h"
+#include "core/rendering/style/ShadowData.h"
+#include "core/rendering/style/StyleBackgroundData.h"
+#include "core/rendering/style/StyleBoxData.h"
+#include "core/rendering/style/StyleDeprecatedFlexibleBoxData.h"
+#include "core/rendering/style/StyleFlexibleBoxData.h"
+#include "core/rendering/style/StyleGridData.h"
+#include "core/rendering/style/StyleGridItemData.h"
+#include "core/rendering/style/StyleMarqueeData.h"
+#include "core/rendering/style/StyleMultiColData.h"
+#include "core/rendering/style/StyleRareInheritedData.h"
+#include "core/rendering/style/StyleRareNonInheritedData.h"
+#include "core/rendering/style/StyleReflection.h"
+#include "core/rendering/style/StyleSurroundData.h"
+#include "core/rendering/style/StyleTransformData.h"
+#include "core/rendering/style/StyleVisualData.h"
+#include <wtf/Forward.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/StdLibExtras.h>
+#include <wtf/Vector.h>
+
+#include "core/rendering/style/StyleFilterData.h"
+
+#if ENABLE(SVG)
+#include "core/rendering/style/SVGRenderStyle.h"
+#include "core/svg/SVGPaint.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
+
+#define SET_BORDERVALUE_COLOR(group, variable, value) \
+    if (!compareEqual(group->variable.color(), value)) \
+        group.access()->variable.setColor(value)
+
+namespace WebCore {
+
+using std::max;
+
+class FilterOperations;
+
+class BorderData;
+class CounterContent;
+class CursorList;
+class Font;
+class FontMetrics;
+class IntRect;
+class Pair;
+class ShadowData;
+class StyleImage;
+class StyleInheritedData;
+class StyleResolver;
+class TransformationMatrix;
+
+class ContentData;
+
+typedef Vector<RefPtr<RenderStyle>, 4> PseudoStyleCache;
+
+class RenderStyle: public RefCounted<RenderStyle> {
+    friend class CSSPropertyAnimation; // Used by CSS animations. We can't allow them to animate based off visited colors.
+    friend class ApplyStyleCommand; // Editing has to only reveal unvisited info.
+    friend class DeprecatedStyleBuilder; // Sets members directly.
+    friend class EditingStyle; // Editing has to only reveal unvisited info.
+    friend class CSSComputedStyleDeclaration; // Ignores visited styles, so needs to be able to see unvisited info.
+    friend class PropertyWrapperMaybeInvalidColor; // Used by CSS animations. We can't allow them to animate based off visited colors.
+    friend class RenderSVGResource; // FIXME: Needs to alter the visited state by hand. Should clean the SVG code up and move it into RenderStyle perhaps.
+    friend class RenderTreeAsText; // FIXME: Only needed so the render tree can keep lying and dump the wrong colors.  Rebaselining would allow this to be yanked.
+    friend class StyleResolver; // Sets members directly.
+protected:
+
+    // non-inherited attributes
+    DataRef<StyleBoxData> m_box;
+    DataRef<StyleVisualData> visual;
+    DataRef<StyleBackgroundData> m_background;
+    DataRef<StyleSurroundData> surround;
+    DataRef<StyleRareNonInheritedData> rareNonInheritedData;
+
+    // inherited attributes
+    DataRef<StyleRareInheritedData> rareInheritedData;
+    DataRef<StyleInheritedData> inherited;
+
+    // list of associated pseudo styles
+    OwnPtr<PseudoStyleCache> m_cachedPseudoStyles;
+
+#if ENABLE(SVG)
+    DataRef<SVGRenderStyle> m_svgStyle;
+#endif
+
+// !START SYNC!: Keep this in sync with the copy constructor in RenderStyle.cpp and implicitlyInherited() in StyleResolver.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)
+                && (_cursor_style == other._cursor_style)
+                && (_direction == other._direction)
+                && (_white_space == other._white_space)
+                && (_border_collapse == other._border_collapse)
+                && (_box_direction == other._box_direction)
+                && (m_rtlOrdering == other.m_rtlOrdering)
+                && (m_printColorAdjust == other.m_printColorAdjust)
+                && (_pointerEvents == other._pointerEvents)
+                && (_insideLink == other._insideLink)
+                && (m_writingMode == other.m_writingMode);
+        }
+
+        bool operator!=(const InheritedFlags& other) const { return !(*this == other); }
+
+        unsigned _empty_cells : 1; // EEmptyCell
+        unsigned _caption_side : 2; // ECaptionSide
+        unsigned _list_style_type : 7; // EListStyleType
+        unsigned _list_style_position : 1; // EListStylePosition
+        unsigned _visibility : 2; // EVisibility
+        unsigned _text_align : 4; // ETextAlign
+        unsigned _text_transform : 2; // ETextTransform
+        unsigned _text_decorations : ETextDecorationBits;
+        unsigned _cursor_style : 6; // ECursor
+        unsigned _direction : 1; // TextDirection
+        unsigned _white_space : 3; // EWhiteSpace
+        // 32 bits
+        unsigned _border_collapse : 1; // EBorderCollapse
+        unsigned _box_direction : 1; // EBoxDirection (CSS3 box_direction property, flexible box layout module)
+
+        // non CSS2 inherited
+        unsigned m_rtlOrdering : 1; // Order
+        unsigned m_printColorAdjust : PrintColorAdjustBits;
+        unsigned _pointerEvents : 4; // EPointerEvents
+        unsigned _insideLink : 2; // EInsideLink
+        // 43 bits
+
+        // CSS Text Layout Module Level 3: Vertical writing support
+        unsigned m_writingMode : 2; // WritingMode
+        // 45 bits
+    } 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
+                && _page_break_inside == other._page_break_inside
+                && _styleType == other._styleType
+                && _affectedByHover == other._affectedByHover
+                && _affectedByActive == other._affectedByActive
+                && _affectedByDrag == other._affectedByDrag
+                && _pseudoBits == other._pseudoBits
+                && _unicodeBidi == other._unicodeBidi
+                && explicitInheritance == other.explicitInheritance
+                && unique == other.unique
+                && emptyState == other.emptyState
+                && firstChildState == other.firstChildState
+                && lastChildState == other.lastChildState
+                && _isLink == other._isLink;
+        }
+
+        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 : 3; // EPosition
+        unsigned _floating : 2; // EFloat
+        unsigned _table_layout : 1; // ETableLayout
+
+        unsigned _unicodeBidi : 3; // EUnicodeBidi
+        // 31 bits
+        unsigned _page_break_before : 2; // EPageBreak
+        unsigned _page_break_after : 2; // EPageBreak
+        unsigned _page_break_inside : 2; // EPageBreak
+
+        unsigned _styleType : 6; // PseudoId
+        unsigned _pseudoBits : 7;
+        unsigned explicitInheritance : 1; // Explicitly inherits a non-inherited property
+        unsigned unique : 1; // Style can not be shared.
+        unsigned emptyState : 1;
+        unsigned firstChildState : 1;
+        unsigned lastChildState : 1;
+
+        bool affectedByHover() const { return _affectedByHover; }
+        void setAffectedByHover(bool value) { _affectedByHover = value; }
+        bool affectedByActive() const { return _affectedByActive; }
+        void setAffectedByActive(bool value) { _affectedByActive = value; }
+        bool affectedByDrag() const { return _affectedByDrag; }
+        void setAffectedByDrag(bool value) { _affectedByDrag = value; }
+        bool isLink() const { return _isLink; }
+        void setIsLink(bool value) { _isLink = value; }
+    private:
+        unsigned _affectedByHover : 1;
+        unsigned _affectedByActive : 1;
+        unsigned _affectedByDrag : 1;
+        unsigned _isLink : 1;
+        // If you add more style bits here, you will also need to update RenderStyle::copyNonInheritedFrom()
+        // 59 bits
+    } noninherited_flags;
+
+// !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._white_space = initialWhiteSpace();
+        inherited_flags._border_collapse = initialBorderCollapse();
+        inherited_flags.m_rtlOrdering = initialRTLOrdering();
+        inherited_flags._box_direction = initialBoxDirection();
+        inherited_flags.m_printColorAdjust = initialPrintColorAdjust();
+        inherited_flags._pointerEvents = initialPointerEvents();
+        inherited_flags._insideLink = NotInsideLink;
+        inherited_flags.m_writingMode = initialWritingMode();
+
+        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._unicodeBidi = initialUnicodeBidi();
+        noninherited_flags._page_break_before = initialPageBreak();
+        noninherited_flags._page_break_after = initialPageBreak();
+        noninherited_flags._page_break_inside = initialPageBreak();
+        noninherited_flags._styleType = NOPSEUDO;
+        noninherited_flags._pseudoBits = 0;
+        noninherited_flags.explicitInheritance = false;
+        noninherited_flags.unique = false;
+        noninherited_flags.emptyState = false;
+        noninherited_flags.firstChildState = false;
+        noninherited_flags.lastChildState = false;
+        noninherited_flags.setAffectedByHover(false);
+        noninherited_flags.setAffectedByActive(false);
+        noninherited_flags.setAffectedByDrag(false);
+        noninherited_flags.setIsLink(false);
+    }
+
+private:
+    ALWAYS_INLINE RenderStyle();
+    // used to create the default style.
+    ALWAYS_INLINE RenderStyle(bool);
+    ALWAYS_INLINE RenderStyle(const RenderStyle&);
+
+public:
+    static PassRefPtr<RenderStyle> create();
+    static PassRefPtr<RenderStyle> createDefaultStyle();
+    static PassRefPtr<RenderStyle> createAnonymousStyleWithDisplay(const RenderStyle* parentStyle, EDisplay);
+    static PassRefPtr<RenderStyle> clone(const RenderStyle*);
+
+    enum IsAtShadowBoundary {
+        AtShadowBoundary,
+        NotAtShadowBoundary,
+    };
+
+    void inheritFrom(const RenderStyle* inheritParent, IsAtShadowBoundary = NotAtShadowBoundary);
+    void copyNonInheritedFrom(const RenderStyle*);
+
+    PseudoId styleType() const { return static_cast<PseudoId>(noninherited_flags._styleType); }
+    void setStyleType(PseudoId styleType) { noninherited_flags._styleType = styleType; }
+
+    RenderStyle* getCachedPseudoStyle(PseudoId) const;
+    RenderStyle* addCachedPseudoStyle(PassRefPtr<RenderStyle>);
+    void removeCachedPseudoStyle(PseudoId);
+
+    const PseudoStyleCache* cachedPseudoStyles() const { return m_cachedPseudoStyles.get(); }
+
+    void setVariable(const AtomicString& name, const String& value) { rareInheritedData.access()->m_variables.access()->setVariable(name, value); }
+    const HashMap<AtomicString, String>* variables() { return &(rareInheritedData->m_variables->m_data); }
+
+    bool affectedByHover() const { return noninherited_flags.affectedByHover(); }
+    bool affectedByActive() const { return noninherited_flags.affectedByActive(); }
+    bool affectedByDrag() const { return noninherited_flags.affectedByDrag(); }
+
+    void setAffectedByHover() { noninherited_flags.setAffectedByHover(true); }
+    void setAffectedByActive() { noninherited_flags.setAffectedByActive(true); }
+    void setAffectedByDrag() { noninherited_flags.setAffectedByDrag(true); }
+
+    bool operator==(const RenderStyle& other) const;
+    bool operator!=(const RenderStyle& other) const { return !(*this == other); }
+    bool isFloating() const { return noninherited_flags._floating != NoFloat; }
+    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 hasMarginBeforeQuirk() const { return marginBefore().quirk(); }
+    bool hasMarginAfterQuirk() const { return marginAfter().quirk(); }
+
+    bool hasBackgroundImage() const { return m_background->background().hasImage(); }
+    bool hasFixedBackgroundImage() const { return m_background->background().hasFixedImage(); }
+    
+    bool hasEntirelyFixedBackground() const;
+    
+    bool hasAppearance() const { return appearance() != NoControlPart; }
+
+    bool hasBackground() const
+    {
+        Color color = visitedDependentColor(CSSPropertyBackgroundColor);
+        if (color.isValid() && color.alpha())
+            return true;
+        return hasBackgroundImage();
+    }
+    
+    LayoutBoxExtent imageOutsets(const NinePieceImage&) const;
+    bool hasBorderImageOutsets() const
+    {
+        return borderImage().hasImage() && borderImage().outset().nonZero();
+    }
+    LayoutBoxExtent borderImageOutsets() const
+    {
+        return imageOutsets(borderImage());
+    }
+
+    LayoutBoxExtent maskBoxImageOutsets() const
+    {
+        return imageOutsets(maskBoxImage());
+    }
+
+    bool hasFilterOutsets() const { return hasFilter() && filter().hasOutsets(); }
+    FilterOutsets filterOutsets() const { return hasFilter() ? filter().outsets() : FilterOutsets(); }
+
+    Order rtlOrdering() const { return static_cast<Order>(inherited_flags.m_rtlOrdering); }
+    void setRTLOrdering(Order o) { inherited_flags.m_rtlOrdering = o; }
+
+    bool isStyleAvailable() const;
+
+    bool hasAnyPublicPseudoStyles() const;
+    bool hasPseudoStyle(PseudoId pseudo) const;
+    void setHasPseudoStyle(PseudoId pseudo);
+    bool hasUniquePseudoStyle() const;
+
+    // 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(); }
+
+    // Accessors for positioned object edges that take into account writing mode.
+    Length logicalLeft() const { return surround->offset.logicalLeft(writingMode()); }
+    Length logicalRight() const { return surround->offset.logicalRight(writingMode()); }
+    Length logicalTop() const { return surround->offset.before(writingMode()); }
+    Length logicalBottom() const { return surround->offset.after(writingMode()); }
+
+    // Whether or not a positioned element requires normal flow x/y to be computed
+    // to determine its position.
+    bool hasAutoLeftAndRight() const { return left().isAuto() && right().isAuto(); }
+    bool hasAutoTopAndBottom() const { return top().isAuto() && bottom().isAuto(); }
+    bool hasStaticInlinePosition(bool horizontal) const { return horizontal ? hasAutoLeftAndRight() : hasAutoTopAndBottom(); }
+    bool hasStaticBlockPosition(bool horizontal) const { return horizontal ? hasAutoTopAndBottom() : hasAutoLeftAndRight(); }
+
+    EPosition position() const { return static_cast<EPosition>(noninherited_flags._position); }
+    bool hasOutOfFlowPosition() const { return position() == AbsolutePosition || position() == FixedPosition; }
+    bool hasInFlowPosition() const { return position() == RelativePosition || position() == StickyPosition; }
+    bool hasPaintOffset() const
+    {
+        bool paintOffset = hasInFlowPosition();
+        paintOffset = paintOffset || (isFloating() && shapeOutside());
+        return paintOffset;
+    }
+    bool hasViewportConstrainedPosition() const { return position() == FixedPosition || position() == StickyPosition; }
+    EFloat floating() const { return static_cast<EFloat>(noninherited_flags._floating); }
+
+    Length width() const { return m_box->width(); }
+    Length height() const { return m_box->height(); }
+    Length minWidth() const { return m_box->minWidth(); }
+    Length maxWidth() const { return m_box->maxWidth(); }
+    Length minHeight() const { return m_box->minHeight(); }
+    Length maxHeight() const { return m_box->maxHeight(); }
+    
+    Length logicalWidth() const { return isHorizontalWritingMode() ? width() : height(); }
+    Length logicalHeight() const { return isHorizontalWritingMode() ? height() : width(); }
+    Length logicalMinWidth() const { return isHorizontalWritingMode() ? minWidth() : minHeight(); }
+    Length logicalMaxWidth() const { return isHorizontalWritingMode() ? maxWidth() : maxHeight(); }
+    Length logicalMinHeight() const { return isHorizontalWritingMode() ? minHeight() : minWidth(); }
+    Length logicalMaxHeight() const { return isHorizontalWritingMode() ? maxHeight() : maxWidth(); }
+
+    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 BorderValue& borderBefore() const;
+    const BorderValue& borderAfter() const;
+    const BorderValue& borderStart() const;
+    const BorderValue& borderEnd() const;
+
+    const NinePieceImage& borderImage() const { return surround->border.image(); }
+    StyleImage* borderImageSource() const { return surround->border.image().image(); }
+    LengthBox borderImageSlices() const { return surround->border.image().imageSlices(); }
+    LengthBox borderImageWidth() const { return surround->border.image().borderSlices(); }
+    LengthBox borderImageOutset() const { return surround->border.image().outset(); }
+
+    LengthSize borderTopLeftRadius() const { return surround->border.topLeft(); }
+    LengthSize borderTopRightRadius() const { return surround->border.topRight(); }
+    LengthSize borderBottomLeftRadius() const { return surround->border.bottomLeft(); }
+    LengthSize borderBottomRightRadius() const { return surround->border.bottomRight(); }
+    bool hasBorderRadius() const { return surround->border.hasBorderRadius(); }
+
+    unsigned borderLeftWidth() const { return surround->border.borderLeftWidth(); }
+    EBorderStyle borderLeftStyle() const { return surround->border.left().style(); }
+    bool borderLeftIsTransparent() const { return surround->border.left().isTransparent(); }
+    unsigned borderRightWidth() const { return surround->border.borderRightWidth(); }
+    EBorderStyle borderRightStyle() const { return surround->border.right().style(); }
+    bool borderRightIsTransparent() const { return surround->border.right().isTransparent(); }
+    unsigned borderTopWidth() const { return surround->border.borderTopWidth(); }
+    EBorderStyle borderTopStyle() const { return surround->border.top().style(); }
+    bool borderTopIsTransparent() const { return surround->border.top().isTransparent(); }
+    unsigned borderBottomWidth() const { return surround->border.borderBottomWidth(); }
+    EBorderStyle borderBottomStyle() const { return surround->border.bottom().style(); }
+    bool borderBottomIsTransparent() const { return surround->border.bottom().isTransparent(); }
+    
+    unsigned short borderBeforeWidth() const;
+    unsigned short borderAfterWidth() const;
+    unsigned short borderStartWidth() const;
+    unsigned short borderEndWidth() const;
+
+    unsigned short outlineSize() const { return max(0, outlineWidth() + outlineOffset()); }
+    unsigned short outlineWidth() const
+    {
+        if (m_background->outline().style() == BNONE)
+            return 0;
+        return m_background->outline().width();
+    }
+    bool hasOutline() const { return outlineWidth() > 0 && outlineStyle() > BHIDDEN; }
+    EBorderStyle outlineStyle() const { return m_background->outline().style(); }
+    OutlineIsAuto outlineStyleIsAuto() const { return static_cast<OutlineIsAuto>(m_background->outline().isAuto()); }
+    
+    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 m_box->verticalAlign(); }
+
+    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;
+    const FontMetrics& fontMetrics() const;
+    const FontDescription& fontDescription() const;
+    float specifiedFontSize() const;
+    float computedFontSize() const;
+    int fontSize() const;
+
+    float textAutosizingMultiplier() const { return visual->m_textAutosizingMultiplier; }
+
+    Length textIndent() const { return rareInheritedData->indent; }
+#if ENABLE(CSS3_TEXT)
+    TextIndentLine textIndentLine() const { return static_cast<TextIndentLine>(rareInheritedData->m_textIndentLine); }
+#endif
+    ETextAlign textAlign() const { return static_cast<ETextAlign>(inherited_flags._text_align); }
+    ETextTransform textTransform() const { return static_cast<ETextTransform>(inherited_flags._text_transform); }
+    ETextDecoration textDecorationsInEffect() const { return static_cast<ETextDecoration>(inherited_flags._text_decorations); }
+    ETextDecoration textDecoration() const { return static_cast<ETextDecoration>(visual->textDecoration); }
+#if ENABLE(CSS3_TEXT)
+    TextDecorationStyle textDecorationStyle() const { return static_cast<TextDecorationStyle>(rareNonInheritedData->m_textDecorationStyle); }
+    TextAlignLast textAlignLast() const { return static_cast<TextAlignLast>(rareInheritedData->m_textAlignLast); }
+    TextUnderlinePosition textUnderlinePosition() const { return static_cast<TextUnderlinePosition>(rareInheritedData->m_textUnderlinePosition); }
+#else
+    TextDecorationStyle textDecorationStyle() const { return TextDecorationStyleSolid; }
+#endif // CSS3_TEXT
+    int wordSpacing() const;
+    int letterSpacing() const;
+
+    float zoom() const { return visual->m_zoom; }
+    float effectiveZoom() const { return rareInheritedData->m_effectiveZoom; }
+
+    TextDirection direction() const { return static_cast<TextDirection>(inherited_flags._direction); }
+    bool isLeftToRightDirection() const { return direction() == LTR; }
+
+    Length specifiedLineHeight() const;
+    Length lineHeight() const;
+    int computedLineHeight(RenderView* = 0) const;
+
+    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 || lineBreak() == LineBreakAfterWhiteSpace;
+    }
+
+    bool breakWords() const
+    {
+        return wordBreak() == BreakWordBreak || overflowWrap() == BreakOverflowWrap;
+    }
+
+    EFillRepeat backgroundRepeatX() const { return static_cast<EFillRepeat>(m_background->background().repeatX()); }
+    EFillRepeat backgroundRepeatY() const { return static_cast<EFillRepeat>(m_background->background().repeatY()); }
+    CompositeOperator backgroundComposite() const { return static_cast<CompositeOperator>(m_background->background().composite()); }
+    EFillAttachment backgroundAttachment() const { return static_cast<EFillAttachment>(m_background->background().attachment()); }
+    EFillBox backgroundClip() const { return static_cast<EFillBox>(m_background->background().clip()); }
+    EFillBox backgroundOrigin() const { return static_cast<EFillBox>(m_background->background().origin()); }
+    Length backgroundXPosition() const { return m_background->background().xPosition(); }
+    Length backgroundYPosition() const { return m_background->background().yPosition(); }
+    EFillSizeType backgroundSizeType() const { return m_background->background().sizeType(); }
+    LengthSize backgroundSizeLength() const { return m_background->background().sizeLength(); }
+    FillLayer* accessBackgroundLayers() { return &(m_background.access()->m_background); }
+    const FillLayer* backgroundLayers() const { return &(m_background->background()); }
+
+    StyleImage* maskImage() const { return rareNonInheritedData->m_mask.image(); }
+    EFillRepeat maskRepeatX() const { return static_cast<EFillRepeat>(rareNonInheritedData->m_mask.repeatX()); }
+    EFillRepeat maskRepeatY() const { return static_cast<EFillRepeat>(rareNonInheritedData->m_mask.repeatY()); }
+    CompositeOperator maskComposite() const { return static_cast<CompositeOperator>(rareNonInheritedData->m_mask.composite()); }
+    EFillBox maskClip() const { return static_cast<EFillBox>(rareNonInheritedData->m_mask.clip()); }
+    EFillBox maskOrigin() const { return static_cast<EFillBox>(rareNonInheritedData->m_mask.origin()); }
+    Length maskXPosition() const { return rareNonInheritedData->m_mask.xPosition(); }
+    Length maskYPosition() const { return rareNonInheritedData->m_mask.yPosition(); }
+    EFillSizeType maskSizeType() const { return rareNonInheritedData->m_mask.sizeType(); }
+    LengthSize maskSizeLength() const { return rareNonInheritedData->m_mask.sizeLength(); }
+    FillLayer* accessMaskLayers() { return &(rareNonInheritedData.access()->m_mask); }
+    const FillLayer* maskLayers() const { return &(rareNonInheritedData->m_mask); }
+    const NinePieceImage& maskBoxImage() const { return rareNonInheritedData->m_maskBoxImage; }
+    StyleImage* maskBoxImageSource() const { return rareNonInheritedData->m_maskBoxImage.image(); }
+ 
+    EBorderCollapse borderCollapse() const { return static_cast<EBorderCollapse>(inherited_flags._border_collapse); }
+    short horizontalBorderSpacing() const;
+    short verticalBorderSpacing() const;
+    EEmptyCell emptyCells() const { return static_cast<EEmptyCell>(inherited_flags._empty_cells); }
+    ECaptionSide captionSide() const { return static_cast<ECaptionSide>(inherited_flags._caption_side); }
+
+    EListStyleType listStyleType() const { return static_cast<EListStyleType>(inherited_flags._list_style_type); }
+    StyleImage* listStyleImage() const;
+    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(); }
+    Length marginBefore() const { return surround->margin.before(writingMode()); }
+    Length marginAfter() const { return surround->margin.after(writingMode()); }
+    Length marginStart() const { return surround->margin.start(writingMode(), direction()); }
+    Length marginEnd() const { return surround->margin.end(writingMode(), direction()); }
+    Length marginStartUsing(const RenderStyle* otherStyle) const { return surround->margin.start(otherStyle->writingMode(), otherStyle->direction()); }
+    Length marginEndUsing(const RenderStyle* otherStyle) const { return surround->margin.end(otherStyle->writingMode(), otherStyle->direction()); }
+    Length marginBeforeUsing(const RenderStyle* otherStyle) const { return surround->margin.before(otherStyle->writingMode()); }
+    Length marginAfterUsing(const RenderStyle* otherStyle) const { return surround->margin.after(otherStyle->writingMode()); }
+
+    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(); }
+    Length paddingBefore() const { return surround->padding.before(writingMode()); }
+    Length paddingAfter() const { return surround->padding.after(writingMode()); }
+    Length paddingStart() const { return surround->padding.start(writingMode(), direction()); }
+    Length paddingEnd() const { return surround->padding.end(writingMode(), direction()); }
+
+    ECursor cursor() const { return static_cast<ECursor>(inherited_flags._cursor_style); }
+    CursorList* cursors() const { return rareInheritedData->cursorData.get(); }
+
+    EInsideLink insideLink() const { return static_cast<EInsideLink>(inherited_flags._insideLink); }
+    bool isLink() const { return noninherited_flags.isLink(); }
+
+    short widows() const { return rareInheritedData->widows; }
+    short orphans() const { return rareInheritedData->orphans; }
+    bool hasAutoWidows() const { return rareInheritedData->m_hasAutoWidows; }
+    bool hasAutoOrphans() const { return rareInheritedData->m_hasAutoOrphans; }
+    EPageBreak pageBreakInside() const { return static_cast<EPageBreak>(noninherited_flags._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
+
+    int outlineOffset() const
+    {
+        if (m_background->outline().style() == BNONE)
+            return 0;
+        return m_background->outline().offset();
+    }
+
+    const ShadowData* textShadow() const { return rareInheritedData->textShadow.get(); }
+    void getTextShadowExtent(LayoutUnit& top, LayoutUnit& right, LayoutUnit& bottom, LayoutUnit& left) const { getShadowExtent(textShadow(), top, right, bottom, left); }
+    void getTextShadowHorizontalExtent(LayoutUnit& left, LayoutUnit& right) const { getShadowHorizontalExtent(textShadow(), left, right); }
+    void getTextShadowVerticalExtent(LayoutUnit& top, LayoutUnit& bottom) const { getShadowVerticalExtent(textShadow(), top, bottom); }
+    void getTextShadowInlineDirectionExtent(LayoutUnit& logicalLeft, LayoutUnit& logicalRight) { getShadowInlineDirectionExtent(textShadow(), logicalLeft, logicalRight); }
+    void getTextShadowBlockDirectionExtent(LayoutUnit& logicalTop, LayoutUnit& logicalBottom) { getShadowBlockDirectionExtent(textShadow(), logicalTop, logicalBottom); }
+
+    float textStrokeWidth() const { return rareInheritedData->textStrokeWidth; }
+    ColorSpace colorSpace() const { return static_cast<ColorSpace>(rareInheritedData->colorSpace); }
+    float opacity() const { return rareNonInheritedData->opacity; }
+    ControlPart appearance() const { return static_cast<ControlPart>(rareNonInheritedData->m_appearance); }
+    // aspect ratio convenience method
+    bool hasAspectRatio() const { return rareNonInheritedData->m_hasAspectRatio; }
+    float aspectRatio() const { return aspectRatioNumerator() / aspectRatioDenominator(); }
+    float aspectRatioDenominator() const { return rareNonInheritedData->m_aspectRatioDenominator; }
+    float aspectRatioNumerator() const { return rareNonInheritedData->m_aspectRatioNumerator; }
+    EBoxAlignment boxAlign() const { return static_cast<EBoxAlignment>(rareNonInheritedData->m_deprecatedFlexibleBox->align); }
+    EBoxDirection boxDirection() const { return static_cast<EBoxDirection>(inherited_flags._box_direction); }
+    float boxFlex() const { return rareNonInheritedData->m_deprecatedFlexibleBox->flex; }
+    unsigned int boxFlexGroup() const { return rareNonInheritedData->m_deprecatedFlexibleBox->flex_group; }
+    EBoxLines boxLines() const { return static_cast<EBoxLines>(rareNonInheritedData->m_deprecatedFlexibleBox->lines); }
+    unsigned int boxOrdinalGroup() const { return rareNonInheritedData->m_deprecatedFlexibleBox->ordinal_group; }
+    EBoxOrient boxOrient() const { return static_cast<EBoxOrient>(rareNonInheritedData->m_deprecatedFlexibleBox->orient); }
+    EBoxPack boxPack() const { return static_cast<EBoxPack>(rareNonInheritedData->m_deprecatedFlexibleBox->pack); }
+
+    int order() const { return rareNonInheritedData->m_order; }
+    float flexGrow() const { return rareNonInheritedData->m_flexibleBox->m_flexGrow; }
+    float flexShrink() const { return rareNonInheritedData->m_flexibleBox->m_flexShrink; }
+    Length flexBasis() const { return rareNonInheritedData->m_flexibleBox->m_flexBasis; }
+    EAlignContent alignContent() const { return static_cast<EAlignContent>(rareNonInheritedData->m_alignContent); }
+    EAlignItems alignItems() const { return static_cast<EAlignItems>(rareNonInheritedData->m_alignItems); }
+    EAlignItems alignSelf() const { return static_cast<EAlignItems>(rareNonInheritedData->m_alignSelf); }
+    EFlexDirection flexDirection() const { return static_cast<EFlexDirection>(rareNonInheritedData->m_flexibleBox->m_flexDirection); }
+    bool isColumnFlexDirection() const { return flexDirection() == FlowColumn || flexDirection() == FlowColumnReverse; }
+    bool isReverseFlexDirection() const { return flexDirection() == FlowRowReverse || flexDirection() == FlowColumnReverse; }
+    EFlexWrap flexWrap() const { return static_cast<EFlexWrap>(rareNonInheritedData->m_flexibleBox->m_flexWrap); }
+    EJustifyContent justifyContent() const { return static_cast<EJustifyContent>(rareNonInheritedData->m_justifyContent); }
+
+    const Vector<GridTrackSize>& gridColumns() const { return rareNonInheritedData->m_grid->m_gridColumns; }
+    const Vector<GridTrackSize>& gridRows() const { return rareNonInheritedData->m_grid->m_gridRows; }
+    GridAutoFlow gridAutoFlow() const { return rareNonInheritedData->m_grid->m_gridAutoFlow; }
+    const GridTrackSize& gridAutoColumns() const { return rareNonInheritedData->m_grid->m_gridAutoColumns; }
+    const GridTrackSize& gridAutoRows() const { return rareNonInheritedData->m_grid->m_gridAutoRows; }
+
+    const GridPosition& gridStart() const { return rareNonInheritedData->m_gridItem->m_gridStart; }
+    const GridPosition& gridEnd() const { return rareNonInheritedData->m_gridItem->m_gridEnd; }
+    const GridPosition& gridBefore() const { return rareNonInheritedData->m_gridItem->m_gridBefore; }
+    const GridPosition& gridAfter() const { return rareNonInheritedData->m_gridItem->m_gridAfter; }
+
+    const ShadowData* boxShadow() const { return rareNonInheritedData->m_boxShadow.get(); }
+    void getBoxShadowExtent(LayoutUnit& top, LayoutUnit& right, LayoutUnit& bottom, LayoutUnit& left) const { getShadowExtent(boxShadow(), top, right, bottom, left); }
+    LayoutBoxExtent getBoxShadowInsetExtent() const { return getShadowInsetExtent(boxShadow()); }
+    void getBoxShadowHorizontalExtent(LayoutUnit& left, LayoutUnit& right) const { getShadowHorizontalExtent(boxShadow(), left, right); }
+    void getBoxShadowVerticalExtent(LayoutUnit& top, LayoutUnit& bottom) const { getShadowVerticalExtent(boxShadow(), top, bottom); }
+    void getBoxShadowInlineDirectionExtent(LayoutUnit& logicalLeft, LayoutUnit& logicalRight) { getShadowInlineDirectionExtent(boxShadow(), logicalLeft, logicalRight); }
+    void getBoxShadowBlockDirectionExtent(LayoutUnit& logicalTop, LayoutUnit& logicalBottom) { getShadowBlockDirectionExtent(boxShadow(), logicalTop, logicalBottom); }
+
+    EBoxDecorationBreak boxDecorationBreak() const { return m_box->boxDecorationBreak(); }
+    StyleReflection* boxReflect() const { return rareNonInheritedData->m_boxReflect.get(); }
+    EBoxSizing boxSizing() const { return m_box->boxSizing(); }
+    Length marqueeIncrement() const { return rareNonInheritedData->m_marquee->increment; }
+    int marqueeSpeed() const { return rareNonInheritedData->m_marquee->speed; }
+    int marqueeLoopCount() const { return rareNonInheritedData->m_marquee->loops; }
+    EMarqueeBehavior marqueeBehavior() const { return static_cast<EMarqueeBehavior>(rareNonInheritedData->m_marquee->behavior); }
+    EMarqueeDirection marqueeDirection() const { return static_cast<EMarqueeDirection>(rareNonInheritedData->m_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); }
+    TextOverflow textOverflow() const { return static_cast<TextOverflow>(rareNonInheritedData->textOverflow); }
+    EMarginCollapse marginBeforeCollapse() const { return static_cast<EMarginCollapse>(rareNonInheritedData->marginBeforeCollapse); }
+    EMarginCollapse marginAfterCollapse() const { return static_cast<EMarginCollapse>(rareNonInheritedData->marginAfterCollapse); }
+    EWordBreak wordBreak() const { return static_cast<EWordBreak>(rareInheritedData->wordBreak); }
+    EOverflowWrap overflowWrap() const { return static_cast<EOverflowWrap>(rareInheritedData->overflowWrap); }
+    LineBreak lineBreak() const { return static_cast<LineBreak>(rareInheritedData->lineBreak); }
+    const AtomicString& highlight() const { return rareInheritedData->highlight; }
+    Hyphens hyphens() const { return static_cast<Hyphens>(rareInheritedData->hyphens); }
+    short hyphenationLimitBefore() const { return rareInheritedData->hyphenationLimitBefore; }
+    short hyphenationLimitAfter() const { return rareInheritedData->hyphenationLimitAfter; }
+    short hyphenationLimitLines() const { return rareInheritedData->hyphenationLimitLines; }
+    const AtomicString& hyphenationString() const { return rareInheritedData->hyphenationString; }
+    const AtomicString& locale() const { return rareInheritedData->locale; }
+    EBorderFit borderFit() const { return static_cast<EBorderFit>(rareNonInheritedData->m_borderFit); }
+    EResize resize() const { return static_cast<EResize>(rareInheritedData->resize); }
+    ColumnAxis columnAxis() const { return static_cast<ColumnAxis>(rareNonInheritedData->m_multiCol->m_axis); }
+    bool hasInlineColumnAxis() const {
+        ColumnAxis axis = columnAxis();
+        return axis == AutoColumnAxis || isHorizontalWritingMode() == (axis == HorizontalColumnAxis);
+    }
+    ColumnProgression columnProgression() const { return static_cast<ColumnProgression>(rareNonInheritedData->m_multiCol->m_progression); }
+    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; }
+    bool specifiesColumns() const { return !hasAutoColumnCount() || !hasAutoColumnWidth() || !hasInlineColumnAxis(); }
+    float columnGap() const { return rareNonInheritedData->m_multiCol->m_gap; }
+    bool hasNormalColumnGap() const { return rareNonInheritedData->m_multiCol->m_normalGap; }
+    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(); }
+    ColumnSpan columnSpan() const { return static_cast<ColumnSpan>(rareNonInheritedData->m_multiCol->m_columnSpan); }
+    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); }
+    EPageBreak regionBreakBefore() const { return static_cast<EPageBreak>(rareNonInheritedData->m_regionBreakBefore); }
+    EPageBreak regionBreakInside() const { return static_cast<EPageBreak>(rareNonInheritedData->m_regionBreakInside); }
+    EPageBreak regionBreakAfter() const { return static_cast<EPageBreak>(rareNonInheritedData->m_regionBreakAfter); }
+    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; }
+    float transformOriginZ() const { return rareNonInheritedData->m_transform->m_z; }
+    bool hasTransform() const { return !rareNonInheritedData->m_transform->m_operations.operations().isEmpty(); }
+
+    TextEmphasisFill textEmphasisFill() const { return static_cast<TextEmphasisFill>(rareInheritedData->textEmphasisFill); }
+    TextEmphasisMark textEmphasisMark() const;
+    const AtomicString& textEmphasisCustomMark() const { return rareInheritedData->textEmphasisCustomMark; }
+    TextEmphasisPosition textEmphasisPosition() const { return static_cast<TextEmphasisPosition>(rareInheritedData->textEmphasisPosition); }
+    const AtomicString& textEmphasisMarkString() const;
+
+    RubyPosition rubyPosition() const { return static_cast<RubyPosition>(rareInheritedData->m_rubyPosition); }
+
+    TextOrientation textOrientation() const { return static_cast<TextOrientation>(rareInheritedData->m_textOrientation); }
+    
+    // Return true if any transform related property (currently transform, transformStyle3D or perspective) 
+    // indicates that we are transforming
+    bool hasTransformRelatedProperty() const { return hasTransform() || preserves3D() || hasPerspective(); }
+
+    enum ApplyTransformOrigin { IncludeTransformOrigin, ExcludeTransformOrigin };
+    void applyTransform(TransformationMatrix&, const LayoutSize& borderBoxSize, ApplyTransformOrigin = IncludeTransformOrigin) const;
+    void applyTransform(TransformationMatrix&, const FloatRect& boundingBox, ApplyTransformOrigin = IncludeTransformOrigin) const;
+
+    bool hasMask() const { return rareNonInheritedData->m_mask.hasImage() || rareNonInheritedData->m_maskBoxImage.hasImage(); }
+
+    TextCombine textCombine() const { return static_cast<TextCombine>(rareNonInheritedData->m_textCombine); }
+    bool hasTextCombine() const { return textCombine() != TextCombineNone; }
+
+    unsigned tabSize() const { return rareInheritedData->m_tabSize; }
+
+    // End CSS3 Getters
+
+    const AtomicString& flowThread() const { return rareNonInheritedData->m_flowThread; }
+    const AtomicString& regionThread() const { return rareNonInheritedData->m_regionThread; }
+    RegionOverflow regionOverflow() const { return static_cast<RegionOverflow>(rareNonInheritedData->m_regionOverflow); }
+
+    const AtomicString& lineGrid() const { return rareInheritedData->m_lineGrid; }
+    LineSnap lineSnap() const { return static_cast<LineSnap>(rareInheritedData->m_lineSnap); }
+    LineAlign lineAlign() const { return static_cast<LineAlign>(rareInheritedData->m_lineAlign); }
+
+    WrapFlow wrapFlow() const { return static_cast<WrapFlow>(rareNonInheritedData->m_wrapFlow); }
+    WrapThrough wrapThrough() const { return static_cast<WrapThrough>(rareNonInheritedData->m_wrapThrough); }
+
+    // Apple-specific property getter methods
+    EPointerEvents pointerEvents() const { return static_cast<EPointerEvents>(inherited_flags._pointerEvents); }
+    const CSSAnimationDataList* animations() const { return rareNonInheritedData->m_animations.get(); }
+    const CSSAnimationDataList* transitions() const { return rareNonInheritedData->m_transitions.get(); }
+
+    CSSAnimationDataList* accessAnimations();
+    CSSAnimationDataList* 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 CSSAnimationData* transitionForProperty(CSSPropertyID) const;
+
+    ETransformStyle3D transformStyle3D() const { return static_cast<ETransformStyle3D>(rareNonInheritedData->m_transformStyle3D); }
+    bool preserves3D() const { return rareNonInheritedData->m_transformStyle3D == TransformStyle3DPreserve3D; }
+
+    EBackfaceVisibility backfaceVisibility() const { return static_cast<EBackfaceVisibility>(rareNonInheritedData->m_backfaceVisibility); }
+    float perspective() const { return rareNonInheritedData->m_perspective; }
+    bool hasPerspective() const { return rareNonInheritedData->m_perspective > 0; }
+    Length perspectiveOriginX() const { return rareNonInheritedData->m_perspectiveOriginX; }
+    Length perspectiveOriginY() const { return rareNonInheritedData->m_perspectiveOriginY; }
+    LengthSize pageSize() const { return rareNonInheritedData->m_pageSize; }
+    PageSizeType pageSizeType() const { return static_cast<PageSizeType>(rareNonInheritedData->m_pageSizeType); }
+    
+    // When set, this ensures that styles compare as different. Used during accelerated animations.
+    bool isRunningAcceleratedAnimation() const { return rareNonInheritedData->m_runningAcceleratedAnimation; }
+
+    LineBoxContain lineBoxContain() const { return rareInheritedData->m_lineBoxContain; }
+    const LineClampValue& lineClamp() const { return rareNonInheritedData->lineClamp; }
+    Color tapHighlightColor() const { return rareInheritedData->tapHighlightColor; }
+#if ENABLE(ACCELERATED_OVERFLOW_SCROLLING)
+    bool useTouchOverflowScrolling() const { return rareInheritedData->useTouchOverflowScrolling; }
+#endif
+    ETextSecurity textSecurity() const { return static_cast<ETextSecurity>(rareInheritedData->textSecurity); }
+
+    WritingMode writingMode() const { return static_cast<WritingMode>(inherited_flags.m_writingMode); }
+    bool isHorizontalWritingMode() const { return WebCore::isHorizontalWritingMode(writingMode()); }
+    bool isFlippedLinesWritingMode() const { return WebCore::isFlippedLinesWritingMode(writingMode()); }
+    bool isFlippedBlocksWritingMode() const { return WebCore::isFlippedBlocksWritingMode(writingMode()); }
+
+    EImageRendering imageRendering() const { return static_cast<EImageRendering>(rareInheritedData->m_imageRendering); }
+
+    ESpeak speak() const { return static_cast<ESpeak>(rareInheritedData->speak); }
+
+    FilterOperations& mutableFilter() { return rareNonInheritedData.access()->m_filter.access()->m_operations; }
+    const FilterOperations& filter() const { return rareNonInheritedData->m_filter->m_operations; }
+    bool hasFilter() const { return !rareNonInheritedData->m_filter->m_operations.operations().isEmpty(); }
+
+#if ENABLE(CSS_COMPOSITING)
+    BlendMode blendMode() const { return static_cast<BlendMode>(rareNonInheritedData->m_effectiveBlendMode); }
+    void setBlendMode(BlendMode v) { rareNonInheritedData.access()->m_effectiveBlendMode = v; }
+    bool hasBlendMode() const { return static_cast<BlendMode>(rareNonInheritedData->m_effectiveBlendMode) != BlendModeNormal; }
+#else
+    bool hasBlendMode() const { return false; }
+#endif
+
+    bool shouldPlaceBlockDirectionScrollbarOnLogicalLeft() const { return !isLeftToRightDirection() && isHorizontalWritingMode(); }
+
+// 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(m_box, m_width, v); }
+    void setHeight(Length v) { SET_VAR(m_box, m_height, v); }
+
+    void setLogicalWidth(Length v)
+    {
+        if (isHorizontalWritingMode()) {
+            SET_VAR(m_box, m_width, v);
+        } else {
+            SET_VAR(m_box, m_height, v);
+        }
+    }
+
+    void setLogicalHeight(Length v)
+    {
+        if (isHorizontalWritingMode()) {
+            SET_VAR(m_box, m_height, v);
+        } else {
+            SET_VAR(m_box, m_width, v);
+        }
+    }
+
+    void setMinWidth(Length v) { SET_VAR(m_box, m_minWidth, v); }
+    void setMaxWidth(Length v) { SET_VAR(m_box, m_maxWidth, v); }
+    void setMinHeight(Length v) { SET_VAR(m_box, m_minHeight, v); }
+    void setMaxHeight(Length v) { SET_VAR(m_box, m_maxHeight, v); }
+
+    DraggableRegionMode getDraggableRegionMode() const { return rareNonInheritedData->m_draggableRegionMode; }
+    void setDraggableRegionMode(DraggableRegionMode v) { SET_VAR(rareNonInheritedData, m_draggableRegionMode, v); }
+
+    void resetBorder() { resetBorderImage(); resetBorderTop(); resetBorderRight(); resetBorderBottom(); resetBorderLeft(); resetBorderRadius(); }
+    void resetBorderTop() { SET_VAR(surround, border.m_top, BorderValue()); }
+    void resetBorderRight() { SET_VAR(surround, border.m_right, BorderValue()); }
+    void resetBorderBottom() { SET_VAR(surround, border.m_bottom, BorderValue()); }
+    void resetBorderLeft() { SET_VAR(surround, border.m_left, BorderValue()); }
+    void resetBorderImage() { SET_VAR(surround, border.m_image, NinePieceImage()); }
+    void resetBorderRadius() { resetBorderTopLeftRadius(); resetBorderTopRightRadius(); resetBorderBottomLeftRadius(); resetBorderBottomRightRadius(); }
+    void resetBorderTopLeftRadius() { SET_VAR(surround, border.m_topLeft, initialBorderRadius()); }
+    void resetBorderTopRightRadius() { SET_VAR(surround, border.m_topRight, initialBorderRadius()); }
+    void resetBorderBottomLeftRadius() { SET_VAR(surround, border.m_bottomLeft, initialBorderRadius()); }
+    void resetBorderBottomRightRadius() { SET_VAR(surround, border.m_bottomRight, initialBorderRadius()); }
+
+    void setBackgroundColor(const Color& v) { SET_VAR(m_background, m_color, v); }
+
+    void setBackgroundXPosition(Length length) { SET_VAR(m_background, m_background.m_xPosition, length); }
+    void setBackgroundYPosition(Length length) { SET_VAR(m_background, m_background.m_yPosition, length); }
+    void setBackgroundSize(EFillSizeType b) { SET_VAR(m_background, m_background.m_sizeType, b); }
+    void setBackgroundSizeLength(LengthSize s) { SET_VAR(m_background, m_background.m_sizeLength, s); }
+    
+    void setBorderImage(const NinePieceImage& b) { SET_VAR(surround, border.m_image, b); }
+    void setBorderImageSource(PassRefPtr<StyleImage>);
+    void setBorderImageSlices(LengthBox);
+    void setBorderImageWidth(LengthBox);
+    void setBorderImageOutset(LengthBox);
+
+    void setBorderTopLeftRadius(LengthSize s) { SET_VAR(surround, border.m_topLeft, s); }
+    void setBorderTopRightRadius(LengthSize s) { SET_VAR(surround, border.m_topRight, s); }
+    void setBorderBottomLeftRadius(LengthSize s) { SET_VAR(surround, border.m_bottomLeft, s); }
+    void setBorderBottomRightRadius(LengthSize s) { SET_VAR(surround, border.m_bottomRight, s); }
+
+    void setBorderRadius(LengthSize s)
+    {
+        setBorderTopLeftRadius(s);
+        setBorderTopRightRadius(s);
+        setBorderBottomLeftRadius(s);
+        setBorderBottomRightRadius(s);
+    }
+    void setBorderRadius(const IntSize& s)
+    {
+        setBorderRadius(LengthSize(Length(s.width(), Fixed), Length(s.height(), Fixed)));
+    }
+    
+    RoundedRect getRoundedBorderFor(const LayoutRect& borderRect, RenderView* = 0, bool includeLogicalLeftEdge = true, bool includeLogicalRightEdge = true) const;
+    RoundedRect getRoundedInnerBorderFor(const LayoutRect& borderRect, bool includeLogicalLeftEdge = true, bool includeLogicalRightEdge = true) const;
+
+    RoundedRect getRoundedInnerBorderFor(const LayoutRect& borderRect,
+        int topWidth, int bottomWidth, int leftWidth, int rightWidth, bool includeLogicalLeftEdge, bool includeLogicalRightEdge) const;
+
+    void setBorderLeftWidth(unsigned v) { SET_VAR(surround, border.m_left.m_width, v); }
+    void setBorderLeftStyle(EBorderStyle v) { SET_VAR(surround, border.m_left.m_style, v); }
+    void setBorderLeftColor(const Color& v) { SET_BORDERVALUE_COLOR(surround, border.m_left, v); }
+    void setBorderRightWidth(unsigned v) { SET_VAR(surround, border.m_right.m_width, v); }
+    void setBorderRightStyle(EBorderStyle v) { SET_VAR(surround, border.m_right.m_style, v); }
+    void setBorderRightColor(const Color& v) { SET_BORDERVALUE_COLOR(surround, border.m_right, v); }
+    void setBorderTopWidth(unsigned v) { SET_VAR(surround, border.m_top.m_width, v); }
+    void setBorderTopStyle(EBorderStyle v) { SET_VAR(surround, border.m_top.m_style, v); }
+    void setBorderTopColor(const Color& v) { SET_BORDERVALUE_COLOR(surround, border.m_top, v); }
+    void setBorderBottomWidth(unsigned v) { SET_VAR(surround, border.m_bottom.m_width, v); }
+    void setBorderBottomStyle(EBorderStyle v) { SET_VAR(surround, border.m_bottom.m_style, v); }
+    void setBorderBottomColor(const Color& v) { SET_BORDERVALUE_COLOR(surround, border.m_bottom, v); }
+
+    void setOutlineWidth(unsigned short v) { SET_VAR(m_background, m_outline.m_width, v); }
+    void setOutlineStyleIsAuto(OutlineIsAuto isAuto) { SET_VAR(m_background, m_outline.m_isAuto, isAuto); }
+    void setOutlineStyle(EBorderStyle v) { SET_VAR(m_background, m_outline.m_style, v); }
+    void setOutlineColor(const Color& v) { SET_BORDERVALUE_COLOR(m_background, m_outline, 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 length) { setVerticalAlign(LENGTH); SET_VAR(m_box, m_verticalAlign, length); }
+
+    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 setClip(LengthBox box) { SET_VAR(visual, clip, box); }
+
+    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&);
+    // Only used for blending font sizes when animating, for MathML anonymous blocks, and for text autosizing.
+    void setFontSize(float);
+
+    void setTextAutosizingMultiplier(float v)
+    {
+        SET_VAR(visual, m_textAutosizingMultiplier, v);
+        setFontSize(fontDescription().specifiedSize());
+    }
+
+    void setColor(const Color&);
+    void setTextIndent(Length v) { SET_VAR(rareInheritedData, indent, v); }
+#if ENABLE(CSS3_TEXT)
+    void setTextIndentLine(TextIndentLine v) { SET_VAR(rareInheritedData, m_textIndentLine, v); }
+#endif
+    void setTextAlign(ETextAlign v) { inherited_flags._text_align = v; }
+    void setTextTransform(ETextTransform v) { inherited_flags._text_transform = v; }
+    void addToTextDecorationsInEffect(ETextDecoration v) { inherited_flags._text_decorations |= v; }
+    void setTextDecorationsInEffect(ETextDecoration v) { inherited_flags._text_decorations = v; }
+    void setTextDecoration(ETextDecoration v) { SET_VAR(visual, textDecoration, v); }
+#if ENABLE(CSS3_TEXT)
+    void setTextDecorationStyle(TextDecorationStyle v) { SET_VAR(rareNonInheritedData, m_textDecorationStyle, v); }
+    void setTextAlignLast(TextAlignLast v) { SET_VAR(rareInheritedData, m_textAlignLast, v); }
+    void setTextUnderlinePosition(TextUnderlinePosition v) { SET_VAR(rareInheritedData, m_textUnderlinePosition, v); }
+#endif // CSS3_TEXT
+    void setDirection(TextDirection v) { inherited_flags._direction = v; }
+    void setLineHeight(Length specifiedLineHeight);
+    bool setZoom(float);
+    void setZoomWithoutReturnValue(float f) { setZoom(f); }
+    bool setEffectiveZoom(float);
+
+    void setImageRendering(EImageRendering v) { SET_VAR(rareInheritedData, m_imageRendering, v); }
+
+    void setWhiteSpace(EWhiteSpace v) { inherited_flags._white_space = v; }
+
+    void setWordSpacing(int);
+    void setLetterSpacing(int);
+
+    void clearBackgroundLayers() { m_background.access()->m_background = FillLayer(BackgroundFillLayer); }
+    void inheritBackgroundLayers(const FillLayer& parent) { m_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 setMaskImage(PassRefPtr<StyleImage> v) { rareNonInheritedData.access()->m_mask.setImage(v); }
+
+    void setMaskBoxImage(const NinePieceImage& b) { SET_VAR(rareNonInheritedData, m_maskBoxImage, b); }
+    void setMaskBoxImageSource(PassRefPtr<StyleImage> v) { rareNonInheritedData.access()->m_maskBoxImage.setImage(v); }
+    void setMaskXPosition(Length length) { SET_VAR(rareNonInheritedData, m_mask.m_xPosition, length); }
+    void setMaskYPosition(Length length) { SET_VAR(rareNonInheritedData, m_mask.m_yPosition, length); }
+    void setMaskSize(LengthSize s) { SET_VAR(rareNonInheritedData, m_mask.m_sizeLength, s); }
+
+    void setBorderCollapse(EBorderCollapse collapse) { inherited_flags._border_collapse = collapse; }
+    void setHorizontalBorderSpacing(short);
+    void setVerticalBorderSpacing(short);
+    void setEmptyCells(EEmptyCell v) { inherited_flags._empty_cells = v; }
+    void setCaptionSide(ECaptionSide v) { inherited_flags._caption_side = v; }
+
+    void setHasAspectRatio(bool b) { SET_VAR(rareNonInheritedData, m_hasAspectRatio, b); }
+    void setAspectRatioDenominator(float v) { SET_VAR(rareNonInheritedData, m_aspectRatioDenominator, v); }
+    void setAspectRatioNumerator(float v) { SET_VAR(rareNonInheritedData, m_aspectRatioNumerator, v); }
+
+    void setListStyleType(EListStyleType v) { inherited_flags._list_style_type = v; }
+    void setListStyleImage(PassRefPtr<StyleImage>);
+    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 setMarginStart(Length);
+    void setMarginEnd(Length);
+
+    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(PassRefPtr<StyleImage>, const IntPoint& hotSpot = IntPoint());
+    void setCursorList(PassRefPtr<CursorList>);
+    void clearCursorList();
+
+    void setInsideLink(EInsideLink insideLink) { inherited_flags._insideLink = insideLink; }
+    void setIsLink(bool b) { noninherited_flags.setIsLink(b); }
+
+    PrintColorAdjust printColorAdjust() const { return static_cast<PrintColorAdjust>(inherited_flags.m_printColorAdjust); }
+    void setPrintColorAdjust(PrintColorAdjust value) { inherited_flags.m_printColorAdjust = value; }
+
+    bool hasAutoZIndex() const { return m_box->hasAutoZIndex(); }
+    void setHasAutoZIndex() { SET_VAR(m_box, m_hasAutoZIndex, true); SET_VAR(m_box, m_zIndex, 0); }
+    int zIndex() const { return m_box->zIndex(); }
+    void setZIndex(int v) { SET_VAR(m_box, m_hasAutoZIndex, false); SET_VAR(m_box, m_zIndex, v); }
+
+    void setHasAutoWidows() { SET_VAR(rareInheritedData, m_hasAutoWidows, true); SET_VAR(rareInheritedData, widows, initialWidows()); }
+    void setWidows(short w) { SET_VAR(rareInheritedData, m_hasAutoWidows, false); SET_VAR(rareInheritedData, widows, w); }
+
+    void setHasAutoOrphans() { SET_VAR(rareInheritedData, m_hasAutoOrphans, true); SET_VAR(rareInheritedData, orphans, initialOrphans()); }
+    void setOrphans(short o) { SET_VAR(rareInheritedData, m_hasAutoOrphans, false); SET_VAR(rareInheritedData, orphans, o); }
+
+    // For valid values of page-break-inside see http://www.w3.org/TR/CSS21/page.html#page-break-props
+    void setPageBreakInside(EPageBreak b) { ASSERT(b == PBAUTO || b == PBAVOID); noninherited_flags._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
+    void setOutlineOffset(int v) { SET_VAR(m_background, m_outline.m_offset, v); }
+    void setTextShadow(PassOwnPtr<ShadowData>, 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 setColorSpace(ColorSpace space) { SET_VAR(rareInheritedData, colorSpace, space); }
+    void setOpacity(float f) { float v = clampTo<float>(f, 0, 1); SET_VAR(rareNonInheritedData, opacity, v); }
+    void setAppearance(ControlPart a) { SET_VAR(rareNonInheritedData, m_appearance, a); }
+    // For valid values of box-align see http://www.w3.org/TR/2009/WD-css3-flexbox-20090723/#alignment
+    void setBoxAlign(EBoxAlignment a) { SET_VAR(rareNonInheritedData.access()->m_deprecatedFlexibleBox, align, a); }
+    void setBoxDecorationBreak(EBoxDecorationBreak b) { SET_VAR(m_box, m_boxDecorationBreak, b); }
+    void setBoxDirection(EBoxDirection d) { inherited_flags._box_direction = d; }
+    void setBoxFlex(float f) { SET_VAR(rareNonInheritedData.access()->m_deprecatedFlexibleBox, flex, f); }
+    void setBoxFlexGroup(unsigned int fg) { SET_VAR(rareNonInheritedData.access()->m_deprecatedFlexibleBox, flex_group, fg); }
+    void setBoxLines(EBoxLines l) { SET_VAR(rareNonInheritedData.access()->m_deprecatedFlexibleBox, lines, l); }
+    void setBoxOrdinalGroup(unsigned int og) { SET_VAR(rareNonInheritedData.access()->m_deprecatedFlexibleBox, ordinal_group, og); }
+    void setBoxOrient(EBoxOrient o) { SET_VAR(rareNonInheritedData.access()->m_deprecatedFlexibleBox, orient, o); }
+    void setBoxPack(EBoxPack p) { SET_VAR(rareNonInheritedData.access()->m_deprecatedFlexibleBox, pack, p); }
+    void setBoxShadow(PassOwnPtr<ShadowData>, bool add = false);
+    void setBoxReflect(PassRefPtr<StyleReflection> reflect) { if (rareNonInheritedData->m_boxReflect != reflect) rareNonInheritedData.access()->m_boxReflect = reflect; }
+    void setBoxSizing(EBoxSizing s) { SET_VAR(m_box, m_boxSizing, s); }
+    void setFlexGrow(float f) { SET_VAR(rareNonInheritedData.access()->m_flexibleBox, m_flexGrow, f); }
+    void setFlexShrink(float f) { SET_VAR(rareNonInheritedData.access()->m_flexibleBox, m_flexShrink, f); }
+    void setFlexBasis(Length length) { SET_VAR(rareNonInheritedData.access()->m_flexibleBox, m_flexBasis, length); }
+    void setOrder(int o) { SET_VAR(rareNonInheritedData, m_order, o); }
+    void setAlignContent(EAlignContent p) { SET_VAR(rareNonInheritedData, m_alignContent, p); }
+    void setAlignItems(EAlignItems a) { SET_VAR(rareNonInheritedData, m_alignItems, a); }
+    void setAlignSelf(EAlignItems a) { SET_VAR(rareNonInheritedData, m_alignSelf, a); }
+    void setFlexDirection(EFlexDirection direction) { SET_VAR(rareNonInheritedData.access()->m_flexibleBox, m_flexDirection, direction); }
+    void setFlexWrap(EFlexWrap w) { SET_VAR(rareNonInheritedData.access()->m_flexibleBox, m_flexWrap, w); }
+    void setJustifyContent(EJustifyContent p) { SET_VAR(rareNonInheritedData, m_justifyContent, p); }
+    void setGridAutoColumns(const GridTrackSize& length) { SET_VAR(rareNonInheritedData.access()->m_grid, m_gridAutoColumns, length); }
+    void setGridAutoRows(const GridTrackSize& length) { SET_VAR(rareNonInheritedData.access()->m_grid, m_gridAutoRows, length); }
+    void setGridColumns(const Vector<GridTrackSize>& lengths) { SET_VAR(rareNonInheritedData.access()->m_grid, m_gridColumns, lengths); }
+    void setGridRows(const Vector<GridTrackSize>& lengths) { SET_VAR(rareNonInheritedData.access()->m_grid, m_gridRows, lengths); }
+    void setGridAutoFlow(GridAutoFlow flow) { SET_VAR(rareNonInheritedData.access()->m_grid, m_gridAutoFlow, flow); }
+
+    void setGridStart(const GridPosition& startPosition) { SET_VAR(rareNonInheritedData.access()->m_gridItem, m_gridStart, startPosition); }
+    void setGridEnd(const GridPosition& endPosition) { SET_VAR(rareNonInheritedData.access()->m_gridItem, m_gridEnd, endPosition); }
+    void setGridBefore(const GridPosition& beforePosition) { SET_VAR(rareNonInheritedData.access()->m_gridItem, m_gridBefore, beforePosition); }
+    void setGridAfter(const GridPosition& afterPosition) { SET_VAR(rareNonInheritedData.access()->m_gridItem, m_gridAfter, afterPosition); }
+
+    void setMarqueeIncrement(Length f) { SET_VAR(rareNonInheritedData.access()->m_marquee, increment, f); }
+    void setMarqueeSpeed(int f) { SET_VAR(rareNonInheritedData.access()->m_marquee, speed, f); }
+    void setMarqueeDirection(EMarqueeDirection d) { SET_VAR(rareNonInheritedData.access()->m_marquee, direction, d); }
+    void setMarqueeBehavior(EMarqueeBehavior b) { SET_VAR(rareNonInheritedData.access()->m_marquee, behavior, b); }
+    void setMarqueeLoopCount(int i) { SET_VAR(rareNonInheritedData.access()->m_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(TextOverflow overflow) { SET_VAR(rareNonInheritedData, textOverflow, overflow); }
+    void setMarginBeforeCollapse(EMarginCollapse c) { SET_VAR(rareNonInheritedData, marginBeforeCollapse, c); }
+    void setMarginAfterCollapse(EMarginCollapse c) { SET_VAR(rareNonInheritedData, marginAfterCollapse, c); }
+    void setWordBreak(EWordBreak b) { SET_VAR(rareInheritedData, wordBreak, b); }
+    void setOverflowWrap(EOverflowWrap b) { SET_VAR(rareInheritedData, overflowWrap, b); }
+    void setLineBreak(LineBreak b) { SET_VAR(rareInheritedData, lineBreak, b); }
+    void setHighlight(const AtomicString& h) { SET_VAR(rareInheritedData, highlight, h); }
+    void setHyphens(Hyphens h) { SET_VAR(rareInheritedData, hyphens, h); }
+    void setHyphenationLimitBefore(short limit) { SET_VAR(rareInheritedData, hyphenationLimitBefore, limit); }
+    void setHyphenationLimitAfter(short limit) { SET_VAR(rareInheritedData, hyphenationLimitAfter, limit); }
+    void setHyphenationLimitLines(short limit) { SET_VAR(rareInheritedData, hyphenationLimitLines, limit); }
+    void setHyphenationString(const AtomicString& h) { SET_VAR(rareInheritedData, hyphenationString, h); }
+    void setLocale(const AtomicString& locale) { SET_VAR(rareInheritedData, locale, locale); }
+    void setBorderFit(EBorderFit b) { SET_VAR(rareNonInheritedData, m_borderFit, b); }
+    void setResize(EResize r) { SET_VAR(rareInheritedData, resize, r); }
+    void setColumnAxis(ColumnAxis axis) { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_axis, axis); }
+    void setColumnProgression(ColumnProgression progression) { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_progression, progression); }
+    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_BORDERVALUE_COLOR(rareNonInheritedData.access()->m_multiCol, m_rule, 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.m_width, w); }
+    void resetColumnRule() { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_rule, BorderValue()); }
+    void setColumnSpan(ColumnSpan columnSpan) { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_columnSpan, columnSpan); }
+    void setColumnBreakBefore(EPageBreak p) { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_breakBefore, p); }
+    // For valid values of column-break-inside see http://www.w3.org/TR/css3-multicol/#break-before-break-after-break-inside
+    void setColumnBreakInside(EPageBreak p) { ASSERT(p == PBAUTO || p == PBAVOID); SET_VAR(rareNonInheritedData.access()->m_multiCol, m_breakInside, p); }
+    void setColumnBreakAfter(EPageBreak p) { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_breakAfter, p); }
+    void setRegionBreakBefore(EPageBreak p) { SET_VAR(rareNonInheritedData, m_regionBreakBefore, p); }
+    void setRegionBreakInside(EPageBreak p) { ASSERT(p == PBAUTO || p == PBAVOID); SET_VAR(rareNonInheritedData, m_regionBreakInside, p); }
+    void setRegionBreakAfter(EPageBreak p) { SET_VAR(rareNonInheritedData, m_regionBreakAfter, p); }
+    void inheritColumnPropertiesFrom(RenderStyle* parent) { rareNonInheritedData.access()->m_multiCol = parent->rareNonInheritedData->m_multiCol; }
+    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); }
+    void setTransformOriginZ(float f) { SET_VAR(rareNonInheritedData.access()->m_transform, m_z, f); }
+    void setSpeak(ESpeak s) { SET_VAR(rareInheritedData, speak, s); }
+    void setTextCombine(TextCombine v) { SET_VAR(rareNonInheritedData, m_textCombine, v); }
+#if ENABLE(CSS3_TEXT)
+    void setTextDecorationColor(const Color& c) { SET_VAR(rareNonInheritedData, m_textDecorationColor, c); }
+#endif // CSS3_TEXT
+    void setTextEmphasisColor(const Color& c) { SET_VAR(rareInheritedData, textEmphasisColor, c); }
+    void setTextEmphasisFill(TextEmphasisFill fill) { SET_VAR(rareInheritedData, textEmphasisFill, fill); }
+    void setTextEmphasisMark(TextEmphasisMark mark) { SET_VAR(rareInheritedData, textEmphasisMark, mark); }
+    void setTextEmphasisCustomMark(const AtomicString& mark) { SET_VAR(rareInheritedData, textEmphasisCustomMark, mark); }
+    void setTextEmphasisPosition(TextEmphasisPosition position) { SET_VAR(rareInheritedData, textEmphasisPosition, position); }
+    bool setTextOrientation(TextOrientation);
+
+    void setRubyPosition(RubyPosition position) { SET_VAR(rareInheritedData, m_rubyPosition, position); }
+
+    void setFilter(const FilterOperations& ops) { SET_VAR(rareNonInheritedData.access()->m_filter, m_operations, ops); }
+
+    void setTabSize(unsigned size) { SET_VAR(rareInheritedData, m_tabSize, size); }
+
+    // End CSS3 Setters
+
+    void setLineGrid(const AtomicString& lineGrid) { SET_VAR(rareInheritedData, m_lineGrid, lineGrid); }
+    void setLineSnap(LineSnap lineSnap) { SET_VAR(rareInheritedData, m_lineSnap, lineSnap); }
+    void setLineAlign(LineAlign lineAlign) { SET_VAR(rareInheritedData, m_lineAlign, lineAlign); }
+
+    void setFlowThread(const AtomicString& flowThread) { SET_VAR(rareNonInheritedData, m_flowThread, flowThread); }
+    void setRegionThread(const AtomicString& regionThread) { SET_VAR(rareNonInheritedData, m_regionThread, regionThread); }
+    void setRegionOverflow(RegionOverflow regionOverflow) { SET_VAR(rareNonInheritedData, m_regionOverflow, regionOverflow); }
+
+    void setWrapFlow(WrapFlow wrapFlow) { SET_VAR(rareNonInheritedData, m_wrapFlow, wrapFlow); }
+    void setWrapThrough(WrapThrough wrapThrough) { SET_VAR(rareNonInheritedData, m_wrapThrough, wrapThrough); }
+
+    // Apple-specific property setters
+    void setPointerEvents(EPointerEvents p) { inherited_flags._pointerEvents = p; }
+
+    void clearAnimations()
+    {
+        rareNonInheritedData.access()->m_animations.clear();
+    }
+
+    void clearTransitions()
+    {
+        rareNonInheritedData.access()->m_transitions.clear();
+    }
+
+    void inheritAnimations(const CSSAnimationDataList* parent) { rareNonInheritedData.access()->m_animations = parent ? adoptPtr(new CSSAnimationDataList(*parent)) : nullptr; }
+    void inheritTransitions(const CSSAnimationDataList* parent) { rareNonInheritedData.access()->m_transitions = parent ? adoptPtr(new CSSAnimationDataList(*parent)) : nullptr; }
+    void adjustAnimations();
+    void adjustTransitions();
+
+    void setTransformStyle3D(ETransformStyle3D b) { SET_VAR(rareNonInheritedData, m_transformStyle3D, b); }
+    void setBackfaceVisibility(EBackfaceVisibility b) { SET_VAR(rareNonInheritedData, m_backfaceVisibility, b); }
+    void setPerspective(float p) { SET_VAR(rareNonInheritedData, m_perspective, p); }
+    void setPerspectiveOriginX(Length l) { SET_VAR(rareNonInheritedData, m_perspectiveOriginX, l); }
+    void setPerspectiveOriginY(Length l) { SET_VAR(rareNonInheritedData, m_perspectiveOriginY, l); }
+    void setPageSize(LengthSize s) { SET_VAR(rareNonInheritedData, m_pageSize, s); }
+    void setPageSizeType(PageSizeType t) { SET_VAR(rareNonInheritedData, m_pageSizeType, t); }
+    void resetPageSizeType() { SET_VAR(rareNonInheritedData, m_pageSizeType, PAGE_SIZE_AUTO); }
+
+    void setIsRunningAcceleratedAnimation(bool b = true) { SET_VAR(rareNonInheritedData, m_runningAcceleratedAnimation, b); }
+
+    void setLineBoxContain(LineBoxContain c) { SET_VAR(rareInheritedData, m_lineBoxContain, c); }
+    void setLineClamp(LineClampValue c) { SET_VAR(rareNonInheritedData, lineClamp, c); }
+    void setTapHighlightColor(const Color& c) { SET_VAR(rareInheritedData, tapHighlightColor, c); }
+#if ENABLE(ACCELERATED_OVERFLOW_SCROLLING)
+    void setUseTouchOverflowScrolling(bool v) { SET_VAR(rareInheritedData, useTouchOverflowScrolling, v); }
+#endif
+    void setTextSecurity(ETextSecurity aTextSecurity) { SET_VAR(rareInheritedData, textSecurity, aTextSecurity); }
+
+#if ENABLE(SVG)
+    const SVGRenderStyle* svgStyle() const { return m_svgStyle.get(); }
+    SVGRenderStyle* accessSVGStyle() { return m_svgStyle.access(); }
+
+    const SVGPaint::SVGPaintType& fillPaintType() const { return svgStyle()->fillPaintType(); }
+    Color fillPaintColor() const { return svgStyle()->fillPaintColor(); }
+    void setFillPaintColor(const Color& c) { accessSVGStyle()->setFillPaint(SVGPaint::SVG_PAINTTYPE_RGBCOLOR, c, ""); }
+    float fillOpacity() const { return svgStyle()->fillOpacity(); }
+    void setFillOpacity(float f) { accessSVGStyle()->setFillOpacity(f); }
+
+    const SVGPaint::SVGPaintType& strokePaintType() const { return svgStyle()->strokePaintType(); }
+    Color strokePaintColor() const { return svgStyle()->strokePaintColor(); }
+    void setStrokePaintColor(const Color& c) { accessSVGStyle()->setStrokePaint(SVGPaint::SVG_PAINTTYPE_RGBCOLOR, c, ""); }
+    float strokeOpacity() const { return svgStyle()->strokeOpacity(); }
+    void setStrokeOpacity(float f) { accessSVGStyle()->setStrokeOpacity(f); }
+    SVGLength strokeWidth() const { return svgStyle()->strokeWidth(); }
+    void setStrokeWidth(SVGLength w) { accessSVGStyle()->setStrokeWidth(w); }
+    SVGLength strokeDashOffset() const { return svgStyle()->strokeDashOffset(); }
+    void setStrokeDashOffset(SVGLength d) { accessSVGStyle()->setStrokeDashOffset(d); }
+    float strokeMiterLimit() const { return svgStyle()->strokeMiterLimit(); }
+    void setStrokeMiterLimit(float f) { accessSVGStyle()->setStrokeMiterLimit(f); }
+
+    float floodOpacity() const { return svgStyle()->floodOpacity(); }
+    void setFloodOpacity(float f) { accessSVGStyle()->setFloodOpacity(f); }
+
+    float stopOpacity() const { return svgStyle()->stopOpacity(); }
+    void setStopOpacity(float f) { accessSVGStyle()->setStopOpacity(f); }
+
+    void setStopColor(const Color& c) { accessSVGStyle()->setStopColor(c); }
+    void setFloodColor(const Color& c) { accessSVGStyle()->setFloodColor(c); }
+    void setLightingColor(const Color& c) { accessSVGStyle()->setLightingColor(c); }
+
+    SVGLength baselineShiftValue() const { return svgStyle()->baselineShiftValue(); }
+    void setBaselineShiftValue(SVGLength s) { accessSVGStyle()->setBaselineShiftValue(s); }
+    SVGLength kerning() const { return svgStyle()->kerning(); }
+    void setKerning(SVGLength k) { accessSVGStyle()->setKerning(k); }
+#endif
+
+    void setShapeInside(PassRefPtr<ExclusionShapeValue> value)
+    {
+        if (rareNonInheritedData->m_shapeInside == value)
+            return;
+        rareNonInheritedData.access()->m_shapeInside = value;
+    }
+    ExclusionShapeValue* shapeInside() const { return rareNonInheritedData->m_shapeInside.get(); }
+    ExclusionShapeValue* resolvedShapeInside() const
+    {
+        ExclusionShapeValue* shapeInside = this->shapeInside();
+        if (shapeInside && shapeInside->type() == ExclusionShapeValue::OUTSIDE)
+            return shapeOutside();
+        return shapeInside;
+    }
+
+    void setShapeOutside(PassRefPtr<ExclusionShapeValue> value)
+    {
+        if (rareNonInheritedData->m_shapeOutside == value)
+            return;
+        rareNonInheritedData.access()->m_shapeOutside = value;
+    }
+    ExclusionShapeValue* shapeOutside() const { return rareNonInheritedData->m_shapeOutside.get(); }
+
+    static ExclusionShapeValue* initialShapeInside();
+    static ExclusionShapeValue* initialShapeOutside() { return 0; }
+
+    void setClipPath(PassRefPtr<ClipPathOperation> operation)
+    {
+        if (rareNonInheritedData->m_clipPath != operation)
+            rareNonInheritedData.access()->m_clipPath = operation;
+    }
+    ClipPathOperation* clipPath() const { return rareNonInheritedData->m_clipPath.get(); }
+
+    static ClipPathOperation* initialClipPath() { return 0; }
+
+    Length shapePadding() const { return rareNonInheritedData->m_shapePadding; }
+    void setShapePadding(Length shapePadding) { SET_VAR(rareNonInheritedData, m_shapePadding, shapePadding); }
+    static Length initialShapePadding() { return Length(0, Fixed); }
+
+    Length shapeMargin() const { return rareNonInheritedData->m_shapeMargin; }
+    void setShapeMargin(Length shapeMargin) { SET_VAR(rareNonInheritedData, m_shapeMargin, shapeMargin); }
+    static Length initialShapeMargin() { return Length(0, Fixed); }
+
+    bool hasContent() const { return contentData(); }
+    const ContentData* contentData() const { return rareNonInheritedData->m_content.get(); }
+    bool contentDataEquivalent(const RenderStyle* otherStyle) const { return const_cast<RenderStyle*>(this)->rareNonInheritedData->contentDataEquivalent(*const_cast<RenderStyle*>(otherStyle)->rareNonInheritedData); }
+    void clearContent();
+    void setContent(const String&, bool add = false);
+    void setContent(PassRefPtr<StyleImage>, bool add = false);
+    void setContent(PassOwnPtr<CounterContent>, bool add = false);
+    void setContent(QuoteType, bool add = false);
+
+    const CounterDirectiveMap* counterDirectives() const;
+    CounterDirectiveMap& accessCounterDirectives();
+    const CounterDirectives getCounterDirectives(const AtomicString& identifier) const;
+
+    QuotesData* quotes() const { return rareInheritedData->quotes.get(); }
+    void setQuotes(PassRefPtr<QuotesData>);
+
+    const AtomicString& hyphenString() const;
+
+    bool inheritedNotEqual(const RenderStyle*) const;
+    bool inheritedDataShared(const RenderStyle*) const;
+
+    StyleDifference diff(const RenderStyle*, unsigned& changedContextSensitiveProperties) const;
+
+    bool isDisplayReplacedType() const { return isDisplayReplacedType(display()); }
+    bool isDisplayInlineType() const { return isDisplayInlineType(display()); }
+    bool isOriginalDisplayInlineType() const { return isDisplayInlineType(originalDisplay()); }
+    bool isDisplayRegionType() const
+    {
+        return display() == BLOCK || display() == INLINE_BLOCK
+            || display() == TABLE_CELL || display() == TABLE_CAPTION
+            || display() == LIST_ITEM;
+    }
+
+    bool setWritingMode(WritingMode v)
+    {
+        if (v == writingMode())
+            return false;
+
+        inherited_flags.m_writingMode = v;
+        return true;
+    }
+
+    // A unique style is one that has matches something that makes it impossible to share.
+    bool unique() const { return noninherited_flags.unique; }
+    void setUnique() { noninherited_flags.unique = true; }
+
+    bool emptyState() const { return noninherited_flags.emptyState; }
+    void setEmptyState(bool b) { setUnique(); noninherited_flags.emptyState = b; }
+    bool firstChildState() const { return noninherited_flags.firstChildState; }
+    void setFirstChildState() { setUnique(); noninherited_flags.firstChildState = true; }
+    bool lastChildState() const { return noninherited_flags.lastChildState; }
+    void setLastChildState() { setUnique(); noninherited_flags.lastChildState = true; }
+
+    Color visitedDependentColor(int colorProperty) const;
+
+    void setHasExplicitlyInheritedProperties() { noninherited_flags.explicitInheritance = true; }
+    bool hasExplicitlyInheritedProperties() const { return noninherited_flags.explicitInheritance; }
+
+    void reportMemoryUsage(MemoryObjectInfo*) const;
+    
+    // Initial values for all the properties
+    static EBorderCollapse initialBorderCollapse() { return BSEPARATE; }
+    static EBorderStyle initialBorderStyle() { return BNONE; }
+    static OutlineIsAuto initialOutlineStyleIsAuto() { return AUTO_OFF; }
+    static NinePieceImage initialNinePieceImage() { return NinePieceImage(); }
+    static LengthSize initialBorderRadius() { return LengthSize(Length(0, Fixed), Length(0, Fixed)); }
+    static ECaptionSide initialCaptionSide() { return CAPTOP; }
+    static EClear initialClear() { return CNONE; }
+    static ColorSpace initialColorSpace() { return ColorSpaceDeviceRGB; }
+    static ColumnAxis initialColumnAxis() { return AutoColumnAxis; }
+    static ColumnProgression initialColumnProgression() { return NormalColumnProgression; }
+    static TextDirection initialDirection() { return LTR; }
+    static WritingMode initialWritingMode() { return TopToBottomWritingMode; }
+    static TextCombine initialTextCombine() { return TextCombineNone; }
+    static TextOrientation initialTextOrientation() { return TextOrientationVerticalRight; }
+    static EDisplay initialDisplay() { return INLINE; }
+    static EEmptyCell initialEmptyCells() { return SHOW; }
+    static EFloat initialFloating() { return NoFloat; }
+    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 initialBorderWidth() { return 3; }
+    static unsigned short initialColumnRuleWidth() { return 3; }
+    static unsigned short initialOutlineWidth() { return 3; }
+    static int initialLetterWordSpacing() { return 0; }
+    static Length initialSize() { return Length(); }
+    static Length initialMinSize() { return Length(Fixed); }
+    static Length initialMaxSize() { return Length(Undefined); }
+    static Length initialOffset() { return Length(); }
+    static Length initialMargin() { return Length(Fixed); }
+    static Length initialPadding() { return Length(Fixed); }
+    static Length initialTextIndent() { return Length(Fixed); }
+#if ENABLE(CSS3_TEXT)
+    static TextIndentLine initialTextIndentLine() { return TextIndentFirstLine; }
+#endif
+    static EVerticalAlign initialVerticalAlign() { return BASELINE; }
+    static short initialWidows() { return 2; }
+    static short initialOrphans() { return 2; }
+    static Length initialLineHeight() { return Length(-100.0, Percent); }
+    static ETextAlign initialTextAlign() { return TASTART; }
+    static ETextDecoration initialTextDecoration() { return TDNONE; }
+#if ENABLE(CSS3_TEXT)
+    static TextDecorationStyle initialTextDecorationStyle() { return TextDecorationStyleSolid; }
+    static TextAlignLast initialTextAlignLast() { return TextAlignLastAuto; }
+    static TextUnderlinePosition initialTextUnderlinePosition() { return TextUnderlinePositionAuto; }
+#endif // CSS3_TEXT
+    static float initialZoom() { return 1.0f; }
+    static int initialOutlineOffset() { return 0; }
+    static float initialOpacity() { return 1.0f; }
+    static EBoxAlignment initialBoxAlign() { return BSTRETCH; }
+    static EBoxDecorationBreak initialBoxDecorationBreak() { return DSLICE; }
+    static EBoxDirection initialBoxDirection() { return BNORMAL; }
+    static EBoxLines initialBoxLines() { return SINGLE; }
+    static EBoxOrient initialBoxOrient() { return HORIZONTAL; }
+    static EBoxPack initialBoxPack() { return Start; }
+    static float initialBoxFlex() { return 0.0f; }
+    static unsigned int initialBoxFlexGroup() { return 1; }
+    static unsigned int initialBoxOrdinalGroup() { return 1; }
+    static EBoxSizing initialBoxSizing() { return CONTENT_BOX; }
+    static StyleReflection* initialBoxReflect() { return 0; }
+    static float initialFlexGrow() { return 0; }
+    static float initialFlexShrink() { return 1; }
+    static Length initialFlexBasis() { return Length(Auto); }
+    static int initialOrder() { return 0; }
+    static EAlignContent initialAlignContent() { return AlignContentStretch; }
+    static EAlignItems initialAlignItems() { return AlignStretch; }
+    static EAlignItems initialAlignSelf() { return AlignAuto; }
+    static EFlexDirection initialFlexDirection() { return FlowRow; }
+    static EFlexWrap initialFlexWrap() { return FlexNoWrap; }
+    static EJustifyContent initialJustifyContent() { return JustifyFlexStart; }
+    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 TextOverflow initialTextOverflow() { return TextOverflowClip; }
+    static EMarginCollapse initialMarginBeforeCollapse() { return MCOLLAPSE; }
+    static EMarginCollapse initialMarginAfterCollapse() { return MCOLLAPSE; }
+    static EWordBreak initialWordBreak() { return NormalWordBreak; }
+    static EOverflowWrap initialOverflowWrap() { return NormalOverflowWrap; }
+    static LineBreak initialLineBreak() { return LineBreakAuto; }
+    static const AtomicString& initialHighlight() { return nullAtom; }
+    static ESpeak initialSpeak() { return SpeakNormal; }
+    static Hyphens initialHyphens() { return HyphensManual; }
+    static short initialHyphenationLimitBefore() { return -1; }
+    static short initialHyphenationLimitAfter() { return -1; }
+    static short initialHyphenationLimitLines() { return -1; }
+    static const AtomicString& initialHyphenationString() { return nullAtom; }
+    static const AtomicString& initialLocale() { return nullAtom; }
+    static EBorderFit initialBorderFit() { return BorderFitBorder; }
+    static EResize initialResize() { return RESIZE_NONE; }
+    static ControlPart initialAppearance() { return NoControlPart; }
+    static bool initialHasAspectRatio() { return false; }
+    static float initialAspectRatioDenominator() { return 1; }
+    static float initialAspectRatioNumerator() { return 1; }
+    static Order initialRTLOrdering() { return LogicalOrder; }
+    static float initialTextStrokeWidth() { return 0; }
+    static unsigned short initialColumnCount() { return 1; }
+    static ColumnSpan initialColumnSpan() { return ColumnSpanNone; }
+    static const TransformOperations& initialTransform() { DEFINE_STATIC_LOCAL(TransformOperations, ops, ()); return ops; }
+    static Length initialTransformOriginX() { return Length(50.0, Percent); }
+    static Length initialTransformOriginY() { return Length(50.0, Percent); }
+    static EPointerEvents initialPointerEvents() { return PE_AUTO; }
+    static float initialTransformOriginZ() { return 0; }
+    static ETransformStyle3D initialTransformStyle3D() { return TransformStyle3DFlat; }
+    static EBackfaceVisibility initialBackfaceVisibility() { return BackfaceVisibilityVisible; }
+    static float initialPerspective() { return 0; }
+    static Length initialPerspectiveOriginX() { return Length(50.0, Percent); }
+    static Length initialPerspectiveOriginY() { return Length(50.0, Percent); }
+    static Color initialBackgroundColor() { return Color::transparent; }
+    static Color initialTextEmphasisColor() { return TextEmphasisFillFilled; }
+    static TextEmphasisFill initialTextEmphasisFill() { return TextEmphasisFillFilled; }
+    static TextEmphasisMark initialTextEmphasisMark() { return TextEmphasisMarkNone; }
+    static const AtomicString& initialTextEmphasisCustomMark() { return nullAtom; }
+    static TextEmphasisPosition initialTextEmphasisPosition() { return TextEmphasisPositionOver; }
+    static RubyPosition initialRubyPosition() { return RubyPositionBefore; }
+    static LineBoxContain initialLineBoxContain() { return LineBoxContainBlock | LineBoxContainInline | LineBoxContainReplaced; }
+    static ImageOrientationEnum initialImageOrientation() { return OriginTopLeft; }
+    static EImageRendering initialImageRendering() { return ImageRenderingAuto; }
+    static ImageResolutionSource initialImageResolutionSource() { return ImageResolutionSpecified; }
+    static ImageResolutionSnap initialImageResolutionSnap() { return ImageResolutionNoSnap; }
+    static float initialImageResolution() { return 1; }
+    static StyleImage* initialBorderImageSource() { return 0; }
+    static StyleImage* initialMaskBoxImageSource() { return 0; }
+    static PrintColorAdjust initialPrintColorAdjust() { return PrintColorAdjustEconomy; }
+
+    // The initial value is 'none' for grid tracks.
+    static Vector<GridTrackSize> initialGridColumns() { return Vector<GridTrackSize>(); }
+    static Vector<GridTrackSize> initialGridRows() { return Vector<GridTrackSize>(); }
+
+    static GridAutoFlow initialGridAutoFlow() { return AutoFlowNone; }
+
+    static GridTrackSize initialGridAutoColumns() { return GridTrackSize(Auto); }
+    static GridTrackSize initialGridAutoRows() { return GridTrackSize(Auto); }
+
+    // 'auto' is the default.
+    static GridPosition initialGridStart() { return GridPosition(); }
+    static GridPosition initialGridEnd() { return GridPosition(); }
+    static GridPosition initialGridBefore() { return GridPosition(); }
+    static GridPosition initialGridAfter() { return GridPosition(); }
+
+    static unsigned initialTabSize() { return 8; }
+
+    static const AtomicString& initialLineGrid() { return nullAtom; }
+    static LineSnap initialLineSnap() { return LineSnapNone; }
+    static LineAlign initialLineAlign() { return LineAlignNone; }
+
+    static const AtomicString& initialFlowThread() { return nullAtom; }
+    static const AtomicString& initialRegionThread() { return nullAtom; }
+    static RegionOverflow initialRegionOverflow() { return AutoRegionOverflow; }
+
+    static WrapFlow initialWrapFlow() { return WrapFlowAuto; }
+    static WrapThrough initialWrapThrough() { return WrapThroughWrap; }
+
+    // Keep these at the end.
+    static LineClampValue initialLineClamp() { return LineClampValue(); }
+    static ETextSecurity initialTextSecurity() { return TSNONE; }
+    static Color initialTapHighlightColor();
+#if ENABLE(ACCELERATED_OVERFLOW_SCROLLING)
+    static bool initialUseTouchOverflowScrolling() { return false; }
+#endif
+    static const FilterOperations& initialFilter() { DEFINE_STATIC_LOCAL(FilterOperations, ops, ()); return ops; }
+#if ENABLE(CSS_COMPOSITING)
+    static BlendMode initialBlendMode() { return BlendModeNormal; }
+#endif
+private:
+    void setVisitedLinkColor(const Color&);
+    void setVisitedLinkBackgroundColor(const Color& v) { SET_VAR(rareNonInheritedData, m_visitedLinkBackgroundColor, v); }
+    void setVisitedLinkBorderLeftColor(const Color& v) { SET_VAR(rareNonInheritedData, m_visitedLinkBorderLeftColor, v); }
+    void setVisitedLinkBorderRightColor(const Color& v) { SET_VAR(rareNonInheritedData, m_visitedLinkBorderRightColor, v); }
+    void setVisitedLinkBorderBottomColor(const Color& v) { SET_VAR(rareNonInheritedData, m_visitedLinkBorderBottomColor, v); }
+    void setVisitedLinkBorderTopColor(const Color& v) { SET_VAR(rareNonInheritedData, m_visitedLinkBorderTopColor, v); }
+    void setVisitedLinkOutlineColor(const Color& v) { SET_VAR(rareNonInheritedData, m_visitedLinkOutlineColor, v); }
+    void setVisitedLinkColumnRuleColor(const Color& v) { SET_VAR(rareNonInheritedData.access()->m_multiCol, m_visitedLinkColumnRuleColor, v); }
+#if ENABLE(CSS3_TEXT)
+    void setVisitedLinkTextDecorationColor(const Color& v) { SET_VAR(rareNonInheritedData, m_visitedLinkTextDecorationColor, v); }
+#endif // CSS3_TEXT
+    void setVisitedLinkTextEmphasisColor(const Color& v) { SET_VAR(rareInheritedData, visitedLinkTextEmphasisColor, v); }
+    void setVisitedLinkTextFillColor(const Color& v) { SET_VAR(rareInheritedData, visitedLinkTextFillColor, v); }
+    void setVisitedLinkTextStrokeColor(const Color& v) { SET_VAR(rareInheritedData, visitedLinkTextStrokeColor, v); }
+
+    void inheritUnicodeBidiFrom(const RenderStyle* parent) { noninherited_flags._unicodeBidi = parent->noninherited_flags._unicodeBidi; }
+    void getShadowExtent(const ShadowData*, LayoutUnit& top, LayoutUnit& right, LayoutUnit& bottom, LayoutUnit& left) const;
+    LayoutBoxExtent getShadowInsetExtent(const ShadowData*) const;
+    void getShadowHorizontalExtent(const ShadowData*, LayoutUnit& left, LayoutUnit& right) const;
+    void getShadowVerticalExtent(const ShadowData*, LayoutUnit& top, LayoutUnit& bottom) const;
+    void getShadowInlineDirectionExtent(const ShadowData* shadow, LayoutUnit& logicalLeft, LayoutUnit& logicalRight) const
+    {
+        return isHorizontalWritingMode() ? getShadowHorizontalExtent(shadow, logicalLeft, logicalRight) : getShadowVerticalExtent(shadow, logicalLeft, logicalRight);
+    }
+    void getShadowBlockDirectionExtent(const ShadowData* shadow, LayoutUnit& logicalTop, LayoutUnit& logicalBottom) const
+    {
+        return isHorizontalWritingMode() ? getShadowVerticalExtent(shadow, logicalTop, logicalBottom) : getShadowHorizontalExtent(shadow, logicalTop, logicalBottom);
+    }
+
+    bool isDisplayReplacedType(EDisplay display) const
+    {
+        return display == INLINE_BLOCK || display == INLINE_BOX || display == INLINE_FLEX
+            || display == INLINE_TABLE || display == INLINE_GRID;
+    }
+
+    bool isDisplayInlineType(EDisplay display) const
+    {
+        return display == INLINE || isDisplayReplacedType(display);
+    }
+
+    // Color accessors are all private to make sure callers use visitedDependentColor instead to access them.
+    Color invalidColor() const { static Color invalid; return invalid; }
+    Color borderLeftColor() const { return surround->border.left().color(); }
+    Color borderRightColor() const { return surround->border.right().color(); }
+    Color borderTopColor() const { return surround->border.top().color(); }
+    Color borderBottomColor() const { return surround->border.bottom().color(); }
+    Color backgroundColor() const { return m_background->color(); }
+    Color color() const;
+    Color columnRuleColor() const { return rareNonInheritedData->m_multiCol->m_rule.color(); }
+    Color outlineColor() const { return m_background->outline().color(); }
+    Color textEmphasisColor() const { return rareInheritedData->textEmphasisColor; }
+    Color textFillColor() const { return rareInheritedData->textFillColor; }
+    Color textStrokeColor() const { return rareInheritedData->textStrokeColor; }
+    Color visitedLinkColor() const;
+    Color visitedLinkBackgroundColor() const { return rareNonInheritedData->m_visitedLinkBackgroundColor; }
+    Color visitedLinkBorderLeftColor() const { return rareNonInheritedData->m_visitedLinkBorderLeftColor; }
+    Color visitedLinkBorderRightColor() const { return rareNonInheritedData->m_visitedLinkBorderRightColor; }
+    Color visitedLinkBorderBottomColor() const { return rareNonInheritedData->m_visitedLinkBorderBottomColor; }
+    Color visitedLinkBorderTopColor() const { return rareNonInheritedData->m_visitedLinkBorderTopColor; }
+    Color visitedLinkOutlineColor() const { return rareNonInheritedData->m_visitedLinkOutlineColor; }
+    Color visitedLinkColumnRuleColor() const { return rareNonInheritedData->m_multiCol->m_visitedLinkColumnRuleColor; }
+#if ENABLE(CSS3_TEXT)
+    Color textDecorationColor() const { return rareNonInheritedData->m_textDecorationColor; }
+    Color visitedLinkTextDecorationColor() const { return rareNonInheritedData->m_visitedLinkTextDecorationColor; }
+#endif // CSS3_TEXT
+    Color visitedLinkTextEmphasisColor() const { return rareInheritedData->visitedLinkTextEmphasisColor; }
+    Color visitedLinkTextFillColor() const { return rareInheritedData->visitedLinkTextFillColor; }
+    Color visitedLinkTextStrokeColor() const { return rareInheritedData->visitedLinkTextStrokeColor; }
+
+    Color colorIncludingFallback(int colorProperty, bool visitedLink) const;
+
+#if ENABLE(SVG)
+    Color stopColor() const { return svgStyle()->stopColor(); }
+    Color floodColor() const { return svgStyle()->floodColor(); }
+    Color lightingColor() const { return svgStyle()->lightingColor(); }
+#endif
+
+    void appendContent(PassOwnPtr<ContentData>);
+};
+
+inline int adjustForAbsoluteZoom(int value, const RenderStyle* style)
+{
+    double zoomFactor = style->effectiveZoom();
+    if (zoomFactor == 1)
+        return value;
+    // Needed because computeLengthInt truncates (rather than rounds) when scaling up.
+    if (zoomFactor > 1) {
+        if (value < 0)
+            value--;
+        else 
+            value++;
+    }
+
+    return roundForImpreciseConversion<int>(value / zoomFactor);
+}
+
+inline float adjustFloatForAbsoluteZoom(float value, const RenderStyle* style)
+{
+    return value / style->effectiveZoom();
+}
+
+inline LayoutUnit adjustLayoutUnitForAbsoluteZoom(LayoutUnit value, const RenderStyle* style)
+{
+    return value / style->effectiveZoom();
+}
+
+inline bool RenderStyle::setZoom(float f)
+{
+    if (compareEqual(visual->m_zoom, f))
+        return false;
+    visual.access()->m_zoom = f;
+    setEffectiveZoom(effectiveZoom() * zoom());
+    return true;
+}
+
+inline bool RenderStyle::setEffectiveZoom(float f)
+{
+    if (compareEqual(rareInheritedData->m_effectiveZoom, f))
+        return false;
+    rareInheritedData.access()->m_effectiveZoom = f;
+    return true;
+}
+
+inline bool RenderStyle::setTextOrientation(TextOrientation textOrientation)
+{
+    if (compareEqual(rareInheritedData->m_textOrientation, textOrientation))
+        return false;
+
+    rareInheritedData.access()->m_textOrientation = textOrientation;
+    return true;
+}
+
+} // namespace WebCore
+
+#endif // RenderStyle_h
diff --git a/Source/core/rendering/style/RenderStyleConstants.h b/Source/core/rendering/style/RenderStyleConstants.h
new file mode 100644
index 0000000..eea12ff
--- /dev/null
+++ b/Source/core/rendering/style/RenderStyleConstants.h
@@ -0,0 +1,503 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ *           (C) 2000 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008, 2009, 2010 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com)
+ * Copyright (C) 2009 Torch Mobile Inc. All rights reserved. (http://www.torchmobile.com/)
+ *
+ * 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 {
+
+static const size_t PrintColorAdjustBits = 1;
+enum PrintColorAdjust {
+    PrintColorAdjustEconomy,
+    PrintColorAdjustExact
+};
+
+// The difference between two styles.  The following values are used:
+// (1) StyleDifferenceEqual - The two styles are identical
+// (2) StyleDifferenceRecompositeLayer - The layer needs its position and transform updated, but no repaint
+// (3) StyleDifferenceRepaint - The object just needs to be repainted.
+// (4) StyleDifferenceRepaintLayer - The layer and its descendant layers needs to be repainted.
+// (5) StyleDifferenceLayoutPositionedMovementOnly - Only the position of this positioned object has been updated
+// (6) StyleDifferenceSimplifiedLayout - Only overflow needs to be recomputed
+// (7) StyleDifferenceSimplifiedLayoutAndPositionedMovement - Both positioned movement and simplified layout updates are required.
+// (8) StyleDifferenceLayout - A full layout is required.
+enum StyleDifference {
+    StyleDifferenceEqual,
+    StyleDifferenceRecompositeLayer,
+    StyleDifferenceRepaint,
+    StyleDifferenceRepaintLayer,
+    StyleDifferenceLayoutPositionedMovementOnly,
+    StyleDifferenceSimplifiedLayout,
+    StyleDifferenceSimplifiedLayoutAndPositionedMovement,
+    StyleDifferenceLayout
+};
+
+// When some style properties change, different amounts of work have to be done depending on
+// context (e.g. whether the property is changing on an element which has a compositing layer).
+// A simple StyleDifference does not provide enough information so we return a bit mask of
+// StyleDifferenceContextSensitiveProperties from RenderStyle::diff() too.
+enum StyleDifferenceContextSensitiveProperty {
+    ContextSensitivePropertyNone = 0,
+    ContextSensitivePropertyTransform = (1 << 0),
+    ContextSensitivePropertyOpacity = (1 << 1),
+    ContextSensitivePropertyFilter = (1 << 2)
+};
+
+// Static pseudo styles. Dynamic ones are produced on the fly.
+enum PseudoId {
+    // The order must be NOP ID, public IDs, and then internal IDs.
+    NOPSEUDO, FIRST_LINE, FIRST_LETTER, BEFORE, AFTER, SELECTION, FIRST_LINE_INHERITED, SCROLLBAR,
+    // Internal IDs follow:
+    SCROLLBAR_THUMB, SCROLLBAR_BUTTON, SCROLLBAR_TRACK, SCROLLBAR_TRACK_PIECE, SCROLLBAR_CORNER, RESIZER,
+    INPUT_LIST_BUTTON,
+    AFTER_LAST_INTERNAL_PSEUDOID,
+    FULL_SCREEN, FULL_SCREEN_DOCUMENT, FULL_SCREEN_ANCESTOR, ANIMATING_FULL_SCREEN_TRANSITION,
+    FIRST_PUBLIC_PSEUDOID = FIRST_LINE,
+    FIRST_INTERNAL_PSEUDOID = SCROLLBAR_THUMB,
+    PUBLIC_PSEUDOID_MASK = ((1 << FIRST_INTERNAL_PSEUDOID) - 1) & ~((1 << FIRST_PUBLIC_PSEUDOID) - 1)
+};
+
+enum ColumnSpan { ColumnSpanNone = 0, ColumnSpanAll };
+
+enum EBorderCollapse { BSEPARATE = 0, BCOLLAPSE = 1 };
+
+// These have been defined in the order of their precedence for border-collapsing. Do
+// not change this order! This order also must match the order in CSSValueKeywords.in.
+enum EBorderStyle { BNONE, BHIDDEN, INSET, GROOVE, OUTSET, RIDGE, DOTTED, DASHED, SOLID, DOUBLE };
+
+enum EBorderPrecedence { BOFF, BTABLE, BCOLGROUP, BCOL, BROWGROUP, BROW, BCELL };
+
+enum OutlineIsAuto { AUTO_OFF = 0, AUTO_ON };
+
+enum EPosition {
+    StaticPosition = 0,
+    RelativePosition = 1,
+    AbsolutePosition = 2,
+    StickyPosition = 3,
+    // This value is required to pack our bits efficiently in RenderObject.
+    FixedPosition = 6
+};
+
+enum EFloat {
+    NoFloat, LeftFloat, RightFloat
+};
+
+enum EMarginCollapse { MCOLLAPSE, MSEPARATE, MDISCARD };
+
+// Box decoration attributes. Not inherited.
+
+enum EBoxDecorationBreak { DSLICE, DCLONE };
+
+// 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, OPAGEDX, OPAGEDY
+};
+
+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 TextCombine {
+    TextCombineNone, TextCombineHorizontal
+};
+
+enum EFillAttachment {
+    ScrollBackgroundAttachment, LocalBackgroundAttachment, FixedBackgroundAttachment
+};
+
+enum EFillBox {
+    BorderFillBox, PaddingFillBox, ContentFillBox, TextFillBox
+};
+
+enum EFillRepeat {
+    RepeatFill, NoRepeatFill, RoundFill, SpaceFill
+};
+
+enum EFillLayerType {
+    BackgroundFillLayer, MaskFillLayer
+};
+
+// CSS3 Background Values
+enum EFillSizeType { Contain, Cover, SizeLength, SizeNone };
+
+// CSS3 Background Position
+enum BackgroundEdgeOrigin { TopEdge, RightEdge, BottomEdge, LeftEdge };
+
+// 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 };
+
+// Deprecated Flexible Box Properties
+
+enum EBoxPack { Start, Center, End, Justify };
+enum EBoxAlignment { BSTRETCH, BSTART, BCENTER, BEND, BBASELINE };
+enum EBoxOrient { HORIZONTAL, VERTICAL };
+enum EBoxLines { SINGLE, MULTIPLE };
+enum EBoxDirection { BNORMAL, BREVERSE };
+
+// CSS3 Flexbox Properties
+
+enum EAlignContent { AlignContentFlexStart, AlignContentFlexEnd, AlignContentCenter, AlignContentSpaceBetween, AlignContentSpaceAround, AlignContentStretch };
+enum EAlignItems { AlignAuto, AlignFlexStart, AlignFlexEnd, AlignCenter, AlignStretch, AlignBaseline };
+enum EFlexDirection { FlowRow, FlowRowReverse, FlowColumn, FlowColumnReverse };
+enum EFlexWrap { FlexNoWrap, FlexWrap, FlexWrapReverse };
+enum EJustifyContent { JustifyFlexStart, JustifyFlexEnd, JustifyCenter, JustifySpaceBetween, JustifySpaceAround };
+
+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, SELECT_ALL
+};
+
+// Word Break Values. Matches WinIE, rather than CSS3
+
+enum EWordBreak {
+    NormalWordBreak, BreakAllWordBreak, BreakWordBreak
+};
+
+enum EOverflowWrap {
+    NormalOverflowWrap, BreakOverflowWrap
+};
+
+enum LineBreak {
+    LineBreakAuto, LineBreakLoose, LineBreakNormal, LineBreakStrict, LineBreakAfterWhiteSpace
+};
+
+enum EResize {
+    RESIZE_NONE, RESIZE_BOTH, RESIZE_HORIZONTAL, RESIZE_VERTICAL
+};
+
+// The order of this enum must match the order of the list style types in CSSValueKeywords.in.
+enum EListStyleType {
+    Disc,
+    Circle,
+    Square,
+    DecimalListStyle,
+    DecimalLeadingZero,
+    ArabicIndic,
+    BinaryListStyle,
+    Bengali,
+    Cambodian,
+    Khmer,
+    Devanagari,
+    Gujarati,
+    Gurmukhi,
+    Kannada,
+    LowerHexadecimal,
+    Lao,
+    Malayalam,
+    Mongolian,
+    Myanmar,
+    Octal,
+    Oriya,
+    Persian,
+    Urdu,
+    Telugu,
+    Tibetan,
+    Thai,
+    UpperHexadecimal,
+    LowerRoman,
+    UpperRoman,
+    LowerGreek,
+    LowerAlpha,
+    LowerLatin,
+    UpperAlpha,
+    UpperLatin,
+    Afar,
+    EthiopicHalehameAaEt,
+    EthiopicHalehameAaEr,
+    Amharic,
+    EthiopicHalehameAmEt,
+    AmharicAbegede,
+    EthiopicAbegedeAmEt,
+    CjkEarthlyBranch,
+    CjkHeavenlyStem,
+    Ethiopic,
+    EthiopicHalehameGez,
+    EthiopicAbegede,
+    EthiopicAbegedeGez,
+    HangulConsonant,
+    Hangul,
+    LowerNorwegian,
+    Oromo,
+    EthiopicHalehameOmEt,
+    Sidama,
+    EthiopicHalehameSidEt,
+    Somali,
+    EthiopicHalehameSoEt,
+    Tigre,
+    EthiopicHalehameTig,
+    TigrinyaEr,
+    EthiopicHalehameTiEr,
+    TigrinyaErAbegede,
+    EthiopicAbegedeTiEr,
+    TigrinyaEt,
+    EthiopicHalehameTiEt,
+    TigrinyaEtAbegede,
+    EthiopicAbegedeTiEt,
+    UpperGreek,
+    UpperNorwegian,
+    Asterisks,
+    Footnotes,
+    Hebrew,
+    Armenian,
+    LowerArmenian,
+    UpperArmenian,
+    Georgian,
+    CJKIdeographic,
+    Hiragana,
+    Katakana,
+    HiraganaIroha,
+    KatakanaIroha,
+    NoneListStyle
+};
+
+enum QuoteType {
+    OPEN_QUOTE, CLOSE_QUOTE, NO_OPEN_QUOTE, NO_CLOSE_QUOTE
+};
+
+enum EBorderFit { BorderFitBorder, BorderFitLines };
+
+enum EAnimationFillMode { AnimationFillModeNone, AnimationFillModeForwards, AnimationFillModeBackwards, AnimationFillModeBoth };
+
+enum EAnimPlayState {
+    AnimPlayStatePlaying = 0x0,
+    AnimPlayStatePaused = 0x1
+};
+
+enum EWhiteSpace {
+    NORMAL, PRE, PRE_WRAP, PRE_LINE, NOWRAP, KHTML_NOWRAP
+};
+
+// The order of this enum must match the order of the text align values in CSSValueKeywords.in.
+enum ETextAlign {
+    LEFT, RIGHT, CENTER, JUSTIFY, WEBKIT_LEFT, WEBKIT_RIGHT, WEBKIT_CENTER, TASTART, TAEND,
+};
+
+enum ETextTransform {
+    CAPITALIZE, UPPERCASE, LOWERCASE, TTNONE
+};
+
+static const size_t ETextDecorationBits = 4;
+enum ETextDecoration {
+    TDNONE = 0x0 , UNDERLINE = 0x1, OVERLINE = 0x2, LINE_THROUGH= 0x4, BLINK = 0x8
+};
+inline ETextDecoration operator|(ETextDecoration a, ETextDecoration b) { return ETextDecoration(int(a) | int(b)); }
+inline ETextDecoration& operator|=(ETextDecoration& a, ETextDecoration b) { return a = a | b; }
+
+enum TextDecorationStyle {
+    TextDecorationStyleSolid,
+#if ENABLE(CSS3_TEXT)
+    TextDecorationStyleDouble,
+    TextDecorationStyleDotted,
+    TextDecorationStyleDashed,
+    TextDecorationStyleWavy
+#endif // CSS3_TEXT
+};
+
+#if ENABLE(CSS3_TEXT)
+enum TextAlignLast {
+    TextAlignLastAuto, TextAlignLastStart, TextAlignLastEnd, TextAlignLastLeft, TextAlignLastRight, TextAlignLastCenter, TextAlignLastJustify
+};
+
+enum TextUnderlinePosition {
+    // FIXME: Implement support for 'under left' and 'under right' values.
+    TextUnderlinePositionAuto = 0x1, TextUnderlinePositionAlphabetic = 0x2, TextUnderlinePositionUnder = 0x4
+};
+#endif // CSS3_TEXT
+
+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
+};
+
+// The order of this enum must match the order of the display values in CSSValueKeywords.in.
+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,
+    FLEX, INLINE_FLEX,
+    GRID, INLINE_GRID,
+    LAZY_BLOCK,
+    NONE
+};
+
+enum EInsideLink {
+    NotInsideLink, InsideUnvisitedLink, InsideVisitedLink
+};
+    
+enum EPointerEvents {
+    PE_NONE, PE_AUTO, PE_STROKE, PE_FILL, PE_PAINTED, PE_VISIBLE,
+    PE_VISIBLE_STROKE, PE_VISIBLE_FILL, PE_VISIBLE_PAINTED, PE_ALL
+};
+
+enum ETransformStyle3D {
+    TransformStyle3DFlat, TransformStyle3DPreserve3D
+};
+
+enum EBackfaceVisibility {
+    BackfaceVisibilityVisible, BackfaceVisibilityHidden
+};
+    
+enum ELineClampType { LineClampLineCount, LineClampPercentage };
+
+enum Hyphens { HyphensNone, HyphensManual, HyphensAuto };
+
+enum ESpeak { SpeakNone, SpeakNormal, SpeakSpellOut, SpeakDigits, SpeakLiteralPunctuation, SpeakNoPunctuation };
+
+enum TextEmphasisFill { TextEmphasisFillFilled, TextEmphasisFillOpen };
+
+enum TextEmphasisMark { TextEmphasisMarkNone, TextEmphasisMarkAuto, TextEmphasisMarkDot, TextEmphasisMarkCircle, TextEmphasisMarkDoubleCircle, TextEmphasisMarkTriangle, TextEmphasisMarkSesame, TextEmphasisMarkCustom };
+
+enum TextEmphasisPosition { TextEmphasisPositionOver, TextEmphasisPositionUnder };
+
+enum TextOrientation { TextOrientationVerticalRight, TextOrientationUpright, TextOrientationSideways, TextOrientationSidewaysRight };
+
+enum TextOverflow { TextOverflowClip = 0, TextOverflowEllipsis };
+
+enum EImageRendering { ImageRenderingAuto, ImageRenderingOptimizeSpeed, ImageRenderingOptimizeQuality, ImageRenderingOptimizeContrast };
+
+enum ImageResolutionSource { ImageResolutionSpecified = 0, ImageResolutionFromImage };
+
+enum ImageResolutionSnap { ImageResolutionNoSnap = 0, ImageResolutionSnapPixels };
+
+enum Order { LogicalOrder = 0, VisualOrder };
+
+enum RegionOverflow { AutoRegionOverflow, BreakRegionOverflow };
+
+enum ColumnAxis { HorizontalColumnAxis, VerticalColumnAxis, AutoColumnAxis };
+
+enum ColumnProgression { NormalColumnProgression, ReverseColumnProgression };
+
+enum LineSnap { LineSnapNone, LineSnapBaseline, LineSnapContain };
+
+enum LineAlign { LineAlignNone, LineAlignEdges };
+
+enum WrapFlow { WrapFlowAuto, WrapFlowBoth, WrapFlowStart, WrapFlowEnd, WrapFlowMaximum, WrapFlowClear };
+
+enum WrapThrough { WrapThroughWrap, WrapThroughNone };
+
+enum RubyPosition { RubyPositionBefore, RubyPositionAfter };
+
+enum GridAutoFlow { AutoFlowNone, AutoFlowColumn, AutoFlowRow };
+
+enum DraggableRegionMode { DraggableRegionNone, DraggableRegionDrag, DraggableRegionNoDrag };
+
+// Reasonable maximum to prevent insane font sizes from causing crashes on some platforms (such as Windows).
+static const float maximumAllowedFontSize = 1000000.0f;
+
+#if ENABLE(CSS3_TEXT)
+enum TextIndentLine { TextIndentFirstLine, TextIndentEachLine };
+#endif
+
+} // namespace WebCore
+
+#endif // RenderStyleConstants_h
diff --git a/Source/core/rendering/style/SVGRenderStyle.cpp b/Source/core/rendering/style/SVGRenderStyle.cpp
new file mode 100644
index 0000000..3623a9a
--- /dev/null
+++ b/Source/core/rendering/style/SVGRenderStyle.cpp
@@ -0,0 +1,237 @@
+/*
+    Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org>
+                  2004, 2005, 2010 Rob Buis <buis@kde.org>
+    Copyright (C) Research In Motion Limited 2010. All rights reserved.
+
+    Based on khtml code by:
+    Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
+    Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
+    Copyright (C) 2002-2003 Dirk Mueller (mueller@kde.org)
+    Copyright (C) 2002 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 "core/rendering/style/SVGRenderStyle.h"
+
+#include "core/css/CSSPrimitiveValue.h"
+#include "core/css/CSSValueList.h"
+#include "core/dom/NodeRenderStyle.h"
+#include "core/platform/graphics/IntRect.h"
+#include "core/svg/SVGStyledElement.h"
+
+using namespace std;
+
+namespace WebCore {
+
+SVGRenderStyle::SVGRenderStyle()
+{
+    static SVGRenderStyle* defaultStyle = new SVGRenderStyle(CreateDefault);
+
+    fill = defaultStyle->fill;
+    stroke = defaultStyle->stroke;
+    text = defaultStyle->text;
+    stops = defaultStyle->stops;
+    misc = defaultStyle->misc;
+    shadowSVG = defaultStyle->shadowSVG;
+    inheritedResources = defaultStyle->inheritedResources;
+    resources = defaultStyle->resources;
+
+    setBitDefaults();
+}
+
+SVGRenderStyle::SVGRenderStyle(CreateDefaultType)
+{
+    setBitDefaults();
+
+    fill.init();
+    stroke.init();
+    text.init();
+    stops.init();
+    misc.init();
+    shadowSVG.init();
+    inheritedResources.init();
+    resources.init();
+}
+
+SVGRenderStyle::SVGRenderStyle(const SVGRenderStyle& other)
+    : RefCounted<SVGRenderStyle>()
+{
+    fill = other.fill;
+    stroke = other.stroke;
+    text = other.text;
+    stops = other.stops;
+    misc = other.misc;
+    shadowSVG = other.shadowSVG;
+    inheritedResources = other.inheritedResources;
+    resources = other.resources;
+
+    svg_inherited_flags = other.svg_inherited_flags;
+    svg_noninherited_flags = other.svg_noninherited_flags;
+}
+
+SVGRenderStyle::~SVGRenderStyle()
+{
+}
+
+bool SVGRenderStyle::operator==(const SVGRenderStyle& other) const
+{
+    return fill == other.fill
+        && stroke == other.stroke
+        && text == other.text
+        && stops == other.stops
+        && misc == other.misc
+        && shadowSVG == other.shadowSVG
+        && inheritedResources == other.inheritedResources
+        && resources == other.resources
+        && svg_inherited_flags == other.svg_inherited_flags
+        && svg_noninherited_flags == other.svg_noninherited_flags;
+}
+
+bool SVGRenderStyle::inheritedNotEqual(const SVGRenderStyle* other) const
+{
+    return fill != other->fill
+        || stroke != other->stroke
+        || text != other->text
+        || inheritedResources != other->inheritedResources
+        || svg_inherited_flags != other->svg_inherited_flags;
+}
+
+void SVGRenderStyle::inheritFrom(const SVGRenderStyle* svgInheritParent)
+{
+    if (!svgInheritParent)
+        return;
+
+    fill = svgInheritParent->fill;
+    stroke = svgInheritParent->stroke;
+    text = svgInheritParent->text;
+    inheritedResources = svgInheritParent->inheritedResources;
+
+    svg_inherited_flags = svgInheritParent->svg_inherited_flags;
+}
+
+void SVGRenderStyle::copyNonInheritedFrom(const SVGRenderStyle* other)
+{
+    svg_noninherited_flags = other->svg_noninherited_flags;
+    stops = other->stops;
+    misc = other->misc;
+    shadowSVG = other->shadowSVG;
+    resources = other->resources;
+}
+
+StyleDifference SVGRenderStyle::diff(const SVGRenderStyle* other) const
+{
+    // NOTE: All comparisions that may return StyleDifferenceLayout have to go before those who return StyleDifferenceRepaint
+
+    // If kerning changes, we need a relayout, to force SVGCharacterData to be recalculated in the SVGRootInlineBox.
+    if (text != other->text)
+        return StyleDifferenceLayout;
+
+    // If resources change, we need a relayout, as the presence of resources influences the repaint rect.
+    if (resources != other->resources)
+        return StyleDifferenceLayout;
+
+    // If markers change, we need a relayout, as marker boundaries are cached in RenderSVGPath.
+    if (inheritedResources != other->inheritedResources)
+        return StyleDifferenceLayout;
+
+    // All text related properties influence layout.
+    if (svg_inherited_flags._textAnchor != other->svg_inherited_flags._textAnchor
+        || svg_inherited_flags._writingMode != other->svg_inherited_flags._writingMode
+        || svg_inherited_flags._glyphOrientationHorizontal != other->svg_inherited_flags._glyphOrientationHorizontal
+        || svg_inherited_flags._glyphOrientationVertical != other->svg_inherited_flags._glyphOrientationVertical
+        || svg_noninherited_flags.f._alignmentBaseline != other->svg_noninherited_flags.f._alignmentBaseline
+        || svg_noninherited_flags.f._dominantBaseline != other->svg_noninherited_flags.f._dominantBaseline
+        || svg_noninherited_flags.f._baselineShift != other->svg_noninherited_flags.f._baselineShift)
+        return StyleDifferenceLayout;
+
+    // Text related properties influence layout.
+    bool miscNotEqual = misc != other->misc;
+    if (miscNotEqual && misc->baselineShiftValue != other->misc->baselineShiftValue)
+        return StyleDifferenceLayout;
+
+    // These properties affect the cached stroke bounding box rects.
+    if (svg_inherited_flags._capStyle != other->svg_inherited_flags._capStyle
+        || svg_inherited_flags._joinStyle != other->svg_inherited_flags._joinStyle)
+        return StyleDifferenceLayout;
+
+    // Shadow changes require relayouts, as they affect the repaint rects.
+    if (shadowSVG != other->shadowSVG)
+        return StyleDifferenceLayout;
+
+    // Some stroke properties, requires relayouts, as the cached stroke boundaries need to be recalculated.
+    if (stroke != other->stroke) {
+        if (stroke->width != other->stroke->width
+            || stroke->paintType != other->stroke->paintType
+            || stroke->paintColor != other->stroke->paintColor
+            || stroke->paintUri != other->stroke->paintUri
+            || stroke->miterLimit != other->stroke->miterLimit
+            || stroke->dashArray != other->stroke->dashArray
+            || stroke->dashOffset != other->stroke->dashOffset)
+            return StyleDifferenceLayout;
+
+        // Only the stroke-opacity case remains, where we only need a repaint.
+        ASSERT(stroke->opacity != other->stroke->opacity);
+        return StyleDifferenceRepaint;
+    }
+
+    // NOTE: All comparisions below may only return StyleDifferenceRepaint
+
+    // Painting related properties only need repaints. 
+    if (miscNotEqual) {
+        if (misc->floodColor != other->misc->floodColor
+            || misc->floodOpacity != other->misc->floodOpacity
+            || misc->lightingColor != other->misc->lightingColor)
+            return StyleDifferenceRepaint;
+    }
+
+    // If fill changes, we just need to repaint. Fill boundaries are not influenced by this, only by the Path, that RenderSVGPath contains.
+    if (fill->paintType != other->fill->paintType || fill->paintColor != other->fill->paintColor
+        || fill->paintUri != other->fill->paintUri || fill->opacity != other->fill->opacity)
+        return StyleDifferenceRepaint;
+
+    // If gradient stops change, we just need to repaint. Style updates are already handled through RenderSVGGradientSTop.
+    if (stops != other->stops)
+        return StyleDifferenceRepaint;
+
+    // Changes of these flags only cause repaints.
+    if (svg_inherited_flags._colorRendering != other->svg_inherited_flags._colorRendering
+        || svg_inherited_flags._shapeRendering != other->svg_inherited_flags._shapeRendering
+        || svg_inherited_flags._clipRule != other->svg_inherited_flags._clipRule
+        || svg_inherited_flags._fillRule != other->svg_inherited_flags._fillRule
+        || svg_inherited_flags._colorInterpolation != other->svg_inherited_flags._colorInterpolation
+        || svg_inherited_flags._colorInterpolationFilters != other->svg_inherited_flags._colorInterpolationFilters)
+        return StyleDifferenceRepaint;
+
+    // FIXME: vector-effect is not taken into account in the layout-phase. Once this is fixed, we should relayout here.
+    if (svg_noninherited_flags.f._vectorEffect != other->svg_noninherited_flags.f._vectorEffect)
+        return StyleDifferenceRepaint;
+
+    if (svg_noninherited_flags.f.bufferedRendering != other->svg_noninherited_flags.f.bufferedRendering)
+        return StyleDifferenceRepaint;
+
+    if (svg_noninherited_flags.f.maskType != other->svg_noninherited_flags.f.maskType)
+        return StyleDifferenceRepaint;
+
+    return StyleDifferenceEqual;
+}
+
+}
+
+#endif // ENABLE(SVG)
diff --git a/Source/core/rendering/style/SVGRenderStyle.h b/Source/core/rendering/style/SVGRenderStyle.h
new file mode 100644
index 0000000..288e07d
--- /dev/null
+++ b/Source/core/rendering/style/SVGRenderStyle.h
@@ -0,0 +1,473 @@
+/*
+    Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org>
+                  2004, 2005 Rob Buis <buis@kde.org>
+    Copyright (C) 2005, 2006 Apple Computer, Inc.
+    Copyright (C) Research In Motion Limited 2010. 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 SVGRenderStyle_h
+#define SVGRenderStyle_h
+
+#if ENABLE(SVG)
+#include "core/css/CSSValueList.h"
+#include "core/dom/ExceptionCodePlaceholder.h"
+#include "core/platform/graphics/GraphicsTypes.h"
+#include "core/platform/graphics/Path.h"
+#include "core/rendering/style/DataRef.h"
+#include "core/rendering/style/RenderStyleConstants.h"
+#include "core/rendering/style/SVGRenderStyleDefs.h"
+#include "core/svg/SVGPaint.h"
+
+namespace WebCore {
+
+class FloatRect;
+class IntRect;
+class RenderObject;
+
+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*);
+    void copyNonInheritedFrom(const SVGRenderStyle*);
+
+    StyleDifference diff(const SVGRenderStyle*) const;
+
+    bool operator==(const SVGRenderStyle&) const;
+    bool operator!=(const SVGRenderStyle& o) const { return !(*this == o); }
+
+    // Initial values for all the properties
+    static EAlignmentBaseline initialAlignmentBaseline() { return AB_AUTO; }
+    static EDominantBaseline initialDominantBaseline() { return DB_AUTO; }
+    static EBaselineShift initialBaselineShift() { return BS_BASELINE; }
+    static EVectorEffect initialVectorEffect() { return VE_NONE; }
+    static EBufferedRendering initialBufferedRendering() { return BR_AUTO; }
+    static LineCap initialCapStyle() { return ButtCap; }
+    static WindRule initialClipRule() { return RULE_NONZERO; }
+    static EColorInterpolation initialColorInterpolation() { return CI_SRGB; }
+    static EColorInterpolation initialColorInterpolationFilters() { return CI_LINEARRGB; }
+    static EColorRendering initialColorRendering() { return CR_AUTO; }
+    static WindRule initialFillRule() { return RULE_NONZERO; }
+    static LineJoin initialJoinStyle() { return MiterJoin; }
+    static EShapeRendering initialShapeRendering() { return SR_AUTO; }
+    static ETextAnchor initialTextAnchor() { return TA_START; }
+    static SVGWritingMode initialWritingMode() { return WM_LRTB; }
+    static EGlyphOrientation initialGlyphOrientationHorizontal() { return GO_0DEG; }
+    static EGlyphOrientation initialGlyphOrientationVertical() { return GO_AUTO; }
+    static float initialFillOpacity() { return 1; }
+    static SVGPaint::SVGPaintType initialFillPaintType() { return SVGPaint::SVG_PAINTTYPE_RGBCOLOR; }
+    static Color initialFillPaintColor() { return Color::black; }
+    static String initialFillPaintUri() { return String(); }
+    static float initialStrokeOpacity() { return 1; }
+    static SVGPaint::SVGPaintType initialStrokePaintType() { return SVGPaint::SVG_PAINTTYPE_NONE; }
+    static Color initialStrokePaintColor() { return Color(); }
+    static String initialStrokePaintUri() { return String(); }
+    static Vector<SVGLength> initialStrokeDashArray() { return Vector<SVGLength>(); }
+    static float initialStrokeMiterLimit() { return 4; }
+    static float initialStopOpacity() { return 1; }
+    static Color initialStopColor() { return Color(0, 0, 0); }
+    static float initialFloodOpacity() { return 1; }
+    static Color initialFloodColor() { return Color(0, 0, 0); }
+    static Color initialLightingColor() { return Color(255, 255, 255); }
+    static ShadowData* initialShadow() { return 0; }
+    static String initialClipperResource() { return String(); }
+    static String initialFilterResource() { return String(); }
+    static String initialMaskerResource() { return String(); }
+    static String initialMarkerStartResource() { return String(); }
+    static String initialMarkerMidResource() { return String(); }
+    static String initialMarkerEndResource() { return String(); }
+    static EMaskType initialMaskType() { return MT_LUMINANCE; }
+
+    static SVGLength initialBaselineShiftValue()
+    {
+        SVGLength length;
+        length.newValueSpecifiedUnits(LengthTypeNumber, 0, ASSERT_NO_EXCEPTION);
+        return length;
+    }
+
+    static SVGLength initialKerning()
+    {
+        SVGLength length;
+        length.newValueSpecifiedUnits(LengthTypeNumber, 0, ASSERT_NO_EXCEPTION);
+        return length;
+    }
+
+    static SVGLength initialStrokeDashOffset()
+    {
+        SVGLength length;
+        length.newValueSpecifiedUnits(LengthTypeNumber, 0, ASSERT_NO_EXCEPTION);
+        return length;
+    }
+
+    static SVGLength initialStrokeWidth()
+    {
+        SVGLength length;
+        length.newValueSpecifiedUnits(LengthTypeNumber, 1, ASSERT_NO_EXCEPTION);
+        return length;
+    }
+
+    // SVG CSS Property setters
+    void setAlignmentBaseline(EAlignmentBaseline val) { svg_noninherited_flags.f._alignmentBaseline = val; }
+    void setDominantBaseline(EDominantBaseline val) { svg_noninherited_flags.f._dominantBaseline = val; }
+    void setBaselineShift(EBaselineShift val) { svg_noninherited_flags.f._baselineShift = val; }
+    void setVectorEffect(EVectorEffect val) { svg_noninherited_flags.f._vectorEffect = val; }
+    void setBufferedRendering(EBufferedRendering val) { svg_noninherited_flags.f.bufferedRendering = val; }
+    void setCapStyle(LineCap val) { svg_inherited_flags._capStyle = val; }
+    void setClipRule(WindRule val) { svg_inherited_flags._clipRule = val; }
+    void setColorInterpolation(EColorInterpolation val) { svg_inherited_flags._colorInterpolation = val; }
+    void setColorInterpolationFilters(EColorInterpolation val) { svg_inherited_flags._colorInterpolationFilters = val; }
+    void setColorRendering(EColorRendering val) { svg_inherited_flags._colorRendering = val; }
+    void setFillRule(WindRule val) { svg_inherited_flags._fillRule = val; }
+    void setJoinStyle(LineJoin val) { svg_inherited_flags._joinStyle = val; }
+    void setShapeRendering(EShapeRendering val) { svg_inherited_flags._shapeRendering = val; }
+    void setTextAnchor(ETextAnchor val) { svg_inherited_flags._textAnchor = val; }
+    void setWritingMode(SVGWritingMode val) { svg_inherited_flags._writingMode = val; }
+    void setGlyphOrientationHorizontal(EGlyphOrientation val) { svg_inherited_flags._glyphOrientationHorizontal = val; }
+    void setGlyphOrientationVertical(EGlyphOrientation val) { svg_inherited_flags._glyphOrientationVertical = val; }
+    void setMaskType(EMaskType val) { svg_noninherited_flags.f.maskType = val; }
+
+    void setFillOpacity(float obj)
+    {
+        if (!(fill->opacity == obj))
+            fill.access()->opacity = obj;
+    }
+
+    void setFillPaint(SVGPaint::SVGPaintType type, const Color& color, const String& uri, bool applyToRegularStyle = true, bool applyToVisitedLinkStyle = false)
+    {
+        if (applyToRegularStyle) {
+            if (!(fill->paintType == type))
+                fill.access()->paintType = type;
+            if (!(fill->paintColor == color))
+                fill.access()->paintColor = color;
+            if (!(fill->paintUri == uri))
+                fill.access()->paintUri = uri;
+        }
+        if (applyToVisitedLinkStyle) {
+            if (!(fill->visitedLinkPaintType == type))
+                fill.access()->visitedLinkPaintType = type;
+            if (!(fill->visitedLinkPaintColor == color))
+                fill.access()->visitedLinkPaintColor = color;
+            if (!(fill->visitedLinkPaintUri == uri))
+                fill.access()->visitedLinkPaintUri = uri;
+        }
+    }
+
+    void setStrokeOpacity(float obj)
+    {
+        if (!(stroke->opacity == obj))
+            stroke.access()->opacity = obj;
+    }
+
+    void setStrokePaint(SVGPaint::SVGPaintType type, const Color& color, const String& uri, bool applyToRegularStyle = true, bool applyToVisitedLinkStyle = false)
+    {
+        if (applyToRegularStyle) {
+            if (!(stroke->paintType == type))
+                stroke.access()->paintType = type;
+            if (!(stroke->paintColor == color))
+                stroke.access()->paintColor = color;
+            if (!(stroke->paintUri == uri))
+                stroke.access()->paintUri = uri;
+        }
+        if (applyToVisitedLinkStyle) {
+            if (!(stroke->visitedLinkPaintType == type))
+                stroke.access()->visitedLinkPaintType = type;
+            if (!(stroke->visitedLinkPaintColor == color))
+                stroke.access()->visitedLinkPaintColor = color;
+            if (!(stroke->visitedLinkPaintUri == uri))
+                stroke.access()->visitedLinkPaintUri = uri;
+        }
+    }
+
+    void setStrokeDashArray(const Vector<SVGLength>& obj)
+    {
+        if (!(stroke->dashArray == obj))
+            stroke.access()->dashArray = obj;
+    }
+
+    void setStrokeMiterLimit(float obj)
+    {
+        if (!(stroke->miterLimit == obj))
+            stroke.access()->miterLimit = obj;
+    }
+
+    void setStrokeWidth(const SVGLength& obj)
+    {
+        if (!(stroke->width == obj))
+            stroke.access()->width = obj;
+    }
+
+    void setStrokeDashOffset(const SVGLength& obj)
+    {
+        if (!(stroke->dashOffset == obj))
+            stroke.access()->dashOffset = obj;
+    }
+
+    void setKerning(const SVGLength& obj)
+    {
+        if (!(text->kerning == obj))
+            text.access()->kerning = obj;
+    }
+
+    void setStopOpacity(float obj)
+    {
+        if (!(stops->opacity == obj))
+            stops.access()->opacity = obj;
+    }
+
+    void setStopColor(const Color& obj)
+    {
+        if (!(stops->color == obj))
+            stops.access()->color = obj;
+    }
+
+    void setFloodOpacity(float obj)
+    {
+        if (!(misc->floodOpacity == obj))
+            misc.access()->floodOpacity = obj;
+    }
+
+    void setFloodColor(const Color& obj)
+    {
+        if (!(misc->floodColor == obj))
+            misc.access()->floodColor = obj;
+    }
+
+    void setLightingColor(const Color& obj)
+    {
+        if (!(misc->lightingColor == obj))
+            misc.access()->lightingColor = obj;
+    }
+
+    void setBaselineShiftValue(const SVGLength& obj)
+    {
+        if (!(misc->baselineShiftValue == obj))
+            misc.access()->baselineShiftValue = obj;
+    }
+
+    void setShadow(PassOwnPtr<ShadowData> obj) { shadowSVG.access()->shadow = obj; }
+
+    // Setters for non-inherited resources
+    void setClipperResource(const String& obj)
+    {
+        if (!(resources->clipper == obj))
+            resources.access()->clipper = obj;
+    }
+
+    void setFilterResource(const String& obj)
+    {
+        if (!(resources->filter == obj))
+            resources.access()->filter = obj;
+    }
+
+    void setMaskerResource(const String& obj)
+    {
+        if (!(resources->masker == obj))
+            resources.access()->masker = obj;
+    }
+
+    // Setters for inherited resources
+    void setMarkerStartResource(const String& obj)
+    {
+        if (!(inheritedResources->markerStart == obj))
+            inheritedResources.access()->markerStart = obj;
+    }
+
+    void setMarkerMidResource(const String& obj)
+    {
+        if (!(inheritedResources->markerMid == obj))
+            inheritedResources.access()->markerMid = obj;
+    }
+
+    void setMarkerEndResource(const String& obj)
+    {
+        if (!(inheritedResources->markerEnd == obj))
+            inheritedResources.access()->markerEnd = obj;
+    }
+
+    // Read accessors for all the properties
+    EAlignmentBaseline alignmentBaseline() const { return (EAlignmentBaseline) svg_noninherited_flags.f._alignmentBaseline; }
+    EDominantBaseline dominantBaseline() const { return (EDominantBaseline) svg_noninherited_flags.f._dominantBaseline; }
+    EBaselineShift baselineShift() const { return (EBaselineShift) svg_noninherited_flags.f._baselineShift; }
+    EVectorEffect vectorEffect() const { return (EVectorEffect) svg_noninherited_flags.f._vectorEffect; }
+    EBufferedRendering bufferedRendering() const { return (EBufferedRendering) svg_noninherited_flags.f.bufferedRendering; }
+    LineCap capStyle() const { return (LineCap) svg_inherited_flags._capStyle; }
+    WindRule clipRule() const { return (WindRule) svg_inherited_flags._clipRule; }
+    EColorInterpolation colorInterpolation() const { return (EColorInterpolation) svg_inherited_flags._colorInterpolation; }
+    EColorInterpolation colorInterpolationFilters() const { return (EColorInterpolation) svg_inherited_flags._colorInterpolationFilters; }
+    EColorRendering colorRendering() const { return (EColorRendering) svg_inherited_flags._colorRendering; }
+    WindRule fillRule() const { return (WindRule) svg_inherited_flags._fillRule; }
+    LineJoin joinStyle() const { return (LineJoin) svg_inherited_flags._joinStyle; }
+    EShapeRendering shapeRendering() const { return (EShapeRendering) svg_inherited_flags._shapeRendering; }
+    ETextAnchor textAnchor() const { return (ETextAnchor) svg_inherited_flags._textAnchor; }
+    SVGWritingMode writingMode() const { return (SVGWritingMode) svg_inherited_flags._writingMode; }
+    EGlyphOrientation glyphOrientationHorizontal() const { return (EGlyphOrientation) svg_inherited_flags._glyphOrientationHorizontal; }
+    EGlyphOrientation glyphOrientationVertical() const { return (EGlyphOrientation) svg_inherited_flags._glyphOrientationVertical; }
+    float fillOpacity() const { return fill->opacity; }
+    const SVGPaint::SVGPaintType& fillPaintType() const { return fill->paintType; }
+    const Color& fillPaintColor() const { return fill->paintColor; }
+    const String& fillPaintUri() const { return fill->paintUri; }    
+    float strokeOpacity() const { return stroke->opacity; }
+    const SVGPaint::SVGPaintType& strokePaintType() const { return stroke->paintType; }
+    const Color& strokePaintColor() const { return stroke->paintColor; }
+    const String& strokePaintUri() const { return stroke->paintUri; }
+    Vector<SVGLength> strokeDashArray() const { return stroke->dashArray; }
+    float strokeMiterLimit() const { return stroke->miterLimit; }
+    SVGLength strokeWidth() const { return stroke->width; }
+    SVGLength strokeDashOffset() const { return stroke->dashOffset; }
+    SVGLength kerning() const { return text->kerning; }
+    float stopOpacity() const { return stops->opacity; }
+    const Color& stopColor() const { return stops->color; }
+    float floodOpacity() const { return misc->floodOpacity; }
+    const Color& floodColor() const { return misc->floodColor; }
+    const Color& lightingColor() const { return misc->lightingColor; }
+    SVGLength baselineShiftValue() const { return misc->baselineShiftValue; }
+    ShadowData* shadow() const { return shadowSVG->shadow.get(); }
+    String clipperResource() const { return resources->clipper; }
+    String filterResource() const { return resources->filter; }
+    String maskerResource() const { return resources->masker; }
+    String markerStartResource() const { return inheritedResources->markerStart; }
+    String markerMidResource() const { return inheritedResources->markerMid; }
+    String markerEndResource() const { return inheritedResources->markerEnd; }
+    EMaskType maskType() const { return (EMaskType) svg_noninherited_flags.f.maskType; }
+
+    const SVGPaint::SVGPaintType& visitedLinkFillPaintType() const { return fill->visitedLinkPaintType; }
+    const Color& visitedLinkFillPaintColor() const { return fill->visitedLinkPaintColor; }
+    const String& visitedLinkFillPaintUri() const { return fill->visitedLinkPaintUri; }
+    const SVGPaint::SVGPaintType& visitedLinkStrokePaintType() const { return stroke->visitedLinkPaintType; }
+    const Color& visitedLinkStrokePaintColor() const { return stroke->visitedLinkPaintColor; }
+    const String& visitedLinkStrokePaintUri() const { return stroke->visitedLinkPaintUri; }
+
+    // convenience
+    bool hasClipper() const { return !clipperResource().isEmpty(); }
+    bool hasMasker() const { return !maskerResource().isEmpty(); }
+    bool hasFilter() const { return !filterResource().isEmpty(); }
+    bool hasMarkers() const { return !markerStartResource().isEmpty() || !markerMidResource().isEmpty() || !markerEndResource().isEmpty(); }
+    bool hasStroke() const { return strokePaintType() != SVGPaint::SVG_PAINTTYPE_NONE; }
+    bool hasVisibleStroke() const { return hasStroke() && !strokeWidth().isZero(); }
+    bool hasFill() const { return fillPaintType() != SVGPaint::SVG_PAINTTYPE_NONE; }
+    bool isVerticalWritingMode() const { return writingMode() == WM_TBRL || writingMode() == WM_TB; }
+
+protected:
+    // inherit
+    struct InheritedFlags {
+        bool operator==(const InheritedFlags& other) const
+        {
+            return (_colorRendering == other._colorRendering)
+                && (_shapeRendering == other._shapeRendering)
+                && (_clipRule == other._clipRule)
+                && (_fillRule == other._fillRule)
+                && (_capStyle == other._capStyle)
+                && (_joinStyle == other._joinStyle)
+                && (_textAnchor == other._textAnchor)
+                && (_colorInterpolation == other._colorInterpolation)
+                && (_colorInterpolationFilters == other._colorInterpolationFilters)
+                && (_writingMode == other._writingMode)
+                && (_glyphOrientationHorizontal == other._glyphOrientationHorizontal)
+                && (_glyphOrientationVertical == other._glyphOrientationVertical);
+        }
+
+        bool operator!=(const InheritedFlags& other) const
+        {
+            return !(*this == other);
+        }
+
+        unsigned _colorRendering : 2; // EColorRendering
+        unsigned _shapeRendering : 2; // EShapeRendering 
+        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 _writingMode : 3; // SVGWritingMode
+        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
+                unsigned _vectorEffect: 1; // EVectorEffect
+                unsigned bufferedRendering: 2; // EBufferedRendering
+                unsigned maskType: 1; // EMaskType
+                // 18 bits unused
+            } f;
+            uint32_t _niflags;
+        };
+    } svg_noninherited_flags;
+
+    // inherited attributes
+    DataRef<StyleFillData> fill;
+    DataRef<StyleStrokeData> stroke;
+    DataRef<StyleTextData> text;
+    DataRef<StyleInheritedResourceData> inheritedResources;
+
+    // non-inherited attributes
+    DataRef<StyleStopData> stops;
+    DataRef<StyleMiscData> misc;
+    DataRef<StyleShadowSVGData> shadowSVG;
+    DataRef<StyleResourceData> resources;
+
+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._shapeRendering = initialShapeRendering();
+        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._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();
+        svg_noninherited_flags.f._vectorEffect = initialVectorEffect();
+        svg_noninherited_flags.f.bufferedRendering = initialBufferedRendering();
+        svg_noninherited_flags.f.maskType = initialMaskType();
+    }
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
+#endif // SVGRenderStyle_h
diff --git a/Source/core/rendering/style/SVGRenderStyleDefs.cpp b/Source/core/rendering/style/SVGRenderStyleDefs.cpp
new file mode 100644
index 0000000..a48e51d
--- /dev/null
+++ b/Source/core/rendering/style/SVGRenderStyleDefs.cpp
@@ -0,0 +1,243 @@
+/*
+    Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org>
+                  2004, 2005, 2007 Rob Buis <buis@kde.org>
+    Copyright (C) Research In Motion Limited 2010. All rights reserved.
+
+    Based on khtml code by:
+    Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
+    Copyright (C) 1999-2003 Lars Knoll (knoll@kde.org)
+    Copyright (C) 2002-2003 Dirk Mueller (mueller@kde.org)
+    Copyright (C) 2002 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 "core/rendering/style/SVGRenderStyleDefs.h"
+
+#include "core/rendering/style/RenderStyle.h"
+#include "core/rendering/style/SVGRenderStyle.h"
+
+namespace WebCore {
+
+StyleFillData::StyleFillData()
+    : opacity(SVGRenderStyle::initialFillOpacity())
+    , paintType(SVGRenderStyle::initialFillPaintType())
+    , paintColor(SVGRenderStyle::initialFillPaintColor())
+    , paintUri(SVGRenderStyle::initialFillPaintUri())
+    , visitedLinkPaintType(SVGRenderStyle::initialStrokePaintType())
+    , visitedLinkPaintColor(SVGRenderStyle::initialFillPaintColor())
+    , visitedLinkPaintUri(SVGRenderStyle::initialFillPaintUri())
+{
+}
+
+StyleFillData::StyleFillData(const StyleFillData& other)
+    : RefCounted<StyleFillData>()
+    , opacity(other.opacity)
+    , paintType(other.paintType)
+    , paintColor(other.paintColor)
+    , paintUri(other.paintUri)
+    , visitedLinkPaintType(other.visitedLinkPaintType)
+    , visitedLinkPaintColor(other.visitedLinkPaintColor)
+    , visitedLinkPaintUri(other.visitedLinkPaintUri)
+{
+}
+
+bool StyleFillData::operator==(const StyleFillData& other) const
+{
+    return opacity == other.opacity 
+        && paintType == other.paintType
+        && paintColor == other.paintColor
+        && paintUri == other.paintUri
+        && visitedLinkPaintType == other.visitedLinkPaintType
+        && visitedLinkPaintColor == other.visitedLinkPaintColor
+        && visitedLinkPaintUri == other.visitedLinkPaintUri;
+}
+
+StyleStrokeData::StyleStrokeData()
+    : opacity(SVGRenderStyle::initialStrokeOpacity())
+    , miterLimit(SVGRenderStyle::initialStrokeMiterLimit())
+    , width(SVGRenderStyle::initialStrokeWidth())
+    , dashOffset(SVGRenderStyle::initialStrokeDashOffset())
+    , dashArray(SVGRenderStyle::initialStrokeDashArray())
+    , paintType(SVGRenderStyle::initialStrokePaintType())
+    , paintColor(SVGRenderStyle::initialStrokePaintColor())
+    , paintUri(SVGRenderStyle::initialStrokePaintUri())
+    , visitedLinkPaintType(SVGRenderStyle::initialStrokePaintType())
+    , visitedLinkPaintColor(SVGRenderStyle::initialStrokePaintColor())
+    , visitedLinkPaintUri(SVGRenderStyle::initialStrokePaintUri())
+{
+}
+
+StyleStrokeData::StyleStrokeData(const StyleStrokeData& other)
+    : RefCounted<StyleStrokeData>()
+    , opacity(other.opacity)
+    , miterLimit(other.miterLimit)
+    , width(other.width)
+    , dashOffset(other.dashOffset)
+    , dashArray(other.dashArray)
+    , paintType(other.paintType)
+    , paintColor(other.paintColor)
+    , paintUri(other.paintUri)
+    , visitedLinkPaintType(other.visitedLinkPaintType)
+    , visitedLinkPaintColor(other.visitedLinkPaintColor)
+    , visitedLinkPaintUri(other.visitedLinkPaintUri)
+{
+}
+
+bool StyleStrokeData::operator==(const StyleStrokeData& other) const
+{
+    return width == other.width
+        && opacity == other.opacity
+        && miterLimit == other.miterLimit
+        && dashOffset == other.dashOffset
+        && dashArray == other.dashArray
+        && paintType == other.paintType
+        && paintColor == other.paintColor
+        && paintUri == other.paintUri
+        && visitedLinkPaintType == other.visitedLinkPaintType
+        && visitedLinkPaintColor == other.visitedLinkPaintColor
+        && visitedLinkPaintUri == other.visitedLinkPaintUri;
+}
+
+StyleStopData::StyleStopData()
+    : opacity(SVGRenderStyle::initialStopOpacity())
+    , color(SVGRenderStyle::initialStopColor())
+{
+}
+
+StyleStopData::StyleStopData(const StyleStopData& other)
+    : RefCounted<StyleStopData>()
+    , opacity(other.opacity)
+    , color(other.color)
+{
+}
+
+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;
+}
+
+StyleMiscData::StyleMiscData()
+    : floodColor(SVGRenderStyle::initialFloodColor())
+    , floodOpacity(SVGRenderStyle::initialFloodOpacity())
+    , lightingColor(SVGRenderStyle::initialLightingColor())
+    , baselineShiftValue(SVGRenderStyle::initialBaselineShiftValue())
+{
+}
+
+StyleMiscData::StyleMiscData(const StyleMiscData& other)
+    : RefCounted<StyleMiscData>()
+    , floodColor(other.floodColor)
+    , floodOpacity(other.floodOpacity)
+    , lightingColor(other.lightingColor)
+    , baselineShiftValue(other.baselineShiftValue)
+{
+}
+
+bool StyleMiscData::operator==(const StyleMiscData& other) const
+{
+    return floodOpacity == other.floodOpacity
+        && floodColor == other.floodColor
+        && lightingColor == other.lightingColor
+        && baselineShiftValue == other.baselineShiftValue;
+}
+
+StyleShadowSVGData::StyleShadowSVGData()
+{
+}
+
+StyleShadowSVGData::StyleShadowSVGData(const StyleShadowSVGData& other)
+    : RefCounted<StyleShadowSVGData>()
+    , shadow(other.shadow ? adoptPtr(new ShadowData(*other.shadow)) : nullptr)
+{
+}
+
+bool StyleShadowSVGData::operator==(const StyleShadowSVGData& other) const
+{
+    if ((!shadow && other.shadow) || (shadow && !other.shadow))
+        return false;
+    if (shadow && other.shadow && (*shadow != *other.shadow))
+        return false;
+    return true;
+}
+
+StyleResourceData::StyleResourceData()
+    : clipper(SVGRenderStyle::initialClipperResource())
+    , filter(SVGRenderStyle::initialFilterResource())
+    , masker(SVGRenderStyle::initialMaskerResource())
+{
+}
+
+StyleResourceData::StyleResourceData(const StyleResourceData& other)
+    : RefCounted<StyleResourceData>()
+    , clipper(other.clipper)
+    , filter(other.filter)
+    , masker(other.masker)
+{
+}
+
+bool StyleResourceData::operator==(const StyleResourceData& other) const
+{
+    return clipper == other.clipper
+        && filter == other.filter
+        && masker == other.masker;
+}
+
+StyleInheritedResourceData::StyleInheritedResourceData()
+    : markerStart(SVGRenderStyle::initialMarkerStartResource())
+    , markerMid(SVGRenderStyle::initialMarkerMidResource())
+    , markerEnd(SVGRenderStyle::initialMarkerEndResource())
+{
+}
+
+StyleInheritedResourceData::StyleInheritedResourceData(const StyleInheritedResourceData& other)
+    : RefCounted<StyleInheritedResourceData>()
+    , markerStart(other.markerStart)
+    , markerMid(other.markerMid)
+    , markerEnd(other.markerEnd)
+{
+}
+
+bool StyleInheritedResourceData::operator==(const StyleInheritedResourceData& other) const
+{
+    return markerStart == other.markerStart
+        && markerMid == other.markerMid
+        && markerEnd == other.markerEnd;
+}
+
+}
+
+#endif // ENABLE(SVG)
diff --git a/Source/core/rendering/style/SVGRenderStyleDefs.h b/Source/core/rendering/style/SVGRenderStyleDefs.h
new file mode 100644
index 0000000..11d0a6f
--- /dev/null
+++ b/Source/core/rendering/style/SVGRenderStyleDefs.h
@@ -0,0 +1,280 @@
+/*
+    Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org>
+                  2004, 2005 Rob Buis <buis@kde.org>
+    Copyright (C) Research In Motion Limited 2010. All rights reserved.
+
+    Based on khtml code by:
+    Copyright (C) 2000-2003 Lars Knoll (knoll@kde.org)
+              (C) 2000 Antti Koivisto (koivisto@kde.org)
+              (C) 2000-2003 Dirk Mueller (mueller@kde.org)
+              (C) 2002-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 SVGRenderStyleDefs_h
+#define SVGRenderStyleDefs_h
+
+#if ENABLE(SVG)
+#include "core/rendering/style/ShadowData.h"
+#include "core/svg/SVGLength.h"
+#include "core/svg/SVGPaint.h"
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+
+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 EShapeRendering {
+        SR_AUTO, SR_OPTIMIZESPEED, SR_CRISPEDGES, SR_GEOMETRICPRECISION
+    };
+
+    enum SVGWritingMode {
+        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 EVectorEffect {
+        VE_NONE,
+        VE_NON_SCALING_STROKE
+    };
+
+    enum EBufferedRendering {
+        BR_AUTO,
+        BR_DYNAMIC,
+        BR_STATIC
+    };
+
+    enum EMaskType {
+        MT_LUMINANCE,
+        MT_ALPHA
+    };
+
+    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&) const;
+        bool operator!=(const StyleFillData& other) const
+        {
+            return !(*this == other);
+        }
+
+        float opacity;
+        SVGPaint::SVGPaintType paintType;
+        Color paintColor;
+        String paintUri;
+        SVGPaint::SVGPaintType visitedLinkPaintType;
+        Color visitedLinkPaintColor;
+        String visitedLinkPaintUri;
+
+    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;
+
+        SVGLength width;
+        SVGLength dashOffset;
+        Vector<SVGLength> dashArray;
+
+        SVGPaint::SVGPaintType paintType;
+        Color paintColor;
+        String paintUri;
+        SVGPaint::SVGPaintType visitedLinkPaintType;
+        Color visitedLinkPaintColor;
+        String visitedLinkPaintUri;
+
+    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&) 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);
+        }
+
+        SVGLength kerning;
+
+    private:
+        StyleTextData();
+        StyleTextData(const StyleTextData&);
+    };
+
+    // 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&) const;
+        bool operator!=(const StyleMiscData& other) const
+        {
+            return !(*this == other);
+        }
+
+        Color floodColor;
+        float floodOpacity;
+        Color lightingColor;
+
+        // non-inherited text stuff lives here not in StyleTextData.
+        SVGLength baselineShiftValue;
+
+    private:
+        StyleMiscData();
+        StyleMiscData(const StyleMiscData&);
+    };
+
+    class StyleShadowSVGData : public RefCounted<StyleShadowSVGData> {
+    public:
+        static PassRefPtr<StyleShadowSVGData> create() { return adoptRef(new StyleShadowSVGData); }
+        PassRefPtr<StyleShadowSVGData> copy() const { return adoptRef(new StyleShadowSVGData(*this)); }
+
+        bool operator==(const StyleShadowSVGData&) const;
+        bool operator!=(const StyleShadowSVGData& other) const
+        {
+            return !(*this == other);
+        }
+
+        OwnPtr<ShadowData> shadow;
+
+    private:
+        StyleShadowSVGData();
+        StyleShadowSVGData(const StyleShadowSVGData&);
+    };
+
+    // Non-inherited resources
+    class StyleResourceData : public RefCounted<StyleResourceData> {
+    public:
+        static PassRefPtr<StyleResourceData> create() { return adoptRef(new StyleResourceData); }
+        PassRefPtr<StyleResourceData> copy() const { return adoptRef(new StyleResourceData(*this)); }
+
+        bool operator==(const StyleResourceData&) const;
+        bool operator!=(const StyleResourceData& other) const
+        {
+            return !(*this == other);
+        }
+
+        String clipper;
+        String filter;
+        String masker;
+
+    private:
+        StyleResourceData();
+        StyleResourceData(const StyleResourceData&);
+    };
+
+    // Inherited resources
+    class StyleInheritedResourceData : public RefCounted<StyleInheritedResourceData> {
+    public:
+        static PassRefPtr<StyleInheritedResourceData> create() { return adoptRef(new StyleInheritedResourceData); }
+        PassRefPtr<StyleInheritedResourceData> copy() const { return adoptRef(new StyleInheritedResourceData(*this)); }
+
+        bool operator==(const StyleInheritedResourceData&) const;
+        bool operator!=(const StyleInheritedResourceData& other) const
+        {
+            return !(*this == other);
+        }
+
+        String markerStart;
+        String markerMid;
+        String markerEnd;
+
+    private:
+        StyleInheritedResourceData();
+        StyleInheritedResourceData(const StyleInheritedResourceData&);
+    };
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
+#endif // SVGRenderStyleDefs_h
diff --git a/Source/core/rendering/style/ShadowData.cpp b/Source/core/rendering/style/ShadowData.cpp
new file mode 100644
index 0000000..d1621b5
--- /dev/null
+++ b/Source/core/rendering/style/ShadowData.cpp
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 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 "core/rendering/style/ShadowData.h"
+
+#include "core/platform/graphics/LayoutRect.h"
+
+using namespace std;
+
+namespace WebCore {
+
+ShadowData::ShadowData(const ShadowData& o)
+    : m_location(o.m_location)
+    , m_blur(o.m_blur)
+    , m_spread(o.m_spread)
+    , m_color(o.m_color)
+    , m_style(o.m_style)
+    , m_isWebkitBoxShadow(o.m_isWebkitBoxShadow)
+    , m_next(o.m_next ? adoptPtr(new ShadowData(*o.m_next)) : nullptr)
+{
+}
+
+bool ShadowData::operator==(const ShadowData& 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;
+    
+    return m_location == o.m_location
+        && m_blur == o.m_blur
+        && m_spread == o.m_spread
+        && m_style == o.m_style
+        && m_color == o.m_color
+        && m_isWebkitBoxShadow == o.m_isWebkitBoxShadow;
+}
+
+static inline void calculateShadowExtent(const ShadowData* shadow, int additionalOutlineSize, int& shadowLeft, int& shadowRight, int& shadowTop, int& shadowBottom)
+{
+    do {
+        int blurAndSpread = shadow->blur() + shadow->spread() + additionalOutlineSize;
+        if (shadow->style() == Normal) {
+            shadowLeft = min(shadow->x() - blurAndSpread, shadowLeft);
+            shadowRight = max(shadow->x() + blurAndSpread, shadowRight);
+            shadowTop = min(shadow->y() - blurAndSpread, shadowTop);
+            shadowBottom = max(shadow->y() + blurAndSpread, shadowBottom);
+        }
+
+        shadow = shadow->next();
+    } while (shadow);
+}
+
+void ShadowData::adjustRectForShadow(LayoutRect& rect, int additionalOutlineSize) const
+{
+    int shadowLeft = 0;
+    int shadowRight = 0;
+    int shadowTop = 0;
+    int shadowBottom = 0;
+    calculateShadowExtent(this, additionalOutlineSize, shadowLeft, shadowRight, shadowTop, shadowBottom);
+
+    rect.move(shadowLeft, shadowTop);
+    rect.setWidth(rect.width() - shadowLeft + shadowRight);
+    rect.setHeight(rect.height() - shadowTop + shadowBottom);
+}
+
+void ShadowData::adjustRectForShadow(FloatRect& rect, int additionalOutlineSize) const
+{
+    int shadowLeft = 0;
+    int shadowRight = 0;
+    int shadowTop = 0;
+    int shadowBottom = 0;
+    calculateShadowExtent(this, additionalOutlineSize, shadowLeft, shadowRight, shadowTop, shadowBottom);
+
+    rect.move(shadowLeft, shadowTop);
+    rect.setWidth(rect.width() - shadowLeft + shadowRight);
+    rect.setHeight(rect.height() - shadowTop + shadowBottom);
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/style/ShadowData.h b/Source/core/rendering/style/ShadowData.h
new file mode 100644
index 0000000..fbf3b95
--- /dev/null
+++ b/Source/core/rendering/style/ShadowData.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ *           (C) 2000 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com)
+ *
+ * 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 "core/platform/graphics/Color.h"
+#include "core/platform/graphics/FloatRect.h"
+#include "core/platform/graphics/LayoutRect.h"
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+
+namespace WebCore {
+
+enum ShadowStyle { Normal, Inset };
+
+// This class holds information about shadows for the text-shadow and box-shadow properties.
+
+class ShadowData {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    ShadowData()
+        : m_blur(0)
+        , m_spread(0)
+        , m_style(Normal)
+        , m_isWebkitBoxShadow(false)
+    {
+    }
+
+    ShadowData(const IntPoint& location, int blur, int spread, ShadowStyle style, bool isWebkitBoxShadow, const Color& color)
+        : m_location(location)
+        , m_blur(blur)
+        , m_spread(spread)
+        , m_color(color)
+        , m_style(style)
+        , m_isWebkitBoxShadow(isWebkitBoxShadow)
+    {
+    }
+
+    ShadowData(const ShadowData& o);
+
+    bool operator==(const ShadowData& o) const;
+    bool operator!=(const ShadowData& o) const
+    {
+        return !(*this == o);
+    }
+    
+    int x() const { return m_location.x(); }
+    int y() const { return m_location.y(); }
+    IntPoint location() const { return m_location; }
+    int blur() const { return m_blur; }
+    int spread() const { return m_spread; }
+    ShadowStyle style() const { return m_style; }
+    const Color& color() const { return m_color; }
+    bool isWebkitBoxShadow() const { return m_isWebkitBoxShadow; }
+
+    const ShadowData* next() const { return m_next.get(); }
+    void setNext(PassOwnPtr<ShadowData> shadow) { m_next = shadow; }
+
+    void adjustRectForShadow(LayoutRect&, int additionalOutlineSize = 0) const;
+    void adjustRectForShadow(FloatRect&, int additionalOutlineSize = 0) const;
+
+private:
+    IntPoint m_location;
+    int m_blur;
+    int m_spread;
+    Color m_color;
+    ShadowStyle m_style;
+    bool m_isWebkitBoxShadow;
+    OwnPtr<ShadowData> m_next;
+};
+
+} // namespace WebCore
+
+#endif // ShadowData_h
diff --git a/Source/core/rendering/style/StyleBackgroundData.cpp b/Source/core/rendering/style/StyleBackgroundData.cpp
new file mode 100644
index 0000000..8c4261e
--- /dev/null
+++ b/Source/core/rendering/style/StyleBackgroundData.cpp
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * 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 "core/rendering/style/StyleBackgroundData.h"
+
+#include "core/rendering/style/RenderStyle.h"
+#include "core/rendering/style/RenderStyleConstants.h"
+
+namespace WebCore {
+
+StyleBackgroundData::StyleBackgroundData()
+    : m_background(BackgroundFillLayer)
+    , m_color(RenderStyle::initialBackgroundColor())
+{
+}
+
+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/Source/core/rendering/style/StyleBackgroundData.h b/Source/core/rendering/style/StyleBackgroundData.h
new file mode 100644
index 0000000..d2d834a
--- /dev/null
+++ b/Source/core/rendering/style/StyleBackgroundData.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ *           (C) 2000 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com)
+ *
+ * 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 "core/platform/graphics/Color.h"
+#include "core/rendering/style/FillLayer.h"
+#include "core/rendering/style/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);
+    }
+
+    const FillLayer& background() const { return m_background; }
+    const Color& color() const { return m_color; }
+    const OutlineValue& outline() const { return m_outline; }
+
+private:
+    friend class RenderStyle;
+
+    StyleBackgroundData();
+    StyleBackgroundData(const StyleBackgroundData&); 
+
+    FillLayer m_background;
+    Color m_color;
+    OutlineValue m_outline;
+};
+
+} // namespace WebCore
+
+#endif // StyleBackgroundData_h
diff --git a/Source/core/rendering/style/StyleBoxData.cpp b/Source/core/rendering/style/StyleBoxData.cpp
new file mode 100644
index 0000000..f78d548
--- /dev/null
+++ b/Source/core/rendering/style/StyleBoxData.cpp
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * 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 "core/rendering/style/StyleBoxData.h"
+
+#include "core/rendering/style/RenderStyle.h"
+#include "core/rendering/style/RenderStyleConstants.h"
+
+namespace WebCore {
+
+struct SameSizeAsStyleBoxData : public RefCounted<SameSizeAsStyleBoxData> {
+    Length length[7];
+    int m_zIndex;
+    uint32_t bitfields;
+};
+
+COMPILE_ASSERT(sizeof(StyleBoxData) == sizeof(SameSizeAsStyleBoxData), StyleBoxData_should_not_grow);
+
+StyleBoxData::StyleBoxData()
+    : m_minWidth(RenderStyle::initialMinSize())
+    , m_maxWidth(RenderStyle::initialMaxSize())
+    , m_minHeight(RenderStyle::initialMinSize())
+    , m_maxHeight(RenderStyle::initialMaxSize())
+    , m_zIndex(0)
+    , m_hasAutoZIndex(true)
+    , m_boxSizing(CONTENT_BOX)
+    , m_boxDecorationBreak(DSLICE)
+{
+}
+
+StyleBoxData::StyleBoxData(const StyleBoxData& o)
+    : RefCounted<StyleBoxData>()
+    , m_width(o.m_width)
+    , m_height(o.m_height)
+    , m_minWidth(o.m_minWidth)
+    , m_maxWidth(o.m_maxWidth)
+    , m_minHeight(o.m_minHeight)
+    , m_maxHeight(o.m_maxHeight)
+    , m_verticalAlign(o.m_verticalAlign)
+    , m_zIndex(o.m_zIndex)
+    , m_hasAutoZIndex(o.m_hasAutoZIndex)
+    , m_boxSizing(o.m_boxSizing)
+    , m_boxDecorationBreak(o.m_boxDecorationBreak)
+{
+}
+
+bool StyleBoxData::operator==(const StyleBoxData& o) const
+{
+    return m_width == o.m_width
+           && m_height == o.m_height
+           && m_minWidth == o.m_minWidth
+           && m_maxWidth == o.m_maxWidth
+           && m_minHeight == o.m_minHeight
+           && m_maxHeight == o.m_maxHeight
+           && m_verticalAlign == o.m_verticalAlign
+           && m_zIndex == o.m_zIndex
+           && m_hasAutoZIndex == o.m_hasAutoZIndex
+           && m_boxSizing == o.m_boxSizing
+           && m_boxDecorationBreak == o.m_boxDecorationBreak
+            ;
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/style/StyleBoxData.h b/Source/core/rendering/style/StyleBoxData.h
new file mode 100644
index 0000000..7f4bd71
--- /dev/null
+++ b/Source/core/rendering/style/StyleBoxData.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ *           (C) 2000 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com)
+ *
+ * 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 "core/platform/Length.h"
+#include "core/rendering/style/RenderStyleConstants.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.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() const { return m_width; }
+    Length height() const { return m_height; }
+    
+    Length minWidth() const { return m_minWidth; }
+    Length minHeight() const { return m_minHeight; }
+    
+    Length maxWidth() const { return m_maxWidth; }
+    Length maxHeight() const { return m_maxHeight; }
+    
+    Length verticalAlign() const { return m_verticalAlign; }
+    
+    int zIndex() const { return m_zIndex; }
+    bool hasAutoZIndex() const { return m_hasAutoZIndex; }
+    
+    EBoxSizing boxSizing() const { return static_cast<EBoxSizing>(m_boxSizing); }
+    EBoxDecorationBreak boxDecorationBreak() const { return static_cast<EBoxDecorationBreak>(m_boxDecorationBreak); }
+
+private:
+    friend class RenderStyle;
+
+    StyleBoxData();
+    StyleBoxData(const StyleBoxData&);
+
+    Length m_width;
+    Length m_height;
+
+    Length m_minWidth;
+    Length m_maxWidth;
+
+    Length m_minHeight;
+    Length m_maxHeight;
+
+    Length m_verticalAlign;
+
+    int m_zIndex;
+    unsigned m_hasAutoZIndex : 1;
+    unsigned m_boxSizing : 1; // EBoxSizing
+    unsigned m_boxDecorationBreak : 1; // EBoxDecorationBreak
+};
+
+} // namespace WebCore
+
+#endif // StyleBoxData_h
diff --git a/Source/core/rendering/style/StyleCachedImage.cpp b/Source/core/rendering/style/StyleCachedImage.cpp
new file mode 100644
index 0000000..27ecb0d
--- /dev/null
+++ b/Source/core/rendering/style/StyleCachedImage.cpp
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ *           (C) 2000 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2000 Dirk Mueller (mueller@kde.org)
+ * 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 "core/rendering/style/StyleCachedImage.h"
+
+#include "core/loader/cache/CachedImage.h"
+#include "core/rendering/RenderObject.h"
+
+namespace WebCore {
+
+StyleCachedImage::StyleCachedImage(CachedImage* image)
+    : m_image(image)
+{
+    m_isCachedImage = true;
+    m_image->addClient(this);
+}
+
+StyleCachedImage::~StyleCachedImage()
+{
+    m_image->removeClient(this);
+}
+
+PassRefPtr<CSSValue> StyleCachedImage::cssValue() const
+{
+    return CSSPrimitiveValue::create(m_image->url(), CSSPrimitiveValue::CSS_URI);
+}
+
+bool StyleCachedImage::canRender(const RenderObject* renderer, float multiplier) const
+{
+    return m_image->canRender(renderer, multiplier);
+}
+
+bool StyleCachedImage::isLoaded() const
+{
+    return m_image->isLoaded();
+}
+
+bool StyleCachedImage::errorOccurred() const
+{
+    return m_image->errorOccurred();
+}
+
+LayoutSize StyleCachedImage::imageSize(const RenderObject* renderer, float multiplier) const
+{
+    return m_image->imageSizeForRenderer(renderer, multiplier);
+}
+
+bool StyleCachedImage::imageHasRelativeWidth() const
+{
+    return m_image->imageHasRelativeWidth();
+}
+
+bool StyleCachedImage::imageHasRelativeHeight() const
+{
+    return m_image->imageHasRelativeHeight();
+}
+
+void StyleCachedImage::computeIntrinsicDimensions(const RenderObject*, Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio)
+{
+    m_image->computeIntrinsicDimensions(intrinsicWidth, intrinsicHeight, intrinsicRatio);
+}
+
+bool StyleCachedImage::usesImageContainerSize() const
+{
+    return m_image->usesImageContainerSize();
+}
+
+void StyleCachedImage::setContainerSizeForRenderer(const RenderObject* renderer, const IntSize& imageContainerSize, float imageContainerZoomFactor)
+{
+    m_image->setContainerSizeForRenderer(renderer, imageContainerSize, imageContainerZoomFactor);
+}
+
+void StyleCachedImage::addClient(RenderObject* renderer)
+{
+    m_image->addClient(renderer);
+}
+
+void StyleCachedImage::removeClient(RenderObject* renderer)
+{
+    m_image->removeClient(renderer);
+}
+
+PassRefPtr<Image> StyleCachedImage::image(RenderObject* renderer, const IntSize&) const
+{
+    return m_image->imageForRenderer(renderer);
+}
+
+bool StyleCachedImage::knownToBeOpaque(const RenderObject* renderer) const
+{
+    return m_image->currentFrameKnownToBeOpaque(renderer);
+}
+
+}
diff --git a/Source/core/rendering/style/StyleCachedImage.h b/Source/core/rendering/style/StyleCachedImage.h
new file mode 100644
index 0000000..f0d445c
--- /dev/null
+++ b/Source/core/rendering/style/StyleCachedImage.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ *           (C) 2000 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2000 Dirk Mueller (mueller@kde.org)
+ * 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 "core/loader/cache/CachedImageClient.h"
+#include "core/loader/cache/CachedResourceHandle.h"
+#include "core/rendering/style/StyleImage.h"
+
+namespace WebCore {
+
+class CachedImage;
+
+class StyleCachedImage : public StyleImage, private CachedImageClient {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    static PassRefPtr<StyleCachedImage> create(CachedImage* image) { return adoptRef(new StyleCachedImage(image)); }
+    virtual ~StyleCachedImage();
+
+    virtual WrappedImagePtr data() const { return m_image.get(); }
+
+    virtual PassRefPtr<CSSValue> cssValue() const;
+    
+    virtual bool canRender(const RenderObject*, float multiplier) const;
+    virtual bool isLoaded() const;
+    virtual bool errorOccurred() const;
+    virtual LayoutSize imageSize(const RenderObject*, float multiplier) const OVERRIDE;
+    virtual bool imageHasRelativeWidth() const;
+    virtual bool imageHasRelativeHeight() const;
+    virtual void computeIntrinsicDimensions(const RenderObject*, Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio);
+    virtual bool usesImageContainerSize() const;
+    virtual void setContainerSizeForRenderer(const RenderObject*, const IntSize&, float);
+    virtual void addClient(RenderObject*);
+    virtual void removeClient(RenderObject*);
+    virtual PassRefPtr<Image> image(RenderObject*, const IntSize&) const;
+    virtual bool knownToBeOpaque(const RenderObject*) const OVERRIDE;
+    virtual CachedImage* cachedImage() const OVERRIDE { return m_image.get(); }
+    
+private:
+    explicit StyleCachedImage(CachedImage*);
+    
+    CachedResourceHandle<CachedImage> m_image;
+};
+
+}
+#endif
diff --git a/Source/core/rendering/style/StyleCachedImageSet.cpp b/Source/core/rendering/style/StyleCachedImageSet.cpp
new file mode 100644
index 0000000..127f3f1
--- /dev/null
+++ b/Source/core/rendering/style/StyleCachedImageSet.cpp
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2012 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. 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 INC. 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 "core/rendering/style/StyleCachedImageSet.h"
+
+#include "core/css/CSSImageSetValue.h"
+#include "core/loader/cache/CachedImage.h"
+#include "core/rendering/RenderObject.h"
+
+namespace WebCore {
+
+StyleCachedImageSet::StyleCachedImageSet(CachedImage* image, float imageScaleFactor, CSSImageSetValue* value)
+    : m_bestFitImage(image)
+    , m_imageScaleFactor(imageScaleFactor)
+    , m_imageSetValue(value)
+{
+    m_isCachedImageSet = true;
+    m_bestFitImage->addClient(this);
+}
+
+
+StyleCachedImageSet::~StyleCachedImageSet()
+{
+    m_bestFitImage->removeClient(this);
+}
+
+PassRefPtr<CSSValue> StyleCachedImageSet::cssValue() const
+{
+    return m_imageSetValue;
+}
+
+bool StyleCachedImageSet::canRender(const RenderObject* renderer, float multiplier) const
+{
+    return m_bestFitImage->canRender(renderer, multiplier);
+}
+
+bool StyleCachedImageSet::isLoaded() const
+{
+    return m_bestFitImage->isLoaded();
+}
+
+bool StyleCachedImageSet::errorOccurred() const
+{
+    return m_bestFitImage->errorOccurred();
+}
+
+LayoutSize StyleCachedImageSet::imageSize(const RenderObject* renderer, float multiplier) const
+{
+    LayoutSize scaledImageSize = m_bestFitImage->imageSizeForRenderer(renderer, multiplier);
+    scaledImageSize.scale(1 / m_imageScaleFactor);
+    return scaledImageSize;
+}
+
+bool StyleCachedImageSet::imageHasRelativeWidth() const
+{
+    return m_bestFitImage->imageHasRelativeWidth();
+}
+
+bool StyleCachedImageSet::imageHasRelativeHeight() const
+{
+    return m_bestFitImage->imageHasRelativeHeight();
+}
+
+void StyleCachedImageSet::computeIntrinsicDimensions(const RenderObject*, Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio)
+{
+    m_bestFitImage->computeIntrinsicDimensions(intrinsicWidth, intrinsicHeight, intrinsicRatio);
+}
+
+bool StyleCachedImageSet::usesImageContainerSize() const
+{
+    return m_bestFitImage->usesImageContainerSize();
+}
+
+void StyleCachedImageSet::setContainerSizeForRenderer(const RenderObject* renderer, const IntSize& imageContainerSize, float imageContainerZoomFactor)
+{
+    m_bestFitImage->setContainerSizeForRenderer(renderer, imageContainerSize, imageContainerZoomFactor);
+}
+
+void StyleCachedImageSet::addClient(RenderObject* renderer)
+{
+    m_bestFitImage->addClient(renderer);
+}
+
+void StyleCachedImageSet::removeClient(RenderObject* renderer)
+{
+    m_bestFitImage->removeClient(renderer);
+}
+
+PassRefPtr<Image> StyleCachedImageSet::image(RenderObject* renderer, const IntSize&) const
+{
+    return m_bestFitImage->imageForRenderer(renderer);
+}
+
+bool StyleCachedImageSet::knownToBeOpaque(const RenderObject* renderer) const
+{
+    return m_bestFitImage->currentFrameKnownToBeOpaque(renderer);
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/style/StyleCachedImageSet.h b/Source/core/rendering/style/StyleCachedImageSet.h
new file mode 100644
index 0000000..313bdd9
--- /dev/null
+++ b/Source/core/rendering/style/StyleCachedImageSet.h
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2012 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. 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 INC. 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 StyleCachedImageSet_h
+#define StyleCachedImageSet_h
+
+#include "core/loader/cache/CachedImageClient.h"
+#include "core/loader/cache/CachedResourceHandle.h"
+#include "core/platform/graphics/LayoutSize.h"
+#include "core/rendering/style/StyleImage.h"
+
+namespace WebCore {
+
+class CachedImage;
+class CSSImageSetValue;
+
+// This class keeps one cached image and has access to a set of alternatives.
+
+class StyleCachedImageSet : public StyleImage, private CachedImageClient {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    static PassRefPtr<StyleCachedImageSet> create(CachedImage* image, float imageScaleFactor, CSSImageSetValue* value)
+    {
+        return adoptRef(new StyleCachedImageSet(image, imageScaleFactor, value));
+    }
+    virtual ~StyleCachedImageSet();
+
+    virtual PassRefPtr<CSSValue> cssValue() const;
+
+    // FIXME: This is used by StyleImage for equals comparison, but this implementation
+    // only looks at the image from the set that we have loaded. I'm not sure if that is
+    // meaningful enough or not.
+    virtual WrappedImagePtr data() const { return m_bestFitImage.get(); }
+
+    void clearImageSetValue() { m_imageSetValue = 0; }
+
+    virtual bool canRender(const RenderObject*, float multiplier) const;
+    virtual bool isLoaded() const;
+    virtual bool errorOccurred() const;
+    virtual LayoutSize imageSize(const RenderObject*, float multiplier) const;
+    virtual bool imageHasRelativeWidth() const;
+    virtual bool imageHasRelativeHeight() const;
+    virtual void computeIntrinsicDimensions(const RenderObject*, Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio);
+    virtual bool usesImageContainerSize() const;
+    virtual void setContainerSizeForRenderer(const RenderObject*, const IntSize&, float);
+    virtual void addClient(RenderObject*);
+    virtual void removeClient(RenderObject*);
+    virtual PassRefPtr<Image> image(RenderObject*, const IntSize&) const;
+    virtual float imageScaleFactor() const { return m_imageScaleFactor; }
+    virtual bool knownToBeOpaque(const RenderObject*) const OVERRIDE;
+    virtual CachedImage* cachedImage() const OVERRIDE { return m_bestFitImage.get(); }
+
+private:
+    StyleCachedImageSet(CachedImage*, float imageScaleFactor, CSSImageSetValue*);
+
+    CachedResourceHandle<CachedImage> m_bestFitImage;
+    float m_imageScaleFactor;
+    CSSImageSetValue* m_imageSetValue; // Not retained; it owns us.
+};
+
+} // namespace WebCore
+
+#endif // StyleCachedImageSet_h
diff --git a/Source/core/rendering/style/StyleCachedShader.cpp b/Source/core/rendering/style/StyleCachedShader.cpp
new file mode 100644
index 0000000..8a23a45
--- /dev/null
+++ b/Source/core/rendering/style/StyleCachedShader.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2011 Adobe Systems Incorporated. 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 THE COPYRIGHT HOLDER “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 THE COPYRIGHT HOLDER 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 "core/rendering/style/StyleCachedShader.h"
+
+#include "core/css/CSSPrimitiveValue.h"
+#include "core/loader/cache/CachedShader.h"
+
+namespace WebCore {
+
+
+StyleCachedShader::StyleCachedShader(CachedShader* shader)
+    : m_shader(shader)
+{
+     m_isCachedShader = true;
+}
+
+PassRefPtr<CSSValue> StyleCachedShader::cssValue() const
+{
+    return CSSPrimitiveValue::create(m_shader->url(), CSSPrimitiveValue::CSS_URI);
+}
+
+} // namespace WebCore
+
+
diff --git a/Source/core/rendering/style/StyleCachedShader.h b/Source/core/rendering/style/StyleCachedShader.h
new file mode 100644
index 0000000..bc79519
--- /dev/null
+++ b/Source/core/rendering/style/StyleCachedShader.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2011 Adobe Systems Incorporated. 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 THE COPYRIGHT HOLDER “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 THE COPYRIGHT HOLDER 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 StyleCachedShader_h
+#define StyleCachedShader_h
+
+#include "core/loader/cache/CachedResourceHandle.h"
+#include "core/rendering/style/StyleShader.h"
+
+namespace WebCore {
+
+class CachedShader;
+
+class StyleCachedShader : public StyleShader {
+public:
+    // FIXME: Keep a reference to the actual CachedShader in this class.
+    static PassRefPtr<StyleCachedShader> create(CachedShader* shader) { return adoptRef(new StyleCachedShader(shader)); }
+    
+    virtual PassRefPtr<CSSValue> cssValue() const;
+    
+    virtual CachedShader* cachedShader() const { return m_shader.get(); }
+    
+private:
+    StyleCachedShader(CachedShader*);
+    
+    CachedResourceHandle<CachedShader> m_shader;
+};
+
+}
+
+#endif // StyleCachedShader_h
diff --git a/Source/core/rendering/style/StyleCustomFilterProgram.cpp b/Source/core/rendering/style/StyleCustomFilterProgram.cpp
new file mode 100644
index 0000000..31c3d64
--- /dev/null
+++ b/Source/core/rendering/style/StyleCustomFilterProgram.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2013 Adobe Systems Incorporated. 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 THE COPYRIGHT HOLDER “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 THE COPYRIGHT HOLDER 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 "core/rendering/style/StyleCustomFilterProgram.h"
+
+#include "core/rendering/style/StyleCustomFilterProgramCache.h"
+
+namespace WebCore {
+
+StyleCustomFilterProgram::~StyleCustomFilterProgram()
+{
+    if (m_cache)
+        m_cache->remove(this);
+}
+
+} // namespace WebCore
+
+
diff --git a/Source/core/rendering/style/StyleCustomFilterProgram.h b/Source/core/rendering/style/StyleCustomFilterProgram.h
new file mode 100644
index 0000000..798e53b
--- /dev/null
+++ b/Source/core/rendering/style/StyleCustomFilterProgram.h
@@ -0,0 +1,185 @@
+/*
+ * Copyright (C) 2012 Adobe Systems Incorporated. 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 THE COPYRIGHT HOLDER “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 THE COPYRIGHT HOLDER 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 StyleCustomFilterProgram_h
+#define StyleCustomFilterProgram_h
+
+#include "core/loader/cache/CachedResourceClient.h"
+#include "core/loader/cache/CachedResourceHandle.h"
+#include "core/loader/cache/CachedShader.h"
+#include "core/platform/KURL.h"
+#include "core/platform/graphics/filters/custom/CustomFilterProgram.h"
+#include "core/rendering/style/StyleShader.h"
+#include <wtf/FastAllocBase.h>
+
+namespace WebCore {
+
+// CSS Shaders
+
+class StyleCustomFilterProgramCache;
+
+class StyleCustomFilterProgram : public CustomFilterProgram, public CachedResourceClient {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    static PassRefPtr<StyleCustomFilterProgram> create(KURL vertexShaderURL, PassRefPtr<StyleShader> vertexShader, 
+        KURL fragmentShaderURL, PassRefPtr<StyleShader> fragmentShader, CustomFilterProgramType programType,
+        const CustomFilterProgramMixSettings& mixSettings, CustomFilterMeshType meshType)
+    {
+        return adoptRef(new StyleCustomFilterProgram(vertexShaderURL, vertexShader, fragmentShaderURL, fragmentShader, programType, mixSettings, meshType));
+    }
+    
+    void setVertexShader(PassRefPtr<StyleShader> shader)
+    {
+        // The shader is immutable while in the cache.
+        ASSERT(!m_cache);
+        m_vertexShader = shader; 
+    }
+    StyleShader* vertexShader() const { return m_vertexShader.get(); }
+    
+    void setFragmentShader(PassRefPtr<StyleShader> shader)
+    {
+        // The shader is immutable while in the cache.
+        ASSERT(!m_cache);
+        m_fragmentShader = shader; 
+    }
+    StyleShader* fragmentShader() const { return m_fragmentShader.get(); }
+    
+    virtual String vertexShaderString() const
+    {
+        ASSERT(isLoaded());
+        return m_cachedVertexShader.get() ? m_cachedVertexShader->shaderString() : String();
+    }
+    
+    virtual String fragmentShaderString() const
+    {
+        ASSERT(isLoaded());
+        return m_cachedFragmentShader.get() ? m_cachedFragmentShader->shaderString() : String();
+    }
+
+    virtual bool isLoaded() const
+    {
+        // Do not use the CachedResource:isLoaded method here, because it actually means !isLoading(),
+        // so missing and canceled resources will have isLoaded set to true, even if they are not loaded yet.
+        ASSERT(!m_vertexShader || m_vertexShader->isCachedShader());
+        ASSERT(!m_fragmentShader || m_fragmentShader->isCachedShader());
+        ASSERT(m_cachedVertexShader.get() || m_cachedFragmentShader.get());
+        return (!m_cachedVertexShader.get() || m_isVertexShaderLoaded)
+            && (!m_cachedFragmentShader.get() || m_isFragmentShaderLoaded);
+    }
+
+    virtual void willHaveClients()
+    {
+        if (m_vertexShader) {
+            m_cachedVertexShader = m_vertexShader->cachedShader();
+            m_cachedVertexShader->addClient(this);
+        }
+        if (m_fragmentShader) {
+            m_cachedFragmentShader = m_fragmentShader->cachedShader();
+            m_cachedFragmentShader->addClient(this);
+        }
+    }
+    
+    virtual void didRemoveLastClient()
+    {
+        if (m_cachedVertexShader.get()) {
+            m_cachedVertexShader->removeClient(this);
+            m_cachedVertexShader = 0;
+            m_isVertexShaderLoaded = false;
+        }
+        if (m_cachedFragmentShader.get()) {
+            m_cachedFragmentShader->removeClient(this);
+            m_cachedFragmentShader = 0;
+            m_isFragmentShaderLoaded = false;
+        }
+    }
+    
+    virtual void notifyFinished(CachedResource* resource)
+    {
+        if (resource->errorOccurred())
+            return;
+        // Note that m_cachedVertexShader might be equal to m_cachedFragmentShader and it would only get one event in that case.
+        if (resource == m_cachedVertexShader.get())
+            m_isVertexShaderLoaded = true;
+        if (resource == m_cachedFragmentShader.get())
+            m_isFragmentShaderLoaded = true;
+        if (isLoaded())
+            notifyClients();
+    }
+
+    bool hasPendingShaders() const
+    {
+        return (m_vertexShader && m_vertexShader->isPendingShader()) 
+            || (m_fragmentShader && m_fragmentShader->isPendingShader());
+    }
+
+    // StyleCustomFilterProgramCache is responsible with updating the reference to the cache.
+    void setCache(StyleCustomFilterProgramCache* cache) { m_cache = cache; }
+    bool inCache() const { return m_cache; }
+    
+    KURL vertexShaderURL() const { return m_vertexShaderURL; }
+    KURL fragmentShaderURL() const { return m_fragmentShaderURL; }
+
+private:
+    StyleCustomFilterProgram(KURL vertexShaderURL, PassRefPtr<StyleShader> vertexShader, KURL fragmentShaderURL, PassRefPtr<StyleShader> fragmentShader, 
+        CustomFilterProgramType programType, const CustomFilterProgramMixSettings& mixSettings, CustomFilterMeshType meshType)
+        : CustomFilterProgram(programType, mixSettings, meshType)
+        , m_vertexShader(vertexShader)
+        , m_fragmentShader(fragmentShader)
+        , m_vertexShaderURL(vertexShaderURL)
+        , m_fragmentShaderURL(fragmentShaderURL)
+        , m_cache(0)
+        , m_isVertexShaderLoaded(false)
+        , m_isFragmentShaderLoaded(false)
+    {
+    }
+
+    ~StyleCustomFilterProgram();
+    
+    RefPtr<StyleShader> m_vertexShader;
+    RefPtr<StyleShader> m_fragmentShader;
+
+    CachedResourceHandle<CachedShader> m_cachedVertexShader;
+    CachedResourceHandle<CachedShader> m_cachedFragmentShader;
+
+    // The URLs form the key of the StyleCustomFilterProgram in the cache and are used
+    // to lookup the StyleCustomFilterProgram when it's removed from the cache.
+    KURL m_vertexShaderURL;
+    KURL m_fragmentShaderURL;
+
+    // The Cache is responsible of invalidating this reference.
+    StyleCustomFilterProgramCache* m_cache;
+    
+    bool m_isVertexShaderLoaded;
+    bool m_isFragmentShaderLoaded;
+};
+
+} // namespace WebCore
+
+
+#endif // StyleCustomFilterProgram_h
diff --git a/Source/core/rendering/style/StyleCustomFilterProgramCache.cpp b/Source/core/rendering/style/StyleCustomFilterProgramCache.cpp
new file mode 100644
index 0000000..ace3af3
--- /dev/null
+++ b/Source/core/rendering/style/StyleCustomFilterProgramCache.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2013 Adobe Systems Incorporated. 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 THE COPYRIGHT HOLDER “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 THE COPYRIGHT HOLDER 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 "core/rendering/style/StyleCustomFilterProgramCache.h"
+
+#include "core/platform/graphics/filters/custom/CustomFilterProgramInfo.h"
+#include "core/rendering/style/StyleCustomFilterProgram.h"
+
+namespace WebCore {
+
+static CustomFilterProgramInfo programCacheKey(StyleCustomFilterProgram* program) 
+{
+    ASSERT(program->vertexShaderURL().isValid() || program->fragmentShaderURL().isValid());
+    return CustomFilterProgramInfo(program->vertexShaderURL(), program->fragmentShaderURL(), 
+        program->programType(), program->mixSettings(), program->meshType());
+}
+
+StyleCustomFilterProgramCache::StyleCustomFilterProgramCache()
+{
+}
+
+StyleCustomFilterProgramCache::~StyleCustomFilterProgramCache()
+{
+    // Make sure the programs are not calling back into this object.
+    for (CacheMap::iterator iter = m_cache.begin(), end = m_cache.end(); iter != end; ++iter)
+        iter->value->setCache(0);
+}
+
+StyleCustomFilterProgram* StyleCustomFilterProgramCache::lookup(const CustomFilterProgramInfo& programInfo) const
+{
+    CacheMap::const_iterator iter = m_cache.find(programInfo);
+    return iter != m_cache.end() ? iter->value : 0;
+}
+
+StyleCustomFilterProgram* StyleCustomFilterProgramCache::lookup(StyleCustomFilterProgram* program) const
+{
+    return lookup(programCacheKey(program));
+}
+
+void StyleCustomFilterProgramCache::add(StyleCustomFilterProgram* program)
+{
+    CustomFilterProgramInfo key = programCacheKey(program);
+    ASSERT(m_cache.find(key) == m_cache.end());
+    m_cache.set(key, program);
+    program->setCache(this);
+}
+
+void StyleCustomFilterProgramCache::remove(StyleCustomFilterProgram* program)
+{
+    CacheMap::iterator iter = m_cache.find(programCacheKey(program));
+    ASSERT(iter != m_cache.end());
+    m_cache.remove(iter);
+}
+
+
+} // namespace WebCore
+
+
diff --git a/Source/core/rendering/style/StyleCustomFilterProgramCache.h b/Source/core/rendering/style/StyleCustomFilterProgramCache.h
new file mode 100644
index 0000000..eb30517
--- /dev/null
+++ b/Source/core/rendering/style/StyleCustomFilterProgramCache.h
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2013 Adobe Systems Incorporated. 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 THE COPYRIGHT HOLDER “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 THE COPYRIGHT HOLDER 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 StyleCustomFilterProgramCache_h
+#define StyleCustomFilterProgramCache_h
+
+#include "core/platform/graphics/filters/custom/CustomFilterProgramInfo.h"
+#include <wtf/FastAllocBase.h>
+#include <wtf/HashMap.h>
+
+namespace WebCore {
+
+class StyleCustomFilterProgram;
+class CustomFilterProgramInfo;
+
+class StyleCustomFilterProgramCache {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    StyleCustomFilterProgramCache();
+    ~StyleCustomFilterProgramCache();
+
+    // Lookups a StyleCustomFilterProgram that has similar parameters with the specified program.
+    StyleCustomFilterProgram* lookup(StyleCustomFilterProgram*) const;
+    StyleCustomFilterProgram* lookup(const CustomFilterProgramInfo&) const;
+
+    void add(StyleCustomFilterProgram*);
+    void remove(StyleCustomFilterProgram*);
+
+private:
+    typedef HashMap<CustomFilterProgramInfo, StyleCustomFilterProgram*> CacheMap;
+    CacheMap m_cache;
+};
+
+} // namespace WebCore
+
+
+#endif // StyleCustomFilterProgramCache_h
diff --git a/Source/core/rendering/style/StyleDeprecatedFlexibleBoxData.cpp b/Source/core/rendering/style/StyleDeprecatedFlexibleBoxData.cpp
new file mode 100644
index 0000000..4b3ff28
--- /dev/null
+++ b/Source/core/rendering/style/StyleDeprecatedFlexibleBoxData.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * 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 "core/rendering/style/StyleDeprecatedFlexibleBoxData.h"
+
+#include "core/rendering/style/RenderStyle.h"
+
+namespace WebCore {
+
+StyleDeprecatedFlexibleBoxData::StyleDeprecatedFlexibleBoxData()
+    : flex(RenderStyle::initialBoxFlex())
+    , flex_group(RenderStyle::initialBoxFlexGroup())
+    , ordinal_group(RenderStyle::initialBoxOrdinalGroup())
+    , align(RenderStyle::initialBoxAlign())
+    , pack(RenderStyle::initialBoxPack())
+    , orient(RenderStyle::initialBoxOrient())
+    , lines(RenderStyle::initialBoxLines())
+{
+}
+
+StyleDeprecatedFlexibleBoxData::StyleDeprecatedFlexibleBoxData(const StyleDeprecatedFlexibleBoxData& o)
+    : RefCounted<StyleDeprecatedFlexibleBoxData>()
+    , 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 StyleDeprecatedFlexibleBoxData::operator==(const StyleDeprecatedFlexibleBoxData& 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/Source/core/rendering/style/StyleDeprecatedFlexibleBoxData.h b/Source/core/rendering/style/StyleDeprecatedFlexibleBoxData.h
new file mode 100644
index 0000000..33337bc
--- /dev/null
+++ b/Source/core/rendering/style/StyleDeprecatedFlexibleBoxData.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ *           (C) 2000 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com)
+ *
+ * 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 StyleDeprecatedFlexibleBoxData_h
+#define StyleDeprecatedFlexibleBoxData_h
+
+#include <wtf/RefCounted.h>
+#include <wtf/PassRefPtr.h>
+
+namespace WebCore {
+
+class StyleDeprecatedFlexibleBoxData : public RefCounted<StyleDeprecatedFlexibleBoxData> {
+public:
+    static PassRefPtr<StyleDeprecatedFlexibleBoxData> create() { return adoptRef(new StyleDeprecatedFlexibleBoxData); }
+    PassRefPtr<StyleDeprecatedFlexibleBoxData> copy() const { return adoptRef(new StyleDeprecatedFlexibleBoxData(*this)); }
+
+    bool operator==(const StyleDeprecatedFlexibleBoxData&) const;
+    bool operator!=(const StyleDeprecatedFlexibleBoxData& o) const
+    {
+        return !(*this == o);
+    }
+
+    float flex;
+    unsigned int flex_group;
+    unsigned int ordinal_group;
+
+    unsigned align : 3; // EBoxAlignment
+    unsigned pack: 2; // EBoxPack
+    unsigned orient: 1; // EBoxOrient
+    unsigned lines : 1; // EBoxLines
+
+private:
+    StyleDeprecatedFlexibleBoxData();
+    StyleDeprecatedFlexibleBoxData(const StyleDeprecatedFlexibleBoxData&);
+};
+
+} // namespace WebCore
+
+#endif // StyleDeprecatedFlexibleBoxData_h
diff --git a/Source/core/rendering/style/StyleFilterData.cpp b/Source/core/rendering/style/StyleFilterData.cpp
new file mode 100644
index 0000000..d4974b6
--- /dev/null
+++ b/Source/core/rendering/style/StyleFilterData.cpp
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2011 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 "core/rendering/style/StyleFilterData.h"
+
+#include "core/platform/graphics/filters/FEGaussianBlur.h"
+
+#include "core/rendering/style/RenderStyle.h"
+
+namespace WebCore {
+
+StyleFilterData::StyleFilterData()
+    : m_operations()
+{
+}
+
+StyleFilterData::StyleFilterData(const StyleFilterData& o)
+    : RefCounted<StyleFilterData>()
+    , m_operations(o.m_operations)
+{
+}
+
+bool StyleFilterData::operator==(const StyleFilterData& o) const
+{
+    return m_operations == o.m_operations;
+}
+
+} // namespace WebCore
+
diff --git a/Source/core/rendering/style/StyleFilterData.h b/Source/core/rendering/style/StyleFilterData.h
new file mode 100644
index 0000000..ce62c62
--- /dev/null
+++ b/Source/core/rendering/style/StyleFilterData.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2011 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 StyleFilterData_h
+#define StyleFilterData_h
+
+#include "core/platform/graphics/filters/FilterOperations.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class StyleFilterData : public RefCounted<StyleFilterData> {
+public:
+    static PassRefPtr<StyleFilterData> create() { return adoptRef(new StyleFilterData); }
+    PassRefPtr<StyleFilterData> copy() const { return adoptRef(new StyleFilterData(*this)); }
+
+    bool operator==(const StyleFilterData&) const;
+    bool operator!=(const StyleFilterData& o) const
+    {
+        return !(*this == o);
+    }
+
+    FilterOperations m_operations;
+
+private:
+    StyleFilterData();
+    StyleFilterData(const StyleFilterData&);
+};
+
+} // namespace WebCore
+
+
+#endif // StyleFilterData_h
diff --git a/Source/core/rendering/style/StyleFlexibleBoxData.cpp b/Source/core/rendering/style/StyleFlexibleBoxData.cpp
new file mode 100644
index 0000000..5622eaa
--- /dev/null
+++ b/Source/core/rendering/style/StyleFlexibleBoxData.cpp
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2011 Google 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. 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 INC. 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 "core/rendering/style/StyleFlexibleBoxData.h"
+
+#include "core/rendering/style/RenderStyle.h"
+
+namespace WebCore {
+
+StyleFlexibleBoxData::StyleFlexibleBoxData()
+    : m_flexGrow(RenderStyle::initialFlexGrow())
+    , m_flexShrink(RenderStyle::initialFlexShrink())
+    , m_flexBasis(RenderStyle::initialFlexBasis())
+    , m_flexDirection(RenderStyle::initialFlexDirection())
+    , m_flexWrap(RenderStyle::initialFlexWrap())
+{
+}
+
+StyleFlexibleBoxData::StyleFlexibleBoxData(const StyleFlexibleBoxData& o)
+    : RefCounted<StyleFlexibleBoxData>()
+    , m_flexGrow(o.m_flexGrow)
+    , m_flexShrink(o.m_flexShrink)
+    , m_flexBasis(o.m_flexBasis)
+    , m_flexDirection(o.m_flexDirection)
+    , m_flexWrap(o.m_flexWrap)
+{
+}
+
+bool StyleFlexibleBoxData::operator==(const StyleFlexibleBoxData& o) const
+{
+    return m_flexGrow == o.m_flexGrow && m_flexShrink == o.m_flexShrink && m_flexBasis == o.m_flexBasis
+        && m_flexDirection == o.m_flexDirection && m_flexWrap == o.m_flexWrap;
+}
+
+}
diff --git a/Source/core/rendering/style/StyleFlexibleBoxData.h b/Source/core/rendering/style/StyleFlexibleBoxData.h
new file mode 100644
index 0000000..04c43e7
--- /dev/null
+++ b/Source/core/rendering/style/StyleFlexibleBoxData.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2011 Google 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. 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 INC. 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 StyleFlexibleBoxData_h
+#define StyleFlexibleBoxData_h
+
+#include "core/platform/Length.h"
+
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.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&) const;
+    bool operator!=(const StyleFlexibleBoxData& o) const
+    {
+        return !(*this == o);
+    }
+
+    float m_flexGrow;
+    float m_flexShrink;
+    Length m_flexBasis;
+
+    unsigned m_flexDirection : 2; // EFlexDirection
+    unsigned m_flexWrap : 2; // EFlexWrap
+
+private:
+    StyleFlexibleBoxData();
+    StyleFlexibleBoxData(const StyleFlexibleBoxData&);
+};
+
+} // namespace WebCore
+
+#endif // StyleFlexibleBoxData_h
diff --git a/Source/core/rendering/style/StyleGeneratedImage.cpp b/Source/core/rendering/style/StyleGeneratedImage.cpp
new file mode 100644
index 0000000..76bdac5
--- /dev/null
+++ b/Source/core/rendering/style/StyleGeneratedImage.cpp
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ *           (C) 2000 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2000 Dirk Mueller (mueller@kde.org)
+ * 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 "core/rendering/style/StyleGeneratedImage.h"
+
+#include "core/css/CSSImageGeneratorValue.h"
+#include "core/css/StyleResolver.h"
+#include "core/rendering/RenderObject.h"
+
+namespace WebCore {
+    
+StyleGeneratedImage::StyleGeneratedImage(PassRefPtr<CSSImageGeneratorValue> value)
+    : m_imageGeneratorValue(value)  
+    , m_fixedSize(m_imageGeneratorValue->isFixedSize())
+{
+    m_isGeneratedImage = true;
+}
+
+PassRefPtr<CSSValue> StyleGeneratedImage::cssValue() const
+{
+    return m_imageGeneratorValue;
+}
+
+LayoutSize StyleGeneratedImage::imageSize(const RenderObject* renderer, float multiplier) const
+{
+    if (m_fixedSize) {
+        IntSize fixedSize = m_imageGeneratorValue->fixedSize(renderer);
+        if (multiplier == 1.0f)
+            return fixedSize;
+
+        LayoutUnit width = fixedSize.width() * multiplier;
+        LayoutUnit height = fixedSize.height() * multiplier;
+
+        // Don't let images that have a width/height >= 1 shrink below 1 when zoomed.
+        if (fixedSize.width() > 0)
+            width = max<LayoutUnit>(1, width);
+
+        if (fixedSize.height() > 0)
+            height = max<LayoutUnit>(1, height);
+
+        return LayoutSize(width, height);
+    }
+    
+    return m_containerSize;
+}
+
+void StyleGeneratedImage::computeIntrinsicDimensions(const RenderObject* renderer, Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio)
+{
+    // At a zoom level of 1 the image is guaranteed to have an integer size.
+    IntSize size = flooredIntSize(imageSize(renderer, 1));
+    intrinsicWidth = Length(size.width(), Fixed);
+    intrinsicHeight = Length(size.height(), Fixed);
+    intrinsicRatio = size;
+}
+
+void StyleGeneratedImage::addClient(RenderObject* renderer)
+{
+    m_imageGeneratorValue->addClient(renderer, IntSize());
+}
+
+void StyleGeneratedImage::removeClient(RenderObject* renderer)
+{
+    m_imageGeneratorValue->removeClient(renderer);
+}
+
+PassRefPtr<Image> StyleGeneratedImage::image(RenderObject* renderer, const IntSize& size) const
+{
+    return m_imageGeneratorValue->image(renderer, size);
+}
+
+bool StyleGeneratedImage::knownToBeOpaque(const RenderObject* renderer) const
+{
+    return m_imageGeneratorValue->knownToBeOpaque(renderer);
+}
+
+}
diff --git a/Source/core/rendering/style/StyleGeneratedImage.h b/Source/core/rendering/style/StyleGeneratedImage.h
new file mode 100644
index 0000000..30dbcb1
--- /dev/null
+++ b/Source/core/rendering/style/StyleGeneratedImage.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ *           (C) 2000 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2000 Dirk Mueller (mueller@kde.org)
+ * 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 "core/rendering/style/StyleImage.h"
+
+namespace WebCore {
+
+class CSSValue;
+class CSSImageGeneratorValue;
+
+class StyleGeneratedImage : public StyleImage {
+public:
+    static PassRefPtr<StyleGeneratedImage> create(CSSImageGeneratorValue* value)
+    {
+        return adoptRef(new StyleGeneratedImage(value));
+    }
+
+    virtual WrappedImagePtr data() const { return m_imageGeneratorValue.get(); }
+
+    virtual PassRefPtr<CSSValue> cssValue() const;
+
+    virtual LayoutSize imageSize(const RenderObject*, float multiplier) const OVERRIDE;
+    virtual bool imageHasRelativeWidth() const { return !m_fixedSize; }
+    virtual bool imageHasRelativeHeight() const { return !m_fixedSize; }
+    virtual void computeIntrinsicDimensions(const RenderObject*, Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio);
+    virtual bool usesImageContainerSize() const { return !m_fixedSize; }
+    virtual void setContainerSizeForRenderer(const RenderObject*, const IntSize& containerSize, float) { m_containerSize = containerSize; }
+    virtual void addClient(RenderObject*);
+    virtual void removeClient(RenderObject*);
+    virtual PassRefPtr<Image> image(RenderObject*, const IntSize&) const;
+    virtual bool knownToBeOpaque(const RenderObject*) const OVERRIDE;
+    
+private:
+    StyleGeneratedImage(PassRefPtr<CSSImageGeneratorValue>);
+    
+    RefPtr<CSSImageGeneratorValue> m_imageGeneratorValue;
+    IntSize m_containerSize;
+    bool m_fixedSize;
+};
+
+}
+#endif
diff --git a/Source/core/rendering/style/StyleGridData.cpp b/Source/core/rendering/style/StyleGridData.cpp
new file mode 100644
index 0000000..cfa9b73
--- /dev/null
+++ b/Source/core/rendering/style/StyleGridData.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2011 Google 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. 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 INC. 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 "core/rendering/style/StyleGridData.h"
+
+#include "core/rendering/style/RenderStyle.h"
+
+namespace WebCore {
+
+StyleGridData::StyleGridData()
+    : m_gridColumns(RenderStyle::initialGridColumns())
+    , m_gridRows(RenderStyle::initialGridRows())
+    , m_gridAutoFlow(RenderStyle::initialGridAutoFlow())
+    , m_gridAutoRows(RenderStyle::initialGridAutoRows())
+    , m_gridAutoColumns(RenderStyle::initialGridAutoColumns())
+{
+}
+
+StyleGridData::StyleGridData(const StyleGridData& o)
+    : RefCounted<StyleGridData>()
+    , m_gridColumns(o.m_gridColumns)
+    , m_gridRows(o.m_gridRows)
+    , m_gridAutoFlow(o.m_gridAutoFlow)
+    , m_gridAutoRows(o.m_gridAutoRows)
+    , m_gridAutoColumns(o.m_gridAutoColumns)
+{
+}
+
+} // namespace WebCore
+
diff --git a/Source/core/rendering/style/StyleGridData.h b/Source/core/rendering/style/StyleGridData.h
new file mode 100644
index 0000000..d2382b9
--- /dev/null
+++ b/Source/core/rendering/style/StyleGridData.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2011 Google 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. 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 INC. 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 StyleGridData_h
+#define StyleGridData_h
+
+#include "core/rendering/style/GridTrackSize.h"
+#include "core/rendering/style/RenderStyleConstants.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class StyleGridData : public RefCounted<StyleGridData> {
+public:
+    static PassRefPtr<StyleGridData> create() { return adoptRef(new StyleGridData); }
+    PassRefPtr<StyleGridData> copy() const { return adoptRef(new StyleGridData(*this)); }
+
+    bool operator==(const StyleGridData& o) const
+    {
+        return m_gridColumns == o.m_gridColumns && m_gridRows == o.m_gridRows && m_gridAutoFlow == o.m_gridAutoFlow && m_gridAutoRows == o.m_gridAutoRows && m_gridAutoColumns == o.m_gridAutoColumns;
+    }
+
+    bool operator!=(const StyleGridData& o) const
+    {
+        return !(*this == o);
+    }
+
+    // FIXME: Update the naming of the following variables.
+    Vector<GridTrackSize> m_gridColumns;
+    Vector<GridTrackSize> m_gridRows;
+
+    GridAutoFlow m_gridAutoFlow;
+
+    GridTrackSize m_gridAutoRows;
+    GridTrackSize m_gridAutoColumns;
+
+private:
+    StyleGridData();
+    StyleGridData(const StyleGridData&);
+};
+
+} // namespace WebCore
+
+#endif // StyleGridData_h
diff --git a/Source/core/rendering/style/StyleGridItemData.cpp b/Source/core/rendering/style/StyleGridItemData.cpp
new file mode 100644
index 0000000..ea93804
--- /dev/null
+++ b/Source/core/rendering/style/StyleGridItemData.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2012 Google 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:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+ * OWNER 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 "core/rendering/style/StyleGridItemData.h"
+
+#include "core/rendering/style/RenderStyle.h"
+
+namespace WebCore {
+
+StyleGridItemData::StyleGridItemData()
+    : m_gridStart(RenderStyle::initialGridStart())
+    , m_gridEnd(RenderStyle::initialGridEnd())
+    , m_gridBefore(RenderStyle::initialGridBefore())
+    , m_gridAfter(RenderStyle::initialGridAfter())
+{
+}
+
+StyleGridItemData::StyleGridItemData(const StyleGridItemData& o)
+    : RefCounted<StyleGridItemData>()
+    , m_gridStart(o.m_gridStart)
+    , m_gridEnd(o.m_gridEnd)
+    , m_gridBefore(o.m_gridBefore)
+    , m_gridAfter(o.m_gridAfter)
+{
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/style/StyleGridItemData.h b/Source/core/rendering/style/StyleGridItemData.h
new file mode 100644
index 0000000..d68ffd4
--- /dev/null
+++ b/Source/core/rendering/style/StyleGridItemData.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2012 Google 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:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+ * OWNER 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 StyleGridItemData_h
+#define StyleGridItemData_h
+
+
+#include "core/rendering/style/GridPosition.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class StyleGridItemData : public RefCounted<StyleGridItemData> {
+public:
+    static PassRefPtr<StyleGridItemData> create() { return adoptRef(new StyleGridItemData); }
+    PassRefPtr<StyleGridItemData> copy() const { return adoptRef(new StyleGridItemData(*this)); }
+
+    bool operator==(const StyleGridItemData& o) const
+    {
+        return m_gridStart == o.m_gridStart && m_gridEnd == o.m_gridEnd
+            && m_gridBefore == o.m_gridBefore && m_gridAfter == o.m_gridAfter;
+    }
+
+    bool operator!=(const StyleGridItemData& o) const
+    {
+        return !(*this == o);
+    }
+
+    GridPosition m_gridStart;
+    GridPosition m_gridEnd;
+    GridPosition m_gridBefore;
+    GridPosition m_gridAfter;
+
+private:
+    StyleGridItemData();
+    StyleGridItemData(const StyleGridItemData&);
+};
+
+} // namespace WebCore
+
+#endif // StyleGridItemData_h
diff --git a/Source/core/rendering/style/StyleImage.h b/Source/core/rendering/style/StyleImage.h
new file mode 100644
index 0000000..b2578b5
--- /dev/null
+++ b/Source/core/rendering/style/StyleImage.h
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ *           (C) 2000 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2000 Dirk Mueller (mueller@kde.org)
+ * 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 "core/css/CSSValue.h"
+#include "core/platform/graphics/Image.h"
+#include "core/platform/graphics/IntSize.h"
+#include "core/platform/graphics/LayoutSize.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+class CachedImage;
+class CSSValue;
+class RenderObject;
+
+typedef void* WrappedImagePtr;
+
+class StyleImage : public RefCounted<StyleImage> {
+public:
+    virtual ~StyleImage() { }
+
+    bool operator==(const StyleImage& other) const
+    {
+        return data() == other.data();
+    }
+
+    virtual PassRefPtr<CSSValue> cssValue() const = 0;
+
+    virtual bool canRender(const RenderObject*, float /*multiplier*/) const { return true; }
+    virtual bool isLoaded() const { return true; }
+    virtual bool errorOccurred() const { return false; }
+    virtual LayoutSize imageSize(const RenderObject*, float multiplier) const = 0;
+    virtual void computeIntrinsicDimensions(const RenderObject*, Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio) = 0;
+    virtual bool imageHasRelativeWidth() const = 0;
+    virtual bool imageHasRelativeHeight() const = 0;
+    virtual bool usesImageContainerSize() const = 0;
+    virtual void setContainerSizeForRenderer(const RenderObject*, const IntSize&, float) = 0;
+    virtual void addClient(RenderObject*) = 0;
+    virtual void removeClient(RenderObject*) = 0;
+    virtual PassRefPtr<Image> image(RenderObject*, const IntSize&) const = 0;
+    virtual WrappedImagePtr data() const = 0;
+    virtual float imageScaleFactor() const { return 1; }
+    virtual bool knownToBeOpaque(const RenderObject*) const = 0;
+    virtual CachedImage* cachedImage() const { return 0; }
+
+    ALWAYS_INLINE bool isCachedImage() const { return m_isCachedImage; }
+    ALWAYS_INLINE bool isPendingImage() const { return m_isPendingImage; }
+    ALWAYS_INLINE bool isGeneratedImage() const { return m_isGeneratedImage; }
+    ALWAYS_INLINE bool isCachedImageSet() const { return m_isCachedImageSet; }
+    
+    static  bool imagesEquivalent(StyleImage* image1, StyleImage* image2)
+    {
+        if (image1 != image2) {
+            if (!image1 || !image2)
+                return false;
+            return *image1 == *image2;
+        }
+        return true;
+    }
+
+protected:
+    StyleImage()
+        : m_isCachedImage(false)
+        , m_isPendingImage(false)
+        , m_isGeneratedImage(false)
+        , m_isCachedImageSet(false)
+    {
+    }
+    bool m_isCachedImage:1;
+    bool m_isPendingImage:1;
+    bool m_isGeneratedImage:1;
+    bool m_isCachedImageSet:1;
+};
+
+}
+#endif
diff --git a/Source/core/rendering/style/StyleInheritedData.cpp b/Source/core/rendering/style/StyleInheritedData.cpp
new file mode 100644
index 0000000..063e7d2
--- /dev/null
+++ b/Source/core/rendering/style/StyleInheritedData.cpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * 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 "core/rendering/style/StyleInheritedData.h"
+
+#include "core/rendering/style/RenderStyle.h"
+
+namespace WebCore {
+
+StyleInheritedData::StyleInheritedData()
+    : horizontal_border_spacing(RenderStyle::initialHorizontalBorderSpacing())
+    , vertical_border_spacing(RenderStyle::initialVerticalBorderSpacing())
+    , line_height(RenderStyle::initialLineHeight())
+    , color(RenderStyle::initialColor())
+    , visitedLinkColor(RenderStyle::initialColor())
+{
+}
+
+StyleInheritedData::~StyleInheritedData()
+{
+}
+
+StyleInheritedData::StyleInheritedData(const StyleInheritedData& o)
+    : RefCounted<StyleInheritedData>()
+    , horizontal_border_spacing(o.horizontal_border_spacing)
+    , vertical_border_spacing(o.vertical_border_spacing)
+    , line_height(o.line_height)
+    , font(o.font)
+    , color(o.color)
+    , visitedLinkColor(o.visitedLinkColor)
+{
+}
+
+bool StyleInheritedData::operator==(const StyleInheritedData& o) const
+{
+    return line_height == o.line_height
+        && font == o.font
+        && color == o.color
+        && visitedLinkColor == o.visitedLinkColor
+        && horizontal_border_spacing == o.horizontal_border_spacing
+        && vertical_border_spacing == o.vertical_border_spacing;
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/style/StyleInheritedData.h b/Source/core/rendering/style/StyleInheritedData.h
new file mode 100644
index 0000000..ac7a73f
--- /dev/null
+++ b/Source/core/rendering/style/StyleInheritedData.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ *           (C) 2000 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com)
+ *
+ * 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 "core/platform/Length.h"
+#include "core/platform/graphics/Color.h"
+#include "core/platform/graphics/Font.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+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);
+    }
+
+    short horizontal_border_spacing;
+    short vertical_border_spacing;
+
+    // could be packed in a short but doesn't
+    // make a difference currently because of padding
+    Length line_height;
+
+    Font font;
+    Color color;
+    Color visitedLinkColor;
+
+private:
+    StyleInheritedData();
+    StyleInheritedData(const StyleInheritedData&);
+};
+
+} // namespace WebCore
+
+#endif // StyleInheritedData_h
diff --git a/Source/core/rendering/style/StyleMarqueeData.cpp b/Source/core/rendering/style/StyleMarqueeData.cpp
new file mode 100644
index 0000000..6023267
--- /dev/null
+++ b/Source/core/rendering/style/StyleMarqueeData.cpp
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * 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 "core/rendering/style/StyleBackgroundData.h"
+
+#include "core/rendering/style/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/Source/core/rendering/style/StyleMarqueeData.h b/Source/core/rendering/style/StyleMarqueeData.h
new file mode 100644
index 0000000..33719c2
--- /dev/null
+++ b/Source/core/rendering/style/StyleMarqueeData.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ *           (C) 2000 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com)
+ *
+ * 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 "core/platform/Length.h"
+#include "core/rendering/style/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/Source/core/rendering/style/StyleMultiColData.cpp b/Source/core/rendering/style/StyleMultiColData.cpp
new file mode 100644
index 0000000..9a4eb5f
--- /dev/null
+++ b/Source/core/rendering/style/StyleMultiColData.cpp
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * 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 "core/rendering/style/StyleMultiColData.h"
+
+#include "core/rendering/style/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_columnSpan(false)
+    , m_breakBefore(RenderStyle::initialPageBreak())
+    , m_breakAfter(RenderStyle::initialPageBreak())
+    , m_breakInside(RenderStyle::initialPageBreak())
+    , m_axis(RenderStyle::initialColumnAxis())
+    , m_progression(RenderStyle::initialColumnProgression())
+{
+}
+
+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_visitedLinkColumnRuleColor(o.m_visitedLinkColumnRuleColor)
+    , m_autoWidth(o.m_autoWidth)
+    , m_autoCount(o.m_autoCount)
+    , m_normalGap(o.m_normalGap)
+    , m_columnSpan(o.m_columnSpan)
+    , m_breakBefore(o.m_breakBefore)
+    , m_breakAfter(o.m_breakAfter)
+    , m_breakInside(o.m_breakInside)
+    , m_axis(o.m_axis)
+    , m_progression(o.m_progression)
+{
+}
+
+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_visitedLinkColumnRuleColor == o.m_visitedLinkColumnRuleColor && m_breakBefore == o.m_breakBefore
+           && m_autoWidth == o.m_autoWidth && m_autoCount == o.m_autoCount && m_normalGap == o.m_normalGap
+           && m_columnSpan == o.m_columnSpan && m_breakAfter == o.m_breakAfter && m_breakInside == o.m_breakInside && m_axis == o.m_axis
+           && m_progression == o.m_progression;
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/style/StyleMultiColData.h b/Source/core/rendering/style/StyleMultiColData.h
new file mode 100644
index 0000000..1b50250
--- /dev/null
+++ b/Source/core/rendering/style/StyleMultiColData.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ *           (C) 2000 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com)
+ *
+ * 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 "core/platform/Length.h"
+#include "core/rendering/style/BorderValue.h"
+#include "core/rendering/style/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;
+    Color m_visitedLinkColumnRuleColor;
+
+    bool m_autoWidth : 1;
+    bool m_autoCount : 1;
+    bool m_normalGap : 1;
+    unsigned m_columnSpan : 1;
+    unsigned m_breakBefore : 2; // EPageBreak
+    unsigned m_breakAfter : 2; // EPageBreak
+    unsigned m_breakInside : 2; // EPageBreak
+    unsigned m_axis : 2; // ColumnAxis
+    unsigned m_progression : 2; // ColumnProgression
+
+private:
+    StyleMultiColData();
+    StyleMultiColData(const StyleMultiColData&);
+};
+
+} // namespace WebCore
+
+#endif // StyleMultiColData_h
diff --git a/Source/core/rendering/style/StylePendingImage.h b/Source/core/rendering/style/StylePendingImage.h
new file mode 100644
index 0000000..8b6e7f1
--- /dev/null
+++ b/Source/core/rendering/style/StylePendingImage.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2010 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 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 StylePendingImage_h
+#define StylePendingImage_h
+
+#include "core/css/CSSCursorImageValue.h"
+#include "core/css/CSSImageGeneratorValue.h"
+#include "core/css/CSSImageSetValue.h"
+#include "core/css/CSSImageValue.h"
+#include "core/platform/graphics/Image.h"
+#include "core/rendering/style/StyleImage.h"
+
+namespace WebCore {
+
+// StylePendingImage is a placeholder StyleImage that is entered into the RenderStyle during
+// style resolution, in order to avoid loading images that are not referenced by the final style.
+// They should never exist in a RenderStyle after it has been returned from the style selector.
+
+class StylePendingImage : public StyleImage {
+public:
+    static PassRefPtr<StylePendingImage> create(CSSValue* value) { return adoptRef(new StylePendingImage(value)); }
+
+    virtual WrappedImagePtr data() const { return static_cast<CSSImageValue*>(m_value); }
+
+    virtual PassRefPtr<CSSValue> cssValue() const { return m_value; }
+    CSSImageValue* cssImageValue() const { return m_value->isImageValue() ? static_cast<CSSImageValue*>(m_value) : 0; }
+    CSSImageGeneratorValue* cssImageGeneratorValue() const { return m_value->isImageGeneratorValue() ? static_cast<CSSImageGeneratorValue*>(m_value) : 0; }
+    CSSCursorImageValue* cssCursorImageValue() const { return m_value->isCursorImageValue() ? static_cast<CSSCursorImageValue*>(m_value) : 0; }
+    CSSImageSetValue* cssImageSetValue() const { return m_value->isImageSetValue() ? static_cast<CSSImageSetValue*>(m_value) : 0; }
+
+    virtual LayoutSize imageSize(const RenderObject*, float /*multiplier*/) const OVERRIDE { return LayoutSize(); }
+    virtual bool imageHasRelativeWidth() const { return false; }
+    virtual bool imageHasRelativeHeight() const { return false; }
+    virtual void computeIntrinsicDimensions(const RenderObject*, Length& /* intrinsicWidth */ , Length& /* intrinsicHeight */, FloatSize& /* intrinsicRatio */) { }
+    virtual bool usesImageContainerSize() const { return false; }
+    virtual void setContainerSizeForRenderer(const RenderObject*, const IntSize&, float) { }
+    virtual void addClient(RenderObject*) { }
+    virtual void removeClient(RenderObject*) { }
+    virtual PassRefPtr<Image> image(RenderObject*, const IntSize&) const
+    {
+        ASSERT_NOT_REACHED();
+        return 0;
+    }
+    virtual bool knownToBeOpaque(const RenderObject*) const { return false; }
+    
+private:
+    StylePendingImage(CSSValue* value)
+        : m_value(value)
+    {
+        m_isPendingImage = true;
+    }
+
+    CSSValue* m_value; // Not retained; it owns us.
+};
+
+}
+#endif
diff --git a/Source/core/rendering/style/StylePendingShader.h b/Source/core/rendering/style/StylePendingShader.h
new file mode 100644
index 0000000..c29de55
--- /dev/null
+++ b/Source/core/rendering/style/StylePendingShader.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2011 Adobe Systems Incorporated. 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 THE COPYRIGHT HOLDER “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 THE COPYRIGHT HOLDER 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 StylePendingShader_h
+#define StylePendingShader_h
+
+#include "core/css/CSSValue.h"
+#include "core/css/WebKitCSSShaderValue.h"
+#include "core/rendering/style/StyleShader.h"
+#include <wtf/PassRefPtr.h>
+
+namespace WebCore {
+
+class WebKitCSSShaderValue;
+
+class StylePendingShader : public StyleShader {
+public:
+    static PassRefPtr<StylePendingShader> create(WebKitCSSShaderValue* value) { return adoptRef(new StylePendingShader(value)); }
+    
+    virtual PassRefPtr<CSSValue> cssValue() const { return m_value; }
+    WebKitCSSShaderValue* cssShaderValue() const { return m_value; }
+private:
+    StylePendingShader(WebKitCSSShaderValue* value)
+        : m_value(value)
+    {
+         m_isPendingShader = true;
+    }
+    
+    WebKitCSSShaderValue* m_value; // Not retained; it owns us.
+};
+
+}
+
+#endif // StylePendingShader_h
diff --git a/Source/core/rendering/style/StyleRareInheritedData.cpp b/Source/core/rendering/style/StyleRareInheritedData.cpp
new file mode 100644
index 0000000..0f31382
--- /dev/null
+++ b/Source/core/rendering/style/StyleRareInheritedData.cpp
@@ -0,0 +1,266 @@
+/*
+ * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009, 2010 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 "core/rendering/style/StyleRareInheritedData.h"
+
+#include "core/dom/WebCoreMemoryInstrumentation.h"
+#include "core/rendering/style/CursorList.h"
+#include "core/rendering/style/QuotesData.h"
+#include "core/rendering/style/RenderStyle.h"
+#include "core/rendering/style/RenderStyleConstants.h"
+#include "core/rendering/style/ShadowData.h"
+#include "core/rendering/style/StyleImage.h"
+#include <wtf/MemoryObjectInfo.h>
+
+namespace WebCore {
+
+struct SameSizeAsStyleRareInheritedData : public RefCounted<SameSizeAsStyleRareInheritedData> {
+    void* styleImage;
+    Color firstColor;
+    float firstFloat;
+    Color colors[5];
+    void* ownPtrs[1];
+    AtomicString atomicStrings[5];
+    void* refPtrs[2];
+    Length lengths[1];
+    float secondFloat;
+    unsigned m_bitfields[2];
+    short pagedMediaShorts[2];
+    unsigned unsigneds[1];
+    short hyphenationShorts[3];
+
+    Color touchColors;
+
+    void* variableDataRefs[1];
+};
+
+COMPILE_ASSERT(sizeof(StyleRareInheritedData) == sizeof(SameSizeAsStyleRareInheritedData), StyleRareInheritedData_should_bit_pack);
+
+StyleRareInheritedData::StyleRareInheritedData()
+    : listStyleImage(RenderStyle::initialListStyleImage())
+    , textStrokeWidth(RenderStyle::initialTextStrokeWidth())
+    , indent(RenderStyle::initialTextIndent())
+    , m_effectiveZoom(RenderStyle::initialZoom())
+    , widows(RenderStyle::initialWidows())
+    , orphans(RenderStyle::initialOrphans())
+    , m_hasAutoWidows(true)
+    , m_hasAutoOrphans(true)
+    , textSecurity(RenderStyle::initialTextSecurity())
+    , userModify(READ_ONLY)
+    , wordBreak(RenderStyle::initialWordBreak())
+    , overflowWrap(RenderStyle::initialOverflowWrap())
+    , lineBreak(LineBreakAuto)
+    , resize(RenderStyle::initialResize())
+    , userSelect(RenderStyle::initialUserSelect())
+    , colorSpace(ColorSpaceDeviceRGB)
+    , speak(SpeakNormal)
+    , hyphens(HyphensManual)
+    , textEmphasisFill(TextEmphasisFillFilled)
+    , textEmphasisMark(TextEmphasisMarkNone)
+    , textEmphasisPosition(TextEmphasisPositionOver)
+    , m_textOrientation(TextOrientationVerticalRight)
+#if ENABLE(CSS3_TEXT)
+    , m_textIndentLine(RenderStyle::initialTextIndentLine())
+#endif
+    , m_lineBoxContain(RenderStyle::initialLineBoxContain())
+    , m_imageRendering(RenderStyle::initialImageRendering())
+    , m_lineSnap(RenderStyle::initialLineSnap())
+    , m_lineAlign(RenderStyle::initialLineAlign())
+#if ENABLE(ACCELERATED_OVERFLOW_SCROLLING)
+    , useTouchOverflowScrolling(RenderStyle::initialUseTouchOverflowScrolling())
+#endif
+#if ENABLE(CSS3_TEXT)
+    , m_textAlignLast(RenderStyle::initialTextAlignLast())
+    , m_textUnderlinePosition(RenderStyle::initialTextUnderlinePosition())
+#endif // CSS3_TEXT
+    , m_rubyPosition(RenderStyle::initialRubyPosition())
+    , hyphenationLimitBefore(-1)
+    , hyphenationLimitAfter(-1)
+    , hyphenationLimitLines(-1)
+    , m_lineGrid(RenderStyle::initialLineGrid())
+    , m_tabSize(RenderStyle::initialTabSize())
+    , tapHighlightColor(RenderStyle::initialTapHighlightColor())
+{
+    m_variables.init();
+}
+
+StyleRareInheritedData::StyleRareInheritedData(const StyleRareInheritedData& o)
+    : RefCounted<StyleRareInheritedData>()
+    , listStyleImage(o.listStyleImage)
+    , textStrokeColor(o.textStrokeColor)
+    , textStrokeWidth(o.textStrokeWidth)
+    , textFillColor(o.textFillColor)
+    , textEmphasisColor(o.textEmphasisColor)
+    , visitedLinkTextStrokeColor(o.visitedLinkTextStrokeColor)
+    , visitedLinkTextFillColor(o.visitedLinkTextFillColor)
+    , visitedLinkTextEmphasisColor(o.visitedLinkTextEmphasisColor)
+    , textShadow(o.textShadow ? adoptPtr(new ShadowData(*o.textShadow)) : nullptr)
+    , highlight(o.highlight)
+    , cursorData(o.cursorData)
+    , indent(o.indent)
+    , m_effectiveZoom(o.m_effectiveZoom)
+    , widows(o.widows)
+    , orphans(o.orphans)
+    , m_hasAutoWidows(o.m_hasAutoWidows)
+    , m_hasAutoOrphans(o.m_hasAutoOrphans)
+    , textSecurity(o.textSecurity)
+    , userModify(o.userModify)
+    , wordBreak(o.wordBreak)
+    , overflowWrap(o.overflowWrap)
+    , lineBreak(o.lineBreak)
+    , resize(o.resize)
+    , userSelect(o.userSelect)
+    , colorSpace(o.colorSpace)
+    , speak(o.speak)
+    , hyphens(o.hyphens)
+    , textEmphasisFill(o.textEmphasisFill)
+    , textEmphasisMark(o.textEmphasisMark)
+    , textEmphasisPosition(o.textEmphasisPosition)
+    , m_textOrientation(o.m_textOrientation)
+#if ENABLE(CSS3_TEXT)
+    , m_textIndentLine(o.m_textIndentLine)
+#endif
+    , m_lineBoxContain(o.m_lineBoxContain)
+    , m_imageRendering(o.m_imageRendering)
+    , m_lineSnap(o.m_lineSnap)
+    , m_lineAlign(o.m_lineAlign)
+#if ENABLE(ACCELERATED_OVERFLOW_SCROLLING)
+    , useTouchOverflowScrolling(o.useTouchOverflowScrolling)
+#endif
+#if ENABLE(CSS3_TEXT)
+    , m_textAlignLast(o.m_textAlignLast)
+    , m_textUnderlinePosition(o.m_textUnderlinePosition)
+#endif // CSS3_TEXT
+    , m_rubyPosition(o.m_rubyPosition)
+    , hyphenationString(o.hyphenationString)
+    , hyphenationLimitBefore(o.hyphenationLimitBefore)
+    , hyphenationLimitAfter(o.hyphenationLimitAfter)
+    , hyphenationLimitLines(o.hyphenationLimitLines)
+    , locale(o.locale)
+    , textEmphasisCustomMark(o.textEmphasisCustomMark)
+    , m_lineGrid(o.m_lineGrid)
+    , m_tabSize(o.m_tabSize)
+    , tapHighlightColor(o.tapHighlightColor)
+    , m_variables(o.m_variables)
+{
+}
+
+StyleRareInheritedData::~StyleRareInheritedData()
+{
+}
+
+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 StyleRareInheritedData::operator==(const StyleRareInheritedData& o) const
+{
+    return textStrokeColor == o.textStrokeColor
+        && textStrokeWidth == o.textStrokeWidth
+        && textFillColor == o.textFillColor
+        && textEmphasisColor == o.textEmphasisColor
+        && visitedLinkTextStrokeColor == o.visitedLinkTextStrokeColor
+        && visitedLinkTextFillColor == o.visitedLinkTextFillColor
+        && visitedLinkTextEmphasisColor == o.visitedLinkTextEmphasisColor
+        && tapHighlightColor == o.tapHighlightColor
+        && shadowDataEquivalent(o)
+        && highlight == o.highlight
+        && cursorDataEquivalent(cursorData.get(), o.cursorData.get())
+        && indent == o.indent
+        && m_effectiveZoom == o.m_effectiveZoom
+        && widows == o.widows
+        && orphans == o.orphans
+        && m_hasAutoWidows == o.m_hasAutoWidows
+        && m_hasAutoOrphans == o.m_hasAutoOrphans
+        && textSecurity == o.textSecurity
+        && userModify == o.userModify
+        && wordBreak == o.wordBreak
+        && overflowWrap == o.overflowWrap
+        && lineBreak == o.lineBreak
+#if ENABLE(ACCELERATED_OVERFLOW_SCROLLING)
+        && useTouchOverflowScrolling == o.useTouchOverflowScrolling
+#endif
+        && resize == o.resize
+        && userSelect == o.userSelect
+        && colorSpace == o.colorSpace
+        && speak == o.speak
+        && hyphens == o.hyphens
+        && hyphenationLimitBefore == o.hyphenationLimitBefore
+        && hyphenationLimitAfter == o.hyphenationLimitAfter
+        && hyphenationLimitLines == o.hyphenationLimitLines
+        && textEmphasisFill == o.textEmphasisFill
+        && textEmphasisMark == o.textEmphasisMark
+        && textEmphasisPosition == o.textEmphasisPosition
+        && m_textOrientation == o.m_textOrientation
+#if ENABLE(CSS3_TEXT)
+        && m_textIndentLine == o.m_textIndentLine
+#endif
+        && m_lineBoxContain == o.m_lineBoxContain
+        && hyphenationString == o.hyphenationString
+        && locale == o.locale
+        && textEmphasisCustomMark == o.textEmphasisCustomMark
+        && QuotesData::equals(quotes.get(), o.quotes.get())
+        && m_tabSize == o.m_tabSize
+        && m_lineGrid == o.m_lineGrid
+        && m_imageRendering == o.m_imageRendering
+#if ENABLE(CSS3_TEXT)
+        && m_textAlignLast == o.m_textAlignLast
+        && m_textUnderlinePosition == o.m_textUnderlinePosition
+#endif // CSS3_TEXT
+        && m_rubyPosition == o.m_rubyPosition
+        && m_lineSnap == o.m_lineSnap
+        && m_variables == o.m_variables
+        && m_lineAlign == o.m_lineAlign
+        && StyleImage::imagesEquivalent(listStyleImage.get(), o.listStyleImage.get());
+}
+
+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;
+}
+
+void StyleRareInheritedData::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS);
+    info.addMember(listStyleImage, "listStyleImage");
+    info.addMember(indent, "indent");
+    info.addMember(textShadow, "textShadow");
+    info.addMember(highlight, "highlight");
+    info.addMember(cursorData, "cursorData");
+    info.addMember(hyphenationString, "hyphenationString");
+    info.addMember(locale, "locale");
+    info.addMember(textEmphasisCustomMark, "textEmphasisCustomMark");
+    info.addMember(quotes, "quotes");
+    info.addMember(m_lineGrid, "lineGrid");
+    info.addMember(m_variables, "variables");
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/style/StyleRareInheritedData.h b/Source/core/rendering/style/StyleRareInheritedData.h
new file mode 100644
index 0000000..0ffd6af
--- /dev/null
+++ b/Source/core/rendering/style/StyleRareInheritedData.h
@@ -0,0 +1,141 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ *           (C) 2000 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com)
+ *
+ * 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 "core/platform/Length.h"
+#include "core/platform/graphics/Color.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.h>
+#include <wtf/text/AtomicString.h>
+
+#include "core/rendering/style/DataRef.h"
+#include "core/rendering/style/StyleVariableData.h"
+
+namespace WebCore {
+
+class CursorList;
+class QuotesData;
+class ShadowData;
+class StyleImage;
+
+// 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;
+
+    void reportMemoryUsage(MemoryObjectInfo*) const;
+
+    RefPtr<StyleImage> listStyleImage;
+
+    Color textStrokeColor;
+    float textStrokeWidth;
+    Color textFillColor;
+    Color textEmphasisColor;
+    
+    Color visitedLinkTextStrokeColor;
+    Color visitedLinkTextFillColor;
+    Color visitedLinkTextEmphasisColor;    
+
+    OwnPtr<ShadowData> textShadow; // Our text shadow information for shadowed text drawing.
+    AtomicString highlight; // Apple-specific extension for custom highlight rendering.
+    
+    RefPtr<CursorList> cursorData;
+    Length indent;
+    float m_effectiveZoom;
+
+    // Paged media properties.
+    short widows;
+    short orphans;
+    unsigned m_hasAutoWidows : 1;
+    unsigned m_hasAutoOrphans : 1;
+    
+    unsigned textSecurity : 2; // ETextSecurity
+    unsigned userModify : 2; // EUserModify (editing)
+    unsigned wordBreak : 2; // EWordBreak
+    unsigned overflowWrap : 1; // EOverflowWrap
+    unsigned lineBreak : 3; // LineBreak
+    unsigned resize : 2; // EResize
+    unsigned userSelect : 2; // EUserSelect
+    unsigned colorSpace : 1; // ColorSpace
+    unsigned speak : 3; // ESpeak
+    unsigned hyphens : 2; // Hyphens
+    unsigned textEmphasisFill : 1; // TextEmphasisFill
+    unsigned textEmphasisMark : 3; // TextEmphasisMark
+    unsigned textEmphasisPosition : 1; // TextEmphasisPosition
+    unsigned m_textOrientation : 2; // TextOrientation
+#if ENABLE(CSS3_TEXT)
+    unsigned m_textIndentLine : 1; // TextIndentEachLine
+#endif
+    unsigned m_lineBoxContain: 7; // LineBoxContain
+    // CSS Image Values Level 3
+    unsigned m_imageRendering : 2; // EImageRendering
+    unsigned m_lineSnap : 2; // LineSnap
+    unsigned m_lineAlign : 1; // LineAlign
+#if ENABLE(ACCELERATED_OVERFLOW_SCROLLING)
+    unsigned useTouchOverflowScrolling: 1;
+#endif
+#if ENABLE(CSS3_TEXT)
+    unsigned m_textAlignLast : 3; // TextAlignLast
+    unsigned m_textUnderlinePosition : 3; // TextUnderlinePosition
+#endif // CSS3_TEXT
+    unsigned m_rubyPosition : 1; // RubyPosition
+
+    AtomicString hyphenationString;
+    short hyphenationLimitBefore;
+    short hyphenationLimitAfter;
+    short hyphenationLimitLines;
+
+    AtomicString locale;
+
+    AtomicString textEmphasisCustomMark;
+    RefPtr<QuotesData> quotes;
+
+    AtomicString m_lineGrid;
+    unsigned m_tabSize;
+
+    Color tapHighlightColor;
+
+    DataRef<StyleVariableData> m_variables;
+
+private:
+    StyleRareInheritedData();
+    StyleRareInheritedData(const StyleRareInheritedData&);
+};
+
+} // namespace WebCore
+
+#endif // StyleRareInheritedData_h
diff --git a/Source/core/rendering/style/StyleRareNonInheritedData.cpp b/Source/core/rendering/style/StyleRareNonInheritedData.cpp
new file mode 100644
index 0000000..ace18a4
--- /dev/null
+++ b/Source/core/rendering/style/StyleRareNonInheritedData.cpp
@@ -0,0 +1,338 @@
+/*
+ * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * 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 "core/rendering/style/StyleRareNonInheritedData.h"
+
+#include "core/css/StyleResolver.h"
+#include "core/dom/WebCoreMemoryInstrumentation.h"
+#include "core/rendering/RenderCounter.h"
+#include "core/rendering/style/ContentData.h"
+#include "core/rendering/style/RenderStyle.h"
+#include "core/rendering/style/ShadowData.h"
+#include "core/rendering/style/StyleFilterData.h"
+#include "core/rendering/style/StyleImage.h"
+#include "core/rendering/style/StyleTransformData.h"
+#include <wtf/MemoryInstrumentationHashMap.h>
+#include <wtf/MemoryInstrumentationVector.h>
+#include <wtf/MemoryObjectInfo.h>
+
+namespace WebCore {
+
+StyleRareNonInheritedData::StyleRareNonInheritedData()
+    : opacity(RenderStyle::initialOpacity())
+    , m_aspectRatioDenominator(RenderStyle::initialAspectRatioDenominator())
+    , m_aspectRatioNumerator(RenderStyle::initialAspectRatioNumerator())
+    , m_perspective(RenderStyle::initialPerspective())
+    , m_perspectiveOriginX(RenderStyle::initialPerspectiveOriginX())
+    , m_perspectiveOriginY(RenderStyle::initialPerspectiveOriginY())
+    , lineClamp(RenderStyle::initialLineClamp())
+    , m_draggableRegionMode(DraggableRegionNone)
+    , m_mask(FillLayer(MaskFillLayer))
+    , m_pageSize()
+    , m_shapeInside(RenderStyle::initialShapeInside())
+    , m_shapeOutside(RenderStyle::initialShapeOutside())
+    , m_shapeMargin(RenderStyle::initialShapeMargin())
+    , m_shapePadding(RenderStyle::initialShapePadding())
+    , m_clipPath(RenderStyle::initialClipPath())
+    , m_visitedLinkBackgroundColor(RenderStyle::initialBackgroundColor())
+    , m_order(RenderStyle::initialOrder())
+    , m_flowThread(RenderStyle::initialFlowThread())
+    , m_regionThread(RenderStyle::initialRegionThread())
+    , m_regionOverflow(RenderStyle::initialRegionOverflow())
+    , m_regionBreakAfter(RenderStyle::initialPageBreak())
+    , m_regionBreakBefore(RenderStyle::initialPageBreak())
+    , m_regionBreakInside(RenderStyle::initialPageBreak())
+    , m_pageSizeType(PAGE_SIZE_AUTO)
+    , m_transformStyle3D(RenderStyle::initialTransformStyle3D())
+    , m_backfaceVisibility(RenderStyle::initialBackfaceVisibility())
+    , m_alignContent(RenderStyle::initialAlignContent())
+    , m_alignItems(RenderStyle::initialAlignItems())
+    , m_alignSelf(RenderStyle::initialAlignSelf())
+    , m_justifyContent(RenderStyle::initialJustifyContent())
+    , userDrag(RenderStyle::initialUserDrag())
+    , textOverflow(RenderStyle::initialTextOverflow())
+    , marginBeforeCollapse(MCOLLAPSE)
+    , marginAfterCollapse(MCOLLAPSE)
+    , m_appearance(RenderStyle::initialAppearance())
+    , m_borderFit(RenderStyle::initialBorderFit())
+    , m_textCombine(RenderStyle::initialTextCombine())
+#if ENABLE(CSS3_TEXT)
+    , m_textDecorationStyle(RenderStyle::initialTextDecorationStyle())
+#endif // CSS3_TEXT
+    , m_wrapFlow(RenderStyle::initialWrapFlow())
+    , m_wrapThrough(RenderStyle::initialWrapThrough())
+    , m_runningAcceleratedAnimation(false)
+    , m_hasAspectRatio(false)
+#if ENABLE(CSS_COMPOSITING)
+    , m_effectiveBlendMode(RenderStyle::initialBlendMode())
+#endif
+{
+    m_maskBoxImage.setMaskDefaults();
+}
+
+StyleRareNonInheritedData::StyleRareNonInheritedData(const StyleRareNonInheritedData& o)
+    : RefCounted<StyleRareNonInheritedData>()
+    , opacity(o.opacity)
+    , m_aspectRatioDenominator(o.m_aspectRatioDenominator)
+    , m_aspectRatioNumerator(o.m_aspectRatioNumerator)
+    , m_perspective(o.m_perspective)
+    , m_perspectiveOriginX(o.m_perspectiveOriginX)
+    , m_perspectiveOriginY(o.m_perspectiveOriginY)
+    , lineClamp(o.lineClamp)
+    , m_draggableRegionMode(o.m_draggableRegionMode)
+    , m_deprecatedFlexibleBox(o.m_deprecatedFlexibleBox)
+    , m_flexibleBox(o.m_flexibleBox)
+    , m_marquee(o.m_marquee)
+    , m_multiCol(o.m_multiCol)
+    , m_transform(o.m_transform)
+    , m_filter(o.m_filter)
+    , m_grid(o.m_grid)
+    , m_gridItem(o.m_gridItem)
+    , m_content(o.m_content ? o.m_content->clone() : nullptr)
+    , m_counterDirectives(o.m_counterDirectives ? clone(*o.m_counterDirectives) : nullptr)
+    , m_boxShadow(o.m_boxShadow ? adoptPtr(new ShadowData(*o.m_boxShadow)) : nullptr)
+    , m_boxReflect(o.m_boxReflect)
+    , m_animations(o.m_animations ? adoptPtr(new CSSAnimationDataList(*o.m_animations)) : nullptr)
+    , m_transitions(o.m_transitions ? adoptPtr(new CSSAnimationDataList(*o.m_transitions)) : nullptr)
+    , m_mask(o.m_mask)
+    , m_maskBoxImage(o.m_maskBoxImage)
+    , m_pageSize(o.m_pageSize)
+    , m_shapeInside(o.m_shapeInside)
+    , m_shapeOutside(o.m_shapeOutside)
+    , m_shapeMargin(o.m_shapeMargin)
+    , m_shapePadding(o.m_shapePadding)
+    , m_clipPath(o.m_clipPath)
+#if ENABLE(CSS3_TEXT)
+    , m_textDecorationColor(o.m_textDecorationColor)
+    , m_visitedLinkTextDecorationColor(o.m_visitedLinkTextDecorationColor)
+#endif // CSS3_TEXT
+    , m_visitedLinkBackgroundColor(o.m_visitedLinkBackgroundColor)
+    , m_visitedLinkOutlineColor(o.m_visitedLinkOutlineColor)
+    , m_visitedLinkBorderLeftColor(o.m_visitedLinkBorderLeftColor)
+    , m_visitedLinkBorderRightColor(o.m_visitedLinkBorderRightColor)
+    , m_visitedLinkBorderTopColor(o.m_visitedLinkBorderTopColor)
+    , m_visitedLinkBorderBottomColor(o.m_visitedLinkBorderBottomColor)
+    , m_order(o.m_order)
+    , m_flowThread(o.m_flowThread)
+    , m_regionThread(o.m_regionThread)
+    , m_regionOverflow(o.m_regionOverflow)
+    , m_regionBreakAfter(o.m_regionBreakAfter)
+    , m_regionBreakBefore(o.m_regionBreakBefore)
+    , m_regionBreakInside(o.m_regionBreakInside)
+    , m_pageSizeType(o.m_pageSizeType)
+    , m_transformStyle3D(o.m_transformStyle3D)
+    , m_backfaceVisibility(o.m_backfaceVisibility)
+    , m_alignContent(o.m_alignContent)
+    , m_alignItems(o.m_alignItems)
+    , m_alignSelf(o.m_alignSelf)
+    , m_justifyContent(o.m_justifyContent)
+    , userDrag(o.userDrag)
+    , textOverflow(o.textOverflow)
+    , marginBeforeCollapse(o.marginBeforeCollapse)
+    , marginAfterCollapse(o.marginAfterCollapse)
+    , m_appearance(o.m_appearance)
+    , m_borderFit(o.m_borderFit)
+    , m_textCombine(o.m_textCombine)
+#if ENABLE(CSS3_TEXT)
+    , m_textDecorationStyle(o.m_textDecorationStyle)
+#endif // CSS3_TEXT
+    , m_wrapFlow(o.m_wrapFlow)
+    , m_wrapThrough(o.m_wrapThrough)
+    , m_runningAcceleratedAnimation(o.m_runningAcceleratedAnimation)
+    , m_hasAspectRatio(o.m_hasAspectRatio)
+#if ENABLE(CSS_COMPOSITING)
+    , m_effectiveBlendMode(o.m_effectiveBlendMode)
+#endif
+{
+}
+
+StyleRareNonInheritedData::~StyleRareNonInheritedData()
+{
+}
+
+bool StyleRareNonInheritedData::operator==(const StyleRareNonInheritedData& o) const
+{
+    return opacity == o.opacity
+        && m_aspectRatioDenominator == o.m_aspectRatioDenominator
+        && m_aspectRatioNumerator == o.m_aspectRatioNumerator
+        && m_perspective == o.m_perspective
+        && m_perspectiveOriginX == o.m_perspectiveOriginX
+        && m_perspectiveOriginY == o.m_perspectiveOriginY
+        && lineClamp == o.lineClamp
+        && m_draggableRegionMode == o.m_draggableRegionMode
+        && m_deprecatedFlexibleBox == o.m_deprecatedFlexibleBox
+        && m_flexibleBox == o.m_flexibleBox
+        && m_marquee == o.m_marquee
+        && m_multiCol == o.m_multiCol
+        && m_transform == o.m_transform
+        && m_filter == o.m_filter
+        && m_grid == o.m_grid
+        && m_gridItem == o.m_gridItem
+        && contentDataEquivalent(o)
+        && counterDataEquivalent(o)
+        && shadowDataEquivalent(o)
+        && reflectionDataEquivalent(o)
+        && animationDataEquivalent(o)
+        && transitionDataEquivalent(o)
+        && m_mask == o.m_mask
+        && m_maskBoxImage == o.m_maskBoxImage
+        && m_pageSize == o.m_pageSize
+        && m_shapeInside == o.m_shapeInside
+        && m_shapeOutside == o.m_shapeOutside
+        && m_shapeMargin == o.m_shapeMargin
+        && m_shapePadding == o.m_shapePadding
+        && m_clipPath == o.m_clipPath
+#if ENABLE(CSS3_TEXT)
+        && m_textDecorationColor == o.m_textDecorationColor
+        && m_visitedLinkTextDecorationColor == o.m_visitedLinkTextDecorationColor
+#endif // CSS3_TEXT
+        && m_visitedLinkBackgroundColor == o.m_visitedLinkBackgroundColor
+        && m_visitedLinkOutlineColor == o.m_visitedLinkOutlineColor
+        && m_visitedLinkBorderLeftColor == o.m_visitedLinkBorderLeftColor
+        && m_visitedLinkBorderRightColor == o.m_visitedLinkBorderRightColor
+        && m_visitedLinkBorderTopColor == o.m_visitedLinkBorderTopColor
+        && m_visitedLinkBorderBottomColor == o.m_visitedLinkBorderBottomColor
+        && m_order == o.m_order
+        && m_flowThread == o.m_flowThread
+        && m_regionThread == o.m_regionThread
+        && m_regionOverflow == o.m_regionOverflow
+        && m_regionBreakAfter == o.m_regionBreakAfter
+        && m_regionBreakBefore == o.m_regionBreakBefore
+        && m_regionBreakInside == o.m_regionBreakInside
+        && m_pageSizeType == o.m_pageSizeType
+        && m_transformStyle3D == o.m_transformStyle3D
+        && m_backfaceVisibility == o.m_backfaceVisibility
+        && m_alignContent == o.m_alignContent
+        && m_alignItems == o.m_alignItems
+        && m_alignSelf == o.m_alignSelf
+        && m_justifyContent == o.m_justifyContent
+        && userDrag == o.userDrag
+        && textOverflow == o.textOverflow
+        && marginBeforeCollapse == o.marginBeforeCollapse
+        && marginAfterCollapse == o.marginAfterCollapse
+        && m_appearance == o.m_appearance
+        && m_borderFit == o.m_borderFit
+        && m_textCombine == o.m_textCombine
+#if ENABLE(CSS3_TEXT)
+        && m_textDecorationStyle == o.m_textDecorationStyle
+#endif // CSS3_TEXT
+        && m_wrapFlow == o.m_wrapFlow
+        && m_wrapThrough == o.m_wrapThrough
+        && !m_runningAcceleratedAnimation && !o.m_runningAcceleratedAnimation
+#if ENABLE(CSS_COMPOSITING)
+        && m_effectiveBlendMode == o.m_effectiveBlendMode
+#endif
+        && m_hasAspectRatio == o.m_hasAspectRatio;
+}
+
+bool StyleRareNonInheritedData::contentDataEquivalent(const StyleRareNonInheritedData& o) const
+{
+    ContentData* a = m_content.get();
+    ContentData* b = o.m_content.get();
+
+    while (a && b && *a == *b) {
+        a = a->next();
+        b = b->next();
+    }
+
+    return !a && !b;
+}
+
+bool StyleRareNonInheritedData::counterDataEquivalent(const StyleRareNonInheritedData& o) const
+{
+    if (m_counterDirectives.get() == o.m_counterDirectives.get())
+        return true;
+        
+    if (m_counterDirectives && o.m_counterDirectives && *m_counterDirectives == *o.m_counterDirectives)
+        return true;
+
+    return false;
+}
+
+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;
+}
+
+void StyleRareNonInheritedData::reportMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
+{
+    MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS);
+    info.addMember(m_deprecatedFlexibleBox, "deprecatedFlexibleBox");
+    info.addMember(m_flexibleBox, "flexibleBox");
+    info.addMember(m_marquee, "marquee");
+    info.addMember(m_multiCol, "multiCol");
+    info.addMember(m_transform, "transform");
+    info.addMember(m_filter, "filter");
+    info.addMember(m_grid, "grid");
+    info.addMember(m_gridItem, "gridItem");
+    info.addMember(m_content, "content");
+    info.addMember(m_counterDirectives, "counterDirectives");
+    info.addMember(m_boxShadow, "boxShadow");
+    info.addMember(m_boxReflect, "boxReflect");
+    info.addMember(m_animations, "animations");
+    info.addMember(m_transitions, "transitions");
+    info.addMember(m_shapeInside, "shapeInside");
+    info.addMember(m_shapeOutside, "shapeOutside");
+    info.addMember(m_clipPath, "clipPath");
+    info.addMember(m_flowThread, "flowThread");
+    info.addMember(m_regionThread, "regionThread");
+
+    info.ignoreMember(m_perspectiveOriginX);
+    info.ignoreMember(m_perspectiveOriginY);
+    info.ignoreMember(m_pageSize);
+    info.ignoreMember(m_shapeMargin);
+    info.ignoreMember(m_shapePadding);
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/style/StyleRareNonInheritedData.h b/Source/core/rendering/style/StyleRareNonInheritedData.h
new file mode 100644
index 0000000..2cad177
--- /dev/null
+++ b/Source/core/rendering/style/StyleRareNonInheritedData.h
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ *           (C) 2000 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com)
+ *
+ * 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 "core/rendering/ClipPathOperation.h"
+#include "core/rendering/style/BasicShapes.h"
+#include "core/rendering/style/CounterDirectives.h"
+#include "core/rendering/style/CursorData.h"
+#include "core/rendering/style/DataRef.h"
+#include "core/rendering/style/ExclusionShapeValue.h"
+#include "core/rendering/style/FillLayer.h"
+#include "core/rendering/style/LineClampValue.h"
+#include "core/rendering/style/NinePieceImage.h"
+#include <wtf/OwnPtr.h>
+#include <wtf/PassRefPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class CSSAnimationDataList;
+class ShadowData;
+class StyleDeprecatedFlexibleBoxData;
+class StyleFilterData;
+class StyleFlexibleBoxData;
+class StyleGridData;
+class StyleGridItemData;
+class StyleMarqueeData;
+class StyleMultiColData;
+class StyleReflection;
+class StyleResolver;
+class StyleTransformData;
+
+class ContentData;
+struct LengthSize;
+
+// Page size type.
+// StyleRareNonInheritedData::m_pageSize is meaningful only when 
+// StyleRareNonInheritedData::m_pageSizeType is PAGE_SIZE_RESOLVED.
+enum PageSizeType {
+    PAGE_SIZE_AUTO, // size: auto
+    PAGE_SIZE_AUTO_LANDSCAPE, // size: landscape
+    PAGE_SIZE_AUTO_PORTRAIT, // size: portrait
+    PAGE_SIZE_RESOLVED // Size is fully resolved.
+};
+
+// 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();
+    
+    bool operator==(const StyleRareNonInheritedData&) const;
+    bool operator!=(const StyleRareNonInheritedData& o) const { return !(*this == o); }
+
+    bool contentDataEquivalent(const StyleRareNonInheritedData&) const;
+    bool counterDataEquivalent(const StyleRareNonInheritedData&) const;
+    bool shadowDataEquivalent(const StyleRareNonInheritedData&) const;
+    bool reflectionDataEquivalent(const StyleRareNonInheritedData&) const;
+    bool animationDataEquivalent(const StyleRareNonInheritedData&) const;
+    bool transitionDataEquivalent(const StyleRareNonInheritedData&) const;
+
+    void reportMemoryUsage(MemoryObjectInfo*) const;
+
+    float opacity; // Whether or not we're transparent.
+
+    float m_aspectRatioDenominator;
+    float m_aspectRatioNumerator;
+
+    float m_perspective;
+    Length m_perspectiveOriginX;
+    Length m_perspectiveOriginY;
+
+    LineClampValue lineClamp; // An Apple extension.
+    DraggableRegionMode m_draggableRegionMode;
+
+    DataRef<StyleDeprecatedFlexibleBoxData> m_deprecatedFlexibleBox; // Flexible box properties
+    DataRef<StyleFlexibleBoxData> m_flexibleBox;
+    DataRef<StyleMarqueeData> m_marquee; // Marquee properties
+    DataRef<StyleMultiColData> m_multiCol; //  CSS3 multicol properties
+    DataRef<StyleTransformData> m_transform; // Transform properties (rotate, scale, skew, etc.)
+
+    DataRef<StyleFilterData> m_filter; // Filter operations (url, sepia, blur, etc.)
+
+    DataRef<StyleGridData> m_grid;
+    DataRef<StyleGridItemData> m_gridItem;
+
+    OwnPtr<ContentData> m_content;
+    OwnPtr<CounterDirectiveMap> m_counterDirectives;
+
+    OwnPtr<ShadowData> m_boxShadow;  // For box-shadow decorations.
+    
+    RefPtr<StyleReflection> m_boxReflect;
+
+    OwnPtr<CSSAnimationDataList> m_animations;
+    OwnPtr<CSSAnimationDataList> m_transitions;
+
+    FillLayer m_mask;
+    NinePieceImage m_maskBoxImage;
+
+    LengthSize m_pageSize;
+
+    RefPtr<ExclusionShapeValue> m_shapeInside;
+    RefPtr<ExclusionShapeValue> m_shapeOutside;
+    Length m_shapeMargin;
+    Length m_shapePadding;
+
+    RefPtr<ClipPathOperation> m_clipPath;
+
+#if ENABLE(CSS3_TEXT)
+    Color m_textDecorationColor;
+    Color m_visitedLinkTextDecorationColor;
+#endif // CSS3_TEXT
+    Color m_visitedLinkBackgroundColor;
+    Color m_visitedLinkOutlineColor;
+    Color m_visitedLinkBorderLeftColor;
+    Color m_visitedLinkBorderRightColor;
+    Color m_visitedLinkBorderTopColor;
+    Color m_visitedLinkBorderBottomColor;
+
+    int m_order;
+
+    AtomicString m_flowThread;
+    AtomicString m_regionThread;
+    unsigned m_regionOverflow : 1; // RegionOverflow
+
+    unsigned m_regionBreakAfter : 2; // EPageBreak
+    unsigned m_regionBreakBefore : 2; // EPageBreak
+    unsigned m_regionBreakInside : 2; // EPageBreak
+
+    unsigned m_pageSizeType : 2; // PageSizeType
+    unsigned m_transformStyle3D : 1; // ETransformStyle3D
+    unsigned m_backfaceVisibility : 1; // EBackfaceVisibility
+
+    unsigned m_alignContent : 3; // EAlignContent
+    unsigned m_alignItems : 3; // EAlignItems
+    unsigned m_alignSelf : 3; // EAlignItems
+    unsigned m_justifyContent : 3; // EJustifyContent
+
+    unsigned userDrag : 2; // EUserDrag
+    unsigned textOverflow : 1; // Whether or not lines that spill out should be truncated with "..."
+    unsigned marginBeforeCollapse : 2; // EMarginCollapse
+    unsigned marginAfterCollapse : 2; // EMarginCollapse
+    unsigned m_appearance : 6; // EAppearance
+    unsigned m_borderFit : 1; // EBorderFit
+    unsigned m_textCombine : 1; // CSS3 text-combine properties
+
+#if ENABLE(CSS3_TEXT)
+    unsigned m_textDecorationStyle : 3; // TextDecorationStyle
+#endif // CSS3_TEXT
+    unsigned m_wrapFlow: 3; // WrapFlow
+    unsigned m_wrapThrough: 1; // WrapThrough
+
+    unsigned m_runningAcceleratedAnimation : 1;
+
+    unsigned m_hasAspectRatio : 1; // Whether or not an aspect ratio has been specified.
+
+#if ENABLE(CSS_COMPOSITING)
+    unsigned m_effectiveBlendMode: 5; // EBlendMode
+#endif
+
+private:
+    StyleRareNonInheritedData();
+    StyleRareNonInheritedData(const StyleRareNonInheritedData&);
+};
+
+} // namespace WebCore
+
+#endif // StyleRareNonInheritedData_h
diff --git a/Source/core/rendering/style/StyleReflection.h b/Source/core/rendering/style/StyleReflection.h
new file mode 100644
index 0000000..0005a5e
--- /dev/null
+++ b/Source/core/rendering/style/StyleReflection.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ *           (C) 2000 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com)
+ *
+ * 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 "core/css/CSSReflectionDirection.h"
+#include "core/platform/Length.h"
+#include "core/rendering/style/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)
+    {
+         m_mask.setMaskDefaults();
+    }
+    
+    CSSReflectionDirection m_direction;
+    Length m_offset;
+    NinePieceImage m_mask;
+};
+
+} // namespace WebCore
+
+#endif // StyleReflection_h
diff --git a/Source/core/rendering/style/StyleShader.h b/Source/core/rendering/style/StyleShader.h
new file mode 100644
index 0000000..9ca34ff
--- /dev/null
+++ b/Source/core/rendering/style/StyleShader.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2011 Adobe Systems Incorporated. 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 THE COPYRIGHT HOLDER “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 THE COPYRIGHT HOLDER 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 StyleShader_h
+#define StyleShader_h
+
+#include <wtf/RefCounted.h>
+
+namespace WebCore {
+
+class CachedShader;
+class CSSValue;
+
+class StyleShader : public RefCounted<StyleShader> {
+public:
+    virtual ~StyleShader() { }
+
+    ALWAYS_INLINE bool isCachedShader() const { return m_isCachedShader; }
+    ALWAYS_INLINE bool isPendingShader() const { return m_isPendingShader; }
+    
+    virtual PassRefPtr<CSSValue> cssValue() const = 0;
+    
+    virtual CachedShader* cachedShader() const { return 0; }
+    
+protected:
+    StyleShader()
+        : m_isCachedShader(false)
+        , m_isPendingShader(false)
+    {
+    }
+    bool m_isCachedShader : 1;
+    bool m_isPendingShader : 1;
+};
+
+}
+
+
+#endif // StyleShader_h
diff --git a/Source/core/rendering/style/StyleSurroundData.cpp b/Source/core/rendering/style/StyleSurroundData.cpp
new file mode 100644
index 0000000..337dcad
--- /dev/null
+++ b/Source/core/rendering/style/StyleSurroundData.cpp
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * 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 "core/rendering/style/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/Source/core/rendering/style/StyleSurroundData.h b/Source/core/rendering/style/StyleSurroundData.h
new file mode 100644
index 0000000..c388e71
--- /dev/null
+++ b/Source/core/rendering/style/StyleSurroundData.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ *           (C) 2000 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com)
+ *
+ * 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 "core/platform/LengthBox.h"
+#include "core/rendering/style/BorderData.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.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/Source/core/rendering/style/StyleTransformData.cpp b/Source/core/rendering/style/StyleTransformData.cpp
new file mode 100644
index 0000000..d772fd8
--- /dev/null
+++ b/Source/core/rendering/style/StyleTransformData.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * 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 "core/rendering/style/StyleTransformData.h"
+
+#include "core/rendering/style/RenderStyle.h"
+
+namespace WebCore {
+
+StyleTransformData::StyleTransformData()
+    : m_operations(RenderStyle::initialTransform())
+    , m_x(RenderStyle::initialTransformOriginX())
+    , m_y(RenderStyle::initialTransformOriginY())
+    , m_z(RenderStyle::initialTransformOriginZ())
+{
+}
+
+StyleTransformData::StyleTransformData(const StyleTransformData& o)
+    : RefCounted<StyleTransformData>()
+    , m_operations(o.m_operations)
+    , m_x(o.m_x)
+    , m_y(o.m_y)
+    , m_z(o.m_z)
+{
+}
+
+bool StyleTransformData::operator==(const StyleTransformData& o) const
+{
+    return m_x == o.m_x && m_y == o.m_y && m_z == o.m_z && m_operations == o.m_operations;
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/style/StyleTransformData.h b/Source/core/rendering/style/StyleTransformData.h
new file mode 100644
index 0000000..92fe9f9
--- /dev/null
+++ b/Source/core/rendering/style/StyleTransformData.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ *           (C) 2000 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com)
+ *
+ * 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 "core/platform/Length.h"
+#include "core/platform/graphics/transforms/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;
+    float m_z;
+
+private:
+    StyleTransformData();
+    StyleTransformData(const StyleTransformData&);
+};
+
+} // namespace WebCore
+
+#endif // StyleTransformData_h
diff --git a/Source/core/rendering/style/StyleVariableData.h b/Source/core/rendering/style/StyleVariableData.h
new file mode 100644
index 0000000..c2edb4f
--- /dev/null
+++ b/Source/core/rendering/style/StyleVariableData.h
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2012 Google 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:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+ * OWNER 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 StyleVariableData_h
+#define StyleVariableData_h
+
+#include <wtf/Forward.h>
+#include <wtf/HashMap.h>
+#include <wtf/RefCounted.h>
+#include <wtf/text/AtomicStringHash.h>
+
+namespace WebCore {
+
+class CursorList;
+class QuotesData;
+class ShadowData;
+
+class StyleVariableData : public RefCounted<StyleVariableData> {
+public:
+    static PassRefPtr<StyleVariableData> create() { return adoptRef(new StyleVariableData()); }
+    PassRefPtr<StyleVariableData> copy() const { return adoptRef(new StyleVariableData(*this)); }
+
+    bool operator==(const StyleVariableData& other) const { return other.m_data == m_data; }
+    bool operator!=(const StyleVariableData& other) const { return !(*this == other); }
+
+    void setVariable(const AtomicString& name, const String& value) { m_data.set(name, value); }
+
+    HashMap<AtomicString, String> m_data;
+private:
+    explicit StyleVariableData() : RefCounted<StyleVariableData>() { }
+    StyleVariableData(const StyleVariableData& other) : RefCounted<StyleVariableData>(), m_data(HashMap<AtomicString, String>(other.m_data)) { }
+};
+
+} // namespace WebCore
+
+#endif /* StyleVariableData_h */
diff --git a/Source/core/rendering/style/StyleVisualData.cpp b/Source/core/rendering/style/StyleVisualData.cpp
new file mode 100644
index 0000000..db87122
--- /dev/null
+++ b/Source/core/rendering/style/StyleVisualData.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 1999 Antti Koivisto (koivisto@kde.org)
+ * 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 "core/rendering/style/StyleVisualData.h"
+
+#include "core/rendering/style/RenderStyle.h"
+
+namespace WebCore {
+
+StyleVisualData::StyleVisualData()
+    : hasClip(false)
+    , textDecoration(RenderStyle::initialTextDecoration())
+    , m_textAutosizingMultiplier(1)
+    , m_zoom(RenderStyle::initialZoom())
+{
+}
+
+StyleVisualData::~StyleVisualData()
+{
+}
+
+StyleVisualData::StyleVisualData(const StyleVisualData& o)
+    : RefCounted<StyleVisualData>()
+    , clip(o.clip)
+    , hasClip(o.hasClip)
+    , textDecoration(o.textDecoration)
+    , m_textAutosizingMultiplier(o.m_textAutosizingMultiplier)
+    , m_zoom(RenderStyle::initialZoom())
+{
+}
+
+} // namespace WebCore
diff --git a/Source/core/rendering/style/StyleVisualData.h b/Source/core/rendering/style/StyleVisualData.h
new file mode 100644
index 0000000..f82c01c
--- /dev/null
+++ b/Source/core/rendering/style/StyleVisualData.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2000 Lars Knoll (knoll@kde.org)
+ *           (C) 2000 Antti Koivisto (koivisto@kde.org)
+ *           (C) 2000 Dirk Mueller (mueller@kde.org)
+ * Copyright (C) 2003, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2006 Graham Dennis (graham.dennis@gmail.com)
+ *
+ * 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 "core/platform/LengthBox.h"
+#include "core/rendering/style/RenderStyleConstants.h"
+#include <wtf/PassRefPtr.h>
+#include <wtf/RefCounted.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
+            && textDecoration == o.textDecoration
+            && m_textAutosizingMultiplier == o.m_textAutosizingMultiplier
+            && m_zoom == o.m_zoom;
+    }
+    bool operator!=(const StyleVisualData& o) const { return !(*this == o); }
+
+    LengthBox clip;
+    bool hasClip : 1;
+    unsigned textDecoration : ETextDecorationBits; // Text decorations defined *only* by this element.
+
+    float m_textAutosizingMultiplier;
+    float m_zoom;
+
+private:
+    StyleVisualData();
+    StyleVisualData(const StyleVisualData&);    
+};
+
+} // namespace WebCore
+
+#endif // StyleVisualData_h
diff --git a/Source/core/rendering/svg/RenderSVGBlock.cpp b/Source/core/rendering/svg/RenderSVGBlock.cpp
new file mode 100644
index 0000000..1a85b15
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGBlock.cpp
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) Research In Motion Limited 2010. 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"
+
+#if ENABLE(SVG)
+#include "core/rendering/svg/RenderSVGBlock.h"
+
+#include "core/rendering/style/StyleInheritedData.h"
+#include "core/rendering/svg/RenderSVGResource.h"
+#include "core/rendering/svg/SVGResourcesCache.h"
+#include "core/svg/SVGElement.h"
+
+namespace WebCore {
+
+RenderSVGBlock::RenderSVGBlock(SVGElement* element)
+    : RenderBlock(element)
+{
+}
+
+LayoutRect RenderSVGBlock::visualOverflowRect() const
+{
+    LayoutRect borderRect = borderBoxRect();
+
+    if (const ShadowData* textShadow = style()->textShadow())
+        textShadow->adjustRectForShadow(borderRect);
+
+    return borderRect;
+}
+
+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->isDisplayInlineType()) {
+        RefPtr<RenderStyle> newStyle = RenderStyle::create();
+        newStyle->inheritFrom(useStyle.get());
+        newStyle->setDisplay(BLOCK);
+        useStyle = newStyle.release();
+    }
+
+    RenderBlock::setStyle(useStyle.release());
+}
+
+void RenderSVGBlock::updateFromStyle()
+{
+    RenderBlock::updateFromStyle();
+
+    // RenderSVGlock, used by Render(SVGText|ForeignObject), is not allowed to call setHasOverflowClip(true).
+    // RenderBlock assumes a layer to be present when the overflow clip functionality is requested. Both
+    // Render(SVGText|ForeignObject) return 'false' on 'requiresLayer'. Fine for RenderSVGText.
+    //
+    // If we want to support overflow rules for <foreignObject> we can choose between two solutions:
+    // a) make RenderSVGForeignObject require layers and SVG layer aware
+    // b) reactor overflow logic out of RenderLayer (as suggested by dhyatt), which is a large task
+    //
+    // Until this is resolved, disable overflow support. Opera/FF don't support it as well at the moment (Feb 2010).
+    //
+    // Note: This does NOT affect overflow handling on outer/inner <svg> elements - this is handled
+    // manually by RenderSVGRoot - which owns the documents enclosing root layer and thus works fine.
+    setHasOverflowClip(false);
+}
+
+void RenderSVGBlock::absoluteRects(Vector<IntRect>&, const LayoutPoint&) const
+{
+    // This code path should never be taken for SVG, as we're assuming useTransforms=true everywhere, absoluteQuads should be used.
+    ASSERT_NOT_REACHED();
+}
+
+void RenderSVGBlock::willBeDestroyed()
+{
+    SVGResourcesCache::clientDestroyed(this);
+    RenderBlock::willBeDestroyed();
+}
+
+void RenderSVGBlock::styleWillChange(StyleDifference diff, const RenderStyle* newStyle)
+{
+    if (diff == StyleDifferenceLayout)
+        setNeedsBoundariesUpdate();
+    RenderBlock::styleWillChange(diff, newStyle);
+}
+
+void RenderSVGBlock::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
+{
+    RenderBlock::styleDidChange(diff, oldStyle);
+    SVGResourcesCache::clientStyleChanged(this, diff, style());
+}
+
+}
+
+#endif
diff --git a/Source/core/rendering/svg/RenderSVGBlock.h b/Source/core/rendering/svg/RenderSVGBlock.h
new file mode 100644
index 0000000..7b53803
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGBlock.h
@@ -0,0 +1,52 @@
+/*
+ * 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 "core/rendering/RenderBlock.h"
+#include "core/rendering/svg/SVGRenderSupport.h"
+
+namespace WebCore {
+
+class SVGElement;
+
+class RenderSVGBlock : public RenderBlock {
+public:
+    explicit RenderSVGBlock(SVGElement*);
+
+    virtual LayoutRect visualOverflowRect() const OVERRIDE FINAL;
+
+protected:
+    virtual void willBeDestroyed() OVERRIDE;
+
+private:
+    virtual void setStyle(PassRefPtr<RenderStyle>) OVERRIDE FINAL;
+    virtual void updateFromStyle() OVERRIDE FINAL;
+
+    virtual void absoluteRects(Vector<IntRect>&, const LayoutPoint& accumulatedOffset) const OVERRIDE FINAL;
+
+    virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle) OVERRIDE FINAL;
+    virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE FINAL;
+};
+
+}
+#endif
+#endif
diff --git a/Source/core/rendering/svg/RenderSVGContainer.cpp b/Source/core/rendering/svg/RenderSVGContainer.cpp
new file mode 100644
index 0000000..e51a4ac
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGContainer.cpp
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) 2004, 2005, 2007, 2008 Rob Buis <buis@kde.org>
+ * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
+ * Copyright (C) 2009 Google, Inc.  All rights reserved.
+ * Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, 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 "core/rendering/svg/RenderSVGContainer.h"
+
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/rendering/LayoutRepainter.h"
+#include "core/rendering/RenderView.h"
+#include "core/rendering/svg/RenderSVGResource.h"
+#include "core/rendering/svg/RenderSVGResourceFilter.h"
+#include "core/rendering/svg/SVGRenderingContext.h"
+#include "core/rendering/svg/SVGResources.h"
+#include "core/rendering/svg/SVGResourcesCache.h"
+#include "core/svg/SVGStyledElement.h"
+
+namespace WebCore {
+
+RenderSVGContainer::RenderSVGContainer(SVGStyledElement* node)
+    : RenderSVGModelObject(node)
+    , m_objectBoundingBoxValid(false)
+    , m_needsBoundariesUpdate(true)
+{
+}
+
+RenderSVGContainer::~RenderSVGContainer()
+{
+}
+
+void RenderSVGContainer::layout()
+{
+    StackStats::LayoutCheckPoint layoutCheckPoint;
+    ASSERT(needsLayout());
+
+    // RenderSVGRoot disables layoutState for the SVG rendering tree.
+    ASSERT(!view()->layoutStateEnabled());
+
+    LayoutRepainter repainter(*this, SVGRenderSupport::checkForSVGRepaintDuringLayout(this) || selfWillPaint());
+
+    // Allow RenderSVGViewportContainer to update its viewport.
+    calcViewport();
+
+    // Allow RenderSVGTransformableContainer to update its transform.
+    bool updatedTransform = calculateLocalTransform();
+
+    // RenderSVGViewportContainer needs to set the 'layout size changed' flag.
+    determineIfLayoutSizeChanged();
+
+    SVGRenderSupport::layoutChildren(this, selfNeedsLayout() || SVGRenderSupport::filtersForceContainerLayout(this));
+
+    // Invalidate all resources of this client if our layout changed.
+    if (everHadLayout() && needsLayout())
+        SVGResourcesCache::clientLayoutChanged(this);
+
+    // At this point LayoutRepainter already grabbed the old bounds,
+    // recalculate them now so repaintAfterLayout() uses the new bounds.
+    if (m_needsBoundariesUpdate || updatedTransform) {
+        updateCachedBoundaries();
+        m_needsBoundariesUpdate = false;
+    
+        // If our bounds changed, notify the parents.
+        RenderSVGModelObject::setNeedsBoundariesUpdate();
+    }
+
+    repainter.repaintAfterLayout();
+    setNeedsLayout(false);
+}
+
+void RenderSVGContainer::addChild(RenderObject* child, RenderObject* beforeChild)
+{
+    RenderSVGModelObject::addChild(child, beforeChild);
+    SVGResourcesCache::clientWasAddedToTree(child, child->style());
+}
+
+void RenderSVGContainer::removeChild(RenderObject* child)
+{
+    SVGResourcesCache::clientWillBeRemovedFromTree(child);
+    RenderSVGModelObject::removeChild(child);
+}
+
+
+bool RenderSVGContainer::selfWillPaint()
+{
+    SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(this);
+    return resources && resources->filter();
+}
+
+void RenderSVGContainer::paint(PaintInfo& paintInfo, const LayoutPoint&)
+{
+    if (paintInfo.context->paintingDisabled())
+        return;
+
+    // Spec: groups w/o children still may render filter content.
+    if (!firstChild() && !selfWillPaint())
+        return;
+
+    FloatRect repaintRect = repaintRectInLocalCoordinates();
+    if (!SVGRenderSupport::paintInfoIntersectsRepaintRect(repaintRect, localToParentTransform(), paintInfo))
+        return;
+
+    PaintInfo childPaintInfo(paintInfo);
+    {
+        GraphicsContextStateSaver stateSaver(*childPaintInfo.context);
+
+        // Let the RenderSVGViewportContainer subclass clip if necessary
+        applyViewportClip(childPaintInfo);
+
+        childPaintInfo.applyTransform(localToParentTransform());
+
+        SVGRenderingContext renderingContext;
+        bool continueRendering = true;
+        if (childPaintInfo.phase == PaintPhaseForeground) {
+            renderingContext.prepareToRenderSVGContent(this, childPaintInfo);
+            continueRendering = renderingContext.isRenderingPrepared();
+        }
+
+        if (continueRendering) {
+            childPaintInfo.updatePaintingRootForChildren(this);
+            for (RenderObject* child = firstChild(); child; child = child->nextSibling())
+                child->paint(childPaintInfo, IntPoint());
+        }
+    }
+    
+    // FIXME: This really should be drawn from local coordinates, but currently we hack it
+    // to avoid our clip killing our outline rect.  Thus we translate our
+    // outline rect into parent coords before drawing.
+    // FIXME: This means our focus ring won't share our rotation like it should.
+    // We should instead disable our clip during PaintPhaseOutline
+    if ((paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) && style()->outlineWidth() && style()->visibility() == VISIBLE) {
+        IntRect paintRectInParent = enclosingIntRect(localToParentTransform().mapRect(repaintRect));
+        paintOutline(paintInfo, paintRectInParent);
+    }
+}
+
+// addFocusRingRects is called from paintOutline and needs to be in the same coordinates as the paintOuline call
+void RenderSVGContainer::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint&, const RenderLayerModelObject*)
+{
+    IntRect paintRectInParent = enclosingIntRect(localToParentTransform().mapRect(repaintRectInLocalCoordinates()));
+    if (!paintRectInParent.isEmpty())
+        rects.append(paintRectInParent);
+}
+
+void RenderSVGContainer::updateCachedBoundaries()
+{
+    SVGRenderSupport::computeContainerBoundingBoxes(this, m_objectBoundingBox, m_objectBoundingBoxValid, m_strokeBoundingBox, m_repaintBoundingBox);
+    SVGRenderSupport::intersectRepaintRectWithResources(this, m_repaintBoundingBox);
+}
+
+bool RenderSVGContainer::nodeAtFloatPoint(const HitTestRequest& request, HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction)
+{
+    // Give RenderSVGViewportContainer a chance to apply its viewport clip
+    if (!pointIsInsideViewportClip(pointInParent))
+        return false;
+
+    FloatPoint localPoint = localToParentTransform().inverse().mapPoint(pointInParent);
+
+    if (!SVGRenderSupport::pointInClippingArea(this, localPoint))
+        return false;
+                
+    for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
+        if (child->nodeAtFloatPoint(request, result, localPoint, hitTestAction)) {
+            updateHitTestResult(result, roundedLayoutPoint(localPoint));
+            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)
diff --git a/Source/core/rendering/svg/RenderSVGContainer.h b/Source/core/rendering/svg/RenderSVGContainer.h
new file mode 100644
index 0000000..e5ef04b
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGContainer.h
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) 2004, 2005, 2007 Rob Buis <buis@kde.org>
+ * Copyright (C) 2009 Google, Inc.  All rights reserved.
+ * Copyright (C) 2009 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 RenderSVGContainer_h
+#define RenderSVGContainer_h
+
+#if ENABLE(SVG)
+
+#include "core/rendering/svg/RenderSVGModelObject.h"
+
+namespace WebCore {
+
+class SVGElement;
+
+class RenderSVGContainer : public RenderSVGModelObject {
+public:
+    explicit RenderSVGContainer(SVGStyledElement*);
+    virtual ~RenderSVGContainer();
+
+    RenderObject* firstChild() const { ASSERT(children() == virtualChildren()); return children()->firstChild(); }
+    RenderObject* lastChild() const { ASSERT(children() == virtualChildren()); return children()->lastChild(); }
+
+    const RenderObjectChildList* children() const { return &m_children; }
+    RenderObjectChildList* children() { return &m_children; }
+
+    virtual void paint(PaintInfo&, const LayoutPoint&);
+    virtual void setNeedsBoundariesUpdate() OVERRIDE FINAL { m_needsBoundariesUpdate = true; }
+    virtual bool needsBoundariesUpdate() OVERRIDE FINAL { return m_needsBoundariesUpdate; }
+    virtual bool didTransformToRootUpdate() { return false; }
+    bool isObjectBoundingBoxValid() const { return m_objectBoundingBoxValid; }
+
+protected:
+    virtual RenderObjectChildList* virtualChildren() OVERRIDE FINAL { return children(); }
+    virtual const RenderObjectChildList* virtualChildren() const OVERRIDE FINAL { return children(); }
+
+    virtual bool isSVGContainer() const OVERRIDE FINAL { return true; }
+    virtual const char* renderName() const { return "RenderSVGContainer"; }
+
+    virtual void layout();
+
+    virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0) OVERRIDE FINAL;
+    virtual void removeChild(RenderObject*) OVERRIDE FINAL;
+    virtual void addFocusRingRects(Vector<IntRect>&, const LayoutPoint& additionalOffset, const RenderLayerModelObject* paintContainer = 0) OVERRIDE FINAL;
+
+    virtual FloatRect objectBoundingBox() const OVERRIDE FINAL { return m_objectBoundingBox; }
+    virtual FloatRect strokeBoundingBox() const OVERRIDE FINAL { return m_strokeBoundingBox; }
+    virtual FloatRect repaintRectInLocalCoordinates() const OVERRIDE FINAL { return m_repaintBoundingBox; }
+
+    virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction);
+
+    // Allow RenderSVGTransformableContainer to hook in at the right time in layout()
+    virtual bool calculateLocalTransform() { return false; }
+
+    // Allow RenderSVGViewportContainer to hook in at the right times in layout(), paint() and nodeAtFloatPoint()
+    virtual void calcViewport() { }
+    virtual void applyViewportClip(PaintInfo&) { }
+    virtual bool pointIsInsideViewportClip(const FloatPoint& /*pointInParent*/) { return true; }
+
+    virtual void determineIfLayoutSizeChanged() { }
+
+    bool selfWillPaint();
+    void updateCachedBoundaries();
+
+private:
+    RenderObjectChildList m_children;
+    FloatRect m_objectBoundingBox;
+    bool m_objectBoundingBoxValid;
+    FloatRect m_strokeBoundingBox;
+    FloatRect m_repaintBoundingBox;
+    bool m_needsBoundariesUpdate : 1;
+};
+  
+inline RenderSVGContainer* toRenderSVGContainer(RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isSVGContainer());
+    return static_cast<RenderSVGContainer*>(object);
+}
+
+inline const RenderSVGContainer* toRenderSVGContainer(const RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isSVGContainer());
+    return static_cast<const RenderSVGContainer*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderSVGContainer(const RenderSVGContainer*);
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
+#endif // RenderSVGContainer_h
diff --git a/Source/core/rendering/svg/RenderSVGEllipse.cpp b/Source/core/rendering/svg/RenderSVGEllipse.cpp
new file mode 100644
index 0000000..aeaf725
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGEllipse.cpp
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2012 Google, 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 UNIVERSITY OF SZEGED ``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 UNIVERSITY OF SZEGED 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 "core/rendering/svg/RenderSVGEllipse.h"
+
+#include "SVGNames.h"
+#include "core/svg/SVGCircleElement.h"
+#include "core/svg/SVGEllipseElement.h"
+#include "core/svg/SVGStyledTransformableElement.h"
+
+namespace WebCore {
+
+RenderSVGEllipse::RenderSVGEllipse(SVGStyledTransformableElement* node)
+    : RenderSVGShape(node)
+    , m_usePathFallback(false)
+{
+}
+
+RenderSVGEllipse::~RenderSVGEllipse()
+{
+}
+
+void RenderSVGEllipse::updateShapeFromElement()
+{
+    // Before creating a new object we need to clear the cached bounding box
+    // to avoid using garbage.
+    m_fillBoundingBox = FloatRect();
+    m_strokeBoundingBox = FloatRect();
+    m_center = FloatPoint();
+    m_radii = FloatSize();
+
+    // Fallback to RenderSVGShape if shape has a non-scaling stroke.
+    if (hasNonScalingStroke()) {
+        RenderSVGShape::updateShapeFromElement();
+        m_usePathFallback = true;
+        return;
+    } else
+        m_usePathFallback = false;
+
+    calculateRadiiAndCenter();
+
+    // Spec: "A value of zero disables rendering of the element."
+    if (m_radii.width() <= 0 || m_radii.height() <= 0)
+        return;
+
+    m_fillBoundingBox = FloatRect(m_center.x() - m_radii.width(), m_center.y() - m_radii.height(), 2 * m_radii.width(), 2 * m_radii.height());
+    m_strokeBoundingBox = m_fillBoundingBox;
+    if (style()->svgStyle()->hasStroke())
+        m_strokeBoundingBox.inflate(strokeWidth() / 2);
+}
+
+void RenderSVGEllipse::calculateRadiiAndCenter()
+{
+    ASSERT(node());
+    if (node()->hasTagName(SVGNames::circleTag)) {
+
+        SVGCircleElement* circle = static_cast<SVGCircleElement*>(node());
+
+        SVGLengthContext lengthContext(circle);
+        float radius = circle->r().value(lengthContext);
+        m_radii = FloatSize(radius, radius);
+        m_center = FloatPoint(circle->cx().value(lengthContext), circle->cy().value(lengthContext));
+        return;
+    }
+
+    ASSERT(node()->hasTagName(SVGNames::ellipseTag));
+    SVGEllipseElement* ellipse = static_cast<SVGEllipseElement*>(node());
+
+    SVGLengthContext lengthContext(ellipse);
+    m_radii = FloatSize(ellipse->rx().value(lengthContext), ellipse->ry().value(lengthContext));
+    m_center = FloatPoint(ellipse->cx().value(lengthContext), ellipse->cy().value(lengthContext));
+}
+
+void RenderSVGEllipse::fillShape(GraphicsContext* context) const
+{
+    if (m_usePathFallback) {
+        RenderSVGShape::fillShape(context);
+        return;
+    }
+    context->fillEllipse(m_fillBoundingBox);
+}
+
+void RenderSVGEllipse::strokeShape(GraphicsContext* context) const
+{
+    if (!style()->svgStyle()->hasVisibleStroke())
+        return;
+    if (m_usePathFallback) {
+        RenderSVGShape::strokeShape(context);
+        return;
+    }
+    context->strokeEllipse(m_fillBoundingBox);
+}
+
+bool RenderSVGEllipse::shapeDependentStrokeContains(const FloatPoint& point)
+{
+    // The optimized contains code below does not support non-smooth strokes so we need
+    // to fall back to RenderSVGShape::shapeDependentStrokeContains in these cases.
+    if (m_usePathFallback || !hasSmoothStroke()) {
+        if (!hasPath())
+            RenderSVGShape::updateShapeFromElement();
+        return RenderSVGShape::shapeDependentStrokeContains(point);
+    }
+
+    float halfStrokeWidth = strokeWidth() / 2;
+    FloatPoint center = FloatPoint(m_center.x() - point.x(), m_center.y() - point.y());
+
+    // This works by checking if the point satisfies the ellipse equation,
+    // (x/rX)^2 + (y/rY)^2 <= 1, for the outer but not the inner stroke.
+    float xrXOuter = center.x() / (m_radii.width() + halfStrokeWidth);
+    float yrYOuter = center.y() / (m_radii.height() + halfStrokeWidth);
+    if (xrXOuter * xrXOuter + yrYOuter * yrYOuter > 1.0)
+        return false;
+
+    float xrXInner = center.x() / (m_radii.width() - halfStrokeWidth);
+    float yrYInner = center.y() / (m_radii.height() - halfStrokeWidth);
+    return xrXInner * xrXInner + yrYInner * yrYInner >= 1.0;
+}
+
+bool RenderSVGEllipse::shapeDependentFillContains(const FloatPoint& point, const WindRule fillRule) const
+{
+    if (m_usePathFallback)
+        return RenderSVGShape::shapeDependentFillContains(point, fillRule);
+
+    FloatPoint center = FloatPoint(m_center.x() - point.x(), m_center.y() - point.y());
+
+    // This works by checking if the point satisfies the ellipse equation.
+    // (x/rX)^2 + (y/rY)^2 <= 1
+    float xrX = center.x() / m_radii.width();
+    float yrY = center.y() / m_radii.height();
+    return xrX * xrX + yrY * yrY <= 1.0;
+}
+
+}
+
+#endif // ENABLE(SVG)
diff --git a/Source/core/rendering/svg/RenderSVGEllipse.h b/Source/core/rendering/svg/RenderSVGEllipse.h
new file mode 100644
index 0000000..ac9d488
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGEllipse.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2012 Google, 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 UNIVERSITY OF SZEGED ``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 UNIVERSITY OF SZEGED 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 RenderSVGEllipse_h
+#define RenderSVGEllipse_h
+
+#if ENABLE(SVG)
+#include "core/rendering/svg/RenderSVGShape.h"
+#include "core/svg/SVGStyledTransformableElement.h"
+
+namespace WebCore {
+
+class RenderSVGEllipse FINAL : public RenderSVGShape {
+public:
+    explicit RenderSVGEllipse(SVGStyledTransformableElement*);
+    virtual ~RenderSVGEllipse();
+
+private:
+    virtual const char* renderName() const { return "RenderSVGEllipse"; }
+
+    virtual void updateShapeFromElement();
+    virtual bool isEmpty() const { return m_usePathFallback ? RenderSVGShape::isEmpty() : m_fillBoundingBox.isEmpty(); };
+    virtual void fillShape(GraphicsContext*) const;
+    virtual void strokeShape(GraphicsContext*) const;
+    virtual bool shapeDependentStrokeContains(const FloatPoint&);
+    virtual bool shapeDependentFillContains(const FloatPoint&, const WindRule) const;
+    void calculateRadiiAndCenter();
+
+private:
+    FloatPoint m_center;
+    FloatSize m_radii;
+    bool m_usePathFallback;
+};
+
+}
+
+#endif // ENABLE(SVG)
+#endif
diff --git a/Source/core/rendering/svg/RenderSVGForeignObject.cpp b/Source/core/rendering/svg/RenderSVGForeignObject.cpp
new file mode 100644
index 0000000..ba0491c
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGForeignObject.cpp
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2009 Google, Inc.
+ * Copyright (C) Research In Motion Limited 2010. 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"
+
+#if ENABLE(SVG)
+#include "core/rendering/svg/RenderSVGForeignObject.h"
+
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/platform/graphics/transforms/TransformState.h"
+#include "core/rendering/HitTestResult.h"
+#include "core/rendering/LayoutRepainter.h"
+#include "core/rendering/RenderObject.h"
+#include "core/rendering/RenderView.h"
+#include "core/rendering/svg/RenderSVGResource.h"
+#include "core/rendering/svg/SVGRenderingContext.h"
+#include "core/rendering/svg/SVGResourcesCache.h"
+#include "core/svg/SVGForeignObjectElement.h"
+#include "core/svg/SVGSVGElement.h"
+
+namespace WebCore {
+
+RenderSVGForeignObject::RenderSVGForeignObject(SVGForeignObjectElement* node) 
+    : RenderSVGBlock(node)
+    , m_needsTransformUpdate(true)
+{
+}
+
+RenderSVGForeignObject::~RenderSVGForeignObject()
+{
+}
+
+void RenderSVGForeignObject::paint(PaintInfo& paintInfo, const LayoutPoint&)
+{
+    if (paintInfo.context->paintingDisabled()
+        || (paintInfo.phase != PaintPhaseForeground && paintInfo.phase != PaintPhaseSelection))
+        return;
+
+    PaintInfo childPaintInfo(paintInfo);
+    GraphicsContextStateSaver stateSaver(*childPaintInfo.context);
+    childPaintInfo.applyTransform(localTransform());
+
+    if (SVGRenderSupport::isOverflowHidden(this))
+        childPaintInfo.context->clip(m_viewport);
+
+    SVGRenderingContext renderingContext;
+    bool continueRendering = true;
+    if (paintInfo.phase == PaintPhaseForeground) {
+        renderingContext.prepareToRenderSVGContent(this, childPaintInfo);
+        continueRendering = renderingContext.isRenderingPrepared();
+    }
+
+    if (continueRendering) {
+        // Paint all phases of FO elements atomically, as though the FO element established its
+        // own stacking context.
+        bool preservePhase = paintInfo.phase == PaintPhaseSelection || paintInfo.phase == PaintPhaseTextClip;
+        LayoutPoint childPoint = IntPoint();
+        childPaintInfo.phase = preservePhase ? paintInfo.phase : PaintPhaseBlockBackground;
+        RenderBlock::paint(childPaintInfo, IntPoint());
+        if (!preservePhase) {
+            childPaintInfo.phase = PaintPhaseChildBlockBackgrounds;
+            RenderBlock::paint(childPaintInfo, childPoint);
+            childPaintInfo.phase = PaintPhaseFloat;
+            RenderBlock::paint(childPaintInfo, childPoint);
+            childPaintInfo.phase = PaintPhaseForeground;
+            RenderBlock::paint(childPaintInfo, childPoint);
+            childPaintInfo.phase = PaintPhaseOutline;
+            RenderBlock::paint(childPaintInfo, childPoint);
+        }
+    }
+}
+
+LayoutRect RenderSVGForeignObject::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const
+{
+    return SVGRenderSupport::clippedOverflowRectForRepaint(this, repaintContainer);
+}
+
+void RenderSVGForeignObject::computeFloatRectForRepaint(const RenderLayerModelObject* repaintContainer, FloatRect& repaintRect, bool fixed) const
+{
+    SVGRenderSupport::computeFloatRectForRepaint(this, repaintContainer, repaintRect, fixed);
+}
+
+const AffineTransform& RenderSVGForeignObject::localToParentTransform() const
+{
+    m_localToParentTransform = localTransform();
+    m_localToParentTransform.translate(m_viewport.x(), m_viewport.y());
+    return m_localToParentTransform;
+}
+
+void RenderSVGForeignObject::updateLogicalWidth()
+{
+    // FIXME: Investigate in size rounding issues
+    // FIXME: Remove unnecessary rounding when layout is off ints: webkit.org/b/63656
+    setWidth(static_cast<int>(roundf(m_viewport.width())));
+}
+
+void RenderSVGForeignObject::computeLogicalHeight(LayoutUnit, LayoutUnit logicalTop, LogicalExtentComputedValues& computedValues) const
+{
+    // FIXME: Investigate in size rounding issues
+    // FIXME: Remove unnecessary rounding when layout is off ints: webkit.org/b/63656
+    // FIXME: Is this correct for vertical writing mode?
+    computedValues.m_extent = static_cast<int>(roundf(m_viewport.height()));
+    computedValues.m_position = logicalTop;
+}
+
+void RenderSVGForeignObject::layout()
+{
+    StackStats::LayoutCheckPoint layoutCheckPoint;
+    ASSERT(needsLayout());
+    ASSERT(!view()->layoutStateEnabled()); // RenderSVGRoot disables layoutState for the SVG rendering tree.
+
+    LayoutRepainter repainter(*this, SVGRenderSupport::checkForSVGRepaintDuringLayout(this));
+    SVGForeignObjectElement* foreign = static_cast<SVGForeignObjectElement*>(node());
+
+    bool updateCachedBoundariesInParents = false;
+    if (m_needsTransformUpdate) {
+        m_localTransform = foreign->animatedLocalTransform();
+        m_needsTransformUpdate = false;
+        updateCachedBoundariesInParents = true;
+    }
+
+    FloatRect oldViewport = m_viewport;
+
+    // Cache viewport boundaries
+    SVGLengthContext lengthContext(foreign);
+    FloatPoint viewportLocation(foreign->x().value(lengthContext), foreign->y().value(lengthContext));
+    m_viewport = FloatRect(viewportLocation, FloatSize(foreign->width().value(lengthContext), foreign->height().value(lengthContext)));
+    if (!updateCachedBoundariesInParents)
+        updateCachedBoundariesInParents = oldViewport != m_viewport;
+
+    // Set box origin to the foreignObject x/y translation, so positioned objects in XHTML content get correct
+    // positions. A regular RenderBoxModelObject would pull this information from RenderStyle - in SVG those
+    // properties are ignored for non <svg> elements, so we mimic what happens when specifying them through CSS.
+
+    // FIXME: Investigate in location rounding issues - only affects RenderSVGForeignObject & RenderSVGText
+    setLocation(roundedIntPoint(viewportLocation));
+
+    bool layoutChanged = everHadLayout() && selfNeedsLayout();
+    RenderBlock::layout();
+    ASSERT(!needsLayout());
+
+    // If our bounds changed, notify the parents.
+    if (updateCachedBoundariesInParents)
+        RenderSVGBlock::setNeedsBoundariesUpdate();
+
+    // Invalidate all resources of this client if our layout changed.
+    if (layoutChanged)
+        SVGResourcesCache::clientLayoutChanged(this);
+
+    repainter.repaintAfterLayout();
+}
+
+bool RenderSVGForeignObject::nodeAtFloatPoint(const HitTestRequest& request, HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction)
+{
+    // Embedded content is drawn in the foreground phase.
+    if (hitTestAction != HitTestForeground)
+        return false;
+
+    FloatPoint localPoint = localTransform().inverse().mapPoint(pointInParent);
+
+    // Early exit if local point is not contained in clipped viewport area
+    if (SVGRenderSupport::isOverflowHidden(this) && !m_viewport.contains(localPoint))
+        return false;
+
+    // FOs establish a stacking context, so we need to hit-test all layers.
+    HitTestLocation hitTestLocation(roundedLayoutPoint(localPoint));
+    return RenderBlock::nodeAtPoint(request, result, hitTestLocation, LayoutPoint(), HitTestForeground)
+        || RenderBlock::nodeAtPoint(request, result, hitTestLocation, LayoutPoint(), HitTestFloat)
+        || RenderBlock::nodeAtPoint(request, result, hitTestLocation, LayoutPoint(), HitTestChildBlockBackgrounds);
+}
+
+bool RenderSVGForeignObject::nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation&, const LayoutPoint&, HitTestAction)
+{
+    ASSERT_NOT_REACHED();
+    return false;
+}
+
+void RenderSVGForeignObject::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags, bool* wasFixed) const
+{
+    SVGRenderSupport::mapLocalToContainer(this, repaintContainer, transformState, wasFixed);
+}
+
+const RenderObject* RenderSVGForeignObject::pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const
+{
+    return SVGRenderSupport::pushMappingToContainer(this, ancestorToStopAt, geometryMap);
+}
+
+}
+
+#endif
diff --git a/Source/core/rendering/svg/RenderSVGForeignObject.h b/Source/core/rendering/svg/RenderSVGForeignObject.h
new file mode 100644
index 0000000..0a67990
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGForeignObject.h
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2009 Google, 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 RenderSVGForeignObject_h
+#define RenderSVGForeignObject_h
+
+#if ENABLE(SVG)
+#include "core/platform/graphics/FloatPoint.h"
+#include "core/platform/graphics/FloatRect.h"
+#include "core/platform/graphics/transforms/AffineTransform.h"
+#include "core/rendering/svg/RenderSVGBlock.h"
+
+namespace WebCore {
+
+class SVGForeignObjectElement;
+
+class RenderSVGForeignObject FINAL : public RenderSVGBlock {
+public:
+    explicit RenderSVGForeignObject(SVGForeignObjectElement*);
+    virtual ~RenderSVGForeignObject();
+
+    virtual const char* renderName() const { return "RenderSVGForeignObject"; }
+
+    virtual void paint(PaintInfo&, const LayoutPoint&);
+
+    virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const OVERRIDE;
+    virtual void computeFloatRectForRepaint(const RenderLayerModelObject* repaintContainer, FloatRect&, bool fixed = false) const OVERRIDE;
+
+    virtual bool requiresLayer() const { return false; }
+    virtual void layout();
+
+    virtual FloatRect objectBoundingBox() const { return FloatRect(FloatPoint(), m_viewport.size()); }
+    virtual FloatRect strokeBoundingBox() const { return FloatRect(FloatPoint(), m_viewport.size()); }
+    virtual FloatRect repaintRectInLocalCoordinates() const { return FloatRect(FloatPoint(), m_viewport.size()); }
+
+    virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction);
+    virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
+    virtual bool isSVGForeignObject() const { return true; }
+
+    virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = 0) const OVERRIDE;
+    virtual const RenderObject* pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap&) const OVERRIDE;
+    virtual void setNeedsTransformUpdate() { m_needsTransformUpdate = true; }
+
+private:
+    virtual void updateLogicalWidth() OVERRIDE;
+    virtual void computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues&) const OVERRIDE;
+
+    virtual const AffineTransform& localToParentTransform() const;
+    virtual AffineTransform localTransform() const { return m_localTransform; }
+
+    bool m_needsTransformUpdate : 1;
+    FloatRect m_viewport;
+    AffineTransform m_localTransform;
+    mutable AffineTransform m_localToParentTransform;
+};
+
+}
+
+#endif
+#endif
diff --git a/Source/core/rendering/svg/RenderSVGGradientStop.cpp b/Source/core/rendering/svg/RenderSVGGradientStop.cpp
new file mode 100644
index 0000000..301a90c
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGGradientStop.cpp
@@ -0,0 +1,81 @@
+/*
+ * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, 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 "core/rendering/svg/RenderSVGGradientStop.h"
+
+#include "SVGNames.h"
+#include "core/rendering/svg/RenderSVGResourceContainer.h"
+#include "core/rendering/svg/SVGResourcesCache.h"
+#include "core/svg/SVGGradientElement.h"
+#include "core/svg/SVGStopElement.h"
+
+namespace WebCore {
+    
+using namespace SVGNames;
+
+RenderSVGGradientStop::RenderSVGGradientStop(SVGStopElement* element)
+    : RenderObject(element)
+{
+}
+
+RenderSVGGradientStop::~RenderSVGGradientStop()
+{
+}
+
+void RenderSVGGradientStop::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
+{
+    RenderObject::styleDidChange(diff, oldStyle);
+    if (diff == StyleDifferenceEqual)
+        return;
+
+    // <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.
+    SVGGradientElement* gradient = gradientElement();
+    if (!gradient)
+        return;
+
+    RenderObject* renderer = gradient->renderer();
+    if (!renderer)
+        return;
+
+    ASSERT(renderer->isSVGResourceContainer());
+    RenderSVGResourceContainer* container = renderer->toRenderSVGResourceContainer();
+    container->removeAllClientsFromCache();
+}
+
+void RenderSVGGradientStop::layout()
+{
+    StackStats::LayoutCheckPoint layoutCheckPoint;
+    setNeedsLayout(false);
+}
+
+SVGGradientElement* RenderSVGGradientStop::gradientElement() const
+{
+    ContainerNode* parentNode = node()->parentNode();
+    if (parentNode->hasTagName(linearGradientTag) || parentNode->hasTagName(radialGradientTag))
+        return static_cast<SVGGradientElement*>(parentNode);
+    return 0;
+}
+
+}
+
+#endif // ENABLE(SVG)
diff --git a/Source/core/rendering/svg/RenderSVGGradientStop.h b/Source/core/rendering/svg/RenderSVGGradientStop.h
new file mode 100644
index 0000000..89b7cea
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGGradientStop.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
+ * Copyright (C) 2009 Google, 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 RenderSVGGradientStop_h
+#define RenderSVGGradientStop_h
+
+#if ENABLE(SVG)
+#include "core/rendering/RenderObject.h"
+
+namespace WebCore {
+    
+class SVGGradientElement;
+class SVGStopElement;
+
+// This class exists mostly so we can hear about gradient stop style changes
+class RenderSVGGradientStop FINAL : public RenderObject {
+public:
+    RenderSVGGradientStop(SVGStopElement*);
+    virtual ~RenderSVGGradientStop();
+
+    virtual bool isSVGGradientStop() const { return true; }
+    virtual const char* renderName() const { return "RenderSVGGradientStop"; }
+
+    virtual void layout();
+
+    // This overrides are needed to prevent ASSERTs on <svg><stop /></svg>
+    // RenderObject's default implementations ASSERT_NOT_REACHED()
+    // https://bugs.webkit.org/show_bug.cgi?id=20400
+    virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject*) const OVERRIDE { return LayoutRect(); }
+    virtual FloatRect objectBoundingBox() const { return FloatRect(); }
+    virtual FloatRect strokeBoundingBox() const { return FloatRect(); }
+    virtual FloatRect repaintRectInLocalCoordinates() const { return FloatRect(); }
+
+protected:
+    virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+
+private:
+    SVGGradientElement* gradientElement() const;
+};
+
+inline const RenderSVGGradientStop* toRenderSVGGradientStop(const RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isSVGGradientStop());
+    return static_cast<const RenderSVGGradientStop*>(object);
+}
+
+}
+
+#endif // ENABLE(SVG)
+#endif // RenderSVGGradientStop_h
diff --git a/Source/core/rendering/svg/RenderSVGHiddenContainer.cpp b/Source/core/rendering/svg/RenderSVGHiddenContainer.cpp
new file mode 100644
index 0000000..5825a0a
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGHiddenContainer.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, 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 "core/rendering/svg/RenderSVGHiddenContainer.h"
+
+#include "core/rendering/svg/RenderSVGPath.h"
+#include "core/svg/SVGStyledElement.h"
+
+namespace WebCore {
+
+RenderSVGHiddenContainer::RenderSVGHiddenContainer(SVGStyledElement* element)
+    : RenderSVGContainer(element)
+{
+}
+
+void RenderSVGHiddenContainer::layout()
+{
+    StackStats::LayoutCheckPoint layoutCheckPoint;
+    ASSERT(needsLayout());
+    SVGRenderSupport::layoutChildren(this, selfNeedsLayout()); 
+    setNeedsLayout(false);    
+}
+
+void RenderSVGHiddenContainer::paint(PaintInfo&, const LayoutPoint&)
+{
+    // This subtree does not paint.
+}
+
+void RenderSVGHiddenContainer::absoluteQuads(Vector<FloatQuad>&, bool*) const
+{
+    // This subtree does not take up space or paint
+}
+
+bool RenderSVGHiddenContainer::nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint&, HitTestAction)
+{
+    return false;
+}
+
+}
+
+#endif // ENABLE(SVG)
diff --git a/Source/core/rendering/svg/RenderSVGHiddenContainer.h b/Source/core/rendering/svg/RenderSVGHiddenContainer.h
new file mode 100644
index 0000000..9df50ec
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGHiddenContainer.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, 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 "core/rendering/svg/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:
+    explicit RenderSVGHiddenContainer(SVGStyledElement*);
+
+    virtual const char* renderName() const { return "RenderSVGHiddenContainer"; }
+
+protected:
+    virtual void layout();
+
+private:
+    virtual bool isSVGHiddenContainer() const OVERRIDE FINAL { return true; }
+
+    virtual void paint(PaintInfo&, const LayoutPoint&) OVERRIDE FINAL;
+    
+    virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject*) const OVERRIDE FINAL { return LayoutRect(); }
+    virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const OVERRIDE FINAL;
+
+    virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction) OVERRIDE FINAL;
+};
+}
+
+#endif // ENABLE(SVG)
+#endif // RenderSVGHiddenContainer_h
diff --git a/Source/core/rendering/svg/RenderSVGImage.cpp b/Source/core/rendering/svg/RenderSVGImage.cpp
new file mode 100644
index 0000000..8ed9a1a
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGImage.cpp
@@ -0,0 +1,225 @@
+/*
+ * Copyright (C) 2006 Alexander Kellett <lypanov@kde.org>
+ * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) 2007, 2008, 2009 Rob Buis <buis@kde.org>
+ * Copyright (C) 2009 Google, Inc.
+ * Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
+ * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com>
+ *
+ * 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 "core/rendering/svg/RenderSVGImage.h"
+
+#include "core/dom/Attr.h"
+#include "core/platform/FloatConversion.h"
+#include "core/platform/graphics/FloatQuad.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/rendering/ImageQualityController.h"
+#include "core/rendering/LayoutRepainter.h"
+#include "core/rendering/PointerEventsHitRules.h"
+#include "core/rendering/RenderImageResource.h"
+#include "core/rendering/RenderLayer.h"
+#include "core/rendering/svg/RenderSVGResourceContainer.h"
+#include "core/rendering/svg/RenderSVGResourceFilter.h"
+#include "core/rendering/svg/SVGRenderingContext.h"
+#include "core/rendering/svg/SVGResources.h"
+#include "core/rendering/svg/SVGResourcesCache.h"
+#include "core/svg/SVGImageElement.h"
+#include "core/svg/SVGLength.h"
+#include "core/svg/SVGPreserveAspectRatio.h"
+
+namespace WebCore {
+
+RenderSVGImage::RenderSVGImage(SVGImageElement* impl)
+    : RenderSVGModelObject(impl)
+    , m_needsBoundariesUpdate(true)
+    , m_needsTransformUpdate(true)
+    , m_imageResource(RenderImageResource::create())
+{
+    m_imageResource->initialize(this);
+}
+
+RenderSVGImage::~RenderSVGImage()
+{
+    ImageQualityController::remove(this);
+    m_imageResource->shutdown();
+}
+
+bool RenderSVGImage::updateImageViewport()
+{
+    SVGImageElement* image = static_cast<SVGImageElement*>(node());
+    FloatRect oldBoundaries = m_objectBoundingBox;
+
+    SVGLengthContext lengthContext(image);
+    m_objectBoundingBox = FloatRect(image->x().value(lengthContext), image->y().value(lengthContext), image->width().value(lengthContext), image->height().value(lengthContext));
+
+    if (oldBoundaries == m_objectBoundingBox)
+        return false;
+
+    m_imageResource->setContainerSizeForRenderer(enclosingIntRect(m_objectBoundingBox).size());
+    m_needsBoundariesUpdate = true;
+    return true;
+}
+
+void RenderSVGImage::layout()
+{
+    StackStats::LayoutCheckPoint layoutCheckPoint;
+    ASSERT(needsLayout());
+
+    LayoutRepainter repainter(*this, SVGRenderSupport::checkForSVGRepaintDuringLayout(this) && selfNeedsLayout());
+    updateImageViewport();
+
+    bool transformOrBoundariesUpdate = m_needsTransformUpdate || m_needsBoundariesUpdate;
+    if (m_needsTransformUpdate) {
+        m_localTransform = static_cast<SVGImageElement*>(node())->animatedLocalTransform();
+        m_needsTransformUpdate = false;
+    }
+
+    if (m_needsBoundariesUpdate) {
+        m_repaintBoundingBoxExcludingShadow = m_objectBoundingBox;
+        SVGRenderSupport::intersectRepaintRectWithResources(this, m_repaintBoundingBoxExcludingShadow);
+
+        m_repaintBoundingBox = m_repaintBoundingBoxExcludingShadow;
+        SVGRenderSupport::intersectRepaintRectWithShadows(this, m_repaintBoundingBox);
+
+        m_needsBoundariesUpdate = false;
+    }
+
+    // Invalidate all resources of this client if our layout changed.
+    if (everHadLayout() && selfNeedsLayout())
+        SVGResourcesCache::clientLayoutChanged(this);
+
+    // If our bounds changed, notify the parents.
+    if (transformOrBoundariesUpdate)
+        RenderSVGModelObject::setNeedsBoundariesUpdate();
+
+    repainter.repaintAfterLayout();
+    setNeedsLayout(false);
+}
+
+void RenderSVGImage::paint(PaintInfo& paintInfo, const LayoutPoint&)
+{
+    if (paintInfo.context->paintingDisabled() || style()->visibility() == HIDDEN || !m_imageResource->hasImage())
+        return;
+
+    FloatRect boundingBox = repaintRectInLocalCoordinates();
+    if (!SVGRenderSupport::paintInfoIntersectsRepaintRect(boundingBox, m_localTransform, paintInfo))
+        return;
+
+    PaintInfo childPaintInfo(paintInfo);
+    bool drawsOutline = style()->outlineWidth() && (childPaintInfo.phase == PaintPhaseOutline || childPaintInfo.phase == PaintPhaseSelfOutline);
+    if (drawsOutline || childPaintInfo.phase == PaintPhaseForeground) {
+        GraphicsContextStateSaver stateSaver(*childPaintInfo.context);
+        childPaintInfo.applyTransform(m_localTransform);
+
+        if (childPaintInfo.phase == PaintPhaseForeground) {
+            SVGRenderingContext renderingContext(this, childPaintInfo);
+
+            if (renderingContext.isRenderingPrepared()) {
+                if (style()->svgStyle()->bufferedRendering() == BR_STATIC  && renderingContext.bufferForeground(m_bufferedForeground))
+                    return;
+
+                paintForeground(childPaintInfo);
+            }
+        }
+
+        if (drawsOutline)
+            paintOutline(childPaintInfo, IntRect(boundingBox));
+    }
+}
+
+void RenderSVGImage::paintForeground(PaintInfo& paintInfo)
+{
+    RefPtr<Image> image = m_imageResource->image();
+    FloatRect destRect = m_objectBoundingBox;
+    FloatRect srcRect(0, 0, image->width(), image->height());
+
+    SVGImageElement* imageElement = static_cast<SVGImageElement*>(node());
+    imageElement->preserveAspectRatio().transformRect(destRect, srcRect);
+
+    bool useLowQualityScaling = false;
+    if (style()->svgStyle()->bufferedRendering() != BR_STATIC)
+        useLowQualityScaling = ImageQualityController::imageQualityController()->shouldPaintAtLowQuality(paintInfo.context, this, image.get(), image.get(), LayoutSize(destRect.size()));
+
+    paintInfo.context->drawImage(image.get(), style()->colorSpace(), destRect, srcRect, CompositeSourceOver, DoNotRespectImageOrientation, useLowQualityScaling);
+}
+
+void RenderSVGImage::invalidateBufferedForeground()
+{
+    m_bufferedForeground.clear();
+}
+
+bool RenderSVGImage::nodeAtFloatPoint(const HitTestRequest& request, HitTestResult& result, const FloatPoint& pointInParent, 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, request, style()->pointerEvents());
+    bool isVisible = (style()->visibility() == VISIBLE);
+    if (isVisible || !hitRules.requireVisible) {
+        FloatPoint localPoint = localToParentTransform().inverse().mapPoint(pointInParent);
+            
+        if (!SVGRenderSupport::pointInClippingArea(this, localPoint))
+            return false;
+
+        if (hitRules.canHitFill) {
+            if (m_objectBoundingBox.contains(localPoint)) {
+                updateHitTestResult(result, roundedLayoutPoint(localPoint));
+                return true;
+            }
+        }
+    }
+
+    return false;
+}
+
+void RenderSVGImage::imageChanged(WrappedImagePtr, const IntRect*)
+{
+    // The image resource defaults to nullImage until the resource arrives.
+    // This empty image may be cached by SVG resources which must be invalidated.
+    if (SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(this))
+        resources->removeClientFromCache(this);
+
+    // Eventually notify parent resources, that we've changed.
+    RenderSVGResource::markForLayoutAndParentResourceInvalidation(this, false);
+
+    // Update the SVGImageCache sizeAndScales entry in case image loading finished after layout.
+    // (https://bugs.webkit.org/show_bug.cgi?id=99489)
+    m_objectBoundingBox = FloatRect();
+    updateImageViewport();
+
+    invalidateBufferedForeground();
+
+    repaint();
+}
+
+void RenderSVGImage::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint&, const RenderLayerModelObject*)
+{
+    // this is called from paint() after the localTransform has already been applied
+    IntRect contentRect = enclosingIntRect(repaintRectInLocalCoordinates());
+    if (!contentRect.isEmpty())
+        rects.append(contentRect);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
diff --git a/Source/core/rendering/svg/RenderSVGImage.h b/Source/core/rendering/svg/RenderSVGImage.h
new file mode 100644
index 0000000..dc20a25
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGImage.h
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2006 Alexander Kellett <lypanov@kde.org>
+ * Copyright (C) 2006, 2009 Apple Inc. All rights reserved.
+ * Copyright (C) 2007 Rob Buis <buis@kde.org>
+ * Copyright (C) 2009 Google, Inc.
+ * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com>
+ *
+ * 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 "core/platform/graphics/FloatRect.h"
+#include "core/platform/graphics/transforms/AffineTransform.h"
+#include "core/rendering/svg/RenderSVGModelObject.h"
+#include "core/rendering/svg/SVGRenderSupport.h"
+#include "core/svg/SVGPreserveAspectRatio.h"
+
+namespace WebCore {
+
+class RenderImageResource;
+class SVGImageElement;
+
+class RenderSVGImage FINAL : public RenderSVGModelObject {
+public:
+    RenderSVGImage(SVGImageElement*);
+    virtual ~RenderSVGImage();
+
+    bool updateImageViewport();
+    virtual void setNeedsBoundariesUpdate() { m_needsBoundariesUpdate = true; }
+    virtual bool needsBoundariesUpdate() OVERRIDE { return m_needsBoundariesUpdate; }
+    virtual void setNeedsTransformUpdate() { m_needsTransformUpdate = true; }
+
+    RenderImageResource* imageResource() { return m_imageResource.get(); }
+    const RenderImageResource* imageResource() const { return m_imageResource.get(); }
+
+    // Note: Assumes the PaintInfo context has had all local transforms applied.
+    void paintForeground(PaintInfo&);
+
+private:
+    virtual const char* renderName() const { return "RenderSVGImage"; }
+    virtual bool isSVGImage() const OVERRIDE { return true; }
+
+    virtual const AffineTransform& localToParentTransform() const { return m_localTransform; }
+
+    virtual FloatRect objectBoundingBox() const { return m_objectBoundingBox; }
+    virtual FloatRect strokeBoundingBox() const { return m_objectBoundingBox; }
+    virtual FloatRect repaintRectInLocalCoordinates() const { return m_repaintBoundingBox; }
+    virtual FloatRect repaintRectInLocalCoordinatesExcludingSVGShadow() const OVERRIDE { return m_repaintBoundingBoxExcludingShadow; }
+
+    virtual void addFocusRingRects(Vector<IntRect>&, const LayoutPoint& additionalOffset, const RenderLayerModelObject* paintContainer = 0) OVERRIDE;
+
+    virtual void imageChanged(WrappedImagePtr, const IntRect* = 0);
+
+    virtual void layout();
+    virtual void paint(PaintInfo&, const LayoutPoint&);
+
+    void invalidateBufferedForeground();
+
+    virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction);
+
+    virtual AffineTransform localTransform() const { return m_localTransform; }
+    void calculateImageViewport();
+
+    bool m_needsBoundariesUpdate : 1;
+    bool m_needsTransformUpdate : 1;
+    AffineTransform m_localTransform;
+    FloatRect m_objectBoundingBox;
+    FloatRect m_repaintBoundingBox;
+    FloatRect m_repaintBoundingBoxExcludingShadow;
+    OwnPtr<RenderImageResource> m_imageResource;
+
+    OwnPtr<ImageBuffer> m_bufferedForeground;
+};
+
+inline RenderSVGImage* toRenderSVGImage(RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isSVGImage());
+    return static_cast<RenderSVGImage*>(object);
+}
+
+inline const RenderSVGImage* toRenderSVGImage(const RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isSVGImage());
+    return static_cast<const RenderSVGImage*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderSVGImage(const RenderSVGImage*);
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
+#endif // RenderSVGImage_h
diff --git a/Source/core/rendering/svg/RenderSVGInline.cpp b/Source/core/rendering/svg/RenderSVGInline.cpp
new file mode 100644
index 0000000..f3fd428
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGInline.cpp
@@ -0,0 +1,148 @@
+/*
+ * Copyright (C) 2006 Oliver Hunt <ojh16@student.canterbury.ac.nz>
+ * Copyright (C) 2006 Apple Inc. All rights reserved.
+ * Copyright (C) Research In Motion Limited 2010. 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"
+
+#if ENABLE(SVG)
+#include "core/rendering/svg/RenderSVGInline.h"
+
+#include "core/rendering/svg/RenderSVGInlineText.h"
+#include "core/rendering/svg/RenderSVGResource.h"
+#include "core/rendering/svg/RenderSVGText.h"
+#include "core/rendering/svg/SVGInlineFlowBox.h"
+#include "core/rendering/svg/SVGResourcesCache.h"
+
+namespace WebCore {
+    
+RenderSVGInline::RenderSVGInline(Element* element)
+    : RenderInline(element)
+{
+    setAlwaysCreateLineBoxes();
+}
+
+InlineFlowBox* RenderSVGInline::createInlineFlowBox()
+{
+    InlineFlowBox* box = new (renderArena()) SVGInlineFlowBox(this);
+    box->setHasVirtualLogicalHeight();
+    return box;
+}
+
+FloatRect RenderSVGInline::objectBoundingBox() const
+{
+    if (const RenderObject* object = RenderSVGText::locateRenderSVGTextAncestor(this))
+        return object->objectBoundingBox();
+
+    return FloatRect();
+}
+
+FloatRect RenderSVGInline::strokeBoundingBox() const
+{
+    if (const RenderObject* object = RenderSVGText::locateRenderSVGTextAncestor(this))
+        return object->strokeBoundingBox();
+
+    return FloatRect();
+}
+
+FloatRect RenderSVGInline::repaintRectInLocalCoordinates() const
+{
+    if (const RenderObject* object = RenderSVGText::locateRenderSVGTextAncestor(this))
+        return object->repaintRectInLocalCoordinates();
+
+    return FloatRect();
+}
+
+LayoutRect RenderSVGInline::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const
+{
+    return SVGRenderSupport::clippedOverflowRectForRepaint(this, repaintContainer);
+}
+
+void RenderSVGInline::computeFloatRectForRepaint(const RenderLayerModelObject* repaintContainer, FloatRect& repaintRect, bool fixed) const
+{
+    SVGRenderSupport::computeFloatRectForRepaint(this, repaintContainer, repaintRect, fixed);
+}
+
+void RenderSVGInline::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags, bool* wasFixed) const
+{
+    SVGRenderSupport::mapLocalToContainer(this, repaintContainer, transformState, wasFixed);
+}
+
+const RenderObject* RenderSVGInline::pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const
+{
+    return SVGRenderSupport::pushMappingToContainer(this, ancestorToStopAt, geometryMap);
+}
+
+void RenderSVGInline::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed) const
+{
+    const RenderObject* object = RenderSVGText::locateRenderSVGTextAncestor(this);
+    if (!object)
+        return;
+
+    FloatRect textBoundingBox = object->strokeBoundingBox();
+    for (InlineFlowBox* box = firstLineBox(); box; box = box->nextLineBox())
+        quads.append(localToAbsoluteQuad(FloatRect(textBoundingBox.x() + box->x(), textBoundingBox.y() + box->y(), box->logicalWidth(), box->logicalHeight()), false, wasFixed));
+}
+
+void RenderSVGInline::willBeDestroyed()
+{
+    SVGResourcesCache::clientDestroyed(this);
+    RenderInline::willBeDestroyed();
+}
+
+void RenderSVGInline::styleWillChange(StyleDifference diff, const RenderStyle* newStyle)
+{
+    if (diff == StyleDifferenceLayout)
+        setNeedsBoundariesUpdate();
+    RenderInline::styleWillChange(diff, newStyle);
+}
+
+void RenderSVGInline::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
+{
+    RenderInline::styleDidChange(diff, oldStyle);
+    SVGResourcesCache::clientStyleChanged(this, diff, style());
+}
+
+void RenderSVGInline::addChild(RenderObject* child, RenderObject* beforeChild)
+{
+    RenderInline::addChild(child, beforeChild);
+    SVGResourcesCache::clientWasAddedToTree(child, child->style());
+
+    if (RenderSVGText* textRenderer = RenderSVGText::locateRenderSVGTextAncestor(this))
+        textRenderer->subtreeChildWasAdded(child);
+}
+
+void RenderSVGInline::removeChild(RenderObject* child)
+{
+    SVGResourcesCache::clientWillBeRemovedFromTree(child);
+
+    RenderSVGText* textRenderer = RenderSVGText::locateRenderSVGTextAncestor(this);
+    if (!textRenderer) {
+        RenderInline::removeChild(child);
+        return;
+    }
+    Vector<SVGTextLayoutAttributes*, 2> affectedAttributes;
+    textRenderer->subtreeChildWillBeRemoved(child, affectedAttributes);
+    RenderInline::removeChild(child);
+    textRenderer->subtreeChildWasRemoved(affectedAttributes);
+}
+
+}
+
+#endif // ENABLE(SVG)
diff --git a/Source/core/rendering/svg/RenderSVGInline.h b/Source/core/rendering/svg/RenderSVGInline.h
new file mode 100644
index 0000000..872752d
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGInline.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2006 Oliver Hunt <ojh16@student.canterbury.ac.nz>
+ * 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 RenderSVGInline_h
+#define RenderSVGInline_h
+
+#if ENABLE(SVG)
+#include "core/rendering/RenderInline.h"
+
+#include "core/rendering/svg/SVGRenderSupport.h"
+
+namespace WebCore {
+
+class RenderSVGInline : public RenderInline {
+public:
+    explicit RenderSVGInline(Element*);
+
+    virtual const char* renderName() const { return "RenderSVGInline"; }
+    virtual bool requiresLayer() const OVERRIDE FINAL { return false; }
+    virtual bool isSVGInline() const OVERRIDE FINAL { return true; }
+
+    // Chapter 10.4 of the SVG Specification say that we should use the
+    // object bounding box of the parent text element.
+    // We search for the root text element and take its bounding box.
+    // It is also necessary to take the stroke and repaint rect of
+    // this element, since we need it for filters.
+    virtual FloatRect objectBoundingBox() const OVERRIDE FINAL;
+    virtual FloatRect strokeBoundingBox() const OVERRIDE FINAL;
+    virtual FloatRect repaintRectInLocalCoordinates() const OVERRIDE FINAL;
+
+    virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const OVERRIDE FINAL;
+    virtual void computeFloatRectForRepaint(const RenderLayerModelObject* repaintContainer, FloatRect&, bool fixed = false) const OVERRIDE FINAL;
+    virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = 0) const OVERRIDE FINAL;
+    virtual const RenderObject* pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap&) const OVERRIDE FINAL;
+    virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const OVERRIDE FINAL;
+
+private:
+    virtual InlineFlowBox* createInlineFlowBox() OVERRIDE FINAL;
+
+    virtual void willBeDestroyed() OVERRIDE FINAL;
+    virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle) OVERRIDE FINAL;
+    virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE FINAL;
+
+    virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0) OVERRIDE FINAL;
+    virtual void removeChild(RenderObject*) OVERRIDE FINAL;
+};
+
+}
+
+#endif // ENABLE(SVG)
+#endif // !RenderSVGTSpan_H
diff --git a/Source/core/rendering/svg/RenderSVGInlineText.cpp b/Source/core/rendering/svg/RenderSVGInlineText.cpp
new file mode 100644
index 0000000..1595312
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGInlineText.cpp
@@ -0,0 +1,253 @@
+/*
+ * Copyright (C) 2006 Oliver Hunt <ojh16@student.canterbury.ac.nz>
+ * Copyright (C) 2006 Apple Computer Inc.
+ * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) 2008 Rob Buis <buis@kde.org>
+ * Copyright (C) Research In Motion Limited 2010. 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"
+
+#if ENABLE(SVG)
+#include "core/rendering/svg/RenderSVGInlineText.h"
+
+#include "core/css/CSSFontSelector.h"
+#include "core/css/StyleResolver.h"
+#include "core/editing/VisiblePosition.h"
+#include "core/page/Settings.h"
+#include "core/platform/FloatConversion.h"
+#include "core/platform/graphics/FloatQuad.h"
+#include "core/rendering/RenderBlock.h"
+#include "core/rendering/svg/RenderSVGRoot.h"
+#include "core/rendering/svg/RenderSVGText.h"
+#include "core/rendering/svg/SVGInlineTextBox.h"
+#include "core/rendering/svg/SVGRenderingContext.h"
+#include "core/rendering/svg/SVGRootInlineBox.h"
+
+namespace WebCore {
+
+static PassRefPtr<StringImpl> applySVGWhitespaceRules(PassRefPtr<StringImpl> string, bool preserveWhiteSpace)
+{
+    if (preserveWhiteSpace) {
+        // 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.
+        RefPtr<StringImpl> newString = string->replace('\t', ' ');
+        newString = newString->replace('\n', ' ');
+        newString = newString->replace('\r', ' ');
+        return newString.release();
+    }
+
+    // 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.
+    RefPtr<StringImpl> newString = string->replace('\n', StringImpl::empty());
+    newString = newString->replace('\r', StringImpl::empty());
+    newString = newString->replace('\t', ' ');
+    return newString.release();
+}
+
+RenderSVGInlineText::RenderSVGInlineText(Node* n, PassRefPtr<StringImpl> string)
+    : RenderText(n, applySVGWhitespaceRules(string, false))
+    , m_scalingFactor(1)
+    , m_layoutAttributes(this)
+{
+}
+
+void RenderSVGInlineText::setTextInternal(PassRefPtr<StringImpl> text)
+{
+    RenderText::setTextInternal(text);
+    if (RenderSVGText* textRenderer = RenderSVGText::locateRenderSVGTextAncestor(this))
+        textRenderer->subtreeTextDidChange(this);
+}
+
+void RenderSVGInlineText::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
+{
+    RenderText::styleDidChange(diff, oldStyle);
+    updateScaledFont();
+
+    bool newPreserves = style() ? style()->whiteSpace() == PRE : false;
+    bool oldPreserves = oldStyle ? oldStyle->whiteSpace() == PRE : false;
+    if (oldPreserves && !newPreserves) {
+        setText(applySVGWhitespaceRules(originalText(), false), true);
+        return;
+    }
+
+    if (!oldPreserves && newPreserves) {
+        setText(applySVGWhitespaceRules(originalText(), true), true);
+        return;
+    }
+
+    if (diff != StyleDifferenceLayout)
+        return;
+
+    // The text metrics may be influenced by style changes.
+    if (RenderSVGText* textRenderer = RenderSVGText::locateRenderSVGTextAncestor(this))
+        textRenderer->subtreeStyleDidChange(this);
+}
+
+InlineTextBox* RenderSVGInlineText::createTextBox()
+{
+    InlineTextBox* box = new (renderArena()) SVGInlineTextBox(this);
+    box->setHasVirtualLogicalHeight();
+    return box;
+}
+
+LayoutRect RenderSVGInlineText::localCaretRect(InlineBox* box, int caretOffset, LayoutUnit*)
+{
+    if (!box || !box->isInlineTextBox())
+        return LayoutRect();
+
+    InlineTextBox* textBox = static_cast<InlineTextBox*>(box);
+    if (static_cast<unsigned>(caretOffset) < textBox->start() || static_cast<unsigned>(caretOffset) > textBox->start() + textBox->len())
+        return LayoutRect();
+
+    // Use the edge of the selection rect to determine the caret rect.
+    if (static_cast<unsigned>(caretOffset) < textBox->start() + textBox->len()) {
+        LayoutRect rect = textBox->localSelectionRect(caretOffset, caretOffset + 1);
+        LayoutUnit x = box->isLeftToRightDirection() ? rect.x() : rect.maxX();
+        return LayoutRect(x, rect.y(), caretWidth, rect.height());
+    }
+
+    LayoutRect rect = textBox->localSelectionRect(caretOffset - 1, caretOffset);
+    LayoutUnit x = box->isLeftToRightDirection() ? rect.maxX() : rect.x();
+    return LayoutRect(x, rect.y(), caretWidth, rect.height());
+}
+
+FloatRect RenderSVGInlineText::floatLinesBoundingBox() const
+{
+    FloatRect boundingBox;
+    for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox())
+        boundingBox.unite(box->calculateBoundaries());
+    return boundingBox;
+}
+
+IntRect RenderSVGInlineText::linesBoundingBox() const
+{
+    return enclosingIntRect(floatLinesBoundingBox());
+}
+
+bool RenderSVGInlineText::characterStartsNewTextChunk(int position) const
+{
+    ASSERT(position >= 0);
+    ASSERT(position < static_cast<int>(textLength()));
+
+    // Each <textPath> element starts a new text chunk, regardless of any x/y values.
+    if (!position && parent()->isSVGTextPath() && !previousSibling())
+        return true;
+
+    const SVGCharacterDataMap::const_iterator it = m_layoutAttributes.characterDataMap().find(static_cast<unsigned>(position + 1));
+    if (it == m_layoutAttributes.characterDataMap().end())
+        return false;
+
+    return it->value.x != SVGTextLayoutAttributes::emptyValue() || it->value.y != SVGTextLayoutAttributes::emptyValue();
+}
+
+VisiblePosition RenderSVGInlineText::positionForPoint(const LayoutPoint& point)
+{
+    if (!firstTextBox() || !textLength())
+        return createVisiblePosition(0, DOWNSTREAM);
+
+    float baseline = m_scaledFont.fontMetrics().floatAscent();
+
+    RenderBlock* containingBlock = this->containingBlock();
+    ASSERT(containingBlock);
+
+    // Map local point to absolute point, as the character origins stored in the text fragments use absolute coordinates.
+    FloatPoint absolutePoint(point);
+    absolutePoint.moveBy(containingBlock->location());
+
+    float closestDistance = std::numeric_limits<float>::max();
+    float closestDistancePosition = 0;
+    const SVGTextFragment* closestDistanceFragment = 0;
+    SVGInlineTextBox* closestDistanceBox = 0;
+
+    AffineTransform fragmentTransform;
+    for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) {
+        if (!box->isSVGInlineTextBox())
+            continue;
+
+        SVGInlineTextBox* textBox = static_cast<SVGInlineTextBox*>(box);
+        Vector<SVGTextFragment>& fragments = textBox->textFragments();
+
+        unsigned textFragmentsSize = fragments.size();
+        for (unsigned i = 0; i < textFragmentsSize; ++i) {
+            const SVGTextFragment& fragment = fragments.at(i);
+            FloatRect fragmentRect(fragment.x, fragment.y - baseline, fragment.width, fragment.height);
+            fragment.buildFragmentTransform(fragmentTransform);
+            if (!fragmentTransform.isIdentity())
+                fragmentRect = fragmentTransform.mapRect(fragmentRect);
+
+            float distance = powf(fragmentRect.x() - absolutePoint.x(), 2) +
+                             powf(fragmentRect.y() + fragmentRect.height() / 2 - absolutePoint.y(), 2);
+
+            if (distance < closestDistance) {
+                closestDistance = distance;
+                closestDistanceBox = textBox;
+                closestDistanceFragment = &fragment;
+                closestDistancePosition = fragmentRect.x();
+            }
+        }
+    }
+
+    if (!closestDistanceFragment)
+        return createVisiblePosition(0, DOWNSTREAM);
+
+    int offset = closestDistanceBox->offsetForPositionInFragment(*closestDistanceFragment, absolutePoint.x() - closestDistancePosition, true);
+    return createVisiblePosition(offset + closestDistanceBox->start(), offset > 0 ? VP_UPSTREAM_IF_POSSIBLE : DOWNSTREAM);
+}
+
+void RenderSVGInlineText::updateScaledFont()
+{
+    computeNewScaledFontForStyle(this, style(), m_scalingFactor, m_scaledFont);
+}
+
+void RenderSVGInlineText::computeNewScaledFontForStyle(RenderObject* renderer, const RenderStyle* style, float& scalingFactor, Font& scaledFont)
+{
+    ASSERT(style);
+    ASSERT(renderer);
+
+    Document* document = renderer->document();
+    ASSERT(document);
+    
+    StyleResolver* styleResolver = document->styleResolver();
+    ASSERT(styleResolver);
+
+    // Alter font-size to the right on-screen value to avoid scaling the glyphs themselves, except when GeometricPrecision is specified
+    scalingFactor = SVGRenderingContext::calculateScreenFontSizeScalingFactor(renderer);
+    if (scalingFactor == 1 || !scalingFactor || style->fontDescription().textRenderingMode() == GeometricPrecision) {
+        scalingFactor = 1;
+        scaledFont = style->font();
+        return;
+    }
+
+    FontDescription fontDescription(style->fontDescription());
+
+    // FIXME: We need to better handle the case when we compute very small fonts below (below 1pt).
+    fontDescription.setComputedSize(StyleResolver::getComputedSizeFromSpecifiedSize(document, scalingFactor, fontDescription.isAbsoluteSize(), fontDescription.computedSize(), DoNotUseSmartMinimumForFontSize));
+
+    scaledFont = Font(fontDescription, 0, 0);
+    scaledFont.update(styleResolver->fontSelector());
+}
+
+}
+
+#endif // ENABLE(SVG)
diff --git a/Source/core/rendering/svg/RenderSVGInlineText.h b/Source/core/rendering/svg/RenderSVGInlineText.h
new file mode 100644
index 0000000..a09e488
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGInlineText.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2006 Oliver Hunt <ojh16@student.canterbury.ac.nz>
+ * Copyright (C) 2006, 2008 Apple Inc. All rights reserved.
+ * Copyright (C) 2008 Rob Buis <buis@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, 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 "core/platform/graphics/Font.h"
+#include "core/rendering/RenderText.h"
+#include "core/rendering/svg/SVGTextLayoutAttributes.h"
+
+namespace WebCore {
+
+class SVGInlineTextBox;
+
+class RenderSVGInlineText FINAL : public RenderText {
+public:
+    RenderSVGInlineText(Node*, PassRefPtr<StringImpl>);
+
+    bool characterStartsNewTextChunk(int position) const;
+    SVGTextLayoutAttributes* layoutAttributes() { return &m_layoutAttributes; }
+
+    float scalingFactor() const { return m_scalingFactor; }
+    const Font& scaledFont() const { return m_scaledFont; }
+    void updateScaledFont();
+    static void computeNewScaledFontForStyle(RenderObject*, const RenderStyle*, float& scalingFactor, Font& scaledFont);
+
+    // Preserves floating point precision for the use in DRT. It knows how to round and does a better job than enclosingIntRect.
+    FloatRect floatLinesBoundingBox() const;
+
+private:
+    virtual const char* renderName() const { return "RenderSVGInlineText"; }
+
+    virtual void setTextInternal(PassRefPtr<StringImpl>);
+    virtual void styleDidChange(StyleDifference, const RenderStyle*);
+
+    virtual FloatRect objectBoundingBox() const { return floatLinesBoundingBox(); }
+
+    virtual bool requiresLayer() const { return false; }
+    virtual bool isSVGInlineText() const { return true; }
+
+    virtual VisiblePosition positionForPoint(const LayoutPoint&);
+    virtual LayoutRect localCaretRect(InlineBox*, int caretOffset, LayoutUnit* extraWidthToEndOfLine = 0);
+    virtual IntRect linesBoundingBox() const;
+    virtual InlineTextBox* createTextBox();
+
+    float m_scalingFactor;
+    Font m_scaledFont;
+    SVGTextLayoutAttributes m_layoutAttributes;
+};
+
+inline RenderSVGInlineText* toRenderSVGInlineText(RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isSVGInlineText());
+    return static_cast<RenderSVGInlineText*>(object);
+}
+
+inline const RenderSVGInlineText* toRenderSVGInlineText(const RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isSVGInlineText());
+    return static_cast<const RenderSVGInlineText*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderSVGInlineText(const RenderSVGInlineText*);
+
+}
+
+#endif // ENABLE(SVG)
+#endif // RenderSVGInlineText_h
diff --git a/Source/core/rendering/svg/RenderSVGModelObject.cpp b/Source/core/rendering/svg/RenderSVGModelObject.cpp
new file mode 100644
index 0000000..dad95e0
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGModelObject.cpp
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2009, Google 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:
+ * 
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+ * OWNER 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 "core/rendering/svg/RenderSVGModelObject.h"
+
+#include "SVGNames.h"
+#include "core/rendering/RenderLayerModelObject.h"
+#include "core/rendering/svg/RenderSVGResource.h"
+#include "core/rendering/svg/SVGResourcesCache.h"
+#include "core/svg/SVGStyledElement.h"
+
+namespace WebCore {
+
+RenderSVGModelObject::RenderSVGModelObject(SVGStyledElement* node)
+    : RenderObject(node)
+    , m_hasSVGShadow(false)
+{
+}
+
+LayoutRect RenderSVGModelObject::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const
+{
+    return SVGRenderSupport::clippedOverflowRectForRepaint(this, repaintContainer);
+}
+
+void RenderSVGModelObject::computeFloatRectForRepaint(const RenderLayerModelObject* repaintContainer, FloatRect& repaintRect, bool fixed) const
+{
+    SVGRenderSupport::computeFloatRectForRepaint(this, repaintContainer, repaintRect, fixed);
+}
+
+void RenderSVGModelObject::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags, bool* wasFixed) const
+{
+    SVGRenderSupport::mapLocalToContainer(this, repaintContainer, transformState, wasFixed);
+}
+
+const RenderObject* RenderSVGModelObject::pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const
+{
+    return SVGRenderSupport::pushMappingToContainer(this, ancestorToStopAt, geometryMap);
+}
+
+// Copied from RenderBox, this method likely requires further refactoring to work easily for both SVG and CSS Box Model content.
+// FIXME: This may also need to move into SVGRenderSupport as the RenderBox version depends
+// on borderBoundingBox() which SVG RenderBox subclases (like SVGRenderBlock) do not implement.
+LayoutRect RenderSVGModelObject::outlineBoundsForRepaint(const RenderLayerModelObject* repaintContainer, const RenderGeometryMap*) const
+{
+    LayoutRect box = enclosingLayoutRect(repaintRectInLocalCoordinates());
+    adjustRectForOutlineAndShadow(box);
+
+    FloatQuad containerRelativeQuad = localToContainerQuad(FloatRect(box), repaintContainer);
+    return containerRelativeQuad.enclosingBoundingBox();
+}
+
+void RenderSVGModelObject::absoluteRects(Vector<IntRect>& rects, const LayoutPoint& accumulatedOffset) const
+{
+    IntRect rect = enclosingIntRect(strokeBoundingBox());
+    rect.moveBy(roundedIntPoint(accumulatedOffset));
+    rects.append(rect);
+}
+
+void RenderSVGModelObject::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed) const
+{
+    quads.append(localToAbsoluteQuad(strokeBoundingBox(), 0 /* mode */, wasFixed));
+}
+
+void RenderSVGModelObject::willBeDestroyed()
+{
+    SVGResourcesCache::clientDestroyed(this);
+    RenderObject::willBeDestroyed();
+}
+
+void RenderSVGModelObject::styleWillChange(StyleDifference diff, const RenderStyle* newStyle)
+{
+    if (diff == StyleDifferenceLayout) {
+        setNeedsBoundariesUpdate();
+        if (newStyle->hasTransform())
+            setNeedsTransformUpdate();
+    }
+    RenderObject::styleWillChange(diff, newStyle);
+}
+
+void RenderSVGModelObject::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
+{
+    RenderObject::styleDidChange(diff, oldStyle);
+    SVGResourcesCache::clientStyleChanged(this, diff, style());
+}
+
+bool RenderSVGModelObject::nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation&, const LayoutPoint&, HitTestAction)
+{
+    ASSERT_NOT_REACHED();
+    return false;
+}
+
+static void getElementCTM(SVGElement* element, AffineTransform& transform)
+{
+    ASSERT(element);
+    element->document()->updateLayoutIgnorePendingStylesheets();
+
+    SVGElement* stopAtElement = SVGLocatable::nearestViewportElement(element);
+    ASSERT(stopAtElement);
+
+    AffineTransform localTransform;
+    Node* current = element;
+
+    while (current && current->isSVGElement()) {
+        SVGElement* currentElement = toSVGElement(current);
+        if (currentElement->isSVGStyledElement()) {
+            localTransform = currentElement->renderer()->localToParentTransform();
+            transform = localTransform.multiply(transform);
+        }
+        // For getCTM() computation, stop at the nearest viewport element
+        if (currentElement == stopAtElement)
+            break;
+
+        current = current->parentOrShadowHostNode();
+    }
+}
+
+// FloatRect::intersects does not consider horizontal or vertical lines (because of isEmpty()).
+// So special-case handling of such lines.
+static bool intersectsAllowingEmpty(const FloatRect& r, const FloatRect& other)
+{
+    if (r.isEmpty() && other.isEmpty())
+        return false;
+    if (r.isEmpty() && !other.isEmpty()) {
+        return (other.contains(r.x(), r.y()) && !other.contains(r.maxX(), r.maxY()))
+               || (!other.contains(r.x(), r.y()) && other.contains(r.maxX(), r.maxY()));
+    }
+    if (other.isEmpty() && !r.isEmpty())
+        return intersectsAllowingEmpty(other, r);
+    return r.intersects(other);
+}
+
+// One of the element types that can cause graphics to be drawn onto the target canvas. Specifically: circle, ellipse,
+// image, line, path, polygon, polyline, rect, text and use.
+static bool isGraphicsElement(RenderObject* renderer)
+{
+    return renderer->isSVGShape() || renderer->isSVGText() || renderer->isSVGImage() || renderer->node()->hasTagName(SVGNames::useTag);
+}
+
+// The SVG addFocusRingRects() method adds rects in local coordinates so the default absoluteFocusRingQuads
+// returns incorrect values for SVG objects. Overriding this method provides access to the absolute bounds.
+void RenderSVGModelObject::absoluteFocusRingQuads(Vector<FloatQuad>& quads)
+{
+    quads.append(localToAbsoluteQuad(FloatQuad(repaintRectInLocalCoordinates())));
+}
+    
+bool RenderSVGModelObject::checkIntersection(RenderObject* renderer, const FloatRect& rect)
+{
+    if (!renderer || renderer->style()->pointerEvents() == PE_NONE)
+        return false;
+    if (!isGraphicsElement(renderer))
+        return false;
+    AffineTransform ctm;
+    SVGElement* svgElement = toSVGElement(renderer->node());
+    getElementCTM(svgElement, ctm);
+    ASSERT(svgElement->renderer());
+    return intersectsAllowingEmpty(rect, ctm.mapRect(svgElement->renderer()->repaintRectInLocalCoordinates()));
+}
+
+bool RenderSVGModelObject::checkEnclosure(RenderObject* renderer, const FloatRect& rect)
+{
+    if (!renderer || renderer->style()->pointerEvents() == PE_NONE)
+        return false;
+    if (!isGraphicsElement(renderer))
+        return false;
+    AffineTransform ctm;
+    SVGElement* svgElement = toSVGElement(renderer->node());
+    getElementCTM(svgElement, ctm);
+    ASSERT(svgElement->renderer());
+    return rect.contains(ctm.mapRect(svgElement->renderer()->repaintRectInLocalCoordinates()));
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
diff --git a/Source/core/rendering/svg/RenderSVGModelObject.h b/Source/core/rendering/svg/RenderSVGModelObject.h
new file mode 100644
index 0000000..70796cc
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGModelObject.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2009, Google 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:
+ * 
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * 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.
+ *     * Neither the name of Google Inc. 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 THE COPYRIGHT HOLDERS AND 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 THE COPYRIGHT
+ * OWNER 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 RenderSVGModelObject_h
+#define RenderSVGModelObject_h
+
+#if ENABLE(SVG)
+
+#include "core/rendering/RenderObject.h"
+#include "core/rendering/svg/SVGRenderSupport.h"
+
+namespace WebCore {
+
+// Most renderers in the SVG rendering tree will inherit from this class
+// but not all. (e.g. RenderSVGForeignObject, RenderSVGBlock) thus methods
+// required by SVG renders need to be declared on RenderObject, but shared
+// logic can go in this class or in SVGRenderSupport.
+
+class SVGStyledElement;
+
+class RenderSVGModelObject : public RenderObject {
+public:
+    explicit RenderSVGModelObject(SVGStyledElement*);
+
+    virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const OVERRIDE;
+    virtual void computeFloatRectForRepaint(const RenderLayerModelObject* repaintContainer, FloatRect&, bool fixed = false) const OVERRIDE FINAL;
+    virtual LayoutRect outlineBoundsForRepaint(const RenderLayerModelObject* repaintContainer, const RenderGeometryMap*) const OVERRIDE FINAL;
+
+    virtual void absoluteRects(Vector<IntRect>&, const LayoutPoint& accumulatedOffset) const OVERRIDE FINAL;
+    virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const;
+
+    virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = 0) const OVERRIDE FINAL;
+    virtual const RenderObject* pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap&) const OVERRIDE FINAL;
+    virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle) OVERRIDE FINAL;
+    virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+
+    static bool checkIntersection(RenderObject*, const FloatRect&);
+    static bool checkEnclosure(RenderObject*, const FloatRect&);
+
+    virtual FloatRect repaintRectInLocalCoordinatesExcludingSVGShadow() const { return repaintRectInLocalCoordinates(); }
+    bool hasSVGShadow() const { return m_hasSVGShadow; }
+    void setHasSVGShadow(bool hasShadow) { m_hasSVGShadow = hasShadow; }
+
+protected:
+    virtual void willBeDestroyed();
+
+private:
+    // This method should never be called, SVG uses a different nodeAtPoint method
+    bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
+    virtual void absoluteFocusRingQuads(Vector<FloatQuad>&) OVERRIDE FINAL;
+    bool m_hasSVGShadow;
+};
+
+}
+
+#endif // ENABLE(SVG)
+#endif
diff --git a/Source/core/rendering/svg/RenderSVGPath.cpp b/Source/core/rendering/svg/RenderSVGPath.cpp
new file mode 100644
index 0000000..ea5a53a
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGPath.cpp
@@ -0,0 +1,167 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) 2004, 2005, 2008 Rob Buis <buis@kde.org>
+ * Copyright (C) 2005, 2007 Eric Seidel <eric@webkit.org>
+ * Copyright (C) 2009 Google, Inc.
+ * Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
+ * Copyright (C) Research In Motion Limited 2010. All rights reserved.
+ * Copyright (C) 2009 Jeff Schiller <codedread@gmail.com>
+ * Copyright (C) 2011 Renata Hodovan <reni@webkit.org>
+ * Copyright (C) 2011 University of Szeged
+ *
+ * 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 "core/rendering/svg/RenderSVGPath.h"
+
+#include "core/rendering/svg/SVGSubpathData.h"
+#include "core/svg/SVGPathElement.h"
+#include "core/svg/SVGStyledTransformableElement.h"
+
+namespace WebCore {
+
+RenderSVGPath::RenderSVGPath(SVGStyledTransformableElement* node)
+    : RenderSVGShape(node)
+{
+}
+
+RenderSVGPath::~RenderSVGPath()
+{
+}
+
+void RenderSVGPath::updateShapeFromElement()
+{
+    RenderSVGShape::updateShapeFromElement();
+    updateZeroLengthSubpaths();
+
+    m_strokeBoundingBox = calculateUpdatedStrokeBoundingBox();
+}
+
+FloatRect RenderSVGPath::calculateUpdatedStrokeBoundingBox() const
+{
+    FloatRect strokeBoundingBox = m_strokeBoundingBox;
+
+    if (style()->svgStyle()->hasStroke()) {
+        // FIXME: zero-length subpaths do not respect vector-effect = non-scaling-stroke.
+        float strokeWidth = this->strokeWidth();
+        for (size_t i = 0; i < m_zeroLengthLinecapLocations.size(); ++i)
+            strokeBoundingBox.unite(zeroLengthSubpathRect(m_zeroLengthLinecapLocations[i], strokeWidth));
+    }
+
+    return strokeBoundingBox;
+}
+
+static void useStrokeStyleToFill(GraphicsContext* context)
+{
+    if (Gradient* gradient = context->strokeGradient())
+        context->setFillGradient(gradient);
+    else if (Pattern* pattern = context->strokePattern())
+        context->setFillPattern(pattern);
+    else
+        context->setFillColor(context->strokeColor(), context->strokeColorSpace());
+}
+
+void RenderSVGPath::strokeShape(GraphicsContext* context) const
+{
+    if (!style()->svgStyle()->hasVisibleStroke())
+        return;
+
+    RenderSVGShape::strokeShape(context);
+
+    if (m_zeroLengthLinecapLocations.isEmpty())
+        return;
+
+    Path* usePath;
+    AffineTransform nonScalingTransform;
+
+    if (hasNonScalingStroke())
+        nonScalingTransform = nonScalingStrokeTransform();
+
+    GraphicsContextStateSaver stateSaver(*context, true);
+    useStrokeStyleToFill(context);
+    for (size_t i = 0; i < m_zeroLengthLinecapLocations.size(); ++i) {
+        usePath = zeroLengthLinecapPath(m_zeroLengthLinecapLocations[i]);
+        if (hasNonScalingStroke())
+            usePath = nonScalingStrokePath(usePath, nonScalingTransform);
+        context->fillPath(*usePath);
+    }
+}
+
+bool RenderSVGPath::shapeDependentStrokeContains(const FloatPoint& point)
+{
+    if (RenderSVGShape::shapeDependentStrokeContains(point))
+        return true;
+
+    const SVGRenderStyle* svgStyle = style()->svgStyle();
+    for (size_t i = 0; i < m_zeroLengthLinecapLocations.size(); ++i) {
+        ASSERT(svgStyle->hasStroke());
+        float strokeWidth = this->strokeWidth();
+        if (svgStyle->capStyle() == SquareCap) {
+            if (zeroLengthSubpathRect(m_zeroLengthLinecapLocations[i], strokeWidth).contains(point))
+                return true;
+        } else {
+            ASSERT(svgStyle->capStyle() == RoundCap);
+            FloatPoint radiusVector(point.x() - m_zeroLengthLinecapLocations[i].x(), point.y() -  m_zeroLengthLinecapLocations[i].y());
+            if (radiusVector.lengthSquared() < strokeWidth * strokeWidth * .25f)
+                return true;
+        }
+    }
+    return false;
+}
+
+bool RenderSVGPath::shouldStrokeZeroLengthSubpath() const
+{
+    // Spec(11.4): Any zero length subpath shall not be stroked if the "stroke-linecap" property has a value of butt
+    // but shall be stroked if the "stroke-linecap" property has a value of round or square
+    return style()->svgStyle()->hasStroke() && style()->svgStyle()->capStyle() != ButtCap;
+}
+
+Path* RenderSVGPath::zeroLengthLinecapPath(const FloatPoint& linecapPosition) const
+{
+    DEFINE_STATIC_LOCAL(Path, tempPath, ());
+
+    tempPath.clear();
+    if (style()->svgStyle()->capStyle() == SquareCap)
+        tempPath.addRect(zeroLengthSubpathRect(linecapPosition, this->strokeWidth()));
+    else
+        tempPath.addEllipse(zeroLengthSubpathRect(linecapPosition, this->strokeWidth()));
+
+    return &tempPath;
+}
+
+FloatRect RenderSVGPath::zeroLengthSubpathRect(const FloatPoint& linecapPosition, float strokeWidth) const
+{
+    return FloatRect(linecapPosition.x() - strokeWidth / 2, linecapPosition.y() - strokeWidth / 2, strokeWidth, strokeWidth);
+}
+
+void RenderSVGPath::updateZeroLengthSubpaths()
+{
+    m_zeroLengthLinecapLocations.clear();
+
+    if (!strokeWidth() || !shouldStrokeZeroLengthSubpath())
+        return;
+
+    SVGSubpathData subpathData(m_zeroLengthLinecapLocations);
+    path().apply(&subpathData, SVGSubpathData::updateFromPathElement);
+    subpathData.pathIsDone();
+}
+
+}
+
+#endif // ENABLE(SVG)
diff --git a/Source/core/rendering/svg/RenderSVGPath.h b/Source/core/rendering/svg/RenderSVGPath.h
new file mode 100644
index 0000000..68409ee
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGPath.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org>
+ * Copyright (C) 2005 Eric Seidel <eric@webkit.org>
+ * Copyright (C) 2006 Apple Computer, Inc
+ * Copyright (C) 2009 Google, Inc.
+ * Copyright (C) 2011 Renata Hodovan <reni@webkit.org>
+ * Copyright (C) 2011 University of Szeged
+ *
+ * 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 RenderSVGPath_h
+#define RenderSVGPath_h
+
+#if ENABLE(SVG)
+#include "core/rendering/svg/RenderSVGShape.h"
+
+namespace WebCore {
+
+class RenderSVGPath FINAL : public RenderSVGShape {
+public:
+    explicit RenderSVGPath(SVGStyledTransformableElement*);
+    virtual ~RenderSVGPath();
+
+private:
+    virtual bool isSVGPath() const OVERRIDE { return true; }
+    virtual const char* renderName() const { return "RenderSVGPath"; }
+
+    virtual void updateShapeFromElement() OVERRIDE;
+    FloatRect calculateUpdatedStrokeBoundingBox() const;
+
+    virtual void strokeShape(GraphicsContext*) const OVERRIDE;
+    virtual bool shapeDependentStrokeContains(const FloatPoint&) OVERRIDE;
+
+    bool shouldStrokeZeroLengthSubpath() const;
+    Path* zeroLengthLinecapPath(const FloatPoint&) const;
+    FloatRect zeroLengthSubpathRect(const FloatPoint&, float) const;
+    void updateZeroLengthSubpaths();
+
+    Vector<FloatPoint> m_zeroLengthLinecapLocations;
+};
+
+inline RenderSVGPath* toRenderSVGPath(RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isSVGPath());
+    return static_cast<RenderSVGPath*>(object);
+}
+
+}
+
+#endif // ENABLE(SVG)
+#endif
diff --git a/Source/core/rendering/svg/RenderSVGRect.cpp b/Source/core/rendering/svg/RenderSVGRect.cpp
new file mode 100644
index 0000000..fe68525
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGRect.cpp
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2011 University of Szeged
+ * Copyright (C) 2011 Renata Hodovan <reni@webkit.org>
+ * 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 UNIVERSITY OF SZEGED ``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 UNIVERSITY OF SZEGED 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 "core/rendering/svg/RenderSVGRect.h"
+
+#include "SVGNames.h"
+#include "core/svg/SVGRectElement.h"
+
+namespace WebCore {
+
+RenderSVGRect::RenderSVGRect(SVGRectElement* node)
+    : RenderSVGShape(node)
+    , m_usePathFallback(false)
+{
+}
+
+RenderSVGRect::~RenderSVGRect()
+{
+}
+
+void RenderSVGRect::updateShapeFromElement()
+{
+    // Before creating a new object we need to clear the cached bounding box
+    // to avoid using garbage.
+    m_fillBoundingBox = FloatRect();
+    m_innerStrokeRect = FloatRect();
+    m_outerStrokeRect = FloatRect();
+    SVGRectElement* rect = static_cast<SVGRectElement*>(node());
+    ASSERT(rect);
+
+    // Fallback to RenderSVGShape if rect has rounded corners or a non-scaling stroke.
+    if (rect->hasAttribute(SVGNames::rxAttr) || rect->hasAttribute(SVGNames::ryAttr) || hasNonScalingStroke()) {
+        RenderSVGShape::updateShapeFromElement();
+        m_usePathFallback = true;
+        return;
+    } else
+        m_usePathFallback = false;
+
+    SVGLengthContext lengthContext(rect);
+    FloatSize boundingBoxSize(rect->width().value(lengthContext), rect->height().value(lengthContext));
+    if (boundingBoxSize.isEmpty())
+        return;
+
+    m_fillBoundingBox = FloatRect(FloatPoint(rect->x().value(lengthContext), rect->y().value(lengthContext)), boundingBoxSize);
+
+    // To decide if the stroke contains a point we create two rects which represent the inner and
+    // the outer stroke borders. A stroke contains the point, if the point is between them.
+    m_innerStrokeRect = m_fillBoundingBox;
+    m_outerStrokeRect = m_fillBoundingBox;
+
+    if (style()->svgStyle()->hasStroke()) {
+        float strokeWidth = this->strokeWidth();
+        m_innerStrokeRect.inflate(-strokeWidth / 2);
+        m_outerStrokeRect.inflate(strokeWidth / 2);
+    }
+
+    m_strokeBoundingBox = m_outerStrokeRect;
+}
+
+void RenderSVGRect::fillShape(GraphicsContext* context) const
+{
+    if (m_usePathFallback) {
+        RenderSVGShape::fillShape(context);
+        return;
+    }
+
+    context->fillRect(m_fillBoundingBox);
+}
+
+void RenderSVGRect::strokeShape(GraphicsContext* context) const
+{
+    if (!style()->svgStyle()->hasVisibleStroke())
+        return;
+
+    if (m_usePathFallback) {
+        RenderSVGShape::strokeShape(context);
+        return;
+    }
+
+    context->strokeRect(m_fillBoundingBox, strokeWidth());
+}
+
+bool RenderSVGRect::shapeDependentStrokeContains(const FloatPoint& point)
+{
+    // The optimized contains code below does not support non-smooth strokes so we need
+    // to fall back to RenderSVGShape::shapeDependentStrokeContains in these cases.
+    if (m_usePathFallback || !hasSmoothStroke()) {
+        if (!hasPath())
+            RenderSVGShape::updateShapeFromElement();
+        return RenderSVGShape::shapeDependentStrokeContains(point);
+    }
+
+    return m_outerStrokeRect.contains(point, FloatRect::InsideOrOnStroke) && !m_innerStrokeRect.contains(point, FloatRect::InsideButNotOnStroke);
+}
+
+bool RenderSVGRect::shapeDependentFillContains(const FloatPoint& point, const WindRule fillRule) const
+{
+    if (m_usePathFallback)
+        return RenderSVGShape::shapeDependentFillContains(point, fillRule);
+    return m_fillBoundingBox.contains(point.x(), point.y());
+}
+
+}
+
+#endif // ENABLE(SVG)
diff --git a/Source/core/rendering/svg/RenderSVGRect.h b/Source/core/rendering/svg/RenderSVGRect.h
new file mode 100644
index 0000000..a73ced1
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGRect.h
@@ -0,0 +1,61 @@
+/*
+ * Copyright (C) 2011 University of Szeged
+ * Copyright (C) 2011 Renata Hodovan <reni@webkit.org>
+ * 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 UNIVERSITY OF SZEGED ``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 UNIVERSITY OF SZEGED 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 RenderSVGRect_h
+#define RenderSVGRect_h
+
+#if ENABLE(SVG)
+#include "core/rendering/svg/RenderSVGPath.h"
+#include "core/svg/SVGRectElement.h"
+
+namespace WebCore {
+
+class RenderSVGRect FINAL : public RenderSVGShape {
+public:
+    explicit RenderSVGRect(SVGRectElement*);
+    virtual ~RenderSVGRect();
+
+private:
+    virtual const char* renderName() const { return "RenderSVGRect"; }
+
+    virtual void updateShapeFromElement();
+    virtual bool isEmpty() const { return m_usePathFallback ? RenderSVGShape::isEmpty() : m_fillBoundingBox.isEmpty(); };
+    virtual void fillShape(GraphicsContext*) const;
+    virtual void strokeShape(GraphicsContext*) const;
+    virtual bool shapeDependentStrokeContains(const FloatPoint&);
+    virtual bool shapeDependentFillContains(const FloatPoint&, const WindRule) const;
+
+private:
+    FloatRect m_innerStrokeRect;
+    FloatRect m_outerStrokeRect;
+    bool m_usePathFallback;
+};
+
+}
+
+#endif // ENABLE(SVG)
+#endif
diff --git a/Source/core/rendering/svg/RenderSVGResource.cpp b/Source/core/rendering/svg/RenderSVGResource.cpp
new file mode 100644
index 0000000..a5c2105
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGResource.cpp
@@ -0,0 +1,221 @@
+/*
+ * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) 2007 Rob Buis <buis@kde.org>
+ * Copyright (C) 2008 Dirk Schulze <krit@webkit.org>
+ * Copyright (C) Research In Motion Limited 2010. 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"
+
+#if ENABLE(SVG)
+#include "core/rendering/svg/RenderSVGResource.h"
+
+#include "core/page/Frame.h"
+#include "core/page/FrameView.h"
+#include "core/rendering/svg/RenderSVGResourceClipper.h"
+#include "core/rendering/svg/RenderSVGResourceContainer.h"
+#include "core/rendering/svg/RenderSVGResourceFilter.h"
+#include "core/rendering/svg/RenderSVGResourceMasker.h"
+#include "core/rendering/svg/RenderSVGResourceSolidColor.h"
+#include "core/rendering/svg/SVGResources.h"
+#include "core/rendering/svg/SVGResourcesCache.h"
+#include "core/svg/SVGURIReference.h"
+
+namespace WebCore {
+
+static inline bool inheritColorFromParentStyleIfNeeded(RenderObject* object, bool applyToFill, Color& color)
+{
+    if (color.isValid())
+        return true;
+    if (!object->parent() || !object->parent()->style())
+        return false;
+    const SVGRenderStyle* parentSVGStyle = object->parent()->style()->svgStyle();
+    color = applyToFill ? parentSVGStyle->fillPaintColor() : parentSVGStyle->strokePaintColor();
+    return true;
+}
+
+static inline RenderSVGResource* requestPaintingResource(RenderSVGResourceMode mode, RenderObject* object, const RenderStyle* style, Color& fallbackColor)
+{
+    ASSERT(object);
+    ASSERT(style);
+
+    // If we have no style at all, ignore it.
+    const SVGRenderStyle* svgStyle = style->svgStyle();
+    if (!svgStyle)
+        return 0;
+
+    bool isRenderingMask = false;
+    if (object->frame() && object->frame()->view())
+        isRenderingMask = object->frame()->view()->paintBehavior() & PaintBehaviorRenderingSVGMask;
+
+    // If we have no fill/stroke, return 0.
+    if (mode == ApplyToFillMode) {
+        // When rendering the mask for a RenderSVGResourceClipper, always use the initial fill paint server, and ignore stroke.
+        if (isRenderingMask) {
+            RenderSVGResourceSolidColor* colorResource = RenderSVGResource::sharedSolidPaintingResource();
+            colorResource->setColor(SVGRenderStyle::initialFillPaintColor());
+            return colorResource;
+        }
+
+        if (!svgStyle->hasFill())
+            return 0;
+    } else {
+        if (!svgStyle->hasStroke() || isRenderingMask)
+            return 0;
+    }
+
+    bool applyToFill = mode == ApplyToFillMode;
+    SVGPaint::SVGPaintType paintType = applyToFill ? svgStyle->fillPaintType() : svgStyle->strokePaintType();
+    if (paintType == SVGPaint::SVG_PAINTTYPE_NONE)
+        return 0;
+
+    Color color;
+    switch (paintType) {
+    case SVGPaint::SVG_PAINTTYPE_CURRENTCOLOR:
+    case SVGPaint::SVG_PAINTTYPE_RGBCOLOR:
+    case SVGPaint::SVG_PAINTTYPE_RGBCOLOR_ICCCOLOR:
+    case SVGPaint::SVG_PAINTTYPE_URI_CURRENTCOLOR:
+    case SVGPaint::SVG_PAINTTYPE_URI_RGBCOLOR:
+    case SVGPaint::SVG_PAINTTYPE_URI_RGBCOLOR_ICCCOLOR:
+        color = applyToFill ? svgStyle->fillPaintColor() : svgStyle->strokePaintColor();
+    default:
+        break;
+    }
+
+    if (style->insideLink() == InsideVisitedLink) {
+        // FIXME: This code doesn't support the uri component of the visited link paint, https://bugs.webkit.org/show_bug.cgi?id=70006
+        SVGPaint::SVGPaintType visitedPaintType = applyToFill ? svgStyle->visitedLinkFillPaintType() : svgStyle->visitedLinkStrokePaintType();
+
+        // For SVG_PAINTTYPE_CURRENTCOLOR, 'color' already contains the 'visitedColor'.
+        if (visitedPaintType < SVGPaint::SVG_PAINTTYPE_URI_NONE && visitedPaintType != SVGPaint::SVG_PAINTTYPE_CURRENTCOLOR) {
+            const Color& visitedColor = applyToFill ? svgStyle->visitedLinkFillPaintColor() : svgStyle->visitedLinkStrokePaintColor();
+            if (visitedColor.isValid())
+                color = Color(visitedColor.red(), visitedColor.green(), visitedColor.blue(), color.alpha());
+        }
+    }
+
+    // If the primary resource is just a color, return immediately.
+    RenderSVGResourceSolidColor* colorResource = RenderSVGResource::sharedSolidPaintingResource();
+    if (paintType < SVGPaint::SVG_PAINTTYPE_URI_NONE) {
+        if (!inheritColorFromParentStyleIfNeeded(object, applyToFill, color))
+            return 0;
+
+        colorResource->setColor(color);
+        return colorResource;
+    }
+
+    // If no resources are associated with the given renderer, return the color resource.
+    SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(object);
+    if (!resources) {
+        if (paintType == SVGPaint::SVG_PAINTTYPE_URI_NONE || !inheritColorFromParentStyleIfNeeded(object, applyToFill, color))
+            return 0;
+
+        colorResource->setColor(color);
+        return colorResource;
+    }
+
+    // If the requested resource is not available, return the color resource.
+    RenderSVGResource* uriResource = mode == ApplyToFillMode ? resources->fill() : resources->stroke();
+    if (!uriResource) {
+        if (!inheritColorFromParentStyleIfNeeded(object, applyToFill, color))
+            return 0;
+
+        colorResource->setColor(color);
+        return colorResource;
+    }
+
+    // The paint server resource exists, though it may be invalid (pattern with width/height=0). Pass the fallback color to our caller
+    // so it can use the solid color painting resource, if applyResource() on the URI resource failed.
+    fallbackColor = color;
+    return uriResource;
+}
+
+RenderSVGResource* RenderSVGResource::fillPaintingResource(RenderObject* object, const RenderStyle* style, Color& fallbackColor)
+{
+    return requestPaintingResource(ApplyToFillMode, object, style, fallbackColor);
+}
+
+RenderSVGResource* RenderSVGResource::strokePaintingResource(RenderObject* object, const RenderStyle* style, Color& fallbackColor)
+{
+    return requestPaintingResource(ApplyToStrokeMode, object, style, fallbackColor);
+}
+
+RenderSVGResourceSolidColor* RenderSVGResource::sharedSolidPaintingResource()
+{
+    static RenderSVGResourceSolidColor* s_sharedSolidPaintingResource = 0;
+    if (!s_sharedSolidPaintingResource)
+        s_sharedSolidPaintingResource = new RenderSVGResourceSolidColor;
+    return s_sharedSolidPaintingResource;
+}
+
+static inline void removeFromCacheAndInvalidateDependencies(RenderObject* object, bool needsLayout)
+{
+    ASSERT(object);
+    if (SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(object)) {
+        if (RenderSVGResourceFilter* filter = resources->filter())
+            filter->removeClientFromCache(object);
+
+        if (RenderSVGResourceMasker* masker = resources->masker())
+            masker->removeClientFromCache(object);
+
+        if (RenderSVGResourceClipper* clipper = resources->clipper())
+            clipper->removeClientFromCache(object);
+    }
+
+    if (!object->node() || !object->node()->isSVGElement())
+        return;
+    HashSet<SVGElement*>* dependencies = object->document()->accessSVGExtensions()->setOfElementsReferencingTarget(toSVGElement(object->node()));
+    if (!dependencies)
+        return;
+    HashSet<SVGElement*>::iterator end = dependencies->end();
+    for (HashSet<SVGElement*>::iterator it = dependencies->begin(); it != end; ++it) {
+        if (RenderObject* renderer = (*it)->renderer())
+            RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer, needsLayout);
+    }
+}
+
+void RenderSVGResource::markForLayoutAndParentResourceInvalidation(RenderObject* object, bool needsLayout)
+{
+    ASSERT(object);
+    ASSERT(object->document());
+    ASSERT(object->node());
+
+    if (needsLayout)
+        object->setNeedsLayout(true);
+
+    removeFromCacheAndInvalidateDependencies(object, needsLayout);
+
+    // Invalidate resources in ancestor chain, if needed.
+    RenderObject* current = object->parent();
+    while (current) {
+        removeFromCacheAndInvalidateDependencies(current, needsLayout);
+
+        if (current->isSVGResourceContainer()) {
+            // This will process the rest of the ancestors.
+            current->toRenderSVGResourceContainer()->removeAllClientsFromCache();
+            break;
+        }
+
+        current = current->parent();
+    }
+}
+
+}
+
+#endif
+
diff --git a/Source/core/rendering/svg/RenderSVGResource.h b/Source/core/rendering/svg/RenderSVGResource.h
new file mode 100644
index 0000000..d18a909
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGResource.h
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) Research In Motion Limited 2009-2010. 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 RenderSVGResource_h
+#define RenderSVGResource_h
+
+#if ENABLE(SVG)
+#include "core/rendering/style/RenderStyleConstants.h"
+#include "core/rendering/svg/RenderSVGShape.h"
+#include "core/svg/SVGDocumentExtensions.h"
+
+namespace WebCore {
+
+enum RenderSVGResourceType {
+    MaskerResourceType,
+    MarkerResourceType,
+    PatternResourceType,
+    LinearGradientResourceType,
+    RadialGradientResourceType,
+    SolidColorResourceType,
+    FilterResourceType,
+    ClipperResourceType
+};
+
+// If this enum changes change the unsigned bitfields using it.
+enum RenderSVGResourceMode {
+    ApplyToDefaultMode = 1 << 0, // used for all resources except gradient/pattern
+    ApplyToFillMode    = 1 << 1,
+    ApplyToStrokeMode  = 1 << 2,
+    ApplyToTextMode    = 1 << 3 // used in combination with ApplyTo{Fill|Stroke}Mode
+};
+
+class Color;
+class FloatRect;
+class GraphicsContext;
+class Path;
+class RenderObject;
+class RenderStyle;
+class RenderSVGResourceSolidColor;
+
+class RenderSVGResource {
+public:
+    RenderSVGResource() { }
+    virtual ~RenderSVGResource() { }
+
+    virtual void removeAllClientsFromCache(bool markForInvalidation = true) = 0;
+    virtual void removeClientFromCache(RenderObject*, bool markForInvalidation = true) = 0;
+
+    virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode) = 0;
+    virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short, const Path*, const RenderSVGShape*) { }
+    virtual FloatRect resourceBoundingBox(RenderObject*) = 0;
+
+    virtual RenderSVGResourceType resourceType() const = 0;
+
+    template<class Renderer>
+    Renderer* cast()
+    {
+        if (Renderer::s_resourceType == resourceType())
+            return static_cast<Renderer*>(this);
+
+        return 0;
+    }
+
+    // Helper utilities used in the render tree to access resources used for painting shapes/text (gradients & patterns & solid colors only)
+    static RenderSVGResource* fillPaintingResource(RenderObject*, const RenderStyle*, Color& fallbackColor);
+    static RenderSVGResource* strokePaintingResource(RenderObject*, const RenderStyle*, Color& fallbackColor);
+    static RenderSVGResourceSolidColor* sharedSolidPaintingResource();
+
+    static void markForLayoutAndParentResourceInvalidation(RenderObject*, bool needsLayout = true);
+};
+
+}
+
+#endif
+#endif
diff --git a/Source/core/rendering/svg/RenderSVGResourceClipper.cpp b/Source/core/rendering/svg/RenderSVGResourceClipper.cpp
new file mode 100644
index 0000000..2ff2310
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGResourceClipper.cpp
@@ -0,0 +1,344 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Rob Buis <buis@kde.org>
+ * Copyright (C) Research In Motion Limited 2009-2010. All rights reserved.
+ * Copyright (C) 2011 Dirk Schulze <krit@webkit.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, 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 "core/rendering/svg/RenderSVGResourceClipper.h"
+
+#include "SVGNames.h"
+#include "core/page/Frame.h"
+#include "core/page/FrameView.h"
+#include "core/platform/graphics/FloatRect.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/platform/graphics/ImageBuffer.h"
+#include "core/platform/graphics/IntRect.h"
+#include "core/platform/graphics/transforms/AffineTransform.h"
+#include "core/rendering/HitTestRequest.h"
+#include "core/rendering/HitTestResult.h"
+#include "core/rendering/RenderObject.h"
+#include "core/rendering/style/RenderStyle.h"
+#include "core/rendering/svg/RenderSVGResource.h"
+#include "core/rendering/svg/SVGRenderSupport.h"
+#include "core/rendering/svg/SVGRenderingContext.h"
+#include "core/rendering/svg/SVGResources.h"
+#include "core/rendering/svg/SVGResourcesCache.h"
+#include "core/svg/SVGClipPathElement.h"
+#include "core/svg/SVGElement.h"
+#include "core/svg/SVGStyledElement.h"
+#include "core/svg/SVGStyledTransformableElement.h"
+#include "core/svg/SVGUnitTypes.h"
+#include "core/svg/SVGUseElement.h"
+#include <wtf/UnusedParam.h>
+
+namespace WebCore {
+
+RenderSVGResourceType RenderSVGResourceClipper::s_resourceType = ClipperResourceType;
+
+RenderSVGResourceClipper::RenderSVGResourceClipper(SVGClipPathElement* node)
+    : RenderSVGResourceContainer(node)
+{
+}
+
+RenderSVGResourceClipper::~RenderSVGResourceClipper()
+{
+    if (m_clipper.isEmpty())
+        return;
+
+    deleteAllValues(m_clipper);
+    m_clipper.clear();
+}
+
+void RenderSVGResourceClipper::removeAllClientsFromCache(bool markForInvalidation)
+{
+    m_clipBoundaries = FloatRect();
+    if (!m_clipper.isEmpty()) {
+        deleteAllValues(m_clipper);
+        m_clipper.clear();
+    }
+
+    markAllClientsForInvalidation(markForInvalidation ? LayoutAndBoundariesInvalidation : ParentOnlyInvalidation);
+}
+
+void RenderSVGResourceClipper::removeClientFromCache(RenderObject* client, bool markForInvalidation)
+{
+    ASSERT(client);
+    if (m_clipper.contains(client))
+        delete m_clipper.take(client);
+
+    markClientForInvalidation(client, markForInvalidation ? BoundariesInvalidation : ParentOnlyInvalidation);
+}
+
+bool RenderSVGResourceClipper::applyResource(RenderObject* object, RenderStyle*, GraphicsContext*& context, unsigned short resourceMode)
+{
+    ASSERT(object);
+    ASSERT(context);
+    ASSERT_UNUSED(resourceMode, resourceMode == ApplyToDefaultMode);
+
+    return applyClippingToContext(object, object->objectBoundingBox(), object->repaintRectInLocalCoordinates(), context);
+}
+
+bool RenderSVGResourceClipper::pathOnlyClipping(GraphicsContext* context, const AffineTransform& animatedLocalTransform, const FloatRect& objectBoundingBox)
+{
+    // If the current clip-path gets clipped itself, we have to fallback to masking.
+    if (!style()->svgStyle()->clipperResource().isEmpty())
+        return false;
+    WindRule clipRule = RULE_NONZERO;
+    Path clipPath = Path();
+
+    // If clip-path only contains one visible shape or path, we can use path-based clipping. Invisible
+    // shapes don't affect the clipping and can be ignored. If clip-path contains more than one
+    // visible shape, the additive clipping may not work, caused by the clipRule. EvenOdd
+    // as well as NonZero can cause self-clipping of the elements.
+    // See also http://www.w3.org/TR/SVG/painting.html#FillRuleProperty
+    for (Node* childNode = node()->firstChild(); childNode; childNode = childNode->nextSibling()) {
+        RenderObject* renderer = childNode->renderer();
+        if (!renderer)
+            continue;
+        // Only shapes or paths are supported for direct clipping. We need to fallback to masking for texts.
+        if (renderer->isSVGText())
+            return false;
+        if (!childNode->isSVGElement() || !toSVGElement(childNode)->isStyledTransformable())
+            continue;
+        SVGStyledTransformableElement* styled = toSVGStyledTransformableElement(childNode);
+        RenderStyle* style = renderer->style();
+        if (!style || style->display() == NONE || style->visibility() != VISIBLE)
+             continue;
+        const SVGRenderStyle* svgStyle = style->svgStyle();
+        // Current shape in clip-path gets clipped too. Fallback to masking.
+        if (!svgStyle->clipperResource().isEmpty())
+            return false;
+        // Fallback to masking, if there is more than one clipping path.
+        if (clipPath.isEmpty()) {
+            styled->toClipPath(clipPath);
+            clipRule = svgStyle->clipRule();
+        } else
+            return false;
+    }
+    // Only one visible shape/path was found. Directly continue clipping and transform the content to userspace if necessary.
+    if (static_cast<SVGClipPathElement*>(node())->clipPathUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
+        AffineTransform transform;
+        transform.translate(objectBoundingBox.x(), objectBoundingBox.y());
+        transform.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.height());
+        clipPath.transform(transform);
+    }
+
+    // Transform path by animatedLocalTransform.
+    clipPath.transform(animatedLocalTransform);
+
+    // The SVG specification wants us to clip everything, if clip-path doesn't have a child.
+    if (clipPath.isEmpty())
+        clipPath.addRect(FloatRect());
+    context->clipPath(clipPath, clipRule);
+    return true;
+}
+
+bool RenderSVGResourceClipper::applyClippingToContext(RenderObject* object, const FloatRect& objectBoundingBox,
+                                                      const FloatRect& repaintRect, GraphicsContext* context)
+{
+    bool missingClipperData = !m_clipper.contains(object);
+    if (missingClipperData)
+        m_clipper.set(object, new ClipperData);
+
+    bool shouldCreateClipData = false;
+    AffineTransform animatedLocalTransform = static_cast<SVGClipPathElement*>(node())->animatedLocalTransform();
+    ClipperData* clipperData = m_clipper.get(object);
+    if (!clipperData->clipMaskImage) {
+        if (pathOnlyClipping(context, animatedLocalTransform, objectBoundingBox))
+            return true;
+        shouldCreateClipData = true;
+    }
+
+    AffineTransform absoluteTransform;
+    SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(object, absoluteTransform);
+
+    if (shouldCreateClipData && !repaintRect.isEmpty()) {
+        if (!SVGRenderingContext::createImageBuffer(repaintRect, absoluteTransform, clipperData->clipMaskImage, ColorSpaceDeviceRGB, Unaccelerated))
+            return false;
+
+        GraphicsContext* maskContext = clipperData->clipMaskImage->context();
+        ASSERT(maskContext);
+
+        maskContext->concatCTM(animatedLocalTransform);
+
+        // clipPath can also be clipped by another clipPath.
+        SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(this);
+        RenderSVGResourceClipper* clipper;
+        bool succeeded;
+        if (resources && (clipper = resources->clipper())) {
+            GraphicsContextStateSaver stateSaver(*maskContext);
+
+            if (!clipper->applyClippingToContext(this, objectBoundingBox, repaintRect, maskContext))
+                return false;
+
+            succeeded = drawContentIntoMaskImage(clipperData, objectBoundingBox);
+            // The context restore applies the clipping on non-CG platforms.
+        } else
+            succeeded = drawContentIntoMaskImage(clipperData, objectBoundingBox);
+
+        if (!succeeded)
+            clipperData->clipMaskImage.clear();
+    }
+
+    if (!clipperData->clipMaskImage)
+        return false;
+
+    SVGRenderingContext::clipToImageBuffer(context, absoluteTransform, repaintRect, clipperData->clipMaskImage, missingClipperData);
+    return true;
+}
+
+bool RenderSVGResourceClipper::drawContentIntoMaskImage(ClipperData* clipperData, const FloatRect& objectBoundingBox)
+{
+    ASSERT(frame());
+    ASSERT(clipperData);
+    ASSERT(clipperData->clipMaskImage);
+
+    GraphicsContext* maskContext = clipperData->clipMaskImage->context();
+    ASSERT(maskContext);
+
+    AffineTransform maskContentTransformation;
+    SVGClipPathElement* clipPath = static_cast<SVGClipPathElement*>(node());
+    if (clipPath->clipPathUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
+        maskContentTransformation.translate(objectBoundingBox.x(), objectBoundingBox.y());
+        maskContentTransformation.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.height());
+        maskContext->concatCTM(maskContentTransformation);
+    }
+
+    // Switch to a paint behavior where all children of this <clipPath> will be rendered using special constraints:
+    // - fill-opacity/stroke-opacity/opacity set to 1
+    // - masker/filter not applied when rendering the children
+    // - fill is set to the initial fill paint server (solid, black)
+    // - stroke is set to the initial stroke paint server (none)
+    PaintBehavior oldBehavior = frame()->view()->paintBehavior();
+    frame()->view()->setPaintBehavior(oldBehavior | PaintBehaviorRenderingSVGMask);
+
+    // Draw all clipPath children into a global mask.
+    for (Node* childNode = node()->firstChild(); childNode; childNode = childNode->nextSibling()) {
+        RenderObject* renderer = childNode->renderer();
+        if (!childNode->isSVGElement() || !toSVGElement(childNode)->isSVGStyledElement() || !renderer)
+            continue;
+        if (renderer->needsLayout()) {
+            frame()->view()->setPaintBehavior(oldBehavior);
+            return false;
+        }
+        RenderStyle* style = renderer->style();
+        if (!style || style->display() == NONE || style->visibility() != VISIBLE)
+            continue;
+
+        WindRule newClipRule = style->svgStyle()->clipRule();
+        bool isUseElement = childNode->hasTagName(SVGNames::useTag);
+        if (isUseElement) {
+            SVGUseElement* useElement = static_cast<SVGUseElement*>(childNode);
+            renderer = useElement->rendererClipChild();
+            if (!renderer)
+                continue;
+            if (!useElement->hasAttribute(SVGNames::clip_ruleAttr))
+                newClipRule = renderer->style()->svgStyle()->clipRule();
+        }
+
+        // Only shapes, paths and texts are allowed for clipping.
+        if (!renderer->isSVGShape() && !renderer->isSVGText())
+            continue;
+
+        maskContext->setFillRule(newClipRule);
+
+        // In the case of a <use> element, we obtained its renderere above, to retrieve its clipRule.
+        // We have to pass the <use> renderer itself to renderSubtreeToImageBuffer() to apply it's x/y/transform/etc. values when rendering.
+        // So if isUseElement is true, refetch the childNode->renderer(), as renderer got overriden above.
+        SVGRenderingContext::renderSubtreeToImageBuffer(clipperData->clipMaskImage.get(), isUseElement ? childNode->renderer() : renderer, maskContentTransformation);
+    }
+
+    frame()->view()->setPaintBehavior(oldBehavior);
+    return true;
+}
+
+void RenderSVGResourceClipper::calculateClipContentRepaintRect()
+{
+    // This is a rough heuristic to appraise the clip size and doesn't consider clip on clip.
+    for (Node* childNode = node()->firstChild(); childNode; childNode = childNode->nextSibling()) {
+        RenderObject* renderer = childNode->renderer();
+        if (!childNode->isSVGElement() || !toSVGElement(childNode)->isSVGStyledElement() || !renderer)
+            continue;
+        if (!renderer->isSVGShape() && !renderer->isSVGText() && !childNode->hasTagName(SVGNames::useTag))
+            continue;
+        RenderStyle* style = renderer->style();
+        if (!style || style->display() == NONE || style->visibility() != VISIBLE)
+             continue;
+        m_clipBoundaries.unite(renderer->localToParentTransform().mapRect(renderer->repaintRectInLocalCoordinates()));
+    }
+    m_clipBoundaries = static_cast<SVGClipPathElement*>(node())->animatedLocalTransform().mapRect(m_clipBoundaries);
+}
+
+bool RenderSVGResourceClipper::hitTestClipContent(const FloatRect& objectBoundingBox, const FloatPoint& nodeAtPoint)
+{
+    FloatPoint point = nodeAtPoint;
+    if (!SVGRenderSupport::pointInClippingArea(this, point))
+        return false;
+
+    SVGClipPathElement* clipPathElement = static_cast<SVGClipPathElement*>(node());
+    if (clipPathElement->clipPathUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
+        AffineTransform transform;
+        transform.translate(objectBoundingBox.x(), objectBoundingBox.y());
+        transform.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.height());
+        point = transform.inverse().mapPoint(point);
+    }
+
+    point = clipPathElement->animatedLocalTransform().inverse().mapPoint(point);
+
+    for (Node* childNode = node()->firstChild(); childNode; childNode = childNode->nextSibling()) {
+        RenderObject* renderer = childNode->renderer();
+        if (!childNode->isSVGElement() || !toSVGElement(childNode)->isSVGStyledElement() || !renderer)
+            continue;
+        if (!renderer->isSVGShape() && !renderer->isSVGText() && !childNode->hasTagName(SVGNames::useTag))
+            continue;
+        IntPoint hitPoint;
+        HitTestResult result(hitPoint);
+        if (renderer->nodeAtFloatPoint(HitTestRequest(HitTestRequest::SVGClipContent | HitTestRequest::DisallowShadowContent), result, point, HitTestForeground))
+            return true;
+    }
+
+    return false;
+}
+
+FloatRect RenderSVGResourceClipper::resourceBoundingBox(RenderObject* object)
+{
+    // Resource was not layouted yet. Give back the boundingBox of the object.
+    if (selfNeedsLayout())
+        return object->objectBoundingBox();
+    
+    if (m_clipBoundaries.isEmpty())
+        calculateClipContentRepaintRect();
+
+    if (static_cast<SVGClipPathElement*>(node())->clipPathUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
+        FloatRect objectBoundingBox = object->objectBoundingBox();
+        AffineTransform transform;
+        transform.translate(objectBoundingBox.x(), objectBoundingBox.y());
+        transform.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.height());
+        return transform.mapRect(m_clipBoundaries);
+    }
+
+    return m_clipBoundaries;
+}
+
+}
+
+#endif // ENABLE(SVG)
diff --git a/Source/core/rendering/svg/RenderSVGResourceClipper.h b/Source/core/rendering/svg/RenderSVGResourceClipper.h
new file mode 100644
index 0000000..fecc657
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGResourceClipper.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) Research In Motion Limited 2009-2010. 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 RenderSVGResourceClipper_h
+#define RenderSVGResourceClipper_h
+
+#if ENABLE(SVG)
+#include "core/platform/graphics/FloatRect.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/platform/graphics/ImageBuffer.h"
+#include "core/platform/graphics/IntSize.h"
+#include "core/platform/graphics/Path.h"
+#include "core/rendering/svg/RenderSVGResourceContainer.h"
+#include "core/svg/SVGClipPathElement.h"
+#include "core/svg/SVGUnitTypes.h"
+
+#include <wtf/HashMap.h>
+#include <wtf/OwnPtr.h>
+
+namespace WebCore {
+
+struct ClipperData {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    OwnPtr<ImageBuffer> clipMaskImage;
+};
+
+class RenderSVGResourceClipper FINAL : public RenderSVGResourceContainer {
+public:
+    RenderSVGResourceClipper(SVGClipPathElement*);
+    virtual ~RenderSVGResourceClipper();
+
+    virtual const char* renderName() const { return "RenderSVGResourceClipper"; }
+
+    virtual void removeAllClientsFromCache(bool markForInvalidation = true);
+    virtual void removeClientFromCache(RenderObject*, bool markForInvalidation = true);
+
+    virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode);
+    // clipPath can be clipped too, but don't have a boundingBox or repaintRect. So we can't call
+    // applyResource directly and use the rects from the object, since they are empty for RenderSVGResources
+    // FIXME: We made applyClippingToContext public because we cannot call applyResource on HTML elements (it asserts on RenderObject::objectBoundingBox)
+    bool applyClippingToContext(RenderObject*, const FloatRect&, const FloatRect&, GraphicsContext*);
+    virtual FloatRect resourceBoundingBox(RenderObject*);
+
+    virtual RenderSVGResourceType resourceType() const { return ClipperResourceType; }
+    
+    bool hitTestClipContent(const FloatRect&, const FloatPoint&);
+
+    SVGUnitTypes::SVGUnitType clipPathUnits() const { return static_cast<SVGClipPathElement*>(node())->clipPathUnits(); }
+
+    static RenderSVGResourceType s_resourceType;
+private:
+    bool pathOnlyClipping(GraphicsContext*, const AffineTransform&, const FloatRect&);
+    bool drawContentIntoMaskImage(ClipperData*, const FloatRect& objectBoundingBox);
+    void calculateClipContentRepaintRect();
+
+    FloatRect m_clipBoundaries;
+    HashMap<RenderObject*, ClipperData*> m_clipper;
+};
+
+}
+
+#endif
+#endif
diff --git a/Source/core/rendering/svg/RenderSVGResourceContainer.cpp b/Source/core/rendering/svg/RenderSVGResourceContainer.cpp
new file mode 100644
index 0000000..bb2c0ea
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGResourceContainer.cpp
@@ -0,0 +1,230 @@
+/*
+ * Copyright (C) Research In Motion Limited 2010. 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"
+
+#if ENABLE(SVG)
+#include "core/rendering/svg/RenderSVGResourceContainer.h"
+
+#include "core/rendering/RenderLayer.h"
+#include "core/rendering/RenderView.h"
+#include "core/rendering/svg/RenderSVGRoot.h"
+#include "core/rendering/svg/SVGRenderingContext.h"
+#include "core/rendering/svg/SVGResourcesCache.h"
+#include "core/svg/SVGStyledTransformableElement.h"
+
+namespace WebCore {
+
+static inline SVGDocumentExtensions* svgExtensionsFromNode(Node* node)
+{
+    ASSERT(node);
+    ASSERT(node->document());
+    return node->document()->accessSVGExtensions();
+}
+
+RenderSVGResourceContainer::RenderSVGResourceContainer(SVGStyledElement* node)
+    : RenderSVGHiddenContainer(node)
+    , m_id(node->getIdAttribute())
+    , m_registered(false)
+    , m_isInvalidating(false)
+{
+}
+
+RenderSVGResourceContainer::~RenderSVGResourceContainer()
+{
+    if (m_registered)
+        svgExtensionsFromNode(node())->removeResource(m_id);
+}
+
+void RenderSVGResourceContainer::layout()
+{
+    StackStats::LayoutCheckPoint layoutCheckPoint;
+    // Invalidate all resources if our layout changed.
+    if (everHadLayout() && selfNeedsLayout())
+        RenderSVGRoot::addResourceForClientInvalidation(this);
+
+    RenderSVGHiddenContainer::layout();
+}
+
+void RenderSVGResourceContainer::willBeDestroyed()
+{
+    SVGResourcesCache::resourceDestroyed(this);
+    RenderSVGHiddenContainer::willBeDestroyed();
+}
+
+void RenderSVGResourceContainer::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
+{
+    RenderSVGHiddenContainer::styleDidChange(diff, oldStyle);
+
+    if (!m_registered) {
+        m_registered = true;
+        registerResource();
+    }
+}
+
+void RenderSVGResourceContainer::idChanged()
+{
+    // Invalidate all our current clients.
+    removeAllClientsFromCache();
+
+    // Remove old id, that is guaranteed to be present in cache.
+    SVGDocumentExtensions* extensions = svgExtensionsFromNode(node());
+    extensions->removeResource(m_id);
+    m_id = toElement(node())->getIdAttribute();
+
+    registerResource();
+}
+
+void RenderSVGResourceContainer::markAllClientsForInvalidation(InvalidationMode mode)
+{
+    if ((m_clients.isEmpty() && m_clientLayers.isEmpty()) || m_isInvalidating)
+        return;
+
+    m_isInvalidating = true;
+    bool needsLayout = mode == LayoutAndBoundariesInvalidation;
+    bool markForInvalidation = mode != ParentOnlyInvalidation;
+
+    HashSet<RenderObject*>::iterator end = m_clients.end();
+    for (HashSet<RenderObject*>::iterator it = m_clients.begin(); it != end; ++it) {
+        RenderObject* client = *it;
+        if (client->isSVGResourceContainer()) {
+            client->toRenderSVGResourceContainer()->removeAllClientsFromCache(markForInvalidation);
+            continue;
+        }
+
+        if (markForInvalidation)
+            markClientForInvalidation(client, mode);
+
+        RenderSVGResource::markForLayoutAndParentResourceInvalidation(client, needsLayout);
+    }
+
+    markAllClientLayersForInvalidation();
+
+    m_isInvalidating = false;
+}
+
+void RenderSVGResourceContainer::markAllClientLayersForInvalidation()
+{
+    HashSet<RenderLayer*>::iterator layerEnd = m_clientLayers.end();
+    for (HashSet<RenderLayer*>::iterator it = m_clientLayers.begin(); it != layerEnd; ++it)
+        (*it)->filterNeedsRepaint();
+}
+
+void RenderSVGResourceContainer::markClientForInvalidation(RenderObject* client, InvalidationMode mode)
+{
+    ASSERT(client);
+    ASSERT(!m_clients.isEmpty());
+
+    switch (mode) {
+    case LayoutAndBoundariesInvalidation:
+    case BoundariesInvalidation:
+        client->setNeedsBoundariesUpdate();
+        break;
+    case RepaintInvalidation:
+        if (client->view())
+            client->repaint();
+        break;
+    case ParentOnlyInvalidation:
+        break;
+    }
+}
+
+void RenderSVGResourceContainer::addClient(RenderObject* client)
+{
+    ASSERT(client);
+    m_clients.add(client);
+}
+
+void RenderSVGResourceContainer::removeClient(RenderObject* client)
+{
+    ASSERT(client);
+    removeClientFromCache(client, false);
+    m_clients.remove(client);
+}
+
+void RenderSVGResourceContainer::addClientRenderLayer(RenderLayer* client)
+{
+    ASSERT(client);
+    m_clientLayers.add(client);
+}
+
+void RenderSVGResourceContainer::removeClientRenderLayer(RenderLayer* client)
+{
+    ASSERT(client);
+    m_clientLayers.remove(client);
+}
+
+void RenderSVGResourceContainer::registerResource()
+{
+    SVGDocumentExtensions* extensions = svgExtensionsFromNode(node());
+    if (!extensions->hasPendingResource(m_id)) {
+        extensions->addResource(m_id, this);
+        return;
+    }
+
+    OwnPtr<SVGDocumentExtensions::SVGPendingElements> clients(extensions->removePendingResource(m_id));
+
+    // Cache us with the new id.
+    extensions->addResource(m_id, this);
+
+    // Update cached resources of pending clients.
+    const SVGDocumentExtensions::SVGPendingElements::const_iterator end = clients->end();
+    for (SVGDocumentExtensions::SVGPendingElements::const_iterator it = clients->begin(); it != end; ++it) {
+        ASSERT((*it)->hasPendingResources());
+        extensions->clearHasPendingResourcesIfPossible(*it);
+        RenderObject* renderer = (*it)->renderer();
+        if (!renderer)
+            continue;
+        SVGResourcesCache::clientStyleChanged(renderer, StyleDifferenceLayout, renderer->style());
+        renderer->setNeedsLayout(true);
+    }
+}
+
+bool RenderSVGResourceContainer::shouldTransformOnTextPainting(RenderObject* object, AffineTransform& resourceTransform)
+{
+    ASSERT_UNUSED(object, object);
+
+    // This method should only be called for RenderObjects that deal with text rendering. Cmp. RenderObject.h's is*() methods.
+    ASSERT(object->isSVGText() || object->isSVGTextPath() || object->isSVGInline());
+
+    // In text drawing, the scaling part of the graphics context CTM is removed, compare SVGInlineTextBox::paintTextWithShadows.
+    // So, we use that scaling factor here, too, and then push it down to pattern or gradient space
+    // in order to keep the pattern or gradient correctly scaled.
+    float scalingFactor = SVGRenderingContext::calculateScreenFontSizeScalingFactor(object);
+    if (scalingFactor == 1)
+        return false;
+    resourceTransform.scale(scalingFactor);
+    return true;
+}
+
+// FIXME: This does not belong here.
+AffineTransform RenderSVGResourceContainer::transformOnNonScalingStroke(RenderObject* object, const AffineTransform& resourceTransform)
+{
+    if (!object->isSVGShape())
+        return resourceTransform;
+
+    SVGStyledTransformableElement* element = toSVGStyledTransformableElement(object->node());
+    AffineTransform transform = element->getScreenCTM(SVGLocatable::DisallowStyleUpdate);
+    transform *= resourceTransform;
+    return transform;
+}
+
+}
+
+#endif
diff --git a/Source/core/rendering/svg/RenderSVGResourceContainer.h b/Source/core/rendering/svg/RenderSVGResourceContainer.h
new file mode 100644
index 0000000..a7a73bb
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGResourceContainer.h
@@ -0,0 +1,102 @@
+/*
+ * Copyright (C) Research In Motion Limited 2010. 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 RenderSVGResourceContainer_h
+#define RenderSVGResourceContainer_h
+
+#if ENABLE(SVG)
+#include "core/rendering/svg/RenderSVGHiddenContainer.h"
+#include "core/rendering/svg/RenderSVGResource.h"
+
+namespace WebCore {
+
+class RenderLayer;
+
+class RenderSVGResourceContainer : public RenderSVGHiddenContainer,
+                                   public RenderSVGResource {
+public:
+    RenderSVGResourceContainer(SVGStyledElement*);
+    virtual ~RenderSVGResourceContainer();
+
+    virtual void layout();
+    virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OVERRIDE FINAL;
+
+    virtual bool isSVGResourceContainer() const OVERRIDE FINAL { return true; }
+    virtual RenderSVGResourceContainer* toRenderSVGResourceContainer() OVERRIDE FINAL { return this; }
+
+    static bool shouldTransformOnTextPainting(RenderObject*, AffineTransform&);
+    static AffineTransform transformOnNonScalingStroke(RenderObject*, const AffineTransform& resourceTransform);
+
+    void idChanged();
+    void addClientRenderLayer(RenderLayer*);
+    void removeClientRenderLayer(RenderLayer*);
+
+protected:
+    enum InvalidationMode {
+        LayoutAndBoundariesInvalidation,
+        BoundariesInvalidation,
+        RepaintInvalidation,
+        ParentOnlyInvalidation
+    };
+
+    // Used from the invalidateClient/invalidateClients methods from classes, inheriting from us.
+    void markAllClientsForInvalidation(InvalidationMode);
+    void markAllClientLayersForInvalidation();
+    void markClientForInvalidation(RenderObject*, InvalidationMode);
+
+private:
+    friend class SVGResourcesCache;
+    void addClient(RenderObject*);
+    void removeClient(RenderObject*);
+
+private:
+    virtual void willBeDestroyed() OVERRIDE FINAL;
+    void registerResource();
+
+    AtomicString m_id;
+    bool m_registered : 1;
+    bool m_isInvalidating : 1;
+    HashSet<RenderObject*> m_clients;
+    HashSet<RenderLayer*> m_clientLayers;
+};
+
+inline RenderSVGResourceContainer* getRenderSVGResourceContainerById(Document* document, const AtomicString& id)
+{
+    if (id.isEmpty())
+        return 0;
+
+    if (RenderSVGResourceContainer* renderResource = document->accessSVGExtensions()->resourceById(id))
+        return renderResource;
+
+    return 0;
+}
+
+template<typename Renderer>
+Renderer* getRenderSVGResourceById(Document* document, const AtomicString& id)
+{
+    if (RenderSVGResourceContainer* container = getRenderSVGResourceContainerById(document, id))
+        return container->cast<Renderer>();
+
+    return 0;
+}
+
+}
+
+#endif
+#endif
diff --git a/Source/core/rendering/svg/RenderSVGResourceFilter.cpp b/Source/core/rendering/svg/RenderSVGResourceFilter.cpp
new file mode 100644
index 0000000..14515ec
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGResourceFilter.cpp
@@ -0,0 +1,374 @@
+/*
+ * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org>
+ * Copyright (C) 2005 Eric Seidel <eric@webkit.org>
+ * Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
+ * Copyright (C) Research In Motion Limited 2010. 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"
+
+#if ENABLE(SVG)
+#include "core/rendering/svg/RenderSVGResourceFilter.h"
+
+#include "SVGNames.h"
+#include "core/html/ImageData.h"
+#include "core/page/Page.h"
+#include "core/page/Settings.h"
+#include "core/platform/graphics/FloatPoint.h"
+#include "core/platform/graphics/FloatRect.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/platform/graphics/Image.h"
+#include "core/platform/graphics/ImageBuffer.h"
+#include "core/platform/graphics/IntRect.h"
+#include "core/platform/graphics/filters/FilterEffect.h"
+#include "core/platform/graphics/filters/SourceAlpha.h"
+#include "core/platform/graphics/filters/SourceGraphic.h"
+#include "core/platform/graphics/transforms/AffineTransform.h"
+#include "core/rendering/svg/RenderSVGResource.h"
+#include "core/rendering/svg/RenderSVGResourceFilterPrimitive.h"
+#include "core/rendering/svg/SVGRenderingContext.h"
+#include "core/svg/SVGElement.h"
+#include "core/svg/SVGFilterElement.h"
+#include "core/svg/SVGFilterPrimitiveStandardAttributes.h"
+#include "core/svg/SVGStyledElement.h"
+#include "core/svg/SVGUnitTypes.h"
+#include "core/svg/graphics/filters/SVGFilter.h"
+
+#include <wtf/UnusedParam.h>
+#include <wtf/Vector.h>
+
+using namespace std;
+
+namespace WebCore {
+
+RenderSVGResourceType RenderSVGResourceFilter::s_resourceType = FilterResourceType;
+
+RenderSVGResourceFilter::RenderSVGResourceFilter(SVGFilterElement* node)
+    : RenderSVGResourceContainer(node)
+{
+}
+
+RenderSVGResourceFilter::~RenderSVGResourceFilter()
+{
+    if (m_filter.isEmpty())
+        return;
+
+    deleteAllValues(m_filter);
+    m_filter.clear();
+}
+
+void RenderSVGResourceFilter::removeAllClientsFromCache(bool markForInvalidation)
+{
+    if (!m_filter.isEmpty()) {
+        deleteAllValues(m_filter);
+        m_filter.clear();
+    }
+
+    markAllClientsForInvalidation(markForInvalidation ? LayoutAndBoundariesInvalidation : ParentOnlyInvalidation);
+}
+
+void RenderSVGResourceFilter::removeClientFromCache(RenderObject* client, bool markForInvalidation)
+{
+    ASSERT(client);
+
+    if (FilterData* filterData = m_filter.get(client)) {
+        if (filterData->savedContext)
+            filterData->state = FilterData::MarkedForRemoval;
+        else
+            delete m_filter.take(client);
+    }
+
+    markClientForInvalidation(client, markForInvalidation ? BoundariesInvalidation : ParentOnlyInvalidation);
+}
+
+PassRefPtr<SVGFilterBuilder> RenderSVGResourceFilter::buildPrimitives(SVGFilter* filter)
+{
+    SVGFilterElement* filterElement = static_cast<SVGFilterElement*>(node());
+    FloatRect targetBoundingBox = filter->targetBoundingBox();
+
+    // Add effects to the builder
+    RefPtr<SVGFilterBuilder> builder = SVGFilterBuilder::create(SourceGraphic::create(filter), SourceAlpha::create(filter));
+    for (Node* node = filterElement->firstChild(); node; node = node->nextSibling()) {
+        if (!node->isSVGElement())
+            continue;
+
+        SVGElement* element = toSVGElement(node);
+        if (!element->isFilterEffect())
+            continue;
+
+        SVGFilterPrimitiveStandardAttributes* effectElement = static_cast<SVGFilterPrimitiveStandardAttributes*>(element);
+        RefPtr<FilterEffect> effect = effectElement->build(builder.get(), filter);
+        if (!effect) {
+            builder->clearEffects();
+            return 0;
+        }
+        builder->appendEffectToEffectReferences(effect, effectElement->renderer());
+        effectElement->setStandardAttributes(effect.get());
+        effect->setEffectBoundaries(SVGLengthContext::resolveRectangle<SVGFilterPrimitiveStandardAttributes>(effectElement, filterElement->primitiveUnits(), targetBoundingBox));
+        effect->setOperatingColorSpace(
+            effectElement->renderer()->style()->svgStyle()->colorInterpolationFilters() == CI_LINEARRGB ? ColorSpaceLinearRGB : ColorSpaceDeviceRGB);
+        builder->add(effectElement->result(), effect);
+    }
+    return builder.release();
+}
+
+bool RenderSVGResourceFilter::fitsInMaximumImageSize(const FloatSize& size, FloatSize& scale)
+{
+    bool matchesFilterSize = true;
+    if (size.width() > kMaxFilterSize) {
+        scale.setWidth(scale.width() * kMaxFilterSize / size.width());
+        matchesFilterSize = false;
+    }
+    if (size.height() > kMaxFilterSize) {
+        scale.setHeight(scale.height() * kMaxFilterSize / size.height());
+        matchesFilterSize = false;
+    }
+
+    return matchesFilterSize;
+}
+
+bool RenderSVGResourceFilter::applyResource(RenderObject* object, RenderStyle*, GraphicsContext*& context, unsigned short resourceMode)
+{
+    ASSERT(object);
+    ASSERT(context);
+    ASSERT_UNUSED(resourceMode, resourceMode == ApplyToDefaultMode);
+
+    if (m_filter.contains(object)) {
+        FilterData* filterData = m_filter.get(object);
+        if (filterData->state == FilterData::PaintingSource || filterData->state == FilterData::Applying)
+            filterData->state = FilterData::CycleDetected;
+        return false; // Already built, or we're in a cycle, or we're marked for removal. Regardless, just do nothing more now.
+    }
+
+    OwnPtr<FilterData> filterData(adoptPtr(new FilterData));
+    FloatRect targetBoundingBox = object->objectBoundingBox();
+
+    SVGFilterElement* filterElement = static_cast<SVGFilterElement*>(node());
+    filterData->boundaries = SVGLengthContext::resolveRectangle<SVGFilterElement>(filterElement, filterElement->filterUnits(), targetBoundingBox);
+    if (filterData->boundaries.isEmpty())
+        return false;
+
+    // Determine absolute transformation matrix for filter. 
+    AffineTransform absoluteTransform;
+    SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(object, absoluteTransform);
+    if (!absoluteTransform.isInvertible())
+        return false;
+
+    // Eliminate shear of the absolute transformation matrix, to be able to produce unsheared tile images for feTile.
+    filterData->shearFreeAbsoluteTransform = AffineTransform(absoluteTransform.xScale(), 0, 0, absoluteTransform.yScale(), 0, 0);
+
+    // Determine absolute boundaries of the filter and the drawing region.
+    FloatRect absoluteFilterBoundaries = filterData->shearFreeAbsoluteTransform.mapRect(filterData->boundaries);
+    filterData->drawingRegion = object->strokeBoundingBox();
+    filterData->drawingRegion.intersect(filterData->boundaries);
+    FloatRect absoluteDrawingRegion = filterData->shearFreeAbsoluteTransform.mapRect(filterData->drawingRegion);
+
+    // Create the SVGFilter object.
+    bool primitiveBoundingBoxMode = filterElement->primitiveUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX;
+    filterData->filter = SVGFilter::create(filterData->shearFreeAbsoluteTransform, absoluteDrawingRegion, targetBoundingBox, filterData->boundaries, primitiveBoundingBoxMode);
+
+    // Create all relevant filter primitives.
+    filterData->builder = buildPrimitives(filterData->filter.get());
+    if (!filterData->builder)
+        return false;
+
+    // Calculate the scale factor for the use of filterRes.
+    // Also see http://www.w3.org/TR/SVG/filters.html#FilterEffectsRegion
+    FloatSize scale(1, 1);
+    if (filterElement->hasAttribute(SVGNames::filterResAttr)) {
+        scale.setWidth(filterElement->filterResX() / absoluteFilterBoundaries.width());
+        scale.setHeight(filterElement->filterResY() / absoluteFilterBoundaries.height());
+    }
+
+    if (scale.isEmpty())
+        return false;
+
+    // Determine scale factor for filter. The size of intermediate ImageBuffers shouldn't be bigger than kMaxFilterSize.
+    FloatRect tempSourceRect = absoluteDrawingRegion;
+    tempSourceRect.scale(scale.width(), scale.height());
+    fitsInMaximumImageSize(tempSourceRect.size(), scale);
+
+    // Set the scale level in SVGFilter.
+    filterData->filter->setFilterResolution(scale);
+
+    FilterEffect* lastEffect = filterData->builder->lastEffect();
+    if (!lastEffect)
+        return false;
+
+    RenderSVGResourceFilterPrimitive::determineFilterPrimitiveSubregion(lastEffect);
+    FloatRect subRegion = lastEffect->maxEffectRect();
+    // At least one FilterEffect has a too big image size,
+    // recalculate the effect sizes with new scale factors.
+    if (!fitsInMaximumImageSize(subRegion.size(), scale)) {
+        filterData->filter->setFilterResolution(scale);
+        RenderSVGResourceFilterPrimitive::determineFilterPrimitiveSubregion(lastEffect);
+    }
+
+    // If the drawingRegion is empty, we have something like <g filter=".."/>.
+    // Even if the target objectBoundingBox() is empty, we still have to draw the last effect result image in postApplyResource.
+    if (filterData->drawingRegion.isEmpty()) {
+        ASSERT(!m_filter.contains(object));
+        filterData->savedContext = context;
+        m_filter.set(object, filterData.leakPtr());
+        return false;
+    }
+
+    // Change the coordinate transformation applied to the filtered element to reflect the resolution of the filter.
+    AffineTransform effectiveTransform;
+    effectiveTransform.scale(scale.width(), scale.height());
+    effectiveTransform.multiply(filterData->shearFreeAbsoluteTransform);
+
+    OwnPtr<ImageBuffer> sourceGraphic;
+    RenderingMode renderingMode = object->document()->page()->settings()->acceleratedFiltersEnabled() ? Accelerated : Unaccelerated;
+    if (!SVGRenderingContext::createImageBuffer(filterData->drawingRegion, effectiveTransform, sourceGraphic, ColorSpaceLinearRGB, renderingMode)) {
+        ASSERT(!m_filter.contains(object));
+        filterData->savedContext = context;
+        m_filter.set(object, filterData.leakPtr());
+        return false;
+    }
+    
+    // Set the rendering mode from the page's settings.
+    filterData->filter->setRenderingMode(renderingMode);
+
+    GraphicsContext* sourceGraphicContext = sourceGraphic->context();
+    ASSERT(sourceGraphicContext);
+  
+    filterData->sourceGraphicBuffer = sourceGraphic.release();
+    filterData->savedContext = context;
+
+    context = sourceGraphicContext;
+
+    ASSERT(!m_filter.contains(object));
+    m_filter.set(object, filterData.leakPtr());
+
+    return true;
+}
+
+void RenderSVGResourceFilter::postApplyResource(RenderObject* object, GraphicsContext*& context, unsigned short resourceMode, const Path*, const RenderSVGShape*)
+{
+    ASSERT(object);
+    ASSERT(context);
+    ASSERT_UNUSED(resourceMode, resourceMode == ApplyToDefaultMode);
+
+    FilterData* filterData = m_filter.get(object);
+    if (!filterData)
+        return;
+
+    switch (filterData->state) {
+    case FilterData::MarkedForRemoval:
+        delete m_filter.take(object);
+        return;
+
+    case FilterData::CycleDetected:
+    case FilterData::Applying:
+        // We have a cycle if we are already applying the data.
+        // This can occur due to FeImage referencing a source that makes use of the FEImage itself.
+        // This is the first place we've hit the cycle, so set the state back to PaintingSource so the return stack
+        // will continue correctly.
+        filterData->state = FilterData::PaintingSource;
+        return;
+
+    case FilterData::PaintingSource:
+        if (!filterData->savedContext) {
+            removeClientFromCache(object);
+            return;
+        }
+
+        context = filterData->savedContext;
+        filterData->savedContext = 0;
+        break;
+
+    case FilterData::Built: { } // Empty
+    }
+
+    FilterEffect* lastEffect = filterData->builder->lastEffect();
+
+    if (lastEffect && !filterData->boundaries.isEmpty() && !lastEffect->filterPrimitiveSubregion().isEmpty()) {
+        // This is the real filtering of the object. It just needs to be called on the
+        // initial filtering process. We just take the stored filter result on a
+        // second drawing.
+        if (filterData->state != FilterData::Built)
+            filterData->filter->setSourceImage(filterData->sourceGraphicBuffer.release());
+
+        // Always true if filterData is just built (filterData->state == FilterData::Built).
+        if (!lastEffect->hasResult()) {
+            filterData->state = FilterData::Applying;
+            lastEffect->apply();
+            lastEffect->correctFilterResultIfNeeded();
+            lastEffect->transformResultColorSpace(ColorSpaceDeviceRGB);
+        }
+        filterData->state = FilterData::Built;
+
+        ImageBuffer* resultImage = lastEffect->asImageBuffer();
+        if (resultImage) {
+            context->concatCTM(filterData->shearFreeAbsoluteTransform.inverse());
+
+            context->scale(FloatSize(1 / filterData->filter->filterResolution().width(), 1 / filterData->filter->filterResolution().height()));
+            context->drawImageBuffer(resultImage, object->style()->colorSpace(), lastEffect->absolutePaintRect());
+            context->scale(filterData->filter->filterResolution());
+
+            context->concatCTM(filterData->shearFreeAbsoluteTransform);
+        }
+    }
+    filterData->sourceGraphicBuffer.clear();
+}
+
+FloatRect RenderSVGResourceFilter::resourceBoundingBox(RenderObject* object)
+{
+    if (SVGFilterElement* element = static_cast<SVGFilterElement*>(node()))
+        return SVGLengthContext::resolveRectangle<SVGFilterElement>(element, element->filterUnits(), object->objectBoundingBox());
+
+    return FloatRect();
+}
+
+void RenderSVGResourceFilter::primitiveAttributeChanged(RenderObject* object, const QualifiedName& attribute)
+{
+    HashMap<RenderObject*, FilterData*>::iterator it = m_filter.begin();
+    HashMap<RenderObject*, FilterData*>::iterator end = m_filter.end();
+    SVGFilterPrimitiveStandardAttributes* primitve = static_cast<SVGFilterPrimitiveStandardAttributes*>(object->node());
+
+    for (; it != end; ++it) {
+        FilterData* filterData = it->value;
+        if (filterData->state != FilterData::Built)
+            continue;
+
+        SVGFilterBuilder* builder = filterData->builder.get();
+        FilterEffect* effect = builder->effectByRenderer(object);
+        if (!effect)
+            continue;
+        // Since all effects shares the same attribute value, all
+        // or none of them will be changed.
+        if (!primitve->setFilterEffectAttribute(effect, attribute))
+            return;
+        builder->clearResultsRecursive(effect);
+
+        // Repaint the image on the screen.
+        markClientForInvalidation(it->key, RepaintInvalidation);
+    }
+    markAllClientLayersForInvalidation();
+}
+
+FloatRect RenderSVGResourceFilter::drawingRegion(RenderObject* object) const
+{
+    FilterData* filterData = m_filter.get(object);
+    return filterData ? filterData->drawingRegion : FloatRect();
+}
+
+}
+#endif
diff --git a/Source/core/rendering/svg/RenderSVGResourceFilter.h b/Source/core/rendering/svg/RenderSVGResourceFilter.h
new file mode 100644
index 0000000..366b53d
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGResourceFilter.h
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2004, 2005, 2006, 2007 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org>
+ * Copyright (C) 2005 Eric Seidel <eric@webkit.org>
+ * Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
+ * Copyright (C) Research In Motion Limited 2010. 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 RenderSVGResourceFilter_h
+#define RenderSVGResourceFilter_h
+
+#if ENABLE(SVG)
+#include "core/platform/graphics/FloatRect.h"
+#include "core/platform/graphics/ImageBuffer.h"
+#include "core/rendering/svg/RenderSVGResourceContainer.h"
+#include "core/svg/SVGFilterElement.h"
+#include "core/svg/SVGUnitTypes.h"
+#include "core/svg/graphics/filters/SVGFilter.h"
+#include "core/svg/graphics/filters/SVGFilterBuilder.h"
+
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+#include <wtf/RefPtr.h>
+
+namespace WebCore {
+
+struct FilterData {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    enum FilterDataState { PaintingSource, Applying, Built, CycleDetected, MarkedForRemoval };
+
+    FilterData()
+        : savedContext(0)
+        , state(PaintingSource)
+    {
+    }
+
+    RefPtr<SVGFilter> filter;
+    RefPtr<SVGFilterBuilder> builder;
+    OwnPtr<ImageBuffer> sourceGraphicBuffer;
+    GraphicsContext* savedContext;
+    AffineTransform shearFreeAbsoluteTransform;
+    FloatRect boundaries;
+    FloatRect drawingRegion;
+    FloatSize scale;
+    FilterDataState state;
+};
+
+class GraphicsContext;
+
+class RenderSVGResourceFilter FINAL : public RenderSVGResourceContainer {
+public:
+    RenderSVGResourceFilter(SVGFilterElement*);
+    virtual ~RenderSVGResourceFilter();
+
+    virtual const char* renderName() const { return "RenderSVGResourceFilter"; }
+    virtual bool isSVGResourceFilter() const OVERRIDE { return true; }
+
+    virtual void removeAllClientsFromCache(bool markForInvalidation = true);
+    virtual void removeClientFromCache(RenderObject*, bool markForInvalidation = true);
+
+    virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode);
+    virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short resourceMode, const Path*, const RenderSVGShape*);
+
+    virtual FloatRect resourceBoundingBox(RenderObject*);
+
+    PassRefPtr<SVGFilterBuilder> buildPrimitives(SVGFilter*);
+
+    SVGUnitTypes::SVGUnitType filterUnits() const { return static_cast<SVGFilterElement*>(node())->filterUnits(); }
+    SVGUnitTypes::SVGUnitType primitiveUnits() const { return static_cast<SVGFilterElement*>(node())->primitiveUnits(); }
+
+    void primitiveAttributeChanged(RenderObject*, const QualifiedName&);
+
+    virtual RenderSVGResourceType resourceType() const { return s_resourceType; }
+    static RenderSVGResourceType s_resourceType;
+
+    FloatRect drawingRegion(RenderObject*) const;
+private:
+    bool fitsInMaximumImageSize(const FloatSize&, FloatSize&);
+
+    HashMap<RenderObject*, FilterData*> m_filter;
+};
+
+inline RenderSVGResourceFilter* toRenderSVGFilter(RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isSVGResourceFilter());
+    return static_cast<RenderSVGResourceFilter*>(object);
+}
+
+}
+
+#endif
+#endif
diff --git a/Source/core/rendering/svg/RenderSVGResourceFilterPrimitive.cpp b/Source/core/rendering/svg/RenderSVGResourceFilterPrimitive.cpp
new file mode 100644
index 0000000..7f985b2
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGResourceFilterPrimitive.cpp
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2010 University of Szeged
+ * Copyright (C) 2010 Zoltan Herczeg
+ * Copyright (C) 2011 Renata Hodovan (reni@webkit.org)
+ *
+ * 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 UNIVERSITY OF SZEGED ``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 UNIVERSITY OF SZEGED 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 "core/rendering/svg/RenderSVGResourceFilterPrimitive.h"
+
+#include "SVGNames.h"
+#include "core/rendering/svg/RenderSVGResource.h"
+#include "core/svg/graphics/filters/SVGFEImage.h"
+#include "core/svg/graphics/filters/SVGFilter.h"
+
+namespace WebCore {
+
+
+void RenderSVGResourceFilterPrimitive::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
+{
+    RenderSVGHiddenContainer::styleDidChange(diff, oldStyle);
+
+    RenderObject* filter = parent();
+    if (!filter)
+        return;
+    ASSERT(filter->isSVGResourceFilter());
+
+    if (diff == StyleDifferenceEqual || !oldStyle)
+        return;
+
+    const SVGRenderStyle* newStyle = this->style()->svgStyle();
+    if (node()->hasTagName(SVGNames::feFloodTag)) {
+        if (newStyle->floodColor() != oldStyle->svgStyle()->floodColor())
+            toRenderSVGFilter(filter)->primitiveAttributeChanged(this, SVGNames::flood_colorAttr);
+        if (newStyle->floodOpacity() != oldStyle->svgStyle()->floodOpacity())
+            toRenderSVGFilter(filter)->primitiveAttributeChanged(this, SVGNames::flood_opacityAttr);
+    } else if (node()->hasTagName(SVGNames::feDiffuseLightingTag) || node()->hasTagName(SVGNames::feSpecularLightingTag)) {
+        if (newStyle->lightingColor() != oldStyle->svgStyle()->lightingColor())
+            toRenderSVGFilter(filter)->primitiveAttributeChanged(this, SVGNames::lighting_colorAttr);
+    }
+}
+
+FloatRect RenderSVGResourceFilterPrimitive::determineFilterPrimitiveSubregion(FilterEffect* effect)
+{
+    SVGFilter* filter = static_cast<SVGFilter*>(effect->filter());
+    ASSERT(filter);
+
+    // FETile, FETurbulence, FEFlood don't have input effects, take the filter region as unite rect.
+    FloatRect subregion;
+    if (unsigned numberOfInputEffects = effect->inputEffects().size()) {
+        subregion = determineFilterPrimitiveSubregion(effect->inputEffect(0));
+        for (unsigned i = 1; i < numberOfInputEffects; ++i)
+            subregion.unite(determineFilterPrimitiveSubregion(effect->inputEffect(i)));
+    } else
+        subregion = filter->filterRegionInUserSpace();
+
+    // After calling determineFilterPrimitiveSubregion on the target effect, reset the subregion again for <feTile>.
+    if (effect->filterEffectType() == FilterEffectTypeTile)
+        subregion = filter->filterRegionInUserSpace();
+
+    FloatRect effectBoundaries = effect->effectBoundaries();
+    if (effect->hasX())
+        subregion.setX(effectBoundaries.x());
+    if (effect->hasY())
+        subregion.setY(effectBoundaries.y());
+    if (effect->hasWidth())
+        subregion.setWidth(effectBoundaries.width());
+    if (effect->hasHeight())
+        subregion.setHeight(effectBoundaries.height());
+
+    effect->setFilterPrimitiveSubregion(subregion);
+
+    FloatRect absoluteSubregion = filter->absoluteTransform().mapRect(subregion);
+    FloatSize filterResolution = filter->filterResolution();
+    absoluteSubregion.scale(filterResolution.width(), filterResolution.height());
+
+    // Clip every filter effect to the filter region.
+    FloatRect absoluteScaledFilterRegion = filter->filterRegion();
+    absoluteScaledFilterRegion.scale(filterResolution.width(), filterResolution.height());
+    absoluteSubregion.intersect(absoluteScaledFilterRegion);
+
+    effect->setMaxEffectRect(absoluteSubregion);
+    return subregion;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
diff --git a/Source/core/rendering/svg/RenderSVGResourceFilterPrimitive.h b/Source/core/rendering/svg/RenderSVGResourceFilterPrimitive.h
new file mode 100644
index 0000000..bc7de40
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGResourceFilterPrimitive.h
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2010 University of Szeged
+ * Copyright (C) 2010 Zoltan Herczeg
+ *
+ * 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 UNIVERSITY OF SZEGED ``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 UNIVERSITY OF SZEGED 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 RenderSVGResourceFilterPrimitive_h
+#define RenderSVGResourceFilterPrimitive_h
+
+#if ENABLE(SVG)
+
+#include "core/rendering/svg/RenderSVGHiddenContainer.h"
+#include "core/rendering/svg/RenderSVGResourceFilter.h"
+
+namespace WebCore {
+
+class FilterEffect;
+
+class RenderSVGResourceFilterPrimitive FINAL : public RenderSVGHiddenContainer {
+public:
+    explicit RenderSVGResourceFilterPrimitive(SVGStyledElement* filterPrimitiveElement)
+        : RenderSVGHiddenContainer(filterPrimitiveElement)
+    {
+    }
+
+    virtual void styleDidChange(StyleDifference, const RenderStyle*);
+
+    virtual const char* renderName() const { return "RenderSVGResourceFilterPrimitive"; }
+    virtual bool isSVGResourceFilterPrimitive() const { return true; }
+
+    // They depend on the RenderObject argument of RenderSVGResourceFilter::applyResource.
+    static FloatRect determineFilterPrimitiveSubregion(FilterEffect*);
+
+    inline void primitiveAttributeChanged(const QualifiedName& attribute)
+    {
+        RenderObject* filter = parent();
+        if (!filter || !filter->isSVGResourceFilter())
+            return;
+        static_cast<RenderSVGResourceFilter*>(filter)->primitiveAttributeChanged(this, attribute);
+    }
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
+
+#endif // RenderSVGResourceFilterPrimitive_h
diff --git a/Source/core/rendering/svg/RenderSVGResourceGradient.cpp b/Source/core/rendering/svg/RenderSVGResourceGradient.cpp
new file mode 100644
index 0000000..5e02bf8
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGResourceGradient.cpp
@@ -0,0 +1,193 @@
+/*
+ * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) 2008 Eric Seidel <eric@webkit.org>
+ * Copyright (C) 2008 Dirk Schulze <krit@webkit.org>
+ * Copyright (C) Research In Motion Limited 2010. 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"
+
+#if ENABLE(SVG)
+#include "core/rendering/svg/RenderSVGResourceGradient.h"
+
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/rendering/svg/RenderSVGShape.h"
+#include "core/rendering/svg/RenderSVGText.h"
+#include "core/rendering/svg/SVGRenderSupport.h"
+#include "core/rendering/svg/SVGRenderingContext.h"
+#include "core/svg/GradientAttributes.h"
+#include <wtf/UnusedParam.h>
+
+namespace WebCore {
+
+RenderSVGResourceGradient::RenderSVGResourceGradient(SVGGradientElement* node)
+    : RenderSVGResourceContainer(node)
+    , m_shouldCollectGradientAttributes(true)
+{
+}
+
+void RenderSVGResourceGradient::removeAllClientsFromCache(bool markForInvalidation)
+{
+    m_gradientMap.clear();
+    m_shouldCollectGradientAttributes = true;
+    markAllClientsForInvalidation(markForInvalidation ? RepaintInvalidation : ParentOnlyInvalidation);
+}
+
+void RenderSVGResourceGradient::removeClientFromCache(RenderObject* client, bool markForInvalidation)
+{
+    ASSERT(client);
+    m_gradientMap.remove(client);
+    markClientForInvalidation(client, markForInvalidation ? RepaintInvalidation : ParentOnlyInvalidation);
+}
+
+bool RenderSVGResourceGradient::applyResource(RenderObject* object, RenderStyle* style, GraphicsContext*& context, unsigned short resourceMode)
+{
+    ASSERT(object);
+    ASSERT(style);
+    ASSERT(context);
+    ASSERT(resourceMode != ApplyToDefaultMode);
+
+    // Be sure to synchronize all SVG properties on the gradientElement _before_ processing any further.
+    // Otherwhise the call to collectGradientAttributes() in createTileImage(), may cause the SVG DOM property
+    // synchronization to kick in, which causes removeAllClientsFromCache() to be called, which in turn deletes our
+    // GradientData object! Leaving out the line below will cause svg/dynamic-updates/SVG*GradientElement-svgdom* to crash.
+    SVGGradientElement* gradientElement = static_cast<SVGGradientElement*>(node());
+    if (!gradientElement)
+        return false;
+
+    if (m_shouldCollectGradientAttributes) {
+        gradientElement->synchronizeAnimatedSVGAttribute(anyQName());
+        if (!collectGradientAttributes(gradientElement))
+            return false;
+
+        m_shouldCollectGradientAttributes = false;
+    }
+
+    // Spec: When the geometry of the applicable element has no width or height and objectBoundingBox is specified,
+    // then the given effect (e.g. a gradient or a filter) will be ignored.
+    FloatRect objectBoundingBox = object->objectBoundingBox();
+    if (gradientUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX && objectBoundingBox.isEmpty())
+        return false;
+
+    OwnPtr<GradientData>& gradientData = m_gradientMap.add(object, nullptr).iterator->value;
+    if (!gradientData)
+        gradientData = adoptPtr(new GradientData);
+
+    bool isPaintingText = resourceMode & ApplyToTextMode;
+
+    // Create gradient object
+    if (!gradientData->gradient) {
+        buildGradient(gradientData.get());
+
+        // We want the text bounding box applied to the gradient space transform now, so the gradient shader can use it.
+        if (gradientUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX && !objectBoundingBox.isEmpty()) {
+            gradientData->userspaceTransform.translate(objectBoundingBox.x(), objectBoundingBox.y());
+            gradientData->userspaceTransform.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.height());
+        }
+
+        AffineTransform gradientTransform;
+        calculateGradientTransform(gradientTransform);
+
+        gradientData->userspaceTransform *= gradientTransform;
+        if (isPaintingText) {
+            // Depending on font scaling factor, we may need to rescale the gradient here since
+            // text painting removes the scale factor from the context.
+            AffineTransform additionalTextTransform;
+            if (shouldTransformOnTextPainting(object, additionalTextTransform))
+                gradientData->userspaceTransform *= additionalTextTransform;
+        }
+        gradientData->gradient->setGradientSpaceTransform(gradientData->userspaceTransform);
+    }
+
+    if (!gradientData->gradient)
+        return false;
+
+    // Draw gradient
+    context->save();
+
+    if (isPaintingText)
+        context->setTextDrawingMode(resourceMode & ApplyToFillMode ? TextModeFill : TextModeStroke);
+
+    const SVGRenderStyle* svgStyle = style->svgStyle();
+    ASSERT(svgStyle);
+
+    if (resourceMode & ApplyToFillMode) {
+        context->setAlpha(svgStyle->fillOpacity());
+        context->setFillGradient(gradientData->gradient);
+        context->setFillRule(svgStyle->fillRule());
+    } else if (resourceMode & ApplyToStrokeMode) {
+        if (svgStyle->vectorEffect() == VE_NON_SCALING_STROKE)
+            gradientData->gradient->setGradientSpaceTransform(transformOnNonScalingStroke(object, gradientData->userspaceTransform));
+        context->setAlpha(svgStyle->strokeOpacity());
+        context->setStrokeGradient(gradientData->gradient);
+        SVGRenderSupport::applyStrokeStyleToContext(context, style, object);
+    }
+
+    return true;
+}
+
+void RenderSVGResourceGradient::postApplyResource(RenderObject* object, GraphicsContext*& context, unsigned short resourceMode, const Path* path, const RenderSVGShape* shape)
+{
+    ASSERT(context);
+    ASSERT(resourceMode != ApplyToDefaultMode);
+    UNUSED_PARAM(object);
+
+    if (resourceMode & ApplyToFillMode) {
+        if (path)
+            context->fillPath(*path);
+        else if (shape)
+            shape->fillShape(context);
+    }
+    if (resourceMode & ApplyToStrokeMode) {
+        if (path)
+            context->strokePath(*path);
+        else if (shape)
+            shape->strokeShape(context);
+    }
+
+    context->restore();
+}
+
+void RenderSVGResourceGradient::addStops(GradientData* gradientData, const Vector<Gradient::ColorStop>& stops) const
+{
+    ASSERT(gradientData->gradient);
+
+    const Vector<Gradient::ColorStop>::const_iterator end = stops.end();
+    for (Vector<Gradient::ColorStop>::const_iterator it = stops.begin(); it != end; ++it)
+        gradientData->gradient->addColorStop(*it);
+}
+
+GradientSpreadMethod RenderSVGResourceGradient::platformSpreadMethodFromSVGType(SVGSpreadMethodType method) const
+{
+    switch (method) {
+    case SVGSpreadMethodUnknown:
+    case SVGSpreadMethodPad:
+        return SpreadMethodPad;
+    case SVGSpreadMethodReflect:
+        return SpreadMethodReflect;
+    case SVGSpreadMethodRepeat:
+        return SpreadMethodRepeat;
+    }
+
+    ASSERT_NOT_REACHED();
+    return SpreadMethodPad;
+}
+
+}
+
+#endif
diff --git a/Source/core/rendering/svg/RenderSVGResourceGradient.h b/Source/core/rendering/svg/RenderSVGResourceGradient.h
new file mode 100644
index 0000000..fdd538a
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGResourceGradient.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) 2008 Eric Seidel <eric@webkit.org>
+ * Copyright (C) Research In Motion Limited 2010. 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 RenderSVGResourceGradient_h
+#define RenderSVGResourceGradient_h
+
+#if ENABLE(SVG)
+#include "core/platform/graphics/FloatRect.h"
+#include "core/platform/graphics/Gradient.h"
+#include "core/platform/graphics/ImageBuffer.h"
+#include "core/platform/graphics/transforms/AffineTransform.h"
+#include "core/rendering/svg/RenderSVGResourceContainer.h"
+#include "core/svg/SVGGradientElement.h"
+
+#include <wtf/HashMap.h>
+
+namespace WebCore {
+
+struct GradientData {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    RefPtr<Gradient> gradient;
+    AffineTransform userspaceTransform;
+};
+
+class GraphicsContext;
+
+class RenderSVGResourceGradient : public RenderSVGResourceContainer {
+public:
+    RenderSVGResourceGradient(SVGGradientElement*);
+
+    virtual void removeAllClientsFromCache(bool markForInvalidation = true) OVERRIDE FINAL;
+    virtual void removeClientFromCache(RenderObject*, bool markForInvalidation = true) OVERRIDE FINAL;
+
+    virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode) OVERRIDE FINAL;
+    virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short resourceMode, const Path*, const RenderSVGShape*) OVERRIDE FINAL;
+    virtual FloatRect resourceBoundingBox(RenderObject*) OVERRIDE FINAL { return FloatRect(); }
+
+protected:
+    void addStops(GradientData*, const Vector<Gradient::ColorStop>&) const;
+
+    virtual SVGUnitTypes::SVGUnitType gradientUnits() const = 0;
+    virtual void calculateGradientTransform(AffineTransform&) = 0;
+    virtual bool collectGradientAttributes(SVGGradientElement*) = 0;
+    virtual void buildGradient(GradientData*) const = 0;
+
+    GradientSpreadMethod platformSpreadMethodFromSVGType(SVGSpreadMethodType) const;
+
+private:
+    bool m_shouldCollectGradientAttributes : 1;
+    HashMap<RenderObject*, OwnPtr<GradientData> > m_gradientMap;
+};
+
+}
+
+#endif
+#endif
diff --git a/Source/core/rendering/svg/RenderSVGResourceLinearGradient.cpp b/Source/core/rendering/svg/RenderSVGResourceLinearGradient.cpp
new file mode 100644
index 0000000..8c3d704
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGResourceLinearGradient.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) Research In Motion Limited 2010. 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"
+
+#if ENABLE(SVG)
+#include "core/rendering/svg/RenderSVGResourceLinearGradient.h"
+
+#include "core/svg/LinearGradientAttributes.h"
+#include "core/svg/SVGLinearGradientElement.h"
+
+namespace WebCore {
+
+RenderSVGResourceType RenderSVGResourceLinearGradient::s_resourceType = LinearGradientResourceType;
+
+RenderSVGResourceLinearGradient::RenderSVGResourceLinearGradient(SVGLinearGradientElement* node)
+    : RenderSVGResourceGradient(node)
+{
+}
+
+RenderSVGResourceLinearGradient::~RenderSVGResourceLinearGradient()
+{
+}
+
+bool RenderSVGResourceLinearGradient::collectGradientAttributes(SVGGradientElement* gradientElement)
+{
+    m_attributes = LinearGradientAttributes();
+    return static_cast<SVGLinearGradientElement*>(gradientElement)->collectGradientAttributes(m_attributes);
+}
+
+FloatPoint RenderSVGResourceLinearGradient::startPoint(const LinearGradientAttributes& attributes) const
+{
+    return SVGLengthContext::resolvePoint(static_cast<const SVGElement*>(node()), attributes.gradientUnits(), attributes.x1(), attributes.y1());
+}
+
+FloatPoint RenderSVGResourceLinearGradient::endPoint(const LinearGradientAttributes& attributes) const
+{
+    return SVGLengthContext::resolvePoint(static_cast<const SVGElement*>(node()), attributes.gradientUnits(), attributes.x2(), attributes.y2());
+}
+
+void RenderSVGResourceLinearGradient::buildGradient(GradientData* gradientData) const
+{
+    gradientData->gradient = Gradient::create(startPoint(m_attributes), endPoint(m_attributes));
+    gradientData->gradient->setSpreadMethod(platformSpreadMethodFromSVGType(m_attributes.spreadMethod()));
+    addStops(gradientData, m_attributes.stops());
+}
+
+}
+
+#endif
diff --git a/Source/core/rendering/svg/RenderSVGResourceLinearGradient.h b/Source/core/rendering/svg/RenderSVGResourceLinearGradient.h
new file mode 100644
index 0000000..986a27d
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGResourceLinearGradient.h
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) Research In Motion Limited 2010. 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 RenderSVGResourceLinearGradient_h
+#define RenderSVGResourceLinearGradient_h
+
+#if ENABLE(SVG)
+#include "core/rendering/svg/RenderSVGResourceGradient.h"
+#include "core/svg/LinearGradientAttributes.h"
+
+namespace WebCore {
+
+class SVGLinearGradientElement;
+
+class RenderSVGResourceLinearGradient FINAL : public RenderSVGResourceGradient {
+public:
+    RenderSVGResourceLinearGradient(SVGLinearGradientElement*);
+    virtual ~RenderSVGResourceLinearGradient();
+
+    virtual const char* renderName() const { return "RenderSVGResourceLinearGradient"; }
+
+    virtual RenderSVGResourceType resourceType() const { return s_resourceType; }
+    static RenderSVGResourceType s_resourceType;
+
+    virtual SVGUnitTypes::SVGUnitType gradientUnits() const { return m_attributes.gradientUnits(); }
+    virtual void calculateGradientTransform(AffineTransform& transform) { transform = m_attributes.gradientTransform(); }
+    virtual bool collectGradientAttributes(SVGGradientElement*);
+    virtual void buildGradient(GradientData*) const;
+
+    FloatPoint startPoint(const LinearGradientAttributes&) const;
+    FloatPoint endPoint(const LinearGradientAttributes&) const;
+
+private:
+    LinearGradientAttributes m_attributes;
+};
+
+}
+
+#endif
+#endif
diff --git a/Source/core/rendering/svg/RenderSVGResourceMarker.cpp b/Source/core/rendering/svg/RenderSVGResourceMarker.cpp
new file mode 100644
index 0000000..bfc2676
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGResourceMarker.cpp
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Rob Buis <buis@kde.org>
+ * Copyright (C) Research In Motion Limited 2009-2010. 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"
+
+#if ENABLE(SVG)
+#include "core/rendering/svg/RenderSVGResourceMarker.h"
+
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/rendering/svg/RenderSVGContainer.h"
+#include "core/rendering/svg/RenderSVGRoot.h"
+#include "core/rendering/svg/SVGRenderSupport.h"
+#include "core/svg/SVGElement.h"
+#include "core/svg/SVGMarkerElement.h"
+#include "core/svg/SVGStyledElement.h"
+#include "core/svg/SVGStyledTransformableElement.h"
+
+namespace WebCore {
+
+RenderSVGResourceType RenderSVGResourceMarker::s_resourceType = MarkerResourceType;
+
+RenderSVGResourceMarker::RenderSVGResourceMarker(SVGMarkerElement* node)
+    : RenderSVGResourceContainer(node)
+{
+}
+
+RenderSVGResourceMarker::~RenderSVGResourceMarker()
+{
+}
+
+void RenderSVGResourceMarker::layout()
+{
+    StackStats::LayoutCheckPoint layoutCheckPoint;
+    // Invalidate all resources if our layout changed.
+    if (everHadLayout() && selfNeedsLayout())
+        RenderSVGRoot::addResourceForClientInvalidation(this);
+
+    // RenderSVGHiddenContainer overwrites layout(). We need the
+    // layouting of RenderSVGContainer for calculating  local
+    // transformations and repaint.
+    RenderSVGContainer::layout();
+}
+
+void RenderSVGResourceMarker::removeAllClientsFromCache(bool markForInvalidation)
+{
+    markAllClientsForInvalidation(markForInvalidation ? LayoutAndBoundariesInvalidation : ParentOnlyInvalidation);
+}
+
+void RenderSVGResourceMarker::removeClientFromCache(RenderObject* client, bool markForInvalidation)
+{
+    ASSERT(client);
+    markClientForInvalidation(client, markForInvalidation ? BoundariesInvalidation : ParentOnlyInvalidation);
+}
+
+void RenderSVGResourceMarker::applyViewportClip(PaintInfo& paintInfo)
+{
+    if (SVGRenderSupport::isOverflowHidden(this))
+        paintInfo.context->clip(m_viewport);
+}
+
+FloatRect RenderSVGResourceMarker::markerBoundaries(const AffineTransform& markerTransformation) const
+{
+    FloatRect coordinates = RenderSVGContainer::repaintRectInLocalCoordinates();
+
+    // Map repaint rect into parent coordinate space, in which the marker boundaries have to be evaluated
+    coordinates = localToParentTransform().mapRect(coordinates);
+
+    return markerTransformation.mapRect(coordinates);
+}
+
+const AffineTransform& RenderSVGResourceMarker::localToParentTransform() const
+{
+    m_localToParentTransform = AffineTransform::translation(m_viewport.x(), m_viewport.y()) * viewportTransform();
+    return m_localToParentTransform;
+    // If this class were ever given a localTransform(), then the above would read:
+    // return viewportTranslation * localTransform() * viewportTransform();
+}
+
+FloatPoint RenderSVGResourceMarker::referencePoint() const
+{
+    SVGMarkerElement* marker = static_cast<SVGMarkerElement*>(node());
+    ASSERT(marker);
+
+    SVGLengthContext lengthContext(marker);
+    return FloatPoint(marker->refX().value(lengthContext), marker->refY().value(lengthContext));
+}
+
+float RenderSVGResourceMarker::angle() const
+{
+    SVGMarkerElement* marker = static_cast<SVGMarkerElement*>(node());
+    ASSERT(marker);
+
+    float angle = -1;
+    if (marker->orientType() == SVGMarkerOrientAngle)
+        angle = marker->orientAngle().value();
+
+    return angle;
+}
+
+AffineTransform RenderSVGResourceMarker::markerTransformation(const FloatPoint& origin, float autoAngle, float strokeWidth) const
+{
+    SVGMarkerElement* marker = static_cast<SVGMarkerElement*>(node());
+    ASSERT(marker);
+
+    float markerAngle = angle();
+    bool useStrokeWidth = marker->markerUnits() == SVGMarkerUnitsStrokeWidth;
+
+    AffineTransform transform;
+    transform.translate(origin.x(), origin.y());
+    transform.rotate(markerAngle == -1 ? autoAngle : markerAngle);
+    transform = markerContentTransformation(transform, referencePoint(), useStrokeWidth ? strokeWidth : -1);
+    return transform;
+}
+
+void RenderSVGResourceMarker::draw(PaintInfo& paintInfo, const AffineTransform& transform)
+{
+    // An empty viewBox disables rendering.
+    SVGMarkerElement* marker = toSVGMarkerElement(toSVGElement(node()));
+    ASSERT(marker);
+    if (marker->hasAttribute(SVGNames::viewBoxAttr) && marker->viewBoxIsValid() && marker->viewBox().isEmpty())
+        return;
+
+    PaintInfo info(paintInfo);
+    GraphicsContextStateSaver stateSaver(*info.context);
+    info.applyTransform(transform);
+    RenderSVGContainer::paint(info, IntPoint());
+}
+
+AffineTransform RenderSVGResourceMarker::markerContentTransformation(const AffineTransform& contentTransformation, const FloatPoint& origin, float strokeWidth) const
+{
+    // The 'origin' coordinate maps to SVGs refX/refY, given in coordinates relative to the viewport established by the marker
+    FloatPoint mappedOrigin = viewportTransform().mapPoint(origin);
+
+    AffineTransform transformation = contentTransformation;
+    if (strokeWidth != -1)
+        transformation.scaleNonUniform(strokeWidth, strokeWidth);
+
+    transformation.translate(-mappedOrigin.x(), -mappedOrigin.y());
+    return transformation;
+}
+
+AffineTransform RenderSVGResourceMarker::viewportTransform() const
+{
+    SVGMarkerElement* marker = static_cast<SVGMarkerElement*>(node());
+    ASSERT(marker);
+
+    return marker->viewBoxToViewTransform(m_viewport.width(), m_viewport.height());
+}
+
+void RenderSVGResourceMarker::calcViewport()
+{
+    if (!selfNeedsLayout())
+        return;
+
+    SVGMarkerElement* marker = static_cast<SVGMarkerElement*>(node());
+    ASSERT(marker);
+    
+    SVGLengthContext lengthContext(marker);
+    float w = marker->markerWidth().value(lengthContext);
+    float h = marker->markerHeight().value(lengthContext);
+    m_viewport = FloatRect(0, 0, w, h);
+}
+
+}
+
+#endif // ENABLE(SVG)
diff --git a/Source/core/rendering/svg/RenderSVGResourceMarker.h b/Source/core/rendering/svg/RenderSVGResourceMarker.h
new file mode 100644
index 0000000..32c4ff4
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGResourceMarker.h
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) Research In Motion Limited 2009-2010. 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 RenderSVGResourceMarker_h
+#define RenderSVGResourceMarker_h
+
+#if ENABLE(SVG)
+#include "core/platform/graphics/FloatRect.h"
+#include "core/rendering/svg/RenderSVGResourceContainer.h"
+#include "core/svg/SVGMarkerElement.h"
+#include "core/svg/SVGStyledElement.h"
+
+#include <wtf/HashSet.h>
+
+namespace WebCore {
+
+class AffineTransform;
+class RenderObject;
+
+class RenderSVGResourceMarker FINAL : public RenderSVGResourceContainer {
+public:
+    RenderSVGResourceMarker(SVGMarkerElement*);
+    virtual ~RenderSVGResourceMarker();
+
+    virtual const char* renderName() const { return "RenderSVGResourceMarker"; }
+
+    virtual void removeAllClientsFromCache(bool markForInvalidation = true);
+    virtual void removeClientFromCache(RenderObject*, bool markForInvalidation = true);
+
+    void draw(PaintInfo&, const AffineTransform&);
+
+    // Calculates marker boundaries, mapped to the target element's coordinate space
+    FloatRect markerBoundaries(const AffineTransform& markerTransformation) const;
+
+    virtual void applyViewportClip(PaintInfo&);
+    virtual void layout();
+    virtual void calcViewport();
+
+    virtual const AffineTransform& localToParentTransform() const;
+    AffineTransform markerTransformation(const FloatPoint& origin, float angle, float strokeWidth) const;
+
+    virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short) { return false; }
+    virtual FloatRect resourceBoundingBox(RenderObject*) { return FloatRect(); }
+
+    FloatPoint referencePoint() const;
+    float angle() const;
+    SVGMarkerUnitsType markerUnits() const { return static_cast<SVGMarkerElement*>(node())->markerUnits(); }
+
+    virtual RenderSVGResourceType resourceType() const { return s_resourceType; }
+    static RenderSVGResourceType s_resourceType;
+
+private:
+    // Generates a transformation matrix usable to render marker content. Handles scaling the marker content
+    // acording to SVGs markerUnits="strokeWidth" concept, when a strokeWidth value != -1 is passed in.
+    AffineTransform markerContentTransformation(const AffineTransform& contentTransformation, const FloatPoint& origin, float strokeWidth = -1) const;
+
+    AffineTransform viewportTransform() const;
+
+    mutable AffineTransform m_localToParentTransform;
+    FloatRect m_viewport;
+};
+
+}
+#endif
+
+#endif
diff --git a/Source/core/rendering/svg/RenderSVGResourceMasker.cpp b/Source/core/rendering/svg/RenderSVGResourceMasker.cpp
new file mode 100644
index 0000000..fe6bc61
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGResourceMasker.cpp
@@ -0,0 +1,203 @@
+/*
+ * Copyright (C) Research In Motion Limited 2009-2010. 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"
+
+#if ENABLE(SVG)
+#include "core/rendering/svg/RenderSVGResourceMasker.h"
+
+#include "core/dom/Element.h"
+#include "core/platform/graphics/FloatPoint.h"
+#include "core/platform/graphics/FloatRect.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/platform/graphics/Image.h"
+#include "core/platform/graphics/ImageBuffer.h"
+#include "core/platform/graphics/IntRect.h"
+#include "core/platform/graphics/transforms/AffineTransform.h"
+#include "core/rendering/svg/RenderSVGResource.h"
+#include "core/rendering/svg/SVGRenderingContext.h"
+#include "core/svg/SVGElement.h"
+#include "core/svg/SVGMaskElement.h"
+#include "core/svg/SVGStyledElement.h"
+#include "core/svg/SVGUnitTypes.h"
+
+#include <wtf/UnusedParam.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+RenderSVGResourceType RenderSVGResourceMasker::s_resourceType = MaskerResourceType;
+
+RenderSVGResourceMasker::RenderSVGResourceMasker(SVGMaskElement* node)
+    : RenderSVGResourceContainer(node)
+{
+}
+
+RenderSVGResourceMasker::~RenderSVGResourceMasker()
+{
+    if (m_masker.isEmpty())
+        return;
+
+    deleteAllValues(m_masker);
+    m_masker.clear();
+}
+
+void RenderSVGResourceMasker::removeAllClientsFromCache(bool markForInvalidation)
+{
+    m_maskContentBoundaries = FloatRect();
+    if (!m_masker.isEmpty()) {
+        deleteAllValues(m_masker);
+        m_masker.clear();
+    }
+
+    markAllClientsForInvalidation(markForInvalidation ? LayoutAndBoundariesInvalidation : ParentOnlyInvalidation);
+}
+
+void RenderSVGResourceMasker::removeClientFromCache(RenderObject* client, bool markForInvalidation)
+{
+    ASSERT(client);
+
+    if (m_masker.contains(client))
+        delete m_masker.take(client);
+
+    markClientForInvalidation(client, markForInvalidation ? BoundariesInvalidation : ParentOnlyInvalidation);
+}
+
+bool RenderSVGResourceMasker::applyResource(RenderObject* object, RenderStyle*, GraphicsContext*& context, unsigned short resourceMode)
+{
+    ASSERT(object);
+    ASSERT(context);
+    ASSERT_UNUSED(resourceMode, resourceMode == ApplyToDefaultMode);
+
+    bool missingMaskerData = !m_masker.contains(object);
+    if (missingMaskerData)
+        m_masker.set(object, new MaskerData);
+
+    MaskerData* maskerData = m_masker.get(object);
+
+    AffineTransform absoluteTransform;
+    SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(object, absoluteTransform);
+
+    FloatRect repaintRect = object->repaintRectInLocalCoordinates();
+
+    if (!maskerData->maskImage && !repaintRect.isEmpty()) {
+        SVGMaskElement* maskElement = static_cast<SVGMaskElement*>(node());
+        if (!maskElement)
+            return false;
+
+        ASSERT(style());
+        const SVGRenderStyle* svgStyle = style()->svgStyle();
+        ASSERT(svgStyle);
+        ColorSpace colorSpace = svgStyle->colorInterpolation() == CI_LINEARRGB ? ColorSpaceLinearRGB : ColorSpaceDeviceRGB;
+        if (!SVGRenderingContext::createImageBuffer(repaintRect, absoluteTransform, maskerData->maskImage, colorSpace, Unaccelerated))
+            return false;
+
+        if (!drawContentIntoMaskImage(maskerData, colorSpace, maskElement, object)) {
+            maskerData->maskImage.clear();
+        }
+    }
+
+    if (!maskerData->maskImage)
+        return false;
+
+    SVGRenderingContext::clipToImageBuffer(context, absoluteTransform, repaintRect, maskerData->maskImage, missingMaskerData);
+    return true;
+}
+
+bool RenderSVGResourceMasker::drawContentIntoMaskImage(MaskerData* maskerData, ColorSpace colorSpace, const SVGMaskElement* maskElement, RenderObject* object)
+{
+    GraphicsContext* maskImageContext = maskerData->maskImage->context();
+    ASSERT(maskImageContext);
+
+    // Eventually adjust the mask image context according to the target objectBoundingBox.
+    AffineTransform maskContentTransformation;
+    if (maskElement->maskContentUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
+        FloatRect objectBoundingBox = object->objectBoundingBox();
+        maskContentTransformation.translate(objectBoundingBox.x(), objectBoundingBox.y());
+        maskContentTransformation.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.height());
+        maskImageContext->concatCTM(maskContentTransformation);
+    }
+
+    // Draw the content into the ImageBuffer.
+    for (Node* node = maskElement->firstChild(); node; node = node->nextSibling()) {
+        RenderObject* renderer = node->renderer();
+        if (!node->isSVGElement() || !toSVGElement(node)->isSVGStyledElement() || !renderer)
+            continue;
+        if (renderer->needsLayout())
+            return false;
+        RenderStyle* style = renderer->style();
+        if (!style || style->display() == NONE || style->visibility() != VISIBLE)
+            continue;
+        SVGRenderingContext::renderSubtreeToImageBuffer(maskerData->maskImage.get(), renderer, maskContentTransformation);
+    }
+
+    maskerData->maskImage->transformColorSpace(ColorSpaceDeviceRGB, colorSpace);
+
+    ASSERT(style());
+    ASSERT(style()->svgStyle());
+    // Create the luminance mask.
+    if (style()->svgStyle()->maskType() == MT_LUMINANCE)
+        maskerData->maskImage->convertToLuminanceMask();
+
+    return true;
+}
+
+void RenderSVGResourceMasker::calculateMaskContentRepaintRect()
+{
+    for (Node* childNode = node()->firstChild(); childNode; childNode = childNode->nextSibling()) {
+        RenderObject* renderer = childNode->renderer();
+        if (!childNode->isSVGElement() || !toSVGElement(childNode)->isSVGStyledElement() || !renderer)
+            continue;
+        RenderStyle* style = renderer->style();
+        if (!style || style->display() == NONE || style->visibility() != VISIBLE)
+             continue;
+        m_maskContentBoundaries.unite(renderer->localToParentTransform().mapRect(renderer->repaintRectInLocalCoordinates()));
+    }
+}
+
+FloatRect RenderSVGResourceMasker::resourceBoundingBox(RenderObject* object)
+{
+    SVGMaskElement* maskElement = static_cast<SVGMaskElement*>(node());
+    ASSERT(maskElement);
+
+    FloatRect objectBoundingBox = object->objectBoundingBox();
+    FloatRect maskBoundaries = SVGLengthContext::resolveRectangle<SVGMaskElement>(maskElement, maskElement->maskUnits(), objectBoundingBox);
+
+    // Resource was not layouted yet. Give back clipping rect of the mask.
+    if (selfNeedsLayout())
+        return maskBoundaries;
+
+    if (m_maskContentBoundaries.isEmpty())
+        calculateMaskContentRepaintRect();
+
+    FloatRect maskRect = m_maskContentBoundaries;
+    if (maskElement->maskContentUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX) {
+        AffineTransform transform;
+        transform.translate(objectBoundingBox.x(), objectBoundingBox.y());
+        transform.scaleNonUniform(objectBoundingBox.width(), objectBoundingBox.height());
+        maskRect = transform.mapRect(maskRect);
+    }
+
+    maskRect.intersect(maskBoundaries);
+    return maskRect;
+}
+
+}
+
+#endif // ENABLE(SVG)
diff --git a/Source/core/rendering/svg/RenderSVGResourceMasker.h b/Source/core/rendering/svg/RenderSVGResourceMasker.h
new file mode 100644
index 0000000..7802db4
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGResourceMasker.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) Research In Motion Limited 2009-2010. 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 RenderSVGResourceMasker_h
+#define RenderSVGResourceMasker_h
+
+#if ENABLE(SVG)
+#include "core/platform/graphics/FloatRect.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/platform/graphics/ImageBuffer.h"
+#include "core/platform/graphics/IntSize.h"
+#include "core/rendering/svg/RenderSVGResourceContainer.h"
+#include "core/svg/SVGMaskElement.h"
+#include "core/svg/SVGUnitTypes.h"
+
+#include <wtf/HashMap.h>
+#include <wtf/OwnPtr.h>
+
+namespace WebCore {
+
+struct MaskerData {
+    OwnPtr<ImageBuffer> maskImage;
+};
+
+class RenderSVGResourceMasker FINAL : public RenderSVGResourceContainer {
+public:
+    RenderSVGResourceMasker(SVGMaskElement*);
+    virtual ~RenderSVGResourceMasker();
+
+    virtual const char* renderName() const { return "RenderSVGResourceMasker"; }
+
+    virtual void removeAllClientsFromCache(bool markForInvalidation = true);
+    virtual void removeClientFromCache(RenderObject*, bool markForInvalidation = true);
+    virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode);
+    virtual FloatRect resourceBoundingBox(RenderObject*);
+
+    SVGUnitTypes::SVGUnitType maskUnits() const { return static_cast<SVGMaskElement*>(node())->maskUnits(); }
+    SVGUnitTypes::SVGUnitType maskContentUnits() const { return static_cast<SVGMaskElement*>(node())->maskContentUnits(); }
+
+    virtual RenderSVGResourceType resourceType() const { return s_resourceType; }
+    static RenderSVGResourceType s_resourceType;
+
+private:
+    bool drawContentIntoMaskImage(MaskerData*, ColorSpace, const SVGMaskElement*, RenderObject*);
+    void calculateMaskContentRepaintRect();
+
+    FloatRect m_maskContentBoundaries;
+    HashMap<RenderObject*, MaskerData*> m_masker;
+};
+
+}
+
+#endif
+#endif
diff --git a/Source/core/rendering/svg/RenderSVGResourcePattern.cpp b/Source/core/rendering/svg/RenderSVGResourcePattern.cpp
new file mode 100644
index 0000000..8d0d399
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGResourcePattern.cpp
@@ -0,0 +1,279 @@
+/*
+ * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) Research In Motion Limited 2010. 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"
+
+#if ENABLE(SVG)
+#include "core/rendering/svg/RenderSVGResourcePattern.h"
+
+#include "core/page/FrameView.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/rendering/svg/RenderSVGRoot.h"
+#include "core/rendering/svg/SVGRenderSupport.h"
+#include "core/rendering/svg/SVGRenderingContext.h"
+#include "core/svg/PatternAttributes.h"
+#include "core/svg/SVGFitToViewBox.h"
+
+namespace WebCore {
+
+RenderSVGResourceType RenderSVGResourcePattern::s_resourceType = PatternResourceType;
+
+RenderSVGResourcePattern::RenderSVGResourcePattern(SVGPatternElement* node)
+    : RenderSVGResourceContainer(node)
+    , m_shouldCollectPatternAttributes(true)
+{
+}
+
+void RenderSVGResourcePattern::removeAllClientsFromCache(bool markForInvalidation)
+{
+    m_patternMap.clear();
+    m_shouldCollectPatternAttributes = true;
+    markAllClientsForInvalidation(markForInvalidation ? RepaintInvalidation : ParentOnlyInvalidation);
+}
+
+void RenderSVGResourcePattern::removeClientFromCache(RenderObject* client, bool markForInvalidation)
+{
+    ASSERT(client);
+    m_patternMap.remove(client);
+    markClientForInvalidation(client, markForInvalidation ? RepaintInvalidation : ParentOnlyInvalidation);
+}
+
+PatternData* RenderSVGResourcePattern::buildPattern(RenderObject* object, unsigned short resourceMode)
+{
+    PatternData* currentData = m_patternMap.get(object);
+    if (currentData && currentData->pattern)
+        return currentData;
+
+    SVGPatternElement* patternElement = static_cast<SVGPatternElement*>(node());
+    if (!patternElement)
+        return 0;
+
+    if (m_shouldCollectPatternAttributes) {
+        patternElement->synchronizeAnimatedSVGAttribute(anyQName());
+
+        m_attributes = PatternAttributes();
+        patternElement->collectPatternAttributes(m_attributes);
+        m_shouldCollectPatternAttributes = false;
+    }
+
+    // If we couldn't determine the pattern content element root, stop here.
+    if (!m_attributes.patternContentElement())
+        return 0;
+
+    // An empty viewBox disables rendering.
+    if (m_attributes.hasViewBox() && m_attributes.viewBox().isEmpty())
+        return 0;
+
+    // Compute all necessary transformations to build the tile image & the pattern.
+    FloatRect tileBoundaries;
+    AffineTransform tileImageTransform;
+    if (!buildTileImageTransform(object, m_attributes, patternElement, tileBoundaries, tileImageTransform))
+        return 0;
+
+    AffineTransform absoluteTransformIgnoringRotation;
+    SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(object, absoluteTransformIgnoringRotation);
+
+    // Ignore 2D rotation, as it doesn't affect the size of the tile.
+    SVGRenderingContext::clear2DRotation(absoluteTransformIgnoringRotation);
+    FloatRect absoluteTileBoundaries = absoluteTransformIgnoringRotation.mapRect(tileBoundaries);
+    FloatRect clampedAbsoluteTileBoundaries;
+
+    // Scale the tile size to match the scale level of the patternTransform.
+    absoluteTileBoundaries.scale(static_cast<float>(m_attributes.patternTransform().xScale()),
+        static_cast<float>(m_attributes.patternTransform().yScale()));
+
+    // Build tile image.
+    OwnPtr<ImageBuffer> tileImage = createTileImage(m_attributes, tileBoundaries, absoluteTileBoundaries, tileImageTransform, clampedAbsoluteTileBoundaries);
+    if (!tileImage)
+        return 0;
+
+    RefPtr<Image> copiedImage = tileImage->copyImage(CopyBackingStore);
+    if (!copiedImage)
+        return 0;
+
+    // Build pattern.
+    OwnPtr<PatternData> patternData = adoptPtr(new PatternData);
+    patternData->pattern = Pattern::create(copiedImage, true, true);
+
+    // Compute pattern space transformation.
+    const IntSize tileImageSize = tileImage->logicalSize();
+    patternData->transform.translate(tileBoundaries.x(), tileBoundaries.y());
+    patternData->transform.scale(tileBoundaries.width() / tileImageSize.width(), tileBoundaries.height() / tileImageSize.height());
+
+    AffineTransform patternTransform = m_attributes.patternTransform();
+    if (!patternTransform.isIdentity())
+        patternData->transform = patternTransform * patternData->transform;
+
+    // Account for text drawing resetting the context to non-scaled, see SVGInlineTextBox::paintTextWithShadows.
+    if (resourceMode & ApplyToTextMode) {
+        AffineTransform additionalTextTransformation;
+        if (shouldTransformOnTextPainting(object, additionalTextTransformation))
+            patternData->transform *= additionalTextTransformation;
+    }
+    patternData->pattern->setPatternSpaceTransform(patternData->transform);
+
+    // Various calls above may trigger invalidations in some fringe cases (ImageBuffer allocation
+    // failures in the SVG image cache for example). To avoid having our PatternData deleted by
+    // removeAllClientsFromCache(), we only make it visible in the cache at the very end.
+    return m_patternMap.set(object, patternData.release()).iterator->value.get();
+}
+
+bool RenderSVGResourcePattern::applyResource(RenderObject* object, RenderStyle* style, GraphicsContext*& context, unsigned short resourceMode)
+{
+    ASSERT(object);
+    ASSERT(style);
+    ASSERT(context);
+    ASSERT(resourceMode != ApplyToDefaultMode);
+
+    // Spec: When the geometry of the applicable element has no width or height and objectBoundingBox is specified,
+    // then the given effect (e.g. a gradient or a filter) will be ignored.
+    FloatRect objectBoundingBox = object->objectBoundingBox();
+    if (m_attributes.patternUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX && objectBoundingBox.isEmpty())
+        return false;
+
+    PatternData* patternData = buildPattern(object, resourceMode);
+    if (!patternData)
+        return false;
+
+    // Draw pattern
+    context->save();
+
+    const SVGRenderStyle* svgStyle = style->svgStyle();
+    ASSERT(svgStyle);
+
+    if (resourceMode & ApplyToFillMode) {
+        context->setAlpha(svgStyle->fillOpacity());
+        context->setFillPattern(patternData->pattern);
+        context->setFillRule(svgStyle->fillRule());
+    } else if (resourceMode & ApplyToStrokeMode) {
+        if (svgStyle->vectorEffect() == VE_NON_SCALING_STROKE)
+            patternData->pattern->setPatternSpaceTransform(transformOnNonScalingStroke(object, patternData->transform));
+        context->setAlpha(svgStyle->strokeOpacity());
+        context->setStrokePattern(patternData->pattern);
+        SVGRenderSupport::applyStrokeStyleToContext(context, style, object);
+    }
+
+    if (resourceMode & ApplyToTextMode) {
+        if (resourceMode & ApplyToFillMode)
+            context->setTextDrawingMode(TextModeFill);
+        else if (resourceMode & ApplyToStrokeMode)
+            context->setTextDrawingMode(TextModeStroke);
+    }
+
+    return true;
+}
+
+void RenderSVGResourcePattern::postApplyResource(RenderObject*, GraphicsContext*& context, unsigned short resourceMode, const Path* path, const RenderSVGShape* shape)
+{
+    ASSERT(context);
+    ASSERT(resourceMode != ApplyToDefaultMode);
+
+    if (resourceMode & ApplyToFillMode) {
+        if (path)
+            context->fillPath(*path);
+        else if (shape)
+            shape->fillShape(context);
+    }
+    if (resourceMode & ApplyToStrokeMode) {
+        if (path)
+            context->strokePath(*path);
+        else if (shape)
+            shape->strokeShape(context);
+    }
+
+    context->restore();
+}
+
+static inline FloatRect calculatePatternBoundaries(const PatternAttributes& attributes,
+                                                   const FloatRect& objectBoundingBox,
+                                                   const SVGPatternElement* patternElement)
+{
+    ASSERT(patternElement);
+    return SVGLengthContext::resolveRectangle(patternElement, attributes.patternUnits(), objectBoundingBox, attributes.x(), attributes.y(), attributes.width(), attributes.height());
+}
+
+bool RenderSVGResourcePattern::buildTileImageTransform(RenderObject* renderer,
+                                                       const PatternAttributes& attributes,
+                                                       const SVGPatternElement* patternElement,
+                                                       FloatRect& patternBoundaries,
+                                                       AffineTransform& tileImageTransform) const
+{
+    ASSERT(renderer);
+    ASSERT(patternElement);
+
+    FloatRect objectBoundingBox = renderer->objectBoundingBox();
+    patternBoundaries = calculatePatternBoundaries(attributes, objectBoundingBox, patternElement); 
+    if (patternBoundaries.width() <= 0 || patternBoundaries.height() <= 0)
+        return false;
+
+    AffineTransform viewBoxCTM = SVGFitToViewBox::viewBoxToViewTransform(attributes.viewBox(), attributes.preserveAspectRatio(), patternBoundaries.width(), patternBoundaries.height());
+
+    // Apply viewBox/objectBoundingBox transformations.
+    if (!viewBoxCTM.isIdentity())
+        tileImageTransform = viewBoxCTM;
+    else if (attributes.patternContentUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX)
+        tileImageTransform.scale(objectBoundingBox.width(), objectBoundingBox.height());
+
+    return true;
+}
+
+PassOwnPtr<ImageBuffer> RenderSVGResourcePattern::createTileImage(const PatternAttributes& attributes,
+                                                                  const FloatRect& tileBoundaries,
+                                                                  const FloatRect& absoluteTileBoundaries,
+                                                                  const AffineTransform& tileImageTransform,
+                                                                  FloatRect& clampedAbsoluteTileBoundaries) const
+{
+    clampedAbsoluteTileBoundaries = SVGRenderingContext::clampedAbsoluteTargetRect(absoluteTileBoundaries);
+
+    OwnPtr<ImageBuffer> tileImage;
+
+    if (!SVGRenderingContext::createImageBufferForPattern(absoluteTileBoundaries, clampedAbsoluteTileBoundaries, tileImage, ColorSpaceDeviceRGB, Unaccelerated))
+        return nullptr;
+
+    GraphicsContext* tileImageContext = tileImage->context();
+    ASSERT(tileImageContext);
+
+    // The image buffer represents the final rendered size, so the content has to be scaled (to avoid pixelation).
+    tileImageContext->scale(FloatSize(clampedAbsoluteTileBoundaries.width() / tileBoundaries.width(),
+                                      clampedAbsoluteTileBoundaries.height() / tileBoundaries.height()));
+
+    // Apply tile image transformations.
+    if (!tileImageTransform.isIdentity())
+        tileImageContext->concatCTM(tileImageTransform);
+
+    AffineTransform contentTransformation;
+    if (attributes.patternContentUnits() == SVGUnitTypes::SVG_UNIT_TYPE_OBJECTBOUNDINGBOX)
+        contentTransformation = tileImageTransform;
+
+    // Draw the content into the ImageBuffer.
+    for (Node* node = attributes.patternContentElement()->firstChild(); node; node = node->nextSibling()) {
+        if (!node->isSVGElement() || !toSVGElement(node)->isSVGStyledElement() || !node->renderer())
+            continue;
+        if (node->renderer()->needsLayout())
+            return nullptr;
+        SVGRenderingContext::renderSubtreeToImageBuffer(tileImage.get(), node->renderer(), contentTransformation);
+    }
+
+    return tileImage.release();
+}
+
+}
+
+#endif
diff --git a/Source/core/rendering/svg/RenderSVGResourcePattern.h b/Source/core/rendering/svg/RenderSVGResourcePattern.h
new file mode 100644
index 0000000..3e368ea
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGResourcePattern.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) Research In Motion Limited 2010. 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 RenderSVGResourcePattern_h
+#define RenderSVGResourcePattern_h
+
+#if ENABLE(SVG)
+#include "core/platform/graphics/FloatRect.h"
+#include "core/platform/graphics/ImageBuffer.h"
+#include "core/platform/graphics/Pattern.h"
+#include "core/platform/graphics/transforms/AffineTransform.h"
+#include "core/rendering/svg/RenderSVGResourceContainer.h"
+#include "core/svg/PatternAttributes.h"
+#include "core/svg/SVGPatternElement.h"
+#include "core/svg/SVGUnitTypes.h"
+
+#include <wtf/HashMap.h>
+#include <wtf/OwnPtr.h>
+
+namespace WebCore {
+
+struct PatternData {
+    WTF_MAKE_FAST_ALLOCATED;
+public:
+    RefPtr<Pattern> pattern;
+    AffineTransform transform;
+};
+
+class RenderSVGResourcePattern FINAL : public RenderSVGResourceContainer {
+public:
+    RenderSVGResourcePattern(SVGPatternElement*);
+
+    virtual const char* renderName() const { return "RenderSVGResourcePattern"; }
+
+    virtual void removeAllClientsFromCache(bool markForInvalidation = true);
+    virtual void removeClientFromCache(RenderObject*, bool markForInvalidation = true);
+
+    virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode);
+    virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short resourceMode, const Path*, const RenderSVGShape*);
+    virtual FloatRect resourceBoundingBox(RenderObject*) { return FloatRect(); }
+
+    virtual RenderSVGResourceType resourceType() const { return s_resourceType; }
+    static RenderSVGResourceType s_resourceType;
+
+private:
+    bool buildTileImageTransform(RenderObject*, const PatternAttributes&, const SVGPatternElement*, FloatRect& patternBoundaries, AffineTransform& tileImageTransform) const;
+
+    PassOwnPtr<ImageBuffer> createTileImage(const PatternAttributes&, const FloatRect& tileBoundaries,
+                                            const FloatRect& absoluteTileBoundaries, const AffineTransform& tileImageTransform,
+                                            FloatRect& clampedAbsoluteTileBoundaries) const;
+
+    PatternData* buildPattern(RenderObject*, unsigned short resourceMode);
+
+    bool m_shouldCollectPatternAttributes : 1;
+    PatternAttributes m_attributes;
+    HashMap<RenderObject*, OwnPtr<PatternData> > m_patternMap;
+};
+
+}
+
+#endif
+#endif
diff --git a/Source/core/rendering/svg/RenderSVGResourceRadialGradient.cpp b/Source/core/rendering/svg/RenderSVGResourceRadialGradient.cpp
new file mode 100644
index 0000000..c401c26
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGResourceRadialGradient.cpp
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) Research In Motion Limited 2010. All rights reserved.
+ * Copyright (C) 2012 Adobe Systems Incorporated. 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"
+
+#if ENABLE(SVG)
+#include "core/rendering/svg/RenderSVGResourceRadialGradient.h"
+
+#include "core/svg/RadialGradientAttributes.h"
+#include "core/svg/SVGRadialGradientElement.h"
+
+namespace WebCore {
+
+RenderSVGResourceType RenderSVGResourceRadialGradient::s_resourceType = RadialGradientResourceType;
+
+RenderSVGResourceRadialGradient::RenderSVGResourceRadialGradient(SVGRadialGradientElement* node)
+    : RenderSVGResourceGradient(node)
+{
+}
+
+RenderSVGResourceRadialGradient::~RenderSVGResourceRadialGradient()
+{
+}
+
+bool RenderSVGResourceRadialGradient::collectGradientAttributes(SVGGradientElement* gradientElement)
+{
+    m_attributes = RadialGradientAttributes();
+    return static_cast<SVGRadialGradientElement*>(gradientElement)->collectGradientAttributes(m_attributes);
+}
+
+FloatPoint RenderSVGResourceRadialGradient::centerPoint(const RadialGradientAttributes& attributes) const
+{
+    return SVGLengthContext::resolvePoint(static_cast<const SVGElement*>(node()), attributes.gradientUnits(), attributes.cx(), attributes.cy());
+}
+
+FloatPoint RenderSVGResourceRadialGradient::focalPoint(const RadialGradientAttributes& attributes) const
+{
+    return SVGLengthContext::resolvePoint(static_cast<const SVGElement*>(node()), attributes.gradientUnits(), attributes.fx(), attributes.fy());
+}
+
+float RenderSVGResourceRadialGradient::radius(const RadialGradientAttributes& attributes) const
+{
+    return SVGLengthContext::resolveLength(static_cast<const SVGElement*>(node()), attributes.gradientUnits(), attributes.r());
+}
+
+float RenderSVGResourceRadialGradient::focalRadius(const RadialGradientAttributes& attributes) const
+{
+    return SVGLengthContext::resolveLength(static_cast<const SVGElement*>(node()), attributes.gradientUnits(), attributes.fr());
+}
+
+void RenderSVGResourceRadialGradient::buildGradient(GradientData* gradientData) const
+{
+    gradientData->gradient = Gradient::create(this->focalPoint(m_attributes),
+        this->focalRadius(m_attributes),
+        this->centerPoint(m_attributes),
+        this->radius(m_attributes));
+
+    gradientData->gradient->setSpreadMethod(platformSpreadMethodFromSVGType(m_attributes.spreadMethod()));
+
+    addStops(gradientData, m_attributes.stops());
+}
+
+}
+
+#endif
diff --git a/Source/core/rendering/svg/RenderSVGResourceRadialGradient.h b/Source/core/rendering/svg/RenderSVGResourceRadialGradient.h
new file mode 100644
index 0000000..8d19284
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGResourceRadialGradient.h
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) Research In Motion Limited 2010. 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 RenderSVGResourceRadialGradient_h
+#define RenderSVGResourceRadialGradient_h
+
+#if ENABLE(SVG)
+#include "core/rendering/svg/RenderSVGResourceGradient.h"
+#include "core/svg/RadialGradientAttributes.h"
+
+namespace WebCore {
+
+class SVGRadialGradientElement;
+
+class RenderSVGResourceRadialGradient FINAL : public RenderSVGResourceGradient {
+public:
+    RenderSVGResourceRadialGradient(SVGRadialGradientElement*);
+    virtual ~RenderSVGResourceRadialGradient();
+
+    virtual const char* renderName() const { return "RenderSVGResourceRadialGradient"; }
+
+    virtual RenderSVGResourceType resourceType() const { return s_resourceType; }
+    static RenderSVGResourceType s_resourceType;
+
+    virtual SVGUnitTypes::SVGUnitType gradientUnits() const { return m_attributes.gradientUnits(); }
+    virtual void calculateGradientTransform(AffineTransform& transform) { transform = m_attributes.gradientTransform(); }
+    virtual bool collectGradientAttributes(SVGGradientElement*);
+    virtual void buildGradient(GradientData*) const;
+
+    FloatPoint centerPoint(const RadialGradientAttributes&) const;
+    FloatPoint focalPoint(const RadialGradientAttributes&) const;
+    float radius(const RadialGradientAttributes&) const;
+    float focalRadius(const RadialGradientAttributes&) const;
+
+private:
+    RadialGradientAttributes m_attributes;
+};
+
+}
+
+#endif
+#endif
diff --git a/Source/core/rendering/svg/RenderSVGResourceSolidColor.cpp b/Source/core/rendering/svg/RenderSVGResourceSolidColor.cpp
new file mode 100644
index 0000000..eb33ae9
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGResourceSolidColor.cpp
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) Research In Motion Limited 2010. 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"
+
+#if ENABLE(SVG)
+#include "core/rendering/svg/RenderSVGResourceSolidColor.h"
+
+#include "core/page/Frame.h"
+#include "core/page/FrameView.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/platform/graphics/skia/PlatformContextSkia.h"
+#include "core/rendering/style/RenderStyle.h"
+#include "core/rendering/svg/RenderSVGShape.h"
+#include "core/rendering/svg/SVGRenderSupport.h"
+
+namespace WebCore {
+
+RenderSVGResourceType RenderSVGResourceSolidColor::s_resourceType = SolidColorResourceType;
+
+RenderSVGResourceSolidColor::RenderSVGResourceSolidColor()
+{
+}
+
+RenderSVGResourceSolidColor::~RenderSVGResourceSolidColor()
+{
+}
+
+bool RenderSVGResourceSolidColor::applyResource(RenderObject* object, RenderStyle* style, GraphicsContext*& context, unsigned short resourceMode)
+{
+    // We are NOT allowed to ASSERT(object) here, unlike all other resources.
+    // RenderSVGResourceSolidColor is the only resource which may be used from HTML, when rendering
+    // SVG Fonts for a HTML document. This will be indicated by a null RenderObject pointer.
+    ASSERT(context);
+    ASSERT(resourceMode != ApplyToDefaultMode);
+
+    const SVGRenderStyle* svgStyle = style ? style->svgStyle() : 0;
+    ColorSpace colorSpace = style ? style->colorSpace() : ColorSpaceDeviceRGB;
+
+    bool isRenderingMask = false;
+    if (object->frame() && object->frame()->view())
+        isRenderingMask = object->frame()->view()->paintBehavior() & PaintBehaviorRenderingSVGMask;
+
+    if (resourceMode & ApplyToFillMode) {
+        if (!isRenderingMask && svgStyle)
+            context->setAlpha(svgStyle->fillOpacity());
+        else
+            context->setAlpha(1);
+        context->setFillColor(m_color, colorSpace);
+        if (!isRenderingMask)
+            context->setFillRule(svgStyle ? svgStyle->fillRule() : RULE_NONZERO);
+
+        if (resourceMode & ApplyToTextMode)
+            context->setTextDrawingMode(TextModeFill);
+    } else if (resourceMode & ApplyToStrokeMode) {
+        // When rendering the mask for a RenderSVGResourceClipper, the stroke code path is never hit.
+        ASSERT(!isRenderingMask);
+        context->setAlpha(svgStyle ? svgStyle->strokeOpacity() : 1);
+        context->setStrokeColor(m_color, colorSpace);
+
+        if (style)
+            SVGRenderSupport::applyStrokeStyleToContext(context, style, object);
+
+        if (resourceMode & ApplyToTextMode)
+            context->setTextDrawingMode(TextModeStroke);
+    }
+
+    return true;
+}
+
+void RenderSVGResourceSolidColor::postApplyResource(RenderObject*, GraphicsContext*& context, unsigned short resourceMode, const Path* path, const RenderSVGShape* shape)
+{
+    ASSERT(context);
+    ASSERT(resourceMode != ApplyToDefaultMode);
+
+    if (resourceMode & ApplyToFillMode) {
+        if (path)
+            context->fillPath(*path);
+        else if (shape)
+            shape->fillShape(context);
+    }
+    if (resourceMode & ApplyToStrokeMode) {
+        if (path)
+            context->strokePath(*path);
+        else if (shape)
+            shape->strokeShape(context);
+    }
+}
+
+}
+
+#endif
diff --git a/Source/core/rendering/svg/RenderSVGResourceSolidColor.h b/Source/core/rendering/svg/RenderSVGResourceSolidColor.h
new file mode 100644
index 0000000..abb9e36
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGResourceSolidColor.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) Research In Motion Limited 2010. 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 RenderSVGResourceSolidColor_h
+#define RenderSVGResourceSolidColor_h
+
+#if ENABLE(SVG)
+#include "core/platform/graphics/Color.h"
+#include "core/platform/graphics/FloatRect.h"
+#include "core/rendering/svg/RenderSVGResource.h"
+
+namespace WebCore {
+
+class RenderSVGResourceSolidColor : public RenderSVGResource {
+public:
+    RenderSVGResourceSolidColor();
+    virtual ~RenderSVGResourceSolidColor();
+
+    virtual void removeAllClientsFromCache(bool = true) { }
+    virtual void removeClientFromCache(RenderObject*, bool = true) { }
+
+    virtual bool applyResource(RenderObject*, RenderStyle*, GraphicsContext*&, unsigned short resourceMode);
+    virtual void postApplyResource(RenderObject*, GraphicsContext*&, unsigned short resourceMode, const Path*, const RenderSVGShape*);
+    virtual FloatRect resourceBoundingBox(RenderObject*) { return FloatRect(); }
+
+    virtual RenderSVGResourceType resourceType() const { return s_resourceType; }
+    static RenderSVGResourceType s_resourceType;
+
+    const Color& color() const { return m_color; }
+    void setColor(const Color& color) { m_color = color; }
+
+private:
+    Color m_color;
+};
+
+}
+
+#endif
+#endif
diff --git a/Source/core/rendering/svg/RenderSVGRoot.cpp b/Source/core/rendering/svg/RenderSVGRoot.cpp
new file mode 100644
index 0000000..3e5dc0e
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGRoot.cpp
@@ -0,0 +1,506 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) 2004, 2005, 2007, 2008, 2009 Rob Buis <buis@kde.org>
+ * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
+ * Copyright (C) 2009 Google, Inc.
+ * Copyright (C) Research In Motion Limited 2011. 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"
+
+#if ENABLE(SVG)
+#include "core/rendering/svg/RenderSVGRoot.h"
+
+#include "core/page/Chrome.h"
+#include "core/page/ChromeClient.h"
+#include "core/page/Frame.h"
+#include "core/page/Page.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/platform/graphics/transforms/TransformState.h"
+#include "core/rendering/HitTestResult.h"
+#include "core/rendering/LayoutRepainter.h"
+#include "core/rendering/RenderPart.h"
+#include "core/rendering/RenderView.h"
+#include "core/rendering/svg/RenderSVGContainer.h"
+#include "core/rendering/svg/RenderSVGResource.h"
+#include "core/rendering/svg/RenderSVGResourceContainer.h"
+#include "core/rendering/svg/RenderSVGResourceFilter.h"
+#include "core/rendering/svg/SVGRenderingContext.h"
+#include "core/rendering/svg/SVGResources.h"
+#include "core/rendering/svg/SVGResourcesCache.h"
+#include "core/svg/SVGLength.h"
+#include "core/svg/SVGSVGElement.h"
+#include "core/svg/SVGStyledElement.h"
+#include "core/svg/SVGViewSpec.h"
+
+using namespace std;
+
+namespace WebCore {
+
+RenderSVGRoot::RenderSVGRoot(SVGStyledElement* node)
+    : RenderReplaced(node)
+    , m_objectBoundingBoxValid(false)
+    , m_isLayoutSizeChanged(false)
+    , m_needsBoundariesOrTransformUpdate(true)
+    , m_hasSVGShadow(false)
+{
+}
+
+RenderSVGRoot::~RenderSVGRoot()
+{
+}
+
+void RenderSVGRoot::computeIntrinsicRatioInformation(FloatSize& intrinsicSize, double& intrinsicRatio, bool& isPercentageIntrinsicSize) const
+{
+    // Spec: http://www.w3.org/TR/SVG/coords.html#IntrinsicSizing
+    // SVG needs to specify how to calculate some intrinsic sizing properties to enable inclusion within other languages.
+    // The intrinsic width and height of the viewport of SVG content must be determined from the ‘width’ and ‘height’ attributes.
+    // If either of these are not specified, a value of '100%' must be assumed. Note: the ‘width’ and ‘height’ attributes are not
+    // the same as the CSS width and height properties. Specifically, percentage values do not provide an intrinsic width or height,
+    // and do not indicate a percentage of the containing block. Rather, once the viewport is established, they indicate the portion
+    // of the viewport that is actually covered by image data.
+    SVGSVGElement* svg = toSVGSVGElement(node());
+    ASSERT(svg);
+    Length intrinsicWidthAttribute = svg->intrinsicWidth(SVGSVGElement::IgnoreCSSProperties);
+    Length intrinsicHeightAttribute = svg->intrinsicHeight(SVGSVGElement::IgnoreCSSProperties);
+
+    // The intrinsic aspect ratio of the viewport of SVG content is necessary for example, when including SVG from an ‘object’
+    // element in HTML styled with CSS. It is possible (indeed, common) for an SVG graphic to have an intrinsic aspect ratio but
+    // not to have an intrinsic width or height. The intrinsic aspect ratio must be calculated based upon the following rules:
+    // - The aspect ratio is calculated by dividing a width by a height.
+    // - If the ‘width’ and ‘height’ of the rootmost ‘svg’ element are both specified with unit identifiers (in, mm, cm, pt, pc,
+    //   px, em, ex) or in user units, then the aspect ratio is calculated from the ‘width’ and ‘height’ attributes after
+    //   resolving both values to user units.
+    if (intrinsicWidthAttribute.isFixed() || intrinsicHeightAttribute.isFixed()) {
+        if (intrinsicWidthAttribute.isFixed())
+            intrinsicSize.setWidth(floatValueForLength(intrinsicWidthAttribute, 0));
+        if (intrinsicHeightAttribute.isFixed())
+            intrinsicSize.setHeight(floatValueForLength(intrinsicHeightAttribute, 0));
+        if (!intrinsicSize.isEmpty())
+            intrinsicRatio = intrinsicSize.width() / static_cast<double>(intrinsicSize.height());
+        return;
+    }
+
+    // - If either/both of the ‘width’ and ‘height’ of the rootmost ‘svg’ element are in percentage units (or omitted), the
+    //   aspect ratio is calculated from the width and height values of the ‘viewBox’ specified for the current SVG document
+    //   fragment. If the ‘viewBox’ is not correctly specified, or set to 'none', the intrinsic aspect ratio cannot be
+    //   calculated and is considered unspecified.
+    intrinsicSize = svg->viewBox().size();
+    if (!intrinsicSize.isEmpty()) {
+        // The viewBox can only yield an intrinsic ratio, not an intrinsic size.
+        intrinsicRatio = intrinsicSize.width() / static_cast<double>(intrinsicSize.height());
+        intrinsicSize = FloatSize();
+        return;
+    }
+
+    // If our intrinsic size is in percentage units, return those to the caller through the intrinsicSize. Notify the caller
+    // about the special situation, by setting isPercentageIntrinsicSize=true, so it knows how to interpret the return values.
+    if (intrinsicWidthAttribute.isPercent() && intrinsicHeightAttribute.isPercent()) {
+        isPercentageIntrinsicSize = true;
+        intrinsicSize = FloatSize(intrinsicWidthAttribute.percent(), intrinsicHeightAttribute.percent());
+    }
+}
+
+bool RenderSVGRoot::isEmbeddedThroughSVGImage() const
+{
+    if (!node())
+        return false;
+
+    Frame* frame = node()->document()->frame();
+    if (!frame)
+        return false;
+
+    // Test whether we're embedded through an img.
+    if (!frame->page() || !frame->page()->chrome())
+        return false;
+
+    ChromeClient* chromeClient = frame->page()->chrome()->client();
+    if (!chromeClient || !chromeClient->isSVGImageChromeClient())
+        return false;
+
+    return true;
+}
+
+bool RenderSVGRoot::isEmbeddedThroughFrameContainingSVGDocument() const
+{
+    if (!node())
+        return false;
+
+    Frame* frame = node()->document()->frame();
+    if (!frame)
+        return false;
+
+    // If our frame has an owner renderer, we're embedded through eg. object/embed/iframe,
+    // but we only negotiate if we're in an SVG document.
+    if (!frame->ownerRenderer())
+        return false;
+    return frame->document()->isSVGDocument();
+}
+
+static inline LayoutUnit resolveLengthAttributeForSVG(const Length& length, float scale, float maxSize, RenderView* renderView)
+{
+    return static_cast<LayoutUnit>(valueForLength(length, maxSize, renderView) * (length.isFixed() ? scale : 1));
+}
+
+LayoutUnit RenderSVGRoot::computeReplacedLogicalWidth(ShouldComputePreferred shouldComputePreferred) const
+{
+    SVGSVGElement* svg = toSVGSVGElement(node());
+    ASSERT(svg);
+
+    // When we're embedded through SVGImage (border-image/background-image/<html:img>/...) we're forced to resize to a specific size.
+    if (!m_containerSize.isEmpty())
+        return m_containerSize.width();
+
+    if (style()->logicalWidth().isSpecified() || style()->logicalMaxWidth().isSpecified())
+        return RenderReplaced::computeReplacedLogicalWidth(shouldComputePreferred);
+
+    if (svg->widthAttributeEstablishesViewport())
+        return resolveLengthAttributeForSVG(svg->intrinsicWidth(SVGSVGElement::IgnoreCSSProperties), style()->effectiveZoom(), containingBlock()->availableLogicalWidth(), view());
+
+    // SVG embedded through object/embed/iframe.
+    if (isEmbeddedThroughFrameContainingSVGDocument())
+        return document()->frame()->ownerRenderer()->availableLogicalWidth();
+
+    // SVG embedded via SVGImage (background-image/border-image/etc) / Inline SVG.
+    return RenderReplaced::computeReplacedLogicalWidth(shouldComputePreferred);
+}
+
+LayoutUnit RenderSVGRoot::computeReplacedLogicalHeight() const
+{
+    SVGSVGElement* svg = toSVGSVGElement(node());
+    ASSERT(svg);
+
+    // When we're embedded through SVGImage (border-image/background-image/<html:img>/...) we're forced to resize to a specific size.
+    if (!m_containerSize.isEmpty())
+        return m_containerSize.height();
+
+    if (style()->logicalHeight().isSpecified() || style()->logicalMaxHeight().isSpecified())
+        return RenderReplaced::computeReplacedLogicalHeight();
+
+    if (svg->heightAttributeEstablishesViewport()) {
+        Length height = svg->intrinsicHeight(SVGSVGElement::IgnoreCSSProperties);
+        if (height.isPercent()) {
+            RenderBlock* cb = containingBlock();
+            ASSERT(cb);
+            while (cb->isAnonymous()) {
+                cb = cb->containingBlock();
+                cb->addPercentHeightDescendant(const_cast<RenderSVGRoot*>(this));
+            }
+        } else
+            RenderBlock::removePercentHeightDescendant(const_cast<RenderSVGRoot*>(this));
+
+        return resolveLengthAttributeForSVG(height, style()->effectiveZoom(), containingBlock()->availableLogicalHeight(IncludeMarginBorderPadding), view());
+    }
+
+    // SVG embedded through object/embed/iframe.
+    if (isEmbeddedThroughFrameContainingSVGDocument())
+        return document()->frame()->ownerRenderer()->availableLogicalHeight(IncludeMarginBorderPadding);
+
+    // SVG embedded via SVGImage (background-image/border-image/etc) / Inline SVG.
+    return RenderReplaced::computeReplacedLogicalHeight();
+}
+
+void RenderSVGRoot::layout()
+{
+    StackStats::LayoutCheckPoint layoutCheckPoint;
+    ASSERT(needsLayout());
+
+    m_resourcesNeedingToInvalidateClients.clear();
+
+    // Arbitrary affine transforms are incompatible with LayoutState.
+    LayoutStateDisabler layoutStateDisabler(view());
+
+    bool needsLayout = selfNeedsLayout();
+    LayoutRepainter repainter(*this, checkForRepaintDuringLayout() && needsLayout);
+
+    LayoutSize oldSize = size();
+    updateLogicalWidth();
+    updateLogicalHeight();
+    buildLocalToBorderBoxTransform();
+
+    SVGSVGElement* svg = toSVGSVGElement(node());
+    ASSERT(svg);
+    m_isLayoutSizeChanged = needsLayout || (svg->hasRelativeLengths() && oldSize != size());
+    SVGRenderSupport::layoutChildren(this, needsLayout || SVGRenderSupport::filtersForceContainerLayout(this));
+
+    if (!m_resourcesNeedingToInvalidateClients.isEmpty()) {
+        // Invalidate resource clients, which may mark some nodes for layout.
+        HashSet<RenderSVGResourceContainer*>::iterator end = m_resourcesNeedingToInvalidateClients.end();
+        for (HashSet<RenderSVGResourceContainer*>::iterator it = m_resourcesNeedingToInvalidateClients.begin(); it != end; ++it)
+            (*it)->removeAllClientsFromCache();
+
+        m_isLayoutSizeChanged = false;
+        SVGRenderSupport::layoutChildren(this, false);
+    }
+
+    // At this point LayoutRepainter already grabbed the old bounds,
+    // recalculate them now so repaintAfterLayout() uses the new bounds.
+    if (m_needsBoundariesOrTransformUpdate) {
+        updateCachedBoundaries();
+        m_needsBoundariesOrTransformUpdate = false;
+    }
+
+    repainter.repaintAfterLayout();
+
+    setNeedsLayout(false);
+}
+
+void RenderSVGRoot::paintReplaced(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    // An empty viewport disables rendering.
+    if (pixelSnappedBorderBoxRect().isEmpty())
+        return;
+
+    // Don't paint, if the context explicitly disabled it.
+    if (paintInfo.context->paintingDisabled())
+        return;
+
+    // An empty viewBox also disables rendering.
+    // (http://www.w3.org/TR/SVG/coords.html#ViewBoxAttribute)
+    SVGSVGElement* svg = toSVGSVGElement(node());
+    ASSERT(svg);
+    if (svg->hasEmptyViewBox())
+        return;
+
+    Page* page = 0;
+    if (Frame* frame = this->frame())
+        page = frame->page();
+
+    // Don't paint if we don't have kids, except if we have filters we should paint those.
+    if (!firstChild()) {
+        SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(this);
+        if (!resources || !resources->filter()) {
+            if (page && paintInfo.phase == PaintPhaseForeground)
+                page->addRelevantUnpaintedObject(this, visualOverflowRect());
+            return;
+        }
+    }
+
+    if (page && paintInfo.phase == PaintPhaseForeground)
+        page->addRelevantRepaintedObject(this, visualOverflowRect());
+
+    // Make a copy of the PaintInfo because applyTransform will modify the damage rect.
+    PaintInfo childPaintInfo(paintInfo);
+    childPaintInfo.context->save();
+
+    // Apply initial viewport clip - not affected by overflow handling
+    childPaintInfo.context->clip(pixelSnappedIntRect(overflowClipRect(paintOffset, paintInfo.renderRegion)));
+
+    // Convert from container offsets (html renderers) to a relative transform (svg renderers).
+    // Transform from our paint container's coordinate system to our local coords.
+    IntPoint adjustedPaintOffset = roundedIntPoint(paintOffset);
+    childPaintInfo.applyTransform(AffineTransform::translation(adjustedPaintOffset.x(), adjustedPaintOffset.y()) * localToBorderBoxTransform());
+
+    // SVGRenderingContext must be destroyed before we restore the childPaintInfo.context, because a filter may have
+    // changed the context and it is only reverted when the SVGRenderingContext destructor finishes applying the filter.
+    {
+        SVGRenderingContext renderingContext;
+        bool continueRendering = true;
+        if (childPaintInfo.phase == PaintPhaseForeground) {
+            renderingContext.prepareToRenderSVGContent(this, childPaintInfo);
+            continueRendering = renderingContext.isRenderingPrepared();
+        }
+
+        if (continueRendering)
+            RenderBox::paint(childPaintInfo, LayoutPoint());
+    }
+
+    childPaintInfo.context->restore();
+}
+
+void RenderSVGRoot::willBeDestroyed()
+{
+    RenderBlock::removePercentHeightDescendant(const_cast<RenderSVGRoot*>(this));
+
+    SVGResourcesCache::clientDestroyed(this);
+    RenderReplaced::willBeDestroyed();
+}
+
+void RenderSVGRoot::styleWillChange(StyleDifference diff, const RenderStyle* newStyle)
+{
+    if (diff == StyleDifferenceLayout)
+        setNeedsBoundariesUpdate();
+    RenderReplaced::styleWillChange(diff, newStyle);
+}
+
+void RenderSVGRoot::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
+{
+    RenderReplaced::styleDidChange(diff, oldStyle);
+    SVGResourcesCache::clientStyleChanged(this, diff, style());
+}
+
+void RenderSVGRoot::addChild(RenderObject* child, RenderObject* beforeChild)
+{
+    RenderReplaced::addChild(child, beforeChild);
+    SVGResourcesCache::clientWasAddedToTree(child, child->style());
+}
+
+void RenderSVGRoot::removeChild(RenderObject* child)
+{
+    SVGResourcesCache::clientWillBeRemovedFromTree(child);
+    RenderReplaced::removeChild(child);
+}
+
+// RenderBox methods will expect coordinates w/o any transforms in coordinates
+// relative to our borderBox origin.  This method gives us exactly that.
+void RenderSVGRoot::buildLocalToBorderBoxTransform()
+{
+    SVGSVGElement* svg = toSVGSVGElement(node());
+    ASSERT(svg);
+    float scale = style()->effectiveZoom();
+    FloatPoint translate = svg->currentTranslate();
+    LayoutSize borderAndPadding(borderLeft() + paddingLeft(), borderTop() + paddingTop());
+    m_localToBorderBoxTransform = svg->viewBoxToViewTransform(contentWidth() / scale, contentHeight() / scale);
+    if (borderAndPadding.isEmpty() && scale == 1 && translate == FloatPoint::zero())
+        return;
+    m_localToBorderBoxTransform = AffineTransform(scale, 0, 0, scale, borderAndPadding.width() + translate.x(), borderAndPadding.height() + translate.y()) * m_localToBorderBoxTransform;
+}
+
+const AffineTransform& RenderSVGRoot::localToParentTransform() const
+{
+    // Slightly optimized version of m_localToParentTransform = AffineTransform::translation(x(), y()) * m_localToBorderBoxTransform;
+    m_localToParentTransform = m_localToBorderBoxTransform;
+    if (x())
+        m_localToParentTransform.setE(m_localToParentTransform.e() + roundToInt(x()));
+    if (y())
+        m_localToParentTransform.setF(m_localToParentTransform.f() + roundToInt(y()));
+    return m_localToParentTransform;
+}
+
+LayoutRect RenderSVGRoot::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const
+{
+    return SVGRenderSupport::clippedOverflowRectForRepaint(this, repaintContainer);
+}
+
+void RenderSVGRoot::computeFloatRectForRepaint(const RenderLayerModelObject* repaintContainer, FloatRect& repaintRect, bool fixed) const
+{
+    // Apply our local transforms (except for x/y translation), then our shadow, 
+    // and then call RenderBox's method to handle all the normal CSS Box model bits
+    repaintRect = m_localToBorderBoxTransform.mapRect(repaintRect);
+
+    const SVGRenderStyle* svgStyle = style()->svgStyle();
+    if (const ShadowData* shadow = svgStyle->shadow())
+        shadow->adjustRectForShadow(repaintRect);
+
+    // Apply initial viewport clip - not affected by overflow settings
+    repaintRect.intersect(pixelSnappedBorderBoxRect());
+
+    LayoutRect rect = enclosingIntRect(repaintRect);
+    RenderReplaced::computeRectForRepaint(repaintContainer, rect, fixed);
+    repaintRect = rect;
+}
+
+// This method expects local CSS box coordinates.
+// Callers with local SVG viewport coordinates should first apply the localToBorderBoxTransform
+// to convert from SVG viewport coordinates to local CSS box coordinates.
+void RenderSVGRoot::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags mode, bool* wasFixed) const
+{
+    ASSERT(mode & ~IsFixed); // We should have no fixed content in the SVG rendering tree.
+    ASSERT(mode & UseTransforms); // mapping a point through SVG w/o respecting trasnforms is useless.
+
+    RenderReplaced::mapLocalToContainer(repaintContainer, transformState, mode | ApplyContainerFlip, wasFixed);
+}
+
+const RenderObject* RenderSVGRoot::pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const
+{
+    return RenderReplaced::pushMappingToContainer(ancestorToStopAt, geometryMap);
+}
+
+void RenderSVGRoot::updateCachedBoundaries()
+{
+    SVGRenderSupport::computeContainerBoundingBoxes(this, m_objectBoundingBox, m_objectBoundingBoxValid, m_strokeBoundingBox, m_repaintBoundingBoxExcludingShadow);
+    SVGRenderSupport::intersectRepaintRectWithResources(this, m_repaintBoundingBoxExcludingShadow);
+    m_repaintBoundingBoxExcludingShadow.inflate(borderAndPaddingWidth());
+
+    m_repaintBoundingBox = m_repaintBoundingBoxExcludingShadow;
+    SVGRenderSupport::intersectRepaintRectWithShadows(this, m_repaintBoundingBox);
+}
+
+bool RenderSVGRoot::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction hitTestAction)
+{
+    LayoutPoint pointInParent = locationInContainer.point() - toLayoutSize(accumulatedOffset);
+    LayoutPoint pointInBorderBox = pointInParent - toLayoutSize(location());
+
+    // Only test SVG content if the point is in our content box.
+    // FIXME: This should be an intersection when rect-based hit tests are supported by nodeAtFloatPoint.
+    if (contentBoxRect().contains(pointInBorderBox)) {
+        FloatPoint localPoint = localToParentTransform().inverse().mapPoint(FloatPoint(pointInParent));
+
+        for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
+            // FIXME: nodeAtFloatPoint() doesn't handle rect-based hit tests yet.
+            if (child->nodeAtFloatPoint(request, result, localPoint, hitTestAction)) {
+                updateHitTestResult(result, pointInBorderBox);
+                if (!result.addNodeToRectBasedTestResult(child->node(), request, locationInContainer))
+                    return true;
+            }
+        }
+    }
+
+    // If we didn't early exit above, we've just hit the container <svg> element. Unlike SVG 1.1, 2nd Edition allows container elements to be hit.
+    if (hitTestAction == HitTestBlockBackground && visibleToHitTestRequest(request)) {
+        // Only return true here, if the last hit testing phase 'BlockBackground' is executed. If we'd return true in the 'Foreground' phase,
+        // hit testing would stop immediately. For SVG only trees this doesn't matter. Though when we have a <foreignObject> subtree we need
+        // to be able to detect hits on the background of a <div> element. If we'd return true here in the 'Foreground' phase, we are not able 
+        // to detect these hits anymore.
+        LayoutRect boundsRect(accumulatedOffset + location(), size());
+        if (locationInContainer.intersects(boundsRect)) {
+            updateHitTestResult(result, pointInBorderBox);
+            if (!result.addNodeToRectBasedTestResult(node(), request, locationInContainer, boundsRect))
+                return true;
+        }
+    }
+
+    return false;
+}
+
+bool RenderSVGRoot::hasRelativeDimensions() const
+{
+    SVGSVGElement* svg = toSVGSVGElement(node());
+    ASSERT(svg);
+
+    return svg->intrinsicHeight(SVGSVGElement::IgnoreCSSProperties).isPercent() || svg->intrinsicWidth(SVGSVGElement::IgnoreCSSProperties).isPercent();
+}
+
+bool RenderSVGRoot::hasRelativeIntrinsicLogicalWidth() const
+{
+    SVGSVGElement* svg = toSVGSVGElement(node());
+    ASSERT(svg);
+    return svg->intrinsicWidth(SVGSVGElement::IgnoreCSSProperties).isPercent();
+}
+
+bool RenderSVGRoot::hasRelativeLogicalHeight() const
+{
+    SVGSVGElement* svg = toSVGSVGElement(node());
+    ASSERT(svg);
+
+    return svg->intrinsicHeight(SVGSVGElement::IgnoreCSSProperties).isPercent();
+}
+
+void RenderSVGRoot::addResourceForClientInvalidation(RenderSVGResourceContainer* resource)
+{
+    RenderObject* svgRoot = resource->parent();
+    while (svgRoot && !svgRoot->isSVGRoot())
+        svgRoot = svgRoot->parent();
+    if (!svgRoot)
+        return;
+    toRenderSVGRoot(svgRoot)->m_resourcesNeedingToInvalidateClients.add(resource);
+}
+
+}
+
+#endif // ENABLE(SVG)
diff --git a/Source/core/rendering/svg/RenderSVGRoot.h b/Source/core/rendering/svg/RenderSVGRoot.h
new file mode 100644
index 0000000..7ed99e5
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGRoot.h
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) 2004, 2005, 2007 Rob Buis <buis@kde.org>
+ * Copyright (C) 2009 Google, Inc.  All rights reserved.
+ * Copyright (C) 2009 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 RenderSVGRoot_h
+#define RenderSVGRoot_h
+
+#if ENABLE(SVG)
+#include "core/platform/graphics/FloatRect.h"
+#include "core/rendering/RenderReplaced.h"
+
+#include "core/rendering/svg/SVGRenderSupport.h"
+
+namespace WebCore {
+
+class AffineTransform;
+class SVGStyledElement;
+
+class RenderSVGRoot FINAL : public RenderReplaced {
+public:
+    explicit RenderSVGRoot(SVGStyledElement*);
+    virtual ~RenderSVGRoot();
+
+    bool isEmbeddedThroughSVGImage() const;
+    bool isEmbeddedThroughFrameContainingSVGDocument() const;
+
+    virtual void computeIntrinsicRatioInformation(FloatSize& intrinsicSize, double& intrinsicRatio, bool& isPercentageIntrinsicSize) const;
+
+    RenderObject* firstChild() const { ASSERT(children() == virtualChildren()); return children()->firstChild(); }
+    RenderObject* lastChild() const { ASSERT(children() == virtualChildren()); return children()->lastChild(); }
+
+    const RenderObjectChildList* children() const { return &m_children; }
+    RenderObjectChildList* children() { return &m_children; }
+
+    bool isLayoutSizeChanged() const { return m_isLayoutSizeChanged; }
+    virtual void setNeedsBoundariesUpdate() { m_needsBoundariesOrTransformUpdate = true; }
+    virtual bool needsBoundariesUpdate() OVERRIDE { return m_needsBoundariesOrTransformUpdate; }
+    virtual void setNeedsTransformUpdate() { m_needsBoundariesOrTransformUpdate = true; }
+
+    IntSize containerSize() const { return m_containerSize; }
+    void setContainerSize(const IntSize& containerSize) { m_containerSize = containerSize; }
+
+    virtual bool hasRelativeDimensions() const OVERRIDE;
+    virtual bool hasRelativeIntrinsicLogicalWidth() const OVERRIDE;
+    virtual bool hasRelativeLogicalHeight() const OVERRIDE;
+
+    // localToBorderBoxTransform maps local SVG viewport coordinates to local CSS box coordinates.  
+    const AffineTransform& localToBorderBoxTransform() const { return m_localToBorderBoxTransform; }
+
+    // The flag is cleared at the beginning of each layout() pass. Elements then call this
+    // method during layout when they are invalidated by a filter.
+    static void addResourceForClientInvalidation(RenderSVGResourceContainer*);
+
+    bool hasSVGShadow() const { return m_hasSVGShadow; }
+    void setHasSVGShadow(bool hasShadow) { m_hasSVGShadow = hasShadow; }
+
+private:
+    virtual RenderObjectChildList* virtualChildren() { return children(); }
+    virtual const RenderObjectChildList* virtualChildren() const { return children(); }
+
+    virtual bool isSVGRoot() const { return true; }
+    virtual const char* renderName() const { return "RenderSVGRoot"; }
+
+    virtual LayoutUnit computeReplacedLogicalWidth(ShouldComputePreferred  = ComputeActual) const OVERRIDE;
+    virtual LayoutUnit computeReplacedLogicalHeight() const;
+    virtual void layout();
+    virtual void paintReplaced(PaintInfo&, const LayoutPoint&);
+
+    virtual void willBeDestroyed();
+    virtual void styleWillChange(StyleDifference, const RenderStyle* newStyle);
+    virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle);
+    virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0) OVERRIDE;
+    virtual void removeChild(RenderObject*) OVERRIDE;
+
+    virtual const AffineTransform& localToParentTransform() const;
+
+    bool fillContains(const FloatPoint&) const;
+    bool strokeContains(const FloatPoint&) const;
+
+    virtual FloatRect objectBoundingBox() const { return m_objectBoundingBox; }
+    virtual FloatRect strokeBoundingBox() const { return m_strokeBoundingBox; }
+    virtual FloatRect repaintRectInLocalCoordinates() const { return m_repaintBoundingBox; }
+    virtual FloatRect repaintRectInLocalCoordinatesExcludingSVGShadow() const { return m_repaintBoundingBoxExcludingShadow; }
+
+    virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
+
+    virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const OVERRIDE;
+    virtual void computeFloatRectForRepaint(const RenderLayerModelObject* repaintContainer, FloatRect& repaintRect, bool fixed) const OVERRIDE;
+
+    virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = 0) const OVERRIDE;
+    virtual const RenderObject* pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap&) const OVERRIDE;
+
+    virtual bool canBeSelectionLeaf() const { return false; }
+    virtual bool canHaveChildren() const { return true; }
+
+    void updateCachedBoundaries();
+    void buildLocalToBorderBoxTransform();
+
+    RenderObjectChildList m_children;
+    IntSize m_containerSize;
+    FloatRect m_objectBoundingBox;
+    bool m_objectBoundingBoxValid;
+    FloatRect m_strokeBoundingBox;
+    FloatRect m_repaintBoundingBox;
+    FloatRect m_repaintBoundingBoxExcludingShadow;
+    mutable AffineTransform m_localToParentTransform;
+    AffineTransform m_localToBorderBoxTransform;
+    HashSet<RenderSVGResourceContainer*> m_resourcesNeedingToInvalidateClients;
+    bool m_isLayoutSizeChanged : 1;
+    bool m_needsBoundariesOrTransformUpdate : 1;
+    bool m_hasSVGShadow : 1;
+};
+
+inline RenderSVGRoot* toRenderSVGRoot(RenderObject* object)
+{ 
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isSVGRoot());
+    return static_cast<RenderSVGRoot*>(object);
+}
+
+inline const RenderSVGRoot* toRenderSVGRoot(const RenderObject* object)
+{ 
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isSVGRoot());
+    return static_cast<const RenderSVGRoot*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderSVGRoot(const RenderSVGRoot*);
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
+#endif // RenderSVGRoot_h
diff --git a/Source/core/rendering/svg/RenderSVGShape.cpp b/Source/core/rendering/svg/RenderSVGShape.cpp
new file mode 100644
index 0000000..4e79827
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGShape.cpp
@@ -0,0 +1,470 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) 2004, 2005, 2008 Rob Buis <buis@kde.org>
+ * Copyright (C) 2005, 2007 Eric Seidel <eric@webkit.org>
+ * Copyright (C) 2009 Google, Inc.
+ * Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
+ * Copyright (C) Research In Motion Limited 2010. All rights reserved.
+ * Copyright (C) 2009 Jeff Schiller <codedread@gmail.com>
+ * Copyright (C) 2011 Renata Hodovan <reni@webkit.org>
+ * Copyright (C) 2011 University of Szeged
+ *
+ * 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 "core/rendering/svg/RenderSVGShape.h"
+
+#include "core/platform/graphics/FloatPoint.h"
+#include "core/platform/graphics/FloatQuad.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/platform/graphics/StrokeStyleApplier.h"
+#include "core/rendering/HitTestRequest.h"
+#include "core/rendering/LayoutRepainter.h"
+#include "core/rendering/PointerEventsHitRules.h"
+#include "core/rendering/svg/RenderSVGContainer.h"
+#include "core/rendering/svg/RenderSVGResourceMarker.h"
+#include "core/rendering/svg/RenderSVGResourceSolidColor.h"
+#include "core/rendering/svg/SVGPathData.h"
+#include "core/rendering/svg/SVGRenderingContext.h"
+#include "core/rendering/svg/SVGResources.h"
+#include "core/rendering/svg/SVGResourcesCache.h"
+#include "core/svg/SVGStyledTransformableElement.h"
+#include "core/svg/SVGTransformList.h"
+#include "core/svg/SVGURIReference.h"
+#include <wtf/MathExtras.h>
+
+namespace WebCore {
+
+RenderSVGShape::RenderSVGShape(SVGStyledTransformableElement* node)
+    : RenderSVGModelObject(node)
+    , m_needsBoundariesUpdate(false) // Default is false, the cached rects are empty from the beginning.
+    , m_needsShapeUpdate(true) // Default is true, so we grab a Path object once from SVGStyledTransformableElement.
+    , m_needsTransformUpdate(true) // Default is true, so we grab a AffineTransform object once from SVGStyledTransformableElement.
+{
+}
+
+RenderSVGShape::~RenderSVGShape()
+{
+}
+
+void RenderSVGShape::updateShapeFromElement()
+{
+    m_path.clear();
+    m_path = adoptPtr(new Path);
+    ASSERT(RenderSVGShape::isEmpty());
+
+    SVGStyledTransformableElement* element = toSVGStyledTransformableElement(node());
+    updatePathFromGraphicsElement(element, path());
+    processMarkerPositions();
+
+    m_fillBoundingBox = calculateObjectBoundingBox();
+    m_strokeBoundingBox = calculateStrokeBoundingBox();
+}
+
+bool RenderSVGShape::isEmpty() const
+{
+    return path().isEmpty();
+}
+
+void RenderSVGShape::fillShape(GraphicsContext* context) const
+{
+    context->fillPath(path());
+}
+
+void RenderSVGShape::strokeShape(GraphicsContext* context) const
+{
+    ASSERT(m_path);
+    Path* usePath = m_path.get();
+
+    if (hasNonScalingStroke())
+        usePath = nonScalingStrokePath(usePath, nonScalingStrokeTransform());
+
+    context->strokePath(*usePath);
+}
+
+bool RenderSVGShape::shapeDependentStrokeContains(const FloatPoint& point)
+{
+    ASSERT(m_path);
+    BoundingRectStrokeStyleApplier applier(this, style());
+
+    if (hasNonScalingStroke()) {
+        AffineTransform nonScalingTransform = nonScalingStrokeTransform();
+        Path* usePath = nonScalingStrokePath(m_path.get(), nonScalingTransform);
+
+        return usePath->strokeContains(&applier, nonScalingTransform.mapPoint(point));
+    }
+
+    return m_path->strokeContains(&applier, point);
+}
+
+bool RenderSVGShape::shapeDependentFillContains(const FloatPoint& point, const WindRule fillRule) const
+{
+    return path().contains(point, fillRule);
+}
+
+bool RenderSVGShape::fillContains(const FloatPoint& point, bool requiresFill, const WindRule fillRule)
+{
+    if (!m_fillBoundingBox.contains(point))
+        return false;
+
+    Color fallbackColor;
+    if (requiresFill && !RenderSVGResource::fillPaintingResource(this, style(), fallbackColor))
+        return false;
+
+    return shapeDependentFillContains(point, fillRule);
+}
+
+bool RenderSVGShape::strokeContains(const FloatPoint& point, bool requiresStroke)
+{
+    if (!strokeBoundingBox().contains(point))
+        return false;
+
+    Color fallbackColor;
+    if (requiresStroke && !RenderSVGResource::strokePaintingResource(this, style(), fallbackColor))
+        return false;
+
+    return shapeDependentStrokeContains(point);
+}
+
+void RenderSVGShape::layout()
+{
+    StackStats::LayoutCheckPoint layoutCheckPoint;
+    LayoutRepainter repainter(*this, SVGRenderSupport::checkForSVGRepaintDuringLayout(this) && selfNeedsLayout());
+    SVGStyledTransformableElement* element = toSVGStyledTransformableElement(node());
+
+    bool updateCachedBoundariesInParents = false;
+
+    if (m_needsShapeUpdate || m_needsBoundariesUpdate) {
+        updateShapeFromElement();
+        m_needsShapeUpdate = false;
+        updateRepaintBoundingBox();
+        m_needsBoundariesUpdate = false;
+        updateCachedBoundariesInParents = true;
+    }
+
+    if (m_needsTransformUpdate) {
+        m_localTransform = element->animatedLocalTransform();
+        m_needsTransformUpdate = false;
+        updateCachedBoundariesInParents = true;
+    }
+
+    // Invalidate all resources of this client if our layout changed.
+    if (everHadLayout() && selfNeedsLayout())
+        SVGResourcesCache::clientLayoutChanged(this);
+
+    // If our bounds changed, notify the parents.
+    if (updateCachedBoundariesInParents)
+        RenderSVGModelObject::setNeedsBoundariesUpdate();
+
+    repainter.repaintAfterLayout();
+    setNeedsLayout(false);
+}
+
+Path* RenderSVGShape::nonScalingStrokePath(const Path* path, const AffineTransform& strokeTransform) const
+{
+    DEFINE_STATIC_LOCAL(Path, tempPath, ());
+
+    tempPath = *path;
+    tempPath.transform(strokeTransform);
+
+    return &tempPath;
+}
+
+bool RenderSVGShape::setupNonScalingStrokeContext(AffineTransform& strokeTransform, GraphicsContextStateSaver& stateSaver)
+{
+    if (!strokeTransform.isInvertible())
+        return false;
+
+    stateSaver.save();
+    stateSaver.context()->concatCTM(strokeTransform.inverse());
+    return true;
+}
+
+AffineTransform RenderSVGShape::nonScalingStrokeTransform() const
+{
+    SVGStyledTransformableElement* element = toSVGStyledTransformableElement(node());
+    return element->getScreenCTM(SVGLocatable::DisallowStyleUpdate);
+}
+
+bool RenderSVGShape::shouldGenerateMarkerPositions() const
+{
+    if (!style()->svgStyle()->hasMarkers())
+        return false;
+
+    SVGStyledTransformableElement* element = toSVGStyledTransformableElement(node());
+    if (!element->supportsMarkers())
+        return false;
+
+    SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(this);
+    if (!resources)
+        return false;
+
+    return resources->markerStart() || resources->markerMid() || resources->markerEnd();
+}
+
+void RenderSVGShape::fillShape(RenderStyle* style, GraphicsContext* context)
+{
+    Color fallbackColor;
+    if (RenderSVGResource* fillPaintingResource = RenderSVGResource::fillPaintingResource(this, style, fallbackColor)) {
+        if (fillPaintingResource->applyResource(this, style, context, ApplyToFillMode))
+            fillPaintingResource->postApplyResource(this, context, ApplyToFillMode, 0, this);
+        else if (fallbackColor.isValid()) {
+            RenderSVGResourceSolidColor* fallbackResource = RenderSVGResource::sharedSolidPaintingResource();
+            fallbackResource->setColor(fallbackColor);
+            if (fallbackResource->applyResource(this, style, context, ApplyToFillMode))
+                fallbackResource->postApplyResource(this, context, ApplyToFillMode, 0, this);
+        }
+    }
+}
+
+void RenderSVGShape::strokeShape(RenderStyle* style, GraphicsContext* context)
+{
+    Color fallbackColor;
+    if (RenderSVGResource* strokePaintingResource = RenderSVGResource::strokePaintingResource(this, style, fallbackColor)) {
+        if (strokePaintingResource->applyResource(this, style, context, ApplyToStrokeMode))
+            strokePaintingResource->postApplyResource(this, context, ApplyToStrokeMode, 0, this);
+        else if (fallbackColor.isValid()) {
+            RenderSVGResourceSolidColor* fallbackResource = RenderSVGResource::sharedSolidPaintingResource();
+            fallbackResource->setColor(fallbackColor);
+            if (fallbackResource->applyResource(this, style, context, ApplyToStrokeMode))
+                fallbackResource->postApplyResource(this, context, ApplyToStrokeMode, 0, this);
+        }
+    }
+}
+
+void RenderSVGShape::fillAndStrokeShape(GraphicsContext* context)
+{
+    RenderStyle* style = this->style();
+
+    fillShape(style, context);
+
+    if (!style->svgStyle()->hasVisibleStroke())
+        return;
+
+    GraphicsContextStateSaver stateSaver(*context, false);
+
+    if (hasNonScalingStroke()) {
+        AffineTransform nonScalingTransform = nonScalingStrokeTransform();
+        if (!setupNonScalingStrokeContext(nonScalingTransform, stateSaver))
+            return;
+    }
+
+    strokeShape(style, context);
+}
+
+void RenderSVGShape::paint(PaintInfo& paintInfo, const LayoutPoint&)
+{
+    if (paintInfo.context->paintingDisabled() || style()->visibility() == HIDDEN || isEmpty())
+        return;
+    FloatRect boundingBox = repaintRectInLocalCoordinates();
+    if (!SVGRenderSupport::paintInfoIntersectsRepaintRect(boundingBox, m_localTransform, paintInfo))
+        return;
+
+    PaintInfo childPaintInfo(paintInfo);
+    bool drawsOutline = style()->outlineWidth() && (childPaintInfo.phase == PaintPhaseOutline || childPaintInfo.phase == PaintPhaseSelfOutline);
+    if (drawsOutline || childPaintInfo.phase == PaintPhaseForeground) {
+        GraphicsContextStateSaver stateSaver(*childPaintInfo.context);
+        childPaintInfo.applyTransform(m_localTransform);
+
+        if (childPaintInfo.phase == PaintPhaseForeground) {
+            SVGRenderingContext renderingContext(this, childPaintInfo);
+
+            if (renderingContext.isRenderingPrepared()) {
+                const SVGRenderStyle* svgStyle = style()->svgStyle();
+                if (svgStyle->shapeRendering() == SR_CRISPEDGES)
+                    childPaintInfo.context->setShouldAntialias(false);
+
+                fillAndStrokeShape(childPaintInfo.context);
+                if (!m_markerPositions.isEmpty())
+                    drawMarkers(childPaintInfo);
+            }
+        }
+
+        if (drawsOutline)
+            paintOutline(childPaintInfo, IntRect(boundingBox));
+    }
+}
+
+// This method is called from inside paintOutline() since we call paintOutline()
+// while transformed to our coord system, return local coords
+void RenderSVGShape::addFocusRingRects(Vector<IntRect>& rects, const LayoutPoint&, const RenderLayerModelObject*)
+{
+    IntRect rect = enclosingIntRect(repaintRectInLocalCoordinates());
+    if (!rect.isEmpty())
+        rects.append(rect);
+}
+
+bool RenderSVGShape::nodeAtFloatPoint(const HitTestRequest& request, HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction)
+{
+    // We only draw in the forground phase, so we only hit-test then.
+    if (hitTestAction != HitTestForeground)
+        return false;
+
+    FloatPoint localPoint = m_localTransform.inverse().mapPoint(pointInParent);
+
+    if (!SVGRenderSupport::pointInClippingArea(this, localPoint))
+        return false;
+
+    PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_PATH_HITTESTING, request, style()->pointerEvents());
+    bool isVisible = (style()->visibility() == VISIBLE);
+    if (isVisible || !hitRules.requireVisible) {
+        const SVGRenderStyle* svgStyle = style()->svgStyle();
+        WindRule fillRule = svgStyle->fillRule();
+        if (request.svgClipContent())
+            fillRule = svgStyle->clipRule();
+        if ((hitRules.canHitStroke && (svgStyle->hasStroke() || !hitRules.requireStroke) && strokeContains(localPoint, hitRules.requireStroke))
+            || (hitRules.canHitFill && (svgStyle->hasFill() || !hitRules.requireFill) && fillContains(localPoint, hitRules.requireFill, fillRule))) {
+            updateHitTestResult(result, roundedLayoutPoint(localPoint));
+            return true;
+        }
+    }
+    return false;
+}
+
+static inline RenderSVGResourceMarker* markerForType(SVGMarkerType type, RenderSVGResourceMarker* markerStart, RenderSVGResourceMarker* markerMid, RenderSVGResourceMarker* markerEnd)
+{
+    switch (type) {
+    case StartMarker:
+        return markerStart;
+    case MidMarker:
+        return markerMid;
+    case EndMarker:
+        return markerEnd;
+    }
+
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
+FloatRect RenderSVGShape::markerRect(float strokeWidth) const
+{
+    ASSERT(!m_markerPositions.isEmpty());
+
+    SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(this);
+    ASSERT(resources);
+
+    RenderSVGResourceMarker* markerStart = resources->markerStart();
+    RenderSVGResourceMarker* markerMid = resources->markerMid();
+    RenderSVGResourceMarker* markerEnd = resources->markerEnd();
+    ASSERT(markerStart || markerMid || markerEnd);
+
+    FloatRect boundaries;
+    unsigned size = m_markerPositions.size();
+    for (unsigned i = 0; i < size; ++i) {
+        if (RenderSVGResourceMarker* marker = markerForType(m_markerPositions[i].type, markerStart, markerMid, markerEnd))
+            boundaries.unite(marker->markerBoundaries(marker->markerTransformation(m_markerPositions[i].origin, m_markerPositions[i].angle, strokeWidth)));
+    }
+    return boundaries;
+}
+
+FloatRect RenderSVGShape::calculateObjectBoundingBox() const
+{
+    return path().boundingRect();
+}
+
+FloatRect RenderSVGShape::calculateStrokeBoundingBox() const
+{
+    ASSERT(m_path);
+    FloatRect strokeBoundingBox = m_fillBoundingBox;
+
+    const SVGRenderStyle* svgStyle = style()->svgStyle();
+    if (svgStyle->hasStroke()) {
+        BoundingRectStrokeStyleApplier strokeStyle(this, style());
+        if (hasNonScalingStroke()) {
+            AffineTransform nonScalingTransform = nonScalingStrokeTransform();
+            if (nonScalingTransform.isInvertible()) {
+                Path* usePath = nonScalingStrokePath(m_path.get(), nonScalingTransform);
+                FloatRect strokeBoundingRect = usePath->strokeBoundingRect(&strokeStyle);
+                strokeBoundingRect = nonScalingTransform.inverse().mapRect(strokeBoundingRect);
+                strokeBoundingBox.unite(strokeBoundingRect);
+            }
+        } else
+            strokeBoundingBox.unite(path().strokeBoundingRect(&strokeStyle));
+    }
+
+    if (!m_markerPositions.isEmpty())
+        strokeBoundingBox.unite(markerRect(strokeWidth()));
+
+    return strokeBoundingBox;
+}
+
+void RenderSVGShape::updateRepaintBoundingBox()
+{
+    m_repaintBoundingBoxExcludingShadow = strokeBoundingBox();
+    SVGRenderSupport::intersectRepaintRectWithResources(this, m_repaintBoundingBoxExcludingShadow);
+
+    m_repaintBoundingBox = m_repaintBoundingBoxExcludingShadow;
+    SVGRenderSupport::intersectRepaintRectWithShadows(this, m_repaintBoundingBox);
+}
+
+float RenderSVGShape::strokeWidth() const
+{
+    SVGElement* svgElement = toSVGElement(node());
+    SVGLengthContext lengthContext(svgElement);
+    return style()->svgStyle()->strokeWidth().value(lengthContext);
+}
+
+bool RenderSVGShape::hasSmoothStroke() const
+{
+    const SVGRenderStyle* svgStyle = style()->svgStyle();
+    return svgStyle->strokeDashArray().isEmpty()
+        && svgStyle->strokeMiterLimit() == svgStyle->initialStrokeMiterLimit()
+        && svgStyle->joinStyle() == svgStyle->initialJoinStyle()
+        && svgStyle->capStyle() == svgStyle->initialCapStyle();
+}
+
+void RenderSVGShape::drawMarkers(PaintInfo& paintInfo)
+{
+    ASSERT(!m_markerPositions.isEmpty());
+
+    SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(this);
+    if (!resources)
+        return;
+
+    RenderSVGResourceMarker* markerStart = resources->markerStart();
+    RenderSVGResourceMarker* markerMid = resources->markerMid();
+    RenderSVGResourceMarker* markerEnd = resources->markerEnd();
+    if (!markerStart && !markerMid && !markerEnd)
+        return;
+
+    float strokeWidth = this->strokeWidth();
+    unsigned size = m_markerPositions.size();
+    for (unsigned i = 0; i < size; ++i) {
+        if (RenderSVGResourceMarker* marker = markerForType(m_markerPositions[i].type, markerStart, markerMid, markerEnd))
+            marker->draw(paintInfo, marker->markerTransformation(m_markerPositions[i].origin, m_markerPositions[i].angle, strokeWidth));
+    }
+}
+
+void RenderSVGShape::processMarkerPositions()
+{
+    m_markerPositions.clear();
+
+    if (!shouldGenerateMarkerPositions())
+        return;
+
+    ASSERT(m_path);
+
+    SVGMarkerData markerData(m_markerPositions);
+    m_path->apply(&markerData, SVGMarkerData::updateFromPathElement);
+    markerData.pathIsDone();
+}
+
+}
+
+#endif // ENABLE(SVG)
diff --git a/Source/core/rendering/svg/RenderSVGShape.h b/Source/core/rendering/svg/RenderSVGShape.h
new file mode 100644
index 0000000..e359bbf
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGShape.h
@@ -0,0 +1,168 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org>
+ * Copyright (C) 2005 Eric Seidel <eric@webkit.org>
+ * Copyright (C) 2006 Apple Computer, Inc
+ * Copyright (C) 2009 Google, Inc.
+ * Copyright (C) 2011 Renata Hodovan <reni@webkit.org>
+ * Copyright (C) 2011 University of Szeged
+ *
+ * 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 RenderSVGShape_h
+#define RenderSVGShape_h
+
+#if ENABLE(SVG)
+#include "core/platform/graphics/FloatRect.h"
+#include "core/platform/graphics/StrokeStyleApplier.h"
+#include "core/platform/graphics/transforms/AffineTransform.h"
+#include "core/rendering/svg/RenderSVGModelObject.h"
+#include "core/rendering/svg/SVGMarkerData.h"
+#include <wtf/OwnPtr.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class FloatPoint;
+class GraphicsContextStateSaver;
+class RenderSVGContainer;
+class RenderSVGPath;
+class RenderSVGResource;
+class SVGStyledTransformableElement;
+
+class BoundingRectStrokeStyleApplier : public StrokeStyleApplier {
+public:
+    BoundingRectStrokeStyleApplier(const RenderObject* object, RenderStyle* style)
+        : m_object(object)
+        , m_style(style)
+    {
+        ASSERT(style);
+        ASSERT(object);
+    }
+
+    void strokeStyle(GraphicsContext* context)
+    {
+        SVGRenderSupport::applyStrokeStyleToContext(context, m_style, m_object);
+    }
+
+private:
+    const RenderObject* m_object;
+    RenderStyle* m_style;
+};
+
+class RenderSVGShape : public RenderSVGModelObject {
+public:
+    explicit RenderSVGShape(SVGStyledTransformableElement*);
+    RenderSVGShape(SVGStyledTransformableElement*, Path*, bool);
+    virtual ~RenderSVGShape();
+
+    void setNeedsShapeUpdate() { m_needsShapeUpdate = true; }
+    virtual void setNeedsBoundariesUpdate() OVERRIDE FINAL { m_needsBoundariesUpdate = true; }
+    virtual bool needsBoundariesUpdate() OVERRIDE FINAL { return m_needsBoundariesUpdate; }
+    virtual void setNeedsTransformUpdate() OVERRIDE FINAL { m_needsTransformUpdate = true; }
+    virtual void fillShape(GraphicsContext*) const;
+    virtual void strokeShape(GraphicsContext*) const;
+
+    Path& path() const
+    {
+        ASSERT(m_path);
+        return *m_path;
+    }
+
+protected:
+    virtual void updateShapeFromElement();
+    virtual bool isEmpty() const;
+    virtual bool shapeDependentStrokeContains(const FloatPoint&);
+    virtual bool shapeDependentFillContains(const FloatPoint&, const WindRule) const;
+    float strokeWidth() const;
+    bool hasPath() const { return m_path.get(); }
+    bool hasSmoothStroke() const;
+
+    bool hasNonScalingStroke() const { return style()->svgStyle()->vectorEffect() == VE_NON_SCALING_STROKE; }
+    AffineTransform nonScalingStrokeTransform() const;
+    Path* nonScalingStrokePath(const Path*, const AffineTransform&) const;
+
+    FloatRect m_fillBoundingBox;
+    FloatRect m_strokeBoundingBox;
+
+private:
+    // Hit-detection separated for the fill and the stroke
+    bool fillContains(const FloatPoint&, bool requiresFill = true, const WindRule fillRule = RULE_NONZERO);
+    bool strokeContains(const FloatPoint&, bool requiresStroke = true);
+
+    virtual FloatRect repaintRectInLocalCoordinates() const OVERRIDE FINAL { return m_repaintBoundingBox; }
+    virtual FloatRect repaintRectInLocalCoordinatesExcludingSVGShadow() const OVERRIDE FINAL { return m_repaintBoundingBoxExcludingShadow; }
+    virtual const AffineTransform& localToParentTransform() const OVERRIDE FINAL { return m_localTransform; }
+    virtual AffineTransform localTransform() const OVERRIDE FINAL { return m_localTransform; }
+
+    virtual bool isSVGShape() const OVERRIDE FINAL { return true; }
+    virtual const char* renderName() const { return "RenderSVGShape"; }
+
+    virtual void layout() OVERRIDE FINAL;
+    virtual void paint(PaintInfo&, const LayoutPoint&) OVERRIDE FINAL;
+    virtual void addFocusRingRects(Vector<IntRect>&, const LayoutPoint& additionalOffset, const RenderLayerModelObject* paintContainer = 0) OVERRIDE FINAL;
+
+    virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction) OVERRIDE FINAL;
+
+    virtual FloatRect objectBoundingBox() const OVERRIDE FINAL { return m_fillBoundingBox; }
+    virtual FloatRect strokeBoundingBox() const OVERRIDE FINAL { return m_strokeBoundingBox; }
+    FloatRect calculateObjectBoundingBox() const;
+    FloatRect calculateStrokeBoundingBox() const;
+    void updateRepaintBoundingBox();
+
+    bool setupNonScalingStrokeContext(AffineTransform&, GraphicsContextStateSaver&);
+
+    bool shouldGenerateMarkerPositions() const;
+    FloatRect markerRect(float strokeWidth) const;
+    void processMarkerPositions();
+
+    void fillShape(RenderStyle*, GraphicsContext*);
+    void strokeShape(RenderStyle*, GraphicsContext*);
+    void fillAndStrokeShape(GraphicsContext*);
+    void drawMarkers(PaintInfo&);
+
+private:
+    FloatRect m_repaintBoundingBox;
+    FloatRect m_repaintBoundingBoxExcludingShadow;
+    AffineTransform m_localTransform;
+    OwnPtr<Path> m_path;
+    Vector<MarkerPosition> m_markerPositions;
+
+    bool m_needsBoundariesUpdate : 1;
+    bool m_needsShapeUpdate : 1;
+    bool m_needsTransformUpdate : 1;
+};
+
+inline RenderSVGShape* toRenderSVGShape(RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isSVGShape());
+    return static_cast<RenderSVGShape*>(object);
+}
+
+inline const RenderSVGShape* toRenderSVGShape(const RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isSVGShape());
+    return static_cast<const RenderSVGShape*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderSVGShape(const RenderSVGShape*);
+
+}
+
+#endif // ENABLE(SVG)
+#endif
diff --git a/Source/core/rendering/svg/RenderSVGTSpan.cpp b/Source/core/rendering/svg/RenderSVGTSpan.cpp
new file mode 100644
index 0000000..e36a748
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGTSpan.cpp
@@ -0,0 +1,37 @@
+/*
+ * This file is part of the WebKit project.
+ *
+ * Copyright (C) 2006 Oliver Hunt <ojh16@student.canterbury.ac.nz>
+ * 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)
+#include "core/rendering/svg/RenderSVGTSpan.h"
+
+namespace WebCore {
+
+RenderSVGTSpan::RenderSVGTSpan(Element* element)
+    : RenderSVGInline(element)
+{
+}
+
+}
+
+#endif // ENABLE(SVG)
diff --git a/Source/core/rendering/svg/RenderSVGTSpan.h b/Source/core/rendering/svg/RenderSVGTSpan.h
new file mode 100644
index 0000000..d9f322e
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGTSpan.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2006 Oliver Hunt <ojh16@student.canterbury.ac.nz>
+ * Copyright (C) 2006 Apple Computer Inc.
+ * Copyright (C) 2009 Google 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 "core/rendering/svg/RenderSVGInline.h"
+
+namespace WebCore {
+class RenderSVGTSpan FINAL : public RenderSVGInline {
+public:
+    explicit RenderSVGTSpan(Element*);
+    virtual const char* renderName() const { return "RenderSVGTSpan"; }
+};
+}
+
+#endif // ENABLE(SVG)
+#endif // !RenderSVGTSpan_h
diff --git a/Source/core/rendering/svg/RenderSVGText.cpp b/Source/core/rendering/svg/RenderSVGText.cpp
new file mode 100644
index 0000000..e736a6c
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGText.cpp
@@ -0,0 +1,566 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2006 Alexander Kellett <lypanov@kde.org>
+ * Copyright (C) 2006 Oliver Hunt <ojh16@student.canterbury.ac.nz>
+ * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) 2008 Rob Buis <buis@kde.org>
+ * Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
+ * Copyright (C) Research In Motion Limited 2010-2012. All rights reserved.
+ * Copyright (C) 2012 Google 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 "core/rendering/svg/RenderSVGText.h"
+
+#include "core/editing/VisiblePosition.h"
+#include "core/platform/FloatConversion.h"
+#include "core/platform/graphics/FloatQuad.h"
+#include "core/platform/graphics/FontCache.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/platform/graphics/SimpleFontData.h"
+#include "core/platform/graphics/transforms/TransformState.h"
+#include "core/rendering/HitTestRequest.h"
+#include "core/rendering/HitTestResult.h"
+#include "core/rendering/LayoutRepainter.h"
+#include "core/rendering/PointerEventsHitRules.h"
+#include "core/rendering/svg/RenderSVGInlineText.h"
+#include "core/rendering/svg/RenderSVGResource.h"
+#include "core/rendering/svg/RenderSVGRoot.h"
+#include "core/rendering/svg/SVGRenderSupport.h"
+#include "core/rendering/svg/SVGResourcesCache.h"
+#include "core/rendering/svg/SVGRootInlineBox.h"
+#include "core/rendering/svg/SVGTextLayoutAttributesBuilder.h"
+#include "core/rendering/svg/SVGTextRunRenderingContext.h"
+#include "core/svg/SVGLengthList.h"
+#include "core/svg/SVGTextElement.h"
+#include "core/svg/SVGTransformList.h"
+#include "core/svg/SVGURIReference.h"
+
+namespace WebCore {
+
+RenderSVGText::RenderSVGText(SVGTextElement* node) 
+    : RenderSVGBlock(node)
+    , m_needsReordering(false)
+    , m_needsPositioningValuesUpdate(false)
+    , m_needsTransformUpdate(true)
+    , m_needsTextMetricsUpdate(false)
+{
+}
+
+RenderSVGText::~RenderSVGText()
+{
+    ASSERT(m_layoutAttributes.isEmpty());
+}
+
+bool RenderSVGText::isChildAllowed(RenderObject* child, RenderStyle*) const
+{
+    return child->isInline();
+}
+
+RenderSVGText* RenderSVGText::locateRenderSVGTextAncestor(RenderObject* start)
+{
+    ASSERT(start);
+    while (start && !start->isSVGText())
+        start = start->parent();
+    if (!start || !start->isSVGText())
+        return 0;
+    return toRenderSVGText(start);
+}
+
+const RenderSVGText* RenderSVGText::locateRenderSVGTextAncestor(const RenderObject* start)
+{
+    ASSERT(start);
+    while (start && !start->isSVGText())
+        start = start->parent();
+    if (!start || !start->isSVGText())
+        return 0;
+    return toRenderSVGText(start);
+}
+
+LayoutRect RenderSVGText::clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const
+{
+    return SVGRenderSupport::clippedOverflowRectForRepaint(this, repaintContainer);
+}
+
+void RenderSVGText::computeRectForRepaint(const RenderLayerModelObject* repaintContainer, LayoutRect& rect, bool fixed) const
+{
+    FloatRect repaintRect = rect;
+    computeFloatRectForRepaint(repaintContainer, repaintRect, fixed);
+    rect = enclosingLayoutRect(repaintRect);
+}
+
+void RenderSVGText::computeFloatRectForRepaint(const RenderLayerModelObject* repaintContainer, FloatRect& repaintRect, bool fixed) const
+{
+    SVGRenderSupport::computeFloatRectForRepaint(this, repaintContainer, repaintRect, fixed);
+}
+
+void RenderSVGText::mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState& transformState, MapCoordinatesFlags, bool* wasFixed) const
+{
+    SVGRenderSupport::mapLocalToContainer(this, repaintContainer, transformState, wasFixed);
+}
+
+const RenderObject* RenderSVGText::pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap) const
+{
+    return SVGRenderSupport::pushMappingToContainer(this, ancestorToStopAt, geometryMap);
+}
+
+static inline void collectLayoutAttributes(RenderObject* text, Vector<SVGTextLayoutAttributes*>& attributes)
+{
+    for (RenderObject* descendant = text; descendant; descendant = descendant->nextInPreOrder(text)) {
+        if (descendant->isSVGInlineText())
+            attributes.append(toRenderSVGInlineText(descendant)->layoutAttributes());
+    }
+}
+
+static inline bool findPreviousAndNextAttributes(RenderObject* start, RenderSVGInlineText* locateElement, bool& stopAfterNext, SVGTextLayoutAttributes*& previous, SVGTextLayoutAttributes*& next)
+{
+    ASSERT(start);
+    ASSERT(locateElement);
+    // FIXME: Make this iterative.
+    for (RenderObject* child = start->firstChild(); child; child = child->nextSibling()) {
+        if (child->isSVGInlineText()) {
+            RenderSVGInlineText* text = toRenderSVGInlineText(child);
+            if (locateElement != text) {
+                if (stopAfterNext) {
+                    next = text->layoutAttributes();
+                    return true;
+                }
+
+                previous = text->layoutAttributes();
+                continue;
+            }
+
+            stopAfterNext = true;
+            continue;
+        }
+
+        if (!child->isSVGInline())
+            continue;
+
+        if (findPreviousAndNextAttributes(child, locateElement, stopAfterNext, previous, next))
+            return true;
+    }
+
+    return false;
+}
+
+inline bool RenderSVGText::shouldHandleSubtreeMutations() const
+{
+    if (beingDestroyed() || !everHadLayout()) {
+        ASSERT(m_layoutAttributes.isEmpty());
+        ASSERT(!m_layoutAttributesBuilder.numberOfTextPositioningElements());
+        return false;
+    }
+    return true;
+}
+
+void RenderSVGText::subtreeChildWasAdded(RenderObject* child)
+{
+    ASSERT(child);
+    if (!shouldHandleSubtreeMutations() || documentBeingDestroyed())
+        return;
+
+    // Always protect the cache before clearing text positioning elements when the cache will subsequently be rebuilt.
+    FontCachePurgePreventer fontCachePurgePreventer;
+
+    // The positioning elements cache doesn't include the new 'child' yet. Clear the
+    // cache, as the next buildLayoutAttributesForTextRenderer() call rebuilds it.
+    m_layoutAttributesBuilder.clearTextPositioningElements();
+
+    if (!child->isSVGInlineText() && !child->isSVGInline())
+        return;
+
+    // Detect changes in layout attributes and only measure those text parts that have changed!
+    Vector<SVGTextLayoutAttributes*> newLayoutAttributes;
+    collectLayoutAttributes(this, newLayoutAttributes);
+    if (newLayoutAttributes.isEmpty()) {
+        ASSERT(m_layoutAttributes.isEmpty());
+        return;
+    }
+
+    // Compare m_layoutAttributes with newLayoutAttributes to figure out which attribute got added.
+    size_t size = newLayoutAttributes.size();
+    SVGTextLayoutAttributes* attributes = 0;
+    for (size_t i = 0; i < size; ++i) {
+        attributes = newLayoutAttributes[i];
+        if (m_layoutAttributes.find(attributes) == notFound) {
+            // Every time this is invoked, there's only a single new entry in the newLayoutAttributes list, compared to the old in m_layoutAttributes.
+            bool stopAfterNext = false;
+            SVGTextLayoutAttributes* previous = 0;
+            SVGTextLayoutAttributes* next = 0;
+            ASSERT_UNUSED(child, attributes->context() == child);
+            findPreviousAndNextAttributes(this, attributes->context(), stopAfterNext, previous, next);
+
+            if (previous)
+                m_layoutAttributesBuilder.buildLayoutAttributesForTextRenderer(previous->context());
+            m_layoutAttributesBuilder.buildLayoutAttributesForTextRenderer(attributes->context());
+            if (next)
+                m_layoutAttributesBuilder.buildLayoutAttributesForTextRenderer(next->context());
+            break;
+        }
+    }
+
+#ifndef NDEBUG
+    // Verify that m_layoutAttributes only differs by a maximum of one entry.
+    for (size_t i = 0; i < size; ++i)
+        ASSERT(m_layoutAttributes.find(newLayoutAttributes[i]) != notFound || newLayoutAttributes[i] == attributes);
+#endif
+
+    m_layoutAttributes = newLayoutAttributes;
+}
+
+static inline void checkLayoutAttributesConsistency(RenderSVGText* text, Vector<SVGTextLayoutAttributes*>& expectedLayoutAttributes)
+{
+#ifndef NDEBUG
+    Vector<SVGTextLayoutAttributes*> newLayoutAttributes;
+    collectLayoutAttributes(text, newLayoutAttributes);
+    ASSERT(newLayoutAttributes == expectedLayoutAttributes);
+#else
+    UNUSED_PARAM(text);
+    UNUSED_PARAM(expectedLayoutAttributes);
+#endif
+}
+
+void RenderSVGText::willBeDestroyed()
+{
+    m_layoutAttributes.clear();
+    m_layoutAttributesBuilder.clearTextPositioningElements();
+
+    RenderSVGBlock::willBeDestroyed();
+}
+
+void RenderSVGText::subtreeChildWillBeRemoved(RenderObject* child, Vector<SVGTextLayoutAttributes*, 2>& affectedAttributes)
+{
+    ASSERT(child);
+    if (!shouldHandleSubtreeMutations())
+        return;
+
+    checkLayoutAttributesConsistency(this, m_layoutAttributes);
+
+    // The positioning elements cache depends on the size of each text renderer in the
+    // subtree. If this changes, clear the cache. It's going to be rebuilt below.
+    m_layoutAttributesBuilder.clearTextPositioningElements();
+    if (m_layoutAttributes.isEmpty() || !child->isSVGInlineText())
+        return;
+
+    // This logic requires that the 'text' child is still inserted in the tree.
+    RenderSVGInlineText* text = toRenderSVGInlineText(child);
+    bool stopAfterNext = false;
+    SVGTextLayoutAttributes* previous = 0;
+    SVGTextLayoutAttributes* next = 0;
+    if (!documentBeingDestroyed())
+        findPreviousAndNextAttributes(this, text, stopAfterNext, previous, next);
+
+    if (previous)
+        affectedAttributes.append(previous);
+    if (next)
+        affectedAttributes.append(next);
+
+    size_t position = m_layoutAttributes.find(text->layoutAttributes());
+    ASSERT(position != notFound);
+    m_layoutAttributes.remove(position);
+}
+
+void RenderSVGText::subtreeChildWasRemoved(const Vector<SVGTextLayoutAttributes*, 2>& affectedAttributes)
+{
+    if (!shouldHandleSubtreeMutations() || documentBeingDestroyed()) {
+        ASSERT(affectedAttributes.isEmpty());
+        return;
+    }
+
+    // This is called immediately after subtreeChildWillBeDestroyed, once the RenderSVGInlineText::willBeDestroyed() method
+    // passes on to the base class, which removes us from the render tree. At this point we can update the layout attributes.
+    unsigned size = affectedAttributes.size();
+    for (unsigned i = 0; i < size; ++i)
+        m_layoutAttributesBuilder.buildLayoutAttributesForTextRenderer(affectedAttributes[i]->context());
+}
+
+void RenderSVGText::subtreeStyleDidChange(RenderSVGInlineText* text)
+{
+    ASSERT(text);
+    if (!shouldHandleSubtreeMutations() || documentBeingDestroyed())
+        return;
+
+    checkLayoutAttributesConsistency(this, m_layoutAttributes);
+
+    // Only update the metrics cache, but not the text positioning element cache
+    // nor the layout attributes cached in the leaf #text renderers.
+    FontCachePurgePreventer fontCachePurgePreventer;
+    for (RenderObject* descendant = text; descendant; descendant = descendant->nextInPreOrder(text)) {
+        if (descendant->isSVGInlineText())
+            m_layoutAttributesBuilder.rebuildMetricsForTextRenderer(toRenderSVGInlineText(descendant));
+    }
+}
+
+void RenderSVGText::subtreeTextDidChange(RenderSVGInlineText* text)
+{
+    ASSERT(text);
+    ASSERT(!beingDestroyed());
+    if (!everHadLayout()) {
+        ASSERT(m_layoutAttributes.isEmpty());
+        ASSERT(!m_layoutAttributesBuilder.numberOfTextPositioningElements());
+        return;
+    }
+
+    // Always protect the cache before clearing text positioning elements when the cache will subsequently be rebuilt.
+    FontCachePurgePreventer fontCachePurgePreventer;
+
+    // The positioning elements cache depends on the size of each text renderer in the
+    // subtree. If this changes, clear the cache. It's going to be rebuilt below.
+    m_layoutAttributesBuilder.clearTextPositioningElements();
+
+    checkLayoutAttributesConsistency(this, m_layoutAttributes);
+    for (RenderObject* descendant = text; descendant; descendant = descendant->nextInPreOrder(text)) {
+        if (descendant->isSVGInlineText())
+            m_layoutAttributesBuilder.buildLayoutAttributesForTextRenderer(toRenderSVGInlineText(descendant));
+    }
+}
+
+static inline void updateFontInAllDescendants(RenderObject* start, SVGTextLayoutAttributesBuilder* builder = 0)
+{
+    for (RenderObject* descendant = start; descendant; descendant = descendant->nextInPreOrder(start)) {
+        if (!descendant->isSVGInlineText())
+            continue;
+        RenderSVGInlineText* text = toRenderSVGInlineText(descendant);
+        text->updateScaledFont();
+        if (builder)
+            builder->rebuildMetricsForTextRenderer(text);
+    }
+}
+
+void RenderSVGText::layout()
+{
+    StackStats::LayoutCheckPoint layoutCheckPoint;
+    ASSERT(needsLayout());
+    LayoutRepainter repainter(*this, SVGRenderSupport::checkForSVGRepaintDuringLayout(this));
+
+    bool updateCachedBoundariesInParents = false;
+    if (m_needsTransformUpdate) {
+        SVGTextElement* text = static_cast<SVGTextElement*>(node());
+        m_localTransform = text->animatedLocalTransform();
+        m_needsTransformUpdate = false;
+        updateCachedBoundariesInParents = true;
+    }
+
+    if (!everHadLayout()) {
+        // When laying out initially, collect all layout attributes, build the character data map,
+        // and propogate resulting SVGLayoutAttributes to all RenderSVGInlineText children in the subtree.
+        ASSERT(m_layoutAttributes.isEmpty());
+        collectLayoutAttributes(this, m_layoutAttributes);
+        updateFontInAllDescendants(this);
+        m_layoutAttributesBuilder.buildLayoutAttributesForForSubtree(this);
+
+        m_needsReordering = true;
+        m_needsTextMetricsUpdate = false;
+        m_needsPositioningValuesUpdate = false;
+        updateCachedBoundariesInParents = true;
+    } else if (m_needsPositioningValuesUpdate) {
+        // When the x/y/dx/dy/rotate lists change, recompute the layout attributes, and eventually
+        // update the on-screen font objects as well in all descendants.
+        if (m_needsTextMetricsUpdate) {
+            updateFontInAllDescendants(this);
+            m_needsTextMetricsUpdate = false;
+        }
+
+        m_layoutAttributesBuilder.buildLayoutAttributesForForSubtree(this);
+        m_needsReordering = true;
+        m_needsPositioningValuesUpdate = false;
+        updateCachedBoundariesInParents = true;
+    } else if (m_needsTextMetricsUpdate || SVGRenderSupport::findTreeRootObject(this)->isLayoutSizeChanged()) {
+        // If the root layout size changed (eg. window size changes) or the transform to the root
+        // context has changed then recompute the on-screen font size.
+        updateFontInAllDescendants(this, &m_layoutAttributesBuilder);
+
+        ASSERT(!m_needsReordering);
+        ASSERT(!m_needsPositioningValuesUpdate);
+        m_needsTextMetricsUpdate = false;
+        updateCachedBoundariesInParents = true;
+    }
+
+    checkLayoutAttributesConsistency(this, m_layoutAttributes);
+
+    // Reduced version of RenderBlock::layoutBlock(), which only takes care of SVG text.
+    // All if branches that could cause early exit in RenderBlocks layoutBlock() method are turned into assertions.
+    ASSERT(!isInline());
+    ASSERT(!simplifiedLayout());
+    ASSERT(!scrollsOverflow());
+    ASSERT(!hasControlClip());
+    ASSERT(!hasColumns());
+    ASSERT(!positionedObjects());
+    ASSERT(!m_overflow);
+    ASSERT(!isAnonymousBlock());
+
+    if (!firstChild())
+        setChildrenInline(true);
+
+    // FIXME: We need to find a way to only layout the child boxes, if needed.
+    FloatRect oldBoundaries = objectBoundingBox();
+    ASSERT(childrenInline());
+    forceLayoutInlineChildren();
+
+    if (m_needsReordering)
+        m_needsReordering = false;
+
+    if (!updateCachedBoundariesInParents)
+        updateCachedBoundariesInParents = oldBoundaries != objectBoundingBox();
+
+    // Invalidate all resources of this client if our layout changed.
+    if (everHadLayout() && selfNeedsLayout())
+        SVGResourcesCache::clientLayoutChanged(this);
+
+    // If our bounds changed, notify the parents.
+    if (updateCachedBoundariesInParents)
+        RenderSVGBlock::setNeedsBoundariesUpdate();
+
+    repainter.repaintAfterLayout();
+    setNeedsLayout(false);
+}
+
+RootInlineBox* RenderSVGText::createRootInlineBox() 
+{
+    RootInlineBox* box = new (renderArena()) SVGRootInlineBox(this);
+    box->setHasVirtualLogicalHeight();
+    return box;
+}
+
+bool RenderSVGText::nodeAtFloatPoint(const HitTestRequest& request, HitTestResult& result, const FloatPoint& pointInParent, HitTestAction hitTestAction)
+{
+    PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_TEXT_HITTESTING, request, style()->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))) {
+            FloatPoint localPoint = localToParentTransform().inverse().mapPoint(pointInParent);
+
+            if (!SVGRenderSupport::pointInClippingArea(this, localPoint))
+                return false;       
+
+            HitTestLocation hitTestLocation(LayoutPoint(flooredIntPoint(localPoint)));
+            return RenderBlock::nodeAtPoint(request, result, hitTestLocation, LayoutPoint(), hitTestAction);
+        }
+    }
+
+    return false;
+}
+
+bool RenderSVGText::nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation&, const LayoutPoint&, HitTestAction)
+{
+    ASSERT_NOT_REACHED();
+    return false;
+}
+
+VisiblePosition RenderSVGText::positionForPoint(const LayoutPoint& pointInContents)
+{
+    RootInlineBox* rootBox = firstRootBox();
+    if (!rootBox)
+        return createVisiblePosition(0, DOWNSTREAM);
+
+    ASSERT_WITH_SECURITY_IMPLICATION(rootBox->isSVGRootInlineBox());
+    ASSERT(!rootBox->nextRootBox());
+    ASSERT(childrenInline());
+
+    InlineBox* closestBox = static_cast<SVGRootInlineBox*>(rootBox)->closestLeafChildForPosition(pointInContents);
+    if (!closestBox)
+        return createVisiblePosition(0, DOWNSTREAM);
+
+    return closestBox->renderer()->positionForPoint(LayoutPoint(pointInContents.x(), closestBox->y()));
+}
+
+void RenderSVGText::absoluteQuads(Vector<FloatQuad>& quads, bool* wasFixed) const
+{
+    quads.append(localToAbsoluteQuad(strokeBoundingBox(), 0 /* mode */, wasFixed));
+}
+
+void RenderSVGText::paint(PaintInfo& paintInfo, const LayoutPoint&)
+{
+    if (paintInfo.context->paintingDisabled())
+        return;
+
+    if (paintInfo.phase != PaintPhaseForeground
+     && paintInfo.phase != PaintPhaseSelfOutline
+     && paintInfo.phase != PaintPhaseSelection)
+         return;
+
+    PaintInfo blockInfo(paintInfo);
+    GraphicsContextStateSaver stateSaver(*blockInfo.context);
+    blockInfo.applyTransform(localToParentTransform());
+    RenderBlock::paint(blockInfo, LayoutPoint());
+}
+
+FloatRect RenderSVGText::strokeBoundingBox() const
+{
+    FloatRect strokeBoundaries = objectBoundingBox();
+    const SVGRenderStyle* svgStyle = style()->svgStyle();
+    if (!svgStyle->hasStroke())
+        return strokeBoundaries;
+
+    ASSERT(node());
+    ASSERT(node()->isSVGElement());
+    SVGLengthContext lengthContext(toSVGElement(node()));
+    strokeBoundaries.inflate(svgStyle->strokeWidth().value(lengthContext));
+    return strokeBoundaries;
+}
+
+FloatRect RenderSVGText::repaintRectInLocalCoordinates() const
+{
+    FloatRect repaintRect = strokeBoundingBox();
+    SVGRenderSupport::intersectRepaintRectWithResources(this, repaintRect);
+
+    if (const ShadowData* textShadow = style()->textShadow())
+        textShadow->adjustRectForShadow(repaintRect);
+
+    return repaintRect;
+}
+
+void RenderSVGText::addChild(RenderObject* child, RenderObject* beforeChild)
+{
+    RenderSVGBlock::addChild(child, beforeChild);
+
+    SVGResourcesCache::clientWasAddedToTree(child, child->style());
+    subtreeChildWasAdded(child);
+}
+
+void RenderSVGText::removeChild(RenderObject* child)
+{
+    SVGResourcesCache::clientWillBeRemovedFromTree(child);
+
+    Vector<SVGTextLayoutAttributes*, 2> affectedAttributes;
+    FontCachePurgePreventer fontCachePurgePreventer;
+    subtreeChildWillBeRemoved(child, affectedAttributes);
+    RenderSVGBlock::removeChild(child);
+    subtreeChildWasRemoved(affectedAttributes);
+}
+
+// Fix for <rdar://problem/8048875>. We should not render :first-line CSS Style
+// in a SVG text element context.
+RenderBlock* RenderSVGText::firstLineBlock() const
+{
+    return 0;
+}
+
+// Fix for <rdar://problem/8048875>. We should not render :first-letter CSS Style
+// in a SVG text element context.
+void RenderSVGText::updateFirstLetter()
+{
+}
+
+}
+
+#endif // ENABLE(SVG)
diff --git a/Source/core/rendering/svg/RenderSVGText.h b/Source/core/rendering/svg/RenderSVGText.h
new file mode 100644
index 0000000..8216298
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGText.h
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2006 Apple Computer, Inc.
+ * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) Research In Motion Limited 2010-2012. 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 RenderSVGText_h
+#define RenderSVGText_h
+
+#if ENABLE(SVG)
+#include "core/platform/graphics/transforms/AffineTransform.h"
+#include "core/rendering/svg/RenderSVGBlock.h"
+#include "core/rendering/svg/SVGTextLayoutAttributesBuilder.h"
+
+namespace WebCore {
+
+class RenderSVGInlineText;
+class SVGTextElement;
+class RenderSVGInlineText;
+
+class RenderSVGText FINAL : public RenderSVGBlock {
+public:
+    RenderSVGText(SVGTextElement*);
+    virtual ~RenderSVGText();
+
+    virtual bool isChildAllowed(RenderObject*, RenderStyle*) const;
+
+    void setNeedsPositioningValuesUpdate() { m_needsPositioningValuesUpdate = true; }
+    virtual void setNeedsTransformUpdate() { m_needsTransformUpdate = true; }
+    void setNeedsTextMetricsUpdate() { m_needsTextMetricsUpdate = true; }
+    virtual FloatRect repaintRectInLocalCoordinates() const;
+
+    static RenderSVGText* locateRenderSVGTextAncestor(RenderObject*);
+    static const RenderSVGText* locateRenderSVGTextAncestor(const RenderObject*);
+
+    bool needsReordering() const { return m_needsReordering; }
+    Vector<SVGTextLayoutAttributes*>& layoutAttributes() { return m_layoutAttributes; }
+
+    void subtreeChildWasAdded(RenderObject*);
+    void subtreeChildWillBeRemoved(RenderObject*, Vector<SVGTextLayoutAttributes*, 2>& affectedAttributes);
+    void subtreeChildWasRemoved(const Vector<SVGTextLayoutAttributes*, 2>& affectedAttributes);
+    void subtreeStyleDidChange(RenderSVGInlineText*);
+    void subtreeTextDidChange(RenderSVGInlineText*);
+
+private:
+    virtual const char* renderName() const { return "RenderSVGText"; }
+    virtual bool isSVGText() const { return true; }
+
+    virtual void paint(PaintInfo&, const LayoutPoint&);
+    virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE;
+    virtual bool nodeAtFloatPoint(const HitTestRequest&, HitTestResult&, const FloatPoint& pointInParent, HitTestAction);
+    virtual VisiblePosition positionForPoint(const LayoutPoint&);
+
+    virtual bool requiresLayer() const { return false; }
+    virtual void layout();
+
+    virtual void absoluteQuads(Vector<FloatQuad>&, bool* wasFixed) const;
+
+    virtual LayoutRect clippedOverflowRectForRepaint(const RenderLayerModelObject* repaintContainer) const OVERRIDE;
+    virtual void computeRectForRepaint(const RenderLayerModelObject* repaintContainer, LayoutRect&, bool fixed = false) const OVERRIDE;
+    virtual void computeFloatRectForRepaint(const RenderLayerModelObject* repaintContainer, FloatRect&, bool fixed = false) const OVERRIDE;
+
+    virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = 0) const OVERRIDE;
+    virtual const RenderObject* pushMappingToContainer(const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap&) const OVERRIDE;
+    virtual void addChild(RenderObject* child, RenderObject* beforeChild = 0);
+    virtual void removeChild(RenderObject*) OVERRIDE;
+    virtual void willBeDestroyed() OVERRIDE;
+
+    virtual FloatRect objectBoundingBox() const { return frameRect(); }
+    virtual FloatRect strokeBoundingBox() const;
+
+    virtual const AffineTransform& localToParentTransform() const { return m_localTransform; }
+    virtual AffineTransform localTransform() const { return m_localTransform; }
+    virtual RootInlineBox* createRootInlineBox();
+
+    virtual RenderBlock* firstLineBlock() const;
+    virtual void updateFirstLetter();
+
+    bool shouldHandleSubtreeMutations() const;
+
+    bool m_needsReordering : 1;
+    bool m_needsPositioningValuesUpdate : 1;
+    bool m_needsTransformUpdate : 1;
+    bool m_needsTextMetricsUpdate : 1;
+    AffineTransform m_localTransform;
+    SVGTextLayoutAttributesBuilder m_layoutAttributesBuilder;
+    Vector<SVGTextLayoutAttributes*> m_layoutAttributes;
+};
+
+inline RenderSVGText* toRenderSVGText(RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isSVGText());
+    return static_cast<RenderSVGText*>(object);
+}
+
+inline const RenderSVGText* toRenderSVGText(const RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isSVGText());
+    return static_cast<const RenderSVGText*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderSVGText(const RenderSVGText*);
+
+}
+
+#endif // ENABLE(SVG)
+#endif
diff --git a/Source/core/rendering/svg/RenderSVGTextPath.cpp b/Source/core/rendering/svg/RenderSVGTextPath.cpp
new file mode 100644
index 0000000..7b16726
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGTextPath.cpp
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, 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 "core/rendering/svg/RenderSVGTextPath.h"
+
+#include "SVGNames.h"
+#include "core/platform/graphics/FloatQuad.h"
+#include "core/rendering/RenderBlock.h"
+#include "core/rendering/svg/SVGInlineTextBox.h"
+#include "core/rendering/svg/SVGPathData.h"
+#include "core/rendering/svg/SVGRootInlineBox.h"
+#include "core/svg/SVGPathElement.h"
+#include "core/svg/SVGTextPathElement.h"
+#include "core/svg/SVGTransformList.h"
+
+namespace WebCore {
+
+RenderSVGTextPath::RenderSVGTextPath(Element* element)
+    : RenderSVGInline(element)
+{
+}
+
+Path RenderSVGTextPath::layoutPath() const
+{
+    SVGTextPathElement* textPathElement = static_cast<SVGTextPathElement*>(node());
+    Element* targetElement = SVGURIReference::targetElementFromIRIString(textPathElement->href(), textPathElement->document());
+    if (!targetElement || !targetElement->hasTagName(SVGNames::pathTag))
+        return Path();
+    
+    SVGPathElement* pathElement = static_cast<SVGPathElement*>(targetElement);
+    
+    Path pathData;
+    updatePathFromGraphicsElement(pathElement, pathData);
+
+    // 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*>(node())->startOffset().valueAsPercentage();
+}
+
+bool RenderSVGTextPath::exactAlignment() const
+{
+    return static_cast<SVGTextPathElement*>(node())->spacing() == SVGTextPathSpacingExact;
+}
+
+bool RenderSVGTextPath::stretchMethod() const
+{
+    return static_cast<SVGTextPathElement*>(node())->method() == SVGTextPathMethodStretch;
+}
+
+}
+
+#endif // ENABLE(SVG)
diff --git a/Source/core/rendering/svg/RenderSVGTextPath.h b/Source/core/rendering/svg/RenderSVGTextPath.h
new file mode 100644
index 0000000..7d8ee87
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGTextPath.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) 2009 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 RenderSVGTextPath_h
+#define RenderSVGTextPath_h
+
+#if ENABLE(SVG)
+#include "core/rendering/svg/RenderSVGInline.h"
+
+namespace WebCore {
+
+class RenderSVGTextPath FINAL : public RenderSVGInline {
+public:
+    RenderSVGTextPath(Element*);
+
+    Path layoutPath() const;
+    float startOffset() const;
+    bool exactAlignment() const;
+    bool stretchMethod() const;
+
+    virtual bool isSVGTextPath() const { return true; }
+
+private:
+    virtual const char* renderName() const { return "RenderSVGTextPath"; }
+
+    Path m_layoutPath;
+};
+
+inline RenderSVGTextPath* toRenderSVGTextPath(RenderObject* object)
+{ 
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isSVGTextPath());
+    return static_cast<RenderSVGTextPath*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderSVGTextPath(const RenderSVGTextPath*);
+
+}
+
+#endif // ENABLE(SVG)
+#endif // RenderSVGTextPath_h
diff --git a/Source/core/rendering/svg/RenderSVGTransformableContainer.cpp b/Source/core/rendering/svg/RenderSVGTransformableContainer.cpp
new file mode 100644
index 0000000..921c88b
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGTransformableContainer.cpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2004, 2005 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) 2004, 2005, 2006 Rob Buis <buis@kde.org>
+ * Copyright (C) 2009 Google, 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 "core/rendering/svg/RenderSVGTransformableContainer.h"
+
+#include "SVGNames.h"
+#include "core/rendering/svg/SVGRenderSupport.h"
+#include "core/svg/SVGStyledTransformableElement.h"
+#include "core/svg/SVGUseElement.h"
+
+namespace WebCore {
+    
+RenderSVGTransformableContainer::RenderSVGTransformableContainer(SVGStyledTransformableElement* node)
+    : RenderSVGContainer(node)
+    , m_needsTransformUpdate(true)
+    , m_didTransformToRootUpdate(false)
+{
+}
+
+bool RenderSVGTransformableContainer::calculateLocalTransform()
+{
+    SVGStyledTransformableElement* element = toSVGStyledTransformableElement(node());
+
+    // If we're either the renderer for a <use> element, or for any <g> element inside the shadow
+    // tree, that was created during the use/symbol/svg expansion in SVGUseElement. These containers
+    // need to respect the translations induced by their corresponding use elements x/y attributes.
+    SVGUseElement* useElement = 0;
+    if (element->hasTagName(SVGNames::useTag))
+        useElement = static_cast<SVGUseElement*>(element);
+    else if (element->isInShadowTree() && element->hasTagName(SVGNames::gTag)) {
+        SVGElement* correspondingElement = element->correspondingElement();
+        if (correspondingElement && correspondingElement->hasTagName(SVGNames::useTag))
+            useElement = static_cast<SVGUseElement*>(correspondingElement);
+    }
+
+    if (useElement) {
+        SVGLengthContext lengthContext(useElement);
+        FloatSize translation(useElement->x().value(lengthContext), useElement->y().value(lengthContext));
+        if (translation != m_lastTranslation)
+            m_needsTransformUpdate = true;
+        m_lastTranslation = translation;
+    }
+
+    m_didTransformToRootUpdate = m_needsTransformUpdate || SVGRenderSupport::transformToRootChanged(parent());
+    if (!m_needsTransformUpdate)
+        return false;
+
+    m_localTransform = element->animatedLocalTransform();
+    m_localTransform.translate(m_lastTranslation.width(), m_lastTranslation.height());
+    m_needsTransformUpdate = false;
+    return true;
+}
+
+}
+
+#endif // ENABLE(SVG)
diff --git a/Source/core/rendering/svg/RenderSVGTransformableContainer.h b/Source/core/rendering/svg/RenderSVGTransformableContainer.h
new file mode 100644
index 0000000..03c0c19
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGTransformableContainer.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
+ * Copyright (C) 2009 Google, 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 RenderSVGTransformableContainer_h
+#define RenderSVGTransformableContainer_h
+
+#if ENABLE(SVG)
+#include "core/rendering/svg/RenderSVGContainer.h"
+
+namespace WebCore {
+    
+class SVGStyledTransformableElement;
+class RenderSVGTransformableContainer FINAL : public RenderSVGContainer {
+public:
+    explicit RenderSVGTransformableContainer(SVGStyledTransformableElement*);
+
+    virtual bool isSVGTransformableContainer() const { return true; }
+    virtual const AffineTransform& localToParentTransform() const { return m_localTransform; }
+    virtual void setNeedsTransformUpdate() { m_needsTransformUpdate = true; }
+    virtual bool didTransformToRootUpdate() { return m_didTransformToRootUpdate; }
+
+private:
+    virtual bool calculateLocalTransform();
+    virtual AffineTransform localTransform() const { return m_localTransform; }
+
+    bool m_needsTransformUpdate : 1;
+    bool m_didTransformToRootUpdate : 1;
+    AffineTransform m_localTransform;
+    FloatSize m_lastTranslation;
+};
+
+}
+
+#endif // ENABLE(SVG)
+#endif // RenderSVGTransformableContainer_h
diff --git a/Source/core/rendering/svg/RenderSVGViewportContainer.cpp b/Source/core/rendering/svg/RenderSVGViewportContainer.cpp
new file mode 100644
index 0000000..a4ad2a5
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGViewportContainer.cpp
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) 2004, 2005, 2007 Rob Buis <buis@kde.org>
+ * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
+ * Copyright (C) 2009 Google, 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 "core/rendering/svg/RenderSVGViewportContainer.h"
+
+#include "SVGNames.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/rendering/RenderView.h"
+#include "core/svg/SVGElementInstance.h"
+#include "core/svg/SVGSVGElement.h"
+#include "core/svg/SVGUseElement.h"
+
+namespace WebCore {
+
+RenderSVGViewportContainer::RenderSVGViewportContainer(SVGStyledElement* node)
+    : RenderSVGContainer(node)
+    , m_didTransformToRootUpdate(false)
+    , m_isLayoutSizeChanged(false)
+    , m_needsTransformUpdate(true)
+{
+}
+
+void RenderSVGViewportContainer::determineIfLayoutSizeChanged()
+{
+    if (!node()->hasTagName(SVGNames::svgTag))
+        return;
+
+    m_isLayoutSizeChanged = toSVGSVGElement(node())->hasRelativeLengths() && selfNeedsLayout();
+}
+
+void RenderSVGViewportContainer::applyViewportClip(PaintInfo& paintInfo)
+{
+    if (SVGRenderSupport::isOverflowHidden(this))
+        paintInfo.context->clip(m_viewport);
+}
+
+void RenderSVGViewportContainer::calcViewport()
+{
+    SVGElement* element = toSVGElement(node());
+    if (!element->hasTagName(SVGNames::svgTag))
+        return;
+    SVGSVGElement* svg = toSVGSVGElement(element);
+    FloatRect oldViewport = m_viewport;
+
+    SVGLengthContext lengthContext(element);
+    m_viewport = FloatRect(svg->x().value(lengthContext), svg->y().value(lengthContext), svg->width().value(lengthContext), svg->height().value(lengthContext));
+
+    SVGElement* correspondingElement = svg->correspondingElement();
+    if (correspondingElement && svg->isInShadowTree()) {
+        const HashSet<SVGElementInstance*>& instances = correspondingElement->instancesForElement();
+        ASSERT(!instances.isEmpty());
+
+        SVGUseElement* useElement = 0;
+        const HashSet<SVGElementInstance*>::const_iterator end = instances.end();
+        for (HashSet<SVGElementInstance*>::const_iterator it = instances.begin(); it != end; ++it) {
+            const SVGElementInstance* instance = (*it);
+            ASSERT(instance->correspondingElement()->hasTagName(SVGNames::svgTag) || instance->correspondingElement()->hasTagName(SVGNames::symbolTag));
+            if (instance->shadowTreeElement() == svg) {
+                ASSERT(correspondingElement == instance->correspondingElement());
+                useElement = instance->directUseElement();
+                if (!useElement)
+                    useElement = instance->correspondingUseElement();
+                break;
+            }
+        }
+
+        ASSERT(useElement);
+        bool isSymbolElement = correspondingElement->hasTagName(SVGNames::symbolTag);
+
+        // Spec (<use> on <symbol>): This generated 'svg' will always have explicit values for attributes width and height.
+        // If attributes width and/or height are provided on the 'use' element, then these attributes
+        // will be transferred to the generated 'svg'. If attributes width and/or height are not specified,
+        // the generated 'svg' element will use values of 100% for these attributes.
+
+        // Spec (<use> on <svg>): If attributes width and/or height are provided on the 'use' element, then these
+        // values will override the corresponding attributes on the 'svg' in the generated tree.
+
+        SVGLengthContext lengthContext(element);
+        if (useElement->hasAttribute(SVGNames::widthAttr))
+            m_viewport.setWidth(useElement->width().value(lengthContext));
+        else if (isSymbolElement && svg->hasAttribute(SVGNames::widthAttr)) {
+            SVGLength containerWidth(LengthModeWidth, "100%");
+            m_viewport.setWidth(containerWidth.value(lengthContext));
+        }
+
+        if (useElement->hasAttribute(SVGNames::heightAttr))
+            m_viewport.setHeight(useElement->height().value(lengthContext));
+        else if (isSymbolElement && svg->hasAttribute(SVGNames::heightAttr)) {
+            SVGLength containerHeight(LengthModeHeight, "100%");
+            m_viewport.setHeight(containerHeight.value(lengthContext));
+        }
+    }
+
+    if (oldViewport != m_viewport) {
+        setNeedsBoundariesUpdate();
+        setNeedsTransformUpdate();
+    }
+}
+
+bool RenderSVGViewportContainer::calculateLocalTransform() 
+{
+    m_didTransformToRootUpdate = m_needsTransformUpdate || SVGRenderSupport::transformToRootChanged(parent());
+    if (!m_needsTransformUpdate)
+        return false;
+    
+    m_localToParentTransform = AffineTransform::translation(m_viewport.x(), m_viewport.y()) * viewportTransform();
+    m_needsTransformUpdate = false;
+    return true;
+}
+
+AffineTransform RenderSVGViewportContainer::viewportTransform() const
+{
+    if (node()->hasTagName(SVGNames::svgTag)) {
+        SVGSVGElement* svg = toSVGSVGElement(node());
+        return svg->viewBoxToViewTransform(m_viewport.width(), m_viewport.height());
+    }
+
+    return AffineTransform();
+}
+
+bool RenderSVGViewportContainer::pointIsInsideViewportClip(const FloatPoint& pointInParent)
+{
+    // Respect the viewport clip (which is in parent coords)
+    if (!SVGRenderSupport::isOverflowHidden(this))
+        return true;
+    
+    return m_viewport.contains(pointInParent);
+}
+
+void RenderSVGViewportContainer::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
+{
+    // An empty viewBox disables rendering.
+    if (node()->hasTagName(SVGNames::svgTag)) {
+        if (toSVGSVGElement(node())->hasEmptyViewBox())
+            return;
+    }
+
+    RenderSVGContainer::paint(paintInfo, paintOffset);
+}
+
+}
+
+#endif // ENABLE(SVG)
diff --git a/Source/core/rendering/svg/RenderSVGViewportContainer.h b/Source/core/rendering/svg/RenderSVGViewportContainer.h
new file mode 100644
index 0000000..b5cfbe9
--- /dev/null
+++ b/Source/core/rendering/svg/RenderSVGViewportContainer.h
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) 2004, 2005, 2007 Rob Buis <buis@kde.org>
+ * Copyright (C) 2009 Google, Inc.
+ * Copyright (C) 2009 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 RenderSVGViewportContainer_h
+#define RenderSVGViewportContainer_h
+
+#if ENABLE(SVG)
+#include "core/rendering/svg/RenderSVGContainer.h"
+
+namespace WebCore {
+
+// This is used for non-root <svg> elements and <marker> elements, neither of which are SVGTransformable
+// thus we inherit from RenderSVGContainer instead of RenderSVGTransformableContainer
+class RenderSVGViewportContainer FINAL : public RenderSVGContainer {
+public:
+    explicit RenderSVGViewportContainer(SVGStyledElement*);
+    FloatRect viewport() const { return m_viewport; }
+
+    bool isLayoutSizeChanged() const { return m_isLayoutSizeChanged; }
+    virtual bool didTransformToRootUpdate() { return m_didTransformToRootUpdate; }
+
+    virtual void determineIfLayoutSizeChanged();
+    virtual void setNeedsTransformUpdate() { m_needsTransformUpdate = true; }
+
+    virtual void paint(PaintInfo&, const LayoutPoint&) OVERRIDE;
+
+private:
+    virtual bool isSVGViewportContainer() const { return true; }
+    virtual const char* renderName() const { return "RenderSVGViewportContainer"; }
+
+    AffineTransform viewportTransform() const;
+    virtual const AffineTransform& localToParentTransform() const { return m_localToParentTransform; }
+
+    virtual void calcViewport();
+    virtual bool calculateLocalTransform();
+
+    virtual void applyViewportClip(PaintInfo&);
+    virtual bool pointIsInsideViewportClip(const FloatPoint& pointInParent);
+
+    FloatRect m_viewport;
+    mutable AffineTransform m_localToParentTransform;
+    bool m_didTransformToRootUpdate : 1;
+    bool m_isLayoutSizeChanged : 1;
+    bool m_needsTransformUpdate : 1;
+};
+  
+inline RenderSVGViewportContainer* toRenderSVGViewportContainer(RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isSVGViewportContainer());
+    return static_cast<RenderSVGViewportContainer*>(object);
+}
+
+inline const RenderSVGViewportContainer* toRenderSVGViewportContainer(const RenderObject* object)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!object || object->isSVGViewportContainer());
+    return static_cast<const RenderSVGViewportContainer*>(object);
+}
+
+// This will catch anyone doing an unnecessary cast.
+void toRenderSVGViewportContainer(const RenderSVGViewportContainer*);
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
+#endif // RenderSVGViewportContainer_h
diff --git a/Source/core/rendering/svg/SVGInlineFlowBox.cpp b/Source/core/rendering/svg/SVGInlineFlowBox.cpp
new file mode 100644
index 0000000..04e3a50
--- /dev/null
+++ b/Source/core/rendering/svg/SVGInlineFlowBox.cpp
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2006 Oliver Hunt <ojh16@student.canterbury.ac.nz>
+ * Copyright (C) 2006 Apple Computer Inc.
+ * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) Research In Motion Limited 2010. 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 "core/rendering/svg/SVGInlineFlowBox.h"
+
+#if ENABLE(SVG)
+#include "core/dom/DocumentMarkerController.h"
+#include "core/dom/RenderedDocumentMarker.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/rendering/svg/RenderSVGInlineText.h"
+#include "core/rendering/svg/SVGInlineTextBox.h"
+#include "core/rendering/svg/SVGRenderingContext.h"
+
+using namespace std;
+
+namespace WebCore {
+
+void SVGInlineFlowBox::paintSelectionBackground(PaintInfo& paintInfo)
+{
+    ASSERT(paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection);
+    ASSERT(!paintInfo.context->paintingDisabled());
+
+    PaintInfo childPaintInfo(paintInfo);
+    for (InlineBox* child = firstChild(); child; child = child->nextOnLine()) {
+        if (child->isSVGInlineTextBox())
+            static_cast<SVGInlineTextBox*>(child)->paintSelectionBackground(childPaintInfo);
+        else if (child->isSVGInlineFlowBox())
+            static_cast<SVGInlineFlowBox*>(child)->paintSelectionBackground(childPaintInfo);
+    }
+}
+
+void SVGInlineFlowBox::paint(PaintInfo& paintInfo, const LayoutPoint&, LayoutUnit, LayoutUnit)
+{
+    ASSERT(paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection);
+    ASSERT(!paintInfo.context->paintingDisabled());
+
+    RenderObject* boxRenderer = renderer();
+    ASSERT(boxRenderer);
+
+    SVGRenderingContext renderingContext(boxRenderer, paintInfo, SVGRenderingContext::SaveGraphicsContext);
+    if (renderingContext.isRenderingPrepared()) {
+        for (InlineBox* child = firstChild(); child; child = child->nextOnLine()) {
+            if (child->isSVGInlineTextBox())
+                computeTextMatchMarkerRectForRenderer(toRenderSVGInlineText(static_cast<SVGInlineTextBox*>(child)->textRenderer()));
+
+            child->paint(paintInfo, LayoutPoint(), 0, 0);
+        }
+    }
+}
+
+FloatRect SVGInlineFlowBox::calculateBoundaries() const
+{
+    FloatRect childRect;
+    for (InlineBox* child = firstChild(); child; child = child->nextOnLine()) {
+        if (!child->isSVGInlineTextBox() && !child->isSVGInlineFlowBox())
+            continue;
+        childRect.unite(child->calculateBoundaries());
+    }
+    return childRect;
+}
+
+void SVGInlineFlowBox::computeTextMatchMarkerRectForRenderer(RenderSVGInlineText* textRenderer)
+{
+    ASSERT(textRenderer);
+
+    Node* node = textRenderer->node();
+    if (!node || !node->inDocument())
+        return;
+
+    RenderStyle* style = textRenderer->style();
+    ASSERT(style);
+
+    AffineTransform fragmentTransform;
+    Document* document = textRenderer->document();
+    Vector<DocumentMarker*> markers = document->markers()->markersFor(textRenderer->node());
+
+    Vector<DocumentMarker*>::iterator markerEnd = markers.end();
+    for (Vector<DocumentMarker*>::iterator markerIt = markers.begin(); markerIt != markerEnd; ++markerIt) {
+        DocumentMarker* marker = *markerIt;
+
+        // SVG is only interessted in the TextMatch marker, for now.
+        if (marker->type() != DocumentMarker::TextMatch)
+            continue;
+
+        FloatRect markerRect;
+        for (InlineTextBox* box = textRenderer->firstTextBox(); box; box = box->nextTextBox()) {
+            if (!box->isSVGInlineTextBox())
+                continue;
+
+            SVGInlineTextBox* textBox = static_cast<SVGInlineTextBox*>(box);
+
+            int markerStartPosition = max<int>(marker->startOffset() - textBox->start(), 0);
+            int markerEndPosition = min<int>(marker->endOffset() - textBox->start(), textBox->len());
+
+            if (markerStartPosition >= markerEndPosition)
+                continue;
+
+            int fragmentStartPosition = 0;
+            int fragmentEndPosition = 0;
+
+            const Vector<SVGTextFragment>& fragments = textBox->textFragments();
+            unsigned textFragmentsSize = fragments.size();
+            for (unsigned i = 0; i < textFragmentsSize; ++i) {
+                const SVGTextFragment& fragment = fragments.at(i);
+
+                fragmentStartPosition = markerStartPosition;
+                fragmentEndPosition = markerEndPosition;
+                if (!textBox->mapStartEndPositionsIntoFragmentCoordinates(fragment, fragmentStartPosition, fragmentEndPosition))
+                    continue;
+
+                FloatRect fragmentRect = textBox->selectionRectForTextFragment(fragment, fragmentStartPosition, fragmentEndPosition, style);
+                fragment.buildFragmentTransform(fragmentTransform);
+                if (!fragmentTransform.isIdentity())
+                    fragmentRect = fragmentTransform.mapRect(fragmentRect);
+
+                markerRect.unite(fragmentRect);
+            }
+        }
+
+        toRenderedDocumentMarker(marker)->setRenderedRect(textRenderer->localToAbsoluteQuad(markerRect).enclosingBoundingBox());
+    }
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
diff --git a/Source/core/rendering/svg/SVGInlineFlowBox.h b/Source/core/rendering/svg/SVGInlineFlowBox.h
new file mode 100644
index 0000000..fc1d7d9
--- /dev/null
+++ b/Source/core/rendering/svg/SVGInlineFlowBox.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2006 Oliver Hunt <ojh16@student.canterbury.ac.nz>
+ * 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 SVGInlineFlowBox_h
+#define SVGInlineFlowBox_h
+
+#if ENABLE(SVG)
+#include "core/rendering/InlineFlowBox.h"
+
+namespace WebCore {
+
+class RenderSVGInlineText;
+
+class SVGInlineFlowBox FINAL : public InlineFlowBox {
+public:
+    SVGInlineFlowBox(RenderObject* obj)
+        : InlineFlowBox(obj)
+        , m_logicalHeight(0)
+    {
+    }
+
+    virtual bool isSVGInlineFlowBox() const { return true; }
+    virtual float virtualLogicalHeight() const { return m_logicalHeight; }
+    void setLogicalHeight(float h) { m_logicalHeight = h; }
+
+    void paintSelectionBackground(PaintInfo&);
+    virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom);
+
+    virtual FloatRect calculateBoundaries() const;
+
+    static void computeTextMatchMarkerRectForRenderer(RenderSVGInlineText*);
+
+private:
+    float m_logicalHeight;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
+
+#endif // SVGInlineFlowBox_h
diff --git a/Source/core/rendering/svg/SVGInlineTextBox.cpp b/Source/core/rendering/svg/SVGInlineTextBox.cpp
new file mode 100644
index 0000000..461860f
--- /dev/null
+++ b/Source/core/rendering/svg/SVGInlineTextBox.cpp
@@ -0,0 +1,729 @@
+/**
+ * Copyright (C) 2007 Rob Buis <buis@kde.org>
+ * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) Research In Motion Limited 2010. 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 "core/rendering/svg/SVGInlineTextBox.h"
+
+#if ENABLE(SVG)
+#include "core/page/Frame.h"
+#include "core/page/FrameView.h"
+#include "core/platform/FloatConversion.h"
+#include "core/platform/graphics/FontCache.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/rendering/HitTestResult.h"
+#include "core/rendering/InlineFlowBox.h"
+#include "core/rendering/PointerEventsHitRules.h"
+#include "core/rendering/RenderBlock.h"
+#include "core/rendering/svg/RenderSVGInlineText.h"
+#include "core/rendering/svg/RenderSVGResource.h"
+#include "core/rendering/svg/RenderSVGResourceSolidColor.h"
+#include "core/rendering/svg/SVGRenderingContext.h"
+#include "core/rendering/svg/SVGResourcesCache.h"
+#include "core/rendering/svg/SVGRootInlineBox.h"
+#include "core/rendering/svg/SVGTextRunRenderingContext.h"
+
+using namespace std;
+
+namespace WebCore {
+
+struct ExpectedSVGInlineTextBoxSize : public InlineTextBox {
+    float float1;
+    uint32_t bitfields : 5;
+    void* pointer;
+    Vector<SVGTextFragment> vector;
+};
+
+COMPILE_ASSERT(sizeof(SVGInlineTextBox) == sizeof(ExpectedSVGInlineTextBoxSize), SVGInlineTextBox_is_not_of_expected_size);
+
+SVGInlineTextBox::SVGInlineTextBox(RenderObject* object)
+    : InlineTextBox(object)
+    , m_logicalHeight(0)
+    , m_paintingResourceMode(ApplyToDefaultMode)
+    , m_startsNewTextChunk(false)
+    , m_paintingResource(0)
+{
+}
+
+void SVGInlineTextBox::dirtyLineBoxes()
+{
+    InlineTextBox::dirtyLineBoxes();
+
+    // Clear the now stale text fragments
+    clearTextFragments();
+}
+
+int SVGInlineTextBox::offsetForPosition(float, bool) const
+{
+    // SVG doesn't use the standard offset <-> position selection system, as it's not suitable for SVGs complex needs.
+    // vertical text selection, inline boxes spanning multiple lines (contrary to HTML, etc.)
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
+int SVGInlineTextBox::offsetForPositionInFragment(const SVGTextFragment& fragment, float position, bool includePartialGlyphs) const
+{
+    RenderSVGInlineText* textRenderer = toRenderSVGInlineText(this->textRenderer());
+    ASSERT(textRenderer);
+
+    float scalingFactor = textRenderer->scalingFactor();
+    ASSERT(scalingFactor);
+
+    RenderStyle* style = textRenderer->style();
+    ASSERT(style);
+
+    TextRun textRun = constructTextRun(style, fragment);
+
+    // Eventually handle lengthAdjust="spacingAndGlyphs".
+    // FIXME: Handle vertical text.
+    AffineTransform fragmentTransform;
+    fragment.buildFragmentTransform(fragmentTransform);
+    if (!fragmentTransform.isIdentity())
+        textRun.setHorizontalGlyphStretch(narrowPrecisionToFloat(fragmentTransform.xScale()));
+
+    return fragment.characterOffset - start() + textRenderer->scaledFont().offsetForPosition(textRun, position * scalingFactor, includePartialGlyphs);
+}
+
+float SVGInlineTextBox::positionForOffset(int) const
+{
+    // SVG doesn't use the offset <-> position selection system. 
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
+FloatRect SVGInlineTextBox::selectionRectForTextFragment(const SVGTextFragment& fragment, int startPosition, int endPosition, RenderStyle* style)
+{
+    ASSERT(startPosition < endPosition);
+    ASSERT(style);
+
+    FontCachePurgePreventer fontCachePurgePreventer;
+
+    RenderSVGInlineText* textRenderer = toRenderSVGInlineText(this->textRenderer());
+    ASSERT(textRenderer);
+
+    float scalingFactor = textRenderer->scalingFactor();
+    ASSERT(scalingFactor);
+
+    const Font& scaledFont = textRenderer->scaledFont();
+    const FontMetrics& scaledFontMetrics = scaledFont.fontMetrics();
+    FloatPoint textOrigin(fragment.x, fragment.y);
+    if (scalingFactor != 1)
+        textOrigin.scale(scalingFactor, scalingFactor);
+
+    textOrigin.move(0, -scaledFontMetrics.floatAscent());
+
+    FloatRect selectionRect = scaledFont.selectionRectForText(constructTextRun(style, fragment), textOrigin, fragment.height * scalingFactor, startPosition, endPosition);
+    if (scalingFactor == 1)
+        return selectionRect;
+
+    selectionRect.scale(1 / scalingFactor);
+    return selectionRect;
+}
+
+LayoutRect SVGInlineTextBox::localSelectionRect(int startPosition, int endPosition)
+{
+    int boxStart = start();
+    startPosition = max(startPosition - boxStart, 0);
+    endPosition = min(endPosition - boxStart, static_cast<int>(len()));
+    if (startPosition >= endPosition)
+        return LayoutRect();
+
+    RenderText* text = textRenderer();
+    ASSERT(text);
+
+    RenderStyle* style = text->style();
+    ASSERT(style);
+
+    AffineTransform fragmentTransform;
+    FloatRect selectionRect;
+    int fragmentStartPosition = 0;
+    int fragmentEndPosition = 0;
+
+    unsigned textFragmentsSize = m_textFragments.size();
+    for (unsigned i = 0; i < textFragmentsSize; ++i) {
+        const SVGTextFragment& fragment = m_textFragments.at(i);
+
+        fragmentStartPosition = startPosition;
+        fragmentEndPosition = endPosition;
+        if (!mapStartEndPositionsIntoFragmentCoordinates(fragment, fragmentStartPosition, fragmentEndPosition))
+            continue;
+
+        FloatRect fragmentRect = selectionRectForTextFragment(fragment, fragmentStartPosition, fragmentEndPosition, style);
+        fragment.buildFragmentTransform(fragmentTransform);
+        if (!fragmentTransform.isIdentity())
+            fragmentRect = fragmentTransform.mapRect(fragmentRect);
+
+        selectionRect.unite(fragmentRect);
+    }
+
+    return enclosingIntRect(selectionRect);
+}
+
+static inline bool textShouldBePainted(RenderSVGInlineText* textRenderer)
+{
+    // Font::pixelSize(), returns FontDescription::computedPixelSize(), which returns "int(x + 0.5)".
+    // If the absolute font size on screen is below x=0.5, don't render anything.
+    return textRenderer->scaledFont().pixelSize();
+}
+
+void SVGInlineTextBox::paintSelectionBackground(PaintInfo& paintInfo)
+{
+    ASSERT(paintInfo.shouldPaintWithinRoot(renderer()));
+    ASSERT(paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection);
+    ASSERT(truncation() == cNoTruncation);
+
+    if (renderer()->style()->visibility() != VISIBLE)
+        return;
+
+    RenderObject* parentRenderer = parent()->renderer();
+    ASSERT(parentRenderer);
+    ASSERT(!parentRenderer->document()->printing());
+
+    // Determine whether or not we're selected.
+    bool paintSelectedTextOnly = paintInfo.phase == PaintPhaseSelection;
+    bool hasSelection = selectionState() != RenderObject::SelectionNone;
+    if (!hasSelection || paintSelectedTextOnly)
+        return;
+
+    Color backgroundColor = renderer()->selectionBackgroundColor();
+    if (!backgroundColor.isValid() || !backgroundColor.alpha())
+        return;
+
+    RenderSVGInlineText* textRenderer = toRenderSVGInlineText(this->textRenderer());
+    ASSERT(textRenderer);
+    if (!textShouldBePainted(textRenderer))
+        return;
+
+    RenderStyle* style = parentRenderer->style();
+    ASSERT(style);
+
+    RenderStyle* selectionStyle = style;
+    if (hasSelection) {
+        selectionStyle = parentRenderer->getCachedPseudoStyle(SELECTION);
+        if (!selectionStyle)
+            selectionStyle = style;
+    }
+
+    int startPosition, endPosition;
+    selectionStartEnd(startPosition, endPosition);
+
+    int fragmentStartPosition = 0;
+    int fragmentEndPosition = 0;
+    AffineTransform fragmentTransform;
+    unsigned textFragmentsSize = m_textFragments.size();
+    for (unsigned i = 0; i < textFragmentsSize; ++i) {
+        SVGTextFragment& fragment = m_textFragments.at(i);
+        ASSERT(!m_paintingResource);
+
+        fragmentStartPosition = startPosition;
+        fragmentEndPosition = endPosition;
+        if (!mapStartEndPositionsIntoFragmentCoordinates(fragment, fragmentStartPosition, fragmentEndPosition))
+            continue;
+
+        GraphicsContextStateSaver stateSaver(*paintInfo.context);
+        fragment.buildFragmentTransform(fragmentTransform);
+        if (!fragmentTransform.isIdentity())
+            paintInfo.context->concatCTM(fragmentTransform);
+
+        paintInfo.context->setFillColor(backgroundColor, style->colorSpace());
+        paintInfo.context->fillRect(selectionRectForTextFragment(fragment, fragmentStartPosition, fragmentEndPosition, style), backgroundColor, style->colorSpace());
+
+        m_paintingResourceMode = ApplyToDefaultMode;
+    }
+
+    ASSERT(!m_paintingResource);
+}
+
+void SVGInlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint&, LayoutUnit, LayoutUnit)
+{
+    ASSERT(paintInfo.shouldPaintWithinRoot(renderer()));
+    ASSERT(paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection);
+    ASSERT(truncation() == cNoTruncation);
+
+    if (renderer()->style()->visibility() != VISIBLE)
+        return;
+
+    // Note: We're explicitely not supporting composition & custom underlines and custom highlighters - unlike InlineTextBox.
+    // If we ever need that for SVG, it's very easy to refactor and reuse the code.
+
+    RenderObject* parentRenderer = parent()->renderer();
+    ASSERT(parentRenderer);
+
+    bool paintSelectedTextOnly = paintInfo.phase == PaintPhaseSelection;
+    bool hasSelection = !parentRenderer->document()->printing() && selectionState() != RenderObject::SelectionNone;
+    if (!hasSelection && paintSelectedTextOnly)
+        return;
+
+    RenderSVGInlineText* textRenderer = toRenderSVGInlineText(this->textRenderer());
+    ASSERT(textRenderer);
+    if (!textShouldBePainted(textRenderer))
+        return;
+
+    RenderStyle* style = parentRenderer->style();
+    ASSERT(style);
+
+    const SVGRenderStyle* svgStyle = style->svgStyle();
+    ASSERT(svgStyle);
+
+    bool hasFill = svgStyle->hasFill();
+    bool hasVisibleStroke = svgStyle->hasVisibleStroke();
+
+    RenderStyle* selectionStyle = style;
+    if (hasSelection) {
+        selectionStyle = parentRenderer->getCachedPseudoStyle(SELECTION);
+        if (selectionStyle) {
+            const SVGRenderStyle* svgSelectionStyle = selectionStyle->svgStyle();
+            ASSERT(svgSelectionStyle);
+
+            if (!hasFill)
+                hasFill = svgSelectionStyle->hasFill();
+            if (!hasVisibleStroke)
+                hasVisibleStroke = svgSelectionStyle->hasVisibleStroke();
+        } else
+            selectionStyle = style;
+    }
+
+    if (textRenderer->frame() && textRenderer->frame()->view() && textRenderer->frame()->view()->paintBehavior() & PaintBehaviorRenderingSVGMask) {
+        hasFill = true;
+        hasVisibleStroke = false;
+    }
+
+    AffineTransform fragmentTransform;
+    unsigned textFragmentsSize = m_textFragments.size();
+    for (unsigned i = 0; i < textFragmentsSize; ++i) {
+        SVGTextFragment& fragment = m_textFragments.at(i);
+        ASSERT(!m_paintingResource);
+
+        GraphicsContextStateSaver stateSaver(*paintInfo.context);
+        fragment.buildFragmentTransform(fragmentTransform);
+        if (!fragmentTransform.isIdentity())
+            paintInfo.context->concatCTM(fragmentTransform);
+
+        // Spec: All text decorations except line-through should be drawn before the text is filled and stroked; thus, the text is rendered on top of these decorations.
+        int decorations = style->textDecorationsInEffect();
+        if (decorations & UNDERLINE)
+            paintDecoration(paintInfo.context, UNDERLINE, fragment);
+        if (decorations & OVERLINE)
+            paintDecoration(paintInfo.context, OVERLINE, fragment);
+
+        // Fill text
+        if (hasFill) {
+            m_paintingResourceMode = ApplyToFillMode | ApplyToTextMode;
+            paintText(paintInfo.context, style, selectionStyle, fragment, hasSelection, paintSelectedTextOnly);
+        }
+
+        // Stroke text
+        if (hasVisibleStroke) {
+            m_paintingResourceMode = ApplyToStrokeMode | ApplyToTextMode;
+            paintText(paintInfo.context, style, selectionStyle, fragment, hasSelection, paintSelectedTextOnly);
+        }
+
+        // Spec: Line-through should be drawn after the text is filled and stroked; thus, the line-through is rendered on top of the text.
+        if (decorations & LINE_THROUGH)
+            paintDecoration(paintInfo.context, LINE_THROUGH, fragment);
+
+        m_paintingResourceMode = ApplyToDefaultMode;
+    }
+
+    ASSERT(!m_paintingResource);
+}
+
+bool SVGInlineTextBox::acquirePaintingResource(GraphicsContext*& context, float scalingFactor, RenderObject* renderer, RenderStyle* style)
+{
+    ASSERT(scalingFactor);
+    ASSERT(renderer);
+    ASSERT(style);
+    ASSERT(m_paintingResourceMode != ApplyToDefaultMode);
+
+    Color fallbackColor;
+    if (m_paintingResourceMode & ApplyToFillMode)
+        m_paintingResource = RenderSVGResource::fillPaintingResource(renderer, style, fallbackColor);
+    else if (m_paintingResourceMode & ApplyToStrokeMode)
+        m_paintingResource = RenderSVGResource::strokePaintingResource(renderer, style, fallbackColor);
+    else {
+        // We're either called for stroking or filling.
+        ASSERT_NOT_REACHED();
+    }
+
+    if (!m_paintingResource)
+        return false;
+
+    if (!m_paintingResource->applyResource(renderer, style, context, m_paintingResourceMode)) {
+        if (fallbackColor.isValid()) {
+            RenderSVGResourceSolidColor* fallbackResource = RenderSVGResource::sharedSolidPaintingResource();
+            fallbackResource->setColor(fallbackColor);
+
+            m_paintingResource = fallbackResource;
+            m_paintingResource->applyResource(renderer, style, context, m_paintingResourceMode);
+        }
+    }
+
+    if (scalingFactor != 1 && m_paintingResourceMode & ApplyToStrokeMode)
+        context->setStrokeThickness(context->strokeThickness() * scalingFactor);
+
+    return true;
+}
+
+void SVGInlineTextBox::releasePaintingResource(GraphicsContext*& context, const Path* path)
+{
+    ASSERT(m_paintingResource);
+
+    RenderObject* parentRenderer = parent()->renderer();
+    ASSERT(parentRenderer);
+
+    m_paintingResource->postApplyResource(parentRenderer, context, m_paintingResourceMode, path, /*RenderSVGShape*/ 0);
+    m_paintingResource = 0;
+}
+
+bool SVGInlineTextBox::prepareGraphicsContextForTextPainting(GraphicsContext*& context, float scalingFactor, TextRun& textRun, RenderStyle* style)
+{
+    bool acquiredResource = acquirePaintingResource(context, scalingFactor, parent()->renderer(), style);
+    if (!acquiredResource)
+        return false;
+
+#if ENABLE(SVG_FONTS)
+    // SVG Fonts need access to the painting resource used to draw the current text chunk.
+    TextRun::RenderingContext* renderingContext = textRun.renderingContext();
+    if (renderingContext)
+        static_cast<SVGTextRunRenderingContext*>(renderingContext)->setActivePaintingResource(m_paintingResource);
+#endif
+
+    return true;
+}
+
+void SVGInlineTextBox::restoreGraphicsContextAfterTextPainting(GraphicsContext*& context, TextRun& textRun)
+{
+    releasePaintingResource(context, /* path */0);
+
+#if ENABLE(SVG_FONTS)
+    TextRun::RenderingContext* renderingContext = textRun.renderingContext();
+    if (renderingContext)
+        static_cast<SVGTextRunRenderingContext*>(renderingContext)->setActivePaintingResource(0);
+#else
+    UNUSED_PARAM(textRun);
+#endif
+}
+
+TextRun SVGInlineTextBox::constructTextRun(RenderStyle* style, const SVGTextFragment& fragment) const
+{
+    ASSERT(style);
+    ASSERT(textRenderer());
+
+    RenderText* text = textRenderer();
+    ASSERT(text);
+
+    TextRun run(text->characters() + fragment.characterOffset
+                , fragment.length
+                , 0 /* xPos, only relevant with allowTabs=true */
+                , 0 /* padding, only relevant for justified text, not relevant for SVG */
+                , TextRun::AllowTrailingExpansion
+                , direction()
+                , dirOverride() || style->rtlOrdering() == VisualOrder /* directionalOverride */);
+
+    if (textRunNeedsRenderingContext(style->font()))
+        run.setRenderingContext(SVGTextRunRenderingContext::create(text));
+
+    run.disableRoundingHacks();
+
+    // We handle letter & word spacing ourselves.
+    run.disableSpacing();
+
+    // Propagate the maximum length of the characters buffer to the TextRun, even when we're only processing a substring.
+    run.setCharactersLength(text->textLength() - fragment.characterOffset);
+    ASSERT(run.charactersLength() >= run.length());
+    return run;
+}
+
+bool SVGInlineTextBox::mapStartEndPositionsIntoFragmentCoordinates(const SVGTextFragment& fragment, int& startPosition, int& endPosition) const
+{
+    if (startPosition >= endPosition)
+        return false;
+
+    int offset = static_cast<int>(fragment.characterOffset) - start();
+    int length = static_cast<int>(fragment.length);
+
+    if (startPosition >= offset + length || endPosition <= offset)
+        return false;
+
+    if (startPosition < offset)
+        startPosition = 0;
+    else
+        startPosition -= offset;
+
+    if (endPosition > offset + length)
+        endPosition = length;
+    else {
+        ASSERT(endPosition >= offset);
+        endPosition -= offset;
+    }
+
+    ASSERT(startPosition < endPosition);
+    return true;
+}
+
+static inline float positionOffsetForDecoration(ETextDecoration decoration, const FontMetrics& fontMetrics, float thickness)
+{
+    // FIXME: For SVG Fonts we need to use the attributes defined in the <font-face> if specified.
+    // Compatible with Batik/Opera.
+    if (decoration == UNDERLINE)
+        return fontMetrics.floatAscent() + thickness * 1.5f;
+    if (decoration == OVERLINE)
+        return thickness;
+    if (decoration == LINE_THROUGH)
+        return fontMetrics.floatAscent() * 5 / 8.0f;
+
+    ASSERT_NOT_REACHED();
+    return 0.0f;
+}
+
+static inline float thicknessForDecoration(ETextDecoration, const Font& font)
+{
+    // FIXME: For SVG Fonts we need to use the attributes defined in the <font-face> if specified.
+    // Compatible with Batik/Opera
+    return font.size() / 20.0f;
+}
+
+static inline RenderObject* findRenderObjectDefininingTextDecoration(InlineFlowBox* parentBox)
+{
+    // Lookup first render object in parent hierarchy which has text-decoration set.
+    RenderObject* renderer = 0;
+    while (parentBox) {
+        renderer = parentBox->renderer();
+
+        if (renderer->style() && renderer->style()->textDecoration() != TDNONE)
+            break;
+
+        parentBox = parentBox->parent();
+    }
+
+    ASSERT(renderer);
+    return renderer;
+}
+
+void SVGInlineTextBox::paintDecoration(GraphicsContext* context, ETextDecoration decoration, const SVGTextFragment& fragment)
+{
+    if (textRenderer()->style()->textDecorationsInEffect() == TDNONE)
+        return;
+
+    // Find out which render style defined the text-decoration, as its fill/stroke properties have to be used for drawing instead of ours.
+    RenderObject* decorationRenderer = findRenderObjectDefininingTextDecoration(parent());
+    RenderStyle* decorationStyle = decorationRenderer->style();
+    ASSERT(decorationStyle);
+
+    if (decorationStyle->visibility() == HIDDEN)
+        return;
+
+    const SVGRenderStyle* svgDecorationStyle = decorationStyle->svgStyle();
+    ASSERT(svgDecorationStyle);
+
+    bool hasDecorationFill = svgDecorationStyle->hasFill();
+    bool hasVisibleDecorationStroke = svgDecorationStyle->hasVisibleStroke();
+
+    if (hasDecorationFill) {
+        m_paintingResourceMode = ApplyToFillMode;
+        paintDecorationWithStyle(context, decoration, fragment, decorationRenderer);
+    }
+
+    if (hasVisibleDecorationStroke) {
+        m_paintingResourceMode = ApplyToStrokeMode;
+        paintDecorationWithStyle(context, decoration, fragment, decorationRenderer);
+    }
+}
+
+void SVGInlineTextBox::paintDecorationWithStyle(GraphicsContext* context, ETextDecoration decoration, const SVGTextFragment& fragment, RenderObject* decorationRenderer)
+{
+    ASSERT(!m_paintingResource);
+    ASSERT(m_paintingResourceMode != ApplyToDefaultMode);
+
+    RenderStyle* decorationStyle = decorationRenderer->style();
+    ASSERT(decorationStyle);
+
+    float scalingFactor = 1;
+    Font scaledFont;
+    RenderSVGInlineText::computeNewScaledFontForStyle(decorationRenderer, decorationStyle, scalingFactor, scaledFont);
+    ASSERT(scalingFactor);
+
+    // The initial y value refers to overline position.
+    float thickness = thicknessForDecoration(decoration, scaledFont);
+
+    if (fragment.width <= 0 && thickness <= 0)
+        return;
+
+    FloatPoint decorationOrigin(fragment.x, fragment.y);
+    float width = fragment.width;
+    const FontMetrics& scaledFontMetrics = scaledFont.fontMetrics();
+
+    GraphicsContextStateSaver stateSaver(*context);
+    if (scalingFactor != 1) {
+        width *= scalingFactor;
+        decorationOrigin.scale(scalingFactor, scalingFactor);
+        context->scale(FloatSize(1 / scalingFactor, 1 / scalingFactor));
+    }
+
+    decorationOrigin.move(0, -scaledFontMetrics.floatAscent() + positionOffsetForDecoration(decoration, scaledFontMetrics, thickness));
+
+    Path path;
+    path.addRect(FloatRect(decorationOrigin, FloatSize(width, thickness)));
+
+    if (acquirePaintingResource(context, scalingFactor, decorationRenderer, decorationStyle))
+        releasePaintingResource(context, &path);
+}
+
+void SVGInlineTextBox::paintTextWithShadows(GraphicsContext* context, RenderStyle* style, TextRun& textRun, const SVGTextFragment& fragment, int startPosition, int endPosition)
+{
+    RenderSVGInlineText* textRenderer = toRenderSVGInlineText(this->textRenderer());
+    ASSERT(textRenderer);
+
+    float scalingFactor = textRenderer->scalingFactor();
+    ASSERT(scalingFactor);
+
+    const Font& scaledFont = textRenderer->scaledFont();
+    const ShadowData* shadow = style->textShadow();
+
+    FloatPoint textOrigin(fragment.x, fragment.y);
+    FloatSize textSize(fragment.width, fragment.height);
+
+    if (scalingFactor != 1) {
+        textOrigin.scale(scalingFactor, scalingFactor);
+        textSize.scale(scalingFactor);
+    }
+
+    FloatRect shadowRect(FloatPoint(textOrigin.x(), textOrigin.y() - scaledFont.fontMetrics().floatAscent()), textSize);
+
+    do {
+        if (!prepareGraphicsContextForTextPainting(context, scalingFactor, textRun, style))
+            break;
+
+        FloatSize extraOffset;
+        if (shadow)
+            extraOffset = applyShadowToGraphicsContext(context, shadow, shadowRect, false /* stroked */, true /* opaque */, true /* horizontal */);
+
+        context->save();
+        context->scale(FloatSize(1 / scalingFactor, 1 / scalingFactor));
+
+        scaledFont.drawText(context, textRun, textOrigin + extraOffset, startPosition, endPosition);
+
+        context->restore();
+
+        restoreGraphicsContextAfterTextPainting(context, textRun);
+
+        if (!shadow)
+            break;
+
+        if (shadow->next())
+            context->restore();
+        else
+            context->clearShadow();
+
+        shadow = shadow->next();
+    } while (shadow);
+}
+
+void SVGInlineTextBox::paintText(GraphicsContext* context, RenderStyle* style, RenderStyle* selectionStyle, const SVGTextFragment& fragment, bool hasSelection, bool paintSelectedTextOnly)
+{
+    ASSERT(style);
+    ASSERT(selectionStyle);
+
+    int startPosition = 0;
+    int endPosition = 0;
+    if (hasSelection) {
+        selectionStartEnd(startPosition, endPosition);
+        hasSelection = mapStartEndPositionsIntoFragmentCoordinates(fragment, startPosition, endPosition);
+    }
+
+    // Fast path if there is no selection, just draw the whole chunk part using the regular style
+    TextRun textRun = constructTextRun(style, fragment);
+    if (!hasSelection || startPosition >= endPosition) {
+        paintTextWithShadows(context, style, textRun, fragment, 0, fragment.length);
+        return;
+    }
+
+    // Eventually draw text using regular style until the start position of the selection
+    if (startPosition > 0 && !paintSelectedTextOnly)
+        paintTextWithShadows(context, style, textRun, fragment, 0, startPosition);
+
+    // Draw text using selection style from the start to the end position of the selection
+    if (style != selectionStyle)
+        SVGResourcesCache::clientStyleChanged(parent()->renderer(), StyleDifferenceRepaint, selectionStyle);
+
+    TextRun selectionTextRun = constructTextRun(selectionStyle, fragment);
+    paintTextWithShadows(context, selectionStyle, textRun, fragment, startPosition, endPosition);
+
+    if (style != selectionStyle)
+        SVGResourcesCache::clientStyleChanged(parent()->renderer(), StyleDifferenceRepaint, style);
+
+    // Eventually draw text using regular style from the end position of the selection to the end of the current chunk part
+    if (endPosition < static_cast<int>(fragment.length) && !paintSelectedTextOnly)
+        paintTextWithShadows(context, style, textRun, fragment, endPosition, fragment.length);
+}
+
+FloatRect SVGInlineTextBox::calculateBoundaries() const
+{
+    FloatRect textRect;
+
+    RenderSVGInlineText* textRenderer = toRenderSVGInlineText(this->textRenderer());
+    ASSERT(textRenderer);
+
+    float scalingFactor = textRenderer->scalingFactor();
+    ASSERT(scalingFactor);
+
+    float baseline = textRenderer->scaledFont().fontMetrics().floatAscent() / scalingFactor;
+
+    AffineTransform fragmentTransform;
+    unsigned textFragmentsSize = m_textFragments.size();
+    for (unsigned i = 0; i < textFragmentsSize; ++i) {
+        const SVGTextFragment& fragment = m_textFragments.at(i);
+        FloatRect fragmentRect(fragment.x, fragment.y - baseline, fragment.width, fragment.height);
+        fragment.buildFragmentTransform(fragmentTransform);
+        if (!fragmentTransform.isIdentity())
+            fragmentRect = fragmentTransform.mapRect(fragmentRect);
+
+        textRect.unite(fragmentRect);
+    }
+
+    return textRect;
+}
+
+bool SVGInlineTextBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit, LayoutUnit)
+{
+    // FIXME: integrate with InlineTextBox::nodeAtPoint better.
+    ASSERT(!isLineBreak());
+
+    PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_TEXT_HITTESTING, request, renderer()->style()->pointerEvents());
+    bool isVisible = renderer()->style()->visibility() == VISIBLE;
+    if (isVisible || !hitRules.requireVisible) {
+        if ((hitRules.canHitStroke && (renderer()->style()->svgStyle()->hasStroke() || !hitRules.requireStroke))
+            || (hitRules.canHitFill && (renderer()->style()->svgStyle()->hasFill() || !hitRules.requireFill))) {
+            FloatPoint boxOrigin(x(), y());
+            boxOrigin.moveBy(accumulatedOffset);
+            FloatRect rect(boxOrigin, size());
+            if (locationInContainer.intersects(rect)) {
+                renderer()->updateHitTestResult(result, locationInContainer.point() - toLayoutSize(accumulatedOffset));
+                if (!result.addNodeToRectBasedTestResult(renderer()->node(), request, locationInContainer, rect))
+                    return true;
+             }
+        }
+    }
+    return false;
+}
+
+} // namespace WebCore
+
+#endif
diff --git a/Source/core/rendering/svg/SVGInlineTextBox.h b/Source/core/rendering/svg/SVGInlineTextBox.h
new file mode 100644
index 0000000..9be999f
--- /dev/null
+++ b/Source/core/rendering/svg/SVGInlineTextBox.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2007 Rob Buis <buis@kde.org>
+ * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) Research In Motion Limited 2010. 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 SVGInlineTextBox_h
+#define SVGInlineTextBox_h
+
+#if ENABLE(SVG)
+#include "core/rendering/InlineTextBox.h"
+#include "core/rendering/svg/SVGTextLayoutEngine.h"
+
+namespace WebCore {
+
+class RenderSVGResource;
+class SVGRootInlineBox;
+
+class SVGInlineTextBox FINAL : public InlineTextBox {
+public:
+    SVGInlineTextBox(RenderObject*);
+
+    virtual bool isSVGInlineTextBox() const { return true; }
+
+    virtual float virtualLogicalHeight() const { return m_logicalHeight; }
+    void setLogicalHeight(float height) { m_logicalHeight = height; }
+
+    virtual int selectionTop() { return top(); }
+    virtual int selectionHeight() { return static_cast<int>(ceilf(m_logicalHeight)); }
+    virtual int offsetForPosition(float x, bool includePartialGlyphs = true) const;
+    virtual float positionForOffset(int offset) const;
+
+    void paintSelectionBackground(PaintInfo&);
+    virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom);
+    virtual LayoutRect localSelectionRect(int startPosition, int endPosition);
+
+    bool mapStartEndPositionsIntoFragmentCoordinates(const SVGTextFragment&, int& startPosition, int& endPosition) const;
+
+    virtual FloatRect calculateBoundaries() const;
+
+    void clearTextFragments() { m_textFragments.clear(); }
+    Vector<SVGTextFragment>& textFragments() { return m_textFragments; }
+    const Vector<SVGTextFragment>& textFragments() const { return m_textFragments; }
+
+    virtual void dirtyLineBoxes() OVERRIDE;
+
+    bool startsNewTextChunk() const { return m_startsNewTextChunk; }
+    void setStartsNewTextChunk(bool newTextChunk) { m_startsNewTextChunk = newTextChunk; }
+
+    int offsetForPositionInFragment(const SVGTextFragment&, float position, bool includePartialGlyphs) const;
+    FloatRect selectionRectForTextFragment(const SVGTextFragment&, int fragmentStartPosition, int fragmentEndPosition, RenderStyle*);
+
+private:
+    TextRun constructTextRun(RenderStyle*, const SVGTextFragment&) const;
+
+    bool acquirePaintingResource(GraphicsContext*&, float scalingFactor, RenderObject*, RenderStyle*);
+    void releasePaintingResource(GraphicsContext*&, const Path*);
+
+    bool prepareGraphicsContextForTextPainting(GraphicsContext*&, float scalingFactor, TextRun&, RenderStyle*);
+    void restoreGraphicsContextAfterTextPainting(GraphicsContext*&, TextRun&);
+
+    void paintDecoration(GraphicsContext*, ETextDecoration, const SVGTextFragment&);
+    void paintDecorationWithStyle(GraphicsContext*, ETextDecoration, const SVGTextFragment&, RenderObject* decorationRenderer);
+    void paintTextWithShadows(GraphicsContext*, RenderStyle*, TextRun&, const SVGTextFragment&, int startPosition, int endPosition);
+    void paintText(GraphicsContext*, RenderStyle*, RenderStyle* selectionStyle, const SVGTextFragment&, bool hasSelection, bool paintSelectedTextOnly);
+
+    virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit lineTop, LayoutUnit lineBottom) OVERRIDE;
+
+private:
+    float m_logicalHeight;
+    unsigned m_paintingResourceMode : 4;
+    unsigned m_startsNewTextChunk : 1;
+    RenderSVGResource* m_paintingResource;
+    Vector<SVGTextFragment> m_textFragments;
+};
+
+} // namespace WebCore
+
+#endif
+#endif // SVGInlineTextBox_h
diff --git a/Source/core/rendering/svg/SVGMarkerData.h b/Source/core/rendering/svg/SVGMarkerData.h
new file mode 100644
index 0000000..5cd0598
--- /dev/null
+++ b/Source/core/rendering/svg/SVGMarkerData.h
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) Research In Motion Limited 2010. 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 SVGMarkerData_h
+#define SVGMarkerData_h
+
+#if ENABLE(SVG)
+#include "core/platform/FloatConversion.h"
+#include "core/platform/graphics/Path.h"
+#include <wtf/MathExtras.h>
+
+namespace WebCore {
+
+class RenderSVGResourceMarker;
+
+enum SVGMarkerType {
+    StartMarker,
+    MidMarker,
+    EndMarker
+};
+
+struct MarkerPosition {
+    MarkerPosition(SVGMarkerType useType, const FloatPoint& useOrigin, float useAngle)
+        : type(useType)
+        , origin(useOrigin)
+        , angle(useAngle)
+    {
+    }
+
+    SVGMarkerType type;
+    FloatPoint origin;
+    float angle;
+};
+
+class SVGMarkerData {
+public:
+    SVGMarkerData(Vector<MarkerPosition>& positions)
+        : m_positions(positions)
+        , m_elementIndex(0)
+    {
+    }
+
+    static void updateFromPathElement(void* info, const PathElement* element)
+    {
+        SVGMarkerData* markerData = static_cast<SVGMarkerData*>(info);
+
+        // First update the outslope for the previous element.
+        markerData->updateOutslope(element->points[0]);
+
+        // Record the marker for the previous element.
+        if (markerData->m_elementIndex > 0) {
+            SVGMarkerType markerType = markerData->m_elementIndex == 1 ? StartMarker : MidMarker;
+            markerData->m_positions.append(MarkerPosition(markerType, markerData->m_origin, markerData->currentAngle(markerType)));
+        }
+
+        // Update our marker data for this element.
+        markerData->updateMarkerDataForPathElement(element);
+        ++markerData->m_elementIndex;
+    }
+
+    void pathIsDone()
+    {
+        m_positions.append(MarkerPosition(EndMarker, m_origin, currentAngle(EndMarker)));
+    }
+
+private:
+    float currentAngle(SVGMarkerType type) const
+    {
+        // For details of this calculation, see: http://www.w3.org/TR/SVG/single-page.html#painting-MarkerElement
+        FloatPoint inSlope(m_inslopePoints[1] - m_inslopePoints[0]);
+        FloatPoint outSlope(m_outslopePoints[1] - m_outslopePoints[0]);
+
+        double inAngle = rad2deg(inSlope.slopeAngleRadians());
+        double outAngle = rad2deg(outSlope.slopeAngleRadians());
+
+        switch (type) {
+        case StartMarker:
+            return narrowPrecisionToFloat(outAngle);
+        case MidMarker:
+            // WK193015: Prevent bugs due to angles being non-continuous.
+            if (fabs(inAngle - outAngle) > 180)
+                inAngle += 360;
+            return narrowPrecisionToFloat((inAngle + outAngle) / 2);
+        case EndMarker:
+            return narrowPrecisionToFloat(inAngle);
+        }
+
+        ASSERT_NOT_REACHED();
+        return 0;
+    }
+
+    void updateOutslope(const FloatPoint& point)
+    {
+        m_outslopePoints[0] = m_origin;
+        m_outslopePoints[1] = point;
+    }
+
+    void updateMarkerDataForPathElement(const PathElement* element)
+    {
+        FloatPoint* points = element->points;
+
+        switch (element->type) {
+        case PathElementAddQuadCurveToPoint:
+            // FIXME: https://bugs.webkit.org/show_bug.cgi?id=33115 (PathElementAddQuadCurveToPoint not handled for <marker>)
+            m_origin = points[1];
+            break;
+        case PathElementAddCurveToPoint:
+            m_inslopePoints[0] = points[1];
+            m_inslopePoints[1] = points[2];
+            m_origin = points[2];
+            break;
+        case PathElementMoveToPoint:
+            m_subpathStart = points[0];
+        case PathElementAddLineToPoint:
+            updateInslope(points[0]);
+            m_origin = points[0];
+            break;
+        case PathElementCloseSubpath:
+            updateInslope(points[0]);
+            m_origin = m_subpathStart;
+            m_subpathStart = FloatPoint();
+        }
+    }
+
+    void updateInslope(const FloatPoint& point)
+    {
+        m_inslopePoints[0] = m_origin;
+        m_inslopePoints[1] = point;
+    }
+
+    Vector<MarkerPosition>& m_positions;
+    unsigned m_elementIndex;
+    FloatPoint m_origin;
+    FloatPoint m_subpathStart;
+    FloatPoint m_inslopePoints[2];
+    FloatPoint m_outslopePoints[2];
+};
+
+}
+
+#endif // ENABLE(SVG)
+#endif // SVGMarkerData_h
diff --git a/Source/core/rendering/svg/SVGPathData.cpp b/Source/core/rendering/svg/SVGPathData.cpp
new file mode 100644
index 0000000..96a6788
--- /dev/null
+++ b/Source/core/rendering/svg/SVGPathData.cpp
@@ -0,0 +1,171 @@
+/*
+ * Copyright (C) Research In Motion Limited 2011. 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 "core/rendering/svg/SVGPathData.h"
+
+#if ENABLE(SVG)
+#include "SVGNames.h"
+#include "core/platform/graphics/Path.h"
+#include "core/svg/SVGCircleElement.h"
+#include "core/svg/SVGEllipseElement.h"
+#include "core/svg/SVGLineElement.h"
+#include "core/svg/SVGPathElement.h"
+#include "core/svg/SVGPathUtilities.h"
+#include "core/svg/SVGPolygonElement.h"
+#include "core/svg/SVGPolylineElement.h"
+#include "core/svg/SVGRectElement.h"
+#include <wtf/HashMap.h>
+
+namespace WebCore {
+
+static void updatePathFromCircleElement(SVGElement* element, Path& path)
+{
+    ASSERT(element->hasTagName(SVGNames::circleTag));
+    SVGCircleElement* circle = static_cast<SVGCircleElement*>(element);
+
+    SVGLengthContext lengthContext(element);
+    float r = circle->r().value(lengthContext);
+    if (r > 0)
+        path.addEllipse(FloatRect(circle->cx().value(lengthContext) - r, circle->cy().value(lengthContext) - r, r * 2, r * 2));
+}
+
+static void updatePathFromEllipseElement(SVGElement* element, Path& path)
+{
+    ASSERT(element->hasTagName(SVGNames::ellipseTag));
+    SVGEllipseElement* ellipse = static_cast<SVGEllipseElement*>(element);
+
+    SVGLengthContext lengthContext(element);
+    float rx = ellipse->rx().value(lengthContext);
+    if (rx <= 0)
+        return;
+    float ry = ellipse->ry().value(lengthContext);
+    if (ry <= 0)
+        return;
+    path.addEllipse(FloatRect(ellipse->cx().value(lengthContext) - rx, ellipse->cy().value(lengthContext) - ry, rx * 2, ry * 2));
+}
+
+static void updatePathFromLineElement(SVGElement* element, Path& path)
+{
+    ASSERT(element->hasTagName(SVGNames::lineTag));
+    SVGLineElement* line = static_cast<SVGLineElement*>(element);
+
+    SVGLengthContext lengthContext(element);
+    path.moveTo(FloatPoint(line->x1().value(lengthContext), line->y1().value(lengthContext)));
+    path.addLineTo(FloatPoint(line->x2().value(lengthContext), line->y2().value(lengthContext)));
+}
+
+static void updatePathFromPathElement(SVGElement* element, Path& path)
+{
+    ASSERT(element->hasTagName(SVGNames::pathTag));
+    buildPathFromByteStream(static_cast<SVGPathElement*>(element)->pathByteStream(), path);
+}
+
+static void updatePathFromPolygonElement(SVGElement* element, Path& path)
+{
+    ASSERT(element->hasTagName(SVGNames::polygonTag));
+    SVGPolygonElement* polygon = static_cast<SVGPolygonElement*>(element);
+
+    SVGPointList& points = polygon->pointList();
+    if (points.isEmpty())
+        return;
+
+    path.moveTo(points.first());
+
+    unsigned size = points.size();
+    for (unsigned i = 1; i < size; ++i)
+        path.addLineTo(points.at(i));
+
+    path.closeSubpath();
+}
+
+static void updatePathFromPolylineElement(SVGElement* element, Path& path)
+{
+    ASSERT(element->hasTagName(SVGNames::polylineTag));
+    SVGPolylineElement* polyline = static_cast<SVGPolylineElement*>(element);
+
+    SVGPointList& points = polyline->pointList();
+    if (points.isEmpty())
+        return;
+
+    path.moveTo(points.first());
+
+    unsigned size = points.size();
+    for (unsigned i = 1; i < size; ++i)
+        path.addLineTo(points.at(i));
+}
+
+static void updatePathFromRectElement(SVGElement* element, Path& path)
+{
+    ASSERT(element->hasTagName(SVGNames::rectTag));
+    SVGRectElement* rect = static_cast<SVGRectElement*>(element);
+
+    SVGLengthContext lengthContext(element);
+    float width = rect->width().value(lengthContext);
+    if (width <= 0)
+        return;
+    float height = rect->height().value(lengthContext);
+    if (height <= 0)
+        return;
+    float x = rect->x().value(lengthContext);
+    float y = rect->y().value(lengthContext);
+    bool hasRx = rect->hasAttribute(SVGNames::rxAttr);
+    bool hasRy = rect->hasAttribute(SVGNames::ryAttr);
+    if (hasRx || hasRy) {
+        float rx = rect->rx().value(lengthContext);
+        float ry = rect->ry().value(lengthContext);
+        if (!hasRx)
+            rx = ry;
+        else if (!hasRy)
+            ry = rx;
+        // FIXME: We currently enforce using beziers here, as at least on CoreGraphics/Lion, as
+        // the native method uses a different line dash origin, causing svg/custom/dashOrigin.svg to fail.
+        // See bug https://bugs.webkit.org/show_bug.cgi?id=79932 which tracks this issue.
+        path.addRoundedRect(FloatRect(x, y, width, height), FloatSize(rx, ry), Path::PreferBezierRoundedRect);
+        return;
+    }
+
+    path.addRect(FloatRect(x, y, width, height));
+}
+
+void updatePathFromGraphicsElement(SVGElement* element, Path& path)
+{
+    ASSERT(element);
+    ASSERT(path.isEmpty());
+
+    typedef void (*PathUpdateFunction)(SVGElement*, Path&);
+    static HashMap<AtomicStringImpl*, PathUpdateFunction>* map = 0;
+    if (!map) {
+        map = new HashMap<AtomicStringImpl*, PathUpdateFunction>;
+        map->set(SVGNames::circleTag.localName().impl(), updatePathFromCircleElement);
+        map->set(SVGNames::ellipseTag.localName().impl(), updatePathFromEllipseElement);
+        map->set(SVGNames::lineTag.localName().impl(), updatePathFromLineElement);
+        map->set(SVGNames::pathTag.localName().impl(), updatePathFromPathElement);
+        map->set(SVGNames::polygonTag.localName().impl(), updatePathFromPolygonElement);
+        map->set(SVGNames::polylineTag.localName().impl(), updatePathFromPolylineElement);
+        map->set(SVGNames::rectTag.localName().impl(), updatePathFromRectElement);
+    }
+
+    if (PathUpdateFunction pathUpdateFunction = map->get(element->localName().impl()))
+        (*pathUpdateFunction)(element, path);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
diff --git a/Source/core/rendering/svg/SVGPathData.h b/Source/core/rendering/svg/SVGPathData.h
new file mode 100644
index 0000000..1a4b7ba
--- /dev/null
+++ b/Source/core/rendering/svg/SVGPathData.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) Research In Motion Limited 2011. 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 SVGPathData_h
+#define SVGPathData_h
+
+#if ENABLE(SVG)
+namespace WebCore {
+
+class SVGElement;
+class Path;
+
+void updatePathFromGraphicsElement(SVGElement*, Path&);
+
+};
+
+#endif // ENABLE(SVG)
+#endif // SVGPathData_h
diff --git a/Source/core/rendering/svg/SVGRenderSupport.cpp b/Source/core/rendering/svg/SVGRenderSupport.cpp
new file mode 100644
index 0000000..d066c91
--- /dev/null
+++ b/Source/core/rendering/svg/SVGRenderSupport.cpp
@@ -0,0 +1,468 @@
+/*
+ * Copyright (C) 2007, 2008 Rob Buis <buis@kde.org>
+ * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
+ * Copyright (C) 2009 Google, Inc.  All rights reserved.
+ * Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
+ * Copyright (C) Research In Motion Limited 2009-2010. 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"
+
+#if ENABLE(SVG)
+#include "core/rendering/svg/SVGRenderSupport.h"
+
+#include "core/dom/NodeRenderStyle.h"
+#include "core/platform/graphics/transforms/TransformState.h"
+#include "core/rendering/RenderGeometryMap.h"
+#include "core/rendering/RenderLayer.h"
+#include "core/rendering/svg/RenderSVGResource.h"
+#include "core/rendering/svg/RenderSVGResourceClipper.h"
+#include "core/rendering/svg/RenderSVGResourceFilter.h"
+#include "core/rendering/svg/RenderSVGResourceMarker.h"
+#include "core/rendering/svg/RenderSVGResourceMasker.h"
+#include "core/rendering/svg/RenderSVGRoot.h"
+#include "core/rendering/svg/RenderSVGText.h"
+#include "core/rendering/svg/RenderSVGViewportContainer.h"
+#include "core/rendering/svg/SVGResources.h"
+#include "core/rendering/svg/SVGResourcesCache.h"
+#include "core/svg/SVGStyledElement.h"
+#include <wtf/UnusedParam.h>
+
+namespace WebCore {
+
+FloatRect SVGRenderSupport::repaintRectForRendererInLocalCoordinatesExcludingSVGShadow(const RenderObject* object)
+{
+    // FIXME: Add support for RenderSVGBlock.
+
+    // FIXME: This should use a safer cast such as toRenderSVGModelObject().
+    if (object->isSVGShape() || object->isSVGImage() || object->isSVGContainer())
+        return static_cast<const RenderSVGModelObject*>(object)->repaintRectInLocalCoordinatesExcludingSVGShadow();
+
+    return object->repaintRectInLocalCoordinates();
+}
+
+LayoutRect SVGRenderSupport::clippedOverflowRectForRepaint(const RenderObject* object, const RenderLayerModelObject* repaintContainer)
+{
+    // Return early for any cases where we don't actually paint
+    if (object->style()->visibility() != VISIBLE && !object->enclosingLayer()->hasVisibleContent())
+        return LayoutRect();
+
+    // Pass our local paint rect to computeRectForRepaint() which will
+    // map to parent coords and recurse up the parent chain.
+    FloatRect repaintRect = repaintRectForRendererInLocalCoordinatesExcludingSVGShadow(object);
+    const SVGRenderStyle* svgStyle = object->style()->svgStyle();
+    if (const ShadowData* shadow = svgStyle->shadow())
+        shadow->adjustRectForShadow(repaintRect);
+    object->computeFloatRectForRepaint(repaintContainer, repaintRect);
+    return enclosingLayoutRect(repaintRect);
+}
+
+void SVGRenderSupport::computeFloatRectForRepaint(const RenderObject* object, const RenderLayerModelObject* repaintContainer, FloatRect& repaintRect, bool fixed)
+{
+    const SVGRenderStyle* svgStyle = object->style()->svgStyle();
+    if (const ShadowData* shadow = svgStyle->shadow())
+        shadow->adjustRectForShadow(repaintRect);
+    repaintRect.inflate(object->style()->outlineWidth());
+
+    // Translate to coords in our parent renderer, and then call computeFloatRectForRepaint() on our parent.
+    repaintRect = object->localToParentTransform().mapRect(repaintRect);
+    object->parent()->computeFloatRectForRepaint(repaintContainer, repaintRect, fixed);
+}
+
+void SVGRenderSupport::mapLocalToContainer(const RenderObject* object, const RenderLayerModelObject* repaintContainer, TransformState& transformState, bool* wasFixed)
+{
+    transformState.applyTransform(object->localToParentTransform());
+
+    RenderObject* parent = object->parent();
+    
+    // At the SVG/HTML boundary (aka RenderSVGRoot), we apply the localToBorderBoxTransform 
+    // to map an element from SVG viewport coordinates to CSS box coordinates.
+    // RenderSVGRoot's mapLocalToContainer method expects CSS box coordinates.
+    if (parent->isSVGRoot())
+        transformState.applyTransform(toRenderSVGRoot(parent)->localToBorderBoxTransform());
+
+    MapCoordinatesFlags mode = UseTransforms;
+    parent->mapLocalToContainer(repaintContainer, transformState, mode, wasFixed);
+}
+
+const RenderObject* SVGRenderSupport::pushMappingToContainer(const RenderObject* object, const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap& geometryMap)
+{
+    ASSERT_UNUSED(ancestorToStopAt, ancestorToStopAt != object);
+
+    RenderObject* parent = object->parent();
+
+    // At the SVG/HTML boundary (aka RenderSVGRoot), we apply the localToBorderBoxTransform 
+    // to map an element from SVG viewport coordinates to CSS box coordinates.
+    // RenderSVGRoot's mapLocalToContainer method expects CSS box coordinates.
+    if (parent->isSVGRoot()) {
+        TransformationMatrix matrix(object->localToParentTransform());
+        matrix.multiply(toRenderSVGRoot(parent)->localToBorderBoxTransform());
+        geometryMap.push(object, matrix);
+    } else
+        geometryMap.push(object, object->localToParentTransform());
+
+    return parent;
+}
+
+bool SVGRenderSupport::checkForSVGRepaintDuringLayout(RenderObject* object)
+{
+    if (!object->checkForRepaintDuringLayout())
+        return false;
+    // When a parent container is transformed in SVG, all children will be painted automatically
+    // so we are able to skip redundant repaint checks.
+    RenderObject* parent = object->parent();
+    return !(parent && parent->isSVGContainer() && toRenderSVGContainer(parent)->didTransformToRootUpdate());
+}
+
+// Update a bounding box taking into account the validity of the other bounding box.
+static inline void updateObjectBoundingBox(FloatRect& objectBoundingBox, bool& objectBoundingBoxValid, RenderObject* other, FloatRect otherBoundingBox)
+{
+    bool otherValid = other->isSVGContainer() ? toRenderSVGContainer(other)->isObjectBoundingBoxValid() : true;
+    if (!otherValid)
+        return;
+
+    if (!objectBoundingBoxValid) {
+        objectBoundingBox = otherBoundingBox;
+        objectBoundingBoxValid = true;
+        return;
+    }
+
+    objectBoundingBox.uniteEvenIfEmpty(otherBoundingBox);
+}
+
+void SVGRenderSupport::computeContainerBoundingBoxes(const RenderObject* container, FloatRect& objectBoundingBox, bool& objectBoundingBoxValid, FloatRect& strokeBoundingBox, FloatRect& repaintBoundingBox)
+{
+    objectBoundingBox = FloatRect();
+    objectBoundingBoxValid = false;
+    strokeBoundingBox = FloatRect();
+
+    // When computing the strokeBoundingBox, we use the repaintRects of the container's children so that the container's stroke includes
+    // the resources applied to the children (such as clips and filters). This allows filters applied to containers to correctly bound
+    // the children, and also improves inlining of SVG content, as the stroke bound is used in that situation also.
+    for (RenderObject* current = container->firstChild(); current; current = current->nextSibling()) {
+        if (current->isSVGHiddenContainer())
+            continue;
+
+        const AffineTransform& transform = current->localToParentTransform();
+        if (transform.isIdentity()) {
+            updateObjectBoundingBox(objectBoundingBox, objectBoundingBoxValid, current, current->objectBoundingBox());
+            strokeBoundingBox.unite(current->repaintRectInLocalCoordinates());
+        } else {
+            updateObjectBoundingBox(objectBoundingBox, objectBoundingBoxValid, current, transform.mapRect(current->objectBoundingBox()));
+            strokeBoundingBox.unite(transform.mapRect(current->repaintRectInLocalCoordinates()));
+        }
+    }
+
+    repaintBoundingBox = strokeBoundingBox;
+}
+
+bool SVGRenderSupport::paintInfoIntersectsRepaintRect(const FloatRect& localRepaintRect, const AffineTransform& localTransform, const PaintInfo& paintInfo)
+{
+    if (localTransform.isIdentity())
+        return localRepaintRect.intersects(paintInfo.rect);
+
+    return localTransform.mapRect(localRepaintRect).intersects(paintInfo.rect);
+}
+
+const RenderSVGRoot* SVGRenderSupport::findTreeRootObject(const RenderObject* start)
+{
+    while (start && !start->isSVGRoot())
+        start = start->parent();
+
+    ASSERT(start);
+    ASSERT(start->isSVGRoot());
+    return toRenderSVGRoot(start);
+}
+
+static inline void invalidateResourcesOfChildren(RenderObject* start)
+{
+    ASSERT(!start->needsLayout());
+    if (SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(start))
+        resources->removeClientFromCache(start, false);
+
+    for (RenderObject* child = start->firstChild(); child; child = child->nextSibling())
+        invalidateResourcesOfChildren(child);
+}
+
+static inline bool layoutSizeOfNearestViewportChanged(const RenderObject* start)
+{
+    while (start && !start->isSVGRoot() && !start->isSVGViewportContainer())
+        start = start->parent();
+
+    ASSERT(start);
+    ASSERT(start->isSVGRoot() || start->isSVGViewportContainer());
+    if (start->isSVGViewportContainer())
+        return toRenderSVGViewportContainer(start)->isLayoutSizeChanged();
+
+    return toRenderSVGRoot(start)->isLayoutSizeChanged();
+}
+
+bool SVGRenderSupport::transformToRootChanged(RenderObject* ancestor)
+{
+    while (ancestor && !ancestor->isSVGRoot()) {
+        if (ancestor->isSVGTransformableContainer())
+            return toRenderSVGContainer(ancestor)->didTransformToRootUpdate();
+        if (ancestor->isSVGViewportContainer())
+            return toRenderSVGViewportContainer(ancestor)->didTransformToRootUpdate();
+        ancestor = ancestor->parent();
+    }
+
+    return false;
+}
+
+void SVGRenderSupport::layoutChildren(RenderObject* start, bool selfNeedsLayout)
+{
+    bool layoutSizeChanged = layoutSizeOfNearestViewportChanged(start);
+    bool transformChanged = transformToRootChanged(start);
+    bool hasSVGShadow = rendererHasSVGShadow(start);
+    bool needsBoundariesUpdate = start->needsBoundariesUpdate();
+    HashSet<RenderObject*> notlayoutedObjects;
+
+    for (RenderObject* child = start->firstChild(); child; child = child->nextSibling()) {
+        bool needsLayout = selfNeedsLayout;
+        bool childEverHadLayout = child->everHadLayout();
+
+        if (needsBoundariesUpdate && hasSVGShadow) {
+            // If we have a shadow, our shadow is baked into our children's cached boundaries,
+            // so they need to update.
+            child->setNeedsBoundariesUpdate();
+            needsLayout = true;
+        }
+
+        if (transformChanged) {
+            // If the transform changed we need to update the text metrics (note: this also happens for layoutSizeChanged=true).
+            if (child->isSVGText())
+                toRenderSVGText(child)->setNeedsTextMetricsUpdate();
+            needsLayout = true;
+        }
+
+        if (layoutSizeChanged) {
+            // When selfNeedsLayout is false and the layout size changed, we have to check whether this child uses relative lengths
+            if (SVGElement* element = child->node()->isSVGElement() ? toSVGElement(child->node()) : 0) {
+                if (element->isSVGStyledElement() && toSVGStyledElement(element)->hasRelativeLengths()) {
+                    // When the layout size changed and when using relative values tell the RenderSVGShape to update its shape object
+                    if (child->isSVGShape())
+                        toRenderSVGShape(child)->setNeedsShapeUpdate();
+                    else if (child->isSVGText()) {
+                        toRenderSVGText(child)->setNeedsTextMetricsUpdate();
+                        toRenderSVGText(child)->setNeedsPositioningValuesUpdate();
+                    }
+
+                    needsLayout = true;
+                }
+            }
+        }
+
+        if (needsLayout)
+            child->setNeedsLayout(true, MarkOnlyThis);
+
+        if (child->needsLayout()) {
+            child->layout();
+            // Renderers are responsible for repainting themselves when changing, except
+            // for the initial paint to avoid potential double-painting caused by non-sensical "old" bounds.
+            // We could handle this in the individual objects, but for now it's easier to have
+            // parent containers call repaint().  (RenderBlock::layout* has similar logic.)
+            if (!childEverHadLayout)
+                child->repaint();
+        } else if (layoutSizeChanged)
+            notlayoutedObjects.add(child);
+
+        ASSERT(!child->needsLayout());
+    }
+
+    if (!layoutSizeChanged) {
+        ASSERT(notlayoutedObjects.isEmpty());
+        return;
+    }
+
+    // If the layout size changed, invalidate all resources of all children that didn't go through the layout() code path.
+    HashSet<RenderObject*>::iterator end = notlayoutedObjects.end();
+    for (HashSet<RenderObject*>::iterator it = notlayoutedObjects.begin(); it != end; ++it)
+        invalidateResourcesOfChildren(*it);
+}
+
+bool SVGRenderSupport::isOverflowHidden(const RenderObject* object)
+{
+    // SVG doesn't support independent x/y overflow
+    ASSERT(object->style()->overflowX() == object->style()->overflowY());
+
+    // OSCROLL is never set for SVG - see StyleResolver::adjustRenderStyle
+    ASSERT(object->style()->overflowX() != OSCROLL);
+
+    // RenderSVGRoot should never query for overflow state - it should always clip itself to the initial viewport size.
+    ASSERT(!object->isRoot());
+
+    return object->style()->overflowX() == OHIDDEN;
+}
+
+bool SVGRenderSupport::rendererHasSVGShadow(const RenderObject* object)
+{
+    // FIXME: Add support for RenderSVGBlock.
+
+    // FIXME: This should use a safer cast such as toRenderSVGModelObject().
+    if (object->isSVGShape() || object->isSVGImage() || object->isSVGContainer())
+        return static_cast<const RenderSVGModelObject*>(object)->hasSVGShadow();
+
+    if (object->isSVGRoot())
+        return toRenderSVGRoot(object)->hasSVGShadow();
+
+    return false;
+}
+
+void SVGRenderSupport::setRendererHasSVGShadow(RenderObject* object, bool hasShadow)
+{
+    // FIXME: Add support for RenderSVGBlock.
+
+    // FIXME: This should use a safer cast such as toRenderSVGModelObject().
+    if (object->isSVGShape() || object->isSVGImage() || object->isSVGContainer())
+        return static_cast<RenderSVGModelObject*>(object)->setHasSVGShadow(hasShadow);
+
+    if (object->isSVGRoot())
+        return static_cast<RenderSVGRoot*>(object)->setHasSVGShadow(hasShadow);
+}
+
+void SVGRenderSupport::intersectRepaintRectWithShadows(const RenderObject* object, FloatRect& repaintRect)
+{
+    // Since -webkit-svg-shadow enables shadow drawing for its children, but its children
+    // don't inherit the shadow in their SVGRenderStyle, we need to search our parents for
+    // shadows in order to correctly compute our repaint rect.
+
+    ASSERT(object);
+
+    const RenderObject* currentObject = object;
+
+    AffineTransform localToRootTransform;
+
+    while (currentObject && rendererHasSVGShadow(currentObject)) {
+        RenderStyle* style = currentObject->style();
+        if (style) {
+            const SVGRenderStyle* svgStyle = style->svgStyle();
+            if (svgStyle) {
+                if (const ShadowData* shadow = svgStyle->shadow())
+                    shadow->adjustRectForShadow(repaintRect);
+            }
+        }
+
+        repaintRect = currentObject->localToParentTransform().mapRect(repaintRect);
+        localToRootTransform *= currentObject->localToParentTransform();
+
+        currentObject = currentObject->parent();
+    };
+
+    if (localToRootTransform.isIdentity())
+        return;
+
+    AffineTransform rootToLocalTransform = localToRootTransform.inverse();
+    repaintRect = rootToLocalTransform.mapRect(repaintRect);
+}
+
+void SVGRenderSupport::intersectRepaintRectWithResources(const RenderObject* object, FloatRect& repaintRect)
+{
+    ASSERT(object);
+
+    RenderObject* renderer = const_cast<RenderObject*>(object);
+    SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(renderer);
+    if (!resources)
+        return;
+
+    if (RenderSVGResourceFilter* filter = resources->filter())
+        repaintRect = filter->resourceBoundingBox(renderer);
+
+    if (RenderSVGResourceClipper* clipper = resources->clipper())
+        repaintRect.intersect(clipper->resourceBoundingBox(renderer));
+
+    if (RenderSVGResourceMasker* masker = resources->masker())
+        repaintRect.intersect(masker->resourceBoundingBox(renderer));
+}
+
+bool SVGRenderSupport::filtersForceContainerLayout(RenderObject* object)
+{
+    // If any of this container's children need to be laid out, and a filter is applied
+    // to the container, we need to repaint the entire container.
+    if (!object->normalChildNeedsLayout())
+        return false;
+
+    SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(object);
+    if (!resources || !resources->filter())
+        return false;
+
+    return true;
+}
+
+bool SVGRenderSupport::pointInClippingArea(RenderObject* object, const FloatPoint& point)
+{
+    ASSERT(object);
+
+    // We just take clippers into account to determine if a point is on the node. The Specification may
+    // change later and we also need to check maskers.
+    SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(object);
+    if (!resources)
+        return true;
+
+    if (RenderSVGResourceClipper* clipper = resources->clipper())
+        return clipper->hitTestClipContent(object->objectBoundingBox(), point);
+
+    return true;
+}
+
+void SVGRenderSupport::applyStrokeStyleToContext(GraphicsContext* context, const RenderStyle* style, const RenderObject* object)
+{
+    ASSERT(context);
+    ASSERT(style);
+    ASSERT(object);
+    ASSERT(object->node());
+    ASSERT(object->node()->isSVGElement());
+
+    const SVGRenderStyle* svgStyle = style->svgStyle();
+    ASSERT(svgStyle);
+
+    SVGLengthContext lengthContext(toSVGElement(object->node()));
+    context->setStrokeThickness(svgStyle->strokeWidth().value(lengthContext));
+    context->setLineCap(svgStyle->capStyle());
+    context->setLineJoin(svgStyle->joinStyle());
+    if (svgStyle->joinStyle() == MiterJoin)
+        context->setMiterLimit(svgStyle->strokeMiterLimit());
+
+    const Vector<SVGLength>& dashes = svgStyle->strokeDashArray();
+    if (dashes.isEmpty())
+        context->setStrokeStyle(SolidStroke);
+    else {
+        DashArray dashArray;
+        const Vector<SVGLength>::const_iterator end = dashes.end();
+        for (Vector<SVGLength>::const_iterator it = dashes.begin(); it != end; ++it)
+            dashArray.append((*it).value(lengthContext));
+
+        context->setLineDash(dashArray, svgStyle->strokeDashOffset().value(lengthContext));
+    }
+}
+
+void SVGRenderSupport::childAdded(RenderObject* parent, RenderObject* child)
+{
+    SVGRenderSupport::setRendererHasSVGShadow(child, SVGRenderSupport::rendererHasSVGShadow(parent) || SVGRenderSupport::rendererHasSVGShadow(child));
+}
+
+void SVGRenderSupport::styleChanged(RenderObject* object)
+{
+    RenderObject* parent = object->parent();
+    SVGRenderSupport::setRendererHasSVGShadow(object, (parent && SVGRenderSupport::rendererHasSVGShadow(parent)) || (object->style()->svgStyle() && object->style()->svgStyle()->shadow()));
+}
+
+}
+
+#endif
diff --git a/Source/core/rendering/svg/SVGRenderSupport.h b/Source/core/rendering/svg/SVGRenderSupport.h
new file mode 100644
index 0000000..8433886
--- /dev/null
+++ b/Source/core/rendering/svg/SVGRenderSupport.h
@@ -0,0 +1,100 @@
+/**
+ * Copyright (C) 2007 Rob Buis <buis@kde.org>
+ * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
+ * Copyright (C) 2009 Google, Inc.  All rights reserved.
+ * Copyright (C) Research In Motion Limited 2010. 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 SVGRenderSupport_h
+#define SVGRenderSupport_h
+
+#if ENABLE(SVG)
+#include "core/rendering/PaintInfo.h"
+
+namespace WebCore {
+
+class FloatPoint;
+class FloatRect;
+class ImageBuffer;
+class LayoutRect;
+class RenderBoxModelObject;
+class RenderGeometryMap;
+class RenderLayerModelObject;
+class RenderObject;
+class RenderStyle;
+class RenderSVGRoot;
+class TransformState;
+
+// SVGRendererSupport is a helper class sharing code between all SVG renderers.
+class SVGRenderSupport {
+public:
+    // Shares child layouting code between RenderSVGRoot/RenderSVG(Hidden)Container
+    static void layoutChildren(RenderObject*, bool selfNeedsLayout);
+
+    // Helper function determining wheter overflow is hidden
+    static bool isOverflowHidden(const RenderObject*);
+
+    static void intersectRepaintRectWithShadows(const RenderObject*, FloatRect&);
+
+    // Calculates the repaintRect in combination with filter, clipper and masker in local coordinates.
+    static void intersectRepaintRectWithResources(const RenderObject*, FloatRect&);
+
+    // Determines whether a container needs to be laid out because it's filtered and a child is being laid out.
+    static bool filtersForceContainerLayout(RenderObject*);
+
+    // Determines whether the passed point lies in a clipping area
+    static bool pointInClippingArea(RenderObject*, const FloatPoint&);
+
+    static void computeContainerBoundingBoxes(const RenderObject* container, FloatRect& objectBoundingBox, bool& objectBoundingBoxValid, FloatRect& strokeBoundingBox, FloatRect& repaintBoundingBox);
+    static bool paintInfoIntersectsRepaintRect(const FloatRect& localRepaintRect, const AffineTransform& localTransform, const PaintInfo&);
+
+    // Important functions used by nearly all SVG renderers centralizing coordinate transformations / repaint rect calculations
+    static FloatRect repaintRectForRendererInLocalCoordinatesExcludingSVGShadow(const RenderObject*);
+    static LayoutRect clippedOverflowRectForRepaint(const RenderObject*, const RenderLayerModelObject* repaintContainer);
+    static void computeFloatRectForRepaint(const RenderObject*, const RenderLayerModelObject* repaintContainer, FloatRect&, bool fixed);
+    static void mapLocalToContainer(const RenderObject*, const RenderLayerModelObject* repaintContainer, TransformState&, bool* wasFixed = 0);
+    static const RenderObject* pushMappingToContainer(const RenderObject*, const RenderLayerModelObject* ancestorToStopAt, RenderGeometryMap&);
+    static bool checkForSVGRepaintDuringLayout(RenderObject*);
+
+    // Shared between SVG renderers and resources.
+    static void applyStrokeStyleToContext(GraphicsContext*, const RenderStyle*, const RenderObject*);
+
+    // Determines if any ancestor's transform has changed.
+    static bool transformToRootChanged(RenderObject*);
+
+    // Helper functions to keep track of whether a renderer has an SVG shadow applied.
+    static bool rendererHasSVGShadow(const RenderObject*);
+    static void setRendererHasSVGShadow(RenderObject*, bool hasShadow);
+
+    static void childAdded(RenderObject* parent, RenderObject* child);
+    static void styleChanged(RenderObject*);
+
+    // FIXME: These methods do not belong here.
+    static const RenderSVGRoot* findTreeRootObject(const RenderObject*);
+
+private:
+    // This class is not constructable.
+    SVGRenderSupport();
+    ~SVGRenderSupport();
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
+#endif // SVGRenderSupport_h
diff --git a/Source/core/rendering/svg/SVGRenderTreeAsText.cpp b/Source/core/rendering/svg/SVGRenderTreeAsText.cpp
new file mode 100644
index 0000000..c3872c1
--- /dev/null
+++ b/Source/core/rendering/svg/SVGRenderTreeAsText.cpp
@@ -0,0 +1,689 @@
+/*
+ * Copyright (C) 2004, 2005, 2007, 2009 Apple Inc. All rights reserved.
+ *           (C) 2005 Rob Buis <buis@kde.org>
+ *           (C) 2006 Alexander Kellett <lypanov@kde.org>
+ * Copyright (C) Research In Motion Limited 2010. 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(SVG)
+#include "core/rendering/svg/SVGRenderTreeAsText.h"
+
+#include "HTMLNames.h"
+#include "SVGNames.h"
+#include "core/dom/NodeRenderStyle.h"
+#include "core/platform/graphics/GraphicsTypes.h"
+#include "core/platform/graphics/Path.h"
+#include "core/rendering/InlineTextBox.h"
+#include "core/rendering/RenderImage.h"
+#include "core/rendering/RenderTreeAsText.h"
+#include "core/rendering/svg/RenderSVGContainer.h"
+#include "core/rendering/svg/RenderSVGGradientStop.h"
+#include "core/rendering/svg/RenderSVGImage.h"
+#include "core/rendering/svg/RenderSVGInlineText.h"
+#include "core/rendering/svg/RenderSVGPath.h"
+#include "core/rendering/svg/RenderSVGResourceClipper.h"
+#include "core/rendering/svg/RenderSVGResourceFilter.h"
+#include "core/rendering/svg/RenderSVGResourceGradient.h"
+#include "core/rendering/svg/RenderSVGResourceLinearGradient.h"
+#include "core/rendering/svg/RenderSVGResourceMarker.h"
+#include "core/rendering/svg/RenderSVGResourceMasker.h"
+#include "core/rendering/svg/RenderSVGResourcePattern.h"
+#include "core/rendering/svg/RenderSVGResourceRadialGradient.h"
+#include "core/rendering/svg/RenderSVGResourceSolidColor.h"
+#include "core/rendering/svg/RenderSVGRoot.h"
+#include "core/rendering/svg/RenderSVGShape.h"
+#include "core/rendering/svg/RenderSVGText.h"
+#include "core/rendering/svg/SVGInlineTextBox.h"
+#include "core/rendering/svg/SVGRootInlineBox.h"
+#include "core/svg/LinearGradientAttributes.h"
+#include "core/svg/PatternAttributes.h"
+#include "core/svg/RadialGradientAttributes.h"
+#include "core/svg/SVGCircleElement.h"
+#include "core/svg/SVGEllipseElement.h"
+#include "core/svg/SVGLineElement.h"
+#include "core/svg/SVGLinearGradientElement.h"
+#include "core/svg/SVGPathElement.h"
+#include "core/svg/SVGPathUtilities.h"
+#include "core/svg/SVGPatternElement.h"
+#include "core/svg/SVGPointList.h"
+#include "core/svg/SVGPolyElement.h"
+#include "core/svg/SVGRadialGradientElement.h"
+#include "core/svg/SVGRectElement.h"
+#include "core/svg/SVGStopElement.h"
+#include "core/svg/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;
+}
+
+template<typename ValueType>
+static void writeNameValuePair(TextStream& ts, const char* name, ValueType value)
+{
+    ts << " [" << name << "=" << value << "]";
+}
+
+template<typename ValueType>
+static void writeNameAndQuotedValue(TextStream& ts, const char* name, ValueType value)
+{
+    ts << " [" << name << "=\"" << value << "\"]";
+}
+
+static void writeIfNotEmpty(TextStream& ts, const char* name, const String& value)
+{
+    if (!value.isEmpty())
+        writeNameValuePair(ts, name, value);
+}
+
+template<typename ValueType>
+static void writeIfNotDefault(TextStream& ts, const char* name, ValueType value, ValueType defaultValue)
+{
+    if (value != defaultValue)
+        writeNameValuePair(ts, name, value);
+}
+
+TextStream& operator<<(TextStream& ts, const FloatRect& r)
+{
+    ts << "at (" << TextStream::FormatNumberRespectingIntegers(r.x());
+    ts << "," << TextStream::FormatNumberRespectingIntegers(r.y());
+    ts << ") size " << TextStream::FormatNumberRespectingIntegers(r.width());
+    ts << "x" << TextStream::FormatNumberRespectingIntegers(r.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;
+}
+
+static TextStream& operator<<(TextStream& ts, const WindRule rule)
+{
+    switch (rule) {
+    case RULE_NONZERO:
+        ts << "NON-ZERO";
+        break;
+    case RULE_EVENODD:
+        ts << "EVEN-ODD";
+        break;
+    }
+
+    return ts;
+}
+
+static TextStream& operator<<(TextStream& ts, const SVGUnitTypes::SVGUnitType& unitType)
+{
+    ts << SVGPropertyTraits<SVGUnitTypes::SVGUnitType>::toString(unitType);
+    return ts;
+}
+
+static TextStream& operator<<(TextStream& ts, const SVGMarkerUnitsType& markerUnit)
+{
+    ts << SVGPropertyTraits<SVGMarkerUnitsType>::toString(markerUnit);
+    return ts;
+}
+
+TextStream& operator<<(TextStream& ts, const Color& c)
+{
+    return ts << c.nameForRenderTreeAsText();
+}
+
+// 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 TextStream& operator<<(TextStream& ts, const SVGSpreadMethodType& type)
+{
+    ts << SVGPropertyTraits<SVGSpreadMethodType>::toString(type).upper();
+    return ts;
+}
+
+static void writeSVGPaintingResource(TextStream& ts, RenderSVGResource* resource)
+{
+    if (resource->resourceType() == SolidColorResourceType) {
+        ts << "[type=SOLID] [color=" << static_cast<RenderSVGResourceSolidColor*>(resource)->color() << "]";
+        return;
+    }
+
+    // All other resources derive from RenderSVGResourceContainer
+    RenderSVGResourceContainer* container = static_cast<RenderSVGResourceContainer*>(resource);
+    Node* node = container->node();
+    ASSERT(node);
+    ASSERT(node->isSVGElement());
+
+    if (resource->resourceType() == PatternResourceType)
+        ts << "[type=PATTERN]";
+    else if (resource->resourceType() == LinearGradientResourceType)
+        ts << "[type=LINEAR-GRADIENT]";
+    else if (resource->resourceType() == RadialGradientResourceType)
+        ts << "[type=RADIAL-GRADIENT]";
+
+    ts << " [id=\"" << toSVGElement(node)->getIdAttribute() << "\"]";
+}
+
+static void writeStyle(TextStream& ts, const RenderObject& object)
+{
+    const RenderStyle* style = object.style();
+    const SVGRenderStyle* svgStyle = style->svgStyle();
+
+    if (!object.localTransform().isIdentity())
+        writeNameValuePair(ts, "transform", object.localTransform());
+    writeIfNotDefault(ts, "image rendering", style->imageRendering(), RenderStyle::initialImageRendering());
+    writeIfNotDefault(ts, "opacity", style->opacity(), RenderStyle::initialOpacity());
+    if (object.isSVGShape()) {
+        const RenderSVGShape& shape = static_cast<const RenderSVGShape&>(object);
+        ASSERT(shape.node());
+        ASSERT(shape.node()->isSVGElement());
+
+        Color fallbackColor;
+        if (RenderSVGResource* strokePaintingResource = RenderSVGResource::strokePaintingResource(const_cast<RenderSVGShape*>(&shape), shape.style(), fallbackColor)) {
+            TextStreamSeparator s(" ");
+            ts << " [stroke={" << s;
+            writeSVGPaintingResource(ts, strokePaintingResource);
+
+            SVGLengthContext lengthContext(toSVGElement(shape.node()));
+            double dashOffset = svgStyle->strokeDashOffset().value(lengthContext);
+            double strokeWidth = svgStyle->strokeWidth().value(lengthContext);
+            const Vector<SVGLength>& dashes = svgStyle->strokeDashArray();
+
+            DashArray dashArray;
+            const Vector<SVGLength>::const_iterator end = dashes.end();
+            for (Vector<SVGLength>::const_iterator it = dashes.begin(); it != end; ++it)
+                dashArray.append((*it).value(lengthContext));
+
+            writeIfNotDefault(ts, "opacity", svgStyle->strokeOpacity(), 1.0f);
+            writeIfNotDefault(ts, "stroke width", strokeWidth, 1.0);
+            writeIfNotDefault(ts, "miter limit", svgStyle->strokeMiterLimit(), 4.0f);
+            writeIfNotDefault(ts, "line cap", svgStyle->capStyle(), ButtCap);
+            writeIfNotDefault(ts, "line join", svgStyle->joinStyle(), MiterJoin);
+            writeIfNotDefault(ts, "dash offset", dashOffset, 0.0);
+            if (!dashArray.isEmpty())
+                writeNameValuePair(ts, "dash array", dashArray);
+
+            ts << "}]";
+        }
+
+        if (RenderSVGResource* fillPaintingResource = RenderSVGResource::fillPaintingResource(const_cast<RenderSVGShape*>(&shape), shape.style(), fallbackColor)) {
+            TextStreamSeparator s(" ");
+            ts << " [fill={" << s;
+            writeSVGPaintingResource(ts, fillPaintingResource);
+
+            writeIfNotDefault(ts, "opacity", svgStyle->fillOpacity(), 1.0f);
+            writeIfNotDefault(ts, "fill rule", svgStyle->fillRule(), RULE_NONZERO);
+            ts << "}]";
+        }
+        writeIfNotDefault(ts, "clip rule", svgStyle->clipRule(), RULE_NONZERO);
+    }
+
+    writeIfNotEmpty(ts, "start marker", svgStyle->markerStartResource());
+    writeIfNotEmpty(ts, "middle marker", svgStyle->markerMidResource());
+    writeIfNotEmpty(ts, "end marker", svgStyle->markerEndResource());
+}
+
+static TextStream& writePositionAndStyle(TextStream& ts, const RenderObject& object)
+{
+    ts << " " << enclosingIntRect(const_cast<RenderObject&>(object).absoluteClippedOverflowRect());
+    writeStyle(ts, object);
+    return ts;
+}
+
+static TextStream& operator<<(TextStream& ts, const RenderSVGShape& shape)
+{
+    writePositionAndStyle(ts, shape);
+
+    ASSERT(shape.node()->isSVGElement());
+    SVGElement* svgElement = toSVGElement(shape.node());
+    SVGLengthContext lengthContext(svgElement);
+
+    if (svgElement->hasTagName(SVGNames::rectTag)) {
+        SVGRectElement* element = static_cast<SVGRectElement*>(svgElement);
+        writeNameValuePair(ts, "x", element->x().value(lengthContext));
+        writeNameValuePair(ts, "y", element->y().value(lengthContext));
+        writeNameValuePair(ts, "width", element->width().value(lengthContext));
+        writeNameValuePair(ts, "height", element->height().value(lengthContext));
+    } else if (svgElement->hasTagName(SVGNames::lineTag)) {
+        SVGLineElement* element = static_cast<SVGLineElement*>(svgElement);
+        writeNameValuePair(ts, "x1", element->x1().value(lengthContext));
+        writeNameValuePair(ts, "y1", element->y1().value(lengthContext));
+        writeNameValuePair(ts, "x2", element->x2().value(lengthContext));
+        writeNameValuePair(ts, "y2", element->y2().value(lengthContext));
+    } else if (svgElement->hasTagName(SVGNames::ellipseTag)) {
+        SVGEllipseElement* element = static_cast<SVGEllipseElement*>(svgElement);
+        writeNameValuePair(ts, "cx", element->cx().value(lengthContext));
+        writeNameValuePair(ts, "cy", element->cy().value(lengthContext));
+        writeNameValuePair(ts, "rx", element->rx().value(lengthContext));
+        writeNameValuePair(ts, "ry", element->ry().value(lengthContext));
+    } else if (svgElement->hasTagName(SVGNames::circleTag)) {
+        SVGCircleElement* element = static_cast<SVGCircleElement*>(svgElement);
+        writeNameValuePair(ts, "cx", element->cx().value(lengthContext));
+        writeNameValuePair(ts, "cy", element->cy().value(lengthContext));
+        writeNameValuePair(ts, "r", element->r().value(lengthContext));
+    } else if (svgElement->hasTagName(SVGNames::polygonTag) || svgElement->hasTagName(SVGNames::polylineTag)) {
+        SVGPolyElement* element = static_cast<SVGPolyElement*>(svgElement);
+        writeNameAndQuotedValue(ts, "points", element->pointList().valueAsString());
+    } else if (svgElement->hasTagName(SVGNames::pathTag)) {
+        SVGPathElement* element = static_cast<SVGPathElement*>(svgElement);
+        String pathString;
+        // FIXME: We should switch to UnalteredParsing here - this will affect the path dumping output of dozens of tests.
+        buildStringFromByteStream(element->pathByteStream(), pathString, NormalizedParsing);
+        writeNameAndQuotedValue(ts, "data", pathString);
+    } else
+        ASSERT_NOT_REACHED();
+    return ts;
+}
+
+static TextStream& operator<<(TextStream& ts, const RenderSVGRoot& root)
+{
+    return writePositionAndStyle(ts, root);
+}
+
+static void writeRenderSVGTextBox(TextStream& ts, const RenderSVGText& text)
+{
+    SVGRootInlineBox* box = static_cast<SVGRootInlineBox*>(text.firstRootBox());
+    if (!box)
+        return;
+
+    ts << " " << enclosingIntRect(FloatRect(text.location(), FloatSize(box->logicalWidth(), box->logicalHeight())));
+    
+    // FIXME: Remove this hack, once the new text layout engine is completly landed. We want to preserve the old layout test results for now.
+    ts << " contains 1 chunk(s)";
+
+    if (text.parent() && (text.parent()->style()->visitedDependentColor(CSSPropertyColor) != text.style()->visitedDependentColor(CSSPropertyColor)))
+        writeNameValuePair(ts, "color", text.style()->visitedDependentColor(CSSPropertyColor).nameForRenderTreeAsText());
+}
+
+static inline void writeSVGInlineTextBox(TextStream& ts, SVGInlineTextBox* textBox, int indent)
+{
+    Vector<SVGTextFragment>& fragments = textBox->textFragments();
+    if (fragments.isEmpty())
+        return;
+
+    RenderSVGInlineText* textRenderer = toRenderSVGInlineText(textBox->textRenderer());
+    ASSERT(textRenderer);
+
+    const SVGRenderStyle* svgStyle = textRenderer->style()->svgStyle();
+    String text = textBox->textRenderer()->text();
+
+    unsigned fragmentsSize = fragments.size();
+    for (unsigned i = 0; i < fragmentsSize; ++i) {
+        SVGTextFragment& fragment = fragments.at(i);
+        writeIndent(ts, indent + 1);
+
+        unsigned startOffset = fragment.characterOffset;
+        unsigned endOffset = fragment.characterOffset + fragment.length;
+
+        // FIXME: Remove this hack, once the new text layout engine is completly landed. We want to preserve the old layout test results for now.
+        ts << "chunk 1 ";
+        ETextAnchor anchor = svgStyle->textAnchor();
+        bool isVerticalText = svgStyle->isVerticalWritingMode();
+        if (anchor == TA_MIDDLE) {
+            ts << "(middle anchor";
+            if (isVerticalText)
+                ts << ", vertical";
+            ts << ") ";
+        } else if (anchor == TA_END) {
+            ts << "(end anchor";
+            if (isVerticalText)
+                ts << ", vertical";
+            ts << ") ";
+        } else if (isVerticalText)
+            ts << "(vertical) ";
+        startOffset -= textBox->start();
+        endOffset -= textBox->start();
+        // </hack>
+
+        ts << "text run " << i + 1 << " at (" << fragment.x << "," << fragment.y << ")";
+        ts << " startOffset " << startOffset << " endOffset " << endOffset;
+        if (isVerticalText)
+            ts << " height " << fragment.height;
+        else
+            ts << " width " << fragment.width;
+
+        if (!textBox->isLeftToRightDirection() || textBox->dirOverride()) {
+            ts << (textBox->isLeftToRightDirection() ? " LTR" : " RTL");
+            if (textBox->dirOverride())
+                ts << " override";
+        }
+
+        ts << ": " << quoteAndEscapeNonPrintables(text.substring(fragment.characterOffset, fragment.length)) << "\n";
+    }
+}
+
+static inline void writeSVGInlineTextBoxes(TextStream& ts, const RenderText& text, int indent)
+{
+    for (InlineTextBox* box = text.firstTextBox(); box; box = box->nextTextBox()) {
+        if (!box->isSVGInlineTextBox())
+            continue;
+
+        writeSVGInlineTextBox(ts, static_cast<SVGInlineTextBox*>(box), indent);
+    }
+}
+
+static void writeStandardPrefix(TextStream& ts, const RenderObject& object, int indent)
+{
+    writeIndent(ts, indent);
+    ts << object.renderName();
+
+    if (object.node())
+        ts << " {" << object.node()->nodeName() << "}";
+}
+
+static void writeChildren(TextStream& ts, const RenderObject& object, int indent)
+{
+    for (RenderObject* child = object.firstChild(); child; child = child->nextSibling())
+        write(ts, *child, indent + 1);
+}
+
+static inline void writeCommonGradientProperties(TextStream& ts, SVGSpreadMethodType spreadMethod, const AffineTransform& gradientTransform, SVGUnitTypes::SVGUnitType gradientUnits)
+{
+    writeNameValuePair(ts, "gradientUnits", gradientUnits);
+
+    if (spreadMethod != SVGSpreadMethodPad)
+        ts << " [spreadMethod=" << spreadMethod << "]";
+
+    if (!gradientTransform.isIdentity())
+        ts << " [gradientTransform=" << gradientTransform << "]";
+}
+
+void writeSVGResourceContainer(TextStream& ts, const RenderObject& object, int indent)
+{
+    writeStandardPrefix(ts, object, indent);
+
+    Element* element = toElement(object.node());
+    const AtomicString& id = element->getIdAttribute();
+    writeNameAndQuotedValue(ts, "id", id);    
+
+    RenderSVGResourceContainer* resource = const_cast<RenderObject&>(object).toRenderSVGResourceContainer();
+    ASSERT(resource);
+
+    if (resource->resourceType() == MaskerResourceType) {
+        RenderSVGResourceMasker* masker = static_cast<RenderSVGResourceMasker*>(resource);
+        writeNameValuePair(ts, "maskUnits", masker->maskUnits());
+        writeNameValuePair(ts, "maskContentUnits", masker->maskContentUnits());
+        ts << "\n";
+    } else if (resource->resourceType() == FilterResourceType) {
+        RenderSVGResourceFilter* filter = static_cast<RenderSVGResourceFilter*>(resource);
+        writeNameValuePair(ts, "filterUnits", filter->filterUnits());
+        writeNameValuePair(ts, "primitiveUnits", filter->primitiveUnits());
+        ts << "\n";
+        // Creating a placeholder filter which is passed to the builder.
+        FloatRect dummyRect;
+        RefPtr<SVGFilter> dummyFilter = SVGFilter::create(AffineTransform(), dummyRect, dummyRect, dummyRect, true);
+        if (RefPtr<SVGFilterBuilder> builder = filter->buildPrimitives(dummyFilter.get())) {
+            if (FilterEffect* lastEffect = builder->lastEffect())
+                lastEffect->externalRepresentation(ts, indent + 1);
+        }
+    } else if (resource->resourceType() == ClipperResourceType) {
+        RenderSVGResourceClipper* clipper = static_cast<RenderSVGResourceClipper*>(resource);
+        writeNameValuePair(ts, "clipPathUnits", clipper->clipPathUnits());
+        ts << "\n";
+    } else if (resource->resourceType() == MarkerResourceType) {
+        RenderSVGResourceMarker* marker = static_cast<RenderSVGResourceMarker*>(resource);
+        writeNameValuePair(ts, "markerUnits", marker->markerUnits());
+        ts << " [ref at " << marker->referencePoint() << "]";
+        ts << " [angle=";
+        if (marker->angle() == -1)
+            ts << "auto" << "]\n";
+        else
+            ts << marker->angle() << "]\n";
+    } else if (resource->resourceType() == PatternResourceType) {
+        RenderSVGResourcePattern* pattern = static_cast<RenderSVGResourcePattern*>(resource);
+
+        // Dump final results that are used for rendering. No use in asking SVGPatternElement for its patternUnits(), as it may
+        // link to other patterns using xlink:href, we need to build the full inheritance chain, aka. collectPatternProperties()
+        PatternAttributes attributes;
+        static_cast<SVGPatternElement*>(pattern->node())->collectPatternAttributes(attributes);
+
+        writeNameValuePair(ts, "patternUnits", attributes.patternUnits());
+        writeNameValuePair(ts, "patternContentUnits", attributes.patternContentUnits());
+
+        AffineTransform transform = attributes.patternTransform();
+        if (!transform.isIdentity())
+            ts << " [patternTransform=" << transform << "]";
+        ts << "\n";
+    } else if (resource->resourceType() == LinearGradientResourceType) {
+        RenderSVGResourceLinearGradient* gradient = static_cast<RenderSVGResourceLinearGradient*>(resource);
+
+        // Dump final results that are used for rendering. No use in asking SVGGradientElement for its gradientUnits(), as it may
+        // link to other gradients using xlink:href, we need to build the full inheritance chain, aka. collectGradientProperties()
+        SVGLinearGradientElement* linearGradientElement = static_cast<SVGLinearGradientElement*>(gradient->node());
+
+        LinearGradientAttributes attributes;
+        linearGradientElement->collectGradientAttributes(attributes);
+        writeCommonGradientProperties(ts, attributes.spreadMethod(), attributes.gradientTransform(), attributes.gradientUnits());
+
+        ts << " [start=" << gradient->startPoint(attributes) << "] [end=" << gradient->endPoint(attributes) << "]\n";
+    }  else if (resource->resourceType() == RadialGradientResourceType) {
+        RenderSVGResourceRadialGradient* gradient = static_cast<RenderSVGResourceRadialGradient*>(resource);
+
+        // Dump final results that are used for rendering. No use in asking SVGGradientElement for its gradientUnits(), as it may
+        // link to other gradients using xlink:href, we need to build the full inheritance chain, aka. collectGradientProperties()
+        SVGRadialGradientElement* radialGradientElement = static_cast<SVGRadialGradientElement*>(gradient->node());
+
+        RadialGradientAttributes attributes;
+        radialGradientElement->collectGradientAttributes(attributes);
+        writeCommonGradientProperties(ts, attributes.spreadMethod(), attributes.gradientTransform(), attributes.gradientUnits());
+
+        FloatPoint focalPoint = gradient->focalPoint(attributes);
+        FloatPoint centerPoint = gradient->centerPoint(attributes);
+        float radius = gradient->radius(attributes);
+        float focalRadius = gradient->focalRadius(attributes);
+
+        ts << " [center=" << centerPoint << "] [focal=" << focalPoint << "] [radius=" << radius << "] [focalRadius=" << focalRadius << "]\n";
+    } else
+        ts << "\n";
+    writeChildren(ts, object, indent);
+}
+
+void writeSVGContainer(TextStream& ts, const RenderObject& container, int indent)
+{
+    // Currently RenderSVGResourceFilterPrimitive has no meaningful output.
+    if (container.isSVGResourceFilterPrimitive())
+        return;
+    writeStandardPrefix(ts, container, indent);
+    writePositionAndStyle(ts, container);
+    ts << "\n";
+    writeResources(ts, container, indent);
+    writeChildren(ts, container, indent);
+}
+
+void write(TextStream& ts, const RenderSVGRoot& root, int indent)
+{
+    writeStandardPrefix(ts, root, indent);
+    ts << root << "\n";
+    writeChildren(ts, root, indent);
+}
+
+void writeSVGText(TextStream& ts, const RenderSVGText& text, int indent)
+{
+    writeStandardPrefix(ts, text, indent);
+    writeRenderSVGTextBox(ts, text);
+    ts << "\n";
+    writeResources(ts, text, indent);
+    writeChildren(ts, text, indent);
+}
+
+void writeSVGInlineText(TextStream& ts, const RenderSVGInlineText& text, int indent)
+{
+    writeStandardPrefix(ts, text, indent);
+    ts << " " << enclosingIntRect(FloatRect(text.firstRunOrigin(), text.floatLinesBoundingBox().size())) << "\n";
+    writeResources(ts, text, indent);
+    writeSVGInlineTextBoxes(ts, text, indent);
+}
+
+void writeSVGImage(TextStream& ts, const RenderSVGImage& image, int indent)
+{
+    writeStandardPrefix(ts, image, indent);
+    writePositionAndStyle(ts, image);
+    ts << "\n";
+    writeResources(ts, image, indent);
+}
+
+void write(TextStream& ts, const RenderSVGShape& shape, int indent)
+{
+    writeStandardPrefix(ts, shape, indent);
+    ts << shape << "\n";
+    writeResources(ts, shape, indent);
+}
+
+void writeSVGGradientStop(TextStream& ts, const RenderSVGGradientStop& stop, int indent)
+{
+    writeStandardPrefix(ts, stop, indent);
+
+    SVGStopElement* stopElement = static_cast<SVGStopElement*>(stop.node());
+    ASSERT(stopElement);
+
+    RenderStyle* style = stop.style();
+    if (!style)
+        return;
+
+    ts << " [offset=" << stopElement->offset() << "] [color=" << stopElement->stopColorIncludingOpacity() << "]\n";
+}
+
+void writeResources(TextStream& ts, const RenderObject& object, int indent)
+{
+    const RenderStyle* style = object.style();
+    const SVGRenderStyle* svgStyle = style->svgStyle();
+
+    // FIXME: We want to use SVGResourcesCache to determine which resources are present, instead of quering the resource <-> id cache.
+    // For now leave the DRT output as is, but later on we should change this so cycles are properly ignored in the DRT output.
+    RenderObject& renderer = const_cast<RenderObject&>(object);
+    if (!svgStyle->maskerResource().isEmpty()) {
+        if (RenderSVGResourceMasker* masker = getRenderSVGResourceById<RenderSVGResourceMasker>(object.document(), svgStyle->maskerResource())) {
+            writeIndent(ts, indent);
+            ts << " ";
+            writeNameAndQuotedValue(ts, "masker", svgStyle->maskerResource());
+            ts << " ";
+            writeStandardPrefix(ts, *masker, 0);
+            ts << " " << masker->resourceBoundingBox(&renderer) << "\n";
+        }
+    }
+    if (!svgStyle->clipperResource().isEmpty()) {
+        if (RenderSVGResourceClipper* clipper = getRenderSVGResourceById<RenderSVGResourceClipper>(object.document(), svgStyle->clipperResource())) {
+            writeIndent(ts, indent);
+            ts << " ";
+            writeNameAndQuotedValue(ts, "clipPath", svgStyle->clipperResource());
+            ts << " ";
+            writeStandardPrefix(ts, *clipper, 0);
+            ts << " " << clipper->resourceBoundingBox(&renderer) << "\n";
+        }
+    }
+    if (!svgStyle->filterResource().isEmpty()) {
+        if (RenderSVGResourceFilter* filter = getRenderSVGResourceById<RenderSVGResourceFilter>(object.document(), svgStyle->filterResource())) {
+            writeIndent(ts, indent);
+            ts << " ";
+            writeNameAndQuotedValue(ts, "filter", svgStyle->filterResource());
+            ts << " ";
+            writeStandardPrefix(ts, *filter, 0);
+            ts << " " << filter->resourceBoundingBox(&renderer) << "\n";
+        }
+    }
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
diff --git a/Source/core/rendering/svg/SVGRenderTreeAsText.h b/Source/core/rendering/svg/SVGRenderTreeAsText.h
new file mode 100644
index 0000000..1c8aab7
--- /dev/null
+++ b/Source/core/rendering/svg/SVGRenderTreeAsText.h
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2004, 2005, 2009 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 SVGRenderTreeAsText_h
+#define SVGRenderTreeAsText_h
+
+#if ENABLE(SVG)
+
+#include "core/platform/text/TextStream.h"
+
+namespace WebCore {
+
+class Color;
+class FloatRect;
+class FloatSize;
+class Node;
+class RenderImage;
+class RenderObject;
+class RenderSVGGradientStop;
+class RenderSVGImage;
+class RenderSVGInlineText;
+class RenderSVGShape;
+class RenderSVGRoot;
+class RenderSVGText;
+class AffineTransform;
+class SVGUnitTypes;
+
+// functions used by the main RenderTreeAsText code
+void write(TextStream&, const RenderSVGShape&, int indent);
+void write(TextStream&, const RenderSVGRoot&, int indent);
+void writeSVGGradientStop(TextStream&, const RenderSVGGradientStop&, int indent);
+void writeSVGResourceContainer(TextStream&, const RenderObject&, int indent);
+void writeSVGContainer(TextStream&, const RenderObject&, int indent);
+void writeSVGImage(TextStream&, const RenderSVGImage&, int indent);
+void writeSVGInlineText(TextStream&, const RenderSVGInlineText&, int indent);
+void writeSVGText(TextStream&, const RenderSVGText&, int indent);
+void writeResources(TextStream&, const RenderObject&, int indent);
+
+// helper operators defined used in various classes to dump the render tree.
+TextStream& operator<<(TextStream&, const AffineTransform&);
+TextStream& operator<<(TextStream&, const Color&);
+TextStream& operator<<(TextStream&, const FloatRect&);
+
+// 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 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/Source/core/rendering/svg/SVGRenderingContext.cpp b/Source/core/rendering/svg/SVGRenderingContext.cpp
new file mode 100644
index 0000000..46a1081
--- /dev/null
+++ b/Source/core/rendering/svg/SVGRenderingContext.cpp
@@ -0,0 +1,354 @@
+/*
+ * Copyright (C) 2007, 2008 Rob Buis <buis@kde.org>
+ * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
+ * Copyright (C) 2009 Google, Inc.  All rights reserved.
+ * Copyright (C) 2009 Dirk Schulze <krit@webkit.org>
+ * Copyright (C) Research In Motion Limited 2009-2010. 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"
+
+#if ENABLE(SVG)
+#include "core/rendering/svg/SVGRenderingContext.h"
+
+#include "core/page/Frame.h"
+#include "core/page/FrameView.h"
+#include "core/rendering/RenderLayer.h"
+#include "core/rendering/style/BasicShapes.h"
+#include "core/rendering/svg/RenderSVGImage.h"
+#include "core/rendering/svg/RenderSVGResource.h"
+#include "core/rendering/svg/RenderSVGResourceClipper.h"
+#include "core/rendering/svg/RenderSVGResourceFilter.h"
+#include "core/rendering/svg/RenderSVGResourceMasker.h"
+#include "core/rendering/svg/SVGResources.h"
+#include "core/rendering/svg/SVGResourcesCache.h"
+
+static int kMaxImageBufferSize = 4096;
+
+namespace WebCore {
+
+static inline bool isRenderingMaskImage(RenderObject* object)
+{
+    if (object->frame() && object->frame()->view())
+        return object->frame()->view()->paintBehavior() & PaintBehaviorRenderingSVGMask;
+    return false;
+}
+
+SVGRenderingContext::~SVGRenderingContext()
+{
+    // Fast path if we don't need to restore anything.
+    if (!(m_renderingFlags & ActionsNeeded))
+        return;
+
+    ASSERT(m_object && m_paintInfo);
+
+    if (m_renderingFlags & EndFilterLayer) {
+        ASSERT(m_filter);
+        m_filter->postApplyResource(m_object, m_paintInfo->context, ApplyToDefaultMode, 0, 0);
+        m_paintInfo->context = m_savedContext;
+        m_paintInfo->rect = m_savedPaintRect;
+    }
+
+    if (m_renderingFlags & EndOpacityLayer)
+        m_paintInfo->context->endTransparencyLayer();
+
+    if (m_renderingFlags & EndShadowLayer)
+        m_paintInfo->context->endTransparencyLayer();
+
+    if (m_renderingFlags & RestoreGraphicsContext)
+        m_paintInfo->context->restore();
+}
+
+void SVGRenderingContext::prepareToRenderSVGContent(RenderObject* object, PaintInfo& paintInfo, NeedsGraphicsContextSave needsGraphicsContextSave)
+{
+    ASSERT(object);
+
+#ifndef NDEBUG
+    // This function must not be called twice!
+    ASSERT(!(m_renderingFlags & PrepareToRenderSVGContentWasCalled));
+    m_renderingFlags |= PrepareToRenderSVGContentWasCalled;
+#endif
+
+    m_object = object;
+    m_paintInfo = &paintInfo;
+    m_filter = 0;
+
+    // We need to save / restore the context even if the initialization failed.
+    if (needsGraphicsContextSave == SaveGraphicsContext) {
+        m_paintInfo->context->save();
+        m_renderingFlags |= RestoreGraphicsContext;
+    }
+
+    RenderStyle* style = m_object->style();
+    ASSERT(style);
+
+    const SVGRenderStyle* svgStyle = style->svgStyle();
+    ASSERT(svgStyle);
+
+    // Setup transparency layers before setting up SVG resources!
+    bool isRenderingMask = isRenderingMaskImage(m_object);
+    float opacity = isRenderingMask ? 1 : style->opacity();
+    const ShadowData* shadow = svgStyle->shadow();
+    if (opacity < 1 || shadow) {
+        FloatRect repaintRect = m_object->repaintRectInLocalCoordinates();
+
+        if (opacity < 1) {
+            m_paintInfo->context->clip(repaintRect);
+            m_paintInfo->context->beginTransparencyLayer(opacity);
+            m_renderingFlags |= EndOpacityLayer;
+        }
+
+        if (shadow) {
+            m_paintInfo->context->clip(repaintRect);
+            m_paintInfo->context->setShadow(IntSize(roundToInt(shadow->x()), roundToInt(shadow->y())), shadow->blur(), shadow->color(), style->colorSpace());
+            m_paintInfo->context->beginTransparencyLayer(1);
+            m_renderingFlags |= EndShadowLayer;
+        }
+    }
+
+    ClipPathOperation* clipPathOperation = style->clipPath();
+    if (clipPathOperation && clipPathOperation->getOperationType() == ClipPathOperation::SHAPE) {
+        ShapeClipPathOperation* clipPath = static_cast<ShapeClipPathOperation*>(clipPathOperation);
+        m_paintInfo->context->clipPath(clipPath->path(object->objectBoundingBox()), clipPath->windRule());
+    }
+
+    SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(m_object);
+    if (!resources) {
+        if (svgStyle->hasFilter())
+            return;
+
+        m_renderingFlags |= RenderingPrepared;
+        return;
+    }
+
+    if (!isRenderingMask) {
+        if (RenderSVGResourceMasker* masker = resources->masker()) {
+            if (!masker->applyResource(m_object, style, m_paintInfo->context, ApplyToDefaultMode))
+                return;
+        }
+    }
+
+    RenderSVGResourceClipper* clipper = resources->clipper();
+    if (!clipPathOperation && clipper) {
+        if (!clipper->applyResource(m_object, style, m_paintInfo->context, ApplyToDefaultMode))
+            return;
+    }
+
+    if (!isRenderingMask) {
+        m_filter = resources->filter();
+        if (m_filter) {
+            m_savedContext = m_paintInfo->context;
+            m_savedPaintRect = m_paintInfo->rect;
+            // Return with false here may mean that we don't need to draw the content
+            // (because it was either drawn before or empty) but we still need to apply the filter.
+            m_renderingFlags |= EndFilterLayer;
+            if (!m_filter->applyResource(m_object, style, m_paintInfo->context, ApplyToDefaultMode))
+                return;
+
+            // Since we're caching the resulting bitmap and do not invalidate it on repaint rect
+            // changes, we need to paint the whole filter region. Otherwise, elements not visible
+            // at the time of the initial paint (due to scrolling, window size, etc.) will never
+            // be drawn.
+            m_paintInfo->rect = IntRect(m_filter->drawingRegion(m_object));
+        }
+    }
+
+    m_renderingFlags |= RenderingPrepared;
+}
+
+static AffineTransform& currentContentTransformation()
+{
+    DEFINE_STATIC_LOCAL(AffineTransform, s_currentContentTransformation, ());
+    return s_currentContentTransformation;
+}
+
+float SVGRenderingContext::calculateScreenFontSizeScalingFactor(const RenderObject* renderer)
+{
+    ASSERT(renderer);
+
+    AffineTransform ctm;
+    calculateTransformationToOutermostCoordinateSystem(renderer, ctm);
+    return narrowPrecisionToFloat(sqrt((pow(ctm.xScale(), 2) + pow(ctm.yScale(), 2)) / 2));
+}
+
+void SVGRenderingContext::calculateTransformationToOutermostCoordinateSystem(const RenderObject* renderer, AffineTransform& absoluteTransform)
+{
+    ASSERT(renderer);
+    absoluteTransform = currentContentTransformation();
+
+    // Walk up the render tree, accumulating SVG transforms.
+    while (renderer) {
+        absoluteTransform = renderer->localToParentTransform() * absoluteTransform;
+        if (renderer->isSVGRoot())
+            break;
+        renderer = renderer->parent();
+    }
+
+    // Continue walking up the layer tree, accumulating CSS transforms.
+    RenderLayer* layer = renderer ? renderer->enclosingLayer() : 0;
+    while (layer) {
+        if (TransformationMatrix* layerTransform = layer->transform())
+            absoluteTransform = layerTransform->toAffineTransform() * absoluteTransform;
+
+        // We can stop at compositing layers, to match the backing resolution.
+        if (layer->isComposited())
+            break;
+
+        layer = layer->parent();
+    }
+}
+
+bool SVGRenderingContext::createImageBuffer(const FloatRect& targetRect, const AffineTransform& absoluteTransform, OwnPtr<ImageBuffer>& imageBuffer, ColorSpace colorSpace, RenderingMode renderingMode)
+{
+    IntRect paintRect = calculateImageBufferRect(targetRect, absoluteTransform);
+    // Don't create empty ImageBuffers.
+    if (paintRect.isEmpty())
+        return false;
+
+    IntSize clampedSize = clampedAbsoluteSize(paintRect.size());
+    OwnPtr<ImageBuffer> image = ImageBuffer::create(clampedSize, 1, colorSpace, renderingMode);
+    if (!image)
+        return false;
+
+    GraphicsContext* imageContext = image->context();
+    ASSERT(imageContext);
+
+    imageContext->scale(FloatSize(static_cast<float>(clampedSize.width()) / paintRect.width(),
+                                  static_cast<float>(clampedSize.height()) / paintRect.height()));
+    imageContext->translate(-paintRect.x(), -paintRect.y());
+    imageContext->concatCTM(absoluteTransform);
+
+    imageBuffer = image.release();
+    return true;
+}
+
+bool SVGRenderingContext::createImageBufferForPattern(const FloatRect& absoluteTargetRect, const FloatRect& clampedAbsoluteTargetRect, OwnPtr<ImageBuffer>& imageBuffer, ColorSpace colorSpace, RenderingMode renderingMode)
+{
+    IntSize imageSize(roundedIntSize(clampedAbsoluteTargetRect.size()));
+    IntSize unclampedImageSize(roundedIntSize(absoluteTargetRect.size()));
+
+    // Don't create empty ImageBuffers.
+    if (imageSize.isEmpty())
+        return false;
+
+    OwnPtr<ImageBuffer> image = ImageBuffer::create(imageSize, 1, colorSpace, renderingMode);
+    if (!image)
+        return false;
+
+    GraphicsContext* imageContext = image->context();
+    ASSERT(imageContext);
+
+    // Compensate rounding effects, as the absolute target rect is using floating-point numbers and the image buffer size is integer.
+    imageContext->scale(FloatSize(unclampedImageSize.width() / absoluteTargetRect.width(), unclampedImageSize.height() / absoluteTargetRect.height()));
+
+    imageBuffer = image.release();
+    return true;
+}
+
+void SVGRenderingContext::renderSubtreeToImageBuffer(ImageBuffer* image, RenderObject* item, const AffineTransform& subtreeContentTransformation)
+{
+    ASSERT(item);
+    ASSERT(image);
+    ASSERT(image->context());
+
+    PaintInfo info(image->context(), PaintInfo::infiniteRect(), PaintPhaseForeground, PaintBehaviorNormal);
+
+    AffineTransform& contentTransformation = currentContentTransformation();
+    AffineTransform savedContentTransformation = contentTransformation;
+    contentTransformation = subtreeContentTransformation * contentTransformation;
+
+    ASSERT(!item->needsLayout());
+    item->paint(info, IntPoint());
+
+    contentTransformation = savedContentTransformation;
+}
+
+void SVGRenderingContext::clipToImageBuffer(GraphicsContext* context, const AffineTransform& absoluteTransform, const FloatRect& targetRect, OwnPtr<ImageBuffer>& imageBuffer, bool safeToClear)
+{
+    ASSERT(context);
+    ASSERT(imageBuffer);
+
+    FloatRect absoluteTargetRect = calculateImageBufferRect(targetRect, absoluteTransform);
+
+    // The mask image has been created in the absolute coordinate space, as the image should not be scaled.
+    // So the actual masking process has to be done in the absolute coordinate space as well.
+    context->concatCTM(absoluteTransform.inverse());
+    context->clipToImageBuffer(imageBuffer.get(), absoluteTargetRect);
+    context->concatCTM(absoluteTransform);
+
+    // When nesting resources, with objectBoundingBox as content unit types, there's no use in caching the
+    // resulting image buffer as the parent resource already caches the result.
+    if (safeToClear && !currentContentTransformation().isIdentity())
+        imageBuffer.clear();
+}
+
+FloatRect SVGRenderingContext::clampedAbsoluteTargetRect(const FloatRect& absoluteTargetRect)
+{
+    const FloatSize maxImageBufferSize(kMaxImageBufferSize, kMaxImageBufferSize);
+    return FloatRect(absoluteTargetRect.location(), absoluteTargetRect.size().shrunkTo(maxImageBufferSize));
+}
+
+IntSize SVGRenderingContext::clampedAbsoluteSize(const IntSize& absoluteSize)
+{
+    const IntSize maxImageBufferSize(kMaxImageBufferSize, kMaxImageBufferSize);
+    return absoluteSize.shrunkTo(maxImageBufferSize);
+}
+
+void SVGRenderingContext::clear2DRotation(AffineTransform& transform)
+{
+    AffineTransform::DecomposedType decomposition;
+    transform.decompose(decomposition);
+    decomposition.angle = 0;
+    transform.recompose(decomposition);
+}
+
+bool SVGRenderingContext::bufferForeground(OwnPtr<ImageBuffer>& imageBuffer)
+{
+    ASSERT(m_paintInfo);
+    ASSERT(m_object->isSVGImage());
+    FloatRect boundingBox = m_object->objectBoundingBox();
+
+    // Invalidate an existing buffer if the scale is not correct.
+    if (imageBuffer) {
+        AffineTransform transform = m_paintInfo->context->getCTM(GraphicsContext::DefinitelyIncludeDeviceScale);
+        IntSize expandedBoundingBox = expandedIntSize(boundingBox.size());
+        IntSize bufferSize(static_cast<int>(ceil(expandedBoundingBox.width() * transform.xScale())), static_cast<int>(ceil(expandedBoundingBox.height() * transform.yScale())));
+        if (bufferSize != imageBuffer->internalSize())
+            imageBuffer.clear();
+    }
+
+    // Create a new buffer and paint the foreground into it.
+    if (!imageBuffer) {
+        if ((imageBuffer = m_paintInfo->context->createCompatibleBuffer(expandedIntSize(boundingBox.size()), true))) {
+            GraphicsContext* bufferedRenderingContext = imageBuffer->context();
+            bufferedRenderingContext->translate(-boundingBox.x(), -boundingBox.y());
+            PaintInfo bufferedInfo(*m_paintInfo);
+            bufferedInfo.context = bufferedRenderingContext;
+            toRenderSVGImage(m_object)->paintForeground(bufferedInfo);
+        } else
+            return false;
+    }
+
+    m_paintInfo->context->drawImageBuffer(imageBuffer.get(), ColorSpaceDeviceRGB, boundingBox);
+    return true;
+}
+
+}
+
+#endif
diff --git a/Source/core/rendering/svg/SVGRenderingContext.h b/Source/core/rendering/svg/SVGRenderingContext.h
new file mode 100644
index 0000000..b605ae6
--- /dev/null
+++ b/Source/core/rendering/svg/SVGRenderingContext.h
@@ -0,0 +1,120 @@
+/**
+ * Copyright (C) 2007 Rob Buis <buis@kde.org>
+ * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
+ * Copyright (C) 2009 Google, Inc.  All rights reserved.
+ * Copyright (C) Research In Motion Limited 2010. All rights reserved.
+ * Copyright (C) 2012 Zoltan Herczeg <zherczeg@webkit.org>.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, 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 SVGRenderingContext_h
+#define SVGRenderingContext_h
+
+#if ENABLE(SVG)
+#include "core/platform/graphics/ImageBuffer.h"
+#include "core/rendering/PaintInfo.h"
+
+namespace WebCore {
+
+class AffineTransform;
+class RenderObject;
+class FloatRect;
+class RenderSVGResourceFilter;
+
+// SVGRenderingContext 
+class SVGRenderingContext {
+public:
+    enum NeedsGraphicsContextSave {
+        SaveGraphicsContext,
+        DontSaveGraphicsContext,
+    };
+
+    // Does not start rendering.
+    SVGRenderingContext()
+        : m_renderingFlags(0)
+        , m_object(0)
+        , m_paintInfo(0)
+        , m_savedContext(0)
+        , m_filter(0)
+    {
+    }
+
+    SVGRenderingContext(RenderObject* object, PaintInfo& paintinfo, NeedsGraphicsContextSave needsGraphicsContextSave = DontSaveGraphicsContext)
+        : m_renderingFlags(0)
+        , m_object(0)
+        , m_paintInfo(0)
+        , m_savedContext(0)
+        , m_filter(0)
+    {
+        prepareToRenderSVGContent(object, paintinfo, needsGraphicsContextSave);
+    }
+
+    // Automatically finishes context rendering.
+    ~SVGRenderingContext();
+
+    // Used by all SVG renderers who apply clip/filter/etc. resources to the renderer content.
+    void prepareToRenderSVGContent(RenderObject*, PaintInfo&, NeedsGraphicsContextSave = DontSaveGraphicsContext);
+    bool isRenderingPrepared() const { return m_renderingFlags & RenderingPrepared; }
+
+    static bool createImageBuffer(const FloatRect& paintRect, const AffineTransform& absoluteTransform, OwnPtr<ImageBuffer>&, ColorSpace, RenderingMode);
+    // Patterns need a different float-to-integer coordinate mapping.
+    static bool createImageBufferForPattern(const FloatRect& absoluteTargetRect, const FloatRect& clampedAbsoluteTargetRect, OwnPtr<ImageBuffer>&, ColorSpace, RenderingMode);
+
+    static void renderSubtreeToImageBuffer(ImageBuffer*, RenderObject*, const AffineTransform&);
+    static void clipToImageBuffer(GraphicsContext*, const AffineTransform& absoluteTransform, const FloatRect& targetRect, OwnPtr<ImageBuffer>&, bool safeToClear);
+
+    static float calculateScreenFontSizeScalingFactor(const RenderObject*);
+    static void calculateTransformationToOutermostCoordinateSystem(const RenderObject*, AffineTransform& absoluteTransform);
+    static IntSize clampedAbsoluteSize(const IntSize&);
+    static FloatRect clampedAbsoluteTargetRect(const FloatRect& absoluteTargetRect);
+    static void clear2DRotation(AffineTransform&);
+
+    static IntRect calculateImageBufferRect(const FloatRect& targetRect, const AffineTransform& absoluteTransform)
+    {
+        return enclosingIntRect(absoluteTransform.mapRect(targetRect));
+    }
+
+    // Support for the buffered-rendering hint.
+    bool bufferForeground(OwnPtr<ImageBuffer>&);
+
+private:
+    // To properly revert partially successful initializtions in the destructor, we record all successful steps.
+    enum RenderingFlags {
+        RenderingPrepared = 1,
+        RestoreGraphicsContext = 1 << 1,
+        EndOpacityLayer = 1 << 2,
+        EndShadowLayer = 1 << 3,
+        EndFilterLayer = 1 << 4,
+        PrepareToRenderSVGContentWasCalled = 1 << 5
+    };
+
+    // List of those flags which require actions during the destructor.
+    const static int ActionsNeeded = RestoreGraphicsContext | EndOpacityLayer | EndShadowLayer | EndFilterLayer;
+
+    int m_renderingFlags;
+    RenderObject* m_object;
+    PaintInfo* m_paintInfo;
+    GraphicsContext* m_savedContext;
+    IntRect m_savedPaintRect;
+    RenderSVGResourceFilter* m_filter;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
+#endif // SVGRenderingContext_h
diff --git a/Source/core/rendering/svg/SVGResources.cpp b/Source/core/rendering/svg/SVGResources.cpp
new file mode 100644
index 0000000..87bbeb4
--- /dev/null
+++ b/Source/core/rendering/svg/SVGResources.cpp
@@ -0,0 +1,668 @@
+/*
+ * Copyright (C) Research In Motion Limited 2010. 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 "core/rendering/svg/SVGResources.h"
+
+#if ENABLE(SVG)
+#include "SVGNames.h"
+#include "core/rendering/style/SVGRenderStyle.h"
+#include "core/rendering/svg/RenderSVGResourceClipper.h"
+#include "core/rendering/svg/RenderSVGResourceFilter.h"
+#include "core/rendering/svg/RenderSVGResourceMarker.h"
+#include "core/rendering/svg/RenderSVGResourceMasker.h"
+#include "core/svg/SVGFilterElement.h"
+#include "core/svg/SVGGradientElement.h"
+#include "core/svg/SVGPaint.h"
+#include "core/svg/SVGPatternElement.h"
+#include "core/svg/SVGURIReference.h"
+
+#ifndef NDEBUG
+#include <stdio.h>
+#endif
+
+namespace WebCore {
+
+SVGResources::SVGResources()
+    : m_linkedResource(0)
+{
+}
+
+static HashSet<AtomicString>& clipperFilterMaskerTags()
+{
+    DEFINE_STATIC_LOCAL(HashSet<AtomicString>, s_tagList, ());
+    if (s_tagList.isEmpty()) {
+        // "container elements": http://www.w3.org/TR/SVG11/intro.html#TermContainerElement
+        // "graphics elements" : http://www.w3.org/TR/SVG11/intro.html#TermGraphicsElement
+        s_tagList.add(SVGNames::aTag.localName());
+        s_tagList.add(SVGNames::circleTag.localName());
+        s_tagList.add(SVGNames::ellipseTag.localName());
+        s_tagList.add(SVGNames::glyphTag.localName());
+        s_tagList.add(SVGNames::gTag.localName());
+        s_tagList.add(SVGNames::imageTag.localName());
+        s_tagList.add(SVGNames::lineTag.localName());
+        s_tagList.add(SVGNames::markerTag.localName());
+        s_tagList.add(SVGNames::maskTag.localName());
+        s_tagList.add(SVGNames::missing_glyphTag.localName());
+        s_tagList.add(SVGNames::pathTag.localName());
+        s_tagList.add(SVGNames::polygonTag.localName());
+        s_tagList.add(SVGNames::polylineTag.localName());
+        s_tagList.add(SVGNames::rectTag.localName());
+        s_tagList.add(SVGNames::svgTag.localName());
+        s_tagList.add(SVGNames::textTag.localName());
+        s_tagList.add(SVGNames::useTag.localName());
+
+        // Not listed in the definitions is the clipPath element, the SVG spec says though:
+        // The "clipPath" element or any of its children can specify property "clip-path".
+        // So we have to add clipPathTag here, otherwhise clip-path on clipPath will fail.
+        // (Already mailed SVG WG, waiting for a solution)
+        s_tagList.add(SVGNames::clipPathTag.localName());
+
+        // Not listed in the definitions are the text content elements, though filter/clipper/masker on tspan/text/.. is allowed.
+        // (Already mailed SVG WG, waiting for a solution)
+        s_tagList.add(SVGNames::altGlyphTag.localName());
+        s_tagList.add(SVGNames::textPathTag.localName());
+        s_tagList.add(SVGNames::trefTag.localName());
+        s_tagList.add(SVGNames::tspanTag.localName());
+
+        // Not listed in the definitions is the foreignObject element, but clip-path
+        // is a supported attribute.
+        s_tagList.add(SVGNames::foreignObjectTag.localName());
+
+        // Elements that we ignore, as it doesn't make any sense.
+        // defs, pattern, switch (FIXME: Mail SVG WG about these)
+        // symbol (is converted to a svg element, when referenced by use, we can safely ignore it.)
+    }
+
+    return s_tagList;
+}
+
+static HashSet<AtomicString>& markerTags()
+{
+    DEFINE_STATIC_LOCAL(HashSet<AtomicString>, s_tagList, ());
+    if (s_tagList.isEmpty()) {
+        s_tagList.add(SVGNames::lineTag.localName());
+        s_tagList.add(SVGNames::pathTag.localName());
+        s_tagList.add(SVGNames::polygonTag.localName());
+        s_tagList.add(SVGNames::polylineTag.localName());
+    }
+
+    return s_tagList;
+}
+
+static HashSet<AtomicString>& fillAndStrokeTags()
+{
+    DEFINE_STATIC_LOCAL(HashSet<AtomicString>, s_tagList, ());
+    if (s_tagList.isEmpty()) {
+        s_tagList.add(SVGNames::altGlyphTag.localName());
+        s_tagList.add(SVGNames::circleTag.localName());
+        s_tagList.add(SVGNames::ellipseTag.localName());
+        s_tagList.add(SVGNames::lineTag.localName());
+        s_tagList.add(SVGNames::pathTag.localName());
+        s_tagList.add(SVGNames::polygonTag.localName());
+        s_tagList.add(SVGNames::polylineTag.localName());
+        s_tagList.add(SVGNames::rectTag.localName());
+        s_tagList.add(SVGNames::textTag.localName());
+        s_tagList.add(SVGNames::textPathTag.localName());
+        s_tagList.add(SVGNames::trefTag.localName());
+        s_tagList.add(SVGNames::tspanTag.localName());
+    }
+
+    return s_tagList;
+}
+
+static HashSet<AtomicString>& chainableResourceTags()
+{
+    DEFINE_STATIC_LOCAL(HashSet<AtomicString>, s_tagList, ());
+    if (s_tagList.isEmpty()) {
+        s_tagList.add(SVGNames::linearGradientTag.localName());
+        s_tagList.add(SVGNames::filterTag.localName());
+        s_tagList.add(SVGNames::patternTag.localName());
+        s_tagList.add(SVGNames::radialGradientTag.localName());
+    }
+
+    return s_tagList;
+}
+
+static inline String targetReferenceFromResource(SVGElement* element)
+{
+    String target;
+    if (element->hasTagName(SVGNames::patternTag))
+        target = static_cast<SVGPatternElement*>(element)->href();
+    else if (element->hasTagName(SVGNames::linearGradientTag) || element->hasTagName(SVGNames::radialGradientTag))
+        target = static_cast<SVGGradientElement*>(element)->href();
+    else if (element->hasTagName(SVGNames::filterTag))
+        target = static_cast<SVGFilterElement*>(element)->href();
+    else
+        ASSERT_NOT_REACHED();
+
+    return SVGURIReference::fragmentIdentifierFromIRIString(target, element->document());
+}
+
+static inline RenderSVGResourceContainer* paintingResourceFromSVGPaint(Document* document, const SVGPaint::SVGPaintType& paintType, const String& paintUri, AtomicString& id, bool& hasPendingResource)
+{
+    if (paintType != SVGPaint::SVG_PAINTTYPE_URI && paintType != SVGPaint::SVG_PAINTTYPE_URI_RGBCOLOR)
+        return 0;
+
+    id = SVGURIReference::fragmentIdentifierFromIRIString(paintUri, document);
+    RenderSVGResourceContainer* container = getRenderSVGResourceContainerById(document, id);
+    if (!container) {
+        hasPendingResource = true;
+        return 0;
+    }
+
+    RenderSVGResourceType resourceType = container->resourceType();
+    if (resourceType != PatternResourceType && resourceType != LinearGradientResourceType && resourceType != RadialGradientResourceType)
+        return 0;
+
+    return container;
+}
+
+static inline void registerPendingResource(SVGDocumentExtensions* extensions, const AtomicString& id, SVGElement* element)
+{
+    ASSERT(element);
+    ASSERT_WITH_SECURITY_IMPLICATION(element->isSVGStyledElement());
+    extensions->addPendingResource(id, toSVGStyledElement(element));
+}
+
+bool SVGResources::buildCachedResources(const RenderObject* object, const SVGRenderStyle* style)
+{
+    ASSERT(object);
+    ASSERT(style);
+
+    Node* node = object->node();
+    ASSERT(node);
+    ASSERT_WITH_SECURITY_IMPLICATION(node->isSVGElement());
+
+    SVGElement* element = toSVGElement(node);
+    if (!element)
+        return false;
+
+    Document* document = object->document();
+    ASSERT(document);
+
+    SVGDocumentExtensions* extensions = document->accessSVGExtensions();
+    ASSERT(extensions);
+
+    const AtomicString& tagName = element->localName();
+    if (tagName.isNull())
+        return false;
+
+    bool foundResources = false;
+    if (clipperFilterMaskerTags().contains(tagName)) {
+        if (style->hasClipper()) {
+            AtomicString id(style->clipperResource());
+            if (setClipper(getRenderSVGResourceById<RenderSVGResourceClipper>(document, id)))
+                foundResources = true;
+            else
+                registerPendingResource(extensions, id, element);
+        }
+
+        if (style->hasFilter()) {
+            AtomicString id(style->filterResource());
+            if (setFilter(getRenderSVGResourceById<RenderSVGResourceFilter>(document, id)))
+                foundResources = true;
+            else
+                registerPendingResource(extensions, id, element);
+        }
+
+        if (style->hasMasker()) {
+            AtomicString id(style->maskerResource());
+            if (setMasker(getRenderSVGResourceById<RenderSVGResourceMasker>(document, id)))
+                foundResources = true;
+            else
+                registerPendingResource(extensions, id, element);
+        }
+    }
+
+    if (markerTags().contains(tagName) && style->hasMarkers()) {
+        AtomicString markerStartId(style->markerStartResource());
+        if (setMarkerStart(getRenderSVGResourceById<RenderSVGResourceMarker>(document, markerStartId)))
+            foundResources = true;
+        else
+            registerPendingResource(extensions, markerStartId, element);
+
+        AtomicString markerMidId(style->markerMidResource());
+        if (setMarkerMid(getRenderSVGResourceById<RenderSVGResourceMarker>(document, markerMidId)))
+            foundResources = true;
+        else
+            registerPendingResource(extensions, markerMidId, element);
+
+        AtomicString markerEndId(style->markerEndResource());
+        if (setMarkerEnd(getRenderSVGResourceById<RenderSVGResourceMarker>(document, markerEndId)))
+            foundResources = true;
+        else
+            registerPendingResource(extensions, markerEndId, element);
+    }
+
+    if (fillAndStrokeTags().contains(tagName)) {
+        if (style->hasFill()) {
+            bool hasPendingResource = false;
+            AtomicString id;
+            if (setFill(paintingResourceFromSVGPaint(document, style->fillPaintType(), style->fillPaintUri(), id, hasPendingResource)))
+                foundResources = true;
+            else if (hasPendingResource)
+                registerPendingResource(extensions, id, element);
+        }
+
+        if (style->hasStroke()) {
+            bool hasPendingResource = false;
+            AtomicString id;
+            if (setStroke(paintingResourceFromSVGPaint(document, style->strokePaintType(), style->strokePaintUri(), id, hasPendingResource)))
+                foundResources = true;
+            else if (hasPendingResource)
+                registerPendingResource(extensions, id, element);
+        }
+    }
+
+    if (chainableResourceTags().contains(tagName)) {
+        AtomicString id(targetReferenceFromResource(element));
+        if (setLinkedResource(getRenderSVGResourceContainerById(document, id)))
+            foundResources = true;
+        else
+            registerPendingResource(extensions, id, element);
+    }
+
+    return foundResources;
+}
+
+void SVGResources::removeClientFromCache(RenderObject* object, bool markForInvalidation) const
+{
+    if (!m_clipperFilterMaskerData && !m_markerData && !m_fillStrokeData && !m_linkedResource)
+        return;
+
+    if (m_linkedResource) {
+        ASSERT(!m_clipperFilterMaskerData);
+        ASSERT(!m_markerData);
+        ASSERT(!m_fillStrokeData);
+        m_linkedResource->removeClientFromCache(object, markForInvalidation);
+        return;
+    }
+
+    if (m_clipperFilterMaskerData) {
+        if (m_clipperFilterMaskerData->clipper)
+            m_clipperFilterMaskerData->clipper->removeClientFromCache(object, markForInvalidation);
+        if (m_clipperFilterMaskerData->filter)
+            m_clipperFilterMaskerData->filter->removeClientFromCache(object, markForInvalidation);
+        if (m_clipperFilterMaskerData->masker)
+            m_clipperFilterMaskerData->masker->removeClientFromCache(object, markForInvalidation);
+    }
+
+    if (m_markerData) {
+        if (m_markerData->markerStart)
+            m_markerData->markerStart->removeClientFromCache(object, markForInvalidation);
+        if (m_markerData->markerMid)
+            m_markerData->markerMid->removeClientFromCache(object, markForInvalidation);
+        if (m_markerData->markerEnd)
+            m_markerData->markerEnd->removeClientFromCache(object, markForInvalidation);
+    }
+
+    if (m_fillStrokeData) {
+        if (m_fillStrokeData->fill)
+            m_fillStrokeData->fill->removeClientFromCache(object, markForInvalidation);
+        if (m_fillStrokeData->stroke)
+            m_fillStrokeData->stroke->removeClientFromCache(object, markForInvalidation);
+    }
+}
+
+void SVGResources::resourceDestroyed(RenderSVGResourceContainer* resource)
+{
+    ASSERT(resource);
+    if (!m_clipperFilterMaskerData && !m_markerData && !m_fillStrokeData && !m_linkedResource)
+        return;
+
+    if (m_linkedResource == resource) {
+        ASSERT(!m_clipperFilterMaskerData);
+        ASSERT(!m_markerData);
+        ASSERT(!m_fillStrokeData);
+        m_linkedResource->removeAllClientsFromCache();
+        m_linkedResource = 0;
+        return;
+    }
+
+    switch (resource->resourceType()) {
+    case MaskerResourceType:
+        if (!m_clipperFilterMaskerData)
+            break;
+        if (m_clipperFilterMaskerData->masker == resource) {
+            m_clipperFilterMaskerData->masker->removeAllClientsFromCache();
+            m_clipperFilterMaskerData->masker = 0;
+        }
+        break;
+    case MarkerResourceType:
+        if (!m_markerData)
+            break;
+        if (m_markerData->markerStart == resource) {
+            m_markerData->markerStart->removeAllClientsFromCache();
+            m_markerData->markerStart = 0;
+        }
+        if (m_markerData->markerMid == resource) {
+            m_markerData->markerMid->removeAllClientsFromCache();
+            m_markerData->markerMid = 0;
+        }
+        if (m_markerData->markerEnd == resource) {
+            m_markerData->markerEnd->removeAllClientsFromCache();
+            m_markerData->markerEnd = 0;
+        }
+        break;
+    case PatternResourceType:
+    case LinearGradientResourceType:
+    case RadialGradientResourceType:
+        if (!m_fillStrokeData)
+            break;
+        if (m_fillStrokeData->fill == resource) {
+            m_fillStrokeData->fill->removeAllClientsFromCache();
+            m_fillStrokeData->fill = 0;
+        }
+        if (m_fillStrokeData->stroke == resource) {
+            m_fillStrokeData->stroke->removeAllClientsFromCache();
+            m_fillStrokeData->stroke = 0;
+        }
+        break;
+    case FilterResourceType:
+        if (!m_clipperFilterMaskerData)
+            break;
+        if (m_clipperFilterMaskerData->filter == resource) {
+            m_clipperFilterMaskerData->filter->removeAllClientsFromCache();
+            m_clipperFilterMaskerData->filter = 0;
+        }
+        break;
+    case ClipperResourceType:
+        if (!m_clipperFilterMaskerData)
+            break; 
+        if (m_clipperFilterMaskerData->clipper == resource) {
+            m_clipperFilterMaskerData->clipper->removeAllClientsFromCache();
+            m_clipperFilterMaskerData->clipper = 0;
+        }
+        break;
+    case SolidColorResourceType:
+        ASSERT_NOT_REACHED();
+    }
+}
+
+void SVGResources::buildSetOfResources(HashSet<RenderSVGResourceContainer*>& set)
+{
+    if (!m_clipperFilterMaskerData && !m_markerData && !m_fillStrokeData && !m_linkedResource)
+        return;
+
+    if (m_linkedResource) {
+        ASSERT(!m_clipperFilterMaskerData);
+        ASSERT(!m_markerData);
+        ASSERT(!m_fillStrokeData);
+        set.add(m_linkedResource);
+        return;
+    }
+
+    if (m_clipperFilterMaskerData) {
+        if (m_clipperFilterMaskerData->clipper)
+            set.add(m_clipperFilterMaskerData->clipper);
+        if (m_clipperFilterMaskerData->filter)
+            set.add(m_clipperFilterMaskerData->filter);
+        if (m_clipperFilterMaskerData->masker)
+            set.add(m_clipperFilterMaskerData->masker);
+    }
+
+    if (m_markerData) {
+        if (m_markerData->markerStart)
+            set.add(m_markerData->markerStart);
+        if (m_markerData->markerMid)
+            set.add(m_markerData->markerMid);
+        if (m_markerData->markerEnd)
+            set.add(m_markerData->markerEnd);
+    }
+
+    if (m_fillStrokeData) {
+        if (m_fillStrokeData->fill)
+            set.add(m_fillStrokeData->fill);
+        if (m_fillStrokeData->stroke)
+            set.add(m_fillStrokeData->stroke);
+    }
+}
+
+bool SVGResources::setClipper(RenderSVGResourceClipper* clipper)
+{
+    if (!clipper)
+        return false;
+
+    ASSERT(clipper->resourceType() == ClipperResourceType);
+
+    if (!m_clipperFilterMaskerData)
+        m_clipperFilterMaskerData = ClipperFilterMaskerData::create();
+
+    m_clipperFilterMaskerData->clipper = clipper;
+    return true;
+}
+
+void SVGResources::resetClipper()
+{
+    ASSERT(m_clipperFilterMaskerData);
+    ASSERT(m_clipperFilterMaskerData->clipper);
+    m_clipperFilterMaskerData->clipper = 0;
+}
+
+bool SVGResources::setFilter(RenderSVGResourceFilter* filter)
+{
+    if (!filter)
+        return false;
+
+    ASSERT(filter->resourceType() == FilterResourceType);
+
+    if (!m_clipperFilterMaskerData)
+        m_clipperFilterMaskerData = ClipperFilterMaskerData::create();
+
+    m_clipperFilterMaskerData->filter = filter;
+    return true;
+}
+
+void SVGResources::resetFilter()
+{
+    ASSERT(m_clipperFilterMaskerData);
+    ASSERT(m_clipperFilterMaskerData->filter);
+    m_clipperFilterMaskerData->filter = 0;
+}
+
+bool SVGResources::setMarkerStart(RenderSVGResourceMarker* markerStart)
+{
+    if (!markerStart)
+        return false;
+
+    ASSERT(markerStart->resourceType() == MarkerResourceType);
+
+    if (!m_markerData)
+        m_markerData = MarkerData::create();
+
+    m_markerData->markerStart = markerStart;
+    return true;
+}
+
+void SVGResources::resetMarkerStart()
+{
+    ASSERT(m_markerData);
+    ASSERT(m_markerData->markerStart);
+    m_markerData->markerStart = 0;
+}
+
+bool SVGResources::setMarkerMid(RenderSVGResourceMarker* markerMid)
+{
+    if (!markerMid)
+        return false;
+
+    ASSERT(markerMid->resourceType() == MarkerResourceType);
+
+    if (!m_markerData)
+        m_markerData = MarkerData::create();
+
+    m_markerData->markerMid = markerMid;
+    return true;
+}
+
+void SVGResources::resetMarkerMid()
+{
+    ASSERT(m_markerData);
+    ASSERT(m_markerData->markerMid);
+    m_markerData->markerMid = 0;
+}
+
+bool SVGResources::setMarkerEnd(RenderSVGResourceMarker* markerEnd)
+{
+    if (!markerEnd)
+        return false;
+
+    ASSERT(markerEnd->resourceType() == MarkerResourceType);
+
+    if (!m_markerData)
+        m_markerData = MarkerData::create();
+
+    m_markerData->markerEnd = markerEnd;
+    return true;
+}
+
+void SVGResources::resetMarkerEnd()
+{
+    ASSERT(m_markerData);
+    ASSERT(m_markerData->markerEnd);
+    m_markerData->markerEnd = 0;
+}
+
+bool SVGResources::setMasker(RenderSVGResourceMasker* masker)
+{
+    if (!masker)
+        return false;
+
+    ASSERT(masker->resourceType() == MaskerResourceType);
+
+    if (!m_clipperFilterMaskerData)
+        m_clipperFilterMaskerData = ClipperFilterMaskerData::create();
+
+    m_clipperFilterMaskerData->masker = masker;
+    return true;
+}
+
+void SVGResources::resetMasker()
+{
+    ASSERT(m_clipperFilterMaskerData);
+    ASSERT(m_clipperFilterMaskerData->masker);
+    m_clipperFilterMaskerData->masker = 0;
+}
+
+bool SVGResources::setFill(RenderSVGResourceContainer* fill)
+{
+    if (!fill)
+        return false;
+
+    ASSERT(fill->resourceType() == PatternResourceType
+           || fill->resourceType() == LinearGradientResourceType
+           || fill->resourceType() == RadialGradientResourceType);
+
+    if (!m_fillStrokeData)
+        m_fillStrokeData = FillStrokeData::create();
+
+    m_fillStrokeData->fill = fill;
+    return true;
+}
+
+void SVGResources::resetFill()
+{
+    ASSERT(m_fillStrokeData);
+    ASSERT(m_fillStrokeData->fill);
+    m_fillStrokeData->fill = 0;
+}
+
+bool SVGResources::setStroke(RenderSVGResourceContainer* stroke)
+{
+    if (!stroke)
+        return false;
+
+    ASSERT(stroke->resourceType() == PatternResourceType
+           || stroke->resourceType() == LinearGradientResourceType
+           || stroke->resourceType() == RadialGradientResourceType);
+
+    if (!m_fillStrokeData)
+        m_fillStrokeData = FillStrokeData::create();
+
+    m_fillStrokeData->stroke = stroke;
+    return true;
+}
+
+void SVGResources::resetStroke()
+{
+    ASSERT(m_fillStrokeData);
+    ASSERT(m_fillStrokeData->stroke);
+    m_fillStrokeData->stroke = 0;
+}
+
+bool SVGResources::setLinkedResource(RenderSVGResourceContainer* linkedResource)
+{
+    if (!linkedResource)
+        return false;
+
+    m_linkedResource = linkedResource;
+    return true;
+}
+
+void SVGResources::resetLinkedResource()
+{
+    ASSERT(m_linkedResource);
+    m_linkedResource = 0;
+}
+
+#ifndef NDEBUG
+void SVGResources::dump(const RenderObject* object)
+{
+    ASSERT(object);
+    ASSERT(object->node());
+
+    fprintf(stderr, "-> this=%p, SVGResources(renderer=%p, node=%p)\n", this, object, object->node());
+    fprintf(stderr, " | DOM Tree:\n");
+    object->node()->showTreeForThis();
+
+    fprintf(stderr, "\n | List of resources:\n");
+    if (m_clipperFilterMaskerData) {
+        if (RenderSVGResourceClipper* clipper = m_clipperFilterMaskerData->clipper)
+            fprintf(stderr, " |-> Clipper    : %p (node=%p)\n", clipper, clipper->node());
+        if (RenderSVGResourceFilter* filter = m_clipperFilterMaskerData->filter)
+            fprintf(stderr, " |-> Filter     : %p (node=%p)\n", filter, filter->node());
+        if (RenderSVGResourceMasker* masker = m_clipperFilterMaskerData->masker)
+            fprintf(stderr, " |-> Masker     : %p (node=%p)\n", masker, masker->node());
+    }
+
+    if (m_markerData) {
+        if (RenderSVGResourceMarker* markerStart = m_markerData->markerStart)
+            fprintf(stderr, " |-> MarkerStart: %p (node=%p)\n", markerStart, markerStart->node());
+        if (RenderSVGResourceMarker* markerMid = m_markerData->markerMid)
+            fprintf(stderr, " |-> MarkerMid  : %p (node=%p)\n", markerMid, markerMid->node());
+        if (RenderSVGResourceMarker* markerEnd = m_markerData->markerEnd)
+            fprintf(stderr, " |-> MarkerEnd  : %p (node=%p)\n", markerEnd, markerEnd->node());
+    }
+
+    if (m_fillStrokeData) {
+        if (RenderSVGResourceContainer* fill = m_fillStrokeData->fill)
+            fprintf(stderr, " |-> Fill       : %p (node=%p)\n", fill, fill->node());
+        if (RenderSVGResourceContainer* stroke = m_fillStrokeData->stroke)
+            fprintf(stderr, " |-> Stroke     : %p (node=%p)\n", stroke, stroke->node());
+    }
+
+    if (m_linkedResource)
+        fprintf(stderr, " |-> xlink:href : %p (node=%p)\n", m_linkedResource, m_linkedResource->node());
+}
+#endif
+
+}
+
+#endif
diff --git a/Source/core/rendering/svg/SVGResources.h b/Source/core/rendering/svg/SVGResources.h
new file mode 100644
index 0000000..9d13e18
--- /dev/null
+++ b/Source/core/rendering/svg/SVGResources.h
@@ -0,0 +1,182 @@
+/*
+ * Copyright (C) Research In Motion Limited 2010. 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 SVGResources_h
+#define SVGResources_h
+
+#if ENABLE(SVG)
+#include <wtf/HashSet.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/OwnPtr.h>
+#include <wtf/PassOwnPtr.h>
+
+namespace WebCore {
+
+class Document;
+class RenderObject;
+class RenderSVGResourceClipper;
+class RenderSVGResourceContainer;
+class RenderSVGResourceFilter;
+class RenderSVGResourceMarker;
+class RenderSVGResourceMasker;
+class SVGRenderStyle;
+
+// Holds a set of resources associated with a RenderObject
+class SVGResources {
+    WTF_MAKE_NONCOPYABLE(SVGResources); WTF_MAKE_FAST_ALLOCATED;
+public:
+    SVGResources();
+
+    bool buildCachedResources(const RenderObject*, const SVGRenderStyle*);
+
+    // Ordinary resources
+    RenderSVGResourceClipper* clipper() const { return m_clipperFilterMaskerData ? m_clipperFilterMaskerData->clipper : 0; }
+    RenderSVGResourceMarker* markerStart() const { return m_markerData ? m_markerData->markerStart : 0; }
+    RenderSVGResourceMarker* markerMid() const { return m_markerData ? m_markerData->markerMid : 0; }
+    RenderSVGResourceMarker* markerEnd() const { return m_markerData ? m_markerData->markerEnd : 0; }
+    RenderSVGResourceMasker* masker() const { return m_clipperFilterMaskerData ? m_clipperFilterMaskerData->masker : 0; }
+
+    RenderSVGResourceFilter* filter() const
+    {
+        if (m_clipperFilterMaskerData)
+            return m_clipperFilterMaskerData->filter;
+        return 0;
+    }
+
+    // Paint servers
+    RenderSVGResourceContainer* fill() const { return m_fillStrokeData ? m_fillStrokeData->fill : 0; }
+    RenderSVGResourceContainer* stroke() const { return m_fillStrokeData ? m_fillStrokeData->stroke : 0; }
+
+    // Chainable resources - linked through xlink:href
+    RenderSVGResourceContainer* linkedResource() const { return m_linkedResource; }
+
+    void buildSetOfResources(HashSet<RenderSVGResourceContainer*>&);
+
+    // Methods operating on all cached resources
+    void removeClientFromCache(RenderObject*, bool markForInvalidation = true) const;
+    void resourceDestroyed(RenderSVGResourceContainer*);
+
+#ifndef NDEBUG
+    void dump(const RenderObject*);
+#endif
+
+private:
+    friend class SVGResourcesCycleSolver;
+
+    // Only used by SVGResourcesCache cycle detection logic
+    void resetClipper();
+    void resetFilter();
+    void resetMarkerStart();
+    void resetMarkerMid();
+    void resetMarkerEnd();
+    void resetMasker();
+    void resetFill();
+    void resetStroke();
+    void resetLinkedResource();
+
+private:
+    bool setClipper(RenderSVGResourceClipper*);
+    bool setFilter(RenderSVGResourceFilter*);
+    bool setMarkerStart(RenderSVGResourceMarker*);
+    bool setMarkerMid(RenderSVGResourceMarker*);
+    bool setMarkerEnd(RenderSVGResourceMarker*);
+    bool setMasker(RenderSVGResourceMasker*);
+    bool setFill(RenderSVGResourceContainer*);
+    bool setStroke(RenderSVGResourceContainer*);
+    bool setLinkedResource(RenderSVGResourceContainer*);
+
+    // From SVG 1.1 2nd Edition
+    // clipper: 'container elements' and 'graphics elements'
+    // filter:  'container elements' and 'graphics elements'
+    // masker:  'container elements' and 'graphics elements'
+    // -> a, circle, defs, ellipse, glyph, g, image, line, marker, mask, missing-glyph, path, pattern, polygon, polyline, rect, svg, switch, symbol, text, use
+    struct ClipperFilterMaskerData {
+        WTF_MAKE_FAST_ALLOCATED;
+    public:
+        ClipperFilterMaskerData()
+            : clipper(0)
+            , filter(0)
+            , masker(0)
+        {
+        }
+
+        static PassOwnPtr<ClipperFilterMaskerData> create()
+        {
+            return adoptPtr(new ClipperFilterMaskerData);
+        }
+
+        RenderSVGResourceClipper* clipper;
+        RenderSVGResourceFilter* filter;
+        RenderSVGResourceMasker* masker;
+    };
+
+    // From SVG 1.1 2nd Edition
+    // marker: line, path, polygon, polyline
+    struct MarkerData {
+        WTF_MAKE_FAST_ALLOCATED;
+    public:
+        MarkerData()
+            : markerStart(0)
+            , markerMid(0)
+            , markerEnd(0)
+        {
+        }
+
+        static PassOwnPtr<MarkerData> create()
+        {
+            return adoptPtr(new MarkerData);
+        }
+
+        RenderSVGResourceMarker* markerStart;
+        RenderSVGResourceMarker* markerMid;
+        RenderSVGResourceMarker* markerEnd;
+    };
+
+    // From SVG 1.1 2nd Edition
+    // fill:       'shapes' and 'text content elements'
+    // stroke:     'shapes' and 'text content elements'
+    // -> altGlyph, circle, ellipse, line, path, polygon, polyline, rect, text, textPath, tref, tspan
+    struct FillStrokeData {
+        WTF_MAKE_FAST_ALLOCATED;
+    public:
+        FillStrokeData()
+            : fill(0)
+            , stroke(0)
+        {
+        }
+
+        static PassOwnPtr<FillStrokeData> create()
+        {
+            return adoptPtr(new FillStrokeData);
+        }
+
+        RenderSVGResourceContainer* fill;
+        RenderSVGResourceContainer* stroke;
+    };
+
+    OwnPtr<ClipperFilterMaskerData> m_clipperFilterMaskerData;
+    OwnPtr<MarkerData> m_markerData;
+    OwnPtr<FillStrokeData> m_fillStrokeData;
+    RenderSVGResourceContainer* m_linkedResource;
+};
+
+}
+
+#endif
+#endif
diff --git a/Source/core/rendering/svg/SVGResourcesCache.cpp b/Source/core/rendering/svg/SVGResourcesCache.cpp
new file mode 100644
index 0000000..9ebf2b2
--- /dev/null
+++ b/Source/core/rendering/svg/SVGResourcesCache.cpp
@@ -0,0 +1,218 @@
+/*
+ * Copyright (C) Research In Motion Limited 2010. 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 "core/rendering/svg/SVGResourcesCache.h"
+
+#if ENABLE(SVG)
+#include "HTMLNames.h"
+#include "core/rendering/svg/RenderSVGResourceContainer.h"
+#include "core/rendering/svg/SVGResources.h"
+#include "core/rendering/svg/SVGResourcesCycleSolver.h"
+#include "core/svg/SVGDocumentExtensions.h"
+#include "core/svg/SVGStyledElement.h"
+
+namespace WebCore {
+
+SVGResourcesCache::SVGResourcesCache()
+{
+}
+
+SVGResourcesCache::~SVGResourcesCache()
+{
+    deleteAllValues(m_cache);
+}
+
+void SVGResourcesCache::addResourcesFromRenderObject(RenderObject* object, const RenderStyle* style)
+{
+    ASSERT(object);
+    ASSERT(style);
+    ASSERT(!m_cache.contains(object));
+
+    const SVGRenderStyle* svgStyle = style->svgStyle();
+    ASSERT(svgStyle);
+
+    // Build a list of all resources associated with the passed RenderObject
+    SVGResources* resources = new SVGResources;
+    if (!resources->buildCachedResources(object, svgStyle)) {
+        delete resources;
+        return;
+    }
+
+    // Put object in cache.
+    m_cache.set(object, resources);
+
+    // Run cycle-detection _afterwards_, so self-references can be caught as well.
+    SVGResourcesCycleSolver solver(object, resources);
+    solver.resolveCycles();
+
+    // Walk resources and register the render object at each resources.
+    HashSet<RenderSVGResourceContainer*> resourceSet;
+    resources->buildSetOfResources(resourceSet);
+
+    HashSet<RenderSVGResourceContainer*>::iterator end = resourceSet.end();
+    for (HashSet<RenderSVGResourceContainer*>::iterator it = resourceSet.begin(); it != end; ++it)
+        (*it)->addClient(object);
+}
+
+void SVGResourcesCache::removeResourcesFromRenderObject(RenderObject* object)
+{
+    if (!m_cache.contains(object))
+        return;
+
+    SVGResources* resources = m_cache.get(object);
+
+    // Walk resources and register the render object at each resources.
+    HashSet<RenderSVGResourceContainer*> resourceSet;
+    resources->buildSetOfResources(resourceSet);
+
+    HashSet<RenderSVGResourceContainer*>::iterator end = resourceSet.end();
+    for (HashSet<RenderSVGResourceContainer*>::iterator it = resourceSet.begin(); it != end; ++it)
+        (*it)->removeClient(object);
+
+    delete m_cache.take(object);
+}
+
+static inline SVGResourcesCache* resourcesCacheFromRenderObject(const RenderObject* renderer)
+{
+    Document* document = renderer->document();
+    ASSERT(document);
+
+    SVGDocumentExtensions* extensions = document->accessSVGExtensions();
+    ASSERT(extensions);
+
+    SVGResourcesCache* cache = extensions->resourcesCache();
+    ASSERT(cache);
+
+    return cache;
+}
+
+SVGResources* SVGResourcesCache::cachedResourcesForRenderObject(const RenderObject* renderer)
+{
+    ASSERT(renderer);
+    SVGResourcesCache* cache = resourcesCacheFromRenderObject(renderer);
+    if (!cache->m_cache.contains(renderer))
+        return 0;
+
+    return cache->m_cache.get(renderer);
+}
+
+void SVGResourcesCache::clientLayoutChanged(RenderObject* object)
+{
+    SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(object);
+    if (!resources)
+        return;
+
+    // Invalidate the resources if either the RenderObject itself changed,
+    // or we have filter resources, which could depend on the layout of children.
+    if (object->selfNeedsLayout())
+        resources->removeClientFromCache(object);
+}
+
+static inline bool rendererCanHaveResources(RenderObject* renderer)
+{
+    ASSERT(renderer);
+    return renderer->node() && renderer->node()->isSVGElement() && !renderer->isSVGInlineText();
+}
+
+void SVGResourcesCache::clientStyleChanged(RenderObject* renderer, StyleDifference diff, const RenderStyle* newStyle)
+{
+    ASSERT(renderer);
+    if (diff == StyleDifferenceEqual || !renderer->parent())
+        return;
+
+    // In this case the proper SVGFE*Element will decide whether the modified CSS properties require a relayout or repaint.
+    if (renderer->isSVGResourceFilterPrimitive() && diff == StyleDifferenceRepaint)
+        return;
+
+    // Dynamic changes of CSS properties like 'clip-path' may require us to recompute the associated resources for a renderer.
+    // FIXME: Avoid passing in a useless StyleDifference, but instead compare oldStyle/newStyle to see which resources changed
+    // to be able to selectively rebuild individual resources, instead of all of them.
+    if (rendererCanHaveResources(renderer)) {
+        SVGResourcesCache* cache = resourcesCacheFromRenderObject(renderer);
+        cache->removeResourcesFromRenderObject(renderer);
+        cache->addResourcesFromRenderObject(renderer, newStyle);
+    }
+
+    RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer, false);
+
+    if (renderer->node() && !renderer->node()->isSVGElement())
+        renderer->node()->setNeedsStyleRecalc(SyntheticStyleChange);
+}
+
+void SVGResourcesCache::clientWasAddedToTree(RenderObject* renderer, const RenderStyle* newStyle)
+{
+    if (!renderer->node())
+        return;
+    RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer, false);
+
+    if (!rendererCanHaveResources(renderer))
+        return;
+    SVGResourcesCache* cache = resourcesCacheFromRenderObject(renderer);
+    cache->addResourcesFromRenderObject(renderer, newStyle);
+}
+
+void SVGResourcesCache::clientWillBeRemovedFromTree(RenderObject* renderer)
+{
+    if (!renderer->node())
+        return;
+    RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer, false);
+
+    if (!rendererCanHaveResources(renderer))
+        return;
+    SVGResourcesCache* cache = resourcesCacheFromRenderObject(renderer);
+    cache->removeResourcesFromRenderObject(renderer);
+}
+
+void SVGResourcesCache::clientDestroyed(RenderObject* renderer)
+{
+    ASSERT(renderer);
+
+    SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(renderer);
+    if (resources)
+        resources->removeClientFromCache(renderer);
+
+    SVGResourcesCache* cache = resourcesCacheFromRenderObject(renderer);
+    cache->removeResourcesFromRenderObject(renderer);
+}
+
+void SVGResourcesCache::resourceDestroyed(RenderSVGResourceContainer* resource)
+{
+    ASSERT(resource);
+    SVGResourcesCache* cache = resourcesCacheFromRenderObject(resource);
+
+    // The resource itself may have clients, that need to be notified.
+    cache->removeResourcesFromRenderObject(resource);
+
+    HashMap<const RenderObject*, SVGResources*>::iterator end = cache->m_cache.end();
+    for (HashMap<const RenderObject*, SVGResources*>::iterator it = cache->m_cache.begin(); it != end; ++it) {
+        it->value->resourceDestroyed(resource);
+
+        // Mark users of destroyed resources as pending resolution based on the id of the old resource.
+        Element* resourceElement = toElement(resource->node());
+        Element* clientElement = toElement(it->key->node());
+        SVGDocumentExtensions* extensions = clientElement->document()->accessSVGExtensions();
+
+        extensions->addPendingResource(resourceElement->fastGetAttribute(HTMLNames::idAttr), clientElement);
+    }
+}
+
+}
+
+#endif
diff --git a/Source/core/rendering/svg/SVGResourcesCache.h b/Source/core/rendering/svg/SVGResourcesCache.h
new file mode 100644
index 0000000..851ea9f
--- /dev/null
+++ b/Source/core/rendering/svg/SVGResourcesCache.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) Research In Motion Limited 2010. 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 SVGResourcesCache_h
+#define SVGResourcesCache_h
+
+#if ENABLE(SVG)
+#include "core/rendering/style/RenderStyleConstants.h"
+#include <wtf/HashMap.h>
+#include <wtf/Noncopyable.h>
+
+namespace WebCore {
+
+class RenderObject;
+class RenderStyle;
+class RenderSVGResourceContainer;
+class SVGResources;
+
+class SVGResourcesCache {
+    WTF_MAKE_NONCOPYABLE(SVGResourcesCache); WTF_MAKE_FAST_ALLOCATED;
+public:
+    SVGResourcesCache();
+    ~SVGResourcesCache();
+
+    static SVGResources* cachedResourcesForRenderObject(const RenderObject*);
+
+    // Called from all SVG renderers addChild() methods.
+    static void clientWasAddedToTree(RenderObject*, const RenderStyle* newStyle);
+
+    // Called from all SVG renderers removeChild() methods.
+    static void clientWillBeRemovedFromTree(RenderObject*);
+
+    // Called from all SVG renderers destroy() methods - except for RenderSVGResourceContainer.
+    static void clientDestroyed(RenderObject*);
+
+    // Called from all SVG renderers layout() methods.
+    static void clientLayoutChanged(RenderObject*);
+
+    // Called from all SVG renderers styleDidChange() methods.
+    static void clientStyleChanged(RenderObject*, StyleDifference, const RenderStyle* newStyle);
+
+    // Called from RenderSVGResourceContainer::willBeDestroyed().
+    static void resourceDestroyed(RenderSVGResourceContainer*);
+
+private:
+    void addResourcesFromRenderObject(RenderObject*, const RenderStyle*);
+    void removeResourcesFromRenderObject(RenderObject*);
+
+    HashMap<const RenderObject*, SVGResources*> m_cache;
+};
+
+}
+
+#endif
+#endif
diff --git a/Source/core/rendering/svg/SVGResourcesCycleSolver.cpp b/Source/core/rendering/svg/SVGResourcesCycleSolver.cpp
new file mode 100644
index 0000000..5e448b6
--- /dev/null
+++ b/Source/core/rendering/svg/SVGResourcesCycleSolver.cpp
@@ -0,0 +1,211 @@
+/*
+ * Copyright (C) Research In Motion Limited 2010. 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 "core/rendering/svg/SVGResourcesCycleSolver.h"
+
+// Set to a value > 0, to debug the resource cache.
+#define DEBUG_CYCLE_DETECTION 0
+
+#if ENABLE(SVG)
+#include "core/rendering/svg/RenderSVGResourceClipper.h"
+#include "core/rendering/svg/RenderSVGResourceFilter.h"
+#include "core/rendering/svg/RenderSVGResourceMarker.h"
+#include "core/rendering/svg/RenderSVGResourceMasker.h"
+#include "core/rendering/svg/SVGResources.h"
+#include "core/rendering/svg/SVGResourcesCache.h"
+#include "core/svg/SVGFilterElement.h"
+#include "core/svg/SVGGradientElement.h"
+#include "core/svg/SVGPatternElement.h"
+
+namespace WebCore {
+
+SVGResourcesCycleSolver::SVGResourcesCycleSolver(RenderObject* renderer, SVGResources* resources)
+    : m_renderer(renderer)
+    , m_resources(resources)
+{
+    ASSERT(m_renderer);
+    ASSERT(m_resources);
+}
+
+SVGResourcesCycleSolver::~SVGResourcesCycleSolver()
+{
+}
+
+bool SVGResourcesCycleSolver::resourceContainsCycles(RenderObject* renderer) const
+{
+    ASSERT(renderer);
+
+    // First operate on the resources of the given renderer.
+    // <marker id="a"> <path marker-start="url(#b)"/> ...
+    // <marker id="b" marker-start="url(#a)"/>
+    if (SVGResources* resources = SVGResourcesCache::cachedResourcesForRenderObject(renderer)) {
+        HashSet<RenderSVGResourceContainer*> resourceSet;
+        resources->buildSetOfResources(resourceSet);
+
+        // Walk all resources and check wheter they reference any resource contained in the resources set.
+        HashSet<RenderSVGResourceContainer*>::iterator end = resourceSet.end();
+        for (HashSet<RenderSVGResourceContainer*>::iterator it = resourceSet.begin(); it != end; ++it) {
+            if (m_allResources.contains(*it))
+                return true;
+        }
+    }
+
+    // Then operate on the child resources of the given renderer.
+    // <marker id="a"> <path marker-start="url(#b)"/> ...
+    // <marker id="b"> <path marker-start="url(#a)"/> ...
+    for (RenderObject* child = renderer->firstChild(); child; child = child->nextSibling()) {
+        SVGResources* childResources = SVGResourcesCache::cachedResourcesForRenderObject(child);
+        if (!childResources)
+            continue;
+        
+        // A child of the given 'resource' contains resources. 
+        HashSet<RenderSVGResourceContainer*> childSet;
+        childResources->buildSetOfResources(childSet);
+
+        // Walk all child resources and check wheter they reference any resource contained in the resources set.
+        HashSet<RenderSVGResourceContainer*>::iterator end = childSet.end();
+        for (HashSet<RenderSVGResourceContainer*>::iterator it = childSet.begin(); it != end; ++it) {
+            if (m_allResources.contains(*it))
+                return true;
+        }
+
+        // Walk children recursively, stop immediately if we found a cycle
+        if (resourceContainsCycles(child))
+            return true;
+    }
+
+    return false;
+}
+
+void SVGResourcesCycleSolver::resolveCycles()
+{
+    ASSERT(m_allResources.isEmpty());
+
+#if DEBUG_CYCLE_DETECTION > 0
+    fprintf(stderr, "\nBefore cycle detection:\n");
+    m_resources->dump(m_renderer);
+#endif
+
+    // Stash all resources into a HashSet for the ease of traversing.
+    HashSet<RenderSVGResourceContainer*> localResources;
+    m_resources->buildSetOfResources(localResources);
+    ASSERT(!localResources.isEmpty());
+
+    // Add all parent resource containers to the HashSet.
+    HashSet<RenderSVGResourceContainer*> parentResources;
+    RenderObject* parent = m_renderer->parent();
+    while (parent) {
+        if (parent->isSVGResourceContainer())
+            parentResources.add(parent->toRenderSVGResourceContainer());
+        parent = parent->parent();
+    }
+
+#if DEBUG_CYCLE_DETECTION > 0
+    fprintf(stderr, "\nDetecting wheter any resources references any of following objects:\n");
+    {
+        fprintf(stderr, "Local resources:\n");
+        HashSet<RenderSVGResourceContainer*>::iterator end = localResources.end();
+        for (HashSet<RenderSVGResourceContainer*>::iterator it = localResources.begin(); it != end; ++it)
+            fprintf(stderr, "|> %s: object=%p (node=%p)\n", (*it)->renderName(), *it, (*it)->node());
+
+        fprintf(stderr, "Parent resources:\n");
+        end = parentResources.end();
+        for (HashSet<RenderSVGResourceContainer*>::iterator it = parentResources.begin(); it != end; ++it)
+            fprintf(stderr, "|> %s: object=%p (node=%p)\n", (*it)->renderName(), *it, (*it)->node());
+    }
+#endif
+
+    // Build combined set of local and parent resources.
+    m_allResources = localResources;
+    HashSet<RenderSVGResourceContainer*>::iterator end = parentResources.end();
+    for (HashSet<RenderSVGResourceContainer*>::iterator it = parentResources.begin(); it != end; ++it)
+        m_allResources.add(*it);
+
+    // If we're a resource, add ourselves to the HashSet.
+    if (m_renderer->isSVGResourceContainer())
+        m_allResources.add(m_renderer->toRenderSVGResourceContainer());
+
+    ASSERT(!m_allResources.isEmpty());
+
+    // The job of this function is to determine wheter any of the 'resources' associated with the given 'renderer'
+    // references us (or wheter any of its kids references us) -> that's a cycle, we need to find and break it.
+    end = localResources.end();
+    for (HashSet<RenderSVGResourceContainer*>::iterator it = localResources.begin(); it != end; ++it) {
+        RenderSVGResourceContainer* resource = *it;
+        if (parentResources.contains(resource) || resourceContainsCycles(resource))
+            breakCycle(resource);
+    }
+
+#if DEBUG_CYCLE_DETECTION > 0
+    fprintf(stderr, "\nAfter cycle detection:\n");
+    m_resources->dump(m_renderer);
+#endif
+
+    m_allResources.clear();
+}
+
+void SVGResourcesCycleSolver::breakCycle(RenderSVGResourceContainer* resourceLeadingToCycle)
+{
+    ASSERT(resourceLeadingToCycle);
+    if (resourceLeadingToCycle == m_resources->linkedResource()) {
+        m_resources->resetLinkedResource();
+        return;
+    }
+
+    switch (resourceLeadingToCycle->resourceType()) {
+    case MaskerResourceType:
+        ASSERT(resourceLeadingToCycle == m_resources->masker());
+        m_resources->resetMasker();
+        break;
+    case MarkerResourceType:
+        ASSERT(resourceLeadingToCycle == m_resources->markerStart() || resourceLeadingToCycle == m_resources->markerMid() || resourceLeadingToCycle == m_resources->markerEnd());
+        if (m_resources->markerStart() == resourceLeadingToCycle)
+            m_resources->resetMarkerStart();
+        if (m_resources->markerMid() == resourceLeadingToCycle)
+            m_resources->resetMarkerMid();
+        if (m_resources->markerEnd() == resourceLeadingToCycle)
+            m_resources->resetMarkerEnd();
+        break;
+    case PatternResourceType:
+    case LinearGradientResourceType:
+    case RadialGradientResourceType:
+        ASSERT(resourceLeadingToCycle == m_resources->fill() || resourceLeadingToCycle == m_resources->stroke());
+        if (m_resources->fill() == resourceLeadingToCycle)
+            m_resources->resetFill();
+        if (m_resources->stroke() == resourceLeadingToCycle)
+            m_resources->resetStroke();
+        break;
+    case FilterResourceType:
+        ASSERT(resourceLeadingToCycle == m_resources->filter());
+        m_resources->resetFilter();
+        break;
+    case ClipperResourceType:
+        ASSERT(resourceLeadingToCycle == m_resources->clipper());
+        m_resources->resetClipper();
+        break;
+    case SolidColorResourceType:
+        ASSERT_NOT_REACHED();
+        break;
+    }
+}
+
+}
+
+#endif
diff --git a/Source/core/rendering/svg/SVGResourcesCycleSolver.h b/Source/core/rendering/svg/SVGResourcesCycleSolver.h
new file mode 100644
index 0000000..51e13cc
--- /dev/null
+++ b/Source/core/rendering/svg/SVGResourcesCycleSolver.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) Research In Motion Limited 2010. 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 SVGResourcesCycleSolver_h
+#define SVGResourcesCycleSolver_h
+
+#if ENABLE(SVG)
+#include <wtf/HashSet.h>
+#include <wtf/Noncopyable.h>
+
+namespace WebCore {
+
+class RenderObject;
+class RenderSVGResourceContainer;
+class SVGResources;
+
+class SVGResourcesCycleSolver {
+    WTF_MAKE_NONCOPYABLE(SVGResourcesCycleSolver);
+public:
+    SVGResourcesCycleSolver(RenderObject*, SVGResources*);
+    ~SVGResourcesCycleSolver();
+
+    void resolveCycles();
+
+private:
+    bool resourceContainsCycles(RenderObject*) const;
+    void breakCycle(RenderSVGResourceContainer*);
+
+    RenderObject* m_renderer;
+    SVGResources* m_resources;
+    HashSet<RenderSVGResourceContainer*> m_allResources; 
+};
+
+}
+
+#endif
+#endif
diff --git a/Source/core/rendering/svg/SVGRootInlineBox.cpp b/Source/core/rendering/svg/SVGRootInlineBox.cpp
new file mode 100644
index 0000000..ac2a44a
--- /dev/null
+++ b/Source/core/rendering/svg/SVGRootInlineBox.cpp
@@ -0,0 +1,311 @@
+/*
+ * Copyright (C) 2006 Oliver Hunt <ojh16@student.canterbury.ac.nz>
+ * Copyright (C) 2006 Apple Computer Inc.
+ * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) Research In Motion Limited 2010. All rights reserved.
+ * Copyright (C) 2011 Torch Mobile (Beijing) CO. Ltd. 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 "core/rendering/svg/SVGRootInlineBox.h"
+
+#if ENABLE(SVG)
+#include "SVGNames.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/rendering/svg/RenderSVGInlineText.h"
+#include "core/rendering/svg/RenderSVGText.h"
+#include "core/rendering/svg/SVGInlineFlowBox.h"
+#include "core/rendering/svg/SVGInlineTextBox.h"
+#include "core/rendering/svg/SVGRenderingContext.h"
+#include "core/svg/SVGTextPositioningElement.h"
+
+namespace WebCore {
+
+void SVGRootInlineBox::paint(PaintInfo& paintInfo, const LayoutPoint&, LayoutUnit, LayoutUnit)
+{
+    ASSERT(paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection);
+    ASSERT(!paintInfo.context->paintingDisabled());
+
+    RenderObject* boxRenderer = renderer();
+    ASSERT(boxRenderer);
+
+    bool isPrinting = renderer()->document()->printing();
+    bool hasSelection = !isPrinting && selectionState() != RenderObject::SelectionNone;
+
+    PaintInfo childPaintInfo(paintInfo);
+    if (hasSelection) {
+        for (InlineBox* child = firstChild(); child; child = child->nextOnLine()) {
+            if (child->isSVGInlineTextBox())
+                static_cast<SVGInlineTextBox*>(child)->paintSelectionBackground(childPaintInfo);
+            else if (child->isSVGInlineFlowBox())
+                static_cast<SVGInlineFlowBox*>(child)->paintSelectionBackground(childPaintInfo);
+        }
+    }
+
+    SVGRenderingContext renderingContext(boxRenderer, paintInfo, SVGRenderingContext::SaveGraphicsContext);
+    if (renderingContext.isRenderingPrepared()) {
+        for (InlineBox* child = firstChild(); child; child = child->nextOnLine()) {
+            if (child->isSVGInlineTextBox())
+                SVGInlineFlowBox::computeTextMatchMarkerRectForRenderer(toRenderSVGInlineText(static_cast<SVGInlineTextBox*>(child)->textRenderer()));
+
+            child->paint(paintInfo, LayoutPoint(), 0, 0);
+        }
+    }
+}
+
+void SVGRootInlineBox::computePerCharacterLayoutInformation()
+{
+    RenderSVGText* textRoot = toRenderSVGText(block());
+    ASSERT(textRoot);
+
+    Vector<SVGTextLayoutAttributes*>& layoutAttributes = textRoot->layoutAttributes();
+    if (layoutAttributes.isEmpty())
+        return;
+
+    if (textRoot->needsReordering())
+        reorderValueLists(layoutAttributes);
+
+    // Perform SVG text layout phase two (see SVGTextLayoutEngine for details).
+    SVGTextLayoutEngine characterLayout(layoutAttributes);
+    layoutCharactersInTextBoxes(this, characterLayout);
+
+    // Perform SVG text layout phase three (see SVGTextChunkBuilder for details).
+    characterLayout.finishLayout();
+
+    // Perform SVG text layout phase four
+    // Position & resize all SVGInlineText/FlowBoxes in the inline box tree, resize the root box as well as the RenderSVGText parent block.
+    FloatRect childRect;
+    layoutChildBoxes(this, &childRect);
+    layoutRootBox(childRect);
+}
+
+void SVGRootInlineBox::layoutCharactersInTextBoxes(InlineFlowBox* start, SVGTextLayoutEngine& characterLayout)
+{
+    for (InlineBox* child = start->firstChild(); child; child = child->nextOnLine()) {
+        if (child->isSVGInlineTextBox()) {
+            ASSERT(child->renderer());
+            ASSERT(child->renderer()->isSVGInlineText());
+
+            SVGInlineTextBox* textBox = static_cast<SVGInlineTextBox*>(child);
+            characterLayout.layoutInlineTextBox(textBox);
+        } else {
+            // Skip generated content.
+            Node* node = child->renderer()->node();
+            if (!node)
+                continue;
+
+            ASSERT_WITH_SECURITY_IMPLICATION(child->isInlineFlowBox());
+
+            SVGInlineFlowBox* flowBox = static_cast<SVGInlineFlowBox*>(child);
+            bool isTextPath = node->hasTagName(SVGNames::textPathTag);
+            if (isTextPath) {
+                // Build text chunks for all <textPath> children, using the line layout algorithm.
+                // This is needeed as text-anchor is just an additional startOffset for text paths.
+                SVGTextLayoutEngine lineLayout(characterLayout.layoutAttributes());
+                layoutCharactersInTextBoxes(flowBox, lineLayout);
+
+                characterLayout.beginTextPathLayout(child->renderer(), lineLayout);
+            }
+
+            layoutCharactersInTextBoxes(flowBox, characterLayout);
+
+            if (isTextPath)
+                characterLayout.endTextPathLayout();
+        }
+    }
+}
+
+void SVGRootInlineBox::layoutChildBoxes(InlineFlowBox* start, FloatRect* childRect)
+{
+    for (InlineBox* child = start->firstChild(); child; child = child->nextOnLine()) {
+        FloatRect boxRect;
+        if (child->isSVGInlineTextBox()) {
+            ASSERT(child->renderer());
+            ASSERT(child->renderer()->isSVGInlineText());
+
+            SVGInlineTextBox* textBox = static_cast<SVGInlineTextBox*>(child);
+            boxRect = textBox->calculateBoundaries();
+            textBox->setX(boxRect.x());
+            textBox->setY(boxRect.y());
+            textBox->setLogicalWidth(boxRect.width());
+            textBox->setLogicalHeight(boxRect.height());
+        } else {
+            // Skip generated content.
+            if (!child->renderer()->node())
+                continue;
+
+            ASSERT_WITH_SECURITY_IMPLICATION(child->isInlineFlowBox());
+
+            SVGInlineFlowBox* flowBox = static_cast<SVGInlineFlowBox*>(child);
+            layoutChildBoxes(flowBox);
+
+            boxRect = flowBox->calculateBoundaries();
+            flowBox->setX(boxRect.x());
+            flowBox->setY(boxRect.y());
+            flowBox->setLogicalWidth(boxRect.width());
+            flowBox->setLogicalHeight(boxRect.height());
+        }
+        if (childRect)
+            childRect->unite(boxRect);
+    }
+}
+
+void SVGRootInlineBox::layoutRootBox(const FloatRect& childRect)
+{
+    RenderBlock* parentBlock = block();
+    ASSERT(parentBlock);
+
+    // Finally, assign the root block position, now that all content is laid out.
+    LayoutRect boundingRect = enclosingLayoutRect(childRect);
+    parentBlock->setLocation(boundingRect.location());
+    parentBlock->setSize(boundingRect.size());
+
+    // Position all children relative to the parent block.
+    for (InlineBox* child = firstChild(); child; child = child->nextOnLine()) {
+        // Skip generated content.
+        if (!child->renderer()->node())
+            continue;
+        child->adjustPosition(-childRect.x(), -childRect.y());
+    }
+
+    // Position ourselves.
+    setX(0);
+    setY(0);
+    setLogicalWidth(childRect.width());
+    setLogicalHeight(childRect.height());
+    setLineTopBottomPositions(0, boundingRect.height(), 0, boundingRect.height());
+}
+
+InlineBox* SVGRootInlineBox::closestLeafChildForPosition(const LayoutPoint& point)
+{
+    InlineBox* firstLeaf = firstLeafChild();
+    InlineBox* lastLeaf = lastLeafChild();
+    if (firstLeaf == lastLeaf)
+        return firstLeaf;
+
+    // FIXME: Check for vertical text!
+    InlineBox* closestLeaf = 0;
+    for (InlineBox* leaf = firstLeaf; leaf; leaf = leaf->nextLeafChild()) {
+        if (!leaf->isSVGInlineTextBox())
+            continue;
+        if (point.y() < leaf->y())
+            continue;
+        if (point.y() > leaf->y() + leaf->virtualLogicalHeight())
+            continue;
+
+        closestLeaf = leaf;
+        if (point.x() < leaf->left() + leaf->logicalWidth())
+            return leaf;
+    }
+
+    return closestLeaf ? closestLeaf : lastLeaf;
+}
+
+static inline void swapItemsInLayoutAttributes(SVGTextLayoutAttributes* firstAttributes, SVGTextLayoutAttributes* lastAttributes, unsigned firstPosition, unsigned lastPosition)
+{
+    SVGCharacterDataMap::iterator itFirst = firstAttributes->characterDataMap().find(firstPosition + 1);
+    SVGCharacterDataMap::iterator itLast = lastAttributes->characterDataMap().find(lastPosition + 1);
+    bool firstPresent = itFirst != firstAttributes->characterDataMap().end();
+    bool lastPresent = itLast != lastAttributes->characterDataMap().end();
+    if (!firstPresent && !lastPresent)
+        return;
+
+    if (firstPresent && lastPresent) {
+        std::swap(itFirst->value, itLast->value);
+        return;
+    }
+
+    if (firstPresent && !lastPresent) {
+        lastAttributes->characterDataMap().set(lastPosition + 1, itFirst->value);
+        return;
+    }
+
+    // !firstPresent && lastPresent
+    firstAttributes->characterDataMap().set(firstPosition + 1, itLast->value);
+}
+
+static inline void findFirstAndLastAttributesInVector(Vector<SVGTextLayoutAttributes*>& attributes, RenderSVGInlineText* firstContext, RenderSVGInlineText* lastContext,
+                                                      SVGTextLayoutAttributes*& first, SVGTextLayoutAttributes*& last)
+{
+    first = 0;
+    last = 0;
+
+    unsigned attributesSize = attributes.size();
+    for (unsigned i = 0; i < attributesSize; ++i) {
+        SVGTextLayoutAttributes* current = attributes[i];
+        if (!first && firstContext == current->context())
+            first = current;
+        if (!last && lastContext == current->context())
+            last = current;
+        if (first && last)
+            break;
+    }
+
+    ASSERT(first);
+    ASSERT(last);
+}
+
+static inline void reverseInlineBoxRangeAndValueListsIfNeeded(void* userData, Vector<InlineBox*>::iterator first, Vector<InlineBox*>::iterator last)
+{
+    ASSERT(userData);
+    Vector<SVGTextLayoutAttributes*>& attributes = *reinterpret_cast<Vector<SVGTextLayoutAttributes*>*>(userData);
+
+    // This is a copy of std::reverse(first, last). It additionally assures that the metrics map within the renderers belonging to the InlineBoxes are reordered as well.
+    while (true)  {
+        if (first == last || first == --last)
+            return;
+
+        if (!(*last)->isSVGInlineTextBox() || !(*first)->isSVGInlineTextBox()) {
+            InlineBox* temp = *first;
+            *first = *last;
+            *last = temp;
+            ++first;
+            continue;
+        }
+
+        SVGInlineTextBox* firstTextBox = static_cast<SVGInlineTextBox*>(*first);
+        SVGInlineTextBox* lastTextBox = static_cast<SVGInlineTextBox*>(*last);
+
+        // Reordering is only necessary for BiDi text that is _absolutely_ positioned.
+        if (firstTextBox->len() == 1 && firstTextBox->len() == lastTextBox->len()) {
+            RenderSVGInlineText* firstContext = toRenderSVGInlineText(firstTextBox->textRenderer());
+            RenderSVGInlineText* lastContext = toRenderSVGInlineText(lastTextBox->textRenderer());
+
+            SVGTextLayoutAttributes* firstAttributes = 0;
+            SVGTextLayoutAttributes* lastAttributes = 0;
+            findFirstAndLastAttributesInVector(attributes, firstContext, lastContext, firstAttributes, lastAttributes);
+            swapItemsInLayoutAttributes(firstAttributes, lastAttributes, firstTextBox->start(), lastTextBox->start());
+        }
+
+        InlineBox* temp = *first;
+        *first = *last;
+        *last = temp;
+
+        ++first;
+    }
+}
+
+void SVGRootInlineBox::reorderValueLists(Vector<SVGTextLayoutAttributes*>& attributes)
+{
+    Vector<InlineBox*> leafBoxesInLogicalOrder;
+    collectLeafBoxesInLogicalOrder(leafBoxesInLogicalOrder, reverseInlineBoxRangeAndValueListsIfNeeded, &attributes);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
diff --git a/Source/core/rendering/svg/SVGRootInlineBox.h b/Source/core/rendering/svg/SVGRootInlineBox.h
new file mode 100644
index 0000000..068033a
--- /dev/null
+++ b/Source/core/rendering/svg/SVGRootInlineBox.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2006 Oliver Hunt <ojh16@student.canterbury.ac.nz>
+ * Copyright (C) 2006 Apple Computer Inc.
+ * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) Research In Motion Limited 2010. 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 SVGRootInlineBox_h
+#define SVGRootInlineBox_h
+
+#if ENABLE(SVG)
+#include "core/rendering/RootInlineBox.h"
+#include "core/rendering/svg/SVGRenderSupport.h"
+#include "core/rendering/svg/SVGTextLayoutEngine.h"
+
+namespace WebCore {
+
+class SVGInlineTextBox;
+
+class SVGRootInlineBox FINAL : public RootInlineBox {
+public:
+    SVGRootInlineBox(RenderBlock* block)
+        : RootInlineBox(block)
+        , m_logicalHeight(0)
+    {
+    }
+
+    virtual bool isSVGRootInlineBox() const { return true; }
+
+    virtual float virtualLogicalHeight() const { return m_logicalHeight; }
+    void setLogicalHeight(float height) { m_logicalHeight = height; }
+
+    virtual void paint(PaintInfo&, const LayoutPoint&, LayoutUnit lineTop, LayoutUnit lineBottom);
+
+    void computePerCharacterLayoutInformation();
+
+    virtual FloatRect objectBoundingBox() const { return FloatRect(); }
+    virtual FloatRect repaintRectInLocalCoordinates() const { return FloatRect(); }
+
+    InlineBox* closestLeafChildForPosition(const LayoutPoint&);
+
+private:
+    void reorderValueLists(Vector<SVGTextLayoutAttributes*>&);
+    void layoutCharactersInTextBoxes(InlineFlowBox*, SVGTextLayoutEngine&);
+    void layoutChildBoxes(InlineFlowBox*, FloatRect* = 0);
+    void layoutRootBox(const FloatRect&);
+
+private:
+    float m_logicalHeight;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
+
+#endif // SVGRootInlineBox_h
diff --git a/Source/core/rendering/svg/SVGSubpathData.h b/Source/core/rendering/svg/SVGSubpathData.h
new file mode 100644
index 0000000..deb9264
--- /dev/null
+++ b/Source/core/rendering/svg/SVGSubpathData.h
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2012 Google, 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 SVGSubpathData_h
+#define SVGSubpathData_h
+
+#if ENABLE(SVG)
+#include "core/platform/graphics/Path.h"
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class SVGSubpathData {
+public:
+    SVGSubpathData(Vector<FloatPoint>& zeroLengthSubpathLocations)
+        : m_zeroLengthSubpathLocations(zeroLengthSubpathLocations)
+        , m_haveSeenMoveOnly(true)
+        , m_pathIsZeroLength(true)
+    {
+        m_lastPoint.set(0, 0);
+        m_movePoint.set(0, 0);
+    }
+
+    static void updateFromPathElement(void* info, const PathElement* element)
+    {
+        SVGSubpathData* subpathFinder = static_cast<SVGSubpathData*>(info);
+        switch (element->type) {
+        case PathElementMoveToPoint:
+            if (subpathFinder->m_pathIsZeroLength && !subpathFinder->m_haveSeenMoveOnly)
+                subpathFinder->m_zeroLengthSubpathLocations.append(subpathFinder->m_lastPoint);
+            subpathFinder->m_lastPoint = subpathFinder->m_movePoint = element->points[0];
+            subpathFinder->m_haveSeenMoveOnly = true;
+            subpathFinder->m_pathIsZeroLength = true;
+            break;
+        case PathElementAddLineToPoint:
+            if (subpathFinder->m_lastPoint != element->points[0]) {
+                subpathFinder->m_pathIsZeroLength = false;
+                subpathFinder->m_lastPoint = element->points[0];
+            }
+            subpathFinder->m_haveSeenMoveOnly = false;
+            break;
+        case PathElementAddQuadCurveToPoint:
+            if (subpathFinder->m_lastPoint != element->points[0] || element->points[0] != element->points[1]) {
+                subpathFinder->m_pathIsZeroLength = false;
+                subpathFinder->m_lastPoint = element->points[1];
+            }
+            subpathFinder->m_haveSeenMoveOnly = false;
+            break;
+        case PathElementAddCurveToPoint:
+            if (subpathFinder->m_lastPoint != element->points[0] || element->points[0] != element->points[1] || element->points[1] != element->points[2]) {
+                subpathFinder->m_pathIsZeroLength = false;
+                subpathFinder->m_lastPoint = element->points[2];
+            }
+            subpathFinder->m_haveSeenMoveOnly = false;
+            break;
+        case PathElementCloseSubpath:
+            if (subpathFinder->m_pathIsZeroLength)
+                subpathFinder->m_zeroLengthSubpathLocations.append(subpathFinder->m_lastPoint);
+            subpathFinder->m_haveSeenMoveOnly = true; // This is an implicit move for the next element
+            subpathFinder->m_pathIsZeroLength = true; // A new sub-path also starts here
+            subpathFinder->m_lastPoint = subpathFinder->m_movePoint;
+            break;
+        }
+    }
+
+    void pathIsDone()
+    {
+        if (m_pathIsZeroLength && !m_haveSeenMoveOnly)
+            m_zeroLengthSubpathLocations.append(m_lastPoint);
+    }
+
+private:
+    Vector<FloatPoint>& m_zeroLengthSubpathLocations;
+    FloatPoint m_lastPoint;
+    FloatPoint m_movePoint;
+    bool m_haveSeenMoveOnly;
+    bool m_pathIsZeroLength;
+};
+
+}
+
+#endif // ENABLE(SVG)
+#endif // SVGSubpathData_h
+
diff --git a/Source/core/rendering/svg/SVGTextChunk.cpp b/Source/core/rendering/svg/SVGTextChunk.cpp
new file mode 100644
index 0000000..450b2df
--- /dev/null
+++ b/Source/core/rendering/svg/SVGTextChunk.cpp
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) Research In Motion Limited 2010. 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"
+
+#if ENABLE(SVG)
+#include "core/rendering/svg/SVGTextChunk.h"
+
+#include "core/rendering/svg/SVGInlineTextBox.h"
+#include "core/rendering/svg/SVGTextFragment.h"
+
+namespace WebCore {
+
+SVGTextChunk::SVGTextChunk(unsigned chunkStyle, float desiredTextLength)
+    : m_chunkStyle(chunkStyle)
+    , m_desiredTextLength(desiredTextLength)
+{
+}
+
+void SVGTextChunk::calculateLength(float& length, unsigned& characters) const
+{
+    SVGTextFragment* lastFragment = 0;
+
+    unsigned boxCount = m_boxes.size();
+    for (unsigned boxPosition = 0; boxPosition < boxCount; ++boxPosition) {
+        SVGInlineTextBox* textBox = m_boxes.at(boxPosition);
+        Vector<SVGTextFragment>& fragments = textBox->textFragments();
+
+        unsigned size = fragments.size();
+        if (!size)
+            continue;
+
+        for (unsigned i = 0; i < size; ++i) {
+            SVGTextFragment& fragment = fragments.at(i);
+            characters += fragment.length;
+
+            if (m_chunkStyle & VerticalText)
+                length += fragment.height;
+            else
+                length += fragment.width;
+
+            if (!lastFragment) {
+                lastFragment = &fragment;
+                continue;
+            }
+
+            // Resepect gap between chunks.
+            if (m_chunkStyle & VerticalText)
+                 length += fragment.y - (lastFragment->y + lastFragment->height);
+            else
+                 length += fragment.x - (lastFragment->x + lastFragment->width);
+
+            lastFragment = &fragment;
+        }
+    }
+}
+
+float SVGTextChunk::calculateTextAnchorShift(float length) const
+{
+    if (m_chunkStyle & MiddleAnchor)
+        return -length / 2;
+    if (m_chunkStyle & EndAnchor)
+        return m_chunkStyle & RightToLeftText ? 0 : -length;
+    return m_chunkStyle & RightToLeftText ? -length : 0;
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
diff --git a/Source/core/rendering/svg/SVGTextChunk.h b/Source/core/rendering/svg/SVGTextChunk.h
new file mode 100644
index 0000000..b96c3d9
--- /dev/null
+++ b/Source/core/rendering/svg/SVGTextChunk.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) Research In Motion Limited 2010. 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 SVGTextChunk_h
+#define SVGTextChunk_h
+
+#if ENABLE(SVG)
+#include "core/rendering/style/SVGRenderStyleDefs.h"
+#include "core/svg/SVGTextContentElement.h"
+
+namespace WebCore {
+
+class SVGInlineTextBox;
+
+// A SVGTextChunk describes a range of SVGTextFragments, see the SVG spec definition of a "text chunk".
+class SVGTextChunk {
+public:
+    enum ChunkStyle {
+        DefaultStyle = 1 << 0,
+        MiddleAnchor = 1 << 1,
+        EndAnchor = 1 << 2,
+        RightToLeftText = 1 << 3,
+        VerticalText = 1 << 4,
+        LengthAdjustSpacing = 1 << 5,
+        LengthAdjustSpacingAndGlyphs = 1 << 6
+    };
+
+    SVGTextChunk(unsigned chunkStyle, float desiredTextLength);
+
+    void calculateLength(float& length, unsigned& characters) const;
+    float calculateTextAnchorShift(float length) const;
+
+    bool isVerticalText() const { return m_chunkStyle & VerticalText; }
+    float desiredTextLength() const { return m_desiredTextLength; }
+
+    Vector<SVGInlineTextBox*>& boxes() { return m_boxes; }
+    const Vector<SVGInlineTextBox*>& boxes() const { return m_boxes; }
+
+    bool hasDesiredTextLength() const { return m_desiredTextLength > 0 && ((m_chunkStyle & LengthAdjustSpacing) || (m_chunkStyle & LengthAdjustSpacingAndGlyphs)); }
+    bool hasTextAnchor() const {  return m_chunkStyle & RightToLeftText ? !(m_chunkStyle & EndAnchor) : (m_chunkStyle & MiddleAnchor) || (m_chunkStyle & EndAnchor); }
+    bool hasLengthAdjustSpacing() const { return m_chunkStyle & LengthAdjustSpacing; }
+    bool hasLengthAdjustSpacingAndGlyphs() const { return m_chunkStyle & LengthAdjustSpacingAndGlyphs; }
+
+private:
+    // Contains all SVGInlineTextBoxes this chunk spans.
+    Vector<SVGInlineTextBox*> m_boxes;
+
+    unsigned m_chunkStyle;
+    float m_desiredTextLength;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
+#endif
diff --git a/Source/core/rendering/svg/SVGTextChunkBuilder.cpp b/Source/core/rendering/svg/SVGTextChunkBuilder.cpp
new file mode 100644
index 0000000..7035017
--- /dev/null
+++ b/Source/core/rendering/svg/SVGTextChunkBuilder.cpp
@@ -0,0 +1,266 @@
+/*
+ * Copyright (C) Research In Motion Limited 2010. 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"
+
+#if ENABLE(SVG)
+#include "core/rendering/svg/SVGTextChunkBuilder.h"
+
+#include "core/rendering/svg/RenderSVGInlineText.h"
+#include "core/rendering/svg/SVGInlineTextBox.h"
+#include "core/svg/SVGElement.h"
+#include "core/svg/SVGLengthContext.h"
+
+namespace WebCore {
+
+SVGTextChunkBuilder::SVGTextChunkBuilder()
+{
+}
+
+void SVGTextChunkBuilder::transformationForTextBox(SVGInlineTextBox* textBox, AffineTransform& transform) const
+{
+    DEFINE_STATIC_LOCAL(const AffineTransform, s_identityTransform, ());
+    if (!m_textBoxTransformations.contains(textBox)) {
+        transform = s_identityTransform;
+        return;
+    }
+
+    transform = m_textBoxTransformations.get(textBox);
+}
+
+void SVGTextChunkBuilder::buildTextChunks(Vector<SVGInlineTextBox*>& lineLayoutBoxes)
+{
+    if (lineLayoutBoxes.isEmpty())
+        return;
+
+    bool foundStart = false;
+    unsigned lastChunkStartPosition = 0;
+    unsigned boxPosition = 0;
+    unsigned boxCount = lineLayoutBoxes.size();
+    for (; boxPosition < boxCount; ++boxPosition) {
+        SVGInlineTextBox* textBox = lineLayoutBoxes[boxPosition];
+        if (!textBox->startsNewTextChunk())
+            continue;
+
+        if (!foundStart) {
+            lastChunkStartPosition = boxPosition;
+            foundStart = true;
+        } else {
+            ASSERT(boxPosition > lastChunkStartPosition);
+            addTextChunk(lineLayoutBoxes, lastChunkStartPosition, boxPosition - lastChunkStartPosition);
+            lastChunkStartPosition = boxPosition;
+        }
+    }
+
+    if (!foundStart)
+        return;
+
+    if (boxPosition - lastChunkStartPosition > 0)
+        addTextChunk(lineLayoutBoxes, lastChunkStartPosition, boxPosition - lastChunkStartPosition);
+}
+
+void SVGTextChunkBuilder::layoutTextChunks(Vector<SVGInlineTextBox*>& lineLayoutBoxes)
+{
+    buildTextChunks(lineLayoutBoxes);
+    if (m_textChunks.isEmpty())
+        return;
+
+    unsigned chunkCount = m_textChunks.size();
+    for (unsigned i = 0; i < chunkCount; ++i)
+        processTextChunk(m_textChunks[i]);
+
+    m_textChunks.clear();
+}
+
+void SVGTextChunkBuilder::addTextChunk(Vector<SVGInlineTextBox*>& lineLayoutBoxes, unsigned boxStart, unsigned boxCount)
+{
+    SVGInlineTextBox* textBox = lineLayoutBoxes[boxStart];
+    ASSERT(textBox);
+
+    RenderSVGInlineText* textRenderer = toRenderSVGInlineText(textBox->textRenderer());
+    ASSERT(textRenderer);
+
+    const RenderStyle* style = textRenderer->style();
+    ASSERT(style);
+
+    const SVGRenderStyle* svgStyle = style->svgStyle();
+    ASSERT(svgStyle);
+
+    // Build chunk style flags.
+    unsigned chunkStyle = SVGTextChunk::DefaultStyle;
+
+    // Handle 'direction' property.
+    if (!style->isLeftToRightDirection())
+        chunkStyle |= SVGTextChunk::RightToLeftText;
+
+    // Handle 'writing-mode' property.
+    if (svgStyle->isVerticalWritingMode())
+        chunkStyle |= SVGTextChunk::VerticalText;
+
+    // Handle 'text-anchor' property.
+    switch (svgStyle->textAnchor()) {
+    case TA_START:
+        break;
+    case TA_MIDDLE:
+        chunkStyle |= SVGTextChunk::MiddleAnchor;
+        break;
+    case TA_END:
+        chunkStyle |= SVGTextChunk::EndAnchor;
+        break;
+    };
+
+    // Handle 'lengthAdjust' property.
+    float desiredTextLength = 0;
+    if (SVGTextContentElement* textContentElement = SVGTextContentElement::elementFromRenderer(textRenderer->parent())) {
+        SVGLengthContext lengthContext(textContentElement);
+        desiredTextLength = textContentElement->specifiedTextLength().value(lengthContext);
+
+        switch (textContentElement->lengthAdjust()) {
+        case SVGLengthAdjustUnknown:
+            break;
+        case SVGLengthAdjustSpacing:
+            chunkStyle |= SVGTextChunk::LengthAdjustSpacing;
+            break;
+        case SVGLengthAdjustSpacingAndGlyphs:
+            chunkStyle |= SVGTextChunk::LengthAdjustSpacingAndGlyphs;
+            break;
+        };
+    }
+
+    SVGTextChunk chunk(chunkStyle, desiredTextLength);
+
+    Vector<SVGInlineTextBox*>& boxes = chunk.boxes();
+    for (unsigned i = boxStart; i < boxStart + boxCount; ++i)
+        boxes.append(lineLayoutBoxes[i]);
+
+    m_textChunks.append(chunk);
+}
+
+void SVGTextChunkBuilder::processTextChunk(const SVGTextChunk& chunk)
+{
+    bool processTextLength = chunk.hasDesiredTextLength();
+    bool processTextAnchor = chunk.hasTextAnchor();
+    if (!processTextAnchor && !processTextLength)
+        return;
+
+    const Vector<SVGInlineTextBox*>& boxes = chunk.boxes();
+    unsigned boxCount = boxes.size();
+    if (!boxCount)
+        return;
+
+    // Calculate absolute length of whole text chunk (starting from text box 'start', spanning 'length' text boxes).
+    float chunkLength = 0;
+    unsigned chunkCharacters = 0;
+    chunk.calculateLength(chunkLength, chunkCharacters);
+
+    bool isVerticalText = chunk.isVerticalText();
+    if (processTextLength) {
+        if (chunk.hasLengthAdjustSpacing()) {
+            float textLengthShift = (chunk.desiredTextLength() - chunkLength) / chunkCharacters;
+            unsigned atCharacter = 0;
+            for (unsigned boxPosition = 0; boxPosition < boxCount; ++boxPosition) {
+                Vector<SVGTextFragment>& fragments = boxes[boxPosition]->textFragments();
+                if (fragments.isEmpty())
+                    continue;
+                processTextLengthSpacingCorrection(isVerticalText, textLengthShift, fragments, atCharacter);
+            }
+        } else {
+            ASSERT(chunk.hasLengthAdjustSpacingAndGlyphs());
+            float textLengthScale = chunk.desiredTextLength() / chunkLength;
+            AffineTransform spacingAndGlyphsTransform;
+
+            bool foundFirstFragment = false;
+            for (unsigned boxPosition = 0; boxPosition < boxCount; ++boxPosition) {
+                SVGInlineTextBox* textBox = boxes[boxPosition];
+                Vector<SVGTextFragment>& fragments = textBox->textFragments();
+                if (fragments.isEmpty())
+                    continue;
+
+                if (!foundFirstFragment) {
+                    foundFirstFragment = true;
+                    buildSpacingAndGlyphsTransform(isVerticalText, textLengthScale, fragments.first(), spacingAndGlyphsTransform);
+                }
+
+                m_textBoxTransformations.set(textBox, spacingAndGlyphsTransform);
+            }
+        }
+    }
+
+    if (!processTextAnchor)
+        return;
+
+    // If we previously applied a lengthAdjust="spacing" correction, we have to recalculate the chunk length, to be able to apply the text-anchor shift.
+    if (processTextLength && chunk.hasLengthAdjustSpacing()) {
+        chunkLength = 0;
+        chunkCharacters = 0;
+        chunk.calculateLength(chunkLength, chunkCharacters);
+    }
+
+    float textAnchorShift = chunk.calculateTextAnchorShift(chunkLength);
+    for (unsigned boxPosition = 0; boxPosition < boxCount; ++boxPosition) {
+        Vector<SVGTextFragment>& fragments = boxes[boxPosition]->textFragments();
+        if (fragments.isEmpty())
+            continue;
+        processTextAnchorCorrection(isVerticalText, textAnchorShift, fragments);
+    }
+}
+
+void SVGTextChunkBuilder::processTextLengthSpacingCorrection(bool isVerticalText, float textLengthShift, Vector<SVGTextFragment>& fragments, unsigned& atCharacter)
+{
+    unsigned fragmentCount = fragments.size();
+    for (unsigned i = 0; i < fragmentCount; ++i) {
+        SVGTextFragment& fragment = fragments[i];
+
+        if (isVerticalText)
+            fragment.y += textLengthShift * atCharacter;
+        else
+            fragment.x += textLengthShift * atCharacter;
+
+        atCharacter += fragment.length;
+    }
+}
+
+void SVGTextChunkBuilder::processTextAnchorCorrection(bool isVerticalText, float textAnchorShift, Vector<SVGTextFragment>& fragments)
+{
+    unsigned fragmentCount = fragments.size();
+    for (unsigned i = 0; i < fragmentCount; ++i) {
+        SVGTextFragment& fragment = fragments[i];
+
+        if (isVerticalText)
+            fragment.y += textAnchorShift;
+        else
+            fragment.x += textAnchorShift;
+    }
+}
+
+void SVGTextChunkBuilder::buildSpacingAndGlyphsTransform(bool isVerticalText, float scale, const SVGTextFragment& fragment, AffineTransform& spacingAndGlyphsTransform)
+{
+    spacingAndGlyphsTransform.translate(fragment.x, fragment.y);
+
+    if (isVerticalText)
+        spacingAndGlyphsTransform.scaleNonUniform(1, scale);
+    else
+        spacingAndGlyphsTransform.scaleNonUniform(scale, 1);
+
+    spacingAndGlyphsTransform.translate(-fragment.x, -fragment.y);
+}
+
+}
+
+#endif // ENABLE(SVG)
diff --git a/Source/core/rendering/svg/SVGTextChunkBuilder.h b/Source/core/rendering/svg/SVGTextChunkBuilder.h
new file mode 100644
index 0000000..7352b7c
--- /dev/null
+++ b/Source/core/rendering/svg/SVGTextChunkBuilder.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) Research In Motion Limited 2010. 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 SVGTextChunkBuilder_h
+#define SVGTextChunkBuilder_h
+
+#if ENABLE(SVG)
+#include "core/rendering/svg/SVGTextChunk.h"
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class SVGInlineTextBox;
+struct SVGTextFragment;
+
+// SVGTextChunkBuilder performs the third layout phase for SVG text.
+//
+// Phase one built the layout information from the SVG DOM stored in the RenderSVGInlineText objects (SVGTextLayoutAttributes).
+// Phase two performed the actual per-character layout, computing the final positions for each character, stored in the SVGInlineTextBox objects (SVGTextFragment).
+// Phase three performs all modifications that have to be applied to each individual text chunk (text-anchor & textLength).
+
+class SVGTextChunkBuilder {
+    WTF_MAKE_NONCOPYABLE(SVGTextChunkBuilder);
+public:
+    SVGTextChunkBuilder();
+
+    const Vector<SVGTextChunk>& textChunks() const { return m_textChunks; }
+    void transformationForTextBox(SVGInlineTextBox*, AffineTransform&) const;
+
+    void buildTextChunks(Vector<SVGInlineTextBox*>& lineLayoutBoxes);
+    void layoutTextChunks(Vector<SVGInlineTextBox*>& lineLayoutBoxes);
+
+private:
+    void addTextChunk(Vector<SVGInlineTextBox*>& lineLayoutBoxes, unsigned boxPosition, unsigned boxCount);
+    void processTextChunk(const SVGTextChunk&);
+
+    void processTextLengthSpacingCorrection(bool isVerticalText, float textLengthShift, Vector<SVGTextFragment>&, unsigned& atCharacter);
+    void processTextAnchorCorrection(bool isVerticalText, float textAnchorShift, Vector<SVGTextFragment>&);
+    void buildSpacingAndGlyphsTransform(bool isVerticalText, float scale, const SVGTextFragment&, AffineTransform&);
+
+private:
+    Vector<SVGTextChunk> m_textChunks;
+    HashMap<SVGInlineTextBox*, AffineTransform> m_textBoxTransformations;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
+#endif
diff --git a/Source/core/rendering/svg/SVGTextFragment.h b/Source/core/rendering/svg/SVGTextFragment.h
new file mode 100644
index 0000000..098da92
--- /dev/null
+++ b/Source/core/rendering/svg/SVGTextFragment.h
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) Research In Motion Limited 2010. 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 SVGTextFragment_h
+#define SVGTextFragment_h
+
+#if ENABLE(SVG)
+#include "core/platform/graphics/transforms/AffineTransform.h"
+
+namespace WebCore {
+
+// A SVGTextFragment describes a text fragment of a RenderSVGInlineText which can be rendered at once.
+struct SVGTextFragment {
+    SVGTextFragment()
+        : characterOffset(0)
+        , metricsListOffset(0)
+        , length(0)
+        , isTextOnPath(false)
+        , x(0)
+        , y(0)
+        , width(0)
+        , height(0)
+    {
+    }
+
+    enum TransformType {
+        TransformRespectingTextLength,
+        TransformIgnoringTextLength
+    };
+
+    void buildFragmentTransform(AffineTransform& result, TransformType type = TransformRespectingTextLength) const
+    {
+        if (type == TransformIgnoringTextLength) {
+            result = transform;
+            transformAroundOrigin(result);
+            return;
+        }
+
+        if (isTextOnPath)
+            buildTransformForTextOnPath(result);
+        else
+            buildTransformForTextOnLine(result);
+    }
+
+    // The first rendered character starts at RenderSVGInlineText::characters() + characterOffset.
+    unsigned characterOffset;
+    unsigned metricsListOffset;
+    unsigned length : 31;
+    bool isTextOnPath : 1;
+
+    float x;
+    float y;
+    float width;
+    float height;
+
+    // Includes rotation/glyph-orientation-(horizontal|vertical) transforms, as well as orientation related shifts
+    // (see SVGTextLayoutEngine, which builds this transformation).
+    AffineTransform transform;
+
+    // Contains lengthAdjust related transformations, which are not allowd to influence the SVGTextQuery code.
+    AffineTransform lengthAdjustTransform;
+
+private:
+    void transformAroundOrigin(AffineTransform& result) const
+    {
+        // Returns (translate(x, y) * result) * translate(-x, -y).
+        result.setE(result.e() + x);
+        result.setF(result.f() + y);
+        result.translate(-x, -y);
+    }
+
+    void buildTransformForTextOnPath(AffineTransform& result) const
+    {
+        // For text-on-path layout, multiply the transform with the lengthAdjustTransform before orienting the resulting transform.
+        result = lengthAdjustTransform.isIdentity() ? transform : transform * lengthAdjustTransform;
+        if (!result.isIdentity())
+            transformAroundOrigin(result);
+    }
+
+    void buildTransformForTextOnLine(AffineTransform& result) const
+    {
+        // For text-on-line layout, orient the transform first, then multiply the lengthAdjustTransform with the oriented transform.
+        if (transform.isIdentity()) {
+            result = lengthAdjustTransform;
+            return;
+        }
+
+        result = transform;
+        transformAroundOrigin(result);
+
+        if (!lengthAdjustTransform.isIdentity())
+            result = lengthAdjustTransform * result;
+    }
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
+#endif
diff --git a/Source/core/rendering/svg/SVGTextLayoutAttributes.cpp b/Source/core/rendering/svg/SVGTextLayoutAttributes.cpp
new file mode 100644
index 0000000..c57d1d4
--- /dev/null
+++ b/Source/core/rendering/svg/SVGTextLayoutAttributes.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) Research In Motion Limited 2010-11. 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"
+
+#if ENABLE(SVG)
+#include "core/rendering/svg/SVGTextLayoutAttributes.h"
+
+#include <stdio.h>
+#include <wtf/text/CString.h>
+
+namespace WebCore {
+
+SVGTextLayoutAttributes::SVGTextLayoutAttributes(RenderSVGInlineText* context)
+    : m_context(context)
+{
+}
+
+void SVGTextLayoutAttributes::clear()
+{
+    m_characterDataMap.clear();
+    m_textMetricsValues.clear();
+}
+
+float SVGTextLayoutAttributes::emptyValue()
+{
+    static float s_emptyValue = std::numeric_limits<float>::max() - 1;
+    return s_emptyValue;
+}
+
+static inline void dumpSVGCharacterDataMapValue(const char* identifier, float value, bool appendSpace = true)
+{
+    if (value == SVGTextLayoutAttributes::emptyValue()) {
+        fprintf(stderr, "%s=x", identifier);
+        if (appendSpace)
+            fprintf(stderr, " ");
+        return;
+    }
+    fprintf(stderr, "%s=%lf", identifier, value);
+    if (appendSpace)
+        fprintf(stderr, " ");
+}
+
+void SVGTextLayoutAttributes::dump() const
+{
+    fprintf(stderr, "context: %p\n", m_context);
+    const SVGCharacterDataMap::const_iterator end = m_characterDataMap.end();
+    for (SVGCharacterDataMap::const_iterator it = m_characterDataMap.begin(); it != end; ++it) {
+        const SVGCharacterData& data = it->value;
+        fprintf(stderr, " ---> pos=%i, data={", it->key);
+        dumpSVGCharacterDataMapValue("x", data.x);
+        dumpSVGCharacterDataMapValue("y", data.y);
+        dumpSVGCharacterDataMapValue("dx", data.dx);
+        dumpSVGCharacterDataMapValue("dy", data.dy);
+        dumpSVGCharacterDataMapValue("rotate", data.rotate, false);
+        fprintf(stderr, "}\n");
+    }
+}
+
+}
+
+#endif // ENABLE(SVG)
diff --git a/Source/core/rendering/svg/SVGTextLayoutAttributes.h b/Source/core/rendering/svg/SVGTextLayoutAttributes.h
new file mode 100644
index 0000000..d444a7f
--- /dev/null
+++ b/Source/core/rendering/svg/SVGTextLayoutAttributes.h
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) Research In Motion Limited 2010-2011. 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 SVGTextLayoutAttributes_h
+#define SVGTextLayoutAttributes_h
+
+#if ENABLE(SVG)
+#include "core/rendering/svg/SVGTextMetrics.h"
+#include <wtf/HashMap.h>
+#include <wtf/Noncopyable.h>
+#include <wtf/text/WTFString.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class RenderSVGInlineText;
+
+struct SVGCharacterData {
+    SVGCharacterData();
+
+    float x;
+    float y;
+    float dx;
+    float dy;
+    float rotate;
+};
+
+typedef HashMap<unsigned, SVGCharacterData> SVGCharacterDataMap;
+
+class SVGTextLayoutAttributes {
+    WTF_MAKE_NONCOPYABLE(SVGTextLayoutAttributes);
+public:
+    SVGTextLayoutAttributes(RenderSVGInlineText*);
+
+    void clear();
+    void dump() const;
+    static float emptyValue();
+
+    RenderSVGInlineText* context() const { return m_context; }
+    
+    SVGCharacterDataMap& characterDataMap() { return m_characterDataMap; }
+    const SVGCharacterDataMap& characterDataMap() const { return m_characterDataMap; }
+
+    Vector<SVGTextMetrics>& textMetricsValues() { return m_textMetricsValues; }
+
+private:
+    RenderSVGInlineText* m_context;
+    SVGCharacterDataMap m_characterDataMap;
+    Vector<SVGTextMetrics> m_textMetricsValues;
+};
+
+inline SVGCharacterData::SVGCharacterData()
+    : x(SVGTextLayoutAttributes::emptyValue())
+    , y(SVGTextLayoutAttributes::emptyValue())
+    , dx(SVGTextLayoutAttributes::emptyValue())
+    , dy(SVGTextLayoutAttributes::emptyValue())
+    , rotate(SVGTextLayoutAttributes::emptyValue())
+{
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
+#endif
diff --git a/Source/core/rendering/svg/SVGTextLayoutAttributesBuilder.cpp b/Source/core/rendering/svg/SVGTextLayoutAttributesBuilder.cpp
new file mode 100644
index 0000000..b38c4cb
--- /dev/null
+++ b/Source/core/rendering/svg/SVGTextLayoutAttributesBuilder.cpp
@@ -0,0 +1,238 @@
+/*
+ * Copyright (C) Research In Motion Limited 2010-2011. 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"
+
+#if ENABLE(SVG)
+#include "core/rendering/svg/SVGTextLayoutAttributesBuilder.h"
+
+#include "core/rendering/svg/RenderSVGInlineText.h"
+#include "core/rendering/svg/RenderSVGText.h"
+#include "core/svg/SVGTextPositioningElement.h"
+
+namespace WebCore {
+
+SVGTextLayoutAttributesBuilder::SVGTextLayoutAttributesBuilder()
+    : m_textLength(0)
+{
+}
+
+void SVGTextLayoutAttributesBuilder::buildLayoutAttributesForTextRenderer(RenderSVGInlineText* text)
+{
+    ASSERT(text);
+
+    RenderSVGText* textRoot = RenderSVGText::locateRenderSVGTextAncestor(text);
+    if (!textRoot)
+        return;
+
+    if (m_textPositions.isEmpty()) {
+        m_characterDataMap.clear();
+
+        m_textLength = 0;
+        const UChar* lastCharacter = 0;
+        collectTextPositioningElements(textRoot, lastCharacter);
+
+        if (!m_textLength)
+            return;
+
+        buildCharacterDataMap(textRoot);
+    }
+
+    m_metricsBuilder.buildMetricsAndLayoutAttributes(textRoot, text, m_characterDataMap);
+}
+
+bool SVGTextLayoutAttributesBuilder::buildLayoutAttributesForForSubtree(RenderSVGText* textRoot)
+{
+    ASSERT(textRoot);
+
+    m_characterDataMap.clear();
+
+    if (m_textPositions.isEmpty()) {
+        m_textLength = 0;
+        const UChar* lastCharacter = 0;
+        collectTextPositioningElements(textRoot, lastCharacter);
+    }
+
+    if (!m_textLength)
+        return false;
+
+    buildCharacterDataMap(textRoot);
+    m_metricsBuilder.buildMetricsAndLayoutAttributes(textRoot, 0, m_characterDataMap);
+    return true;
+}
+
+void SVGTextLayoutAttributesBuilder::rebuildMetricsForTextRenderer(RenderSVGInlineText* text)
+{
+    ASSERT(text);
+    m_metricsBuilder.measureTextRenderer(text);
+}
+
+static inline void processRenderSVGInlineText(RenderSVGInlineText* text, unsigned& atCharacter, const UChar*& lastCharacter)
+{
+    if (text->style()->whiteSpace() == PRE) {
+        atCharacter += text->textLength();
+        return;
+    }
+
+    const UChar* characters = text->characters();
+    unsigned textLength = text->textLength();    
+    for (unsigned textPosition = 0; textPosition < textLength; ++textPosition) {
+        const UChar* currentCharacter = characters + textPosition;
+        if (*currentCharacter == ' ' && (!lastCharacter || *lastCharacter == ' '))
+            continue;
+
+        lastCharacter = currentCharacter;
+        ++atCharacter;
+    }
+}
+
+void SVGTextLayoutAttributesBuilder::collectTextPositioningElements(RenderObject* start, const UChar*& lastCharacter)
+{
+    ASSERT(!start->isSVGText() || m_textPositions.isEmpty());
+
+    for (RenderObject* child = start->firstChild(); child; child = child->nextSibling()) { 
+        if (child->isSVGInlineText()) {
+            processRenderSVGInlineText(toRenderSVGInlineText(child), m_textLength, lastCharacter);
+            continue;
+        }
+
+        if (!child->isSVGInline())
+            continue;
+
+        SVGTextPositioningElement* element = SVGTextPositioningElement::elementFromRenderer(child);
+        unsigned atPosition = m_textPositions.size();
+        if (element)
+            m_textPositions.append(TextPosition(element, m_textLength));
+
+        collectTextPositioningElements(child, lastCharacter);
+
+        if (!element)
+            continue;
+
+        // Update text position, after we're back from recursion.
+        TextPosition& position = m_textPositions[atPosition];
+        ASSERT(!position.length);
+        position.length = m_textLength - position.start;
+    }
+}
+
+void SVGTextLayoutAttributesBuilder::buildCharacterDataMap(RenderSVGText* textRoot)
+{
+    SVGTextPositioningElement* outermostTextElement = SVGTextPositioningElement::elementFromRenderer(textRoot);
+    ASSERT(outermostTextElement);
+
+    // Grab outermost <text> element value lists and insert them in the character data map.
+    TextPosition wholeTextPosition(outermostTextElement, 0, m_textLength);
+    fillCharacterDataMap(wholeTextPosition);
+
+    // Handle x/y default attributes.
+    SVGCharacterDataMap::iterator it = m_characterDataMap.find(1);
+    if (it == m_characterDataMap.end()) {
+        SVGCharacterData data;
+        data.x = 0;
+        data.y = 0;
+        m_characterDataMap.set(1, data);
+    } else {
+        SVGCharacterData& data = it->value;
+        if (data.x == SVGTextLayoutAttributes::emptyValue())
+            data.x = 0;
+        if (data.y == SVGTextLayoutAttributes::emptyValue())
+            data.y = 0;
+    }
+
+    // Fill character data map using child text positioning elements in top-down order. 
+    unsigned size = m_textPositions.size();
+    for (unsigned i = 0; i < size; ++i)
+        fillCharacterDataMap(m_textPositions[i]);
+}
+
+static inline void updateCharacterData(unsigned i, float& lastRotation, SVGCharacterData& data, const SVGLengthContext& lengthContext, const SVGLengthList* xList, const SVGLengthList* yList, const SVGLengthList* dxList, const SVGLengthList* dyList, const SVGNumberList* rotateList)
+{
+    if (xList)
+        data.x = xList->at(i).value(lengthContext);
+    if (yList)
+        data.y = yList->at(i).value(lengthContext);
+    if (dxList)
+        data.dx = dxList->at(i).value(lengthContext);
+    if (dyList)
+        data.dy = dyList->at(i).value(lengthContext);
+    if (rotateList) {
+        data.rotate = rotateList->at(i);
+        lastRotation = data.rotate;
+    }
+}
+
+void SVGTextLayoutAttributesBuilder::fillCharacterDataMap(const TextPosition& position)
+{
+    const SVGLengthList& xList = position.element->x();
+    const SVGLengthList& yList = position.element->y();
+    const SVGLengthList& dxList = position.element->dx();
+    const SVGLengthList& dyList = position.element->dy();
+    const SVGNumberList& rotateList = position.element->rotate();
+
+    unsigned xListSize = xList.size();
+    unsigned yListSize = yList.size();
+    unsigned dxListSize = dxList.size();
+    unsigned dyListSize = dyList.size();
+    unsigned rotateListSize = rotateList.size();
+    if (!xListSize && !yListSize && !dxListSize && !dyListSize && !rotateListSize)
+        return;
+
+    float lastRotation = SVGTextLayoutAttributes::emptyValue();
+    SVGLengthContext lengthContext(position.element);
+    for (unsigned i = 0; i < position.length; ++i) {
+        const SVGLengthList* xListPtr = i < xListSize ? &xList : 0;
+        const SVGLengthList* yListPtr = i < yListSize ? &yList : 0;
+        const SVGLengthList* dxListPtr = i < dxListSize ? &dxList : 0;
+        const SVGLengthList* dyListPtr = i < dyListSize ? &dyList : 0;
+        const SVGNumberList* rotateListPtr = i < rotateListSize ? &rotateList : 0;
+        if (!xListPtr && !yListPtr && !dxListPtr && !dyListPtr && !rotateListPtr)
+            break;
+
+        SVGCharacterDataMap::iterator it = m_characterDataMap.find(position.start + i + 1);
+        if (it == m_characterDataMap.end()) {
+            SVGCharacterData data;
+            updateCharacterData(i, lastRotation, data, lengthContext, xListPtr, yListPtr, dxListPtr, dyListPtr, rotateListPtr);
+            m_characterDataMap.set(position.start + i + 1, data);
+            continue;
+        }
+
+        updateCharacterData(i, lastRotation, it->value, lengthContext, xListPtr, yListPtr, dxListPtr, dyListPtr, rotateListPtr);
+    }
+
+    // The last rotation value always spans the whole scope.
+    if (lastRotation == SVGTextLayoutAttributes::emptyValue())
+        return;
+
+    for (unsigned i = rotateList.size(); i < position.length; ++i) {
+        SVGCharacterDataMap::iterator it = m_characterDataMap.find(position.start + i + 1);
+        if (it == m_characterDataMap.end()) {
+            SVGCharacterData data;
+            data.rotate = lastRotation;
+            m_characterDataMap.set(position.start + i + 1, data);
+            continue;
+        }
+
+        it->value.rotate = lastRotation;
+    }
+}
+
+}
+
+#endif // ENABLE(SVG)
diff --git a/Source/core/rendering/svg/SVGTextLayoutAttributesBuilder.h b/Source/core/rendering/svg/SVGTextLayoutAttributesBuilder.h
new file mode 100644
index 0000000..c01a596
--- /dev/null
+++ b/Source/core/rendering/svg/SVGTextLayoutAttributesBuilder.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) Research In Motion Limited 2010-2012. 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 SVGTextLayoutAttributesBuilder_h
+#define SVGTextLayoutAttributesBuilder_h
+
+#if ENABLE(SVG)
+#include "core/rendering/svg/SVGTextMetricsBuilder.h"
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class RenderObject;
+class RenderSVGInlineText;
+class RenderSVGText;
+class SVGTextPositioningElement;
+
+// SVGTextLayoutAttributesBuilder performs the first layout phase for SVG text.
+//
+// It extracts the x/y/dx/dy/rotate values from the SVGTextPositioningElements in the DOM.
+// These values are propagated to the corresponding RenderSVGInlineText renderers.
+// The first layout phase only extracts the relevant information needed in RenderBlockLineLayout
+// to create the InlineBox tree based on text chunk boundaries & BiDi information.
+// The second layout phase is carried out by SVGTextLayoutEngine.
+
+class SVGTextLayoutAttributesBuilder {
+    WTF_MAKE_NONCOPYABLE(SVGTextLayoutAttributesBuilder);
+public:
+    SVGTextLayoutAttributesBuilder();
+    bool buildLayoutAttributesForForSubtree(RenderSVGText*);
+    void buildLayoutAttributesForTextRenderer(RenderSVGInlineText*);
+
+    void rebuildMetricsForTextRenderer(RenderSVGInlineText*);
+
+    // Invoked whenever the underlying DOM tree changes, so that m_textPositions is rebuild.
+    void clearTextPositioningElements() { m_textPositions.clear(); }
+    unsigned numberOfTextPositioningElements() const { return m_textPositions.size(); }
+
+private:
+    struct TextPosition {
+        TextPosition(SVGTextPositioningElement* newElement = 0, unsigned newStart = 0, unsigned newLength = 0)
+            : element(newElement)
+            , start(newStart)
+            , length(newLength)
+        {
+        }
+
+        SVGTextPositioningElement* element;
+        unsigned start;
+        unsigned length;
+    };
+
+    void buildCharacterDataMap(RenderSVGText*);
+    void collectTextPositioningElements(RenderObject*, const UChar*& lastCharacter);
+    void fillCharacterDataMap(const TextPosition&);
+
+private:
+    unsigned m_textLength;
+    Vector<TextPosition> m_textPositions;
+    SVGCharacterDataMap m_characterDataMap;
+    SVGTextMetricsBuilder m_metricsBuilder;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
+#endif
diff --git a/Source/core/rendering/svg/SVGTextLayoutEngine.cpp b/Source/core/rendering/svg/SVGTextLayoutEngine.cpp
new file mode 100644
index 0000000..12eacf2
--- /dev/null
+++ b/Source/core/rendering/svg/SVGTextLayoutEngine.cpp
@@ -0,0 +1,659 @@
+/*
+ * Copyright (C) Research In Motion Limited 2010-2012. 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"
+
+#if ENABLE(SVG)
+#include "core/rendering/svg/SVGTextLayoutEngine.h"
+
+#include "core/rendering/svg/RenderSVGInlineText.h"
+#include "core/rendering/svg/RenderSVGTextPath.h"
+#include "core/rendering/svg/SVGInlineTextBox.h"
+#include "core/rendering/svg/SVGTextLayoutEngineBaseline.h"
+#include "core/rendering/svg/SVGTextLayoutEngineSpacing.h"
+#include "core/svg/SVGElement.h"
+#include "core/svg/SVGLengthContext.h"
+
+// Set to a value > 0 to dump the text fragments
+#define DUMP_TEXT_FRAGMENTS 0
+
+namespace WebCore {
+
+SVGTextLayoutEngine::SVGTextLayoutEngine(Vector<SVGTextLayoutAttributes*>& layoutAttributes)
+    : m_layoutAttributes(layoutAttributes)
+    , m_layoutAttributesPosition(0)
+    , m_logicalCharacterOffset(0)
+    , m_logicalMetricsListOffset(0)
+    , m_visualCharacterOffset(0)
+    , m_visualMetricsListOffset(0)
+    , m_x(0)
+    , m_y(0)
+    , m_dx(0)
+    , m_dy(0)
+    , m_isVerticalText(false)
+    , m_inPathLayout(false)
+    , m_textPathLength(0)
+    , m_textPathCurrentOffset(0)
+    , m_textPathSpacing(0)
+    , m_textPathScaling(1)
+{
+    ASSERT(!m_layoutAttributes.isEmpty());
+}
+
+void SVGTextLayoutEngine::updateCharacerPositionIfNeeded(float& x, float& y)
+{
+    if (m_inPathLayout)
+        return;
+
+    // Replace characters x/y position, with the current text position plus any
+    // relative adjustments, if it doesn't specify an absolute position itself.
+    if (x == SVGTextLayoutAttributes::emptyValue()) 
+        x = m_x + m_dx;
+
+    if (y == SVGTextLayoutAttributes::emptyValue())
+        y = m_y + m_dy;
+
+    m_dx = 0;
+    m_dy = 0;
+}
+
+void SVGTextLayoutEngine::updateCurrentTextPosition(float x, float y, float glyphAdvance)
+{
+    // Update current text position after processing the character.
+    if (m_isVerticalText) {
+        m_x = x;
+        m_y = y + glyphAdvance;
+    } else {
+        m_x = x + glyphAdvance;
+        m_y = y;
+    }
+}
+
+void SVGTextLayoutEngine::updateRelativePositionAdjustmentsIfNeeded(float dx, float dy)
+{
+    // Update relative positioning information.
+    if (dx == SVGTextLayoutAttributes::emptyValue() && dy == SVGTextLayoutAttributes::emptyValue())
+        return;
+
+    if (dx == SVGTextLayoutAttributes::emptyValue())
+        dx = 0;
+    if (dy == SVGTextLayoutAttributes::emptyValue())
+        dy = 0;
+
+    if (m_inPathLayout) {
+        if (m_isVerticalText) {
+            m_dx += dx;
+            m_dy = dy;
+        } else {
+            m_dx = dx;
+            m_dy += dy;
+        }
+
+        return;
+    }
+
+    m_dx = dx;
+    m_dy = dy;
+}
+
+void SVGTextLayoutEngine::recordTextFragment(SVGInlineTextBox* textBox, Vector<SVGTextMetrics>& textMetricsValues)
+{
+    ASSERT(!m_currentTextFragment.length);
+    ASSERT(m_visualMetricsListOffset > 0);
+
+    // Figure out length of fragment.
+    m_currentTextFragment.length = m_visualCharacterOffset - m_currentTextFragment.characterOffset;
+
+    // Figure out fragment metrics.
+    SVGTextMetrics& lastCharacterMetrics = textMetricsValues.at(m_visualMetricsListOffset - 1);
+    m_currentTextFragment.width = lastCharacterMetrics.width();
+    m_currentTextFragment.height = lastCharacterMetrics.height();
+
+    if (m_currentTextFragment.length > 1) {
+        // SVGTextLayoutAttributesBuilder assures that the length of the range is equal to the sum of the individual lengths of the glyphs.
+        float length = 0;
+        if (m_isVerticalText) {
+            for (unsigned i = m_currentTextFragment.metricsListOffset; i < m_visualMetricsListOffset; ++i)
+                length += textMetricsValues.at(i).height();
+            m_currentTextFragment.height = length;
+        } else {
+            for (unsigned i = m_currentTextFragment.metricsListOffset; i < m_visualMetricsListOffset; ++i)
+                length += textMetricsValues.at(i).width();
+            m_currentTextFragment.width = length;
+        }
+    }
+
+    textBox->textFragments().append(m_currentTextFragment);
+    m_currentTextFragment = SVGTextFragment();
+}
+
+bool SVGTextLayoutEngine::parentDefinesTextLength(RenderObject* parent) const
+{
+    RenderObject* currentParent = parent;
+    while (currentParent) {
+        if (SVGTextContentElement* textContentElement = SVGTextContentElement::elementFromRenderer(currentParent)) {
+            SVGLengthContext lengthContext(textContentElement);
+            if (textContentElement->lengthAdjust() == SVGLengthAdjustSpacing && textContentElement->specifiedTextLength().value(lengthContext) > 0)
+                return true;
+        }
+
+        if (currentParent->isSVGText())
+            return false;
+
+        currentParent = currentParent->parent();
+    }
+
+    ASSERT_NOT_REACHED();
+    return false;
+}
+
+void SVGTextLayoutEngine::beginTextPathLayout(RenderObject* object, SVGTextLayoutEngine& lineLayout)
+{
+    ASSERT(object);
+
+    m_inPathLayout = true;
+    RenderSVGTextPath* textPath = toRenderSVGTextPath(object);
+
+    m_textPath = textPath->layoutPath();
+    if (m_textPath.isEmpty())
+        return;
+    m_textPathStartOffset = textPath->startOffset();
+    m_textPathLength = m_textPath.length();
+    if (m_textPathStartOffset > 0 && m_textPathStartOffset <= 1)
+        m_textPathStartOffset *= m_textPathLength;
+
+    float totalLength = 0;
+    unsigned totalCharacters = 0;
+
+    lineLayout.m_chunkLayoutBuilder.buildTextChunks(lineLayout.m_lineLayoutBoxes);
+    const Vector<SVGTextChunk>& textChunks = lineLayout.m_chunkLayoutBuilder.textChunks();
+
+    unsigned size = textChunks.size();
+    for (unsigned i = 0; i < size; ++i) {
+        const SVGTextChunk& chunk = textChunks.at(i);
+
+        float length = 0;
+        unsigned characters = 0;
+        chunk.calculateLength(length, characters);
+
+        // Handle text-anchor as additional start offset for text paths.
+        m_textPathStartOffset += chunk.calculateTextAnchorShift(length);
+
+        totalLength += length;
+        totalCharacters += characters;
+    }
+
+    m_textPathCurrentOffset = m_textPathStartOffset;
+
+    // Eventually handle textLength adjustments.
+    SVGLengthAdjustType lengthAdjust = SVGLengthAdjustUnknown;
+    float desiredTextLength = 0;
+
+    if (SVGTextContentElement* textContentElement = SVGTextContentElement::elementFromRenderer(textPath)) {
+        SVGLengthContext lengthContext(textContentElement);
+        lengthAdjust = textContentElement->lengthAdjust();
+        desiredTextLength = textContentElement->specifiedTextLength().value(lengthContext);
+    }
+
+    if (!desiredTextLength)
+        return;
+
+    if (lengthAdjust == SVGLengthAdjustSpacing)
+        m_textPathSpacing = (desiredTextLength - totalLength) / totalCharacters;
+    else
+        m_textPathScaling = desiredTextLength / totalLength;
+}
+
+void SVGTextLayoutEngine::endTextPathLayout()
+{
+    m_inPathLayout = false;
+    m_textPath = Path();
+    m_textPathLength = 0;
+    m_textPathStartOffset = 0;
+    m_textPathCurrentOffset = 0;
+    m_textPathSpacing = 0;
+    m_textPathScaling = 1;
+}
+
+void SVGTextLayoutEngine::layoutInlineTextBox(SVGInlineTextBox* textBox)
+{
+    ASSERT(textBox);
+
+    RenderSVGInlineText* text = toRenderSVGInlineText(textBox->textRenderer());
+    ASSERT(text);
+    ASSERT(text->parent());
+    ASSERT(text->parent()->node());
+    ASSERT(text->parent()->node()->isSVGElement());
+
+    const RenderStyle* style = text->style();
+    ASSERT(style);
+
+    textBox->clearTextFragments();
+    m_isVerticalText = style->svgStyle()->isVerticalWritingMode();
+    layoutTextOnLineOrPath(textBox, text, style);
+
+    if (m_inPathLayout) {
+        m_pathLayoutBoxes.append(textBox);
+        return;
+    }
+
+    m_lineLayoutBoxes.append(textBox);
+}
+
+#if DUMP_TEXT_FRAGMENTS > 0
+static inline void dumpTextBoxes(Vector<SVGInlineTextBox*>& boxes)
+{
+    unsigned boxCount = boxes.size();
+    fprintf(stderr, "Dumping all text fragments in text sub tree, %i boxes\n", boxCount);
+
+    for (unsigned boxPosition = 0; boxPosition < boxCount; ++boxPosition) {
+        SVGInlineTextBox* textBox = boxes.at(boxPosition);
+        Vector<SVGTextFragment>& fragments = textBox->textFragments();
+        fprintf(stderr, "-> Box %i: Dumping text fragments for SVGInlineTextBox, textBox=%p, textRenderer=%p\n", boxPosition, textBox, textBox->textRenderer());
+        fprintf(stderr, "        textBox properties, start=%i, len=%i, box direction=%i\n", textBox->start(), textBox->len(), textBox->direction());
+        fprintf(stderr, "   textRenderer properties, textLength=%i\n", textBox->textRenderer()->textLength());
+
+        const UChar* characters = textBox->textRenderer()->characters();
+
+        unsigned fragmentCount = fragments.size();
+        for (unsigned i = 0; i < fragmentCount; ++i) {
+            SVGTextFragment& fragment = fragments.at(i);
+            String fragmentString(characters + fragment.characterOffset, fragment.length);
+            fprintf(stderr, "    -> Fragment %i, x=%lf, y=%lf, width=%lf, height=%lf, characterOffset=%i, length=%i, characters='%s'\n"
+                          , i, fragment.x, fragment.y, fragment.width, fragment.height, fragment.characterOffset, fragment.length, fragmentString.utf8().data());
+        }
+    }
+}
+#endif
+
+void SVGTextLayoutEngine::finalizeTransformMatrices(Vector<SVGInlineTextBox*>& boxes)
+{
+    unsigned boxCount = boxes.size();
+    if (!boxCount)
+        return;
+
+    AffineTransform textBoxTransformation;
+    for (unsigned boxPosition = 0; boxPosition < boxCount; ++boxPosition) {
+        SVGInlineTextBox* textBox = boxes.at(boxPosition);
+        Vector<SVGTextFragment>& fragments = textBox->textFragments();
+
+        unsigned fragmentCount = fragments.size();
+        for (unsigned i = 0; i < fragmentCount; ++i) {
+            m_chunkLayoutBuilder.transformationForTextBox(textBox, textBoxTransformation);
+            if (textBoxTransformation.isIdentity())
+                continue;
+            ASSERT(fragments[i].lengthAdjustTransform.isIdentity());
+            fragments[i].lengthAdjustTransform = textBoxTransformation;
+        }
+    }
+
+    boxes.clear();
+}
+
+void SVGTextLayoutEngine::finishLayout()
+{
+    // After all text fragments are stored in their correpsonding SVGInlineTextBoxes, we can layout individual text chunks.
+    // Chunk layouting is only performed for line layout boxes, not for path layout, where it has already been done.
+    m_chunkLayoutBuilder.layoutTextChunks(m_lineLayoutBoxes);
+
+    // Finalize transform matrices, after the chunk layout corrections have been applied, and all fragment x/y positions are finalized.
+    if (!m_lineLayoutBoxes.isEmpty()) {
+#if DUMP_TEXT_FRAGMENTS > 0
+        fprintf(stderr, "Line layout: ");
+        dumpTextBoxes(m_lineLayoutBoxes);
+#endif
+
+        finalizeTransformMatrices(m_lineLayoutBoxes);
+    }
+
+    if (!m_pathLayoutBoxes.isEmpty()) {
+#if DUMP_TEXT_FRAGMENTS > 0
+        fprintf(stderr, "Path layout: ");
+        dumpTextBoxes(m_pathLayoutBoxes);
+#endif
+
+        finalizeTransformMatrices(m_pathLayoutBoxes);
+    }
+}
+
+bool SVGTextLayoutEngine::currentLogicalCharacterAttributes(SVGTextLayoutAttributes*& logicalAttributes)
+{
+    if (m_layoutAttributesPosition == m_layoutAttributes.size())
+        return false;
+
+    logicalAttributes = m_layoutAttributes[m_layoutAttributesPosition];
+    ASSERT(logicalAttributes);
+
+    if (m_logicalCharacterOffset != logicalAttributes->context()->textLength())
+        return true;
+
+    ++m_layoutAttributesPosition;
+    if (m_layoutAttributesPosition == m_layoutAttributes.size())
+        return false;
+
+    logicalAttributes = m_layoutAttributes[m_layoutAttributesPosition];
+    m_logicalMetricsListOffset = 0;
+    m_logicalCharacterOffset = 0;
+    return true;
+}
+
+bool SVGTextLayoutEngine::currentLogicalCharacterMetrics(SVGTextLayoutAttributes*& logicalAttributes, SVGTextMetrics& logicalMetrics)
+{
+    Vector<SVGTextMetrics>* textMetricsValues = &logicalAttributes->textMetricsValues();
+    unsigned textMetricsSize = textMetricsValues->size();
+    while (true) {
+        if (m_logicalMetricsListOffset == textMetricsSize) {
+            if (!currentLogicalCharacterAttributes(logicalAttributes))
+                return false;
+
+            textMetricsValues = &logicalAttributes->textMetricsValues();
+            textMetricsSize = textMetricsValues->size();
+            continue;
+        }
+
+        ASSERT(textMetricsSize);
+        ASSERT(m_logicalMetricsListOffset < textMetricsSize);
+        logicalMetrics = textMetricsValues->at(m_logicalMetricsListOffset);
+        if (logicalMetrics.isEmpty() || (!logicalMetrics.width() && !logicalMetrics.height())) {
+            advanceToNextLogicalCharacter(logicalMetrics);
+            continue;
+        }
+
+        // Stop if we found the next valid logical text metrics object.
+        return true;
+    }
+
+    ASSERT_NOT_REACHED();
+    return true;
+}
+
+bool SVGTextLayoutEngine::currentVisualCharacterMetrics(SVGInlineTextBox* textBox, Vector<SVGTextMetrics>& visualMetricsValues, SVGTextMetrics& visualMetrics)
+{
+    ASSERT(!visualMetricsValues.isEmpty());
+    unsigned textMetricsSize = visualMetricsValues.size();
+    unsigned boxStart = textBox->start();
+    unsigned boxLength = textBox->len();
+
+    if (m_visualMetricsListOffset == textMetricsSize)
+        return false;
+
+    while (m_visualMetricsListOffset < textMetricsSize) {
+        // Advance to text box start location.
+        if (m_visualCharacterOffset < boxStart) {
+            advanceToNextVisualCharacter(visualMetricsValues[m_visualMetricsListOffset]);
+            continue;
+        }
+
+        // Stop if we've finished processing this text box.
+        if (m_visualCharacterOffset >= boxStart + boxLength)
+            return false;
+
+        visualMetrics = visualMetricsValues[m_visualMetricsListOffset];
+        return true;
+    }
+
+    return false;
+}
+
+void SVGTextLayoutEngine::advanceToNextLogicalCharacter(const SVGTextMetrics& logicalMetrics)
+{
+    ++m_logicalMetricsListOffset;
+    m_logicalCharacterOffset += logicalMetrics.length();
+}
+
+void SVGTextLayoutEngine::advanceToNextVisualCharacter(const SVGTextMetrics& visualMetrics)
+{
+    ++m_visualMetricsListOffset;
+    m_visualCharacterOffset += visualMetrics.length();
+}
+
+void SVGTextLayoutEngine::layoutTextOnLineOrPath(SVGInlineTextBox* textBox, RenderSVGInlineText* text, const RenderStyle* style)
+{
+    if (m_inPathLayout && m_textPath.isEmpty())
+        return;
+
+    SVGElement* lengthContext = toSVGElement(text->parent()->node());
+    
+    RenderObject* textParent = text->parent();
+    bool definesTextLength = textParent ? parentDefinesTextLength(textParent) : false;
+
+    const SVGRenderStyle* svgStyle = style->svgStyle();
+    ASSERT(svgStyle);
+
+    m_visualMetricsListOffset = 0;
+    m_visualCharacterOffset = 0;
+
+    Vector<SVGTextMetrics>& visualMetricsValues = text->layoutAttributes()->textMetricsValues();
+    ASSERT(!visualMetricsValues.isEmpty());
+
+    const UChar* characters = text->characters();
+    const Font& font = style->font();
+
+    SVGTextLayoutEngineSpacing spacingLayout(font);
+    SVGTextLayoutEngineBaseline baselineLayout(font);
+
+    bool didStartTextFragment = false;
+    bool applySpacingToNextCharacter = false;
+
+    float lastAngle = 0;
+    float baselineShift = baselineLayout.calculateBaselineShift(svgStyle, lengthContext);
+    baselineShift -= baselineLayout.calculateAlignmentBaselineShift(m_isVerticalText, text);
+
+    // Main layout algorithm.
+    while (true) {
+        // Find the start of the current text box in this list, respecting ligatures.
+        SVGTextMetrics visualMetrics(SVGTextMetrics::SkippedSpaceMetrics);
+        if (!currentVisualCharacterMetrics(textBox, visualMetricsValues, visualMetrics))
+            break;
+
+        if (visualMetrics.isEmpty()) {
+            advanceToNextVisualCharacter(visualMetrics);
+            continue;
+        }
+
+        SVGTextLayoutAttributes* logicalAttributes = 0;
+        if (!currentLogicalCharacterAttributes(logicalAttributes))
+            break;
+
+        ASSERT(logicalAttributes);
+        SVGTextMetrics logicalMetrics(SVGTextMetrics::SkippedSpaceMetrics);
+        if (!currentLogicalCharacterMetrics(logicalAttributes, logicalMetrics))
+            break;
+
+        SVGCharacterDataMap& characterDataMap = logicalAttributes->characterDataMap();
+        SVGCharacterData data;
+        SVGCharacterDataMap::iterator it = characterDataMap.find(m_logicalCharacterOffset + 1);
+        if (it != characterDataMap.end())
+            data = it->value;
+
+        float x = data.x;
+        float y = data.y;
+
+        // When we've advanced to the box start offset, determine using the original x/y values,
+        // whether this character starts a new text chunk, before doing any further processing.
+        if (m_visualCharacterOffset == textBox->start())
+            textBox->setStartsNewTextChunk(logicalAttributes->context()->characterStartsNewTextChunk(m_logicalCharacterOffset));
+
+        float angle = data.rotate == SVGTextLayoutAttributes::emptyValue() ? 0 : data.rotate;
+
+        // Calculate glyph orientation angle.
+        const UChar* currentCharacter = characters + m_visualCharacterOffset;
+        float orientationAngle = baselineLayout.calculateGlyphOrientationAngle(m_isVerticalText, svgStyle, *currentCharacter);
+
+        // Calculate glyph advance & x/y orientation shifts.
+        float xOrientationShift = 0;
+        float yOrientationShift = 0;
+        float glyphAdvance = baselineLayout.calculateGlyphAdvanceAndOrientation(m_isVerticalText, visualMetrics, orientationAngle, xOrientationShift, yOrientationShift);
+
+        // Assign current text position to x/y values, if needed.
+        updateCharacerPositionIfNeeded(x, y);
+
+        // Apply dx/dy value adjustments to current text position, if needed.
+        updateRelativePositionAdjustmentsIfNeeded(data.dx, data.dy);
+
+        // Calculate SVG Fonts kerning, if needed.
+        float kerning = spacingLayout.calculateSVGKerning(m_isVerticalText, visualMetrics.glyph());
+
+        // Calculate CSS 'kerning', 'letter-spacing' and 'word-spacing' for next character, if needed.
+        float spacing = spacingLayout.calculateCSSKerningAndSpacing(svgStyle, lengthContext, currentCharacter);
+
+        float textPathOffset = 0;
+        if (m_inPathLayout) {
+            float scaledGlyphAdvance = glyphAdvance * m_textPathScaling;
+            if (m_isVerticalText) {
+                // If there's an absolute y position available, it marks the beginning of a new position along the path.
+                if (y != SVGTextLayoutAttributes::emptyValue())
+                    m_textPathCurrentOffset = y + m_textPathStartOffset;
+
+                m_textPathCurrentOffset += m_dy - kerning;
+                m_dy = 0;
+
+                // Apply dx/dy correction and setup translations that move to the glyph midpoint.
+                xOrientationShift += m_dx + baselineShift;
+                yOrientationShift -= scaledGlyphAdvance / 2;
+            } else {
+                // If there's an absolute x position available, it marks the beginning of a new position along the path.
+                if (x != SVGTextLayoutAttributes::emptyValue())
+                    m_textPathCurrentOffset = x + m_textPathStartOffset;
+
+                m_textPathCurrentOffset += m_dx - kerning;
+                m_dx = 0;
+
+                // Apply dx/dy correction and setup translations that move to the glyph midpoint.
+                xOrientationShift -= scaledGlyphAdvance / 2;
+                yOrientationShift += m_dy - baselineShift;
+            }
+
+            // Calculate current offset along path.
+            textPathOffset = m_textPathCurrentOffset + scaledGlyphAdvance / 2;
+
+            // Move to next character.
+            m_textPathCurrentOffset += scaledGlyphAdvance + m_textPathSpacing + spacing * m_textPathScaling;
+
+            // Skip character, if we're before the path.
+            if (textPathOffset < 0) {
+                advanceToNextLogicalCharacter(logicalMetrics);
+                advanceToNextVisualCharacter(visualMetrics);
+                continue;
+            }
+
+            // Stop processing, if the next character lies behind the path.
+            if (textPathOffset > m_textPathLength)
+                break;
+
+            bool ok = false;
+            FloatPoint point = m_textPath.pointAtLength(textPathOffset, ok);
+            ASSERT(ok);
+
+            x = point.x();
+            y = point.y();
+            angle = m_textPath.normalAngleAtLength(textPathOffset, ok);
+            ASSERT(ok);
+
+            // For vertical text on path, the actual angle has to be rotated 90 degrees anti-clockwise, not the orientation angle!
+            if (m_isVerticalText)
+                angle -= 90;
+        } else {
+            // Apply all previously calculated shift values.
+            if (m_isVerticalText) {
+                x += baselineShift;
+                y -= kerning;
+            } else {
+                x -= kerning;
+                y -= baselineShift;
+            }
+
+            x += m_dx;
+            y += m_dy;
+        }
+
+        // Determine whether we have to start a new fragment.
+        bool shouldStartNewFragment = m_dx || m_dy || m_isVerticalText || m_inPathLayout || angle || angle != lastAngle
+            || orientationAngle || kerning || applySpacingToNextCharacter || definesTextLength;
+
+        // If we already started a fragment, close it now.
+        if (didStartTextFragment && shouldStartNewFragment) {
+            applySpacingToNextCharacter = false;
+            recordTextFragment(textBox, visualMetricsValues);
+        }
+
+        // Eventually start a new fragment, if not yet done.
+        if (!didStartTextFragment || shouldStartNewFragment) {
+            ASSERT(!m_currentTextFragment.characterOffset);
+            ASSERT(!m_currentTextFragment.length);
+
+            didStartTextFragment = true;
+            m_currentTextFragment.characterOffset = m_visualCharacterOffset;
+            m_currentTextFragment.metricsListOffset = m_visualMetricsListOffset;
+            m_currentTextFragment.x = x;
+            m_currentTextFragment.y = y;
+
+            // Build fragment transformation.
+            if (angle)
+                m_currentTextFragment.transform.rotate(angle);
+
+            if (xOrientationShift || yOrientationShift)
+                m_currentTextFragment.transform.translate(xOrientationShift, yOrientationShift);
+
+            if (orientationAngle)
+                m_currentTextFragment.transform.rotate(orientationAngle);
+
+            m_currentTextFragment.isTextOnPath = m_inPathLayout && m_textPathScaling != 1;
+            if (m_currentTextFragment.isTextOnPath) {
+                if (m_isVerticalText)
+                    m_currentTextFragment.lengthAdjustTransform.scaleNonUniform(1, m_textPathScaling);
+                else
+                    m_currentTextFragment.lengthAdjustTransform.scaleNonUniform(m_textPathScaling, 1);
+            }
+        }
+
+        // Update current text position, after processing of the current character finished.
+        if (m_inPathLayout)
+            updateCurrentTextPosition(x, y, glyphAdvance);
+        else {
+            // Apply CSS 'kerning', 'letter-spacing' and 'word-spacing' to next character, if needed.
+            if (spacing)
+                applySpacingToNextCharacter = true;
+
+            float xNew = x - m_dx;
+            float yNew = y - m_dy;
+
+            if (m_isVerticalText)
+                xNew -= baselineShift;
+            else
+                yNew += baselineShift;
+
+            updateCurrentTextPosition(xNew, yNew, glyphAdvance + spacing);
+        }
+
+        advanceToNextLogicalCharacter(logicalMetrics);
+        advanceToNextVisualCharacter(visualMetrics);
+        lastAngle = angle;
+    }
+
+    if (!didStartTextFragment)
+        return;
+
+    // Close last open fragment, if needed.
+    recordTextFragment(textBox, visualMetricsValues);
+}
+
+}
+
+#endif // ENABLE(SVG)
diff --git a/Source/core/rendering/svg/SVGTextLayoutEngine.h b/Source/core/rendering/svg/SVGTextLayoutEngine.h
new file mode 100644
index 0000000..1edffd0
--- /dev/null
+++ b/Source/core/rendering/svg/SVGTextLayoutEngine.h
@@ -0,0 +1,112 @@
+/*
+ * Copyright (C) Research In Motion Limited 2010-2012. 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 SVGTextLayoutEngine_h
+#define SVGTextLayoutEngine_h
+
+#if ENABLE(SVG)
+#include "core/platform/graphics/Path.h"
+#include "core/rendering/svg/SVGTextChunkBuilder.h"
+#include "core/rendering/svg/SVGTextFragment.h"
+#include "core/rendering/svg/SVGTextLayoutAttributes.h"
+#include "core/rendering/svg/SVGTextMetrics.h"
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class RenderObject;
+class RenderStyle;
+class RenderSVGInlineText;
+class SVGElement;
+class SVGInlineTextBox;
+class SVGRenderStyle;
+
+// SVGTextLayoutEngine performs the second layout phase for SVG text.
+//
+// The InlineBox tree was created, containing the text chunk information, necessary to apply
+// certain SVG specific text layout properties (text-length adjustments and text-anchor).
+// The second layout phase uses the SVGTextLayoutAttributes stored in the individual
+// RenderSVGInlineText renderers to compute the final positions for each character
+// which are stored in the SVGInlineTextBox objects.
+
+class SVGTextLayoutEngine {
+    WTF_MAKE_NONCOPYABLE(SVGTextLayoutEngine);
+public:
+    SVGTextLayoutEngine(Vector<SVGTextLayoutAttributes*>&);
+
+    Vector<SVGTextLayoutAttributes*>& layoutAttributes() { return m_layoutAttributes; }
+    SVGTextChunkBuilder& chunkLayoutBuilder() { return m_chunkLayoutBuilder; }
+
+    void beginTextPathLayout(RenderObject*, SVGTextLayoutEngine& lineLayout);
+    void endTextPathLayout();
+
+    void layoutInlineTextBox(SVGInlineTextBox*);
+    void finishLayout();
+
+private:
+    void updateCharacerPositionIfNeeded(float& x, float& y);
+    void updateCurrentTextPosition(float x, float y, float glyphAdvance);
+    void updateRelativePositionAdjustmentsIfNeeded(float dx, float dy);
+
+    void recordTextFragment(SVGInlineTextBox*, Vector<SVGTextMetrics>&);
+    bool parentDefinesTextLength(RenderObject*) const;
+
+    void layoutTextOnLineOrPath(SVGInlineTextBox*, RenderSVGInlineText*, const RenderStyle*);
+    void finalizeTransformMatrices(Vector<SVGInlineTextBox*>&);
+
+    bool currentLogicalCharacterAttributes(SVGTextLayoutAttributes*&);
+    bool currentLogicalCharacterMetrics(SVGTextLayoutAttributes*&, SVGTextMetrics&);
+    bool currentVisualCharacterMetrics(SVGInlineTextBox*, Vector<SVGTextMetrics>&, SVGTextMetrics&);
+
+    void advanceToNextLogicalCharacter(const SVGTextMetrics&);
+    void advanceToNextVisualCharacter(const SVGTextMetrics&);
+
+private:
+    Vector<SVGTextLayoutAttributes*>& m_layoutAttributes;
+
+    Vector<SVGInlineTextBox*> m_lineLayoutBoxes;
+    Vector<SVGInlineTextBox*> m_pathLayoutBoxes;
+    SVGTextChunkBuilder m_chunkLayoutBuilder;
+
+    SVGTextFragment m_currentTextFragment;
+    unsigned m_layoutAttributesPosition;
+    unsigned m_logicalCharacterOffset;
+    unsigned m_logicalMetricsListOffset;
+    unsigned m_visualCharacterOffset;
+    unsigned m_visualMetricsListOffset;
+    float m_x;
+    float m_y;
+    float m_dx;
+    float m_dy;
+    bool m_isVerticalText;
+    bool m_inPathLayout;
+
+    // Text on path layout
+    Path m_textPath;
+    float m_textPathLength;
+    float m_textPathStartOffset;
+    float m_textPathCurrentOffset;
+    float m_textPathSpacing;
+    float m_textPathScaling;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
+#endif
diff --git a/Source/core/rendering/svg/SVGTextLayoutEngineBaseline.cpp b/Source/core/rendering/svg/SVGTextLayoutEngineBaseline.cpp
new file mode 100644
index 0000000..b9db574
--- /dev/null
+++ b/Source/core/rendering/svg/SVGTextLayoutEngineBaseline.cpp
@@ -0,0 +1,239 @@
+/*
+ * Copyright (C) Research In Motion Limited 2010. 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"
+
+#if ENABLE(SVG)
+#include "core/rendering/svg/SVGTextLayoutEngineBaseline.h"
+
+#include "core/platform/graphics/Font.h"
+#include "core/platform/text/UnicodeRange.h"
+#include "core/rendering/RenderObject.h"
+#include "core/rendering/style/SVGRenderStyle.h"
+#include "core/rendering/svg/SVGTextMetrics.h"
+#include "core/svg/SVGLengthContext.h"
+
+namespace WebCore {
+
+SVGTextLayoutEngineBaseline::SVGTextLayoutEngineBaseline(const Font& font)
+    : m_font(font)
+{
+}
+
+float SVGTextLayoutEngineBaseline::calculateBaselineShift(const SVGRenderStyle* style, SVGElement* contextElement) const
+{
+    if (style->baselineShift() == BS_LENGTH) {
+        SVGLength baselineShiftValueLength = style->baselineShiftValue();
+        if (baselineShiftValueLength.unitType() == LengthTypePercentage)
+            return baselineShiftValueLength.valueAsPercentage() * m_font.pixelSize();
+
+        SVGLengthContext lengthContext(contextElement);
+        return baselineShiftValueLength.value(lengthContext);
+    }
+
+    switch (style->baselineShift()) {
+    case BS_BASELINE:
+        return 0;
+    case BS_SUB:
+        return -m_font.fontMetrics().floatHeight() / 2;
+    case BS_SUPER:
+        return m_font.fontMetrics().floatHeight() / 2;
+    default:
+        ASSERT_NOT_REACHED();
+        return 0;
+    }
+}
+
+EAlignmentBaseline SVGTextLayoutEngineBaseline::dominantBaselineToAlignmentBaseline(bool isVerticalText, const RenderObject* textRenderer) const
+{
+    ASSERT(textRenderer);
+    ASSERT(textRenderer->style());
+    ASSERT(textRenderer->parent());
+    ASSERT(textRenderer->parent()->style());
+
+    const SVGRenderStyle* style = textRenderer->style()->svgStyle();
+    ASSERT(style);
+
+    EDominantBaseline baseline = style->dominantBaseline();
+    if (baseline == DB_AUTO) {
+        if (isVerticalText)
+            baseline = DB_CENTRAL;
+        else
+            baseline = DB_ALPHABETIC;
+    }
+
+    switch (baseline) {
+    case DB_USE_SCRIPT:
+        // FIXME: 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:
+        return dominantBaselineToAlignmentBaseline(isVerticalText, textRenderer->parent());
+    case DB_RESET_SIZE:
+        return dominantBaselineToAlignmentBaseline(isVerticalText, textRenderer->parent());
+    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;
+    }
+}
+
+float SVGTextLayoutEngineBaseline::calculateAlignmentBaselineShift(bool isVerticalText, const RenderObject* textRenderer) const
+{
+    ASSERT(textRenderer);
+    ASSERT(textRenderer->style());
+    ASSERT(textRenderer->style()->svgStyle());
+    ASSERT(textRenderer->parent());
+
+    const RenderObject* textRendererParent = textRenderer->parent();
+    ASSERT(textRendererParent);
+
+    EAlignmentBaseline baseline = textRenderer->style()->svgStyle()->alignmentBaseline();
+    if (baseline == AB_AUTO) {
+        baseline = dominantBaselineToAlignmentBaseline(isVerticalText, textRendererParent);
+        ASSERT(baseline != AB_AUTO);
+    }
+
+    const FontMetrics& fontMetrics = m_font.fontMetrics();
+
+    // Note: http://wiki.apache.org/xmlgraphics-fop/LineLayout/AlignmentHandling
+    switch (baseline) {
+    case AB_BASELINE:
+        return dominantBaselineToAlignmentBaseline(isVerticalText, textRendererParent);
+    case AB_BEFORE_EDGE:
+    case AB_TEXT_BEFORE_EDGE:
+        return fontMetrics.floatAscent();
+    case AB_MIDDLE:
+        return fontMetrics.xHeight() / 2;
+    case AB_CENTRAL:
+        return (fontMetrics.floatAscent() - fontMetrics.floatDescent()) / 2;
+    case AB_AFTER_EDGE:
+    case AB_TEXT_AFTER_EDGE:
+    case AB_IDEOGRAPHIC:
+        return fontMetrics.floatDescent();
+    case AB_ALPHABETIC:
+        return 0;
+    case AB_HANGING:
+        return fontMetrics.floatAscent() * 8 / 10.f;
+    case AB_MATHEMATICAL:
+        return fontMetrics.floatAscent() / 2;
+    default:
+        ASSERT_NOT_REACHED();
+        return 0;
+    }
+}
+
+float SVGTextLayoutEngineBaseline::calculateGlyphOrientationAngle(bool isVerticalText, const SVGRenderStyle* style, const UChar& character) const
+{
+    ASSERT(style);
+
+    switch (isVerticalText ? style->glyphOrientationVertical() : style->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;
+
+        return 0;
+    }
+    case GO_90DEG:
+        return 90;
+    case GO_180DEG:
+        return 180;
+    case GO_270DEG:
+        return 270;
+    case GO_0DEG:
+    default:
+        return 0;
+    }
+}
+
+static inline bool glyphOrientationIsMultiplyOf180Degrees(float orientationAngle)
+{
+    return !fabsf(fmodf(orientationAngle, 180));
+}
+
+float SVGTextLayoutEngineBaseline::calculateGlyphAdvanceAndOrientation(bool isVerticalText, SVGTextMetrics& metrics, float angle, float& xOrientationShift, float& yOrientationShift) const
+{
+    bool orientationIsMultiplyOf180Degrees = glyphOrientationIsMultiplyOf180Degrees(angle);
+
+    // 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.
+
+    const FontMetrics& fontMetrics = m_font.fontMetrics();
+
+    // Vertical orientation handling.
+    if (isVerticalText) {
+        float ascentMinusDescent = fontMetrics.floatAscent() - fontMetrics.floatDescent();
+        if (!angle) {
+            xOrientationShift = (ascentMinusDescent - metrics.width()) / 2;
+            yOrientationShift = fontMetrics.floatAscent();
+        } else if (angle == 180)
+            xOrientationShift = (ascentMinusDescent + metrics.width()) / 2;
+        else if (angle == 270) {
+            yOrientationShift = metrics.width();
+            xOrientationShift = ascentMinusDescent;
+        }
+
+        // Vertical advance calculation.
+        if (angle && !orientationIsMultiplyOf180Degrees)
+            return metrics.width();
+
+        return metrics.height();
+    }
+
+    // Horizontal orientation handling.
+    if (angle == 90)
+        yOrientationShift = -metrics.width();
+    else if (angle == 180) {
+        xOrientationShift = metrics.width();
+        yOrientationShift = -fontMetrics.floatAscent();
+    } else if (angle == 270)
+        xOrientationShift = metrics.width();
+
+    // Horizontal advance calculation.
+    if (angle && !orientationIsMultiplyOf180Degrees)
+        return metrics.height();
+
+    return metrics.width();
+}
+
+}
+
+#endif // ENABLE(SVG)
diff --git a/Source/core/rendering/svg/SVGTextLayoutEngineBaseline.h b/Source/core/rendering/svg/SVGTextLayoutEngineBaseline.h
new file mode 100644
index 0000000..7973158
--- /dev/null
+++ b/Source/core/rendering/svg/SVGTextLayoutEngineBaseline.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) Research In Motion Limited 2010. 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 SVGTextLayoutEngineBaseline_h
+#define SVGTextLayoutEngineBaseline_h
+
+#if ENABLE(SVG)
+#include "core/rendering/style/SVGRenderStyleDefs.h"
+#include <wtf/Noncopyable.h>
+
+namespace WebCore {
+
+class Font;
+class RenderObject;
+class SVGElement;
+class SVGRenderStyle;
+class SVGTextMetrics;
+
+// Helper class used by SVGTextLayoutEngine to handle 'alignment-baseline' / 'dominant-baseline' and 'baseline-shift'.
+class SVGTextLayoutEngineBaseline {
+    WTF_MAKE_NONCOPYABLE(SVGTextLayoutEngineBaseline);
+public:
+    SVGTextLayoutEngineBaseline(const Font&);
+
+    float calculateBaselineShift(const SVGRenderStyle*, SVGElement* lengthContext) const;
+    float calculateAlignmentBaselineShift(bool isVerticalText, const RenderObject* textRenderer) const;
+    float calculateGlyphOrientationAngle(bool isVerticalText, const SVGRenderStyle*, const UChar& character) const;
+    float calculateGlyphAdvanceAndOrientation(bool isVerticalText, SVGTextMetrics&, float angle, float& xOrientationShift, float& yOrientationShift) const;
+
+private:
+    EAlignmentBaseline dominantBaselineToAlignmentBaseline(bool isVerticalText, const RenderObject* textRenderer) const;
+
+    const Font& m_font;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
+#endif
diff --git a/Source/core/rendering/svg/SVGTextLayoutEngineSpacing.cpp b/Source/core/rendering/svg/SVGTextLayoutEngineSpacing.cpp
new file mode 100644
index 0000000..80fc39c
--- /dev/null
+++ b/Source/core/rendering/svg/SVGTextLayoutEngineSpacing.cpp
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) Research In Motion Limited 2010. 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"
+
+#if ENABLE(SVG)
+#include "core/rendering/svg/SVGTextLayoutEngineSpacing.h"
+
+#include "core/platform/graphics/Font.h"
+#include "core/rendering/style/SVGRenderStyle.h"
+#include "core/svg/SVGLengthContext.h"
+
+#if ENABLE(SVG_FONTS)
+#include "core/svg/SVGFontData.h"
+#include "core/svg/SVGFontElement.h"
+#include "core/svg/SVGFontFaceElement.h"
+#else
+#include <wtf/UnusedParam.h>
+#endif
+
+namespace WebCore {
+
+SVGTextLayoutEngineSpacing::SVGTextLayoutEngineSpacing(const Font& font)
+    : m_font(font)
+    , m_lastCharacter(0)
+{
+}
+
+float SVGTextLayoutEngineSpacing::calculateSVGKerning(bool isVerticalText, const SVGTextMetrics::Glyph& currentGlyph)
+{
+#if ENABLE(SVG_FONTS)
+    const SimpleFontData* fontData = m_font.primaryFont();
+    if (!fontData->isSVGFont()) {
+        m_lastGlyph.isValid = false;
+        return 0;
+    }
+
+    ASSERT(fontData->isCustomFont());
+    ASSERT(fontData->isSVGFont());
+
+    const SVGFontData* svgFontData = static_cast<const SVGFontData*>(fontData->fontData());
+    SVGFontFaceElement* svgFontFace = svgFontData->svgFontFaceElement();
+    ASSERT(svgFontFace);
+
+    SVGFontElement* svgFont = svgFontFace->associatedFontElement();
+    if (!svgFont) {
+        m_lastGlyph.isValid = false;
+        return 0;
+    }
+
+    float kerning = 0;
+    if (m_lastGlyph.isValid) {
+        if (isVerticalText)
+            kerning = svgFont->verticalKerningForPairOfStringsAndGlyphs(m_lastGlyph.unicodeString, m_lastGlyph.name, currentGlyph.unicodeString, currentGlyph.name);
+        else
+            kerning = svgFont->horizontalKerningForPairOfStringsAndGlyphs(m_lastGlyph.unicodeString, m_lastGlyph.name, currentGlyph.unicodeString, currentGlyph.name);
+    }
+
+    m_lastGlyph = currentGlyph;
+    m_lastGlyph.isValid = true;
+    kerning *= m_font.size() / m_font.fontMetrics().unitsPerEm();
+    return kerning;
+#else
+    UNUSED_PARAM(isVerticalText);
+    UNUSED_PARAM(currentGlyph);
+    return false;
+#endif
+}
+
+float SVGTextLayoutEngineSpacing::calculateCSSKerningAndSpacing(const SVGRenderStyle* style, SVGElement* contextElement, const UChar* currentCharacter)
+{
+    float kerning = 0;
+    SVGLength kerningLength = style->kerning();
+    if (kerningLength.unitType() == LengthTypePercentage)
+        kerning = kerningLength.valueAsPercentage() * m_font.pixelSize();
+    else {
+        SVGLengthContext lengthContext(contextElement);
+        kerning = kerningLength.value(lengthContext);
+    }
+
+    const UChar* lastCharacter = m_lastCharacter;
+    m_lastCharacter = currentCharacter;
+
+    if (!kerning && !m_font.letterSpacing() && !m_font.wordSpacing())
+        return 0;
+
+    float spacing = m_font.letterSpacing() + kerning;
+    if (currentCharacter && lastCharacter && m_font.wordSpacing()) {
+        if (Font::treatAsSpace(*currentCharacter) && !Font::treatAsSpace(*lastCharacter))
+            spacing += m_font.wordSpacing();
+    }
+
+    return spacing;
+}
+
+}
+
+#endif // ENABLE(SVG)
diff --git a/Source/core/rendering/svg/SVGTextLayoutEngineSpacing.h b/Source/core/rendering/svg/SVGTextLayoutEngineSpacing.h
new file mode 100644
index 0000000..da3bd32
--- /dev/null
+++ b/Source/core/rendering/svg/SVGTextLayoutEngineSpacing.h
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) Research In Motion Limited 2010. 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 SVGTextLayoutEngineSpacing_h
+#define SVGTextLayoutEngineSpacing_h
+
+#if ENABLE(SVG)
+#include "core/rendering/svg/SVGTextMetrics.h"
+
+namespace WebCore {
+
+class Font;
+class SVGRenderStyle;
+class SVGElement;
+
+// Helper class used by SVGTextLayoutEngine to handle 'kerning' / 'letter-spacing' and 'word-spacing'.
+class SVGTextLayoutEngineSpacing {
+    WTF_MAKE_NONCOPYABLE(SVGTextLayoutEngineSpacing);
+public:
+    SVGTextLayoutEngineSpacing(const Font&);
+
+    float calculateSVGKerning(bool isVerticalText, const SVGTextMetrics::Glyph& currentGlyph);
+    float calculateCSSKerningAndSpacing(const SVGRenderStyle*, SVGElement* lengthContext, const UChar* currentCharacter);
+
+private:
+    const Font& m_font;
+    const UChar* m_lastCharacter;
+
+#if ENABLE(SVG_FONTS)
+    SVGTextMetrics::Glyph m_lastGlyph;
+#endif
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
+#endif
diff --git a/Source/core/rendering/svg/SVGTextMetrics.cpp b/Source/core/rendering/svg/SVGTextMetrics.cpp
new file mode 100644
index 0000000..fb97eb4
--- /dev/null
+++ b/Source/core/rendering/svg/SVGTextMetrics.cpp
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) Research In Motion Limited 2010-2012. 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"
+
+#if ENABLE(SVG)
+#include "core/rendering/svg/SVGTextMetrics.h"
+
+#include "core/platform/graphics/WidthIterator.h"
+#include "core/rendering/svg/RenderSVGInlineText.h"
+#include "core/rendering/svg/SVGTextRunRenderingContext.h"
+
+namespace WebCore {
+
+SVGTextMetrics::SVGTextMetrics()
+    : m_width(0)
+    , m_height(0)
+    , m_length(0)
+{
+}
+
+SVGTextMetrics::SVGTextMetrics(SVGTextMetrics::MetricsType)
+    : m_width(0)
+    , m_height(0)
+    , m_length(1)
+{
+}
+
+SVGTextMetrics::SVGTextMetrics(RenderSVGInlineText* textRenderer, const TextRun& run)
+{
+    ASSERT(textRenderer);
+
+    float scalingFactor = textRenderer->scalingFactor();
+    ASSERT(scalingFactor);
+
+    const Font& scaledFont = textRenderer->scaledFont();
+    int length = 0;
+
+    // Calculate width/height using the scaled font, divide this result by the scalingFactor afterwards.
+    m_width = scaledFont.width(run, length, m_glyph.name) / scalingFactor;
+    m_height = scaledFont.fontMetrics().floatHeight() / scalingFactor;
+
+    m_glyph.unicodeString = run.is8Bit() ? String(run.characters8(), length) : String(run.characters16(), length);
+    m_glyph.isValid = true;
+
+    ASSERT(length >= 0);
+    m_length = static_cast<unsigned>(length);
+}
+
+TextRun SVGTextMetrics::constructTextRun(RenderSVGInlineText* text, const UChar* characters, unsigned position, unsigned length)
+{
+    RenderStyle* style = text->style();
+    ASSERT(style);
+
+    TextRun run(characters + position
+                , length
+                , 0 /* xPos, only relevant with allowTabs=true */
+                , 0 /* padding, only relevant for justified text, not relevant for SVG */
+                , TextRun::AllowTrailingExpansion
+                , style->direction()
+                , isOverride(style->unicodeBidi()) /* directionalOverride */);
+
+    if (textRunNeedsRenderingContext(style->font()))
+        run.setRenderingContext(SVGTextRunRenderingContext::create(text));
+
+    run.disableRoundingHacks();
+
+    // We handle letter & word spacing ourselves.
+    run.disableSpacing();
+
+    // Propagate the maximum length of the characters buffer to the TextRun, even when we're only processing a substring.
+    run.setCharactersLength(text->textLength() - position);
+    ASSERT(run.charactersLength() >= run.length());
+    return run;
+}
+
+SVGTextMetrics SVGTextMetrics::measureCharacterRange(RenderSVGInlineText* text, unsigned position, unsigned length)
+{
+    ASSERT(text);
+    return SVGTextMetrics(text, constructTextRun(text, text->characters(), position, length));
+}
+
+SVGTextMetrics::SVGTextMetrics(RenderSVGInlineText* text, unsigned position, unsigned length, float width, const String& glyphName)
+{
+    ASSERT(text);
+
+    bool needsContext = textRunNeedsRenderingContext(text->style()->font());
+    float scalingFactor = text->scalingFactor();
+    ASSERT(scalingFactor);
+
+    m_width = width / scalingFactor;
+    m_height = text->scaledFont().fontMetrics().floatHeight() / scalingFactor;
+    if (needsContext) {
+        m_glyph.isValid = true;
+        m_glyph.unicodeString = String(text->characters() + position, length);
+        m_glyph.name = glyphName;
+    }
+
+    m_length = length;
+}
+
+}
+
+#endif // ENABLE(SVG)
diff --git a/Source/core/rendering/svg/SVGTextMetrics.h b/Source/core/rendering/svg/SVGTextMetrics.h
new file mode 100644
index 0000000..ba008c0
--- /dev/null
+++ b/Source/core/rendering/svg/SVGTextMetrics.h
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) Research In Motion Limited 2010-2012. 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 SVGTextMetrics_h
+#define SVGTextMetrics_h
+
+#if ENABLE(SVG)
+#include <wtf/text/WTFString.h>
+
+namespace WebCore {
+
+class RenderSVGInlineText;
+class SVGTextLayoutAttributes;
+class TextRun;
+
+class SVGTextMetrics {
+public:
+    enum MetricsType {
+        SkippedSpaceMetrics
+    };
+
+    SVGTextMetrics();
+    SVGTextMetrics(MetricsType);
+    SVGTextMetrics(RenderSVGInlineText*, unsigned position, unsigned length, float width, const String& glyphName);
+
+    static SVGTextMetrics measureCharacterRange(RenderSVGInlineText*, unsigned position, unsigned length);
+    static TextRun constructTextRun(RenderSVGInlineText*, const UChar* characters, unsigned position, unsigned length);
+
+    bool isEmpty() const { return !m_width && !m_height && !m_glyph.isValid && m_length == 1; }
+
+    float width() const { return m_width; }
+    void setWidth(float width) { m_width = width; }
+
+    float height() const { return m_height; }
+    unsigned length() const { return m_length; }
+
+    struct Glyph {
+        Glyph()
+            : isValid(false)
+        {
+        }
+
+        bool operator==(const Glyph& other)
+        {
+            return isValid == other.isValid
+                && name == other.name
+                && unicodeString == other.unicodeString;
+        }
+
+        bool isValid;
+        String name;
+        String unicodeString;
+    };
+
+    // Only useful when measuring individual characters, to lookup ligatures.
+    const Glyph& glyph() const { return m_glyph; }
+
+private:
+    SVGTextMetrics(RenderSVGInlineText*, const TextRun&);
+
+    float m_width;
+    float m_height;
+    unsigned m_length;
+    Glyph m_glyph;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
+#endif
diff --git a/Source/core/rendering/svg/SVGTextMetricsBuilder.cpp b/Source/core/rendering/svg/SVGTextMetricsBuilder.cpp
new file mode 100644
index 0000000..fa1d20b
--- /dev/null
+++ b/Source/core/rendering/svg/SVGTextMetricsBuilder.cpp
@@ -0,0 +1,227 @@
+/*
+ * Copyright (C) Research In Motion Limited 2010-2012. 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"
+
+#if ENABLE(SVG)
+#include "core/rendering/svg/SVGTextMetricsBuilder.h"
+
+#include "core/rendering/svg/RenderSVGInlineText.h"
+#include "core/rendering/svg/RenderSVGText.h"
+#include "core/rendering/svg/SVGTextRunRenderingContext.h"
+
+namespace WebCore {
+
+SVGTextMetricsBuilder::SVGTextMetricsBuilder()
+    : m_text(0)
+    , m_run(static_cast<const UChar*>(0), 0)
+    , m_textPosition(0)
+    , m_isComplexText(false)
+    , m_totalWidth(0)
+{
+}
+
+inline bool SVGTextMetricsBuilder::currentCharacterStartsSurrogatePair() const
+{
+    return U16_IS_LEAD(m_run[m_textPosition]) && int(m_textPosition + 1) < m_run.charactersLength() && U16_IS_TRAIL(m_run[m_textPosition + 1]);
+}
+
+bool SVGTextMetricsBuilder::advance()
+{
+    m_textPosition += m_currentMetrics.length();
+    if (int(m_textPosition) >= m_run.charactersLength())
+        return false;
+
+    if (m_isComplexText)
+        advanceComplexText();
+    else
+        advanceSimpleText();
+
+    return m_currentMetrics.length() > 0;
+}
+
+void SVGTextMetricsBuilder::advanceSimpleText()
+{
+    GlyphBuffer glyphBuffer;
+    unsigned metricsLength = m_simpleWidthIterator->advance(m_textPosition + 1, &glyphBuffer);
+    if (!metricsLength) {
+        m_currentMetrics = SVGTextMetrics();
+        return;
+    }
+
+    float currentWidth = m_simpleWidthIterator->runWidthSoFar() - m_totalWidth;
+    m_totalWidth = m_simpleWidthIterator->runWidthSoFar();
+
+#if ENABLE(SVG_FONTS)
+    m_currentMetrics = SVGTextMetrics(m_text, m_textPosition, metricsLength, currentWidth, m_simpleWidthIterator->lastGlyphName());
+#else
+    m_currentMetrics = SVGTextMetrics(m_text, m_textPosition, metricsLength, currentWidth, emptyString());
+#endif
+}
+
+void SVGTextMetricsBuilder::advanceComplexText()
+{
+    unsigned metricsLength = currentCharacterStartsSurrogatePair() ? 2 : 1;
+    m_currentMetrics = SVGTextMetrics::measureCharacterRange(m_text, m_textPosition, metricsLength);
+    m_complexStartToCurrentMetrics = SVGTextMetrics::measureCharacterRange(m_text, 0, m_textPosition + metricsLength);
+    ASSERT(m_currentMetrics.length() == metricsLength);
+
+    // Frequent case for Arabic text: when measuring a single character the arabic isolated form is taken
+    // when rendering the glyph "in context" (with it's surrounding characters) it changes due to shaping.
+    // So whenever currentWidth != currentMetrics.width(), we are processing a text run whose length is
+    // not equal to the sum of the individual lengths of the glyphs, when measuring them isolated.
+    float currentWidth = m_complexStartToCurrentMetrics.width() - m_totalWidth;
+    if (currentWidth != m_currentMetrics.width())
+        m_currentMetrics.setWidth(currentWidth);
+
+    m_totalWidth = m_complexStartToCurrentMetrics.width();
+}
+
+void SVGTextMetricsBuilder::initializeMeasurementWithTextRenderer(RenderSVGInlineText* text)
+{
+    m_text = text;
+    m_textPosition = 0;
+    m_currentMetrics = SVGTextMetrics();
+    m_complexStartToCurrentMetrics = SVGTextMetrics();
+    m_totalWidth = 0;
+
+    const Font& scaledFont = text->scaledFont();
+    m_run = SVGTextMetrics::constructTextRun(text, text->characters(), 0, text->textLength());
+    m_isComplexText = scaledFont.codePath(m_run) == Font::Complex;
+
+    if (m_isComplexText)
+        m_simpleWidthIterator.clear();
+    else
+        m_simpleWidthIterator = adoptPtr(new WidthIterator(&scaledFont, m_run));
+}
+
+struct MeasureTextData {
+    MeasureTextData(SVGCharacterDataMap* characterDataMap)
+        : allCharactersMap(characterDataMap)
+        , lastCharacter(0)
+        , processRenderer(false)
+        , valueListPosition(0)
+        , skippedCharacters(0)
+    {
+    }
+
+    SVGCharacterDataMap* allCharactersMap;
+    const UChar* lastCharacter;
+    bool processRenderer;
+    unsigned valueListPosition;
+    unsigned skippedCharacters;
+};
+
+void SVGTextMetricsBuilder::measureTextRenderer(RenderSVGInlineText* text, MeasureTextData* data)
+{
+    ASSERT(text);
+
+    SVGTextLayoutAttributes* attributes = text->layoutAttributes();
+    Vector<SVGTextMetrics>* textMetricsValues = &attributes->textMetricsValues();
+    if (data->processRenderer) {
+        if (data->allCharactersMap)
+            attributes->clear();
+        else
+            textMetricsValues->clear();
+    }
+
+    initializeMeasurementWithTextRenderer(text);
+    bool preserveWhiteSpace = text->style()->whiteSpace() == PRE;
+    int surrogatePairCharacters = 0;
+
+    while (advance()) {
+        const UChar* currentCharacter = m_run.data16(m_textPosition);
+        if (*currentCharacter == ' ' && !preserveWhiteSpace && (!data->lastCharacter || *data->lastCharacter == ' ')) {
+            if (data->processRenderer)
+                textMetricsValues->append(SVGTextMetrics(SVGTextMetrics::SkippedSpaceMetrics));
+            if (data->allCharactersMap)
+                data->skippedCharacters += m_currentMetrics.length();
+            continue;
+        }
+
+        if (data->processRenderer) {
+            if (data->allCharactersMap) {
+                const SVGCharacterDataMap::const_iterator it = data->allCharactersMap->find(data->valueListPosition + m_textPosition - data->skippedCharacters - surrogatePairCharacters + 1);
+                if (it != data->allCharactersMap->end())
+                    attributes->characterDataMap().set(m_textPosition + 1, it->value);
+            }
+            textMetricsValues->append(m_currentMetrics);
+        }
+
+        if (data->allCharactersMap && currentCharacterStartsSurrogatePair())
+            surrogatePairCharacters++;
+
+        data->lastCharacter = currentCharacter;
+    }
+
+    if (!data->allCharactersMap)
+        return;
+
+    data->valueListPosition += m_textPosition - data->skippedCharacters;
+    data->skippedCharacters = 0;
+}
+
+void SVGTextMetricsBuilder::walkTree(RenderObject* start, RenderSVGInlineText* stopAtLeaf, MeasureTextData* data)
+{
+    for (RenderObject* child = start->firstChild(); child; child = child->nextSibling()) {
+        if (child->isSVGInlineText()) {
+            RenderSVGInlineText* text = toRenderSVGInlineText(child);
+            if (stopAtLeaf && stopAtLeaf != text) {
+                data->processRenderer = false;
+                measureTextRenderer(text, data);
+                continue;
+            }
+
+            data->processRenderer = true;
+            measureTextRenderer(text, data);
+            if (stopAtLeaf)
+                return;
+
+            continue;
+        }
+
+        if (!child->isSVGInline())
+            continue;
+
+        walkTree(child, stopAtLeaf, data);
+    }
+}
+
+void SVGTextMetricsBuilder::measureTextRenderer(RenderSVGInlineText* text)
+{
+    ASSERT(text);
+
+    RenderSVGText* textRoot = RenderSVGText::locateRenderSVGTextAncestor(text);
+    if (!textRoot)
+        return;
+
+    MeasureTextData data(0);
+    walkTree(textRoot, text, &data);
+}
+
+void SVGTextMetricsBuilder::buildMetricsAndLayoutAttributes(RenderSVGText* textRoot, RenderSVGInlineText* stopAtLeaf, SVGCharacterDataMap& allCharactersMap)
+{
+    ASSERT(textRoot);
+    MeasureTextData data(&allCharactersMap);
+    walkTree(textRoot, stopAtLeaf, &data);
+}
+
+}
+
+#endif // ENABLE(SVG)
diff --git a/Source/core/rendering/svg/SVGTextMetricsBuilder.h b/Source/core/rendering/svg/SVGTextMetricsBuilder.h
new file mode 100644
index 0000000..bd45b07
--- /dev/null
+++ b/Source/core/rendering/svg/SVGTextMetricsBuilder.h
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) Research In Motion Limited 2010-2012. 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 SVGTextMetricsBuilder_h
+#define SVGTextMetricsBuilder_h
+
+#if ENABLE(SVG)
+#include "core/platform/graphics/TextRun.h"
+#include "core/platform/graphics/WidthIterator.h"
+#include "core/rendering/svg/SVGTextLayoutAttributes.h"
+#include "core/rendering/svg/SVGTextMetrics.h"
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class RenderObject;
+class RenderSVGInlineText;
+class RenderSVGText;
+struct MeasureTextData;
+
+class SVGTextMetricsBuilder {
+    WTF_MAKE_NONCOPYABLE(SVGTextMetricsBuilder);
+public:
+    SVGTextMetricsBuilder();
+    void measureTextRenderer(RenderSVGInlineText*);
+    void buildMetricsAndLayoutAttributes(RenderSVGText*, RenderSVGInlineText* stopAtLeaf, SVGCharacterDataMap& allCharactersMap);
+
+private:
+    bool advance();
+    void advanceSimpleText();
+    void advanceComplexText();
+    bool currentCharacterStartsSurrogatePair() const;
+
+    void initializeMeasurementWithTextRenderer(RenderSVGInlineText*);
+    void walkTree(RenderObject*, RenderSVGInlineText* stopAtLeaf, MeasureTextData*);
+    void measureTextRenderer(RenderSVGInlineText*, MeasureTextData*);
+
+    RenderSVGInlineText* m_text;
+    TextRun m_run;
+    unsigned m_textPosition;
+    bool m_isComplexText;
+    SVGTextMetrics m_currentMetrics;
+    float m_totalWidth;
+
+    // Simple text only.
+    OwnPtr<WidthIterator> m_simpleWidthIterator;
+
+    // Complex text only.
+    SVGTextMetrics m_complexStartToCurrentMetrics;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(SVG)
+#endif
diff --git a/Source/core/rendering/svg/SVGTextQuery.cpp b/Source/core/rendering/svg/SVGTextQuery.cpp
new file mode 100644
index 0000000..3213db5
--- /dev/null
+++ b/Source/core/rendering/svg/SVGTextQuery.cpp
@@ -0,0 +1,560 @@
+/*
+ * Copyright (C) Research In Motion Limited 2010-2012. 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 "core/rendering/svg/SVGTextQuery.h"
+
+#if ENABLE(SVG)
+#include "core/editing/VisiblePosition.h"
+#include "core/platform/FloatConversion.h"
+#include "core/rendering/InlineFlowBox.h"
+#include "core/rendering/RenderBlock.h"
+#include "core/rendering/RenderInline.h"
+#include "core/rendering/svg/RenderSVGInlineText.h"
+#include "core/rendering/svg/SVGInlineTextBox.h"
+#include "core/rendering/svg/SVGTextMetrics.h"
+
+#include <wtf/MathExtras.h>
+
+namespace WebCore {
+
+// Base structure for callback user data
+struct SVGTextQuery::Data {
+    Data()
+        : isVerticalText(false)
+        , processedCharacters(0)
+        , textRenderer(0)
+        , textBox(0)
+    {
+    }
+
+    bool isVerticalText;
+    unsigned processedCharacters;
+    RenderSVGInlineText* textRenderer;
+    const SVGInlineTextBox* textBox;
+};
+
+static inline InlineFlowBox* flowBoxForRenderer(RenderObject* renderer)
+{
+    if (!renderer)
+        return 0;
+
+    if (renderer->isRenderBlock()) {
+        // If we're given a block element, it has to be a RenderSVGText.
+        ASSERT(renderer->isSVGText());
+        RenderBlock* renderBlock = toRenderBlock(renderer);
+
+        // RenderSVGText only ever contains a single line box.
+        InlineFlowBox* flowBox = renderBlock->firstLineBox();
+        ASSERT(flowBox == renderBlock->lastLineBox());
+        return flowBox;
+    }
+
+    if (renderer->isRenderInline()) {
+        // We're given a RenderSVGInline or objects that derive from it (RenderSVGTSpan / RenderSVGTextPath)
+        RenderInline* renderInline = toRenderInline(renderer);
+
+        // RenderSVGInline only ever contains a single line box.
+        InlineFlowBox* flowBox = renderInline->firstLineBox();
+        ASSERT(flowBox == renderInline->lastLineBox());
+        return flowBox;
+    }
+
+    ASSERT_NOT_REACHED();
+    return 0;
+}
+
+SVGTextQuery::SVGTextQuery(RenderObject* renderer)
+{
+    collectTextBoxesInFlowBox(flowBoxForRenderer(renderer));
+}
+
+void SVGTextQuery::collectTextBoxesInFlowBox(InlineFlowBox* flowBox)
+{
+    if (!flowBox)
+        return;
+
+    for (InlineBox* child = flowBox->firstChild(); child; child = child->nextOnLine()) {
+        if (child->isInlineFlowBox()) {
+            // Skip generated content.
+            if (!child->renderer()->node())
+                continue;
+
+            collectTextBoxesInFlowBox(static_cast<InlineFlowBox*>(child));
+            continue;
+        }
+
+        if (child->isSVGInlineTextBox())
+            m_textBoxes.append(static_cast<SVGInlineTextBox*>(child));
+    }
+}
+
+bool SVGTextQuery::executeQuery(Data* queryData, ProcessTextFragmentCallback fragmentCallback) const
+{
+    ASSERT(!m_textBoxes.isEmpty());
+
+    unsigned processedCharacters = 0;
+    unsigned textBoxCount = m_textBoxes.size();
+
+    // Loop over all text boxes
+    for (unsigned textBoxPosition = 0; textBoxPosition < textBoxCount; ++textBoxPosition) {
+        queryData->textBox = m_textBoxes.at(textBoxPosition);
+        queryData->textRenderer = toRenderSVGInlineText(queryData->textBox->textRenderer());
+        ASSERT(queryData->textRenderer);
+        ASSERT(queryData->textRenderer->style());
+        ASSERT(queryData->textRenderer->style()->svgStyle());
+
+        queryData->isVerticalText = queryData->textRenderer->style()->svgStyle()->isVerticalWritingMode();
+        const Vector<SVGTextFragment>& fragments = queryData->textBox->textFragments();
+    
+        // Loop over all text fragments in this text box, firing a callback for each.
+        unsigned fragmentCount = fragments.size();
+        for (unsigned i = 0; i < fragmentCount; ++i) {
+            const SVGTextFragment& fragment = fragments.at(i);
+            if ((this->*fragmentCallback)(queryData, fragment))
+                return true;
+
+            processedCharacters += fragment.length;
+        }
+
+        queryData->processedCharacters = processedCharacters;
+    }
+
+    return false;
+}
+
+bool SVGTextQuery::mapStartEndPositionsIntoFragmentCoordinates(Data* queryData, const SVGTextFragment& fragment, int& startPosition, int& endPosition) const
+{
+    // Reuse the same logic used for text selection & painting, to map our query start/length into start/endPositions of the current text fragment.
+    startPosition -= queryData->processedCharacters;
+    endPosition -= queryData->processedCharacters;
+
+    if (startPosition >= endPosition || startPosition < 0 || endPosition < 0)
+        return false;
+
+    modifyStartEndPositionsRespectingLigatures(queryData, startPosition, endPosition);
+    if (!queryData->textBox->mapStartEndPositionsIntoFragmentCoordinates(fragment, startPosition, endPosition))
+        return false;
+
+    ASSERT(startPosition < endPosition);
+    return true;
+}
+
+void SVGTextQuery::modifyStartEndPositionsRespectingLigatures(Data* queryData, int& startPosition, int& endPosition) const
+{
+    SVGTextLayoutAttributes* layoutAttributes = queryData->textRenderer->layoutAttributes();
+    Vector<SVGTextMetrics>& textMetricsValues = layoutAttributes->textMetricsValues();
+    unsigned boxStart = queryData->textBox->start();
+    unsigned boxLength = queryData->textBox->len();
+
+    unsigned textMetricsOffset = 0;
+    unsigned textMetricsSize = textMetricsValues.size();
+
+    unsigned positionOffset = 0;
+    unsigned positionSize = layoutAttributes->context()->textLength();
+
+    bool alterStartPosition = true;
+    bool alterEndPosition = true;
+
+    int lastPositionOffset = -1;
+    for (; textMetricsOffset < textMetricsSize && positionOffset < positionSize; ++textMetricsOffset) {
+        SVGTextMetrics& metrics = textMetricsValues[textMetricsOffset];
+
+        // Advance to text box start location.
+        if (positionOffset < boxStart) {
+            positionOffset += metrics.length();
+            continue;
+        }
+
+        // Stop if we've finished processing this text box.
+        if (positionOffset >= boxStart + boxLength)
+            break;
+
+        // If the start position maps to a character in the metrics list, we don't need to modify it.
+        if (startPosition == static_cast<int>(positionOffset))
+            alterStartPosition = false;
+
+        // If the start position maps to a character in the metrics list, we don't need to modify it.
+        if (endPosition == static_cast<int>(positionOffset))
+            alterEndPosition = false;
+
+        // Detect ligatures.
+        if (lastPositionOffset != -1 && lastPositionOffset - positionOffset > 1) {
+            if (alterStartPosition && startPosition > lastPositionOffset && startPosition < static_cast<int>(positionOffset)) {
+                startPosition = lastPositionOffset;
+                alterStartPosition = false;
+            }
+
+            if (alterEndPosition && endPosition > lastPositionOffset && endPosition < static_cast<int>(positionOffset)) {
+                endPosition = positionOffset;
+                alterEndPosition = false;
+            }
+        }
+
+        if (!alterStartPosition && !alterEndPosition)
+            break;
+
+        lastPositionOffset = positionOffset;
+        positionOffset += metrics.length();
+    }
+
+    if (!alterStartPosition && !alterEndPosition)
+        return;
+
+    if (lastPositionOffset != -1 && lastPositionOffset - positionOffset > 1) {
+        if (alterStartPosition && startPosition > lastPositionOffset && startPosition < static_cast<int>(positionOffset)) {
+            startPosition = lastPositionOffset;
+            alterStartPosition = false;
+        }
+
+        if (alterEndPosition && endPosition > lastPositionOffset && endPosition < static_cast<int>(positionOffset)) {
+            endPosition = positionOffset;
+            alterEndPosition = false;
+        }
+    }
+}
+
+// numberOfCharacters() implementation
+bool SVGTextQuery::numberOfCharactersCallback(Data*, const SVGTextFragment&) const
+{
+    // no-op
+    return false;
+}
+
+unsigned SVGTextQuery::numberOfCharacters() const
+{
+    if (m_textBoxes.isEmpty())
+        return 0;
+
+    Data data;
+    executeQuery(&data, &SVGTextQuery::numberOfCharactersCallback);
+    return data.processedCharacters;
+}
+
+// textLength() implementation
+struct TextLengthData : SVGTextQuery::Data {
+    TextLengthData()
+        : textLength(0)
+    {
+    }
+
+    float textLength;
+};
+
+bool SVGTextQuery::textLengthCallback(Data* queryData, const SVGTextFragment& fragment) const
+{
+    TextLengthData* data = static_cast<TextLengthData*>(queryData);
+    data->textLength += queryData->isVerticalText ? fragment.height : fragment.width;
+    return false;
+}
+
+float SVGTextQuery::textLength() const
+{
+    if (m_textBoxes.isEmpty())
+        return 0;
+
+    TextLengthData data;
+    executeQuery(&data, &SVGTextQuery::textLengthCallback);
+    return data.textLength;
+}
+
+// subStringLength() implementation
+struct SubStringLengthData : SVGTextQuery::Data {
+    SubStringLengthData(unsigned queryStartPosition, unsigned queryLength)
+        : startPosition(queryStartPosition)
+        , length(queryLength)
+        , subStringLength(0)
+    {
+    }
+
+    unsigned startPosition;
+    unsigned length;
+
+    float subStringLength;
+};
+
+bool SVGTextQuery::subStringLengthCallback(Data* queryData, const SVGTextFragment& fragment) const
+{
+    SubStringLengthData* data = static_cast<SubStringLengthData*>(queryData);
+
+    int startPosition = data->startPosition;
+    int endPosition = startPosition + data->length;
+    if (!mapStartEndPositionsIntoFragmentCoordinates(queryData, fragment, startPosition, endPosition))
+        return false;
+
+    SVGTextMetrics metrics = SVGTextMetrics::measureCharacterRange(queryData->textRenderer, fragment.characterOffset + startPosition, endPosition - startPosition);
+    data->subStringLength += queryData->isVerticalText ? metrics.height() : metrics.width();
+    return false;
+}
+
+float SVGTextQuery::subStringLength(unsigned startPosition, unsigned length) const
+{
+    if (m_textBoxes.isEmpty())
+        return 0;
+
+    SubStringLengthData data(startPosition, length);
+    executeQuery(&data, &SVGTextQuery::subStringLengthCallback);
+    return data.subStringLength;
+}
+
+// startPositionOfCharacter() implementation
+struct StartPositionOfCharacterData : SVGTextQuery::Data {
+    StartPositionOfCharacterData(unsigned queryPosition)
+        : position(queryPosition)
+    {
+    }
+
+    unsigned position;
+    FloatPoint startPosition;
+};
+
+bool SVGTextQuery::startPositionOfCharacterCallback(Data* queryData, const SVGTextFragment& fragment) const
+{
+    StartPositionOfCharacterData* data = static_cast<StartPositionOfCharacterData*>(queryData);
+
+    int startPosition = data->position;
+    int endPosition = startPosition + 1;
+    if (!mapStartEndPositionsIntoFragmentCoordinates(queryData, fragment, startPosition, endPosition))
+        return false;
+
+    data->startPosition = FloatPoint(fragment.x, fragment.y);
+
+    if (startPosition) {
+        SVGTextMetrics metrics = SVGTextMetrics::measureCharacterRange(queryData->textRenderer, fragment.characterOffset, startPosition);
+        if (queryData->isVerticalText)
+            data->startPosition.move(0, metrics.height());
+        else
+            data->startPosition.move(metrics.width(), 0);
+    }
+
+    AffineTransform fragmentTransform;
+    fragment.buildFragmentTransform(fragmentTransform, SVGTextFragment::TransformIgnoringTextLength);
+    if (fragmentTransform.isIdentity())
+        return true;
+
+    data->startPosition = fragmentTransform.mapPoint(data->startPosition);
+    return true;
+}
+
+FloatPoint SVGTextQuery::startPositionOfCharacter(unsigned position) const
+{
+    if (m_textBoxes.isEmpty())
+        return FloatPoint();
+
+    StartPositionOfCharacterData data(position);
+    executeQuery(&data, &SVGTextQuery::startPositionOfCharacterCallback);
+    return data.startPosition;
+}
+
+// endPositionOfCharacter() implementation
+struct EndPositionOfCharacterData : SVGTextQuery::Data {
+    EndPositionOfCharacterData(unsigned queryPosition)
+        : position(queryPosition)
+    {
+    }
+
+    unsigned position;
+    FloatPoint endPosition;
+};
+
+bool SVGTextQuery::endPositionOfCharacterCallback(Data* queryData, const SVGTextFragment& fragment) const
+{
+    EndPositionOfCharacterData* data = static_cast<EndPositionOfCharacterData*>(queryData);
+
+    int startPosition = data->position;
+    int endPosition = startPosition + 1;
+    if (!mapStartEndPositionsIntoFragmentCoordinates(queryData, fragment, startPosition, endPosition))
+        return false;
+
+    data->endPosition = FloatPoint(fragment.x, fragment.y);
+
+    SVGTextMetrics metrics = SVGTextMetrics::measureCharacterRange(queryData->textRenderer, fragment.characterOffset, startPosition + 1);
+    if (queryData->isVerticalText)
+        data->endPosition.move(0, metrics.height());
+    else
+        data->endPosition.move(metrics.width(), 0);
+
+    AffineTransform fragmentTransform;
+    fragment.buildFragmentTransform(fragmentTransform, SVGTextFragment::TransformIgnoringTextLength);
+    if (fragmentTransform.isIdentity())
+        return true;
+
+    data->endPosition = fragmentTransform.mapPoint(data->endPosition);
+    return true;
+}
+
+FloatPoint SVGTextQuery::endPositionOfCharacter(unsigned position) const
+{
+    if (m_textBoxes.isEmpty())
+        return FloatPoint();
+
+    EndPositionOfCharacterData data(position);
+    executeQuery(&data, &SVGTextQuery::endPositionOfCharacterCallback);
+    return data.endPosition;
+}
+
+// rotationOfCharacter() implementation
+struct RotationOfCharacterData : SVGTextQuery::Data {
+    RotationOfCharacterData(unsigned queryPosition)
+        : position(queryPosition)
+        , rotation(0)
+    {
+    }
+
+    unsigned position;
+    float rotation;
+};
+
+bool SVGTextQuery::rotationOfCharacterCallback(Data* queryData, const SVGTextFragment& fragment) const
+{
+    RotationOfCharacterData* data = static_cast<RotationOfCharacterData*>(queryData);
+
+    int startPosition = data->position;
+    int endPosition = startPosition + 1;
+    if (!mapStartEndPositionsIntoFragmentCoordinates(queryData, fragment, startPosition, endPosition))
+        return false;
+
+    AffineTransform fragmentTransform;
+    fragment.buildFragmentTransform(fragmentTransform, SVGTextFragment::TransformIgnoringTextLength);
+    if (fragmentTransform.isIdentity())
+        data->rotation = 0;
+    else {
+        fragmentTransform.scale(1 / fragmentTransform.xScale(), 1 / fragmentTransform.yScale());
+        data->rotation = narrowPrecisionToFloat(rad2deg(atan2(fragmentTransform.b(), fragmentTransform.a())));
+    }
+
+    return true;
+}
+
+float SVGTextQuery::rotationOfCharacter(unsigned position) const
+{
+    if (m_textBoxes.isEmpty())
+        return 0;
+
+    RotationOfCharacterData data(position);
+    executeQuery(&data, &SVGTextQuery::rotationOfCharacterCallback);
+    return data.rotation;
+}
+
+// extentOfCharacter() implementation
+struct ExtentOfCharacterData : SVGTextQuery::Data {
+    ExtentOfCharacterData(unsigned queryPosition)
+        : position(queryPosition)
+    {
+    }
+
+    unsigned position;
+    FloatRect extent;
+};
+
+static inline void calculateGlyphBoundaries(SVGTextQuery::Data* queryData, const SVGTextFragment& fragment, int startPosition, FloatRect& extent)
+{
+    float scalingFactor = queryData->textRenderer->scalingFactor();
+    ASSERT(scalingFactor);
+
+    extent.setLocation(FloatPoint(fragment.x, fragment.y - queryData->textRenderer->scaledFont().fontMetrics().floatAscent() / scalingFactor));
+
+    if (startPosition) {
+        SVGTextMetrics metrics = SVGTextMetrics::measureCharacterRange(queryData->textRenderer, fragment.characterOffset, startPosition);
+        if (queryData->isVerticalText)
+            extent.move(0, metrics.height());
+        else
+            extent.move(metrics.width(), 0);
+    }
+
+    SVGTextMetrics metrics = SVGTextMetrics::measureCharacterRange(queryData->textRenderer, fragment.characterOffset + startPosition, 1);
+    extent.setSize(FloatSize(metrics.width(), metrics.height()));
+
+    AffineTransform fragmentTransform;
+    fragment.buildFragmentTransform(fragmentTransform, SVGTextFragment::TransformIgnoringTextLength);
+    if (fragmentTransform.isIdentity())
+        return;
+
+    extent = fragmentTransform.mapRect(extent);
+}
+
+bool SVGTextQuery::extentOfCharacterCallback(Data* queryData, const SVGTextFragment& fragment) const
+{
+    ExtentOfCharacterData* data = static_cast<ExtentOfCharacterData*>(queryData);
+
+    int startPosition = data->position;
+    int endPosition = startPosition + 1;
+    if (!mapStartEndPositionsIntoFragmentCoordinates(queryData, fragment, startPosition, endPosition))
+        return false;
+
+    calculateGlyphBoundaries(queryData, fragment, startPosition, data->extent);
+    return true;
+}
+
+FloatRect SVGTextQuery::extentOfCharacter(unsigned position) const
+{
+    if (m_textBoxes.isEmpty())
+        return FloatRect();
+
+    ExtentOfCharacterData data(position);
+    executeQuery(&data, &SVGTextQuery::extentOfCharacterCallback);
+    return data.extent;
+}
+
+// characterNumberAtPosition() implementation
+struct CharacterNumberAtPositionData : SVGTextQuery::Data {
+    CharacterNumberAtPositionData(const FloatPoint& queryPosition)
+        : position(queryPosition)
+    {
+    }
+
+    FloatPoint position;
+};
+
+bool SVGTextQuery::characterNumberAtPositionCallback(Data* queryData, const SVGTextFragment& fragment) const
+{
+    CharacterNumberAtPositionData* data = static_cast<CharacterNumberAtPositionData*>(queryData);
+
+    FloatRect extent;
+    for (unsigned i = 0; i < fragment.length; ++i) {
+        int startPosition = data->processedCharacters + i;
+        int endPosition = startPosition + 1;
+        if (!mapStartEndPositionsIntoFragmentCoordinates(queryData, fragment, startPosition, endPosition))
+            continue;
+
+        calculateGlyphBoundaries(queryData, fragment, startPosition, extent);
+        if (extent.contains(data->position)) {
+            data->processedCharacters += i;
+            return true;
+        }
+    }
+
+    return false;
+}
+
+int SVGTextQuery::characterNumberAtPosition(const FloatPoint& position) const
+{
+    if (m_textBoxes.isEmpty())
+        return -1;
+
+    CharacterNumberAtPositionData data(position);
+    if (!executeQuery(&data, &SVGTextQuery::characterNumberAtPositionCallback))
+        return -1;
+
+    return data.processedCharacters;
+}
+
+}
+
+#endif
diff --git a/Source/core/rendering/svg/SVGTextQuery.h b/Source/core/rendering/svg/SVGTextQuery.h
new file mode 100644
index 0000000..ed6247a
--- /dev/null
+++ b/Source/core/rendering/svg/SVGTextQuery.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) Research In Motion Limited 2010. 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 SVGTextQuery_h
+#define SVGTextQuery_h
+
+#if ENABLE(SVG)
+#include "core/platform/graphics/FloatRect.h"
+#include "core/rendering/svg/SVGTextFragment.h"
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+class InlineFlowBox;
+class RenderObject;
+class SVGInlineTextBox;
+
+class SVGTextQuery {
+public:
+    SVGTextQuery(RenderObject*);
+
+    unsigned numberOfCharacters() const;
+    float textLength() const;
+    float subStringLength(unsigned startPosition, unsigned length) const;
+    FloatPoint startPositionOfCharacter(unsigned position) const;
+    FloatPoint endPositionOfCharacter(unsigned position) const;
+    float rotationOfCharacter(unsigned position) const;
+    FloatRect extentOfCharacter(unsigned position) const;
+    int characterNumberAtPosition(const FloatPoint&) const;
+
+    // Public helper struct. Private classes in SVGTextQuery inherit from it.
+    struct Data;
+
+private:
+    typedef bool (SVGTextQuery::*ProcessTextFragmentCallback)(Data*, const SVGTextFragment&) const;
+    bool executeQuery(Data*, ProcessTextFragmentCallback) const;
+
+    void collectTextBoxesInFlowBox(InlineFlowBox*);
+    bool mapStartEndPositionsIntoFragmentCoordinates(Data*, const SVGTextFragment&, int& startPosition, int& endPosition) const;
+    void modifyStartEndPositionsRespectingLigatures(Data*, int& startPosition, int& endPosition) const;
+
+private:
+    bool numberOfCharactersCallback(Data*, const SVGTextFragment&) const;
+    bool textLengthCallback(Data*, const SVGTextFragment&) const;
+    bool subStringLengthCallback(Data*, const SVGTextFragment&) const;
+    bool startPositionOfCharacterCallback(Data*, const SVGTextFragment&) const;
+    bool endPositionOfCharacterCallback(Data*, const SVGTextFragment&) const;
+    bool rotationOfCharacterCallback(Data*, const SVGTextFragment&) const;
+    bool extentOfCharacterCallback(Data*, const SVGTextFragment&) const;
+    bool characterNumberAtPositionCallback(Data*, const SVGTextFragment&) const;
+
+private:
+    Vector<SVGInlineTextBox*> m_textBoxes;
+};
+
+}
+
+#endif
+#endif
diff --git a/Source/core/rendering/svg/SVGTextRunRenderingContext.cpp b/Source/core/rendering/svg/SVGTextRunRenderingContext.cpp
new file mode 100644
index 0000000..9c962a5
--- /dev/null
+++ b/Source/core/rendering/svg/SVGTextRunRenderingContext.cpp
@@ -0,0 +1,248 @@
+/*
+ * Copyright (C) 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
+ * Copyright (C) Research In Motion Limited 2010-2011. 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"
+
+#if ENABLE(SVG_FONTS)
+#include "core/rendering/svg/SVGTextRunRenderingContext.h"
+
+#include "SVGNames.h"
+#include "core/platform/graphics/Font.h"
+#include "core/platform/graphics/GlyphBuffer.h"
+#include "core/platform/graphics/GraphicsContext.h"
+#include "core/platform/graphics/WidthIterator.h"
+#include "core/rendering/RenderObject.h"
+#include "core/rendering/svg/RenderSVGInlineText.h"
+#include "core/rendering/svg/RenderSVGResourceSolidColor.h"
+#include "core/svg/SVGFontData.h"
+#include "core/svg/SVGFontElement.h"
+#include "core/svg/SVGFontFaceElement.h"
+#include "core/svg/SVGGlyphElement.h"
+
+namespace WebCore {
+
+static inline const SVGFontData* svgFontAndFontFaceElementForFontData(const SimpleFontData* fontData, SVGFontFaceElement*& fontFace, SVGFontElement*& font)
+{
+    ASSERT(fontData);
+    ASSERT(fontData->isCustomFont());
+    ASSERT(fontData->isSVGFont());
+
+    const SVGFontData* svgFontData = static_cast<const SVGFontData*>(fontData->fontData());
+
+    fontFace = svgFontData->svgFontFaceElement();
+    ASSERT(fontFace);
+
+    font = fontFace->associatedFontElement();
+    return svgFontData;
+}
+
+static inline RenderObject* firstParentRendererForNonTextNode(RenderObject* renderer)
+{
+    ASSERT(renderer);
+    return renderer->isText() ? renderer->parent() : renderer;
+}
+
+static inline RenderObject* renderObjectFromRun(const TextRun& run)
+{
+    if (TextRun::RenderingContext* renderingContext = run.renderingContext())
+        return static_cast<SVGTextRunRenderingContext*>(renderingContext)->renderer();
+    return 0;
+}
+
+static inline RenderSVGResource* activePaintingResourceFromRun(const TextRun& run)
+{
+    if (TextRun::RenderingContext* renderingContext = run.renderingContext())
+        return static_cast<SVGTextRunRenderingContext*>(renderingContext)->activePaintingResource();
+    return 0;
+}
+
+float SVGTextRunRenderingContext::floatWidthUsingSVGFont(const Font& font, const TextRun& run, int& charsConsumed, String& glyphName) const
+{
+    WidthIterator it(&font, run);
+    GlyphBuffer glyphBuffer;
+    charsConsumed += it.advance(run.length(), &glyphBuffer);
+    glyphName = it.lastGlyphName();
+    return it.runWidthSoFar();
+}
+ 
+void SVGTextRunRenderingContext::drawSVGGlyphs(GraphicsContext* context, const TextRun& run, const SimpleFontData* fontData, const GlyphBuffer& glyphBuffer, int from, int numGlyphs, const FloatPoint& point) const
+{
+    SVGFontElement* fontElement = 0;
+    SVGFontFaceElement* fontFaceElement = 0;
+
+    const SVGFontData* svgFontData = svgFontAndFontFaceElementForFontData(fontData, fontFaceElement, fontElement);
+    if (!fontElement || !fontFaceElement)
+        return;
+
+    // We can only paint SVGFonts if a context is available.
+    RenderSVGResource* activePaintingResource = activePaintingResourceFromRun(run);
+    RenderObject* renderObject = renderObjectFromRun(run);
+    RenderObject* parentRenderObject = firstParentRendererForNonTextNode(renderObject);
+    RenderStyle* parentRenderObjectStyle = 0;
+
+    ASSERT(renderObject);
+    if (!activePaintingResource) {
+        // TODO: We're only supporting simple filled HTML text so far.
+        RenderSVGResourceSolidColor* solidPaintingResource = RenderSVGResource::sharedSolidPaintingResource();
+        solidPaintingResource->setColor(context->fillColor());
+        activePaintingResource = solidPaintingResource;
+    }
+ 
+    bool isVerticalText = false;
+    if (parentRenderObject) {
+        parentRenderObjectStyle = parentRenderObject->style();
+        ASSERT(parentRenderObjectStyle);
+        isVerticalText = parentRenderObjectStyle->svgStyle()->isVerticalWritingMode();
+    }
+
+    float scale = scaleEmToUnits(fontData->platformData().size(), fontFaceElement->unitsPerEm());
+    ASSERT(activePaintingResource);
+
+    FloatPoint glyphOrigin;
+    glyphOrigin.setX(svgFontData->horizontalOriginX() * scale);
+    glyphOrigin.setY(svgFontData->horizontalOriginY() * scale);
+
+    FloatPoint currentPoint = point;
+    RenderSVGResourceMode resourceMode = context->textDrawingMode() == TextModeStroke ? ApplyToStrokeMode : ApplyToFillMode;
+    for (int i = 0; i < numGlyphs; ++i) {
+        Glyph glyph = glyphBuffer.glyphAt(from + i);
+        if (!glyph)
+            continue;
+
+        float advance = glyphBuffer.advanceAt(from + i);
+        SVGGlyph svgGlyph = fontElement->svgGlyphForGlyph(glyph);
+        ASSERT(!svgGlyph.isPartOfLigature);
+        ASSERT(svgGlyph.tableEntry == glyph);
+
+        SVGGlyphElement::inheritUnspecifiedAttributes(svgGlyph, svgFontData);
+
+        // FIXME: Support arbitary SVG content as glyph (currently limited to <glyph d="..."> situations).
+        if (svgGlyph.pathData.isEmpty()) {
+            if (isVerticalText)
+                currentPoint.move(0, advance);
+            else
+                currentPoint.move(advance, 0);
+            continue;
+         }
+
+        if (isVerticalText) {
+            glyphOrigin.setX(svgGlyph.verticalOriginX * scale);
+            glyphOrigin.setY(svgGlyph.verticalOriginY * scale);
+         }
+
+        AffineTransform glyphPathTransform;
+        glyphPathTransform.translate(currentPoint.x() + glyphOrigin.x(), currentPoint.y() + glyphOrigin.y());
+        glyphPathTransform.scale(scale, -scale);
+
+        Path glyphPath = svgGlyph.pathData;
+        glyphPath.transform(glyphPathTransform);
+
+        if (activePaintingResource->applyResource(parentRenderObject, parentRenderObjectStyle, context, resourceMode)) {
+            float strokeThickness = context->strokeThickness();
+            if (renderObject && renderObject->isSVGInlineText())
+                context->setStrokeThickness(strokeThickness * toRenderSVGInlineText(renderObject)->scalingFactor());
+            activePaintingResource->postApplyResource(parentRenderObject, context, resourceMode, &glyphPath, 0);
+            context->setStrokeThickness(strokeThickness);
+        }
+
+        if (isVerticalText)
+            currentPoint.move(0, advance);
+        else
+            currentPoint.move(advance, 0);
+    }
+}
+
+GlyphData SVGTextRunRenderingContext::glyphDataForCharacter(const Font& font, const TextRun& run, WidthIterator& iterator, UChar32 character, bool mirror, int currentCharacter, unsigned& advanceLength)
+{
+    const SimpleFontData* primaryFont = font.primaryFont();
+    ASSERT(primaryFont);
+
+    pair<GlyphData, GlyphPage*> pair = font.glyphDataAndPageForCharacter(character, mirror);
+    GlyphData glyphData = pair.first;
+
+    // Check if we have the missing glyph data, in which case we can just return.
+    GlyphData missingGlyphData = primaryFont->missingGlyphData();
+    if (glyphData.glyph == missingGlyphData.glyph && glyphData.fontData == missingGlyphData.fontData) {
+        ASSERT(glyphData.fontData);
+        return glyphData;
+    }
+
+    // Save data fromt he font fallback list because we may modify it later. Do this before the
+    // potential change to glyphData.fontData below.
+    FontFallbackList* fontList = font.fontList();
+    ASSERT(fontList);
+    FontFallbackList::GlyphPagesStateSaver glyphPagesSaver(*fontList);
+
+    // Characters enclosed by an <altGlyph> element, may not be registered in the GlyphPage.
+    const SimpleFontData* originalFontData = glyphData.fontData;
+    if (glyphData.fontData && !glyphData.fontData->isSVGFont()) {
+        if (TextRun::RenderingContext* renderingContext = run.renderingContext()) {
+            RenderObject* renderObject = static_cast<SVGTextRunRenderingContext*>(renderingContext)->renderer();
+            RenderObject* parentRenderObject = renderObject->isText() ? renderObject->parent() : renderObject;
+            ASSERT(parentRenderObject);
+            if (Element* parentRenderObjectElement = toElement(parentRenderObject->node())) {
+                if (parentRenderObjectElement->hasTagName(SVGNames::altGlyphTag))
+                    glyphData.fontData = primaryFont;
+            }
+        }
+    }
+
+    const SimpleFontData* fontData = glyphData.fontData;
+    if (fontData) {
+        if (!fontData->isSVGFont())
+            return glyphData;
+
+        SVGFontElement* fontElement = 0;
+        SVGFontFaceElement* fontFaceElement = 0;
+
+        const SVGFontData* svgFontData = svgFontAndFontFaceElementForFontData(fontData, fontFaceElement, fontElement);
+        if (!fontElement || !fontFaceElement)
+            return glyphData;
+
+        // If we got here, we're dealing with a glyph defined in a SVG Font.
+        // The returned glyph by glyphDataAndPageForCharacter() is a glyph stored in the SVG Font glyph table.
+        // This doesn't necessarily mean the glyph is suitable for rendering/measuring in this context, its
+        // arabic-form/orientation/... may not match, we have to apply SVG Glyph selection to discover that.
+        if (svgFontData->applySVGGlyphSelection(iterator, glyphData, mirror, currentCharacter, advanceLength))
+            return glyphData;
+    }
+
+    GlyphPage* page = pair.second;
+    ASSERT(page);
+
+    // No suitable glyph found that is compatible with the requirments (same language, arabic-form, orientation etc.)
+    // Even though our GlyphPage contains an entry for eg. glyph "a", it's not compatible. So we have to temporarily
+    // remove the glyph data information from the GlyphPage, and retry the lookup, which handles font fallbacks correctly.
+    page->setGlyphDataForCharacter(character, 0, 0);
+
+    // Assure that the font fallback glyph selection worked, aka. the fallbackGlyphData font data is not the same as before.
+    GlyphData fallbackGlyphData = font.glyphDataForCharacter(character, mirror);
+    ASSERT(fallbackGlyphData.fontData != fontData);
+
+    // Restore original state of the SVG Font glyph table and the current font fallback list,
+    // to assure the next lookup of the same glyph won't immediately return the fallback glyph.
+    page->setGlyphDataForCharacter(character, glyphData.glyph, originalFontData);
+    ASSERT(fallbackGlyphData.fontData);
+    return fallbackGlyphData;
+}
+
+}
+
+#endif
diff --git a/Source/core/rendering/svg/SVGTextRunRenderingContext.h b/Source/core/rendering/svg/SVGTextRunRenderingContext.h
new file mode 100644
index 0000000..6b4793c
--- /dev/null
+++ b/Source/core/rendering/svg/SVGTextRunRenderingContext.h
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) Research In Motion Limited 2011. 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 SVGTextRunRenderingContext_h
+#define SVGTextRunRenderingContext_h
+
+#include "core/platform/graphics/Font.h"
+#include "core/platform/graphics/TextRun.h"
+
+namespace WebCore {
+
+class RenderObject;
+class RenderSVGResource;
+
+class SVGTextRunRenderingContext : public TextRun::RenderingContext {
+public:
+    static PassRefPtr<SVGTextRunRenderingContext> create(RenderObject* renderer)
+    {
+        return adoptRef(new SVGTextRunRenderingContext(renderer));
+    }
+
+    RenderObject* renderer() const { return m_renderer; }
+
+#if ENABLE(SVG_FONTS)
+    RenderSVGResource* activePaintingResource() const { return m_activePaintingResource; }
+    void setActivePaintingResource(RenderSVGResource* object) { m_activePaintingResource = object; }
+
+    virtual GlyphData glyphDataForCharacter(const Font&, const TextRun&, WidthIterator&, UChar32 character, bool mirror, int currentCharacter, unsigned& advanceLength);
+    virtual void drawSVGGlyphs(GraphicsContext*, const TextRun&, const SimpleFontData*, const GlyphBuffer&, int from, int to, const FloatPoint&) const;
+    virtual float floatWidthUsingSVGFont(const Font&, const TextRun&, int& charsConsumed, String& glyphName) const;
+#endif
+
+private:
+    SVGTextRunRenderingContext(RenderObject* renderer)
+        : m_renderer(renderer)
+#if ENABLE(SVG_FONTS)
+        , m_activePaintingResource(0)
+#endif
+    {
+    }
+
+    virtual ~SVGTextRunRenderingContext() { }
+
+    RenderObject* m_renderer;
+
+#if ENABLE(SVG_FONTS)
+    RenderSVGResource* m_activePaintingResource;
+#endif
+};
+
+inline bool textRunNeedsRenderingContext(const Font& font)
+{
+    // Only save the extra data if SVG Fonts are used, which depend on them.
+    // FIXME: SVG Fonts won't work as segmented fonts at the moment, if that's fixed, we need to check for them as well below.
+    ASSERT(font.primaryFont());
+    return font.primaryFont()->isSVGFont();
+}
+
+} // namespace WebCore
+
+#endif // SVGTextRunRenderingContext_h