File indexing completed on 2024-05-05 16:11:04
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)