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"
30197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch#include "core/dom/StyleEngine.h"
3153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/editing/VisiblePosition.h"
3253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/svg/RenderSVGText.h"
3353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/svg/SVGInlineTextBox.h"
3453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/svg/SVGRenderingContext.h"
355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
36c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static PassRefPtr<StringImpl> applySVGWhitespaceRules(PassRefPtr<StringImpl> string, bool preserveWhiteSpace)
395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (preserveWhiteSpace) {
415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Spec: When xml:space="preserve", the SVG user agent will do the following using a
425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // copy of the original character data content. It will convert all newline and tab
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // characters into space characters. Then, it will draw all space characters, including
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // leading, trailing and multiple contiguous space characters.
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        RefPtr<StringImpl> newString = string->replace('\t', ' ');
465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        newString = newString->replace('\n', ' ');
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        newString = newString->replace('\r', ' ');
485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return newString.release();
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Spec: When xml:space="default", the SVG user agent will do the following using a
525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // copy of the original character data content. First, it will remove all newline
535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // characters. Then it will convert all tab characters into space characters.
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Then, it will strip off all leading and trailing space characters.
555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Then, all contiguous space characters will be consolidated.
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RefPtr<StringImpl> newString = string->replace('\n', StringImpl::empty());
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    newString = newString->replace('\r', StringImpl::empty());
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    newString = newString->replace('\t', ' ');
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return newString.release();
605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)RenderSVGInlineText::RenderSVGInlineText(Node* n, PassRefPtr<StringImpl> string)
635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    : RenderText(n, applySVGWhitespaceRules(string, false))
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_scalingFactor(1)
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    , m_layoutAttributes(this)
665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderSVGInlineText::setTextInternal(PassRefPtr<StringImpl> text)
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderText::setTextInternal(text);
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (RenderSVGText* textRenderer = RenderSVGText::locateRenderSVGTextAncestor(this))
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        textRenderer->subtreeTextDidChange(this);
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void RenderSVGInlineText::styleDidChange(StyleDifference diff, const RenderStyle* oldStyle)
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderText::styleDidChange(diff, oldStyle);
795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    updateScaledFont();
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool newPreserves = style() ? style()->whiteSpace() == PRE : false;
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool oldPreserves = oldStyle ? oldStyle->whiteSpace() == PRE : false;
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (oldPreserves && !newPreserves) {
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        setText(applySVGWhitespaceRules(originalText(), false), true);
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!oldPreserves && newPreserves) {
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        setText(applySVGWhitespaceRules(originalText(), true), true);
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
9310f88d5669dbd969c059d61ba09fa37dd72ac559Ben Murdoch    if (!diff.needsFullLayout())
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // The text metrics may be influenced by style changes.
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (RenderSVGText* textRenderer = RenderSVGText::locateRenderSVGTextAncestor(this))
985d92fedcae5e801a8b224de090094f2d9df0b54aTorne (Richard Coles)        textRenderer->setNeedsLayoutAndFullPaintInvalidation();
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)InlineTextBox* RenderSVGInlineText::createTextBox()
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
103d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    InlineTextBox* box = new SVGInlineTextBox(*this);
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    box->setHasVirtualLogicalHeight();
1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return box;
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)LayoutRect RenderSVGInlineText::localCaretRect(InlineBox* box, int caretOffset, LayoutUnit*)
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!box || !box->isInlineTextBox())
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return LayoutRect();
1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
11306f816c7c76bc45a15e452ade8a34e8af077693eTorne (Richard Coles)    InlineTextBox* textBox = toInlineTextBox(box);
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (static_cast<unsigned>(caretOffset) < textBox->start() || static_cast<unsigned>(caretOffset) > textBox->start() + textBox->len())
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return LayoutRect();
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Use the edge of the selection rect to determine the caret rect.
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (static_cast<unsigned>(caretOffset) < textBox->start() + textBox->len()) {
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        LayoutRect rect = textBox->localSelectionRect(caretOffset, caretOffset + 1);
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        LayoutUnit x = box->isLeftToRightDirection() ? rect.x() : rect.maxX();
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return LayoutRect(x, rect.y(), caretWidth, rect.height());
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    LayoutRect rect = textBox->localSelectionRect(caretOffset - 1, caretOffset);
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    LayoutUnit x = box->isLeftToRightDirection() ? rect.maxX() : rect.x();
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return LayoutRect(x, rect.y(), caretWidth, rect.height());
1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)FloatRect RenderSVGInlineText::floatLinesBoundingBox() const
1305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FloatRect boundingBox;
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox())
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        boundingBox.unite(box->calculateBoundaries());
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return boundingBox;
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)IntRect RenderSVGInlineText::linesBoundingBox() const
1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return enclosingIntRect(floatLinesBoundingBox());
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)bool RenderSVGInlineText::characterStartsNewTextChunk(int position) const
1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(position >= 0);
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(position < static_cast<int>(textLength()));
1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Each <textPath> element starts a new text chunk, regardless of any x/y values.
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!position && parent()->isSVGTextPath() && !previousSibling())
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return true;
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const SVGCharacterDataMap::const_iterator it = m_layoutAttributes.characterDataMap().find(static_cast<unsigned>(position + 1));
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (it == m_layoutAttributes.characterDataMap().end())
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return false;
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return it->value.x != SVGTextLayoutAttributes::emptyValue() || it->value.y != SVGTextLayoutAttributes::emptyValue();
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
158f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)PositionWithAffinity RenderSVGInlineText::positionForPoint(const LayoutPoint& point)
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (!firstTextBox() || !textLength())
161f5e4ad553afbc08dd2e729bb77e937a9a94d5827Torne (Richard Coles)        return createPositionWithAffinity(0, DOWNSTREAM);
1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    float baseline = m_scaledFont.fontMetrics().floatAscent();
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    RenderBlock* containingBlock = this->containingBlock();
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(containingBlock);
1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Map local point to absolute point, as the character origins stored in the text fragments use absolute coordinates.
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FloatPoint absolutePoint(point);
1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    absolutePoint.moveBy(containingBlock->location());
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    float closestDistance = std::numeric_limits<float>::max();
1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    float closestDistancePosition = 0;
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const SVGTextFragment* closestDistanceFragment = 0;
1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SVGInlineTextBox* closestDistanceBox = 0;
1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    AffineTransform fragmentTransform;
1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox()) {
1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!box->isSVGInlineTextBox())
1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            continue;
1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
182591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        SVGInlineTextBox* textBox = toSVGInlineTextBox(box);
1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        Vector<SVGTextFragment>& fragments = textBox->textFragments();
1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        unsigned textFragmentsSize = fragments.size();
1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (unsigned i = 0; i < textFragmentsSize; ++i) {
1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            const SVGTextFragment& fragment = fragments.at(i);
1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            FloatRect fragmentRect(fragment.x, fragment.y - baseline, fragment.width, fragment.height);
1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            fragment.buildFragmentTransform(fragmentTransform);
190d5428f32f5d1719f774f62e19147104ca245a3abTorne (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);
2237242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    if (style->effectiveZoom() == 1 && (scalingFactor == 1 || !scalingFactor)) {
2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        scalingFactor = 1;
2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        scaledFont = style->font();
2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
229d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (style->fontDescription().textRendering() == 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)
23809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    scaledFont = Font(fontDescription);
239a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    scaledFont.update(document.styleEngine()->fontSelector());
2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
243