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.
29 #include "RenderSVGInlineText.h"
31 #include "FloatConversion.h"
32 #include "RenderBlock.h"
33 #include "RenderSVGRoot.h"
34 #include "SVGInlineTextBox.h"
35 #include "SVGRootInlineBox.h"
39 static inline bool isChildOfHiddenContainer(RenderObject
* start
)
42 if (start
->isSVGHiddenContainer())
45 start
= start
->parent();
51 RenderSVGInlineText::RenderSVGInlineText(Node
* n
, PassRefPtr
<StringImpl
> 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());
66 if (selectionState() == SelectionNone
)
69 // Early exit if we're ie. a <text> within a <defs> section.
70 if (isChildOfHiddenContainer(this))
73 // Now calculate startPos and endPos for painting selection.
74 // We include a selection while endPos > 0
76 if (selectionState() == SelectionInside
) {
77 // We are fully selected.
79 endPos
= textLength();
81 selectionStartEnd(startPos
, endPos
);
82 if (selectionState() == SelectionStart
)
83 endPos
= textLength();
84 else if (selectionState() == SelectionEnd
)
88 if (startPos
== endPos
)
91 return computeAbsoluteRectForRange(startPos
, endPos
);
94 IntRect
RenderSVGInlineText::computeAbsoluteRectForRange(int startPos
, int endPos
)
98 RenderBlock
* cb
= containingBlock();
99 if (!cb
|| !cb
->container())
102 RenderSVGRoot
* root
= findSVGRootObject(parent());
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
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;
143 return VisiblePosition(element(), 0, DOWNSTREAM
);
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)
154 if (offset
> (int) box
->start())
160 return VisiblePosition(element(), offset
, DOWNSTREAM
);
163 void RenderSVGInlineText::destroy()
165 if (!documentBeingDestroyed()) {
166 setNeedsLayoutAndPrefWidthsRecalc();
169 RenderText::destroy();
174 #endif // ENABLE(SVG)