Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / rendering / InlineTextBox.cpp
old mode 100755 (executable)
new mode 100644 (file)
index 063cb06..e1a36d3
 #include "core/dom/DocumentMarkerController.h"
 #include "core/dom/RenderedDocumentMarker.h"
 #include "core/dom/Text.h"
+#include "core/editing/CompositionUnderline.h"
+#include "core/editing/CompositionUnderlineRangeFilter.h"
 #include "core/editing/Editor.h"
 #include "core/editing/InputMethodController.h"
-#include "core/frame/Frame.h"
+#include "core/frame/LocalFrame.h"
 #include "core/page/Page.h"
 #include "core/frame/Settings.h"
 #include "core/rendering/AbstractInlineTextBox.h"
 #include "core/rendering/RenderTheme.h"
 #include "core/rendering/style/ShadowList.h"
 #include "core/rendering/svg/SVGTextRunRenderingContext.h"
+#include "platform/RuntimeEnabledFeatures.h"
 #include "platform/fonts/FontCache.h"
+#include "platform/fonts/GlyphBuffer.h"
 #include "platform/fonts/WidthIterator.h"
-#include "platform/graphics/DrawLooper.h"
 #include "platform/graphics/GraphicsContextStateSaver.h"
 #include "wtf/Vector.h"
 #include "wtf/text/CString.h"
 #include "wtf/text/StringBuilder.h"
 
-using namespace std;
+#include <algorithm>
 
-namespace WebCore {
+namespace blink {
 
 struct SameSizeAsInlineTextBox : public InlineBox {
     unsigned variables[1];
@@ -78,13 +81,11 @@ void InlineTextBox::destroy()
     InlineBox::destroy();
 }
 
-void InlineTextBox::markDirty(bool dirty)
+void InlineTextBox::markDirty()
 {
-    if (dirty) {
-        m_len = 0;
-        m_start = 0;
-    }
-    InlineBox::markDirty(dirty);
+    m_len = 0;
+    m_start = 0;
+    InlineBox::markDirty();
 }
 
 LayoutRect InlineTextBox::logicalOverflowRect() const
@@ -106,58 +107,58 @@ int InlineTextBox::baselinePosition(FontBaseline baselineType) const
 {
     if (!isText() || !parent())
         return 0;
-    if (parent()->renderer() == renderer()->parent())
+    if (parent()->renderer() == renderer().parent())
         return parent()->baselinePosition(baselineType);
-    return toRenderBoxModelObject(renderer()->parent())->baselinePosition(baselineType, isFirstLineStyle(), isHorizontal() ? HorizontalLine : VerticalLine, PositionOnContainingLine);
+    return toRenderBoxModelObject(renderer().parent())->baselinePosition(baselineType, isFirstLineStyle(), isHorizontal() ? HorizontalLine : VerticalLine, PositionOnContainingLine);
 }
 
 LayoutUnit InlineTextBox::lineHeight() const
 {
-    if (!isText() || !renderer()->parent())
+    if (!isText() || !renderer().parent())
         return 0;
-    if (m_renderer->isBR())
-        return toRenderBR(m_renderer)->lineHeight(isFirstLineStyle());
-    if (parent()->renderer() == renderer()->parent())
+    if (renderer().isBR())
+        return toRenderBR(renderer()).lineHeight(isFirstLineStyle());
+    if (parent()->renderer() == renderer().parent())
         return parent()->lineHeight();
-    return toRenderBoxModelObject(renderer()->parent())->lineHeight(isFirstLineStyle(), isHorizontal() ? HorizontalLine : VerticalLine, PositionOnContainingLine);
+    return toRenderBoxModelObject(renderer().parent())->lineHeight(isFirstLineStyle(), isHorizontal() ? HorizontalLine : VerticalLine, PositionOnContainingLine);
 }
 
 LayoutUnit InlineTextBox::selectionTop()
 {
-    return root()->selectionTop();
+    return root().selectionTop();
 }
 
 LayoutUnit InlineTextBox::selectionBottom()
 {
-    return root()->selectionBottom();
+    return root().selectionBottom();
 }
 
 LayoutUnit InlineTextBox::selectionHeight()
 {
-    return root()->selectionHeight();
+    return root().selectionHeight();
 }
 
 bool InlineTextBox::isSelected(int startPos, int endPos) const
 {
-    int sPos = max(startPos - m_start, 0);
+    int sPos = std::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));
+    int ePos = std::min(endPos - m_start, int(m_len) + (isLineBreak() ? 0 : 1));
     return (sPos < ePos);
 }
 
 RenderObject::SelectionState InlineTextBox::selectionState()
 {
-    RenderObject::SelectionState state = renderer()->selectionState();
+    RenderObject::SelectionState state = renderer().selectionState();
     if (state == RenderObject::SelectionStart || state == RenderObject::SelectionEnd || state == RenderObject::SelectionBoth) {
         int startPos, endPos;
-        renderer()->selectionStartEnd(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;
+        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)
@@ -174,8 +175,8 @@ RenderObject::SelectionState InlineTextBox::selectionState()
     }
 
     // If there are ellipsis following, make sure their selection is updated.
-    if (m_truncation != cNoTruncation && root()->ellipsisBox()) {
-        EllipsisBox* ellipsis = root()->ellipsisBox();
+    if (m_truncation != cNoTruncation && root().ellipsisBox()) {
+        EllipsisBox* ellipsis = root().ellipsisBox();
         if (state != RenderObject::SelectionNone) {
             int start, end;
             selectionStartEnd(start, end);
@@ -194,30 +195,29 @@ RenderObject::SelectionState InlineTextBox::selectionState()
 
 LayoutRect InlineTextBox::localSelectionRect(int startPos, int endPos)
 {
-    int sPos = max(startPos - m_start, 0);
-    int ePos = min(endPos - m_start, (int)m_len);
+    int sPos = std::max(startPos - m_start, 0);
+    int ePos = std::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());
+    RenderStyle* styleToUse = renderer().style(isFirstLineStyle());
     const Font& font = styleToUse->font();
 
     StringBuilder charactersWithHyphen;
     bool respectHyphen = ePos == m_len && hasHyphen();
     TextRun textRun = constructTextRun(styleToUse, font, respectHyphen ? &charactersWithHyphen : 0);
 
-    FloatPoint startingPoint = FloatPoint(logicalLeft(), selTop);
+    FloatPoint startingPoint = FloatPoint(logicalLeft(), selTop.toFloat());
     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)));
+        r = enclosingIntRect(FloatRect(startingPoint, FloatSize(m_logicalWidth, selHeight.toFloat())));
 
     LayoutUnit logicalWidth = r.width();
     if (r.x() > logicalRight())
@@ -234,7 +234,7 @@ LayoutRect InlineTextBox::localSelectionRect(int startPos, int endPos)
 
 void InlineTextBox::deleteLine()
 {
-    toRenderText(renderer())->removeTextBox(this);
+    renderer().removeTextBox(this);
     destroy();
 }
 
@@ -243,7 +243,7 @@ void InlineTextBox::extractLine()
     if (extracted())
         return;
 
-    toRenderText(renderer())->extractTextBox(this);
+    renderer().extractTextBox(this);
 }
 
 void InlineTextBox::attachLine()
@@ -251,7 +251,7 @@ void InlineTextBox::attachLine()
     if (!extracted())
         return;
 
-    toRenderText(renderer())->attachTextBox(this);
+    renderer().attachTextBox(this);
 }
 
 float InlineTextBox::placeEllipsisBox(bool flowIsLTR, float visibleLeftEdge, float visibleRightEdge, float ellipsisWidth, float &truncatedWidth, bool& foundBox)
@@ -297,7 +297,7 @@ float InlineTextBox::placeEllipsisBox(bool flowIsLTR, float visibleLeftEdge, flo
             // and the ellipsis edge.
             m_truncation = cFullTruncation;
             truncatedWidth += ellipsisWidth;
-            return min(ellipsisX, logicalLeft());
+            return std::min(ellipsisX, logicalLeft());
         }
 
         // Set the truncation index on the text run.
@@ -305,7 +305,7 @@ float InlineTextBox::placeEllipsisBox(bool flowIsLTR, float visibleLeftEdge, flo
 
         // 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(), flowIsLTR ? LTR : RTL, isFirstLineStyle());
+        float widthOfVisibleText = renderer().width(m_start, offset, textPos(), flowIsLTR ? LTR : RTL, isFirstLineStyle());
 
         // The ellipsis needs to be placed just after the last visible character.
         // Where "after" is defined by the flow directionality, not the inline
@@ -322,28 +322,14 @@ float InlineTextBox::placeEllipsisBox(bool flowIsLTR, float visibleLeftEdge, flo
     return -1;
 }
 
-Color correctedTextColor(Color textColor, Color backgroundColor)
+static Color textColorForWhiteBackground(Color textColor)
 {
-    // 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();
+    // semi-arbitrarily chose 65025 (255^2) value here after a few tests;
+    return distanceFromWhite > 65025 ? textColor : textColor.dark();
 }
 
-void updateGraphicsContext(GraphicsContext* context, const Color& fillColor, const Color& strokeColor, float strokeThickness)
+static void updateGraphicsContext(GraphicsContext* context, const Color& fillColor, const Color& strokeColor, float strokeThickness)
 {
     TextDrawingModeFlags mode = context->textDrawingMode();
     if (strokeThickness > 0) {
@@ -367,7 +353,7 @@ void updateGraphicsContext(GraphicsContext* context, const Color& fillColor, con
 
 bool InlineTextBox::isLineBreak() const
 {
-    return renderer()->isBR() || (renderer()->style()->preserveNewline() && len() == 1 && (*textRenderer()->text().impl())[start()] == '\n');
+    return renderer().isBR() || (renderer().style()->preserveNewline() && len() == 1 && (*renderer().text().impl())[start()] == '\n');
 }
 
 bool InlineTextBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit /* lineTop */, LayoutUnit /*lineBottom*/)
@@ -379,36 +365,24 @@ bool InlineTextBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& re
     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))
+        renderer().updateHitTestResult(result, flipForWritingMode(locationInContainer.point() - toLayoutSize(accumulatedOffset)));
+        if (!result.addNodeToRectBasedTestResult(renderer().node(), request, locationInContainer, rect))
             return true;
     }
     return false;
 }
 
 static void paintTextWithShadows(GraphicsContext* context,
-    const RenderObject* renderer, const Font& font, const TextRun& textRun,
+    const Font& font, const TextRun& textRun,
     const AtomicString& emphasisMark, int emphasisMarkOffset,
     int startOffset, int endOffset, int truncationPoint,
     const FloatPoint& textOrigin, const FloatRect& boxRect,
-    const ShadowList* shadowList, bool stroked, bool horizontal)
+    const ShadowList* shadowList, bool horizontal)
 {
     // Text shadows are disabled when printing. http://crbug.com/258321
     bool hasShadow = shadowList && !context->printing();
-
-    if (hasShadow) {
-        DrawLooper drawLooper;
-        for (size_t i = shadowList->shadows().size(); i--; ) {
-            const ShadowData& shadow = shadowList->shadows()[i];
-            float shadowX = horizontal ? shadow.x() : shadow.y();
-            float shadowY = horizontal ? shadow.y() : -shadow.x();
-            FloatSize offset(shadowX, shadowY);
-            drawLooper.addShadow(offset, shadow.blur(), shadow.color(),
-                DrawLooper::ShadowRespectsTransforms, DrawLooper::ShadowIgnoresAlpha);
-        }
-        drawLooper.addUnmodifiedContent();
-        context->setDrawLooper(drawLooper);
-    }
+    if (hasShadow)
+        context->setDrawLooper(shadowList->createDrawLooper(DrawLooperBuilder::ShadowIgnoresAlpha, horizontal));
 
     TextRunPaintInfo textRunPaintInfo(textRun);
     textRunPaintInfo.bounds = boxRect;
@@ -442,6 +416,27 @@ static void paintTextWithShadows(GraphicsContext* context,
         context->clearDrawLooper();
 }
 
+static void paintEmphasisMark(GraphicsContext* context,
+    const AtomicString& emphasisMark, int emphasisMarkOffset,
+    int startOffset, int endOffset, int paintRunLength,
+    const Font& font, Color emphasisMarkColor, Color textStrokeColor, float textStrokeWidth, const ShadowList* textShadow,
+    RenderCombineText* combinedText, const TextRun& textRun,
+    const FloatPoint& textOrigin, const FloatRect& boxRect, bool horizontal)
+{
+    ASSERT(!emphasisMark.isEmpty());
+    updateGraphicsContext(context, emphasisMarkColor, textStrokeColor, textStrokeWidth);
+
+    if (combinedText) {
+        DEFINE_STATIC_LOCAL(TextRun, objectReplacementCharacterTextRun, (&objectReplacementCharacter, 1));
+        FloatPoint emphasisMarkTextOrigin(boxRect.x() + boxRect.width() / 2, boxRect.y() + font.fontMetrics().ascent());
+        context->concatCTM(InlineTextBox::rotation(boxRect, InlineTextBox::Clockwise));
+        paintTextWithShadows(context, combinedText->originalFont(), objectReplacementCharacterTextRun, emphasisMark, emphasisMarkOffset, 0, 1, 1, emphasisMarkTextOrigin, boxRect, textShadow, horizontal);
+        context->concatCTM(InlineTextBox::rotation(boxRect, InlineTextBox::Counterclockwise));
+    } else {
+        paintTextWithShadows(context, font, textRun, emphasisMark, emphasisMarkOffset, startOffset, endOffset, paintRunLength, textOrigin, boxRect, textShadow, horizontal);
+    }
+}
+
 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.
@@ -452,7 +447,7 @@ bool InlineTextBox::getEmphasisMarkPosition(RenderStyle* style, TextEmphasisPosi
     if (emphasisPosition == TextEmphasisPositionUnder)
         return true; // Ruby text is always over, so it cannot suppress emphasis marks under.
 
-    RenderBlock* containingBlock = renderer()->containingBlock();
+    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.
 
@@ -465,28 +460,118 @@ bool InlineTextBox::getEmphasisMarkPosition(RenderStyle* style, TextEmphasisPosi
     return !rubyText || !rubyText->firstLineBox();
 }
 
+namespace {
+
+struct TextPaintingStyle {
+    Color fillColor;
+    Color strokeColor;
+    Color emphasisMarkColor;
+    float strokeWidth;
+    const ShadowList* shadow;
+
+    bool operator==(const TextPaintingStyle& other)
+    {
+        return fillColor == other.fillColor
+            && strokeColor == other.strokeColor
+            && emphasisMarkColor == other.emphasisMarkColor
+            && strokeWidth == other.strokeWidth
+            && shadow == other.shadow;
+    }
+    bool operator!=(const TextPaintingStyle& other) { return !(*this == other); }
+};
+
+TextPaintingStyle textPaintingStyle(RenderText& renderer, RenderStyle* style, bool forceBlackText, bool isPrinting)
+{
+    TextPaintingStyle textStyle;
+
+    if (forceBlackText) {
+        textStyle.fillColor = Color::black;
+        textStyle.strokeColor = Color::black;
+        textStyle.emphasisMarkColor = Color::black;
+        textStyle.strokeWidth = style->textStrokeWidth();
+        textStyle.shadow = 0;
+    } else {
+        textStyle.fillColor = renderer.resolveColor(style, CSSPropertyWebkitTextFillColor);
+        textStyle.strokeColor = renderer.resolveColor(style, CSSPropertyWebkitTextStrokeColor);
+        textStyle.emphasisMarkColor = renderer.resolveColor(style, CSSPropertyWebkitTextEmphasisColor);
+        textStyle.strokeWidth = style->textStrokeWidth();
+        textStyle.shadow = style->textShadow();
+
+        // Adjust text color when printing with a white background.
+        bool forceBackgroundToWhite = false;
+        if (isPrinting) {
+            if (style->printColorAdjust() == PrintColorAdjustEconomy)
+                forceBackgroundToWhite = true;
+            if (renderer.document().settings() && renderer.document().settings()->shouldPrintBackgrounds())
+                forceBackgroundToWhite = false;
+        }
+        if (forceBackgroundToWhite) {
+            textStyle.fillColor = textColorForWhiteBackground(textStyle.fillColor);
+            textStyle.strokeColor = textColorForWhiteBackground(textStyle.strokeColor);
+            textStyle.emphasisMarkColor = textColorForWhiteBackground(textStyle.emphasisMarkColor);
+        }
+
+        // Text shadows are disabled when printing. http://crbug.com/258321
+        if (isPrinting)
+            textStyle.shadow = 0;
+    }
+
+    return textStyle;
+}
+
+TextPaintingStyle selectionPaintingStyle(RenderText& renderer, bool haveSelection, bool forceBlackText, bool isPrinting, const TextPaintingStyle& textStyle)
+{
+    TextPaintingStyle selectionStyle = textStyle;
+
+    if (haveSelection) {
+        if (!forceBlackText) {
+            selectionStyle.fillColor = renderer.selectionForegroundColor();
+            selectionStyle.emphasisMarkColor = renderer.selectionEmphasisMarkColor();
+        }
+
+        if (RenderStyle* pseudoStyle = renderer.getCachedPseudoStyle(SELECTION)) {
+            selectionStyle.strokeColor = forceBlackText ? Color::black : renderer.resolveColor(pseudoStyle, CSSPropertyWebkitTextStrokeColor);
+            selectionStyle.strokeWidth = pseudoStyle->textStrokeWidth();
+            selectionStyle.shadow = forceBlackText ? 0 : pseudoStyle->textShadow();
+        }
+
+        // Text shadows are disabled when printing. http://crbug.com/258321
+        if (isPrinting)
+            selectionStyle.shadow = 0;
+    }
+
+    return selectionStyle;
+}
+
+} // namespace
+
 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)
+    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;
+    LayoutRect logicalVisualOverflow = logicalOverflowRect();
+    LayoutUnit logicalStart = logicalVisualOverflow.x() + (isHorizontal() ? paintOffset.x() : paintOffset.y());
+    LayoutUnit logicalExtent = logicalVisualOverflow.width();
 
     LayoutUnit paintEnd = isHorizontal() ? paintInfo.rect.maxX() : paintInfo.rect.maxY();
     LayoutUnit paintStart = isHorizontal() ? paintInfo.rect.x() : paintInfo.rect.y();
 
-    LayoutPoint adjustedPaintOffset = roundedIntPoint(paintOffset);
+    // When subpixel font scaling is enabled text runs are positioned at
+    // subpixel boundaries on the x-axis and thus there is no reason to
+    // snap the x value. We still round the y-axis to ensure consistent
+    // line heights.
+    LayoutPoint adjustedPaintOffset = RuntimeEnabledFeatures::subpixelFontScalingEnabled()
+        ? LayoutPoint(paintOffset.x(), paintOffset.y().round())
+        : roundedIntPoint(paintOffset);
 
     if (logicalStart >= paintEnd || logicalStart + logicalExtent <= paintStart)
         return;
 
-    bool isPrinting = textRenderer()->document().printing();
+    bool isPrinting = renderer().document().printing();
 
     // Determine whether or not we're selected.
     bool haveSelection = !isPrinting && paintInfo.phase != PaintPhaseTextClip && selectionState() != RenderObject::SelectionNone;
@@ -495,7 +580,7 @@ void InlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset,
         return;
 
     if (m_truncation != cNoTruncation) {
-        if (renderer()->containingBlock()->style()->isLeftToRightDirection() != isLeftToRightDirection()) {
+        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:
@@ -504,7 +589,7 @@ void InlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset,
             // 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(), isLeftToRightDirection() ? LTR : RTL, isFirstLineStyle());
+            LayoutUnit widthOfVisibleText = renderer().width(m_start, m_truncation, textPos(), isLeftToRightDirection() ? LTR : RTL, 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);
@@ -513,138 +598,48 @@ void InlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset,
     }
 
     GraphicsContext* context = paintInfo.context;
-
-    RenderObject* rendererToUse = renderer();
-    RenderStyle* styleToUse = rendererToUse->style(isFirstLineStyle());
+    RenderStyle* styleToUse = renderer().style(isFirstLineStyle());
 
     adjustedPaintOffset.move(0, styleToUse->isHorizontalWritingMode() ? 0 : -logicalHeight());
 
     FloatPoint boxOrigin = locationIncludingFlipping();
-    boxOrigin.move(adjustedPaintOffset.x(), adjustedPaintOffset.y());
+    boxOrigin.move(adjustedPaintOffset.x().toFloat(), adjustedPaintOffset.y().toFloat());
     FloatRect boxRect(boxOrigin, LayoutSize(logicalWidth(), logicalHeight()));
 
-    RenderCombineText* combinedText = styleToUse->hasTextCombine() && textRenderer()->isCombineText() && toRenderCombineText(textRenderer())->isCombined() ? toRenderCombineText(textRenderer()) : 0;
+    RenderCombineText* combinedText = styleToUse->hasTextCombine() && renderer().isCombineText() && toRenderCombineText(renderer()).isCombined() ? &toRenderCombineText(renderer()) : 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()->inputMethodController().compositionNode() == renderer()->node();
-    bool useCustomUnderlines = containsComposition && renderer()->frame()->inputMethodController().compositionUsesCustomUnderlines();
-
-    // Determine the text colors and selection colors.
-    Color textFillColor;
-    Color textStrokeColor;
-    Color emphasisMarkColor;
-    float textStrokeWidth = styleToUse->textStrokeWidth();
-
-    // Text shadows are disabled when printing. http://crbug.com/258321
-    const ShadowList* textShadow = (context->printing() || paintInfo.forceBlackText()) ? 0 : styleToUse->textShadow();
-
-    if (paintInfo.forceBlackText()) {
-        textFillColor = Color::black;
-        textStrokeColor = Color::black;
-        emphasisMarkColor = Color::black;
-    } else {
-        textFillColor = rendererToUse->resolveColor(styleToUse, 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 = rendererToUse->resolveColor(styleToUse, CSSPropertyWebkitTextStrokeColor);
-
-        // Make the text stroke color legible against a white background
-        if (forceBackgroundToWhite)
-            textStrokeColor = correctedTextColor(textStrokeColor, Color::white);
-
-        emphasisMarkColor = rendererToUse->resolveColor(styleToUse, CSSPropertyWebkitTextEmphasisColor);
-
-        // Make the text stroke color legible against a white background
-        if (forceBackgroundToWhite)
-            emphasisMarkColor = correctedTextColor(emphasisMarkColor, Color::white);
-    }
+    bool containsComposition = renderer().node() && renderer().frame()->inputMethodController().compositionNode() == renderer().node();
+    bool useCustomUnderlines = containsComposition && renderer().frame()->inputMethodController().compositionUsesCustomUnderlines();
 
+    // Determine text colors.
+    TextPaintingStyle textStyle = textPaintingStyle(renderer(), styleToUse, paintInfo.forceBlackText(), isPrinting);
+    TextPaintingStyle selectionStyle = selectionPaintingStyle(renderer(), haveSelection, paintInfo.forceBlackText(), isPrinting, textStyle);
     bool paintSelectedTextOnly = (paintInfo.phase == PaintPhaseSelection);
-    bool paintSelectedTextSeparately = false;
-
-    Color selectionFillColor = textFillColor;
-    Color selectionStrokeColor = textStrokeColor;
-    Color selectionEmphasisMarkColor = emphasisMarkColor;
-    float selectionStrokeWidth = textStrokeWidth;
-    const ShadowList* selectionShadow = textShadow;
-    if (haveSelection) {
-        // Check foreground color first.
-        Color foreground = paintInfo.forceBlackText() ? Color::black : renderer()->selectionForegroundColor();
-        if (foreground != selectionFillColor) {
-            if (!paintSelectedTextOnly)
-                paintSelectedTextSeparately = true;
-            selectionFillColor = foreground;
-        }
-
-        Color emphasisMarkForeground = paintInfo.forceBlackText() ? Color::black : renderer()->selectionEmphasisMarkColor();
-        if (emphasisMarkForeground != selectionEmphasisMarkColor) {
-            if (!paintSelectedTextOnly)
-                paintSelectedTextSeparately = true;
-            selectionEmphasisMarkColor = emphasisMarkForeground;
-        }
-
-        if (RenderStyle* pseudoStyle = renderer()->getCachedPseudoStyle(SELECTION)) {
-            // Text shadows are disabled when printing. http://crbug.com/258321
-            const ShadowList* shadow = (context->printing() || 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 : rendererToUse->resolveColor(pseudoStyle, CSSPropertyWebkitTextStrokeColor);
-            if (stroke != selectionStrokeColor) {
-                if (!paintSelectedTextOnly)
-                    paintSelectedTextSeparately = true;
-                selectionStrokeColor = stroke;
-            }
-        }
-    }
+    bool paintSelectedTextSeparately = !paintSelectedTextOnly && textStyle != selectionStyle;
 
     // 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.
+    // and composition highlights.
     if (paintInfo.phase != PaintPhaseSelection && paintInfo.phase != PaintPhaseTextClip && !isPrinting) {
-
-        if (containsComposition && !useCustomUnderlines) {
-            paintCompositionBackground(context, boxOrigin, styleToUse, font,
-                renderer()->frame()->inputMethodController().compositionStart(),
-                renderer()->frame()->inputMethodController().compositionEnd());
+        if (containsComposition) {
+            paintCompositionBackgrounds(context, boxOrigin, styleToUse, font, useCustomUnderlines);
         }
 
         paintDocumentMarkers(context, boxOrigin, styleToUse, font, true);
 
         if (haveSelection && !useCustomUnderlines)
-            paintSelection(context, boxOrigin, styleToUse, font, selectionFillColor);
+            paintSelection(context, boxOrigin, styleToUse, font, selectionStyle.fillColor);
     }
 
     // 2. Now paint the foreground, including text and decorations like underline/overline (in quirks mode only).
@@ -652,10 +647,10 @@ void InlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset,
     int maximumLength;
     StringView string;
     if (!combinedText) {
-        string = textRenderer()->text().createView();
+        string = renderer().text().createView();
         if (static_cast<unsigned>(length) != string.length() || m_start)
             string.narrow(m_start, length);
-        maximumLength = textRenderer()->textLength() - m_start;
+        maximumLength = renderer().textLength() - m_start;
     } else {
         combinedText->getStringToRender(m_start, string, length);
         maximumLength = length;
@@ -672,8 +667,8 @@ void InlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset,
         selectionStartEnd(sPos, ePos);
 
     if (m_truncation != cNoTruncation) {
-        sPos = min<int>(sPos, m_truncation);
-        ePos = min<int>(ePos, m_truncation);
+        sPos = std::min<int>(sPos, m_truncation);
+        ePos = std::min<int>(ePos, m_truncation);
         length = m_truncation;
     }
 
@@ -685,68 +680,43 @@ void InlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset,
         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);
-        if (!paintSelectedTextSeparately || ePos <= sPos) {
-            // FIXME: Truncate right-to-left text correctly.
-            paintTextWithShadows(context, rendererToUse, font, textRun, nullAtom, 0, 0, length, length, textOrigin, boxRect, textShadow, textStrokeWidth > 0, isHorizontal());
-        } else {
-            paintTextWithShadows(context, rendererToUse, font, textRun, nullAtom, 0, ePos, sPos, length, textOrigin, boxRect, textShadow, textStrokeWidth > 0, isHorizontal());
+        // FIXME: Truncate right-to-left text correctly.
+        int startOffset = 0;
+        int endOffset = length;
+        if (paintSelectedTextSeparately && ePos > sPos) {
+            startOffset = ePos;
+            endOffset = sPos;
         }
 
-        if (!emphasisMark.isEmpty()) {
-            updateGraphicsContext(context, emphasisMarkColor, textStrokeColor, textStrokeWidth);
-
-            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));
+        // 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, textStyle.strokeWidth > 0);
 
-            if (!paintSelectedTextSeparately || ePos <= sPos) {
-                // FIXME: Truncate right-to-left text correctly.
-                paintTextWithShadows(context, rendererToUse, combinedText ? combinedText->originalFont() : font, emphasisMarkTextRun, emphasisMark, emphasisMarkOffset, 0, length, length, emphasisMarkTextOrigin, boxRect, textShadow, textStrokeWidth > 0, isHorizontal());
-            } else {
-                paintTextWithShadows(context, rendererToUse, combinedText ? combinedText->originalFont() : font, emphasisMarkTextRun, emphasisMark, emphasisMarkOffset, ePos, sPos, length, emphasisMarkTextOrigin, boxRect, textShadow, textStrokeWidth > 0, isHorizontal());
-            }
+        updateGraphicsContext(context, textStyle.fillColor, textStyle.strokeColor, textStyle.strokeWidth);
+        paintTextWithShadows(context, font, textRun, nullAtom, 0, startOffset, endOffset, length, textOrigin, boxRect, textStyle.shadow, isHorizontal());
 
-            if (combinedText)
-                context->concatCTM(rotation(boxRect, Counterclockwise));
-        }
+        if (!emphasisMark.isEmpty())
+            paintEmphasisMark(context, emphasisMark, emphasisMarkOffset, startOffset, endOffset, length, font, textStyle.emphasisMarkColor, textStyle.strokeColor, textStyle.strokeWidth, textStyle.shadow, combinedText, textRun, textOrigin, boxRect, isHorizontal());
     }
 
     if ((paintSelectedTextOnly || paintSelectedTextSeparately) && sPos < ePos) {
         // paint only the text that is selected
-        GraphicsContextStateSaver stateSaver(*context, selectionStrokeWidth > 0);
-
-        updateGraphicsContext(context, selectionFillColor, selectionStrokeColor, selectionStrokeWidth);
-        paintTextWithShadows(context, rendererToUse, font, textRun, nullAtom, 0, sPos, ePos, length, textOrigin, boxRect, selectionShadow, selectionStrokeWidth > 0, isHorizontal());
-        if (!emphasisMark.isEmpty()) {
-            updateGraphicsContext(context, selectionEmphasisMarkColor, textStrokeColor, textStrokeWidth);
-
-            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));
+        GraphicsContextStateSaver stateSaver(*context, selectionStyle.strokeWidth > 0);
 
-            paintTextWithShadows(context, rendererToUse, combinedText ? combinedText->originalFont() : font, emphasisMarkTextRun, emphasisMark, emphasisMarkOffset, sPos, ePos, length, emphasisMarkTextOrigin, boxRect, selectionShadow, selectionStrokeWidth > 0, isHorizontal());
+        updateGraphicsContext(context, selectionStyle.fillColor, selectionStyle.strokeColor, selectionStyle.strokeWidth);
+        paintTextWithShadows(context, font, textRun, nullAtom, 0, sPos, ePos, length, textOrigin, boxRect, selectionStyle.shadow, isHorizontal());
 
-            if (combinedText)
-                context->concatCTM(rotation(boxRect, Counterclockwise));
-        }
+        if (!emphasisMark.isEmpty())
+            paintEmphasisMark(context, emphasisMark, emphasisMarkOffset, sPos, ePos, length, font, selectionStyle.emphasisMarkColor, selectionStyle.strokeColor, textStyle.strokeWidth, selectionStyle.shadow, combinedText, textRun, textOrigin, boxRect, isHorizontal());
     }
 
     // Paint decorations
     TextDecoration textDecorations = styleToUse->textDecorationsInEffect();
     if (textDecorations != TextDecorationNone && paintInfo.phase != PaintPhaseSelection) {
-        updateGraphicsContext(context, textFillColor, textStrokeColor, textStrokeWidth);
+        updateGraphicsContext(context, textStyle.fillColor, textStyle.strokeColor, textStyle.strokeWidth);
         if (combinedText)
             context->concatCTM(rotation(boxRect, Clockwise));
-        paintDecoration(context, boxOrigin, textDecorations, styleToUse->textDecorationStyle(), textShadow);
+        paintDecoration(context, boxOrigin, textDecorations, textStyle.shadow);
         if (combinedText)
             context->concatCTM(rotation(boxRect, Counterclockwise));
     }
@@ -754,28 +724,14 @@ void InlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset,
     if (paintInfo.phase == PaintPhaseForeground) {
         paintDocumentMarkers(context, boxOrigin, styleToUse, font, false);
 
+        // Paint custom underlines for compositions.
         if (useCustomUnderlines) {
-            const Vector<CompositionUnderline>& underlines = renderer()->frame()->inputMethodController().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.
+            const Vector<CompositionUnderline>& underlines = renderer().frame()->inputMethodController().customCompositionUnderlines();
+            CompositionUnderlineRangeFilter filter(underlines, start(), end());
+            for (CompositionUnderlineRangeFilter::ConstIterator it = filter.begin(); it != filter.end(); ++it) {
+                if (it->color == Color::transparent)
                     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;
+                paintCompositionUnderline(context, boxOrigin, *it);
             }
         }
     }
@@ -787,40 +743,30 @@ void InlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset,
 void InlineTextBox::selectionStartEnd(int& sPos, int& ePos)
 {
     int startPos, endPos;
-    if (renderer()->selectionState() == RenderObject::SelectionInside) {
+    if (renderer().selectionState() == RenderObject::SelectionInside) {
         startPos = 0;
-        endPos = textRenderer()->textLength();
+        endPos = renderer().textLength();
     } else {
-        textRenderer()->selectionStartEnd(startPos, endPos);
-        if (renderer()->selectionState() == RenderObject::SelectionStart)
-            endPos = textRenderer()->textLength();
-        else if (renderer()->selectionState() == RenderObject::SelectionEnd)
+        renderer().selectionStartEnd(startPos, endPos);
+        if (renderer().selectionState() == RenderObject::SelectionStart)
+            endPos = renderer().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()));
+    sPos = std::max(startPos - m_start, 0);
+    ePos = std::min(endPos - m_start, (int)m_len);
 }
 
 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();
+    Color c = renderer().selectionBackgroundColor();
     if (!c.alpha())
         return;
 
@@ -835,51 +781,58 @@ void InlineTextBox::paintSelection(GraphicsContext* context, const FloatPoint& b
     // 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;
-    StringView string = textRenderer()->text().createView();
+    StringView string = renderer().text().createView();
 
     if (string.length() != static_cast<unsigned>(length) || m_start)
         string.narrow(m_start, length);
 
     StringBuilder charactersWithHyphen;
     bool respectHyphen = ePos == length && hasHyphen();
-    TextRun textRun = constructTextRun(style, font, string, textRenderer()->textLength() - m_start, respectHyphen ? &charactersWithHyphen : 0);
+    TextRun textRun = constructTextRun(style, font, string, renderer().textLength() - m_start, respectHyphen ? &charactersWithHyphen : 0);
     if (respectHyphen)
         ePos = textRun.length();
 
-    LayoutUnit selectionBottom = root()->selectionBottom();
-    LayoutUnit selectionTop = root()->selectionTopAdjustedForPrecedingBlock();
+    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));
+    int deltaY = roundToInt(renderer().style()->isFlippedLinesWritingMode() ? selectionBottom - logicalBottom() : logicalTop() - selectionTop);
+    int selHeight = std::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, sPos, ePos);
 }
 
-void InlineTextBox::paintCompositionBackground(GraphicsContext* context, const FloatPoint& boxOrigin, RenderStyle* style, const Font& font, int startPos, int endPos)
+unsigned InlineTextBox::underlinePaintStart(const CompositionUnderline& underline)
 {
-    int offset = m_start;
-    int sPos = max(startPos - offset, 0);
-    int ePos = min(endPos - offset, (int)m_len);
+    return std::max(static_cast<unsigned>(m_start), underline.startOffset);
+}
+
+unsigned InlineTextBox::underlinePaintEnd(const CompositionUnderline& underline)
+{
+    unsigned paintEnd = std::min(end() + 1, underline.endOffset); // end() points at the last char, not past it.
+    if (m_truncation != cNoTruncation)
+        paintEnd = std::min(paintEnd, static_cast<unsigned>(m_start + m_truncation));
+    return paintEnd;
+}
 
+void InlineTextBox::paintSingleCompositionBackgroundRun(GraphicsContext* context, const FloatPoint& boxOrigin, RenderStyle* style, const Font& font, Color backgroundColor, int startPos, int endPos)
+{
+    int sPos = std::max(startPos - m_start, 0);
+    int ePos = std::min(endPos - m_start, static_cast<int>(m_len));
     if (sPos >= ePos)
         return;
 
     GraphicsContextStateSaver stateSaver(*context);
 
-    Color c = Color(225, 221, 85);
+    updateGraphicsContext(context, backgroundColor, backgroundColor, 0); // Don't draw text at all!
 
-    updateGraphicsContext(context, c, c, 0); // Don't draw text at all!
-
-    int deltaY = renderer()->style()->isFlippedLinesWritingMode() ? selectionBottom() - logicalBottom() : logicalTop() - selectionTop();
+    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, sPos, ePos);
+    context->drawHighlightForText(font, constructTextRun(style, font), localOrigin, selHeight, backgroundColor, sPos, ePos);
 }
 
 static StrokeStyle textDecorationStyleToStrokeStyle(TextDecorationStyle decorationStyle)
@@ -910,7 +863,18 @@ static int computeUnderlineOffset(const TextUnderlinePosition underlinePosition,
 {
     // 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 = std::max<int>(1, ceilf(textDecorationThickness / 2.f));
+    int gap = 0;
+
+    // Underline position of zero means draw underline on Baseline Position,
+    // in Blink we need at least 1-pixel gap to adding following check.
+    // Positive underline Position means underline should be drawn above baselin e
+    // and negative value means drawing below baseline, negating the value as in Blink
+    // downward Y-increases.
+
+    if (fontMetrics.underlinePosition())
+        gap = -fontMetrics.underlinePosition();
+    else
+        gap = std::max<int>(1, ceilf(textDecorationThickness / 2.f));
 
     // FIXME: We support only horizontal text for now.
     switch (underlinePosition) {
@@ -918,7 +882,7 @@ static int computeUnderlineOffset(const TextUnderlinePosition underlinePosition,
         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();
+        const float offset = inlineTextBox->root().maxLogicalTop() - inlineTextBox->logicalTop();
         if (offset > 0)
             return inlineTextBox->logicalHeight() + gap + offset;
         return inlineTextBox->logicalHeight() + gap;
@@ -974,7 +938,7 @@ static void adjustStepToDecorationLength(float& step, float& controlPointDistanc
  *             |-----------|
  *                 step
  */
-static void strokeWavyTextDecoration(GraphicsContext* context, FloatPoint& p1, FloatPoint& p2, float strokeThickness)
+static void strokeWavyTextDecoration(GraphicsContext* context, FloatPoint p1, FloatPoint p2, float strokeThickness)
 {
     context->adjustLineToPixelBoundaries(p1, p2, strokeThickness, context->strokeStyle());
 
@@ -986,12 +950,12 @@ static void strokeWavyTextDecoration(GraphicsContext* context, FloatPoint& p1, F
     // 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);
+    float controlPointDistance = 3 * std::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);
+    float step = 2 * std::max<float>(2, strokeThickness);
 
     bool isVerticalLine = (p1.x() == p2.x());
 
@@ -1051,7 +1015,39 @@ static void strokeWavyTextDecoration(GraphicsContext* context, FloatPoint& p1, F
     context->strokePath(path);
 }
 
-void InlineTextBox::paintDecoration(GraphicsContext* context, const FloatPoint& boxOrigin, TextDecoration deco, TextDecorationStyle decorationStyle, const ShadowList* shadowList)
+static bool shouldSetDecorationAntialias(TextDecorationStyle decorationStyle)
+{
+    return decorationStyle == TextDecorationStyleDotted || decorationStyle == TextDecorationStyleDashed;
+}
+
+static bool shouldSetDecorationAntialias(TextDecorationStyle underline, TextDecorationStyle overline, TextDecorationStyle linethrough)
+{
+    return shouldSetDecorationAntialias(underline) || shouldSetDecorationAntialias(overline) || shouldSetDecorationAntialias(linethrough);
+}
+
+static void paintAppliedDecoration(GraphicsContext* context, FloatPoint start, float width, float doubleOffset, int wavyOffsetFactor,
+    RenderObject::AppliedTextDecoration decoration, float thickness, bool antialiasDecoration, bool isPrinting)
+{
+    context->setStrokeStyle(textDecorationStyleToStrokeStyle(decoration.style));
+    context->setStrokeColor(decoration.color);
+
+    switch (decoration.style) {
+    case TextDecorationStyleWavy:
+        strokeWavyTextDecoration(context, start + FloatPoint(0, doubleOffset * wavyOffsetFactor), start + FloatPoint(width, doubleOffset * wavyOffsetFactor), thickness);
+        break;
+    case TextDecorationStyleDotted:
+    case TextDecorationStyleDashed:
+        context->setShouldAntialias(antialiasDecoration);
+        // Fall through
+    default:
+        context->drawLineForText(start, width, isPrinting);
+
+        if (decoration.style == TextDecorationStyleDouble)
+            context->drawLineForText(start + FloatPoint(0, doubleOffset), width, isPrinting);
+    }
+}
+
+void InlineTextBox::paintDecoration(GraphicsContext* context, const FloatPoint& boxOrigin, TextDecoration deco, const ShadowList* shadowList)
 {
     GraphicsContextStateSaver stateSaver(*context);
 
@@ -1062,31 +1058,41 @@ void InlineTextBox::paintDecoration(GraphicsContext* context, const FloatPoint&
 
     float width = m_logicalWidth;
     if (m_truncation != cNoTruncation) {
-        width = toRenderText(renderer())->width(m_start, m_truncation, textPos(), isLeftToRightDirection() ? LTR : RTL, isFirstLineStyle());
+        width = renderer().width(m_start, m_truncation, textPos(), isLeftToRightDirection() ? LTR : RTL, isFirstLineStyle());
         if (!isLeftToRightDirection())
             localOrigin.move(m_logicalWidth - width, 0);
     }
 
     // Get the text decoration colors.
-    Color underline(Color::transparent), overline(Color::transparent), linethrough(Color::transparent);
-    renderer()->getTextDecorationColors(deco, underline, overline, linethrough, true);
+    RenderObject::AppliedTextDecoration underline, overline, linethrough;
+
+    renderer().getTextDecorations(deco, underline, overline, linethrough, true);
     if (isFirstLineStyle())
-        renderer()->getTextDecorationColors(deco, underline, overline, linethrough, true, true);
+        renderer().getTextDecorations(deco, underline, overline, linethrough, true, true);
 
     // Use a special function for underlines to get the positioning exactly right.
-    bool isPrinting = textRenderer()->document().printing();
+    bool isPrinting = renderer().document().printing();
 
-    bool linesAreOpaque = !isPrinting && (!(deco & TextDecorationUnderline) || underline.alpha() == 255) && (!(deco & TextDecorationOverline) || overline.alpha() == 255) && (!(deco & TextDecorationLineThrough) || linethrough.alpha() == 255);
+    bool linesAreOpaque = !isPrinting && (!(deco & TextDecorationUnderline) || underline.color.alpha() == 255) && (!(deco & TextDecorationOverline) || overline.color.alpha() == 255) && (!(deco & TextDecorationLineThrough) || linethrough.color.alpha() == 255);
 
-    RenderStyle* styleToUse = renderer()->style(isFirstLineStyle());
+    RenderStyle* styleToUse = renderer().style(isFirstLineStyle());
     int baseline = styleToUse->fontMetrics().ascent();
 
     size_t shadowCount = shadowList ? shadowList->shadows().size() : 0;
     // Set the thick of the line to be 10% (or something else ?)of the computed font size and not less than 1px.
     // Using computedFontSize should take care of zoom as well.
-    const float textDecorationThickness = std::max(1.f, styleToUse->computedFontSize() / 10.f);
+
+    // Update Underline thickness, in case we have Faulty Font Metrics calculating underline thickness by old method.
+    float textDecorationThickness = styleToUse->fontMetrics().underlineThickness();
+    int fontHeightInt  = (int)(styleToUse->fontMetrics().floatHeight() + 0.5);
+    if ((textDecorationThickness == 0.f) || (textDecorationThickness >= (fontHeightInt >> 1)))
+        textDecorationThickness = std::max(1.f, styleToUse->computedFontSize() / 10.f);
+
     context->setStrokeThickness(textDecorationThickness);
 
+    bool antialiasDecoration = shouldSetDecorationAntialias(overline.style, underline.style, linethrough.style)
+        && RenderBoxModelObject::shouldAntialiasLines(context);
+
     float extraOffset = 0;
     if (!linesAreOpaque && shadowCount > 1) {
         FloatRect clipRect(localOrigin, FloatSize(width, baseline + 2));
@@ -1098,14 +1104,14 @@ void InlineTextBox::paintDecoration(GraphicsContext* context, const FloatPoint&
             float shadowY = isHorizontal() ? s.y() : -s.x();
             shadowRect.move(shadowX, shadowY);
             clipRect.unite(shadowRect);
-            extraOffset = max(extraOffset, max(0.0f, shadowY) + s.blur());
+            extraOffset = std::max(extraOffset, std::max(0.0f, shadowY) + s.blur());
         }
         context->clip(clipRect);
         extraOffset += baseline + 2;
         localOrigin.move(0, extraOffset);
     }
 
-    for (size_t i = max(static_cast<size_t>(1), shadowCount); i--; ) {
+    for (size_t i = std::max(static_cast<size_t>(1), shadowCount); i--; ) {
         // Even if we have no shadows, we still want to run the code below this once.
         if (i < shadowCount) {
             if (!i) {
@@ -1121,53 +1127,17 @@ void InlineTextBox::paintDecoration(GraphicsContext* context, const FloatPoint&
 
         // Offset between lines - always non-zero, so lines never cross each other.
         float doubleOffset = textDecorationThickness + 1.f;
-        context->setStrokeStyle(textDecorationStyleToStrokeStyle(decorationStyle));
+
         if (deco & TextDecorationUnderline) {
-            context->setStrokeColor(underline);
             const int underlineOffset = computeUnderlineOffset(styleToUse->textUnderlinePosition(), 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);
-            }
+            paintAppliedDecoration(context, localOrigin + FloatPoint(0, underlineOffset), width, doubleOffset, 1, underline, textDecorationThickness, antialiasDecoration, isPrinting);
         }
         if (deco & TextDecorationOverline) {
-            context->setStrokeColor(overline);
-            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:
-                context->drawLineForText(localOrigin, width, isPrinting);
-                if (decorationStyle == TextDecorationStyleDouble)
-                    context->drawLineForText(FloatPoint(localOrigin.x(), localOrigin.y() - doubleOffset), width, isPrinting);
-            }
+            paintAppliedDecoration(context, localOrigin, width, -doubleOffset, 1, overline, textDecorationThickness, antialiasDecoration, isPrinting);
         }
         if (deco & TextDecorationLineThrough) {
-            context->setStrokeColor(linethrough);
-            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:
-                context->drawLineForText(FloatPoint(localOrigin.x(), localOrigin.y() + 2 * baseline / 3), width, isPrinting);
-                if (decorationStyle == TextDecorationStyleDouble)
-                    context->drawLineForText(FloatPoint(localOrigin.x(), localOrigin.y() + doubleOffset + 2 * baseline / 3), width, isPrinting);
-            }
+            const float lineThroughOffset = 2 * baseline / 3;
+            paintAppliedDecoration(context, localOrigin + FloatPoint(0, lineThroughOffset), width, doubleOffset, 0, linethrough, textDecorationThickness, antialiasDecoration, isPrinting);
         }
     }
 }
@@ -1188,7 +1158,7 @@ static GraphicsContext::DocumentMarkerLineStyle lineStyleForMarkerType(DocumentM
 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())
+    if (renderer().document().printing())
         return;
 
     if (m_truncation == cFullTruncation)
@@ -1207,14 +1177,14 @@ void InlineTextBox::paintDocumentMarker(GraphicsContext* pt, const FloatPoint& b
         markerSpansWholeBox = false;
 
     if (!markerSpansWholeBox || grammar) {
-        int startPosition = max<int>(marker->startOffset() - m_start, 0);
-        int endPosition = min<int>(marker->endOffset() - m_start, m_len);
+        int startPosition = std::max<int>(marker->startOffset() - m_start, 0);
+        int endPosition = std::min<int>(marker->endOffset() - m_start, m_len);
 
         if (m_truncation != cNoTruncation)
-            endPosition = min<int>(endPosition, m_truncation);
+            endPosition = std::min<int>(endPosition, m_truncation);
 
         // Calculate start & width
-        int deltaY = renderer()->style()->isFlippedLinesWritingMode() ? selectionBottom() - logicalBottom() : logicalTop() - selectionTop();
+        int deltaY = renderer().style()->isFlippedLinesWritingMode() ? selectionBottom() - logicalBottom() : logicalTop() - selectionTop();
         int selHeight = selectionHeight();
         FloatPoint startPoint(boxOrigin.x(), boxOrigin.y() - deltaY);
         TextRun run = constructTextRun(style, font);
@@ -1228,7 +1198,7 @@ void InlineTextBox::paintDocumentMarker(GraphicsContext* pt, const FloatPoint& b
         // display a toolTip. We don't do this for misspelling markers.
         if (grammar) {
             markerRect.move(-boxOrigin.x(), -boxOrigin.y());
-            markerRect = renderer()->localToAbsoluteQuad(FloatRect(markerRect)).enclosingBoundingBox();
+            markerRect = renderer().localToAbsoluteQuad(FloatRect(markerRect)).enclosingBoundingBox();
             toRenderedDocumentMarker(marker)->setRenderedRect(markerRect);
         }
     }
@@ -1240,7 +1210,7 @@ void InlineTextBox::paintDocumentMarker(GraphicsContext* pt, const FloatPoint& b
     // 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 = misspellingLineThickness;
-    int baseline = renderer()->style(isFirstLineStyle())->fontMetrics().ascent();
+    int baseline = renderer().style(isFirstLineStyle())->fontMetrics().ascent();
     int descent = logicalHeight() - baseline;
     int underlineOffset;
     if (descent <= (2 + lineThickness)) {
@@ -1257,20 +1227,20 @@ void InlineTextBox::paintTextMatchMarker(GraphicsContext* pt, const FloatPoint&
 {
     // 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 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);
+    int sPos = std::max(marker->startOffset() - m_start, (unsigned)0);
+    int ePos = std::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();
+    markerRect = renderer().localToAbsoluteQuad(FloatRect(markerRect)).enclosingBoundingBox();
     toRenderedDocumentMarker(marker)->setRenderedRect(markerRect);
 
     // Optionally highlight the text
-    if (renderer()->frame()->editor().markedTextMatchesAreHighlighted()) {
+    if (renderer().frame()->editor().markedTextMatchesAreHighlighted()) {
         Color color = marker->activeMatch() ?
             RenderTheme::theme().platformActiveTextSearchHighlightColor() :
             RenderTheme::theme().platformInactiveTextSearchHighlightColor();
@@ -1281,13 +1251,32 @@ void InlineTextBox::paintTextMatchMarker(GraphicsContext* pt, const FloatPoint&
     }
 }
 
+void InlineTextBox::paintCompositionBackgrounds(GraphicsContext* pt, const FloatPoint& boxOrigin, RenderStyle* style, const Font& font, bool useCustomUnderlines)
+{
+    if (useCustomUnderlines) {
+        // Paint custom background highlights for compositions.
+        const Vector<CompositionUnderline>& underlines = renderer().frame()->inputMethodController().customCompositionUnderlines();
+        CompositionUnderlineRangeFilter filter(underlines, start(), end());
+        for (CompositionUnderlineRangeFilter::ConstIterator it = filter.begin(); it != filter.end(); ++it) {
+            if (it->backgroundColor == Color::transparent)
+                continue;
+            paintSingleCompositionBackgroundRun(pt, boxOrigin, style, font, it->backgroundColor, underlinePaintStart(*it), underlinePaintEnd(*it));
+        }
+
+    } else {
+        paintSingleCompositionBackgroundRun(pt, boxOrigin, style, font, RenderTheme::theme().platformDefaultCompositionBackgroundColor(),
+            renderer().frame()->inputMethodController().compositionStart(),
+            renderer().frame()->inputMethodController().compositionEnd());
+    }
+}
+
 void InlineTextBox::paintDocumentMarkers(GraphicsContext* pt, const FloatPoint& boxOrigin, RenderStyle* style, const Font& font, bool background)
 {
-    if (!renderer()->node())
+    if (!renderer().node())
         return;
 
-    Vector<DocumentMarker*> markers = renderer()->document().markers()->markersFor(renderer()->node());
-    Vector<DocumentMarker*>::const_iterator markerIt = markers.begin();
+    DocumentMarkerVector markers = renderer().document().markers().markersFor(renderer().node());
+    DocumentMarkerVector::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.
@@ -1341,33 +1330,21 @@ void InlineTextBox::paintCompositionUnderline(GraphicsContext* ctx, const FloatP
     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(), isLeftToRightDirection() ? LTR : RTL, 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, isLeftToRightDirection() ? LTR : RTL, isFirstLineStyle());
-    }
+    unsigned paintStart = underlinePaintStart(underline);
+    unsigned paintEnd = underlinePaintEnd(underline);
+
+    // start of line to draw, relative to paintOffset.
+    float start = paintStart == static_cast<unsigned>(m_start) ? 0 :
+        renderer().width(m_start, paintStart - m_start, textPos(), isLeftToRightDirection() ? LTR : RTL, isFirstLineStyle());
+    // how much line to draw
+    float width = (paintStart == static_cast<unsigned>(m_start) && paintEnd == static_cast<unsigned>(end()) + 1) ? m_logicalWidth :
+        renderer().width(paintStart, paintEnd - paintStart, textPos() + start, isLeftToRightDirection() ? LTR : RTL, 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();
+    int baseline = renderer().style(isFirstLineStyle())->fontMetrics().ascent();
     if (underline.thick && logicalHeight() - baseline >= 2)
         lineThickness = 2;
 
@@ -1378,7 +1355,7 @@ void InlineTextBox::paintCompositionUnderline(GraphicsContext* ctx, const FloatP
 
     ctx->setStrokeColor(underline.color);
     ctx->setStrokeThickness(lineThickness);
-    ctx->drawLineForText(FloatPoint(boxOrigin.x() + start, boxOrigin.y() + logicalHeight() - lineThickness), width, textRenderer()->document().printing());
+    ctx->drawLineForText(FloatPoint(boxOrigin.x() + start, boxOrigin.y() + logicalHeight() - lineThickness), width, renderer().document().printing());
 }
 
 int InlineTextBox::caretMinOffset() const
@@ -1397,7 +1374,7 @@ float InlineTextBox::textPos() const
     // 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();
+    return logicalLeft() - root().logicalLeft();
 }
 
 int InlineTextBox::offsetForPosition(float lineOffset, bool includePartialGlyphs) const
@@ -1412,8 +1389,8 @@ int InlineTextBox::offsetForPosition(float lineOffset, bool includePartialGlyphs
 
     FontCachePurgePreventer fontCachePurgePreventer;
 
-    RenderText* text = toRenderText(renderer());
-    RenderStyle* style = text->style(isFirstLineStyle());
+    RenderText& text = renderer();
+    RenderStyle* style = text.style(isFirstLineStyle());
     const Font& font = style->font();
     return font.offsetForPosition(constructTextRun(style, font), lineOffset - logicalLeft(), includePartialGlyphs);
 }
@@ -1428,8 +1405,8 @@ float InlineTextBox::positionForOffset(int offset) const
 
     FontCachePurgePreventer fontCachePurgePreventer;
 
-    RenderText* text = toRenderText(renderer());
-    RenderStyle* styleToUse = text->style(isFirstLineStyle());
+    RenderText& text = renderer();
+    RenderStyle* styleToUse = text.style(isFirstLineStyle());
     ASSERT(styleToUse);
     const Font& font = styleToUse->font();
     int from = !isLeftToRightDirection() ? offset - m_start : 0;
@@ -1466,8 +1443,7 @@ void InlineTextBox::characterWidths(Vector<float>& widths) const
 {
     FontCachePurgePreventer fontCachePurgePreventer;
 
-    RenderText* textObj = textRenderer();
-    RenderStyle* styleToUse = textObj->style(isFirstLineStyle());
+    RenderStyle* styleToUse = renderer().style(isFirstLineStyle());
     const Font& font = styleToUse->font();
 
     TextRun textRun = constructTextRun(styleToUse, font);
@@ -1486,28 +1462,22 @@ void InlineTextBox::characterWidths(Vector<float>& widths) const
 TextRun InlineTextBox::constructTextRun(RenderStyle* style, const Font& font, StringBuilder* charactersWithHyphen) const
 {
     ASSERT(style);
+    ASSERT(renderer().text());
 
-    RenderText* textRenderer = this->textRenderer();
-    ASSERT(textRenderer);
-    ASSERT(textRenderer->text());
-
-    StringView string = textRenderer->text().createView();
+    StringView string = renderer().text().createView();
     unsigned startPos = start();
     unsigned length = len();
 
     if (string.length() != length || startPos)
         string.narrow(startPos, length);
 
-    return constructTextRun(style, font, string, textRenderer->textLength() - startPos, charactersWithHyphen);
+    return constructTextRun(style, font, string, renderer().textLength() - startPos, charactersWithHyphen);
 }
 
 TextRun InlineTextBox::constructTextRun(RenderStyle* style, const Font& font, StringView string, int maximumLength, StringBuilder* charactersWithHyphen) const
 {
     ASSERT(style);
 
-    RenderText* textRenderer = this->textRenderer();
-    ASSERT(textRenderer);
-
     if (charactersWithHyphen) {
         const AtomicString& hyphenString = style->hyphenString();
         charactersWithHyphen->reserveCapacity(string.length() + hyphenString.length());
@@ -1519,11 +1489,11 @@ TextRun InlineTextBox::constructTextRun(RenderStyle* style, const Font& font, St
 
     ASSERT(maximumLength >= static_cast<int>(string.length()));
 
-    TextRun run(string, textPos(), expansion(), expansionBehavior(), direction(), dirOverride() || style->rtlOrdering() == VisualOrder, !textRenderer->canUseSimpleFontCodePath());
+    TextRun run(string, textPos(), expansion(), expansionBehavior(), direction(), dirOverride() || style->rtlOrdering() == VisualOrder, !renderer().canUseSimpleFontCodePath());
     run.setTabSize(!style->collapseWhiteSpace(), style->tabSize());
-    run.setCharacterScanForCodePath(!textRenderer->canUseSimpleFontCodePath());
+    run.setCharacterScanForCodePath(!renderer().canUseSimpleFontCodePath());
     if (textRunNeedsRenderingContext(font))
-        run.setRenderingContext(SVGTextRunRenderingContext::create(textRenderer));
+        run.setRenderingContext(SVGTextRunRenderingContext::create(&renderer()));
 
     // Propagate the maximum length of the characters buffer to the TextRun, even when we're only processing a substring.
     run.setCharactersLength(maximumLength);
@@ -1545,15 +1515,15 @@ const char* InlineTextBox::boxName() const
 
 void InlineTextBox::showBox(int printedCharacters) const
 {
-    const RenderText* obj = toRenderText(renderer());
-    String value = obj->text();
+    const RenderText& obj = 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);
+    printedCharacters = fprintf(stderr, "\t%s %p", obj.renderName(), &obj);
     const int rendererCharacterOffset = 24;
     for (; printedCharacters < rendererCharacterOffset; printedCharacters++)
         fputc(' ', stderr);
@@ -1562,4 +1532,4 @@ void InlineTextBox::showBox(int printedCharacters) const
 
 #endif
 
-} // namespace WebCore
+} // namespace blink