15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/**
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2007 Rob Buis <buis@kde.org>
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) Research In Motion Limited 2010. All rights reserved.
55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is free software; you can redistribute it and/or
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modify it under the terms of the GNU Library General Public
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * License as published by the Free Software Foundation; either
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * version 2 of the License, or (at your option) any later version.
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is distributed in the hope that it will be useful,
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * but WITHOUT ANY WARRANTY; without even the implied warranty of
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Library General Public License for more details.
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * You should have received a copy of the GNU Library General Public License
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * along with this library; see the file COPYING.LIB.  If not, write to
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Boston, MA 02110-1301, USA.
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h"
2353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/svg/SVGInlineTextBox.h"
245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "core/dom/DocumentMarkerController.h"
2609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "core/dom/RenderedDocumentMarker.h"
2709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "core/editing/Editor.h"
281e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "core/frame/FrameView.h"
29d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)#include "core/frame/LocalFrame.h"
307242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "core/paint/InlinePainter.h"
3153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/HitTestResult.h"
3253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/InlineFlowBox.h"
33d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)#include "core/rendering/PaintInfo.h"
3453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/PointerEventsHitRules.h"
35d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)#include "core/rendering/RenderInline.h"
3609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#include "core/rendering/RenderTheme.h"
37f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)#include "core/rendering/style/ShadowList.h"
3853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/svg/RenderSVGInlineText.h"
3953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/svg/RenderSVGResource.h"
4053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/svg/RenderSVGResourceSolidColor.h"
417242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "core/rendering/svg/SVGRenderSupport.h"
4253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/svg/SVGResourcesCache.h"
4353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/svg/SVGTextRunRenderingContext.h"
441e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)#include "platform/FloatConversion.h"
45a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/fonts/FontCache.h"
46a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/graphics/GraphicsContextStateSaver.h"
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
48c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)struct ExpectedSVGInlineTextBoxSize : public InlineTextBox {
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    float float1;
526f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    uint32_t bitfields : 1;
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Vector<SVGTextFragment> vector;
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)};
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)COMPILE_ASSERT(sizeof(SVGInlineTextBox) == sizeof(ExpectedSVGInlineTextBoxSize), SVGInlineTextBox_is_not_of_expected_size);
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
58d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)SVGInlineTextBox::SVGInlineTextBox(RenderObject& object)
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    : InlineTextBox(object)
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_logicalHeight(0)
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_startsNewTextChunk(false)
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGInlineTextBox::dirtyLineBoxes()
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    InlineTextBox::dirtyLineBoxes();
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Clear the now stale text fragments
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    clearTextFragments();
7193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
7293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    // And clear any following text fragments as the text on which they
7393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    // depend may now no longer exist, or glyph positions may be wrong
7493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    InlineTextBox* nextBox = nextTextBox();
7593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    if (nextBox)
7693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        nextBox->dirtyLineBoxes();
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)int SVGInlineTextBox::offsetForPosition(float, bool) const
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // SVG doesn't use the standard offset <-> position selection system, as it's not suitable for SVGs complex needs.
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // vertical text selection, inline boxes spanning multiple lines (contrary to HTML, etc.)
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT_NOT_REACHED();
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return 0;
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)int SVGInlineTextBox::offsetForPositionInFragment(const SVGTextFragment& fragment, float position, bool includePartialGlyphs) const
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
89c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    RenderSVGInlineText& textRenderer = toRenderSVGInlineText(this->renderer());
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
91d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    float scalingFactor = textRenderer.scalingFactor();
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(scalingFactor);
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
94d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    RenderStyle* style = textRenderer.style();
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(style);
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    TextRun textRun = constructTextRun(style, fragment);
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Eventually handle lengthAdjust="spacingAndGlyphs".
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // FIXME: Handle vertical text.
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    AffineTransform fragmentTransform;
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    fragment.buildFragmentTransform(fragmentTransform);
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!fragmentTransform.isIdentity())
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        textRun.setHorizontalGlyphStretch(narrowPrecisionToFloat(fragmentTransform.xScale()));
1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
106d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    return fragment.characterOffset - start() + textRenderer.scaledFont().offsetForPosition(textRun, position * scalingFactor, includePartialGlyphs);
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)float SVGInlineTextBox::positionForOffset(int) const
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
11102772c6a72f1ee0b226341a4f4439970c29fc861Ben Murdoch    // SVG doesn't use the offset <-> position selection system.
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT_NOT_REACHED();
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return 0;
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)FloatRect SVGInlineTextBox::selectionRectForTextFragment(const SVGTextFragment& fragment, int startPosition, int endPosition, RenderStyle* style)
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(startPosition < endPosition);
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(style);
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FontCachePurgePreventer fontCachePurgePreventer;
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
123c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    RenderSVGInlineText& textRenderer = toRenderSVGInlineText(this->renderer());
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
125d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    float scalingFactor = textRenderer.scalingFactor();
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(scalingFactor);
1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
128d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    const Font& scaledFont = textRenderer.scaledFont();
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const FontMetrics& scaledFontMetrics = scaledFont.fontMetrics();
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FloatPoint textOrigin(fragment.x, fragment.y);
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (scalingFactor != 1)
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        textOrigin.scale(scalingFactor, scalingFactor);
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    textOrigin.move(0, -scaledFontMetrics.floatAscent());
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FloatRect selectionRect = scaledFont.selectionRectForText(constructTextRun(style, fragment), textOrigin, fragment.height * scalingFactor, startPosition, endPosition);
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (scalingFactor == 1)
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return selectionRect;
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    selectionRect.scale(1 / scalingFactor);
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return selectionRect;
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)LayoutRect SVGInlineTextBox::localSelectionRect(int startPosition, int endPosition)
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int boxStart = start();
147197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    startPosition = std::max(startPosition - boxStart, 0);
148197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    endPosition = std::min(endPosition - boxStart, static_cast<int>(len()));
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (startPosition >= endPosition)
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return LayoutRect();
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
152c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    RenderStyle* style = renderer().style();
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(style);
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    AffineTransform fragmentTransform;
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FloatRect selectionRect;
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int fragmentStartPosition = 0;
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int fragmentEndPosition = 0;
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned textFragmentsSize = m_textFragments.size();
1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (unsigned i = 0; i < textFragmentsSize; ++i) {
1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        const SVGTextFragment& fragment = m_textFragments.at(i);
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        fragmentStartPosition = startPosition;
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        fragmentEndPosition = endPosition;
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!mapStartEndPositionsIntoFragmentCoordinates(fragment, fragmentStartPosition, fragmentEndPosition))
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            continue;
1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        FloatRect fragmentRect = selectionRectForTextFragment(fragment, fragmentStartPosition, fragmentEndPosition, style);
1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        fragment.buildFragmentTransform(fragmentTransform);
171d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        fragmentRect = fragmentTransform.mapRect(fragmentRect);
1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        selectionRect.unite(fragmentRect);
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return enclosingIntRect(selectionRect);
1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
179d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)static inline bool textShouldBePainted(RenderSVGInlineText& textRenderer)
1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Font::pixelSize(), returns FontDescription::computedPixelSize(), which returns "int(x + 0.5)".
1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If the absolute font size on screen is below x=0.5, don't render anything.
183d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    return textRenderer.scaledFont().fontDescription().computedPixelSize();
1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGInlineTextBox::paintSelectionBackground(PaintInfo& paintInfo)
1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
188d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    ASSERT(paintInfo.shouldPaintWithinRoot(&renderer()));
1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection);
1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(truncation() == cNoTruncation);
1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
192d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (renderer().style()->visibility() != VISIBLE)
1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
195d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    RenderObject& parentRenderer = parent()->renderer();
196d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    ASSERT(!parentRenderer.document().printing());
1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Determine whether or not we're selected.
1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool paintSelectedTextOnly = paintInfo.phase == PaintPhaseSelection;
2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool hasSelection = selectionState() != RenderObject::SelectionNone;
2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!hasSelection || paintSelectedTextOnly)
2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
204d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    Color backgroundColor = renderer().selectionBackgroundColor();
20509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (!backgroundColor.alpha())
2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
208c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    RenderSVGInlineText& textRenderer = toRenderSVGInlineText(this->renderer());
2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!textShouldBePainted(textRenderer))
2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
212d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    RenderStyle* style = parentRenderer.style();
2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(style);
2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int startPosition, endPosition;
2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    selectionStartEnd(startPosition, endPosition);
2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int fragmentStartPosition = 0;
2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int fragmentEndPosition = 0;
2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    AffineTransform fragmentTransform;
2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned textFragmentsSize = m_textFragments.size();
2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (unsigned i = 0; i < textFragmentsSize; ++i) {
2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        SVGTextFragment& fragment = m_textFragments.at(i);
2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        fragmentStartPosition = startPosition;
2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        fragmentEndPosition = endPosition;
2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!mapStartEndPositionsIntoFragmentCoordinates(fragment, fragmentStartPosition, fragmentEndPosition))
2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            continue;
2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        GraphicsContextStateSaver stateSaver(*paintInfo.context);
2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        fragment.buildFragmentTransform(fragmentTransform);
2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!fragmentTransform.isIdentity())
2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            paintInfo.context->concatCTM(fragmentTransform);
2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2355267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        paintInfo.context->setFillColor(backgroundColor);
2365267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        paintInfo.context->fillRect(selectionRectForTextFragment(fragment, fragmentStartPosition, fragmentEndPosition, style), backgroundColor);
2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
24009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void SVGInlineTextBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit, LayoutUnit)
2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
242d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    ASSERT(paintInfo.shouldPaintWithinRoot(&renderer()));
2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection);
2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(truncation() == cNoTruncation);
2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
246d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (renderer().style()->visibility() != VISIBLE)
2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Note: We're explicitely not supporting composition & custom underlines and custom highlighters - unlike InlineTextBox.
2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // If we ever need that for SVG, it's very easy to refactor and reuse the code.
2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
252d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    RenderObject& parentRenderer = parent()->renderer();
2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool paintSelectedTextOnly = paintInfo.phase == PaintPhaseSelection;
255d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    bool hasSelection = !parentRenderer.document().printing() && selectionState() != RenderObject::SelectionNone;
2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!hasSelection && paintSelectedTextOnly)
2575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
2585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
259c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    RenderSVGInlineText& textRenderer = toRenderSVGInlineText(this->renderer());
2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!textShouldBePainted(textRenderer))
2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
2625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
263d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    RenderStyle* style = parentRenderer.style();
2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(style);
2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
266d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    paintDocumentMarkers(paintInfo.context, paintOffset, style, textRenderer.scaledFont(), true);
26709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
268197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    const SVGRenderStyle& svgStyle = style->svgStyle();
2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
270197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    bool hasFill = svgStyle.hasFill();
271197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    bool hasVisibleStroke = svgStyle.hasVisibleStroke();
2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderStyle* selectionStyle = style;
2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (hasSelection) {
275d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        selectionStyle = parentRenderer.getCachedPseudoStyle(SELECTION);
2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (selectionStyle) {
277197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            const SVGRenderStyle& svgSelectionStyle = selectionStyle->svgStyle();
2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!hasFill)
280197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch                hasFill = svgSelectionStyle.hasFill();
2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!hasVisibleStroke)
282197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch                hasVisibleStroke = svgSelectionStyle.hasVisibleStroke();
283d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        } else {
2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            selectionStyle = style;
285d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)        }
2865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
288d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (textRenderer.frame() && textRenderer.frame()->view() && textRenderer.frame()->view()->paintBehavior() & PaintBehaviorRenderingSVGMask) {
2895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        hasFill = true;
2905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        hasVisibleStroke = false;
2915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    AffineTransform fragmentTransform;
2945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned textFragmentsSize = m_textFragments.size();
2955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (unsigned i = 0; i < textFragmentsSize; ++i) {
2965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        SVGTextFragment& fragment = m_textFragments.at(i);
2975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
29809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        GraphicsContextStateSaver stateSaver(*paintInfo.context, false);
2995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        fragment.buildFragmentTransform(fragmentTransform);
30009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        if (!fragmentTransform.isIdentity()) {
30109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            stateSaver.save();
3025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            paintInfo.context->concatCTM(fragmentTransform);
30309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        }
3045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Spec: All text decorations except line-through should be drawn before the text is filled and stroked; thus, the text is rendered on top of these decorations.
30651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        unsigned decorations = style->textDecorationsInEffect();
30793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        if (decorations & TextDecorationUnderline)
30893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)            paintDecoration(paintInfo.context, TextDecorationUnderline, fragment);
30993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        if (decorations & TextDecorationOverline)
31093ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)            paintDecoration(paintInfo.context, TextDecorationOverline, fragment);
3115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
312e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)        for (int i = 0; i < 3; i++) {
313197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            switch (svgStyle.paintOrderType(i)) {
314e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            case PT_FILL:
315e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                // Fill text
316e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                if (hasFill) {
3176f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch                    paintText(paintInfo.context, style, selectionStyle, fragment,
3186f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch                        ApplyToFillMode | ApplyToTextMode, hasSelection, paintSelectedTextOnly);
319e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                }
320e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                break;
321e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            case PT_STROKE:
322e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                // Stroke text
323e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                if (hasVisibleStroke) {
3246f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch                    paintText(paintInfo.context, style, selectionStyle, fragment,
3256f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch                        ApplyToStrokeMode | ApplyToTextMode, hasSelection, paintSelectedTextOnly);
326e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                }
327e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                break;
328e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            case PT_MARKERS:
329e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                // Markers don't apply to text
330e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                break;
331e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            default:
332e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                ASSERT_NOT_REACHED();
333e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)                break;
334e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)            }
3355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
3365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Spec: Line-through should be drawn after the text is filled and stroked; thus, the line-through is rendered on top of the text.
33893ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        if (decorations & TextDecorationLineThrough)
33993ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)            paintDecoration(paintInfo.context, TextDecorationLineThrough, fragment);
3405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
342d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    // finally, paint the outline if any
343d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    if (style->hasOutline() && parentRenderer.isRenderInline())
3447242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        InlinePainter(toRenderInline(parentRenderer)).paintOutline(paintInfo, paintOffset);
3455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3477242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucciclass PaintingResourceScope {
3487242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccipublic:
3497242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    PaintingResourceScope(RenderObject& renderer)
3507242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        : m_renderer(renderer)
3517242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        , m_paintingResource(0)
3527242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    {
3537242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    }
3547242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    ~PaintingResourceScope() { ASSERT(!m_paintingResource); }
3557242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
3567242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    bool acquirePaintingResource(GraphicsContext*&, RenderStyle*, RenderSVGResourceModeFlags);
3577242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    void releasePaintingResource(GraphicsContext*&);
3587242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
3597242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucciprivate:
3607242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    RenderObject& m_renderer;
3617242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    RenderSVGResource* m_paintingResource;
3627242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci};
3637242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
3647242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccibool PaintingResourceScope::acquirePaintingResource(GraphicsContext*& context, RenderStyle* style, RenderSVGResourceModeFlags resourceModeFlags)
3655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(style);
3677242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    ASSERT(resourceModeFlags != ApplyToDefaultMode);
3687242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    RenderSVGResourceMode resourceMode = static_cast<RenderSVGResourceMode>(resourceModeFlags & (ApplyToFillMode | ApplyToStrokeMode));
3697242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    ASSERT(resourceMode == ApplyToFillMode || resourceMode == ApplyToStrokeMode);
3705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
371d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    bool hasFallback = false;
3727242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    m_paintingResource = RenderSVGResource::requestPaintingResource(resourceMode, &m_renderer, style, hasFallback);
3735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!m_paintingResource)
3745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
3755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3767242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (!m_paintingResource->applyResource(&m_renderer, style, context, resourceModeFlags)) {
37709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        if (hasFallback) {
37809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            m_paintingResource = RenderSVGResource::sharedSolidPaintingResource();
3797242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            m_paintingResource->applyResource(&m_renderer, style, context, resourceModeFlags);
3805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
3815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
3825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return true;
3835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3857242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccivoid PaintingResourceScope::releasePaintingResource(GraphicsContext*& context)
3865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(m_paintingResource);
3885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3897242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    m_paintingResource->postApplyResource(&m_renderer, context);
3905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    m_paintingResource = 0;
3915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
3925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)TextRun SVGInlineTextBox::constructTextRun(RenderStyle* style, const SVGTextFragment& fragment) const
3945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
3955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(style);
3965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
397c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    RenderText* text = &renderer();
3985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
399f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    // FIXME(crbug.com/264211): This should not be necessary but can occur if we
400f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    //                          layout during layout. Remove this when 264211 is fixed.
401f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)    RELEASE_ASSERT(!text->needsLayout());
402f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)
403e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    TextRun run(static_cast<const LChar*>(0) // characters, will be set below if non-zero.
404e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch                , 0 // length, will be set below if non-zero.
405e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch                , 0 // xPos, only relevant with allowTabs=true
406e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch                , 0 // padding, only relevant for justified text, not relevant for SVG
4075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                , TextRun::AllowTrailingExpansion
4085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                , direction()
4095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                , dirOverride() || style->rtlOrdering() == VisualOrder /* directionalOverride */);
4105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
411e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    if (fragment.length) {
412e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        if (text->is8Bit())
413e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            run.setText(text->characters8() + fragment.characterOffset, fragment.length);
414e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch        else
415e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch            run.setText(text->characters16() + fragment.characterOffset, fragment.length);
416e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch    }
417e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch
4185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (textRunNeedsRenderingContext(style->font()))
4195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        run.setRenderingContext(SVGTextRunRenderingContext::create(text));
4205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // We handle letter & word spacing ourselves.
4225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    run.disableSpacing();
4235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Propagate the maximum length of the characters buffer to the TextRun, even when we're only processing a substring.
4255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    run.setCharactersLength(text->textLength() - fragment.characterOffset);
4265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(run.charactersLength() >= run.length());
4275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return run;
4285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool SVGInlineTextBox::mapStartEndPositionsIntoFragmentCoordinates(const SVGTextFragment& fragment, int& startPosition, int& endPosition) const
4315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (startPosition >= endPosition)
4335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
4345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int offset = static_cast<int>(fragment.characterOffset) - start();
4365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int length = static_cast<int>(fragment.length);
4375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (startPosition >= offset + length || endPosition <= offset)
4395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
4405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (startPosition < offset)
4425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        startPosition = 0;
4435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else
4445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        startPosition -= offset;
4455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (endPosition > offset + length)
4475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        endPosition = length;
4485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    else {
4495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ASSERT(endPosition >= offset);
4505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        endPosition -= offset;
4515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(startPosition < endPosition);
4545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return true;
4555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4577242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci// Offset from the baseline for |decoration|. Positive offsets are above the baseline.
4587242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tuccistatic inline float baselineOffsetForDecoration(TextDecoration decoration, const FontMetrics& fontMetrics, float thickness)
4595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // FIXME: For SVG Fonts we need to use the attributes defined in the <font-face> if specified.
4617242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // Compatible with Batik/Presto.
46293ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    if (decoration == TextDecorationUnderline)
4637242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        return -thickness * 1.5f;
46493ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    if (decoration == TextDecorationOverline)
4657242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        return fontMetrics.floatAscent() - thickness;
46693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)    if (decoration == TextDecorationLineThrough)
4677242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        return fontMetrics.floatAscent() * 3 / 8.0f;
4685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT_NOT_REACHED();
4705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return 0.0f;
4715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
47393ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)static inline float thicknessForDecoration(TextDecoration, const Font& font)
4745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // FIXME: For SVG Fonts we need to use the attributes defined in the <font-face> if specified.
4767242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    // Compatible with Batik/Presto
47709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    return font.fontDescription().computedSize() / 20.0f;
4785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline RenderObject* findRenderObjectDefininingTextDecoration(InlineFlowBox* parentBox)
4815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
4825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Lookup first render object in parent hierarchy which has text-decoration set.
4835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderObject* renderer = 0;
4845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (parentBox) {
485d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        renderer = &parentBox->renderer();
4865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
48793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)        if (renderer->style() && renderer->style()->textDecoration() != TextDecorationNone)
4885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
4895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        parentBox = parentBox->parent();
4915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
4925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
4935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(renderer);
4945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return renderer;
4955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
4965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
49793ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)void SVGInlineTextBox::paintDecoration(GraphicsContext* context, TextDecoration decoration, const SVGTextFragment& fragment)
4985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
499c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    if (renderer().style()->textDecorationsInEffect() == TextDecorationNone)
5005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
5015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Find out which render style defined the text-decoration, as its fill/stroke properties have to be used for drawing instead of ours.
5035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderObject* decorationRenderer = findRenderObjectDefininingTextDecoration(parent());
5045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderStyle* decorationStyle = decorationRenderer->style();
5055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(decorationStyle);
5065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (decorationStyle->visibility() == HIDDEN)
5085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
5095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
510197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    const SVGRenderStyle& svgDecorationStyle = decorationStyle->svgStyle();
5115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
512a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch    for (int i = 0; i < 3; i++) {
513197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        switch (svgDecorationStyle.paintOrderType(i)) {
514a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        case PT_FILL:
515197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            if (svgDecorationStyle.hasFill())
5166f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch                paintDecorationWithStyle(context, decoration, fragment, decorationRenderer, ApplyToFillMode);
517a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            break;
518a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        case PT_STROKE:
519197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            if (svgDecorationStyle.hasVisibleStroke())
5206f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch                paintDecorationWithStyle(context, decoration, fragment, decorationRenderer, ApplyToStrokeMode);
521a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            break;
522a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        case PT_MARKERS:
523a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            break;
524a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        default:
525a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            ASSERT_NOT_REACHED();
526a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch        }
5275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
5285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5306f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdochvoid SVGInlineTextBox::paintDecorationWithStyle(GraphicsContext* context, TextDecoration decoration,
5316f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    const SVGTextFragment& fragment, RenderObject* decorationRenderer, RenderSVGResourceModeFlags resourceMode)
5325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
5336f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    ASSERT(resourceMode != ApplyToDefaultMode);
5345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderStyle* decorationStyle = decorationRenderer->style();
5365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(decorationStyle);
5375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    float scalingFactor = 1;
5395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Font scaledFont;
5405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderSVGInlineText::computeNewScaledFontForStyle(decorationRenderer, decorationStyle, scalingFactor, scaledFont);
5415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(scalingFactor);
5425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    float thickness = thicknessForDecoration(decoration, scaledFont);
5445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (fragment.width <= 0 && thickness <= 0)
5465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
5475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5487242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    float decorationOffset = baselineOffsetForDecoration(decoration, scaledFont.fontMetrics(), thickness);
5497242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    FloatPoint decorationOrigin(fragment.x, fragment.y - decorationOffset / scalingFactor);
5505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Path path;
5527242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    path.addRect(FloatRect(decorationOrigin, FloatSize(fragment.width, thickness / scalingFactor)));
5535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5547242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    PaintingResourceScope resourceScope(*decorationRenderer);
5557242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (resourceScope.acquirePaintingResource(context, decorationStyle, resourceMode)) {
5567242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        SVGRenderSupport::fillOrStrokePath(context, resourceMode, path);
5577242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        resourceScope.releasePaintingResource(context);
5587242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    }
5595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
5605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5616f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdochvoid SVGInlineTextBox::paintTextWithShadows(GraphicsContext* context, RenderStyle* style,
5626f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    TextRun& textRun, const SVGTextFragment& fragment, int startPosition, int endPosition,
5636f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    RenderSVGResourceModeFlags resourceMode)
5645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
565c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    RenderSVGInlineText& textRenderer = toRenderSVGInlineText(this->renderer());
5665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
567d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    float scalingFactor = textRenderer.scalingFactor();
5685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(scalingFactor);
5695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
570d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    const Font& scaledFont = textRenderer.scaledFont();
571f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    const ShadowList* shadowList = style->textShadow();
5727757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch
5737757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch    // Text shadows are disabled when printing. http://crbug.com/258321
574f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)    bool hasShadow = shadowList && !context->printing();
5755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FloatPoint textOrigin(fragment.x, fragment.y);
5775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FloatSize textSize(fragment.width, fragment.height);
5785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (scalingFactor != 1) {
5805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        textOrigin.scale(scalingFactor, scalingFactor);
5815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        textSize.scale(scalingFactor);
5825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        context->save();
5835d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        context->scale(1 / scalingFactor, 1 / scalingFactor);
5845267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    }
5855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
586197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch    if (hasShadow)
587197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        context->setDrawLooper(shadowList->createDrawLooper(DrawLooperBuilder::ShadowRespectsAlpha));
5885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
5897242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    PaintingResourceScope resourceScope(parent()->renderer());
5907242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (resourceScope.acquirePaintingResource(context, style, resourceMode)) {
5917242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        if (scalingFactor != 1 && resourceMode & ApplyToStrokeMode)
5927242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            context->setStrokeThickness(context->strokeThickness() * scalingFactor);
5937242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
5945267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        TextRunPaintInfo textRunPaintInfo(textRun);
5955267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        textRunPaintInfo.from = startPosition;
5965267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        textRunPaintInfo.to = endPosition;
5977242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
5987242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        float baseline = scaledFont.fontMetrics().floatAscent();
5997242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        textRunPaintInfo.bounds = FloatRect(textOrigin.x(), textOrigin.y() - baseline,
6007242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci            textSize.width(), textSize.height());
6017242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci
6025267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        scaledFont.drawText(context, textRunPaintInfo, textOrigin);
6037242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        resourceScope.releasePaintingResource(context);
6045267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    }
6055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6065267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    if (scalingFactor != 1)
6075267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        context->restore();
6085267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)    else if (hasShadow)
6095267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)        context->clearShadow();
6105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6126f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdochvoid SVGInlineTextBox::paintText(GraphicsContext* context, RenderStyle* style,
6136f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    RenderStyle* selectionStyle, const SVGTextFragment& fragment,
6146f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    RenderSVGResourceModeFlags resourceMode, bool hasSelection, bool paintSelectedTextOnly)
6155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
6165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(style);
6175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(selectionStyle);
6185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int startPosition = 0;
6205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int endPosition = 0;
6215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (hasSelection) {
6225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        selectionStartEnd(startPosition, endPosition);
6235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        hasSelection = mapStartEndPositionsIntoFragmentCoordinates(fragment, startPosition, endPosition);
6245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
6255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Fast path if there is no selection, just draw the whole chunk part using the regular style
6275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    TextRun textRun = constructTextRun(style, fragment);
6285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!hasSelection || startPosition >= endPosition) {
6296f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        paintTextWithShadows(context, style, textRun, fragment, 0, fragment.length, resourceMode);
6305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
6315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
6325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Eventually draw text using regular style until the start position of the selection
6345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (startPosition > 0 && !paintSelectedTextOnly)
6356f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        paintTextWithShadows(context, style, textRun, fragment, 0, startPosition, resourceMode);
6365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Draw text using selection style from the start to the end position of the selection
63810f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    if (style != selectionStyle) {
63910f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch        StyleDifference diff;
640e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)        diff.setNeedsPaintInvalidationObject();
64110f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch        SVGResourcesCache::clientStyleChanged(&parent()->renderer(), diff, selectionStyle);
64210f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    }
6435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6446f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch    paintTextWithShadows(context, selectionStyle, textRun, fragment, startPosition, endPosition, resourceMode);
6455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
64610f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    if (style != selectionStyle) {
64710f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch        StyleDifference diff;
648e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)        diff.setNeedsPaintInvalidationObject();
6497242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci        SVGResourcesCache::clientStyleChanged(&parent()->renderer(), diff, style);
65010f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    }
6515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
6525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Eventually draw text using regular style from the end position of the selection to the end of the current chunk part
6535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (endPosition < static_cast<int>(fragment.length) && !paintSelectedTextOnly)
6546f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch        paintTextWithShadows(context, style, textRun, fragment, endPosition, fragment.length, resourceMode);
6555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
6565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
65709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void SVGInlineTextBox::paintDocumentMarker(GraphicsContext*, const FloatPoint&, DocumentMarker*, RenderStyle*, const Font&, bool)
65809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
65909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // SVG does not have support for generic document markers (e.g., spellchecking, etc).
66009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
66109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
66209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void SVGInlineTextBox::paintTextMatchMarker(GraphicsContext* context, const FloatPoint&, DocumentMarker* marker, RenderStyle* style, const Font& font)
66309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles){
66409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    // SVG is only interested in the TextMatch markers.
66509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    if (marker->type() != DocumentMarker::TextMatch)
66609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        return;
66709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
668c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    RenderSVGInlineText& textRenderer = toRenderSVGInlineText(this->renderer());
66909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
67009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    FloatRect markerRect;
67109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    AffineTransform fragmentTransform;
672d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    for (InlineTextBox* box = textRenderer.firstTextBox(); box; box = box->nextTextBox()) {
67309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        if (!box->isSVGInlineTextBox())
67409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            continue;
67509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
67609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        SVGInlineTextBox* textBox = toSVGInlineTextBox(box);
67709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
678197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        int markerStartPosition = std::max<int>(marker->startOffset() - textBox->start(), 0);
679197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        int markerEndPosition = std::min<int>(marker->endOffset() - textBox->start(), textBox->len());
68009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
68109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        if (markerStartPosition >= markerEndPosition)
68209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            continue;
68309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
68409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        const Vector<SVGTextFragment>& fragments = textBox->textFragments();
68509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        unsigned textFragmentsSize = fragments.size();
68609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        for (unsigned i = 0; i < textFragmentsSize; ++i) {
68709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            const SVGTextFragment& fragment = fragments.at(i);
68809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
68909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            int fragmentStartPosition = markerStartPosition;
69009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            int fragmentEndPosition = markerEndPosition;
69109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            if (!textBox->mapStartEndPositionsIntoFragmentCoordinates(fragment, fragmentStartPosition, fragmentEndPosition))
69209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)                continue;
69309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
69409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            FloatRect fragmentRect = textBox->selectionRectForTextFragment(fragment, fragmentStartPosition, fragmentEndPosition, style);
69509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            fragment.buildFragmentTransform(fragmentTransform);
69609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
69709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            // Draw the marker highlight.
698d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            if (renderer().frame()->editor().markedTextMatchesAreHighlighted()) {
69909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)                Color color = marker->activeMatch() ?
70009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)                    RenderTheme::theme().platformActiveTextSearchHighlightColor() :
70109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)                    RenderTheme::theme().platformInactiveTextSearchHighlightColor();
70209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)                GraphicsContextStateSaver stateSaver(*context);
703d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                if (!fragmentTransform.isIdentity())
70409380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)                    context->concatCTM(fragmentTransform);
70509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)                context->setFillColor(color);
70609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)                context->fillRect(fragmentRect, color);
70709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            }
70809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
709d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            fragmentRect = fragmentTransform.mapRect(fragmentRect);
71009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            markerRect.unite(fragmentRect);
71109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        }
71209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    }
71309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
714d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    toRenderedDocumentMarker(marker)->setRenderedRect(textRenderer.localToAbsoluteQuad(markerRect).enclosingBoundingBox());
71509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)}
71609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)
7175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)FloatRect SVGInlineTextBox::calculateBoundaries() const
7185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
7195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FloatRect textRect;
7205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
721c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    RenderSVGInlineText& textRenderer = toRenderSVGInlineText(this->renderer());
7225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
723d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    float scalingFactor = textRenderer.scalingFactor();
7245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(scalingFactor);
7255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
726d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    float baseline = textRenderer.scaledFont().fontMetrics().floatAscent() / scalingFactor;
7275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    AffineTransform fragmentTransform;
7295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned textFragmentsSize = m_textFragments.size();
7305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (unsigned i = 0; i < textFragmentsSize; ++i) {
7315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        const SVGTextFragment& fragment = m_textFragments.at(i);
7325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        FloatRect fragmentRect(fragment.x, fragment.y - baseline, fragment.width, fragment.height);
7335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        fragment.buildFragmentTransform(fragmentTransform);
734d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        fragmentRect = fragmentTransform.mapRect(fragmentRect);
7355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        textRect.unite(fragmentRect);
7375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
7385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return textRect;
7405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
7415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
7425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool SVGInlineTextBox::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, LayoutUnit, LayoutUnit)
7435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
7445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // FIXME: integrate with InlineTextBox::nodeAtPoint better.
7455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(!isLineBreak());
7465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
747d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_TEXT_HITTESTING, request, renderer().style()->pointerEvents());
748d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    bool isVisible = renderer().style()->visibility() == VISIBLE;
7495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (isVisible || !hitRules.requireVisible) {
750a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)        if (hitRules.canHitBoundingBox
751197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            || (hitRules.canHitStroke && (renderer().style()->svgStyle().hasStroke() || !hitRules.requireStroke))
752197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            || (hitRules.canHitFill && (renderer().style()->svgStyle().hasFill() || !hitRules.requireFill))) {
7535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            FloatPoint boxOrigin(x(), y());
7545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            boxOrigin.moveBy(accumulatedOffset);
7555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            FloatRect rect(boxOrigin, size());
7565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (locationInContainer.intersects(rect)) {
757d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                renderer().updateHitTestResult(result, locationInContainer.point() - toLayoutSize(accumulatedOffset));
758d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                if (!result.addNodeToRectBasedTestResult(renderer().node(), request, locationInContainer, rect))
7595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                    return true;
7605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)             }
7615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
7625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
7635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return false;
7645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
7655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
766c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink
767