Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / rendering / InlineFlowBox.cpp
index e3186f5..4d0c4a6 100644 (file)
@@ -22,6 +22,8 @@
 
 #include "core/CSSPropertyNames.h"
 #include "core/dom/Document.h"
+#include "core/paint/BoxPainter.h"
+#include "core/paint/InlineFlowBoxPainter.h"
 #include "core/rendering/HitTestResult.h"
 #include "core/rendering/InlineTextBox.h"
 #include "core/rendering/RenderBlock.h"
@@ -382,12 +384,19 @@ float InlineFlowBox::placeBoxRangeInInlineDirection(InlineBox* firstChild, Inlin
         if (curr->renderer().isText()) {
             InlineTextBox* text = toInlineTextBox(curr);
             RenderText& rt = text->renderer();
+            float space = 0;
             if (rt.textLength()) {
                 if (needsWordSpacing && isSpaceOrNewline(rt.characterAt(text->start())))
-                    logicalLeft += rt.style(isFirstLineStyle())->font().fontDescription().wordSpacing();
+                    space = rt.style(isFirstLineStyle())->font().fontDescription().wordSpacing();
                 needsWordSpacing = !isSpaceOrNewline(rt.characterAt(text->end()));
             }
-            text->setLogicalLeft(logicalLeft);
+            if (isLeftToRightDirection()) {
+                logicalLeft += space;
+                text->setLogicalLeft(logicalLeft);
+            } else {
+                text->setLogicalLeft(logicalLeft);
+                logicalLeft += space;
+            }
             if (knownToHaveNoOverflow())
                 minLogicalLeft = std::min(logicalLeft, minLogicalLeft);
             logicalLeft += text->logicalWidth();
@@ -940,7 +949,7 @@ void InlineFlowBox::computeOverflow(LayoutUnit lineTop, LayoutUnit lineBottom, G
     if (m_overflow)
         m_overflow.clear();
 
-    // Visual overflow just includes overflow for stuff we need to repaint ourselves.  Self-painting layers are ignored.
+    // Visual overflow just includes overflow for stuff we need to issues paint invalidations for 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)));
@@ -1090,77 +1099,7 @@ bool InlineFlowBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& re
 
 void InlineFlowBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit lineTop, LayoutUnit lineBottom)
 {
-    LayoutRect overflowRect(visualOverflowRect(lineTop, lineBottom));
-    flipForWritingMode(overflowRect);
-    overflowRect.moveBy(paintOffset);
-
-    if (!paintInfo.rect.intersects(pixelSnappedIntRect(overflowRect)))
-        return;
-
-    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 if (paintInfo.phase == PaintPhaseForeground) {
-        // Paint our background, border and box-shadow.
-        paintBoxDecorationBackground(paintInfo, paintOffset);
-    }
-
-    // Paint our children.
-    if (paintInfo.phase != PaintPhaseSelfOutline) {
-        PaintInfo childInfo(paintInfo);
-        childInfo.phase = paintInfo.phase == PaintPhaseChildOutlines ? PaintPhaseOutline : paintInfo.phase;
-
-        if (childInfo.paintingRoot && childInfo.paintingRoot->isDescendantOf(&renderer()))
-            childInfo.paintingRoot = 0;
-        else
-            childInfo.updatePaintingRootForChildren(&renderer());
-
-        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.next())
-        paintFillLayers(paintInfo, c, *fillLayer.next(), rect, op);
-    paintFillLayer(paintInfo, c, fillLayer, rect, op);
+    InlineFlowBoxPainter(*this).paint(paintInfo, paintOffset, lineTop, lineBottom);
 }
 
 bool InlineFlowBox::boxShadowCanBeAppliedToBackground(const FillLayer& lastBackgroundLayer) const
@@ -1172,60 +1111,6 @@ bool InlineFlowBox::boxShadowCanBeAppliedToBackground(const FillLayer& lastBackg
     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();
@@ -1246,184 +1131,6 @@ void InlineFlowBox::constrainToLineTopAndBottomIfNeeded(LayoutRect& rect) const
     }
 }
 
-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::paintBoxDecorationBackground(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
-{
-    ASSERT(paintInfo.phase == PaintPhaseForeground);
-    if (!paintInfo.shouldPaintWithinRoot(&renderer()) || renderer().style()->visibility() != VISIBLE)
-        return;
-
-    // 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());
-    bool shouldPaintBoxDecorationBackground;
-    if (parent())
-        shouldPaintBoxDecorationBackground = renderer().hasBoxDecorationBackground();
-    else
-        shouldPaintBoxDecorationBackground = isFirstLineStyle() && styleToUse != renderer().style();
-
-    if (!shouldPaintBoxDecorationBackground)
-        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();
-
-    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 backgroundColor = renderer().resolveColor(styleToUse, CSSPropertyBackgroundColor);
-    paintFillLayers(paintInfo, backgroundColor, 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(*paintInfo.context);
-            paintInfo.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::transparent, renderer().style()->maskLayers(), paintRect, compositeOp);
-
-    bool hasBoxImage = maskBoxImage && maskBoxImage->canRender(renderer(), renderer().style()->effectiveZoom());
-    if (!hasBoxImage || !maskBoxImage->isLoaded()) {
-        if (pushTransparencyLayer)
-            paintInfo.context->endLayer();
-        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->endLayer();
-}
-
 InlineBox* InlineFlowBox::firstLeafChild() const
 {
     InlineBox* leaf = 0;
@@ -1440,7 +1147,7 @@ InlineBox* InlineFlowBox::lastLeafChild() const
     return leaf;
 }
 
-RenderObject::SelectionState InlineFlowBox::selectionState()
+RenderObject::SelectionState InlineFlowBox::selectionState() const
 {
     return RenderObject::SelectionNone;
 }