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