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) Research In Motion Limited 2010. All rights reserved.
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2011 Torch Mobile (Beijing) CO. Ltd. 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"
2553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/svg/SVGRootInlineBox.h"
265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2753e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/svg/RenderSVGInlineText.h"
2853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/svg/RenderSVGText.h"
2953e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/svg/SVGInlineFlowBox.h"
3053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/svg/SVGInlineTextBox.h"
3153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "core/rendering/svg/SVGRenderingContext.h"
325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
33c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink {
345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
3509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)void SVGRootInlineBox::paint(PaintInfo& paintInfo, const LayoutPoint& paintOffset, LayoutUnit, LayoutUnit)
365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection);
385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
39d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    bool isPrinting = renderer().document().printing();
405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool hasSelection = !isPrinting && selectionState() != RenderObject::SelectionNone;
415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    PaintInfo childPaintInfo(paintInfo);
435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (hasSelection) {
445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (InlineBox* child = firstChild(); child; child = child->nextOnLine()) {
455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (child->isSVGInlineTextBox())
46591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch                toSVGInlineTextBox(child)->paintSelectionBackground(childPaintInfo);
475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            else if (child->isSVGInlineFlowBox())
480019e4eead4d990e4304c54a9028aca9122fb256Ben Murdoch                toSVGInlineFlowBox(child)->paintSelectionBackground(childPaintInfo);
495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
527242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    GraphicsContextStateSaver stateSaver(*paintInfo.context);
537242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci    SVGRenderingContext renderingContext(&renderer(), paintInfo);
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (renderingContext.isRenderingPrepared()) {
5509380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        for (InlineBox* child = firstChild(); child; child = child->nextOnLine())
5609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            child->paint(paintInfo, paintOffset, 0, 0);
575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
60f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liuvoid SVGRootInlineBox::markDirty()
6193ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles){
62f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    for (InlineBox* child = firstChild(); child; child = child->nextOnLine())
63f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu        child->markDirty();
64f91f5fa1608c2cdd9af1842fb5dadbe78275be2aBo Liu    RootInlineBox::markDirty();
6593ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)}
6693ac45cfc74041c8ae536ce58a9534d46db2024eTorne (Richard Coles)
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGRootInlineBox::computePerCharacterLayoutInformation()
685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
69d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    RenderSVGText& textRoot = toRenderSVGText(block());
705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
71d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    Vector<SVGTextLayoutAttributes*>& layoutAttributes = textRoot.layoutAttributes();
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (layoutAttributes.isEmpty())
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
75d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (textRoot.needsReordering())
765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        reorderValueLists(layoutAttributes);
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Perform SVG text layout phase two (see SVGTextLayoutEngine for details).
795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SVGTextLayoutEngine characterLayout(layoutAttributes);
805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    layoutCharactersInTextBoxes(this, characterLayout);
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Perform SVG text layout phase three (see SVGTextChunkBuilder for details).
835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    characterLayout.finishLayout();
845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Perform SVG text layout phase four
865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Position & resize all SVGInlineText/FlowBoxes in the inline box tree, resize the root box as well as the RenderSVGText parent block.
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    FloatRect childRect;
885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    layoutChildBoxes(this, &childRect);
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    layoutRootBox(childRect);
905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGRootInlineBox::layoutCharactersInTextBoxes(InlineFlowBox* start, SVGTextLayoutEngine& characterLayout)
935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (InlineBox* child = start->firstChild(); child; child = child->nextOnLine()) {
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (child->isSVGInlineTextBox()) {
96d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            ASSERT(child->renderer().isSVGInlineText());
97591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            characterLayout.layoutInlineTextBox(toSVGInlineTextBox(child));
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        } else {
995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Skip generated content.
100d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            Node* node = child->renderer().node();
1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (!node)
1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                continue;
1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1040019e4eead4d990e4304c54a9028aca9122fb256Ben Murdoch            SVGInlineFlowBox* flowBox = toSVGInlineFlowBox(child);
105d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            bool isTextPath = isSVGTextPathElement(*node);
1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (isTextPath) {
1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                // Build text chunks for all <textPath> children, using the line layout algorithm.
1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                // This is needeed as text-anchor is just an additional startOffset for text paths.
1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                SVGTextLayoutEngine lineLayout(characterLayout.layoutAttributes());
1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                layoutCharactersInTextBoxes(flowBox, lineLayout);
1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
112d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)                characterLayout.beginTextPathLayout(&child->renderer(), lineLayout);
1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            layoutCharactersInTextBoxes(flowBox, characterLayout);
1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (isTextPath)
1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                characterLayout.endTextPathLayout();
1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGRootInlineBox::layoutChildBoxes(InlineFlowBox* start, FloatRect* childRect)
1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (InlineBox* child = start->firstChild(); child; child = child->nextOnLine()) {
1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        FloatRect boxRect;
1275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (child->isSVGInlineTextBox()) {
128d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            ASSERT(child->renderer().isSVGInlineText());
1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
130591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch            SVGInlineTextBox* textBox = toSVGInlineTextBox(child);
1315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            boxRect = textBox->calculateBoundaries();
1325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            textBox->setX(boxRect.x());
1335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            textBox->setY(boxRect.y());
1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            textBox->setLogicalWidth(boxRect.width());
1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            textBox->setLogicalHeight(boxRect.height());
1365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        } else {
1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            // Skip generated content.
138d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            if (!child->renderer().node())
1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                continue;
1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1410019e4eead4d990e4304c54a9028aca9122fb256Ben Murdoch            SVGInlineFlowBox* flowBox = toSVGInlineFlowBox(child);
1425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            layoutChildBoxes(flowBox);
1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            boxRect = flowBox->calculateBoundaries();
1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            flowBox->setX(boxRect.x());
1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            flowBox->setY(boxRect.y());
1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            flowBox->setLogicalWidth(boxRect.width());
1485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            flowBox->setLogicalHeight(boxRect.height());
1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (childRect)
1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            childRect->unite(boxRect);
1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGRootInlineBox::layoutRootBox(const FloatRect& childRect)
1565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
157d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    RenderBlockFlow& parentBlock = block();
1585c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Finally, assign the root block position, now that all content is laid out.
160926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    LayoutRect boundingRect = enclosingLayoutRect(childRect);
161d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    parentBlock.setLocation(boundingRect.location());
162d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    parentBlock.setSize(boundingRect.size());
1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Position all children relative to the parent block.
1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (InlineBox* child = firstChild(); child; child = child->nextOnLine()) {
1665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Skip generated content.
167d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)        if (!child->renderer().node())
1685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            continue;
1695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        child->adjustPosition(-childRect.x(), -childRect.y());
1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // Position ourselves.
1735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    setX(0);
1745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    setY(0);
1755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    setLogicalWidth(childRect.width());
1765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    setLogicalHeight(childRect.height());
177926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    setLineTopBottomPositions(0, boundingRect.height(), 0, boundingRect.height());
1785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
1795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)InlineBox* SVGRootInlineBox::closestLeafChildForPosition(const LayoutPoint& point)
1815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
1825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    InlineBox* firstLeaf = firstLeafChild();
1835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    InlineBox* lastLeaf = lastLeafChild();
1845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    if (firstLeaf == lastLeaf)
1855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return firstLeaf;
1865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // FIXME: Check for vertical text!
1885c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    InlineBox* closestLeaf = 0;
1895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (InlineBox* leaf = firstLeaf; leaf; leaf = leaf->nextLeafChild()) {
1905c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!leaf->isSVGInlineTextBox())
1915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            continue;
1925c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (point.y() < leaf->y())
1935c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            continue;
1945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (point.y() > leaf->y() + leaf->virtualLogicalHeight())
1955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            continue;
1965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
1975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        closestLeaf = leaf;
1985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (point.x() < leaf->left() + leaf->logicalWidth())
1995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return leaf;
2005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return closestLeaf ? closestLeaf : lastLeaf;
2035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline void swapItemsInLayoutAttributes(SVGTextLayoutAttributes* firstAttributes, SVGTextLayoutAttributes* lastAttributes, unsigned firstPosition, unsigned lastPosition)
2065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SVGCharacterDataMap::iterator itFirst = firstAttributes->characterDataMap().find(firstPosition + 1);
2085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SVGCharacterDataMap::iterator itLast = lastAttributes->characterDataMap().find(lastPosition + 1);
2095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool firstPresent = itFirst != firstAttributes->characterDataMap().end();
2105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    bool lastPresent = itLast != lastAttributes->characterDataMap().end();
211d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // We only want to perform the swap if both inline boxes are absolutely
212d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    // positioned.
213d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    if (!firstPresent || !lastPresent)
2145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        return;
215d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)    std::swap(itFirst->value, itLast->value);
2165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline void findFirstAndLastAttributesInVector(Vector<SVGTextLayoutAttributes*>& attributes, RenderSVGInlineText* firstContext, RenderSVGInlineText* lastContext,
2195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                                      SVGTextLayoutAttributes*& first, SVGTextLayoutAttributes*& last)
2205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    first = 0;
2225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    last = 0;
2235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    unsigned attributesSize = attributes.size();
2255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (unsigned i = 0; i < attributesSize; ++i) {
2265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        SVGTextLayoutAttributes* current = attributes[i];
2275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!first && firstContext == current->context())
2285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            first = current;
2295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!last && lastContext == current->context())
2305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            last = current;
2315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (first && last)
2325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            break;
2335c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(first);
2365c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(last);
2375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline void reverseInlineBoxRangeAndValueListsIfNeeded(void* userData, Vector<InlineBox*>::iterator first, Vector<InlineBox*>::iterator last)
2405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    ASSERT(userData);
2425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Vector<SVGTextLayoutAttributes*>& attributes = *reinterpret_cast<Vector<SVGTextLayoutAttributes*>*>(userData);
2435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    // This is a copy of std::reverse(first, last). It additionally assures that the metrics map within the renderers belonging to the InlineBoxes are reordered as well.
2455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    while (true)  {
2465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (first == last || first == --last)
2475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            return;
2485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (!(*last)->isSVGInlineTextBox() || !(*first)->isSVGInlineTextBox()) {
2505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            InlineBox* temp = *first;
2515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            *first = *last;
2525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            *last = temp;
2535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ++first;
2545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            continue;
2555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
257591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        SVGInlineTextBox* firstTextBox = toSVGInlineTextBox(*first);
258591b958dee2cf159d33a0b931e6231072eaf38d5Ben Murdoch        SVGInlineTextBox* lastTextBox = toSVGInlineTextBox(*last);
2595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // Reordering is only necessary for BiDi text that is _absolutely_ positioned.
2615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        if (firstTextBox->len() == 1 && firstTextBox->len() == lastTextBox->len()) {
262c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            RenderSVGInlineText& firstContext = toRenderSVGInlineText(firstTextBox->renderer());
263c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)            RenderSVGInlineText& lastContext = toRenderSVGInlineText(lastTextBox->renderer());
2645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            SVGTextLayoutAttributes* firstAttributes = 0;
2665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            SVGTextLayoutAttributes* lastAttributes = 0;
267d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)            findFirstAndLastAttributesInVector(attributes, &firstContext, &lastContext, firstAttributes, lastAttributes);
2685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            swapItemsInLayoutAttributes(firstAttributes, lastAttributes, firstTextBox->start(), lastTextBox->start());
2695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        }
2705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        InlineBox* temp = *first;
2725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        *first = *last;
2735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        *last = temp;
2745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        ++first;
2765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
2775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
2795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SVGRootInlineBox::reorderValueLists(Vector<SVGTextLayoutAttributes*>& attributes)
2805c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){
2815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    Vector<InlineBox*> leafBoxesInLogicalOrder;
2825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    collectLeafBoxesInLogicalOrder(leafBoxesInLogicalOrder, reverseInlineBoxRangeAndValueListsIfNeeded, &attributes);
2835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
285c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink
286