File indexing completed on 2024-04-28 15:24:18
0001 /* 0002 * This file is part of the WebKit project. 0003 * 0004 * Copyright (C) 2006 Apple Computer, Inc. 0005 * 2006 Alexander Kellett <lypanov@kde.org> 0006 * 2006 Oliver Hunt <ojh16@student.canterbury.ac.nz> 0007 * 2007 Nikolas Zimmermann <zimmermann@kde.org> 0008 * 0009 * This library is free software; you can redistribute it and/or 0010 * modify it under the terms of the GNU Library General Public 0011 * License as published by the Free Software Foundation; either 0012 * version 2 of the License, or (at your option) any later version. 0013 * 0014 * This library is distributed in the hope that it will be useful, 0015 * but WITHOUT ANY WARRANTY; without even the implied warranty of 0016 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0017 * Library General Public License for more details. 0018 * 0019 * You should have received a copy of the GNU Library General Public License 0020 * along with this library; see the file COPYING.LIB. If not, write to 0021 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0022 * Boston, MA 02110-1301, USA. 0023 * 0024 */ 0025 0026 #include "wtf/Platform.h" 0027 0028 #if ENABLE(SVG) 0029 #include "RenderSVGText.h" 0030 0031 #include "FloatConversion.h" 0032 /*#include "GraphicsContext.h" 0033 #include "PointerEventsHitRules.h"*/ 0034 #include "RenderSVGRoot.h" 0035 /*#include "SimpleFontData.h"*/ 0036 #include "SVGLengthList.h" 0037 #include "SVGResourceFilter.h" 0038 #include "SVGRootInlineBox.h" 0039 #include "SVGTextElement.h" 0040 #include "SVGTransformList.h" 0041 #include "SVGURIReference.h" 0042 0043 namespace WebCore 0044 { 0045 0046 RenderSVGText::RenderSVGText(SVGTextElement *node) 0047 : RenderSVGBlock(node) 0048 { 0049 } 0050 0051 IntRect RenderSVGText::absoluteClippedOverflowRect() 0052 { 0053 FloatRect repaintRect = absoluteTransform().mapRect(relativeBBox(true)); 0054 0055 #if ENABLE(SVG_FILTERS) 0056 // Filters can expand the bounding box 0057 SVGResourceFilter *filter = getFilterById(document(), SVGURIReference::getTarget(style()->svgStyle()->filter())); 0058 if (filter) { 0059 repaintRect.unite(filter->filterBBoxForItemBBox(repaintRect)); 0060 } 0061 #endif 0062 0063 if (!repaintRect.isEmpty()) { 0064 repaintRect.inflate(1); // inflate 1 pixel for antialiasing 0065 } 0066 0067 return enclosingIntRect(repaintRect); 0068 } 0069 0070 bool RenderSVGText::requiresLayer() const 0071 { 0072 return false; 0073 } 0074 0075 bool RenderSVGText::calculateLocalTransform() 0076 { 0077 AffineTransform oldTransform = m_localTransform; 0078 m_localTransform = static_cast<SVGTextElement *>(element())->animatedLocalTransform(); 0079 return (oldTransform != m_localTransform); 0080 } 0081 0082 void RenderSVGText::layout() 0083 { 0084 ASSERT(needsLayout()); 0085 0086 // FIXME: This is a hack to avoid the RenderBlock::layout() partial repainting code which is not (yet) SVG aware 0087 setNeedsLayout(true); 0088 0089 IntRect oldBounds; 0090 IntRect oldOutlineBox; 0091 /*bool checkForRepaint = checkForRepaintDuringLayout(); 0092 if (checkForRepaint) { 0093 oldBounds = m_absoluteBounds; 0094 oldOutlineBox = absoluteOutlineBox(); 0095 }*/ 0096 0097 // Best guess for a relative starting point 0098 SVGTextElement *text = static_cast<SVGTextElement *>(element()); 0099 int xOffset = (int)(text->x()->getFirst().value()); 0100 int yOffset = (int)(text->y()->getFirst().value()); 0101 setPos(xOffset, yOffset); 0102 0103 calculateLocalTransform(); 0104 0105 RenderBlock::layout(); 0106 0107 m_absoluteBounds = absoluteClippedOverflowRect(); 0108 0109 /*bool repainted = false; 0110 if (checkForRepaint) 0111 repainted = repaintAfterLayoutIfNeeded(oldBounds, oldOutlineBox);*/ 0112 0113 setNeedsLayout(false); 0114 } 0115 0116 InlineBox *RenderSVGText::createInlineBox(bool makePlaceHolderBox, bool isRootLineBox/*, bool isOnlyRun*/) 0117 { 0118 Q_UNUSED(makePlaceHolderBox); 0119 Q_UNUSED(isRootLineBox); 0120 // qCDebug(KHTML_LOG) << "createInlineBox" << makePlaceHolderBox << isRootLineBox; 0121 ASSERT(!isInlineFlow()); 0122 InlineFlowBox *flowBox = new(renderArena()) SVGRootInlineBox(this); 0123 0124 if (!m_firstLineBox) { 0125 m_firstLineBox = m_lastLineBox = flowBox; 0126 } else { 0127 m_lastLineBox->setNextLineBox(flowBox); 0128 flowBox->setPreviousLineBox(m_lastLineBox); 0129 m_lastLineBox = flowBox; 0130 } 0131 0132 return flowBox; 0133 } 0134 0135 /*bool RenderSVGText::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction) 0136 { 0137 PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_TEXT_HITTESTING, style()->svgStyle()->pointerEvents()); 0138 bool isVisible = (style()->visibility() == VISIBLE); 0139 if (isVisible || !hitRules.requireVisible) { 0140 if ((hitRules.canHitStroke && (style()->svgStyle()->hasStroke() || !hitRules.requireStroke)) 0141 || (hitRules.canHitFill && (style()->svgStyle()->hasFill() || !hitRules.requireFill))) { 0142 AffineTransform totalTransform = absoluteTransform(); 0143 double localX, localY; 0144 totalTransform.inverse().map(_x, _y, &localX, &localY); 0145 FloatPoint hitPoint(_x, _y); 0146 return RenderBlock::nodeAtPoint(request, result, (int)localX, (int)localY, _tx, _ty, hitTestAction); 0147 } 0148 } 0149 0150 return false; 0151 }*/ 0152 0153 void RenderSVGText::absoluteRects(Vector<IntRect> &rects, int, int, bool) 0154 { 0155 RenderSVGRoot *root = findSVGRootObject(parent()); 0156 if (!root) { 0157 return; 0158 } 0159 0160 int x, y; 0161 absolutePosition(x, y); 0162 0163 AffineTransform htmlParentCtm = root->RenderContainer::absoluteTransform(); 0164 0165 // Don't use relativeBBox here, as it's unites the selection rects. Makes it hard 0166 // to spot errors, if there are any using WebInspector. Individually feed them into 'rects'. 0167 for (InlineRunBox *runBox = firstLineBox(); runBox; runBox = runBox->nextLineBox()) { 0168 ASSERT(runBox->isInlineFlowBox()); 0169 0170 InlineFlowBox *flowBox = static_cast<InlineFlowBox *>(runBox); 0171 for (InlineBox *box = flowBox->firstChild(); box; box = box->nextOnLine()) { 0172 FloatRect boxRect(box->xPos(), box->yPos(), box->width(), box->height()); 0173 boxRect.move(narrowPrecisionToFloat(x - htmlParentCtm.e()), narrowPrecisionToFloat(y - htmlParentCtm.f())); 0174 rects.append(enclosingIntRect(absoluteTransform().mapRect(boxRect))); 0175 } 0176 } 0177 } 0178 0179 void RenderSVGText::paint(PaintInfo &paintInfo, int, int) 0180 { 0181 RenderObject::PaintInfo pi(paintInfo); 0182 //FIXME khtml pi.rect = absoluteTransform().inverse().mapRect(pi.rect); 0183 RenderBlock::paint(pi, 0, 0); 0184 } 0185 0186 FloatRect RenderSVGText::relativeBBox(bool includeStroke) const 0187 { 0188 FloatRect repaintRect; 0189 0190 for (InlineRunBox *runBox = firstLineBox(); runBox; runBox = runBox->nextLineBox()) { 0191 ASSERT(runBox->isInlineFlowBox()); 0192 0193 InlineFlowBox *flowBox = static_cast<InlineFlowBox *>(runBox); 0194 for (InlineBox *box = flowBox->firstChild(); box; box = box->nextOnLine()) { 0195 repaintRect.unite(FloatRect(box->xPos(), box->yPos(), box->width(), box->height())); 0196 } 0197 } 0198 0199 // SVG needs to include the strokeWidth(), not the textStrokeWidth(). 0200 if (includeStroke && style()->svgStyle()->hasStroke()) { 0201 float strokeWidth = SVGRenderStyle::cssPrimitiveToLength(this, style()->svgStyle()->strokeWidth(), 0.0f); 0202 0203 #if ENABLE(SVG_FONTS) 0204 /*FIXME khtml const Font& font = style()->font(); 0205 if (font.primaryFont()->isSVGFont()) { 0206 float scale = font.unitsPerEm() > 0 ? font.size() / font.unitsPerEm() : 0.0f; 0207 0208 if (scale != 0.0f) 0209 strokeWidth /= scale; 0210 }*/ 0211 #endif 0212 0213 repaintRect.inflate(strokeWidth); 0214 } 0215 0216 repaintRect.move(xPos(), yPos()); 0217 return repaintRect; 0218 } 0219 0220 } 0221 0222 #endif // ENABLE(SVG) 0223