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 = ¤t; 2592bde8e466a4451c7319e3a072d118917957d6554Steve Block if (!last && lastContext == current.context()) 2602bde8e466a4451c7319e3a072d118917957d6554Steve Block last = ¤t; 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