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