summaryrefslogtreecommitdiffstats
path: root/WebCore/rendering/RenderSVGInlineText.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/rendering/RenderSVGInlineText.cpp')
-rw-r--r--WebCore/rendering/RenderSVGInlineText.cpp164
1 files changed, 164 insertions, 0 deletions
diff --git a/WebCore/rendering/RenderSVGInlineText.cpp b/WebCore/rendering/RenderSVGInlineText.cpp
new file mode 100644
index 0000000..36eb128
--- /dev/null
+++ b/WebCore/rendering/RenderSVGInlineText.cpp
@@ -0,0 +1,164 @@
+/*
+ * This file is part of the WebKit project.
+ *
+ * Copyright (C) 2006 Oliver Hunt <ojh16@student.canterbury.ac.nz>
+ * (C) 2006 Apple Computer Inc.
+ * (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "config.h"
+
+#if ENABLE(SVG)
+#include "RenderSVGInlineText.h"
+
+#include "FloatConversion.h"
+#include "RenderBlock.h"
+#include "RenderSVGRoot.h"
+#include "SVGInlineTextBox.h"
+#include "SVGRootInlineBox.h"
+
+namespace WebCore {
+
+static inline bool isChildOfHiddenContainer(RenderObject* start)
+{
+ while (start) {
+ if (start->isSVGHiddenContainer())
+ return true;
+
+ start = start->parent();
+ }
+
+ return false;
+}
+
+RenderSVGInlineText::RenderSVGInlineText(Node* n, PassRefPtr<StringImpl> str)
+ : RenderText(n, str)
+{
+}
+
+void RenderSVGInlineText::absoluteRects(Vector<IntRect>& rects, int, int, bool)
+{
+ rects.append(computeAbsoluteRectForRange(0, textLength()));
+}
+
+IntRect RenderSVGInlineText::selectionRect(bool)
+{
+ ASSERT(!needsLayout());
+
+ IntRect rect;
+ if (selectionState() == SelectionNone)
+ return rect;
+
+ // Early exit if we're ie. a <text> within a <defs> section.
+ if (isChildOfHiddenContainer(this))
+ return rect;
+
+ // Now calculate startPos and endPos for painting selection.
+ // We include a selection while endPos > 0
+ int startPos, endPos;
+ if (selectionState() == SelectionInside) {
+ // We are fully selected.
+ startPos = 0;
+ endPos = textLength();
+ } else {
+ selectionStartEnd(startPos, endPos);
+ if (selectionState() == SelectionStart)
+ endPos = textLength();
+ else if (selectionState() == SelectionEnd)
+ startPos = 0;
+ }
+
+ if (startPos == endPos)
+ return rect;
+
+ return computeAbsoluteRectForRange(startPos, endPos);
+}
+
+IntRect RenderSVGInlineText::computeAbsoluteRectForRange(int startPos, int endPos)
+{
+ IntRect rect;
+
+ RenderBlock* cb = containingBlock();
+ if (!cb || !cb->container())
+ return rect;
+
+ RenderSVGRoot* root = findSVGRootObject(parent());
+ if (!root)
+ return rect;
+
+ for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox())
+ rect.unite(box->selectionRect(0, 0, startPos, endPos));
+
+ // Mimic RenderBox::computeAbsoluteRepaintRect() functionality. But only the subset needed for SVG and respecting SVG transformations.
+ int x, y;
+ cb->container()->absolutePosition(x, y);
+
+ // Remove HTML parent translation offsets here! These need to be retrieved from the RenderSVGRoot object.
+ // But do take the containingBlocks's container position into account, ie. SVG text in scrollable <div>.
+ AffineTransform htmlParentCtm = root->RenderContainer::absoluteTransform();
+
+ FloatRect fixedRect(narrowPrecisionToFloat(rect.x() + x - xPos() - htmlParentCtm.e()), narrowPrecisionToFloat(rect.y() + y - yPos() - htmlParentCtm.f()), rect.width(), rect.height());
+ return enclosingIntRect(absoluteTransform().mapRect(fixedRect));
+}
+
+InlineTextBox* RenderSVGInlineText::createInlineTextBox()
+{
+ return new (renderArena()) SVGInlineTextBox(this);
+}
+
+IntRect RenderSVGInlineText::caretRect(int offset, EAffinity affinity, int* extraWidthToEndOfLine)
+{
+ // SVG doesn't have any editable content where a caret rect would be needed
+ return IntRect();
+}
+
+VisiblePosition RenderSVGInlineText::positionForCoordinates(int x, int y)
+{
+ SVGInlineTextBox* textBox = static_cast<SVGInlineTextBox*>(firstTextBox());
+
+ if (!textBox || textLength() == 0)
+ return VisiblePosition(element(), 0, DOWNSTREAM);
+
+ SVGRootInlineBox* rootBox = textBox->svgRootInlineBox();
+ RenderObject* object = rootBox ? rootBox->object() : 0;
+
+ if (!object)
+ return VisiblePosition(element(), 0, DOWNSTREAM);
+
+ int offset = 0;
+
+ for (SVGInlineTextBox* box = textBox; box; box = static_cast<SVGInlineTextBox*>(box->nextTextBox())) {
+ if (box->svgCharacterHitsPosition(x + object->xPos(), y + object->yPos(), offset)) {
+ // If we're not at the end/start of the box, stop looking for other selected boxes.
+ if (!box->m_reversed) {
+ if (offset <= (int) box->end() + 1)
+ break;
+ } else {
+ if (offset > (int) box->start())
+ break;
+ }
+ }
+ }
+
+ return VisiblePosition(element(), offset, DOWNSTREAM);
+}
+
+}
+
+#endif // ENABLE(SVG)