17242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci// Copyright 2014 The Chromium Authors. All rights reserved.
27242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci// Use of this source code is governed by a BSD-style license that can be
37242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci// found in the LICENSE file.
47242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
57242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "config.h"
67242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "core/paint/InlineFlowBoxPainter.h"
77242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
87242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "core/paint/BoxPainter.h"
97242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "core/rendering/InlineFlowBox.h"
107242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "core/rendering/PaintInfo.h"
117242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "core/rendering/RenderBlock.h"
127242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "core/rendering/RenderInline.h"
137242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "core/rendering/RenderLayer.h"
147242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "core/rendering/RenderView.h"
157242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "platform/graphics/GraphicsContextStateSaver.h"
167242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
177242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccinamespace blink {
187242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
197242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccivoid InlineFlowBoxPainter::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, const LayoutUnit lineTop, const LayoutUnit lineBottom)
207242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci{
217242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    LayoutRect overflowRect(m_inlineFlowBox.visualOverflowRect(lineTop, lineBottom));
227242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    m_inlineFlowBox.flipForWritingMode(overflowRect);
237242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    overflowRect.moveBy(paintOffset);
247242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
257242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (!paintInfo.rect.intersects(pixelSnappedIntRect(overflowRect)))
267242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        return;
277242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
287242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) {
297242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        // Add ourselves to the paint info struct's list of inlines that need to paint their
307242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        // outlines.
317242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        if (m_inlineFlowBox.renderer().style()->visibility() == VISIBLE && m_inlineFlowBox.renderer().style()->hasOutline() && !m_inlineFlowBox.isRootInlineBox()) {
327242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            RenderInline& inlineFlow = toRenderInline(m_inlineFlowBox.renderer());
337242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
347242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            RenderBlock* cb = 0;
357242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            bool containingBlockPaintsContinuationOutline = inlineFlow.continuation() || inlineFlow.isInlineElementContinuation();
367242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            if (containingBlockPaintsContinuationOutline) {
377242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci                // FIXME: See https://bugs.webkit.org/show_bug.cgi?id=54690. We currently don't reconnect inline continuations
387242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci                // after a child removal. As a result, those merged inlines do not get seperated and hence not get enclosed by
397242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci                // anonymous blocks. In this case, it is better to bail out and paint it ourself.
407242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci                RenderBlock* enclosingAnonymousBlock = m_inlineFlowBox.renderer().containingBlock();
417242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci                if (!enclosingAnonymousBlock->isAnonymousBlock()) {
427242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci                    containingBlockPaintsContinuationOutline = false;
437242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci                } else {
447242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci                    cb = enclosingAnonymousBlock->containingBlock();
457242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci                    for (RenderBoxModelObject* box = m_inlineFlowBox.boxModelObject(); box != cb; box = box->parent()->enclosingBoxModelObject()) {
467242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci                        if (box->hasSelfPaintingLayer()) {
477242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci                            containingBlockPaintsContinuationOutline = false;
487242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci                            break;
497242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci                        }
507242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci                    }
517242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci                }
527242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            }
537242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
547242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            if (containingBlockPaintsContinuationOutline) {
557242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci                // Add ourselves to the containing block of the entire continuation so that it can
567242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci                // paint us atomically.
577242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci                cb->addContinuationWithOutline(toRenderInline(m_inlineFlowBox.renderer().node()->renderer()));
587242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            } else if (!inlineFlow.isInlineElementContinuation()) {
597242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci                paintInfo.outlineObjects()->add(&inlineFlow);
607242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            }
617242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        }
627242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    } else if (paintInfo.phase == PaintPhaseMask) {
637242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        paintMask(paintInfo, paintOffset);
647242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        return;
657242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    } else if (paintInfo.phase == PaintPhaseForeground) {
667242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        // Paint our background, border and box-shadow.
677242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        paintBoxDecorationBackground(paintInfo, paintOffset);
687242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    }
697242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
707242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // Paint our children.
717242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (paintInfo.phase != PaintPhaseSelfOutline) {
727242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        PaintInfo childInfo(paintInfo);
737242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        childInfo.phase = paintInfo.phase == PaintPhaseChildOutlines ? PaintPhaseOutline : paintInfo.phase;
747242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
757242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        if (childInfo.paintingRoot && childInfo.paintingRoot->isDescendantOf(&m_inlineFlowBox.renderer()))
767242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            childInfo.paintingRoot = 0;
777242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        else
787242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            childInfo.updatePaintingRootForChildren(&m_inlineFlowBox.renderer());
797242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
807242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        for (InlineBox* curr = m_inlineFlowBox.firstChild(); curr; curr = curr->nextOnLine()) {
817242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            if (curr->renderer().isText() || !curr->boxModelObject()->hasSelfPaintingLayer())
827242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci                curr->paint(childInfo, paintOffset, lineTop, lineBottom);
837242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        }
847242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    }
857242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci}
867242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
877242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccivoid InlineFlowBoxPainter::paintFillLayers(const PaintInfo& paintInfo, const Color& c, const FillLayer& fillLayer, const LayoutRect& rect, CompositeOperator op)
887242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci{
897242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // FIXME: This should be a for loop or similar. It's a little non-trivial to do so, however, since the layers need to be
907242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // painted in reverse order.
917242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (fillLayer.next())
927242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        paintFillLayers(paintInfo, c, *fillLayer.next(), rect, op);
937242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    paintFillLayer(paintInfo, c, fillLayer, rect, op);
947242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci}
957242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
967242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccivoid InlineFlowBoxPainter::paintFillLayer(const PaintInfo& paintInfo, const Color& c, const FillLayer& fillLayer, const LayoutRect& rect, CompositeOperator op)
977242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci{
987242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    StyleImage* img = fillLayer.image();
997242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    bool hasFillImage = img && img->canRender(m_inlineFlowBox.renderer(), m_inlineFlowBox.renderer().style()->effectiveZoom());
1007242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if ((!hasFillImage && !m_inlineFlowBox.renderer().style()->hasBorderRadius()) || (!m_inlineFlowBox.prevLineBox() && !m_inlineFlowBox.nextLineBox()) || !m_inlineFlowBox.parent()) {
1017242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        BoxPainter::paintFillLayerExtended(*m_inlineFlowBox.boxModelObject(), paintInfo, c, fillLayer, rect, BackgroundBleedNone, &m_inlineFlowBox, rect.size(), op);
1027242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    } else if (m_inlineFlowBox.renderer().style()->boxDecorationBreak() == DCLONE) {
1037242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        GraphicsContextStateSaver stateSaver(*paintInfo.context);
1047242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        paintInfo.context->clip(LayoutRect(rect.x(), rect.y(), m_inlineFlowBox.width(), m_inlineFlowBox.height()));
1057242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        BoxPainter::paintFillLayerExtended(*m_inlineFlowBox.boxModelObject(), paintInfo, c, fillLayer, rect, BackgroundBleedNone, &m_inlineFlowBox, rect.size(), op);
1067242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    } else {
1077242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        // We have a fill image that spans multiple lines.
1087242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        // We need to adjust tx and ty by the width of all previous lines.
1097242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        // Think of background painting on inlines as though you had one long line, a single continuous
1107242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        // strip. Even though that strip has been broken up across multiple lines, you still paint it
1117242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        // as though you had one single line. This means each line has to pick up the background where
1127242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        // the previous line left off.
1137242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        LayoutUnit logicalOffsetOnLine = 0;
1147242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        LayoutUnit totalLogicalWidth;
1157242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        if (m_inlineFlowBox.renderer().style()->direction() == LTR) {
1167242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            for (InlineFlowBox* curr = m_inlineFlowBox.prevLineBox(); curr; curr = curr->prevLineBox())
1177242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci                logicalOffsetOnLine += curr->logicalWidth();
1187242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            totalLogicalWidth = logicalOffsetOnLine;
1197242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            for (InlineFlowBox* curr = &m_inlineFlowBox; curr; curr = curr->nextLineBox())
1207242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci                totalLogicalWidth += curr->logicalWidth();
1217242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        } else {
1227242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            for (InlineFlowBox* curr = m_inlineFlowBox.nextLineBox(); curr; curr = curr->nextLineBox())
1237242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci                logicalOffsetOnLine += curr->logicalWidth();
1247242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            totalLogicalWidth = logicalOffsetOnLine;
1257242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            for (InlineFlowBox* curr = &m_inlineFlowBox; curr; curr = curr->prevLineBox())
1267242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci                totalLogicalWidth += curr->logicalWidth();
1277242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        }
1287242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        LayoutUnit stripX = rect.x() - (m_inlineFlowBox.isHorizontal() ? logicalOffsetOnLine : LayoutUnit());
1297242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        LayoutUnit stripY = rect.y() - (m_inlineFlowBox.isHorizontal() ? LayoutUnit() : logicalOffsetOnLine);
1307242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        LayoutUnit stripWidth = m_inlineFlowBox.isHorizontal() ? totalLogicalWidth : static_cast<LayoutUnit>(m_inlineFlowBox.width());
1317242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        LayoutUnit stripHeight = m_inlineFlowBox.isHorizontal() ? static_cast<LayoutUnit>(m_inlineFlowBox.height()) : totalLogicalWidth;
1327242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
1337242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        GraphicsContextStateSaver stateSaver(*paintInfo.context);
1347242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        paintInfo.context->clip(LayoutRect(rect.x(), rect.y(), m_inlineFlowBox.width(), m_inlineFlowBox.height()));
1357242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        BoxPainter::paintFillLayerExtended(*m_inlineFlowBox.boxModelObject(), paintInfo, c, fillLayer, LayoutRect(stripX, stripY, stripWidth, stripHeight), BackgroundBleedNone, &m_inlineFlowBox, rect.size(), op);
1367242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    }
1377242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci}
1387242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
1397242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccivoid InlineFlowBoxPainter::paintBoxShadow(const PaintInfo& info, RenderStyle* s, ShadowStyle shadowStyle, const LayoutRect& paintRect)
1407242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci{
1417242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if ((!m_inlineFlowBox.prevLineBox() && !m_inlineFlowBox.nextLineBox()) || !m_inlineFlowBox.parent()) {
1427242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        BoxPainter::paintBoxShadow(info, paintRect, s, shadowStyle);
1437242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    } else {
1447242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        // FIXME: We can do better here in the multi-line case. We want to push a clip so that the shadow doesn't
1457242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        // protrude incorrectly at the edges, and we want to possibly include shadows cast from the previous/following lines
1467242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        BoxPainter::paintBoxShadow(info, paintRect, s, shadowStyle, m_inlineFlowBox.includeLogicalLeftEdge(), m_inlineFlowBox.includeLogicalRightEdge());
1477242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    }
1487242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci}
1497242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
1507242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
1517242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccistatic LayoutRect clipRectForNinePieceImageStrip(InlineFlowBox* box, const NinePieceImage& image, const LayoutRect& paintRect)
1527242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci{
1537242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    LayoutRect clipRect(paintRect);
1547242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    RenderStyle* style = box->renderer().style();
1557242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    LayoutBoxExtent outsets = style->imageOutsets(image);
1567242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (box->isHorizontal()) {
1577242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        clipRect.setY(paintRect.y() - outsets.top());
1587242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        clipRect.setHeight(paintRect.height() + outsets.top() + outsets.bottom());
1597242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        if (box->includeLogicalLeftEdge()) {
1607242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            clipRect.setX(paintRect.x() - outsets.left());
1617242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            clipRect.setWidth(paintRect.width() + outsets.left());
1627242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        }
1637242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        if (box->includeLogicalRightEdge())
1647242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            clipRect.setWidth(clipRect.width() + outsets.right());
1657242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    } else {
1667242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        clipRect.setX(paintRect.x() - outsets.left());
1677242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        clipRect.setWidth(paintRect.width() + outsets.left() + outsets.right());
1687242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        if (box->includeLogicalLeftEdge()) {
1697242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            clipRect.setY(paintRect.y() - outsets.top());
1707242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            clipRect.setHeight(paintRect.height() + outsets.top());
1717242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        }
1727242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        if (box->includeLogicalRightEdge())
1737242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            clipRect.setHeight(clipRect.height() + outsets.bottom());
1747242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    }
1757242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    return clipRect;
1767242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci}
1777242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
1787242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccivoid InlineFlowBoxPainter::paintBoxDecorationBackground(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
1797242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci{
1807242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    ASSERT(paintInfo.phase == PaintPhaseForeground);
1817242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (!paintInfo.shouldPaintWithinRoot(&m_inlineFlowBox.renderer()) || m_inlineFlowBox.renderer().style()->visibility() != VISIBLE)
1827242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        return;
1837242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
1847242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // You can use p::first-line to specify a background. If so, the root line boxes for
1857242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // a line may actually have to paint a background.
1867242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    RenderStyle* styleToUse = m_inlineFlowBox.renderer().style(m_inlineFlowBox.isFirstLineStyle());
1877242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    bool shouldPaintBoxDecorationBackground;
1887242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (m_inlineFlowBox.parent())
1897242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        shouldPaintBoxDecorationBackground = m_inlineFlowBox.renderer().hasBoxDecorationBackground();
1907242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    else
1917242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        shouldPaintBoxDecorationBackground = m_inlineFlowBox.isFirstLineStyle() && styleToUse != m_inlineFlowBox.renderer().style();
1927242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
1937242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (!shouldPaintBoxDecorationBackground)
1947242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        return;
1957242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
1967242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    LayoutRect frameRect = roundedFrameRectClampedToLineTopAndBottomIfNeeded();
1977242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
1987242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // Move x/y to our coordinates.
1997242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    LayoutRect localRect(frameRect);
2007242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    m_inlineFlowBox.flipForWritingMode(localRect);
2017242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    LayoutPoint adjustedPaintOffset = paintOffset + localRect.location();
2027242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
2037242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    LayoutRect paintRect = LayoutRect(adjustedPaintOffset, frameRect.size());
2047242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
2057242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // Shadow comes first and is behind the background and border.
2067242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (!m_inlineFlowBox.boxModelObject()->boxShadowShouldBeAppliedToBackground(BackgroundBleedNone, &m_inlineFlowBox))
2077242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        paintBoxShadow(paintInfo, styleToUse, Normal, paintRect);
2087242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
2097242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    Color backgroundColor = m_inlineFlowBox.renderer().resolveColor(styleToUse, CSSPropertyBackgroundColor);
2107242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    paintFillLayers(paintInfo, backgroundColor, styleToUse->backgroundLayers(), paintRect);
2117242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    paintBoxShadow(paintInfo, styleToUse, Inset, paintRect);
2127242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
2137242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // :first-line cannot be used to put borders on a line. Always paint borders with our
2147242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // non-first-line style.
2157242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (m_inlineFlowBox.parent() && m_inlineFlowBox.renderer().style()->hasBorder()) {
2167242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        const NinePieceImage& borderImage = m_inlineFlowBox.renderer().style()->borderImage();
2177242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        StyleImage* borderImageSource = borderImage.image();
2187242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        bool hasBorderImage = borderImageSource && borderImageSource->canRender(m_inlineFlowBox.renderer(), styleToUse->effectiveZoom());
2197242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        if (hasBorderImage && !borderImageSource->isLoaded())
2207242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            return; // Don't paint anything while we wait for the image to load.
2217242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
2227242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        // The simple case is where we either have no border image or we are the only box for this object.
2237242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        // In those cases only a single call to draw is required.
2247242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        if (!hasBorderImage || (!m_inlineFlowBox.prevLineBox() && !m_inlineFlowBox.nextLineBox())) {
2257242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            BoxPainter::paintBorder(*m_inlineFlowBox.boxModelObject(), paintInfo, paintRect, m_inlineFlowBox.renderer().style(m_inlineFlowBox.isFirstLineStyle()), BackgroundBleedNone, m_inlineFlowBox.includeLogicalLeftEdge(), m_inlineFlowBox.includeLogicalRightEdge());
2267242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        } else {
2277242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            // We have a border image that spans multiple lines.
2287242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            // We need to adjust tx and ty by the width of all previous lines.
2297242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            // Think of border image painting on inlines as though you had one long line, a single continuous
2307242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            // strip. Even though that strip has been broken up across multiple lines, you still paint it
2317242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            // as though you had one single line. This means each line has to pick up the image where
2327242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            // the previous line left off.
2337242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            // FIXME: What the heck do we do with RTL here? The math we're using is obviously not right,
2347242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            // but it isn't even clear how this should work at all.
2357242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            LayoutUnit logicalOffsetOnLine = 0;
2367242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            for (InlineFlowBox* curr = m_inlineFlowBox.prevLineBox(); curr; curr = curr->prevLineBox())
2377242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci                logicalOffsetOnLine += curr->logicalWidth();
2387242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            LayoutUnit totalLogicalWidth = logicalOffsetOnLine;
2397242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            for (InlineFlowBox* curr = &m_inlineFlowBox; curr; curr = curr->nextLineBox())
2407242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci                totalLogicalWidth += curr->logicalWidth();
2417242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            LayoutUnit stripX = adjustedPaintOffset.x() - (m_inlineFlowBox.isHorizontal() ? logicalOffsetOnLine : LayoutUnit());
2427242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            LayoutUnit stripY = adjustedPaintOffset.y() - (m_inlineFlowBox.isHorizontal() ? LayoutUnit() : logicalOffsetOnLine);
2437242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            LayoutUnit stripWidth = m_inlineFlowBox.isHorizontal() ? totalLogicalWidth : frameRect.width();
2447242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            LayoutUnit stripHeight = m_inlineFlowBox.isHorizontal() ? frameRect.height() : totalLogicalWidth;
2457242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
2467242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            LayoutRect clipRect = clipRectForNinePieceImageStrip(&m_inlineFlowBox, borderImage, paintRect);
2477242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            GraphicsContextStateSaver stateSaver(*paintInfo.context);
2487242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            paintInfo.context->clip(clipRect);
2497242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            BoxPainter::paintBorder(*m_inlineFlowBox.boxModelObject(), paintInfo, LayoutRect(stripX, stripY, stripWidth, stripHeight), m_inlineFlowBox.renderer().style(m_inlineFlowBox.isFirstLineStyle()));
2507242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        }
2517242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    }
2527242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci}
2537242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
2547242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccivoid InlineFlowBoxPainter::paintMask(PaintInfo& paintInfo, const LayoutPoint& paintOffset)
2557242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci{
2567242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (!paintInfo.shouldPaintWithinRoot(&m_inlineFlowBox.renderer()) || m_inlineFlowBox.renderer().style()->visibility() != VISIBLE || paintInfo.phase != PaintPhaseMask)
2577242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        return;
2587242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
2597242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    LayoutRect frameRect = roundedFrameRectClampedToLineTopAndBottomIfNeeded();
2607242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
2617242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // Move x/y to our coordinates.
2627242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    LayoutRect localRect(frameRect);
2637242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    m_inlineFlowBox.flipForWritingMode(localRect);
2647242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    LayoutPoint adjustedPaintOffset = paintOffset + localRect.location();
2657242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
2667242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    const NinePieceImage& maskNinePieceImage = m_inlineFlowBox.renderer().style()->maskBoxImage();
2677242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    StyleImage* maskBoxImage = m_inlineFlowBox.renderer().style()->maskBoxImage().image();
2687242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
2697242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // Figure out if we need to push a transparency layer to render our mask.
2707242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    bool pushTransparencyLayer = false;
2717242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    bool compositedMask = m_inlineFlowBox.renderer().hasLayer() && m_inlineFlowBox.boxModelObject()->layer()->hasCompositedMask();
2727242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    bool flattenCompositingLayers = m_inlineFlowBox.renderer().view()->frameView() && m_inlineFlowBox.renderer().view()->frameView()->paintBehavior() & PaintBehaviorFlattenCompositingLayers;
2737242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    CompositeOperator compositeOp = CompositeSourceOver;
2747242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (!compositedMask || flattenCompositingLayers) {
2757242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        if ((maskBoxImage && m_inlineFlowBox.renderer().style()->maskLayers().hasImage()) || m_inlineFlowBox.renderer().style()->maskLayers().next())
2767242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            pushTransparencyLayer = true;
2777242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
2787242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        compositeOp = CompositeDestinationIn;
2797242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        if (pushTransparencyLayer) {
2807242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            paintInfo.context->setCompositeOperation(CompositeDestinationIn);
2817242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            paintInfo.context->beginTransparencyLayer(1.0f);
2827242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            compositeOp = CompositeSourceOver;
2837242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        }
2847242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    }
2857242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
2867242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    LayoutRect paintRect = LayoutRect(adjustedPaintOffset, frameRect.size());
2877242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    paintFillLayers(paintInfo, Color::transparent, m_inlineFlowBox.renderer().style()->maskLayers(), paintRect, compositeOp);
2887242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
2897242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    bool hasBoxImage = maskBoxImage && maskBoxImage->canRender(m_inlineFlowBox.renderer(), m_inlineFlowBox.renderer().style()->effectiveZoom());
2907242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (!hasBoxImage || !maskBoxImage->isLoaded()) {
2917242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        if (pushTransparencyLayer)
2927242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            paintInfo.context->endLayer();
2937242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        return; // Don't paint anything while we wait for the image to load.
2947242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    }
2957242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
2967242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // The simple case is where we are the only box for this object. In those
2977242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // cases only a single call to draw is required.
2987242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (!m_inlineFlowBox.prevLineBox() && !m_inlineFlowBox.nextLineBox()) {
2997242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        BoxPainter::paintNinePieceImage(*m_inlineFlowBox.boxModelObject(), paintInfo.context, LayoutRect(adjustedPaintOffset, frameRect.size()), m_inlineFlowBox.renderer().style(), maskNinePieceImage, compositeOp);
3007242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    } else {
3017242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        // We have a mask image that spans multiple lines.
3027242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        // We need to adjust _tx and _ty by the width of all previous lines.
3037242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        LayoutUnit logicalOffsetOnLine = 0;
3047242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        for (InlineFlowBox* curr = m_inlineFlowBox.prevLineBox(); curr; curr = curr->prevLineBox())
3057242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            logicalOffsetOnLine += curr->logicalWidth();
3067242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        LayoutUnit totalLogicalWidth = logicalOffsetOnLine;
3077242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        for (InlineFlowBox* curr = &m_inlineFlowBox; curr; curr = curr->nextLineBox())
3087242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            totalLogicalWidth += curr->logicalWidth();
3097242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        LayoutUnit stripX = adjustedPaintOffset.x() - (m_inlineFlowBox.isHorizontal() ? logicalOffsetOnLine : LayoutUnit());
3107242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        LayoutUnit stripY = adjustedPaintOffset.y() - (m_inlineFlowBox.isHorizontal() ? LayoutUnit() : logicalOffsetOnLine);
3117242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        LayoutUnit stripWidth = m_inlineFlowBox.isHorizontal() ? totalLogicalWidth : frameRect.width();
3127242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        LayoutUnit stripHeight = m_inlineFlowBox.isHorizontal() ? frameRect.height() : totalLogicalWidth;
3137242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
3147242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        LayoutRect clipRect = clipRectForNinePieceImageStrip(&m_inlineFlowBox, maskNinePieceImage, paintRect);
3157242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        GraphicsContextStateSaver stateSaver(*paintInfo.context);
3167242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        paintInfo.context->clip(clipRect);
3177242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        BoxPainter::paintNinePieceImage(*m_inlineFlowBox.boxModelObject(), paintInfo.context, LayoutRect(stripX, stripY, stripWidth, stripHeight), m_inlineFlowBox.renderer().style(), maskNinePieceImage, compositeOp);
3187242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    }
3197242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
3207242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (pushTransparencyLayer)
3217242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        paintInfo.context->endLayer();
3227242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci}
3237242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
3247242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano TucciLayoutRect InlineFlowBoxPainter::roundedFrameRectClampedToLineTopAndBottomIfNeeded() const
3257242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci{
3267242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // Pixel snap rect painting.
3277242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    LayoutRect rect = m_inlineFlowBox.roundedFrameRect();
3287242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
3297242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    bool noQuirksMode = m_inlineFlowBox.renderer().document().inNoQuirksMode();
3307242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (!noQuirksMode && !m_inlineFlowBox.hasTextChildren() && !(m_inlineFlowBox.descendantsHaveSameLineHeightAndBaseline() && m_inlineFlowBox.hasTextDescendants())) {
3317242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        const RootInlineBox& rootBox = m_inlineFlowBox.root();
3327242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        LayoutUnit logicalTop = m_inlineFlowBox.isHorizontal() ? rect.y() : rect.x();
3337242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        LayoutUnit logicalHeight = m_inlineFlowBox.isHorizontal() ? rect.height() : rect.width();
3347242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        LayoutUnit bottom = std::min(rootBox.lineBottom(), logicalTop + logicalHeight);
3357242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        logicalTop = std::max(rootBox.lineTop(), logicalTop);
3367242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        logicalHeight = bottom - logicalTop;
3377242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        if (m_inlineFlowBox.isHorizontal()) {
3387242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            rect.setY(logicalTop);
3397242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            rect.setHeight(logicalHeight);
3407242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        } else {
3417242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            rect.setX(logicalTop);
3427242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            rect.setWidth(logicalHeight);
3437242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        }
3447242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    }
3457242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    return rect;
3467242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci}
3477242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
3487242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci} // namespace blink
349