1a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch/**
2a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * Copyright (C) 2007 Rob Buis <buis@kde.org>
365f03d4f644ce73618e5f4f50dd694b26f55ae12Ben Murdoch * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
4a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * Copyright (C) Research In Motion Limited 2010. All rights reserved.
5a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch *
6a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * This library is free software; you can redistribute it and/or
7a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * modify it under the terms of the GNU Library General Public
8a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * License as published by the Free Software Foundation; either
9a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * version 2 of the License, or (at your option) any later version.
10a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch *
11a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * This library is distributed in the hope that it will be useful,
12a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * but WITHOUT ANY WARRANTY; without even the implied warranty of
13a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * Library General Public License for more details.
15a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch *
16a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * You should have received a copy of the GNU Library General Public License
17a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * along with this library; see the file COPYING.LIB.  If not, write to
18a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * Boston, MA 02110-1301, USA.
20a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch */
21a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
22a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "config.h"
23a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "SVGInlineTextBox.h"
24a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
25a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#if ENABLE(SVG)
26a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "FloatConversion.h"
27a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "GraphicsContext.h"
28a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "InlineFlowBox.h"
29a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "RenderBlock.h"
30a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "RenderSVGInlineText.h"
31a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "RenderSVGResource.h"
32a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "RenderSVGResourceSolidColor.h"
332fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include "SVGImageBufferTools.h"
34a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "SVGRootInlineBox.h"
35ab9e7a118cf1ea2e3a93dce683b2ded3e7291ddbBen Murdoch#include "TextRun.h"
36a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
37a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochusing namespace std;
38a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
39a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochnamespace WebCore {
40a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
41a94275402997c11dd2e778633dacf4b7e630a35dBen MurdochSVGInlineTextBox::SVGInlineTextBox(RenderObject* object)
42a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    : InlineTextBox(object)
43a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    , m_logicalHeight(0)
44a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    , m_paintingResourceMode(ApplyToDefaultMode)
45a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    , m_startsNewTextChunk(false)
46a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    , m_paintingResource(0)
47a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
48a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
49a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
5081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochint SVGInlineTextBox::offsetForPosition(float, bool) const
51a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
52a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // SVG doesn't use the standard offset <-> position selection system, as it's not suitable for SVGs complex needs.
53a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // vertical text selection, inline boxes spanning multiple lines (contrary to HTML, etc.)
54a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT_NOT_REACHED();
55a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    return 0;
56a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
57a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
58a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochint SVGInlineTextBox::offsetForPositionInFragment(const SVGTextFragment& fragment, float position, bool includePartialGlyphs) const
59a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
602fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    RenderSVGInlineText* textRenderer = toRenderSVGInlineText(this->textRenderer());
61a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT(textRenderer);
62a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
632fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    float scalingFactor = textRenderer->scalingFactor();
642fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    ASSERT(scalingFactor);
652fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
66a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    RenderStyle* style = textRenderer->style();
67a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT(style);
68a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
69a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    TextRun textRun(constructTextRun(style, fragment));
70a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
71a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // Eventually handle lengthAdjust="spacingAndGlyphs".
72a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // FIXME: Handle vertical text.
732daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    AffineTransform fragmentTransform;
742daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    fragment.buildFragmentTransform(fragmentTransform);
752daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    if (!fragmentTransform.isIdentity())
762daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        textRun.setHorizontalGlyphStretch(narrowPrecisionToFloat(fragmentTransform.xScale()));
77a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
782bde8e466a4451c7319e3a072d118917957d6554Steve Block    return fragment.characterOffset - start() + textRenderer->scaledFont().offsetForPosition(textRun, position * scalingFactor, includePartialGlyphs);
79a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
80a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
8181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochfloat SVGInlineTextBox::positionForOffset(int) const
82a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
83a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // SVG doesn't use the offset <-> position selection system.
84a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT_NOT_REACHED();
85a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    return 0;
86a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
87a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
88a94275402997c11dd2e778633dacf4b7e630a35dBen MurdochFloatRect SVGInlineTextBox::selectionRectForTextFragment(const SVGTextFragment& fragment, int startPosition, int endPosition, RenderStyle* style)
89a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
90a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT(startPosition < endPosition);
912fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    ASSERT(style);
922fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
932fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    RenderSVGInlineText* textRenderer = toRenderSVGInlineText(this->textRenderer());
942fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    ASSERT(textRenderer);
952fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
962fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    float scalingFactor = textRenderer->scalingFactor();
972fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    ASSERT(scalingFactor);
98a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
992fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    const Font& scaledFont = textRenderer->scaledFont();
1002fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    const FontMetrics& scaledFontMetrics = scaledFont.fontMetrics();
1012fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    FloatPoint textOrigin(fragment.x, fragment.y);
1022fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (scalingFactor != 1)
1032fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        textOrigin.scale(scalingFactor, scalingFactor);
1042fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1052fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    textOrigin.move(0, -scaledFontMetrics.floatAscent());
1062fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1072fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    FloatRect selectionRect = scaledFont.selectionRectForText(constructTextRun(style, fragment), textOrigin, fragment.height * scalingFactor, startPosition, endPosition);
1082fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (scalingFactor == 1)
1092fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return selectionRect;
1102fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
1112fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    selectionRect.scale(1 / scalingFactor);
1122fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    return selectionRect;
113a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
114a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
115a94275402997c11dd2e778633dacf4b7e630a35dBen MurdochIntRect SVGInlineTextBox::selectionRect(int, int, int startPosition, int endPosition)
116a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
117a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    int boxStart = start();
118a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    startPosition = max(startPosition - boxStart, 0);
119a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    endPosition = min(endPosition - boxStart, static_cast<int>(len()));
120a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (startPosition >= endPosition)
121a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return IntRect();
122a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
123a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    RenderText* text = textRenderer();
124a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT(text);
125a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
126a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    RenderStyle* style = text->style();
127a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT(style);
128a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
1292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    AffineTransform fragmentTransform;
130a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    FloatRect selectionRect;
131a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    int fragmentStartPosition = 0;
132a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    int fragmentEndPosition = 0;
133a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
134a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    unsigned textFragmentsSize = m_textFragments.size();
135a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    for (unsigned i = 0; i < textFragmentsSize; ++i) {
136a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        const SVGTextFragment& fragment = m_textFragments.at(i);
137a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
138a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        fragmentStartPosition = startPosition;
139a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        fragmentEndPosition = endPosition;
140a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        if (!mapStartEndPositionsIntoFragmentCoordinates(fragment, fragmentStartPosition, fragmentEndPosition))
141a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            continue;
142a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
143a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        FloatRect fragmentRect = selectionRectForTextFragment(fragment, fragmentStartPosition, fragmentEndPosition, style);
1442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        fragment.buildFragmentTransform(fragmentTransform);
1452daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!fragmentTransform.isIdentity())
1462daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            fragmentRect = fragmentTransform.mapRect(fragmentRect);
147a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
148a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        selectionRect.unite(fragmentRect);
149a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
150a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
151a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    return enclosingIntRect(selectionRect);
152a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
153a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
1542fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockstatic inline bool textShouldBePainted(RenderSVGInlineText* textRenderer)
1552fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{
1562fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    // Font::pixelSize(), returns FontDescription::computedPixelSize(), which returns "int(x + 0.5)".
1572fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    // If the absolute font size on screen is below x=0.5, don't render anything.
1582fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    return textRenderer->scaledFont().pixelSize();
1592fc2651226baac27029e38c9d6ef883fa32084dbSteve Block}
1602fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
161a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid SVGInlineTextBox::paintSelectionBackground(PaintInfo& paintInfo)
162a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
163a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT(paintInfo.shouldPaintWithinRoot(renderer()));
164a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT(paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection);
165a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT(truncation() == cNoTruncation);
166a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
167a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (renderer()->style()->visibility() != VISIBLE)
168a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return;
169a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
170a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    RenderObject* parentRenderer = parent()->renderer();
171a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT(parentRenderer);
172a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT(!parentRenderer->document()->printing());
173a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
174a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // Determine whether or not we're selected.
175a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    bool paintSelectedTextOnly = paintInfo.phase == PaintPhaseSelection;
176a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    bool hasSelection = selectionState() != RenderObject::SelectionNone;
177a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (!hasSelection || paintSelectedTextOnly)
178a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return;
179a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
180a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    Color backgroundColor = renderer()->selectionBackgroundColor();
181a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (!backgroundColor.isValid() || !backgroundColor.alpha())
182a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return;
183a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
1842fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    RenderSVGInlineText* textRenderer = toRenderSVGInlineText(this->textRenderer());
1852fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    ASSERT(textRenderer);
1862fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (!textShouldBePainted(textRenderer))
1872fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return;
1882fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
189a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    RenderStyle* style = parentRenderer->style();
190a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT(style);
191a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
192a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    const SVGRenderStyle* svgStyle = style->svgStyle();
193a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT(svgStyle);
194a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
195a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    bool hasFill = svgStyle->hasFill();
196a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    bool hasStroke = svgStyle->hasStroke();
197a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
198a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    RenderStyle* selectionStyle = style;
199a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (hasSelection) {
200a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        selectionStyle = parentRenderer->getCachedPseudoStyle(SELECTION);
201a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        if (selectionStyle) {
202a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            const SVGRenderStyle* svgSelectionStyle = selectionStyle->svgStyle();
203a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            ASSERT(svgSelectionStyle);
204a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
205a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            if (!hasFill)
206a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                hasFill = svgSelectionStyle->hasFill();
207a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            if (!hasStroke)
208a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                hasStroke = svgSelectionStyle->hasStroke();
209a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        } else
210a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            selectionStyle = style;
211a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
212a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
213a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    int startPosition, endPosition;
214a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    selectionStartEnd(startPosition, endPosition);
215a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
216a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    int fragmentStartPosition = 0;
217a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    int fragmentEndPosition = 0;
2182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    AffineTransform fragmentTransform;
219a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    unsigned textFragmentsSize = m_textFragments.size();
220a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    for (unsigned i = 0; i < textFragmentsSize; ++i) {
221a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        SVGTextFragment& fragment = m_textFragments.at(i);
222a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ASSERT(!m_paintingResource);
223a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
224a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        fragmentStartPosition = startPosition;
225a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        fragmentEndPosition = endPosition;
226a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        if (!mapStartEndPositionsIntoFragmentCoordinates(fragment, fragmentStartPosition, fragmentEndPosition))
227a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            continue;
228a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
229a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        paintInfo.context->save();
2302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        fragment.buildFragmentTransform(fragmentTransform);
2312daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!fragmentTransform.isIdentity())
2322daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            paintInfo.context->concatCTM(fragmentTransform);
233a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
234a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        paintInfo.context->setFillColor(backgroundColor, style->colorSpace());
235a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        paintInfo.context->fillRect(selectionRectForTextFragment(fragment, fragmentStartPosition, fragmentEndPosition, style), backgroundColor, style->colorSpace());
236a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
237a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        m_paintingResourceMode = ApplyToDefaultMode;
238a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        paintInfo.context->restore();
239a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
240a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
241a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT(!m_paintingResource);
242a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
243a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
2442daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochvoid SVGInlineTextBox::paint(PaintInfo& paintInfo, int, int, int, int)
245a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
246a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT(paintInfo.shouldPaintWithinRoot(renderer()));
247a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT(paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection);
248a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT(truncation() == cNoTruncation);
249a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
250a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (renderer()->style()->visibility() != VISIBLE)
251a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return;
252a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
253a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // Note: We're explicitely not supporting composition & custom underlines and custom highlighters - unlike InlineTextBox.
254a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // If we ever need that for SVG, it's very easy to refactor and reuse the code.
255a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
256a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    RenderObject* parentRenderer = parent()->renderer();
257a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT(parentRenderer);
258a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
259a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    bool paintSelectedTextOnly = paintInfo.phase == PaintPhaseSelection;
260a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    bool hasSelection = !parentRenderer->document()->printing() && selectionState() != RenderObject::SelectionNone;
261a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (!hasSelection && paintSelectedTextOnly)
262a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return;
263a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
2642fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    RenderSVGInlineText* textRenderer = toRenderSVGInlineText(this->textRenderer());
2652fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    ASSERT(textRenderer);
2662fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (!textShouldBePainted(textRenderer))
2672fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return;
2682fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
269a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    RenderStyle* style = parentRenderer->style();
270a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT(style);
271a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
272a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    const SVGRenderStyle* svgStyle = style->svgStyle();
273a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT(svgStyle);
274a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
275a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    bool hasFill = svgStyle->hasFill();
276a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    bool hasStroke = svgStyle->hasStroke();
277a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
278a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    RenderStyle* selectionStyle = style;
279a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (hasSelection) {
280a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        selectionStyle = parentRenderer->getCachedPseudoStyle(SELECTION);
281a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        if (selectionStyle) {
282a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            const SVGRenderStyle* svgSelectionStyle = selectionStyle->svgStyle();
283a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            ASSERT(svgSelectionStyle);
284a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
285a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            if (!hasFill)
286a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                hasFill = svgSelectionStyle->hasFill();
287a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            if (!hasStroke)
288a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                hasStroke = svgSelectionStyle->hasStroke();
289a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        } else
290a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            selectionStyle = style;
291a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
292a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
2932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    AffineTransform fragmentTransform;
294a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    unsigned textFragmentsSize = m_textFragments.size();
295a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    for (unsigned i = 0; i < textFragmentsSize; ++i) {
296a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        SVGTextFragment& fragment = m_textFragments.at(i);
297a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ASSERT(!m_paintingResource);
298a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
299a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        paintInfo.context->save();
3002daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        fragment.buildFragmentTransform(fragmentTransform);
3012daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!fragmentTransform.isIdentity())
3022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            paintInfo.context->concatCTM(fragmentTransform);
303a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
304a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // 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.
305a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        int decorations = style->textDecorationsInEffect();
306a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        if (decorations & UNDERLINE)
307a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            paintDecoration(paintInfo.context, UNDERLINE, fragment);
308a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        if (decorations & OVERLINE)
309a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            paintDecoration(paintInfo.context, OVERLINE, fragment);
310a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
311a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // Fill text
312a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        if (hasFill) {
313a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            m_paintingResourceMode = ApplyToFillMode | ApplyToTextMode;
314a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            paintText(paintInfo.context, style, selectionStyle, fragment, hasSelection, paintSelectedTextOnly);
315a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        }
316a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
317a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // Stroke text
318a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        if (hasStroke) {
319a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            m_paintingResourceMode = ApplyToStrokeMode | ApplyToTextMode;
320a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            paintText(paintInfo.context, style, selectionStyle, fragment, hasSelection, paintSelectedTextOnly);
321a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        }
322a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
323a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // Spec: Line-through should be drawn after the text is filled and stroked; thus, the line-through is rendered on top of the text.
324a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        if (decorations & LINE_THROUGH)
325a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            paintDecoration(paintInfo.context, LINE_THROUGH, fragment);
326a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
327a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        m_paintingResourceMode = ApplyToDefaultMode;
328a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        paintInfo.context->restore();
329a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
330a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
331a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT(!m_paintingResource);
332a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
333a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
3342fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockbool SVGInlineTextBox::acquirePaintingResource(GraphicsContext*& context, float scalingFactor, RenderObject* renderer, RenderStyle* style)
335a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
3362fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    ASSERT(scalingFactor);
337a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT(renderer);
338a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT(style);
339a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT(m_paintingResourceMode != ApplyToDefaultMode);
340a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
341a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    Color fallbackColor;
342a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (m_paintingResourceMode & ApplyToFillMode)
343a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        m_paintingResource = RenderSVGResource::fillPaintingResource(renderer, style, fallbackColor);
344a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    else if (m_paintingResourceMode & ApplyToStrokeMode)
345a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        m_paintingResource = RenderSVGResource::strokePaintingResource(renderer, style, fallbackColor);
346a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    else {
347a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // We're either called for stroking or filling.
348a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ASSERT_NOT_REACHED();
349a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
350a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
351a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (!m_paintingResource)
352a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return false;
353a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
354a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (!m_paintingResource->applyResource(renderer, style, context, m_paintingResourceMode)) {
355a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        if (fallbackColor.isValid()) {
356a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            RenderSVGResourceSolidColor* fallbackResource = RenderSVGResource::sharedSolidPaintingResource();
357a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            fallbackResource->setColor(fallbackColor);
358a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
359a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            m_paintingResource = fallbackResource;
360a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            m_paintingResource->applyResource(renderer, style, context, m_paintingResourceMode);
361a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        }
362a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
363a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
3642fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (scalingFactor != 1 && m_paintingResourceMode & ApplyToStrokeMode)
3652fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        context->setStrokeThickness(context->strokeThickness() * scalingFactor);
3662fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
367a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    return true;
368a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
369a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
370f05b935882198ccf7d81675736e3aeb089c5113aBen Murdochvoid SVGInlineTextBox::releasePaintingResource(GraphicsContext*& context, const Path* path)
371a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
372a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT(m_paintingResource);
373a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
374a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    RenderObject* parentRenderer = parent()->renderer();
375a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT(parentRenderer);
376a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
377f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    m_paintingResource->postApplyResource(parentRenderer, context, m_paintingResourceMode, path);
378a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    m_paintingResource = 0;
379a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
380a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
3812fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockbool SVGInlineTextBox::prepareGraphicsContextForTextPainting(GraphicsContext*& context, float scalingFactor, TextRun& textRun, RenderStyle* style)
382a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
3832fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    bool acquiredResource = acquirePaintingResource(context, scalingFactor, parent()->renderer(), style);
384a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
385a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#if ENABLE(SVG_FONTS)
386a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // SVG Fonts need access to the painting resource used to draw the current text chunk.
387a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (acquiredResource)
388a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        textRun.setActivePaintingResource(m_paintingResource);
389a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#endif
390a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
391a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    return acquiredResource;
392a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
393a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
394a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid SVGInlineTextBox::restoreGraphicsContextAfterTextPainting(GraphicsContext*& context, TextRun& textRun)
395a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
396f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch    releasePaintingResource(context, /* path */0);
397a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
398a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#if ENABLE(SVG_FONTS)
399a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    textRun.setActivePaintingResource(0);
400a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#endif
401a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
402a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
403a94275402997c11dd2e778633dacf4b7e630a35dBen MurdochTextRun SVGInlineTextBox::constructTextRun(RenderStyle* style, const SVGTextFragment& fragment) const
404a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
405a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT(style);
406a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT(textRenderer());
407a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
408a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    RenderText* text = textRenderer();
409a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT(text);
410a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
4112bde8e466a4451c7319e3a072d118917957d6554Steve Block    TextRun run(text->characters() + fragment.characterOffset
412a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                , fragment.length
413a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                , false /* allowTabs */
414a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                , 0 /* xPos, only relevant with allowTabs=true */
415a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                , 0 /* padding, only relevant for justified text, not relevant for SVG */
4162fc2651226baac27029e38c9d6ef883fa32084dbSteve Block                , TextRun::AllowTrailingExpansion
417a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                , direction() == RTL
418a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                , m_dirOverride || style->visuallyOrdered() /* directionalOverride */);
419a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
420a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#if ENABLE(SVG_FONTS)
4212fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    run.setReferencingRenderObject(text);
422a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#endif
423a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
424a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // We handle letter & word spacing ourselves.
425a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    run.disableSpacing();
426a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    return run;
427a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
428a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
429a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochbool SVGInlineTextBox::mapStartEndPositionsIntoFragmentCoordinates(const SVGTextFragment& fragment, int& startPosition, int& endPosition) const
430a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
431a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (startPosition >= endPosition)
432a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return false;
433a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
4342bde8e466a4451c7319e3a072d118917957d6554Steve Block    int offset = static_cast<int>(fragment.characterOffset) - start();
435a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    int length = static_cast<int>(fragment.length);
436a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
437a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (startPosition >= offset + length || endPosition <= offset)
438a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return false;
439a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
440a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (startPosition < offset)
441a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        startPosition = 0;
442a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    else
443a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        startPosition -= offset;
444a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
445a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (endPosition > offset + length)
446a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        endPosition = length;
447a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    else {
448a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        ASSERT(endPosition >= offset);
449a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        endPosition -= offset;
450a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
451a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
452a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT(startPosition < endPosition);
453a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    return true;
454a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
455a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
4562fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockstatic inline float positionOffsetForDecoration(ETextDecoration decoration, const FontMetrics& fontMetrics, float thickness)
457a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
458a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // FIXME: For SVG Fonts we need to use the attributes defined in the <font-face> if specified.
459a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // Compatible with Batik/Opera.
460a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (decoration == UNDERLINE)
4612fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return fontMetrics.floatAscent() + thickness * 1.5f;
462a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (decoration == OVERLINE)
463a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return thickness;
464a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (decoration == LINE_THROUGH)
4652fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        return fontMetrics.floatAscent() * 5 / 8.0f;
466a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
467a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT_NOT_REACHED();
468a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    return 0.0f;
469a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
470a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
471a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochstatic inline float thicknessForDecoration(ETextDecoration, const Font& font)
472a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
473a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // FIXME: For SVG Fonts we need to use the attributes defined in the <font-face> if specified.
474a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // Compatible with Batik/Opera
475a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    return font.size() / 20.0f;
476a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
477a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
478a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochstatic inline RenderObject* findRenderObjectDefininingTextDecoration(InlineFlowBox* parentBox)
479a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
480a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // Lookup first render object in parent hierarchy which has text-decoration set.
481a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    RenderObject* renderer = 0;
482a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    while (parentBox) {
483a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        renderer = parentBox->renderer();
484a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
485a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        if (renderer->style() && renderer->style()->textDecoration() != TDNONE)
486a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            break;
487a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
488a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        parentBox = parentBox->parent();
489a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
490a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
491a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT(renderer);
492a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    return renderer;
493a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
494a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
495a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid SVGInlineTextBox::paintDecoration(GraphicsContext* context, ETextDecoration decoration, const SVGTextFragment& fragment)
496a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
497a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (textRenderer()->style()->textDecorationsInEffect() == TDNONE)
498a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return;
499a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
500a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // Find out which render style defined the text-decoration, as its fill/stroke properties have to be used for drawing instead of ours.
501a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    RenderObject* decorationRenderer = findRenderObjectDefininingTextDecoration(parent());
502a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    RenderStyle* decorationStyle = decorationRenderer->style();
503a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT(decorationStyle);
504a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
505a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (decorationStyle->visibility() == HIDDEN)
506a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return;
507a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
508a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    const SVGRenderStyle* svgDecorationStyle = decorationStyle->svgStyle();
509a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT(svgDecorationStyle);
510a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
511a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    bool hasDecorationFill = svgDecorationStyle->hasFill();
512a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    bool hasDecorationStroke = svgDecorationStyle->hasStroke();
513a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
514a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (hasDecorationFill) {
515a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        m_paintingResourceMode = ApplyToFillMode;
516a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        paintDecorationWithStyle(context, decoration, fragment, decorationRenderer);
517a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
518a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
519a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (hasDecorationStroke) {
520a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        m_paintingResourceMode = ApplyToStrokeMode;
521a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        paintDecorationWithStyle(context, decoration, fragment, decorationRenderer);
522a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
523a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
524a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
52581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdochstatic inline void normalizeTransform(AffineTransform& transform)
52681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch{
52781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    // Obtain consistent numerical results for the AffineTransform on both 32/64bit platforms.
52881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    // Tested with SnowLeopard on Core Duo vs. Core 2 Duo.
52981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    static const float s_floatEpsilon = std::numeric_limits<float>::epsilon();
53081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
53181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (fabs(transform.a() - 1) <= s_floatEpsilon)
53281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        transform.setA(1);
53381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    else if (fabs(transform.a() + 1) <= s_floatEpsilon)
53481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        transform.setA(-1);
53581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
53681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (fabs(transform.d() - 1) <= s_floatEpsilon)
53781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        transform.setD(1);
53881bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    else if (fabs(transform.d() + 1) <= s_floatEpsilon)
53981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        transform.setD(-1);
54081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
54181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (fabs(transform.e()) <= s_floatEpsilon)
54281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        transform.setE(0);
54381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
54481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch    if (fabs(transform.f()) <= s_floatEpsilon)
54581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        transform.setF(0);
54681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch}
54781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
548a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid SVGInlineTextBox::paintDecorationWithStyle(GraphicsContext* context, ETextDecoration decoration, const SVGTextFragment& fragment, RenderObject* decorationRenderer)
549a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
550a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT(!m_paintingResource);
551a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT(m_paintingResourceMode != ApplyToDefaultMode);
552a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
553a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    RenderStyle* decorationStyle = decorationRenderer->style();
554a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT(decorationStyle);
555a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
5562fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    float scalingFactor = 1;
5572fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    Font scaledFont;
5582fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    RenderSVGInlineText::computeNewScaledFontForStyle(decorationRenderer, decorationStyle, scalingFactor, scaledFont);
5592fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    ASSERT(scalingFactor);
560a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
561a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // The initial y value refers to overline position.
5622fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    float thickness = thicknessForDecoration(decoration, scaledFont);
563a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
564a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (fragment.width <= 0 && thickness <= 0)
565a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return;
566a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
5672fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    FloatPoint decorationOrigin(fragment.x, fragment.y);
5682fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    float width = fragment.width;
5692fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    const FontMetrics& scaledFontMetrics = scaledFont.fontMetrics();
570a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
571a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    context->save();
5722fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (scalingFactor != 1) {
5732fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        width *= scalingFactor;
5742fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        decorationOrigin.scale(scalingFactor, scalingFactor);
57581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
5767839f0a8c60340239148921eb35c3e2afc750701Steve Block#if PLATFORM(ANDROID)
5777839f0a8c60340239148921eb35c3e2afc750701Steve Block        // Android does not support GraphicsContext::setCTM().
5787839f0a8c60340239148921eb35c3e2afc750701Steve Block        AffineTransform scaleTransform;
5797839f0a8c60340239148921eb35c3e2afc750701Steve Block        scaleTransform.scale(1 / scalingFactor);
5807839f0a8c60340239148921eb35c3e2afc750701Steve Block        context->concatCTM(scaleTransform);
5817839f0a8c60340239148921eb35c3e2afc750701Steve Block#else
58281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        AffineTransform newTransform = context->getCTM();
58381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        newTransform.scale(1 / scalingFactor);
58481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        normalizeTransform(newTransform);
58581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
58681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        context->setCTM(newTransform);
5877839f0a8c60340239148921eb35c3e2afc750701Steve Block#endif
5882fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    }
589a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
5902fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    decorationOrigin.move(0, -scaledFontMetrics.floatAscent() + positionOffsetForDecoration(decoration, scaledFontMetrics, thickness));
5912fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
5922fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    Path path;
5932fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    path.addRect(FloatRect(decorationOrigin, FloatSize(width, thickness)));
5942fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
5952fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (acquirePaintingResource(context, scalingFactor, decorationRenderer, decorationStyle))
596f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch        releasePaintingResource(context, &path);
597a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
598a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    context->restore();
599a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
600a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
601a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid SVGInlineTextBox::paintTextWithShadows(GraphicsContext* context, RenderStyle* style, TextRun& textRun, const SVGTextFragment& fragment, int startPosition, int endPosition)
602a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
6032fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    RenderSVGInlineText* textRenderer = toRenderSVGInlineText(this->textRenderer());
6042fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    ASSERT(textRenderer);
6052fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
6062fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    float scalingFactor = textRenderer->scalingFactor();
6072fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    ASSERT(scalingFactor);
6082fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
6092fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    const Font& scaledFont = textRenderer->scaledFont();
610a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    const ShadowData* shadow = style->textShadow();
611a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
612a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    FloatPoint textOrigin(fragment.x, fragment.y);
6132fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    FloatSize textSize(fragment.width, fragment.height);
6142fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
6152fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    if (scalingFactor != 1) {
6162fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        textOrigin.scale(scalingFactor, scalingFactor);
6172fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        textSize.scale(scalingFactor);
6182fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    }
6192fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
6202fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    FloatRect shadowRect(FloatPoint(textOrigin.x(), textOrigin.y() - scaledFont.fontMetrics().floatAscent()), textSize);
621a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
622a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    do {
6232fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        if (!prepareGraphicsContextForTextPainting(context, scalingFactor, textRun, style))
624a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            break;
625a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
626a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        FloatSize extraOffset;
627a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        if (shadow)
62828040489d744e0c5d475a88663056c9040ed5320Teng-Hui Zhu            extraOffset = applyShadowToGraphicsContext(context, shadow, shadowRect, false /* stroked */, true /* opaque */, true /* horizontal */);
629a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
63081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        AffineTransform originalTransform;
63181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        if (scalingFactor != 1) {
6327839f0a8c60340239148921eb35c3e2afc750701Steve Block#if PLATFORM(ANDROID)
6337839f0a8c60340239148921eb35c3e2afc750701Steve Block            // Android does not support GraphicsContext::setCTM().
6347839f0a8c60340239148921eb35c3e2afc750701Steve Block            context->save();
6357839f0a8c60340239148921eb35c3e2afc750701Steve Block            AffineTransform scaleTransform;
6367839f0a8c60340239148921eb35c3e2afc750701Steve Block            scaleTransform.scale(1 / scalingFactor);
6377839f0a8c60340239148921eb35c3e2afc750701Steve Block            context->concatCTM(scaleTransform);
6387839f0a8c60340239148921eb35c3e2afc750701Steve Block#else
63981bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            originalTransform = context->getCTM();
64081bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
64181bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            AffineTransform newTransform = originalTransform;
64281bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            newTransform.scale(1 / scalingFactor);
64381bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            normalizeTransform(newTransform);
64481bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch
64581bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            context->setCTM(newTransform);
6467839f0a8c60340239148921eb35c3e2afc750701Steve Block#endif
64781bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch        }
6482fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
6492fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        scaledFont.drawText(context, textRun, textOrigin + extraOffset, startPosition, endPosition);
6502fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
6512fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        if (scalingFactor != 1)
6527839f0a8c60340239148921eb35c3e2afc750701Steve Block#if PLATFORM(ANDROID)
6537839f0a8c60340239148921eb35c3e2afc750701Steve Block            // Android does not support GraphicsContext::setCTM().
6547839f0a8c60340239148921eb35c3e2afc750701Steve Block            context->restore();
6557839f0a8c60340239148921eb35c3e2afc750701Steve Block#else
65681bc750723a18f21cd17d1b173cd2a4dda9cea6eBen Murdoch            context->setCTM(originalTransform);
6577839f0a8c60340239148921eb35c3e2afc750701Steve Block#endif
6582fc2651226baac27029e38c9d6ef883fa32084dbSteve Block
659a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        restoreGraphicsContextAfterTextPainting(context, textRun);
660a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
661a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        if (!shadow)
662a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            break;
663a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
664a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        if (shadow->next())
665a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            context->restore();
666a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        else
667a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            context->clearShadow();
668a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
669a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        shadow = shadow->next();
670a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    } while (shadow);
671a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
672a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
673a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid SVGInlineTextBox::paintText(GraphicsContext* context, RenderStyle* style, RenderStyle* selectionStyle, const SVGTextFragment& fragment, bool hasSelection, bool paintSelectedTextOnly)
674a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
675a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT(style);
676a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT(selectionStyle);
677a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
678a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    int startPosition = 0;
679a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    int endPosition = 0;
680a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (hasSelection) {
681a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        selectionStartEnd(startPosition, endPosition);
682a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        hasSelection = mapStartEndPositionsIntoFragmentCoordinates(fragment, startPosition, endPosition);
683a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
684a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
685a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // Fast path if there is no selection, just draw the whole chunk part using the regular style
686a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    TextRun textRun(constructTextRun(style, fragment));
687a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (!hasSelection || startPosition >= endPosition) {
688a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        paintTextWithShadows(context, style, textRun, fragment, 0, fragment.length);
689a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return;
690a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
691a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
692a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // Eventually draw text using regular style until the start position of the selection
693a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (startPosition > 0 && !paintSelectedTextOnly)
694a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        paintTextWithShadows(context, style, textRun, fragment, 0, startPosition);
695a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
696a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // Draw text using selection style from the start to the end position of the selection
697a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (style != selectionStyle)
698a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        SVGResourcesCache::clientStyleChanged(parent()->renderer(), StyleDifferenceRepaint, selectionStyle);
699a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
700a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    TextRun selectionTextRun(constructTextRun(selectionStyle, fragment));
701a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    paintTextWithShadows(context, selectionStyle, textRun, fragment, startPosition, endPosition);
702a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
703a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (style != selectionStyle)
704a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        SVGResourcesCache::clientStyleChanged(parent()->renderer(), StyleDifferenceRepaint, style);
705a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
706a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // Eventually draw text using regular style from the end position of the selection to the end of the current chunk part
707a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (endPosition < static_cast<int>(fragment.length) && !paintSelectedTextOnly)
708a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        paintTextWithShadows(context, style, textRun, fragment, endPosition, fragment.length);
709a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
710a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
711a94275402997c11dd2e778633dacf4b7e630a35dBen MurdochIntRect SVGInlineTextBox::calculateBoundaries() const
712a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
713a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    FloatRect textRect;
714a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
7152fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    RenderSVGInlineText* textRenderer = toRenderSVGInlineText(this->textRenderer());
716a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT(textRenderer);
717a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
7182fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    float scalingFactor = textRenderer->scalingFactor();
7192fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    ASSERT(scalingFactor);
720a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
7212fc2651226baac27029e38c9d6ef883fa32084dbSteve Block    float baseline = textRenderer->scaledFont().fontMetrics().floatAscent() / scalingFactor;
722a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
7232daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch    AffineTransform fragmentTransform;
724a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    unsigned textFragmentsSize = m_textFragments.size();
725a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    for (unsigned i = 0; i < textFragmentsSize; ++i) {
726a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        const SVGTextFragment& fragment = m_textFragments.at(i);
7272fc2651226baac27029e38c9d6ef883fa32084dbSteve Block        FloatRect fragmentRect(fragment.x, fragment.y - baseline, fragment.width, fragment.height);
7282daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        fragment.buildFragmentTransform(fragmentTransform);
7292daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!fragmentTransform.isIdentity())
7302daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            fragmentRect = fragmentTransform.mapRect(fragmentRect);
731a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
732a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        textRect.unite(fragmentRect);
733a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
734a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
735a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    return enclosingIntRect(textRect);
736a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
737a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
738a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} // namespace WebCore
739a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
740a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#endif
741