2008-11-04 Anders Carlsson <andersca@apple.com>
[webkit/qt.git] / WebCore / rendering / RenderSVGInlineText.cpp
blob4ba458df1ed626b7154e2c21e1eb5bd2deada69f
1 /*
2 * This file is part of the WebKit project.
4 * Copyright (C) 2006 Oliver Hunt <ojh16@student.canterbury.ac.nz>
5 * (C) 2006 Apple Computer Inc.
6 * (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
7 * (C) 2008 Rob Buis <buis@kde.org>
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
19 * You should have received a copy of the GNU Library General Public License
20 * along with this library; see the file COPYING.LIB. If not, write to
21 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 * Boston, MA 02110-1301, USA.
26 #include "config.h"
28 #if ENABLE(SVG)
29 #include "RenderSVGInlineText.h"
31 #include "FloatConversion.h"
32 #include "RenderBlock.h"
33 #include "RenderSVGRoot.h"
34 #include "SVGInlineTextBox.h"
35 #include "SVGRootInlineBox.h"
37 namespace WebCore {
39 static inline bool isChildOfHiddenContainer(RenderObject* start)
41 while (start) {
42 if (start->isSVGHiddenContainer())
43 return true;
45 start = start->parent();
48 return false;
51 RenderSVGInlineText::RenderSVGInlineText(Node* n, PassRefPtr<StringImpl> str)
52 : RenderText(n, str)
56 void RenderSVGInlineText::absoluteRects(Vector<IntRect>& rects, int, int, bool)
58 rects.append(computeAbsoluteRectForRange(0, textLength()));
61 IntRect RenderSVGInlineText::selectionRect(bool)
63 ASSERT(!needsLayout());
65 IntRect rect;
66 if (selectionState() == SelectionNone)
67 return rect;
69 // Early exit if we're ie. a <text> within a <defs> section.
70 if (isChildOfHiddenContainer(this))
71 return rect;
73 // Now calculate startPos and endPos for painting selection.
74 // We include a selection while endPos > 0
75 int startPos, endPos;
76 if (selectionState() == SelectionInside) {
77 // We are fully selected.
78 startPos = 0;
79 endPos = textLength();
80 } else {
81 selectionStartEnd(startPos, endPos);
82 if (selectionState() == SelectionStart)
83 endPos = textLength();
84 else if (selectionState() == SelectionEnd)
85 startPos = 0;
88 if (startPos == endPos)
89 return rect;
91 return computeAbsoluteRectForRange(startPos, endPos);
94 IntRect RenderSVGInlineText::computeAbsoluteRectForRange(int startPos, int endPos)
96 IntRect rect;
98 RenderBlock* cb = containingBlock();
99 if (!cb || !cb->container())
100 return rect;
102 RenderSVGRoot* root = findSVGRootObject(parent());
103 if (!root)
104 return rect;
106 for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox())
107 rect.unite(box->selectionRect(0, 0, startPos, endPos));
109 // Mimic RenderBox::computeAbsoluteRepaintRect() functionality. But only the subset needed for SVG and respecting SVG transformations.
110 FloatPoint absPos = cb->container()->localToAbsolute();
112 // Remove HTML parent translation offsets here! These need to be retrieved from the RenderSVGRoot object.
113 // But do take the containingBlocks's container position into account, ie. SVG text in scrollable <div>.
114 AffineTransform htmlParentCtm = root->RenderContainer::absoluteTransform();
116 FloatRect fixedRect(narrowPrecisionToFloat(rect.x() + absPos.x() - xPos() - htmlParentCtm.e()),
117 narrowPrecisionToFloat(rect.y() + absPos.y() - yPos() - htmlParentCtm.f()), rect.width(), rect.height());
118 return enclosingIntRect(absoluteTransform().mapRect(fixedRect));
121 InlineTextBox* RenderSVGInlineText::createInlineTextBox()
123 return new (renderArena()) SVGInlineTextBox(this);
126 IntRect RenderSVGInlineText::caretRect(InlineBox* inlineBox, int caretOffset, int* extraWidthToEndOfLine)
128 // SVG doesn't have any editable content where a caret rect would be needed
129 return IntRect();
132 VisiblePosition RenderSVGInlineText::positionForCoordinates(int x, int y)
134 SVGInlineTextBox* textBox = static_cast<SVGInlineTextBox*>(firstTextBox());
136 if (!textBox || textLength() == 0)
137 return VisiblePosition(element(), 0, DOWNSTREAM);
139 SVGRootInlineBox* rootBox = textBox->svgRootInlineBox();
140 RenderObject* object = rootBox ? rootBox->object() : 0;
142 if (!object)
143 return VisiblePosition(element(), 0, DOWNSTREAM);
145 int offset = 0;
147 for (SVGInlineTextBox* box = textBox; box; box = static_cast<SVGInlineTextBox*>(box->nextTextBox())) {
148 if (box->svgCharacterHitsPosition(x + object->xPos(), y + object->yPos(), offset)) {
149 // If we're not at the end/start of the box, stop looking for other selected boxes.
150 if (box->direction() == LTR) {
151 if (offset <= (int) box->end() + 1)
152 break;
153 } else {
154 if (offset > (int) box->start())
155 break;
160 return VisiblePosition(element(), offset, DOWNSTREAM);
163 void RenderSVGInlineText::destroy()
165 if (!documentBeingDestroyed()) {
166 setNeedsLayoutAndPrefWidthsRecalc();
167 repaint();
169 RenderText::destroy();
174 #endif // ENABLE(SVG)