15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* 25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2006 Oliver Hunt <ojh16@student.canterbury.ac.nz> 35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2006 Apple Computer Inc. 45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org> 55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2008 Rob Buis <buis@kde.org> 65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) Research In Motion Limited 2010. All rights reserved. 75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is free software; you can redistribute it and/or 95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modify it under the terms of the GNU Library General Public 105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * License as published by the Free Software Foundation; either 115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * version 2 of the License, or (at your option) any later version. 125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * This library is distributed in the hope that it will be useful, 145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * but WITHOUT ANY WARRANTY; without even the implied warranty of 155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Library General Public License for more details. 175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * You should have received a copy of the GNU Library General Public License 195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * along with this library; see the file COPYING.LIB. If not, write to 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Boston, MA 02110-1301, USA. 225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h" 255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/svg/RenderSVGInlineText.h" 275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/css/CSSFontSelector.h" 295267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles)#include "core/css/FontSize.h" 3053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/editing/VisiblePosition.h" 3153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/svg/RenderSVGText.h" 3253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/svg/SVGInlineTextBox.h" 3353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/svg/SVGRenderingContext.h" 345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WebCore { 365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static PassRefPtr<StringImpl> applySVGWhitespaceRules(PassRefPtr<StringImpl> string, bool preserveWhiteSpace) 385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (preserveWhiteSpace) { 405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Spec: When xml:space="preserve", the SVG user agent will do the following using a 415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // copy of the original character data content. It will convert all newline and tab 425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // characters into space characters. Then, it will draw all space characters, including 435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // leading, trailing and multiple contiguous space characters. 445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RefPtr<StringImpl> newString = string->replace('\t', ' '); 455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) newString = newString->replace('\n', ' '); 465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) newString = newString->replace('\r', ' '); 475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return newString.release(); 485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Spec: When xml:space="default", the SVG user agent will do the following using a 515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // copy of the original character data content. First, it will remove all newline 525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // characters. Then it will convert all tab characters into space characters. 535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Then, it will strip off all leading and trailing space characters. 545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Then, all contiguous space characters will be consolidated. 555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RefPtr<StringImpl> newString = string->replace('\n', StringImpl::empty()); 565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) newString = newString->replace('\r', StringImpl::empty()); 575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) newString = newString->replace('\t', ' '); 585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return newString.release(); 595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)RenderSVGInlineText::RenderSVGInlineText(Node* n, PassRefPtr<StringImpl> string) 625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) : RenderText(n, applySVGWhitespaceRules(string, false)) 635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_scalingFactor(1) 645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_layoutAttributes(this) 655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderSVGInlineText::setTextInternal(PassRefPtr<StringImpl> text) 695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RenderText::setTextInternal(text); 715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (RenderSVGText* textRenderer = RenderSVGText::locateRenderSVGTextAncestor(this)) 725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) textRenderer->subtreeTextDidChange(this); 735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderSVGInlineText::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle) 765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RenderText::styleDidChange(diff, oldStyle); 785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) updateScaledFont(); 795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool newPreserves = style() ? style()->whiteSpace() == PRE : false; 815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) bool oldPreserves = oldStyle ? oldStyle->whiteSpace() == PRE : false; 825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (oldPreserves && !newPreserves) { 835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) setText(applySVGWhitespaceRules(originalText(), false), true); 845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!oldPreserves && newPreserves) { 885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) setText(applySVGWhitespaceRules(originalText(), true), true); 895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (diff != StyleDifferenceLayout) 935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // The text metrics may be influenced by style changes. 965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (RenderSVGText* textRenderer = RenderSVGText::locateRenderSVGTextAncestor(this)) 975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) textRenderer->subtreeStyleDidChange(this); 985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)InlineTextBox* RenderSVGInlineText::createTextBox() 1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 102f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) InlineTextBox* box = new SVGInlineTextBox(this); 1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) box->setHasVirtualLogicalHeight(); 1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return box; 1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)LayoutRect RenderSVGInlineText::localCaretRect(InlineBox* box, int caretOffset, LayoutUnit*) 1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!box || !box->isInlineTextBox()) 1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return LayoutRect(); 1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 11206f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles) InlineTextBox* textBox = toInlineTextBox(box); 1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (static_cast<unsigned>(caretOffset) < textBox->start() || static_cast<unsigned>(caretOffset) > textBox->start() + textBox->len()) 1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return LayoutRect(); 1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Use the edge of the selection rect to determine the caret rect. 1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (static_cast<unsigned>(caretOffset) < textBox->start() + textBox->len()) { 1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) LayoutRect rect = textBox->localSelectionRect(caretOffset, caretOffset + 1); 1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) LayoutUnit x = box->isLeftToRightDirection() ? rect.x() : rect.maxX(); 1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return LayoutRect(x, rect.y(), caretWidth, rect.height()); 1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) LayoutRect rect = textBox->localSelectionRect(caretOffset - 1, caretOffset); 1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) LayoutUnit x = box->isLeftToRightDirection() ? rect.maxX() : rect.x(); 1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return LayoutRect(x, rect.y(), caretWidth, rect.height()); 1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)FloatRect RenderSVGInlineText::floatLinesBoundingBox() const 1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) FloatRect boundingBox; 1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) 1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) boundingBox.unite(box->calculateBoundaries()); 1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return boundingBox; 1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)IntRect RenderSVGInlineText::linesBoundingBox() const 1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return enclosingIntRect(floatLinesBoundingBox()); 1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool RenderSVGInlineText::characterStartsNewTextChunk(int position) const 1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(position >= 0); 1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(position < static_cast<int>(textLength())); 1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Each <textPath> element starts a new text chunk, regardless of any x/y values. 1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!position && parent()->isSVGTextPath() && !previousSibling()) 1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return true; 1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const SVGCharacterDataMap::const_iterator it = m_layoutAttributes.characterDataMap().find(static_cast<unsigned>(position + 1)); 1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (it == m_layoutAttributes.characterDataMap().end()) 1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return false; 1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return it->value.x != SVGTextLayoutAttributes::emptyValue() || it->value.y != SVGTextLayoutAttributes::emptyValue(); 1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 157f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)PositionWithAffinity RenderSVGInlineText::positionForPoint(const LayoutPoint& point) 1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!firstTextBox() || !textLength()) 160f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) return createPositionWithAffinity(0, DOWNSTREAM); 1615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float baseline = m_scaledFont.fontMetrics().floatAscent(); 1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) RenderBlock* containingBlock = this->containingBlock(); 1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(containingBlock); 1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Map local point to absolute point, as the character origins stored in the text fragments use absolute coordinates. 1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) FloatPoint absolutePoint(point); 1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) absolutePoint.moveBy(containingBlock->location()); 1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float closestDistance = std::numeric_limits<float>::max(); 1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float closestDistancePosition = 0; 1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const SVGTextFragment* closestDistanceFragment = 0; 1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) SVGInlineTextBox* closestDistanceBox = 0; 1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) AffineTransform fragmentTransform; 1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) { 1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!box->isSVGInlineTextBox()) 1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) continue; 1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 181591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch SVGInlineTextBox* textBox = toSVGInlineTextBox(box); 1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) Vector<SVGTextFragment>& fragments = textBox->textFragments(); 1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) unsigned textFragmentsSize = fragments.size(); 1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) for (unsigned i = 0; i < textFragmentsSize; ++i) { 1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) const SVGTextFragment& fragment = fragments.at(i); 1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) FloatRect fragmentRect(fragment.x, fragment.y - baseline, fragment.width, fragment.height); 1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) fragment.buildFragmentTransform(fragmentTransform); 1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!fragmentTransform.isIdentity()) 1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) fragmentRect = fragmentTransform.mapRect(fragmentRect); 1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) float distance = powf(fragmentRect.x() - absolutePoint.x(), 2) + 1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) powf(fragmentRect.y() + fragmentRect.height() / 2 - absolutePoint.y(), 2); 1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (distance < closestDistance) { 1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) closestDistance = distance; 1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) closestDistanceBox = textBox; 1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) closestDistanceFragment = &fragment; 1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) closestDistancePosition = fragmentRect.x(); 2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (!closestDistanceFragment) 205f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) return createPositionWithAffinity(0, DOWNSTREAM); 2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) int offset = closestDistanceBox->offsetForPositionInFragment(*closestDistanceFragment, absolutePoint.x() - closestDistancePosition, true); 208f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles) return createPositionWithAffinity(offset + closestDistanceBox->start(), offset > 0 ? VP_UPSTREAM_IF_POSSIBLE : DOWNSTREAM); 2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderSVGInlineText::updateScaledFont() 2125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) computeNewScaledFontForStyle(this, style(), m_scalingFactor, m_scaledFont); 2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderSVGInlineText::computeNewScaledFontForStyle(RenderObject* renderer, const RenderStyle* style, float& scalingFactor, Font& scaledFont) 2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(style); 2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(renderer); 2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 221e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch // Alter font-size to the right on-screen value to avoid scaling the glyphs themselves, except when GeometricPrecision is specified. 2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) scalingFactor = SVGRenderingContext::calculateScreenFontSizeScalingFactor(renderer); 223e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch if (scalingFactor == 1 || !scalingFactor) { 2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) scalingFactor = 1; 2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) scaledFont = style->font(); 2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 229e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch if (style->fontDescription().textRenderingMode() == GeometricPrecision) 230e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch scalingFactor = 1; 231e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch 2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) FontDescription fontDescription(style->fontDescription()); 2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 234a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) Document& document = renderer->document(); 2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // FIXME: We need to better handle the case when we compute very small fonts below (below 1pt). 2368abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles) fontDescription.setComputedSize(FontSize::getComputedSizeFromSpecifiedSize(&document, scalingFactor, fontDescription.isAbsoluteSize(), fontDescription.specifiedSize(), DoNotUseSmartMinimumForFontSize)); 2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) scaledFont = Font(fontDescription, 0, 0); 239a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) scaledFont.update(document.styleEngine()->fontSelector()); 2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 243