File indexing completed on 2024-05-05 12:16:13

0001 /*
0002  * This file is part of the WebKit project.
0003  *
0004  * Copyright (C) 2006 Oliver Hunt <ojh16@student.canterbury.ac.nz>
0005  *           (C) 2006 Apple Computer Inc.
0006  *           (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
0007  *
0008  * This library is free software; you can redistribute it and/or
0009  * modify it under the terms of the GNU Library General Public
0010  * License as published by the Free Software Foundation; either
0011  * version 2 of the License, or (at your option) any later version.
0012  *
0013  * This library is distributed in the hope that it will be useful,
0014  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0016  * Library General Public License for more details.
0017  *
0018  * You should have received a copy of the GNU Library General Public License
0019  * along with this library; see the file COPYING.LIB.  If not, write to
0020  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0021  * Boston, MA 02110-1301, USA.
0022  *
0023  */
0024 
0025 #include "wtf/Platform.h"
0026 
0027 #if ENABLE(SVG)
0028 #include "RenderSVGInlineText.h"
0029 
0030 #include "FloatConversion.h"
0031 //#include "RenderBlock.h"
0032 #include "render_block.h" // khtml
0033 #include "RenderSVGRoot.h"
0034 #include "SVGInlineTextBox.h"
0035 #include "SVGRootInlineBox.h"
0036 
0037 namespace WebCore
0038 {
0039 using namespace khtml;
0040 
0041 static inline bool isChildOfHiddenContainer(RenderObject *start)
0042 {
0043     while (start) {
0044         if (start->isSVGHiddenContainer()) {
0045             return true;
0046         }
0047 
0048         start = start->parent();
0049     }
0050 
0051     return false;
0052 }
0053 
0054 RenderSVGInlineText::RenderSVGInlineText(Node *n, DOMStringImpl *str)
0055     : RenderText(n, str)
0056 {
0057 }
0058 
0059 void RenderSVGInlineText::absoluteRects(Vector<IntRect> &rects, int, int, bool)
0060 {
0061     rects.append(computeAbsoluteRectForRange(0, stringLength()));
0062 }
0063 
0064 IntRect RenderSVGInlineText::selectionRect(bool)
0065 {
0066     ASSERT(!needsLayout());
0067 
0068     IntRect rect;
0069     if (selectionState() == SelectionNone) {
0070         return rect;
0071     }
0072 
0073     // Early exit if we're ie. a <text> within a <defs> section.
0074     if (isChildOfHiddenContainer(this)) {
0075         return rect;
0076     }
0077 
0078     // Now calculate startPos and endPos for painting selection.
0079     // We include a selection while endPos > 0
0080     int startPos, endPos;
0081     if (selectionState() == SelectionInside) {
0082         // We are fully selected.
0083         startPos = 0;
0084         endPos = stringLength();
0085     } else {
0086         selectionStartEnd(startPos, endPos);
0087         if (selectionState() == SelectionStart) {
0088             endPos = stringLength();
0089         } else if (selectionState() == SelectionEnd) {
0090             startPos = 0;
0091         }
0092     }
0093 
0094     if (startPos == endPos) {
0095         return rect;
0096     }
0097 
0098     return computeAbsoluteRectForRange(startPos, endPos);
0099 }
0100 
0101 IntRect RenderSVGInlineText::computeAbsoluteRectForRange(int startPos, int endPos)
0102 {
0103     Q_UNUSED(startPos);
0104     Q_UNUSED(endPos);
0105     IntRect rect;
0106 
0107     RenderBlock *cb = containingBlock();
0108     if (!cb || !cb->container()) {
0109         return rect;
0110     }
0111 
0112     RenderSVGRoot *root = findSVGRootObject(parent());
0113     if (!root) {
0114         return rect;
0115     }
0116 
0117     /*FIXME khtml for (InlineTextBox* box = firstTextBox(); box; box = box->nextTextBox())
0118         rect.unite(box->selectionRect(0, 0, startPos, endPos));*/
0119 
0120     // Mimic RenderBox::computeAbsoluteRepaintRect() functionality. But only the subset needed for SVG and respecting SVG transformations.
0121     int x, y;
0122     cb->container()->absolutePosition(x, y);
0123 
0124     // Remove HTML parent translation offsets here! These need to be retrieved from the RenderSVGRoot object.
0125     // But do take the containingBlocks's container position into account, ie. SVG text in scrollable <div>.
0126     AffineTransform htmlParentCtm = root->RenderContainer::absoluteTransform();
0127 
0128     FloatRect fixedRect(narrowPrecisionToFloat(rect.x() + x - xPos() - htmlParentCtm.e()), narrowPrecisionToFloat(rect.y() + y - yPos() - htmlParentCtm.f()), rect.width(), rect.height());
0129     return enclosingIntRect(absoluteTransform().mapRect(fixedRect));
0130 }
0131 
0132 InlineTextBox *RenderSVGInlineText::createInlineTextBox()
0133 {
0134     // qCDebug(KHTML_LOG) << "allocate";
0135     return new(renderArena()) SVGInlineTextBox(this);
0136 }
0137 
0138 /*IntRect RenderSVGInlineText::caretRect(int offset, EAffinity affinity, int* extraWidthToEndOfLine)
0139 {
0140     // SVG doesn't have any editable content where a caret rect would be needed
0141     return IntRect();
0142 }*/
0143 
0144 /*VisiblePosition RenderSVGInlineText::positionForCoordinates(int x, int y)
0145 {
0146     SVGInlineTextBox* textBox = static_cast<SVGInlineTextBox*>(firstTextBox());
0147 
0148     if (!textBox || textLength() == 0)
0149         return VisiblePosition(element(), 0, DOWNSTREAM);
0150 
0151     SVGRootInlineBox* rootBox = textBox->svgRootInlineBox();
0152     RenderObject* object = rootBox ? rootBox->object() : 0;
0153 
0154     if (!object)
0155         return VisiblePosition(element(), 0, DOWNSTREAM);
0156 
0157     int offset = 0;
0158 
0159     for (SVGInlineTextBox* box = textBox; box; box = static_cast<SVGInlineTextBox*>(box->nextTextBox())) {
0160         if (box->svgCharacterHitsPosition(x + object->xPos(), y + object->yPos(), offset)) {
0161             // If we're not at the end/start of the box, stop looking for other selected boxes.
0162             if (!box->m_reversed) {
0163                 if (offset <= (int) box->end() + 1)
0164                     break;
0165             } else {
0166                 if (offset > (int) box->start())
0167                     break;
0168             }
0169         }
0170     }
0171 
0172     return VisiblePosition(element(), offset, DOWNSTREAM);
0173 }*/
0174 
0175 }
0176 
0177 #endif // ENABLE(SVG)