1a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch/* 2a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * Copyright (C) 2006 Oliver Hunt <ojh16@student.canterbury.ac.nz> 3a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * Copyright (C) 2006 Apple Computer Inc. 4a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org> 5a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * Copyright (C) 2008 Rob Buis <buis@kde.org> 6a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * Copyright (C) Research In Motion Limited 2010. All rights reserved. 7a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * 8a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * This library is free software; you can redistribute it and/or 9a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * modify it under the terms of the GNU Library General Public 10a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * License as published by the Free Software Foundation; either 11a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * version 2 of the License, or (at your option) any later version. 12a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * 13a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * This library is distributed in the hope that it will be useful, 14a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * but WITHOUT ANY WARRANTY; without even the implied warranty of 15a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * Library General Public License for more details. 17a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * 18a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * You should have received a copy of the GNU Library General Public License 19a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * along with this library; see the file COPYING.LIB. If not, write to 20a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 21a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * Boston, MA 02110-1301, USA. 22a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch */ 23a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 24a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "config.h" 25a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 26a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#if ENABLE(SVG) 27a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "RenderSVGInlineText.h" 28a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 292fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include "CSSStyleSelector.h" 30a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "FloatConversion.h" 31a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "FloatQuad.h" 32a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "RenderBlock.h" 33a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "RenderSVGRoot.h" 34a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "RenderSVGText.h" 352fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include "Settings.h" 362fc2651226baac27029e38c9d6ef883fa32084dbSteve Block#include "SVGImageBufferTools.h" 37a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "SVGInlineTextBox.h" 38a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "SVGRootInlineBox.h" 39a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "VisiblePosition.h" 40a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 41a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochnamespace WebCore { 42a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 43a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochstatic PassRefPtr<StringImpl> applySVGWhitespaceRules(PassRefPtr<StringImpl> string, bool preserveWhiteSpace) 44a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 45a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (preserveWhiteSpace) { 46a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // Spec: When xml:space="preserve", the SVG user agent will do the following using a 47a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // copy of the original character data content. It will convert all newline and tab 48a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // characters into space characters. Then, it will draw all space characters, including 49a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // leading, trailing and multiple contiguous space characters. 50a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch RefPtr<StringImpl> newString = string->replace('\t', ' '); 51a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch newString = newString->replace('\n', ' '); 52a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch newString = newString->replace('\r', ' '); 53a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return newString.release(); 54a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } 55a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 56a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // Spec: When xml:space="default", the SVG user agent will do the following using a 57a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // copy of the original character data content. First, it will remove all newline 58a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // characters. Then it will convert all tab characters into space characters. 59a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // Then, it will strip off all leading and trailing space characters. 60a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // Then, all contiguous space characters will be consolidated. 61a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch RefPtr<StringImpl> newString = string->replace('\n', StringImpl::empty()); 62a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch newString = newString->replace('\r', StringImpl::empty()); 63a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch newString = newString->replace('\t', ' '); 64a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return newString.release(); 65a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 66a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 67a94275402997c11dd2e778633dacf4b7e630a35dBen MurdochRenderSVGInlineText::RenderSVGInlineText(Node* n, PassRefPtr<StringImpl> string) 68a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch : RenderText(n, applySVGWhitespaceRules(string, false)) 692fc2651226baac27029e38c9d6ef883fa32084dbSteve Block , m_scalingFactor(1) 70a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 71a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 72a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 7354cdeeebc7adcbcd900e8b6a141a8cae27d9a631Steve Blockvoid RenderSVGInlineText::destroy() 7454cdeeebc7adcbcd900e8b6a141a8cae27d9a631Steve Block{ 7554cdeeebc7adcbcd900e8b6a141a8cae27d9a631Steve Block if (RenderSVGText* textRenderer = RenderSVGText::locateRenderSVGTextAncestor(this)) 7654cdeeebc7adcbcd900e8b6a141a8cae27d9a631Steve Block textRenderer->setNeedsPositioningValuesUpdate(); 7754cdeeebc7adcbcd900e8b6a141a8cae27d9a631Steve Block 7854cdeeebc7adcbcd900e8b6a141a8cae27d9a631Steve Block RenderText::destroy(); 7954cdeeebc7adcbcd900e8b6a141a8cae27d9a631Steve Block} 8054cdeeebc7adcbcd900e8b6a141a8cae27d9a631Steve Block 81a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid RenderSVGInlineText::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) 82a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 83a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch RenderText::styleDidChange(diff, oldStyle); 84a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 85a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (diff == StyleDifferenceLayout) { 86a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // The text metrics may be influenced by style changes. 87a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (RenderSVGText* textRenderer = RenderSVGText::locateRenderSVGTextAncestor(this)) 88a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch textRenderer->setNeedsPositioningValuesUpdate(); 892fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 902fc2651226baac27029e38c9d6ef883fa32084dbSteve Block updateScaledFont(); 91a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } 92a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 93a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch const RenderStyle* newStyle = style(); 94a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (!newStyle || newStyle->whiteSpace() != PRE) 95a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return; 96a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 97a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (!oldStyle || oldStyle->whiteSpace() != PRE) 98a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch setText(applySVGWhitespaceRules(originalText(), true), true); 99a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 100a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 101a94275402997c11dd2e778633dacf4b7e630a35dBen MurdochInlineTextBox* RenderSVGInlineText::createTextBox() 102a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 103a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch InlineTextBox* box = new (renderArena()) SVGInlineTextBox(this); 104a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch box->setHasVirtualLogicalHeight(); 105a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return box; 106a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 107a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 108cad810f21b803229eb11403f9209855525a25d57Steve BlockIntRect RenderSVGInlineText::localCaretRect(InlineBox* box, int caretOffset, int*) 109a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 110cad810f21b803229eb11403f9209855525a25d57Steve Block if (!box->isInlineTextBox()) 111cad810f21b803229eb11403f9209855525a25d57Steve Block return IntRect(); 112cad810f21b803229eb11403f9209855525a25d57Steve Block 113cad810f21b803229eb11403f9209855525a25d57Steve Block InlineTextBox* textBox = static_cast<InlineTextBox*>(box); 114cad810f21b803229eb11403f9209855525a25d57Steve Block if (static_cast<unsigned>(caretOffset) < textBox->start() || static_cast<unsigned>(caretOffset) > textBox->start() + textBox->len()) 115cad810f21b803229eb11403f9209855525a25d57Steve Block return IntRect(); 116cad810f21b803229eb11403f9209855525a25d57Steve Block 117cad810f21b803229eb11403f9209855525a25d57Steve Block // Use the edge of the selection rect to determine the caret rect. 118cad810f21b803229eb11403f9209855525a25d57Steve Block if (static_cast<unsigned>(caretOffset) < textBox->start() + textBox->len()) { 119cad810f21b803229eb11403f9209855525a25d57Steve Block IntRect rect = textBox->selectionRect(0, 0, caretOffset, caretOffset + 1); 1202fc2651226baac27029e38c9d6ef883fa32084dbSteve Block int x = box->isLeftToRightDirection() ? rect.x() : rect.maxX(); 121cad810f21b803229eb11403f9209855525a25d57Steve Block return IntRect(x, rect.y(), caretWidth, rect.height()); 122cad810f21b803229eb11403f9209855525a25d57Steve Block } 123cad810f21b803229eb11403f9209855525a25d57Steve Block 124cad810f21b803229eb11403f9209855525a25d57Steve Block IntRect rect = textBox->selectionRect(0, 0, caretOffset - 1, caretOffset); 1252fc2651226baac27029e38c9d6ef883fa32084dbSteve Block int x = box->isLeftToRightDirection() ? rect.maxX() : rect.x(); 126cad810f21b803229eb11403f9209855525a25d57Steve Block return IntRect(x, rect.y(), caretWidth, rect.height()); 127a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 128a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 129a94275402997c11dd2e778633dacf4b7e630a35dBen MurdochIntRect RenderSVGInlineText::linesBoundingBox() const 130a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 131a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch IntRect boundingBox; 132a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) 133a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch boundingBox.unite(box->calculateBoundaries()); 134a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return boundingBox; 135a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 136a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 137a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochbool RenderSVGInlineText::characterStartsNewTextChunk(int position) const 138a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 139a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch ASSERT(m_attributes.xValues().size() == textLength()); 140a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch ASSERT(m_attributes.yValues().size() == textLength()); 141a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch ASSERT(position >= 0); 142a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch ASSERT(position < static_cast<int>(textLength())); 143a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 144a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // Each <textPath> element starts a new text chunk, regardless of any x/y values. 145a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (!position && parent()->isSVGTextPath() && !previousSibling()) 146a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return true; 147a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 148a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch int currentPosition = 0; 149a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch unsigned size = m_attributes.textMetricsValues().size(); 150a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch for (unsigned i = 0; i < size; ++i) { 151a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch const SVGTextMetrics& metrics = m_attributes.textMetricsValues().at(i); 152a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 153a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // We found the desired character. 154a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (currentPosition == position) { 155a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return m_attributes.xValues().at(position) != SVGTextLayoutAttributes::emptyValue() 156a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch || m_attributes.yValues().at(position) != SVGTextLayoutAttributes::emptyValue(); 157a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } 158a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 159a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch currentPosition += metrics.length(); 160a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (currentPosition > position) 161a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch break; 162a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } 163a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 164a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // The desired position is available in the x/y list, but not in the character data values list. 165a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // That means the previous character data described a single glyph, consisting of multiple unicode characters. 166a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // The consequence is that the desired character does not define a new absolute x/y position, even if present in the x/y test. 167a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // This code is tested by svg/W3C-SVG-1.1/text-text-06-t.svg (and described in detail, why this influences chunk detection). 168a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return false; 169a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 170a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 171a94275402997c11dd2e778633dacf4b7e630a35dBen MurdochVisiblePosition RenderSVGInlineText::positionForPoint(const IntPoint& point) 172a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{ 173a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (!firstTextBox() || !textLength()) 174a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return createVisiblePosition(0, DOWNSTREAM); 175a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 1762fc2651226baac27029e38c9d6ef883fa32084dbSteve Block float baseline = m_scaledFont.fontMetrics().floatAscent(); 177a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 178a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch RenderBlock* containingBlock = this->containingBlock(); 179a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch ASSERT(containingBlock); 180a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 181a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch // Map local point to absolute point, as the character origins stored in the text fragments use absolute coordinates. 182a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch FloatPoint absolutePoint(point); 183a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch absolutePoint.move(containingBlock->x(), containingBlock->y()); 184a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 185a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch float closestDistance = std::numeric_limits<float>::max(); 186a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch float closestDistancePosition = 0; 187a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch const SVGTextFragment* closestDistanceFragment = 0; 188a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch SVGInlineTextBox* closestDistanceBox = 0; 189a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 1902daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch AffineTransform fragmentTransform; 191a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) { 1922daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if (!box->isSVGInlineTextBox()) 1932daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch continue; 1942daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch 195a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch SVGInlineTextBox* textBox = static_cast<SVGInlineTextBox*>(box); 196a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch Vector<SVGTextFragment>& fragments = textBox->textFragments(); 197a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 198a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch unsigned textFragmentsSize = fragments.size(); 199a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch for (unsigned i = 0; i < textFragmentsSize; ++i) { 200a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch const SVGTextFragment& fragment = fragments.at(i); 201a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch FloatRect fragmentRect(fragment.x, fragment.y - baseline, fragment.width, fragment.height); 2022daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch fragment.buildFragmentTransform(fragmentTransform); 2032daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch if (!fragmentTransform.isIdentity()) 2042daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch fragmentRect = fragmentTransform.mapRect(fragmentRect); 205a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 206a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch float distance = powf(fragmentRect.x() - absolutePoint.x(), 2) + 207a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch powf(fragmentRect.y() + fragmentRect.height() / 2 - absolutePoint.y(), 2); 208a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 209a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (distance < closestDistance) { 210a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch closestDistance = distance; 211a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch closestDistanceBox = textBox; 212a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch closestDistanceFragment = &fragment; 213a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch closestDistancePosition = fragmentRect.x(); 214a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } 215a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } 216a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch } 217a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 218a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch if (!closestDistanceFragment) 219a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return createVisiblePosition(0, DOWNSTREAM); 220a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 221a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch int offset = closestDistanceBox->offsetForPositionInFragment(*closestDistanceFragment, absolutePoint.x() - closestDistancePosition, true); 222a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch return createVisiblePosition(offset + closestDistanceBox->start(), offset > 0 ? VP_UPSTREAM_IF_POSSIBLE : DOWNSTREAM); 223a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 224a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 2252fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockvoid RenderSVGInlineText::updateScaledFont() 2262fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{ 2272fc2651226baac27029e38c9d6ef883fa32084dbSteve Block computeNewScaledFontForStyle(this, style(), m_scalingFactor, m_scaledFont); 2282fc2651226baac27029e38c9d6ef883fa32084dbSteve Block} 2292fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 2302fc2651226baac27029e38c9d6ef883fa32084dbSteve Blockvoid RenderSVGInlineText::computeNewScaledFontForStyle(RenderObject* renderer, const RenderStyle* style, float& scalingFactor, Font& scaledFont) 2312fc2651226baac27029e38c9d6ef883fa32084dbSteve Block{ 2322fc2651226baac27029e38c9d6ef883fa32084dbSteve Block ASSERT(style); 2332fc2651226baac27029e38c9d6ef883fa32084dbSteve Block ASSERT(renderer); 2342fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 2352fc2651226baac27029e38c9d6ef883fa32084dbSteve Block Document* document = renderer->document(); 2362fc2651226baac27029e38c9d6ef883fa32084dbSteve Block ASSERT(document); 2372fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 2382fc2651226baac27029e38c9d6ef883fa32084dbSteve Block CSSStyleSelector* styleSelector = document->styleSelector(); 2392fc2651226baac27029e38c9d6ef883fa32084dbSteve Block ASSERT(styleSelector); 2402fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 2412fc2651226baac27029e38c9d6ef883fa32084dbSteve Block // Alter font-size to the right on-screen value, to avoid scaling the glyphs themselves. 2422fc2651226baac27029e38c9d6ef883fa32084dbSteve Block AffineTransform ctm; 2432fc2651226baac27029e38c9d6ef883fa32084dbSteve Block SVGImageBufferTools::calculateTransformationToOutermostSVGCoordinateSystem(renderer, ctm); 2442fc2651226baac27029e38c9d6ef883fa32084dbSteve Block scalingFactor = narrowPrecisionToFloat(sqrt((pow(ctm.xScale(), 2) + pow(ctm.yScale(), 2)) / 2)); 2452fc2651226baac27029e38c9d6ef883fa32084dbSteve Block if (scalingFactor == 1 || !scalingFactor) { 2462fc2651226baac27029e38c9d6ef883fa32084dbSteve Block scalingFactor = 1; 2472fc2651226baac27029e38c9d6ef883fa32084dbSteve Block scaledFont = style->font(); 2482fc2651226baac27029e38c9d6ef883fa32084dbSteve Block return; 2492fc2651226baac27029e38c9d6ef883fa32084dbSteve Block } 2502fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 2512fc2651226baac27029e38c9d6ef883fa32084dbSteve Block FontDescription fontDescription(style->fontDescription()); 2522fc2651226baac27029e38c9d6ef883fa32084dbSteve Block fontDescription.setComputedSize(fontDescription.computedSize() * scalingFactor); 2532fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 2542fc2651226baac27029e38c9d6ef883fa32084dbSteve Block scaledFont = Font(fontDescription, 0, 0); 2552fc2651226baac27029e38c9d6ef883fa32084dbSteve Block scaledFont.update(styleSelector->fontSelector()); 2562fc2651226baac27029e38c9d6ef883fa32084dbSteve Block} 2572fc2651226baac27029e38c9d6ef883fa32084dbSteve Block 258a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} 259a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch 260a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#endif // ENABLE(SVG) 261