1a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch/*
2a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * Copyright (C) 2006 Oliver Hunt <ojh16@student.canterbury.ac.nz>
3a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * Copyright (C) 2006 Apple Computer Inc.
4a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
5a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * Copyright (C) Research In Motion Limited 2010. All rights reserved.
6a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch *
7a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * This library is free software; you can redistribute it and/or
8a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * modify it under the terms of the GNU Library General Public
9a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * License as published by the Free Software Foundation; either
10a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * version 2 of the License, or (at your option) any later version.
11a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch *
12a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * This library is distributed in the hope that it will be useful,
13a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * but WITHOUT ANY WARRANTY; without even the implied warranty of
14a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * Library General Public License for more details.
16a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch *
17a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * You should have received a copy of the GNU Library General Public License
18a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * along with this library; see the file COPYING.LIB.  If not, write to
19a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch * Boston, MA 02110-1301, USA.
21a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch */
22a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
23a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "config.h"
24a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "SVGRootInlineBox.h"
25a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
26a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#if ENABLE(SVG)
27a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "GraphicsContext.h"
28a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "RenderSVGInlineText.h"
292bde8e466a4451c7319e3a072d118917957d6554Steve Block#include "RenderSVGText.h"
30a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "SVGInlineFlowBox.h"
31a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "SVGInlineTextBox.h"
32f05b935882198ccf7d81675736e3aeb089c5113aBen Murdoch#include "SVGNames.h"
33a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "SVGRenderSupport.h"
34a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#include "SVGTextPositioningElement.h"
35a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
36a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochnamespace WebCore {
37a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
382daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdochvoid SVGRootInlineBox::paint(PaintInfo& paintInfo, int, int, int, int)
39a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
40a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT(paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection);
41a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT(!paintInfo.context->paintingDisabled());
42a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
43a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    RenderObject* boxRenderer = renderer();
44a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT(boxRenderer);
45a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
46a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    bool isPrinting = renderer()->document()->printing();
47a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    bool hasSelection = !isPrinting && selectionState() != RenderObject::SelectionNone;
48a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
49a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    PaintInfo childPaintInfo(paintInfo);
50a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (hasSelection) {
51a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        for (InlineBox* child = firstChild(); child; child = child->nextOnLine()) {
52a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            if (child->isSVGInlineTextBox())
53a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                static_cast<SVGInlineTextBox*>(child)->paintSelectionBackground(childPaintInfo);
54a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            else if (child->isSVGInlineFlowBox())
55a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                static_cast<SVGInlineFlowBox*>(child)->paintSelectionBackground(childPaintInfo);
56a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        }
57a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
58a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
59a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    childPaintInfo.context->save();
60a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
61a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (SVGRenderSupport::prepareToRenderSVGContent(boxRenderer, childPaintInfo)) {
62a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        for (InlineBox* child = firstChild(); child; child = child->nextOnLine()) {
63a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            if (child->isSVGInlineTextBox())
64a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                SVGInlineFlowBox::computeTextMatchMarkerRectForRenderer(toRenderSVGInlineText(static_cast<SVGInlineTextBox*>(child)->textRenderer()));
65a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
662daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            child->paint(childPaintInfo, 0, 0, 0, 0);
67a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        }
68a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
69a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
70a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    SVGRenderSupport::finishRenderSVGContent(boxRenderer, childPaintInfo, paintInfo.context);
71a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    childPaintInfo.context->restore();
72a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
73a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
74a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid SVGRootInlineBox::computePerCharacterLayoutInformation()
75a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
762bde8e466a4451c7319e3a072d118917957d6554Steve Block    RenderSVGText* parentBlock = toRenderSVGText(block());
772bde8e466a4451c7319e3a072d118917957d6554Steve Block    ASSERT(parentBlock);
782bde8e466a4451c7319e3a072d118917957d6554Steve Block
792bde8e466a4451c7319e3a072d118917957d6554Steve Block    Vector<SVGTextLayoutAttributes>& attributes = parentBlock->layoutAttributes();
802bde8e466a4451c7319e3a072d118917957d6554Steve Block    if (parentBlock->needsReordering())
812bde8e466a4451c7319e3a072d118917957d6554Steve Block        reorderValueLists(attributes);
822bde8e466a4451c7319e3a072d118917957d6554Steve Block
83a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // Perform SVG text layout phase two (see SVGTextLayoutEngine for details).
842bde8e466a4451c7319e3a072d118917957d6554Steve Block    SVGTextLayoutEngine characterLayout(attributes);
85a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    layoutCharactersInTextBoxes(this, characterLayout);
86a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
87a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // Perform SVG text layout phase three (see SVGTextChunkBuilder for details).
88a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    characterLayout.finishLayout();
89a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
90a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // Perform SVG text layout phase four
91a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // Position & resize all SVGInlineText/FlowBoxes in the inline box tree, resize the root box as well as the RenderSVGText parent block.
92a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    layoutChildBoxes(this);
93a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    layoutRootBox();
94a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
95a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
96a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid SVGRootInlineBox::layoutCharactersInTextBoxes(InlineFlowBox* start, SVGTextLayoutEngine& characterLayout)
97a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
98a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    for (InlineBox* child = start->firstChild(); child; child = child->nextOnLine()) {
99a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        if (child->isSVGInlineTextBox()) {
100a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            ASSERT(child->renderer());
101a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            ASSERT(child->renderer()->isSVGInlineText());
102a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
103a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            SVGInlineTextBox* textBox = static_cast<SVGInlineTextBox*>(child);
104a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            characterLayout.layoutInlineTextBox(textBox);
105a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        } else {
106a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            // Skip generated content.
107a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            Node* node = child->renderer()->node();
108a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            if (!node)
109a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                continue;
110a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
1112daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            ASSERT(child->isInlineFlowBox());
1122daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
113a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            SVGInlineFlowBox* flowBox = static_cast<SVGInlineFlowBox*>(child);
114a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            bool isTextPath = node->hasTagName(SVGNames::textPathTag);
115a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            if (isTextPath) {
116a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                // Build text chunks for all <textPath> children, using the line layout algorithm.
117a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                // This is needeed as text-anchor is just an additional startOffset for text paths.
1182bde8e466a4451c7319e3a072d118917957d6554Steve Block                RenderSVGText* parentBlock = toRenderSVGText(block());
1192bde8e466a4451c7319e3a072d118917957d6554Steve Block                ASSERT(parentBlock);
1202bde8e466a4451c7319e3a072d118917957d6554Steve Block
1212bde8e466a4451c7319e3a072d118917957d6554Steve Block                SVGTextLayoutEngine lineLayout(parentBlock->layoutAttributes());
122a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                layoutCharactersInTextBoxes(flowBox, lineLayout);
1232bde8e466a4451c7319e3a072d118917957d6554Steve Block
124a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                characterLayout.beginTextPathLayout(child->renderer(), lineLayout);
125a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            }
126a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
127a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            layoutCharactersInTextBoxes(flowBox, characterLayout);
128a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
129a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            if (isTextPath)
130a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                characterLayout.endTextPathLayout();
131a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        }
132a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
133a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
134a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
135a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid SVGRootInlineBox::layoutChildBoxes(InlineFlowBox* start)
136a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
137a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    for (InlineBox* child = start->firstChild(); child; child = child->nextOnLine()) {
138a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        if (child->isSVGInlineTextBox()) {
139a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            ASSERT(child->renderer());
140a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            ASSERT(child->renderer()->isSVGInlineText());
141a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
142a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            SVGInlineTextBox* textBox = static_cast<SVGInlineTextBox*>(child);
143a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            IntRect boxRect = textBox->calculateBoundaries();
144a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            textBox->setX(boxRect.x());
145a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            textBox->setY(boxRect.y());
146a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            textBox->setLogicalWidth(boxRect.width());
147a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            textBox->setLogicalHeight(boxRect.height());
148a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        } else {
149a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            // Skip generated content.
150a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            if (!child->renderer()->node())
151a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch                continue;
152a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
1532daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            ASSERT(child->isInlineFlowBox());
1542daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch
155a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            SVGInlineFlowBox* flowBox = static_cast<SVGInlineFlowBox*>(child);
156a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            layoutChildBoxes(flowBox);
157a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
158a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            IntRect boxRect = flowBox->calculateBoundaries();
159a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            flowBox->setX(boxRect.x());
160a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            flowBox->setY(boxRect.y());
161a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            flowBox->setLogicalWidth(boxRect.width());
162a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            flowBox->setLogicalHeight(boxRect.height());
163a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        }
164a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
165a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
166a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
167a94275402997c11dd2e778633dacf4b7e630a35dBen Murdochvoid SVGRootInlineBox::layoutRootBox()
168a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
169a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    RenderBlock* parentBlock = block();
170a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    ASSERT(parentBlock);
171a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
172a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    IntRect childRect;
173a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    for (InlineBox* child = firstChild(); child; child = child->nextOnLine()) {
174a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // Skip generated content.
175a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        if (!child->renderer()->node())
176a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            continue;
177a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        childRect.unite(child->calculateBoundaries());
178a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
179a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
180a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    int xBlock = childRect.x();
181a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    int yBlock = childRect.y();
182a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    int widthBlock = childRect.width();
183a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    int heightBlock = childRect.height();
184a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
185a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // Finally, assign the root block position, now that all content is laid out.
186a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    parentBlock->setLocation(xBlock, yBlock);
187a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    parentBlock->setWidth(widthBlock);
188a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    parentBlock->setHeight(heightBlock);
189a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
190a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // Position all children relative to the parent block.
191a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    for (InlineBox* child = firstChild(); child; child = child->nextOnLine()) {
192a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        // Skip generated content.
193a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        if (!child->renderer()->node())
194a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            continue;
195a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        child->adjustPosition(-xBlock, -yBlock);
196a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
197a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
198a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // Position ourselves.
199a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    setX(0);
200a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    setY(0);
201a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    setLogicalWidth(widthBlock);
202a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    setLogicalHeight(heightBlock);
203a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    setBlockLogicalHeight(heightBlock);
204a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    setLineTopBottomPositions(0, heightBlock);
205a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
206a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
207a94275402997c11dd2e778633dacf4b7e630a35dBen MurdochInlineBox* SVGRootInlineBox::closestLeafChildForPosition(const IntPoint& point)
208a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch{
209a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    InlineBox* firstLeaf = firstLeafChild();
210a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    InlineBox* lastLeaf = lastLeafChild();
211a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    if (firstLeaf == lastLeaf)
212a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        return firstLeaf;
213a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
214a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    // FIXME: Check for vertical text!
215a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    InlineBox* closestLeaf = 0;
216a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    for (InlineBox* leaf = firstLeaf; leaf; leaf = leaf->nextLeafChild()) {
2172daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!leaf->isSVGInlineTextBox())
2182daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            continue;
219a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        if (point.y() < leaf->m_y)
220a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            continue;
221a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        if (point.y() > leaf->m_y + leaf->virtualLogicalHeight())
222a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            continue;
223a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
224a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        closestLeaf = leaf;
225a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch        if (point.x() < leaf->m_x + leaf->m_logicalWidth)
226a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch            return leaf;
227a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    }
228a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
229a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch    return closestLeaf ? closestLeaf : lastLeaf;
230a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch}
2312bde8e466a4451c7319e3a072d118917957d6554Steve Block
2322bde8e466a4451c7319e3a072d118917957d6554Steve Blockstatic inline void swapItemsInVector(Vector<float>& firstVector, Vector<float>& lastVector, unsigned first, unsigned last)
2332bde8e466a4451c7319e3a072d118917957d6554Steve Block{
2342bde8e466a4451c7319e3a072d118917957d6554Steve Block    float temp = firstVector.at(first);
2352bde8e466a4451c7319e3a072d118917957d6554Steve Block    firstVector.at(first) = lastVector.at(last);
2362bde8e466a4451c7319e3a072d118917957d6554Steve Block    lastVector.at(last) = temp;
2372bde8e466a4451c7319e3a072d118917957d6554Steve Block}
2382bde8e466a4451c7319e3a072d118917957d6554Steve Block
2392bde8e466a4451c7319e3a072d118917957d6554Steve Blockstatic inline void swapItemsInLayoutAttributes(SVGTextLayoutAttributes& firstAttributes, SVGTextLayoutAttributes& lastAttributes, unsigned firstPosition, unsigned lastPosition)
2402bde8e466a4451c7319e3a072d118917957d6554Steve Block{
2412bde8e466a4451c7319e3a072d118917957d6554Steve Block    swapItemsInVector(firstAttributes.xValues(), lastAttributes.xValues(), firstPosition, lastPosition);
2422bde8e466a4451c7319e3a072d118917957d6554Steve Block    swapItemsInVector(firstAttributes.yValues(), lastAttributes.yValues(), firstPosition, lastPosition);
2432bde8e466a4451c7319e3a072d118917957d6554Steve Block    swapItemsInVector(firstAttributes.dxValues(), lastAttributes.dxValues(), firstPosition, lastPosition);
2442bde8e466a4451c7319e3a072d118917957d6554Steve Block    swapItemsInVector(firstAttributes.dyValues(), lastAttributes.dyValues(), firstPosition, lastPosition);
2452bde8e466a4451c7319e3a072d118917957d6554Steve Block    swapItemsInVector(firstAttributes.rotateValues(), lastAttributes.rotateValues(), firstPosition, lastPosition);
2462bde8e466a4451c7319e3a072d118917957d6554Steve Block}
2472bde8e466a4451c7319e3a072d118917957d6554Steve Block
2482bde8e466a4451c7319e3a072d118917957d6554Steve Blockstatic inline void findFirstAndLastAttributesInVector(Vector<SVGTextLayoutAttributes>& attributes, RenderSVGInlineText* firstContext, RenderSVGInlineText* lastContext,
2492bde8e466a4451c7319e3a072d118917957d6554Steve Block                                                      SVGTextLayoutAttributes*& first, SVGTextLayoutAttributes*& last)
2502bde8e466a4451c7319e3a072d118917957d6554Steve Block{
2512bde8e466a4451c7319e3a072d118917957d6554Steve Block    first = 0;
2522bde8e466a4451c7319e3a072d118917957d6554Steve Block    last = 0;
2532bde8e466a4451c7319e3a072d118917957d6554Steve Block
2542bde8e466a4451c7319e3a072d118917957d6554Steve Block    unsigned attributesSize = attributes.size();
2552bde8e466a4451c7319e3a072d118917957d6554Steve Block    for (unsigned i = 0; i < attributesSize; ++i) {
2562bde8e466a4451c7319e3a072d118917957d6554Steve Block        SVGTextLayoutAttributes& current = attributes.at(i);
2572bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (!first && firstContext == current.context())
2582bde8e466a4451c7319e3a072d118917957d6554Steve Block            first = &current;
2592bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (!last && lastContext == current.context())
2602bde8e466a4451c7319e3a072d118917957d6554Steve Block            last = &current;
2612bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (first && last)
2622bde8e466a4451c7319e3a072d118917957d6554Steve Block            break;
2632bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
2642bde8e466a4451c7319e3a072d118917957d6554Steve Block
2652bde8e466a4451c7319e3a072d118917957d6554Steve Block    ASSERT(first);
2662bde8e466a4451c7319e3a072d118917957d6554Steve Block    ASSERT(last);
2672bde8e466a4451c7319e3a072d118917957d6554Steve Block}
2682bde8e466a4451c7319e3a072d118917957d6554Steve Block
2692bde8e466a4451c7319e3a072d118917957d6554Steve Blockstatic inline void reverseInlineBoxRangeAndValueListsIfNeeded(void* userData, Vector<InlineBox*>::iterator first, Vector<InlineBox*>::iterator last)
2702bde8e466a4451c7319e3a072d118917957d6554Steve Block{
2712bde8e466a4451c7319e3a072d118917957d6554Steve Block    ASSERT(userData);
2722bde8e466a4451c7319e3a072d118917957d6554Steve Block    Vector<SVGTextLayoutAttributes>& attributes = *reinterpret_cast<Vector<SVGTextLayoutAttributes>*>(userData);
2732bde8e466a4451c7319e3a072d118917957d6554Steve Block
2742bde8e466a4451c7319e3a072d118917957d6554Steve Block    // This is a copy of std::reverse(first, last). It additionally assure that the value lists within the InlineBoxes are reordered as well.
2752bde8e466a4451c7319e3a072d118917957d6554Steve Block    while (true)  {
2762bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (first == last || first == --last)
2772bde8e466a4451c7319e3a072d118917957d6554Steve Block            return;
2782bde8e466a4451c7319e3a072d118917957d6554Steve Block
2792daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        if (!(*last)->isSVGInlineTextBox() || !(*first)->isSVGInlineTextBox()) {
2802daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            InlineBox* temp = *first;
2812daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            *first = *last;
2822daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            *last = temp;
2832daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            ++first;
2842daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch            continue;
2852daae5fd11344eaa88a0d92b0f6d65f8d2255c00Ben Murdoch        }
2862bde8e466a4451c7319e3a072d118917957d6554Steve Block
2872bde8e466a4451c7319e3a072d118917957d6554Steve Block        SVGInlineTextBox* firstTextBox = static_cast<SVGInlineTextBox*>(*first);
2882bde8e466a4451c7319e3a072d118917957d6554Steve Block        SVGInlineTextBox* lastTextBox = static_cast<SVGInlineTextBox*>(*last);
2892bde8e466a4451c7319e3a072d118917957d6554Steve Block
2902bde8e466a4451c7319e3a072d118917957d6554Steve Block        // Reordering is only necessary for BiDi text that is _absolutely_ positioned.
2912bde8e466a4451c7319e3a072d118917957d6554Steve Block        if (firstTextBox->len() == 1 && firstTextBox->len() == lastTextBox->len()) {
2922bde8e466a4451c7319e3a072d118917957d6554Steve Block            RenderSVGInlineText* firstContext = toRenderSVGInlineText(firstTextBox->textRenderer());
2932bde8e466a4451c7319e3a072d118917957d6554Steve Block            RenderSVGInlineText* lastContext = toRenderSVGInlineText(lastTextBox->textRenderer());
2942bde8e466a4451c7319e3a072d118917957d6554Steve Block
2952bde8e466a4451c7319e3a072d118917957d6554Steve Block            SVGTextLayoutAttributes* firstAttributes = 0;
2962bde8e466a4451c7319e3a072d118917957d6554Steve Block            SVGTextLayoutAttributes* lastAttributes = 0;
2972bde8e466a4451c7319e3a072d118917957d6554Steve Block            findFirstAndLastAttributesInVector(attributes, firstContext, lastContext, firstAttributes, lastAttributes);
2982bde8e466a4451c7319e3a072d118917957d6554Steve Block
2992bde8e466a4451c7319e3a072d118917957d6554Steve Block            unsigned firstBoxPosition = firstTextBox->start();
3002bde8e466a4451c7319e3a072d118917957d6554Steve Block            unsigned firstBoxEnd = firstTextBox->end();
3012bde8e466a4451c7319e3a072d118917957d6554Steve Block
3022bde8e466a4451c7319e3a072d118917957d6554Steve Block            unsigned lastBoxPosition = lastTextBox->start();
3032bde8e466a4451c7319e3a072d118917957d6554Steve Block            unsigned lastBoxEnd = lastTextBox->end();
3042bde8e466a4451c7319e3a072d118917957d6554Steve Block            for (; firstBoxPosition <= firstBoxEnd && lastBoxPosition <= lastBoxEnd; ++lastBoxPosition, ++firstBoxPosition)
3052bde8e466a4451c7319e3a072d118917957d6554Steve Block                swapItemsInLayoutAttributes(*firstAttributes, *lastAttributes, firstBoxPosition, lastBoxPosition);
3062bde8e466a4451c7319e3a072d118917957d6554Steve Block        }
3072bde8e466a4451c7319e3a072d118917957d6554Steve Block
3082bde8e466a4451c7319e3a072d118917957d6554Steve Block        InlineBox* temp = *first;
3092bde8e466a4451c7319e3a072d118917957d6554Steve Block        *first = *last;
3102bde8e466a4451c7319e3a072d118917957d6554Steve Block        *last = temp;
3112bde8e466a4451c7319e3a072d118917957d6554Steve Block
3122bde8e466a4451c7319e3a072d118917957d6554Steve Block        ++first;
3132bde8e466a4451c7319e3a072d118917957d6554Steve Block    }
3142bde8e466a4451c7319e3a072d118917957d6554Steve Block}
3152bde8e466a4451c7319e3a072d118917957d6554Steve Block
3162bde8e466a4451c7319e3a072d118917957d6554Steve Blockvoid SVGRootInlineBox::reorderValueLists(Vector<SVGTextLayoutAttributes>& attributes)
3172bde8e466a4451c7319e3a072d118917957d6554Steve Block{
3182bde8e466a4451c7319e3a072d118917957d6554Steve Block    Vector<InlineBox*> leafBoxesInLogicalOrder;
3192bde8e466a4451c7319e3a072d118917957d6554Steve Block    collectLeafBoxesInLogicalOrder(leafBoxesInLogicalOrder, reverseInlineBoxRangeAndValueListsIfNeeded, &attributes);
3202bde8e466a4451c7319e3a072d118917957d6554Steve Block}
321a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
322a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch} // namespace WebCore
323a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch
324a94275402997c11dd2e778633dacf4b7e630a35dBen Murdoch#endif // ENABLE(SVG)
325