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