KHtml

RenderSVGText.cpp
1 /*
2  * This file is part of the WebKit project.
3  *
4  * Copyright (C) 2006 Apple Computer, Inc.
5  * 2006 Alexander Kellett <[email protected]>
6  * 2006 Oliver Hunt <[email protected]>
7  * 2007 Nikolas Zimmermann <[email protected]>
8  *
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.
13  *
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.
18  *
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.
23  *
24  */
25 
26 #include "wtf/Platform.h"
27 
28 #if ENABLE(SVG)
29 #include "RenderSVGText.h"
30 
31 #include "FloatConversion.h"
32 /*#include "GraphicsContext.h"
33 #include "PointerEventsHitRules.h"*/
34 #include "RenderSVGRoot.h"
35 /*#include "SimpleFontData.h"*/
36 #include "SVGLengthList.h"
37 #include "SVGResourceFilter.h"
38 #include "SVGRootInlineBox.h"
39 #include "SVGTextElement.h"
40 #include "SVGTransformList.h"
41 #include "SVGURIReference.h"
42 
43 namespace WebCore
44 {
45 
46 RenderSVGText::RenderSVGText(SVGTextElement *node)
47  : RenderSVGBlock(node)
48 {
49 }
50 
51 IntRect RenderSVGText::absoluteClippedOverflowRect()
52 {
53  FloatRect repaintRect = absoluteTransform().mapRect(relativeBBox(true));
54 
55 #if ENABLE(SVG_FILTERS)
56  // Filters can expand the bounding box
57  SVGResourceFilter *filter = getFilterById(document(), SVGURIReference::getTarget(style()->svgStyle()->filter()));
58  if (filter) {
59  repaintRect.unite(filter->filterBBoxForItemBBox(repaintRect));
60  }
61 #endif
62 
63  if (!repaintRect.isEmpty()) {
64  repaintRect.inflate(1); // inflate 1 pixel for antialiasing
65  }
66 
67  return enclosingIntRect(repaintRect);
68 }
69 
70 bool RenderSVGText::requiresLayer() const
71 {
72  return false;
73 }
74 
75 bool RenderSVGText::calculateLocalTransform()
76 {
77  AffineTransform oldTransform = m_localTransform;
78  m_localTransform = static_cast<SVGTextElement *>(element())->animatedLocalTransform();
79  return (oldTransform != m_localTransform);
80 }
81 
82 void RenderSVGText::layout()
83 {
84  ASSERT(needsLayout());
85 
86  // FIXME: This is a hack to avoid the RenderBlock::layout() partial repainting code which is not (yet) SVG aware
87  setNeedsLayout(true);
88 
89  IntRect oldBounds;
90  IntRect oldOutlineBox;
91  /*bool checkForRepaint = checkForRepaintDuringLayout();
92  if (checkForRepaint) {
93  oldBounds = m_absoluteBounds;
94  oldOutlineBox = absoluteOutlineBox();
95  }*/
96 
97  // Best guess for a relative starting point
98  SVGTextElement *text = static_cast<SVGTextElement *>(element());
99  int xOffset = (int)(text->x()->getFirst().value());
100  int yOffset = (int)(text->y()->getFirst().value());
101  setPos(xOffset, yOffset);
102 
103  calculateLocalTransform();
104 
105  RenderBlock::layout();
106 
107  m_absoluteBounds = absoluteClippedOverflowRect();
108 
109  /*bool repainted = false;
110  if (checkForRepaint)
111  repainted = repaintAfterLayoutIfNeeded(oldBounds, oldOutlineBox);*/
112 
113  setNeedsLayout(false);
114 }
115 
116 InlineBox *RenderSVGText::createInlineBox(bool makePlaceHolderBox, bool isRootLineBox/*, bool isOnlyRun*/)
117 {
118  Q_UNUSED(makePlaceHolderBox);
119  Q_UNUSED(isRootLineBox);
120  // qCDebug(KHTML_LOG) << "createInlineBox" << makePlaceHolderBox << isRootLineBox;
121  ASSERT(!isInlineFlow());
122  InlineFlowBox *flowBox = new(renderArena()) SVGRootInlineBox(this);
123 
124  if (!m_firstLineBox) {
125  m_firstLineBox = m_lastLineBox = flowBox;
126  } else {
127  m_lastLineBox->setNextLineBox(flowBox);
128  flowBox->setPreviousLineBox(m_lastLineBox);
129  m_lastLineBox = flowBox;
130  }
131 
132  return flowBox;
133 }
134 
135 /*bool RenderSVGText::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction)
136 {
137  PointerEventsHitRules hitRules(PointerEventsHitRules::SVG_TEXT_HITTESTING, style()->svgStyle()->pointerEvents());
138  bool isVisible = (style()->visibility() == VISIBLE);
139  if (isVisible || !hitRules.requireVisible) {
140  if ((hitRules.canHitStroke && (style()->svgStyle()->hasStroke() || !hitRules.requireStroke))
141  || (hitRules.canHitFill && (style()->svgStyle()->hasFill() || !hitRules.requireFill))) {
142  AffineTransform totalTransform = absoluteTransform();
143  double localX, localY;
144  totalTransform.inverse().map(_x, _y, &localX, &localY);
145  FloatPoint hitPoint(_x, _y);
146  return RenderBlock::nodeAtPoint(request, result, (int)localX, (int)localY, _tx, _ty, hitTestAction);
147  }
148  }
149 
150  return false;
151 }*/
152 
153 void RenderSVGText::absoluteRects(Vector<IntRect> &rects, int, int, bool)
154 {
155  RenderSVGRoot *root = findSVGRootObject(parent());
156  if (!root) {
157  return;
158  }
159 
160  int x, y;
161  absolutePosition(x, y);
162 
163  AffineTransform htmlParentCtm = root->RenderContainer::absoluteTransform();
164 
165  // Don't use relativeBBox here, as it's unites the selection rects. Makes it hard
166  // to spot errors, if there are any using WebInspector. Individually feed them into 'rects'.
167  for (InlineRunBox *runBox = firstLineBox(); runBox; runBox = runBox->nextLineBox()) {
168  ASSERT(runBox->isInlineFlowBox());
169 
170  InlineFlowBox *flowBox = static_cast<InlineFlowBox *>(runBox);
171  for (InlineBox *box = flowBox->firstChild(); box; box = box->nextOnLine()) {
172  FloatRect boxRect(box->xPos(), box->yPos(), box->width(), box->height());
173  boxRect.move(narrowPrecisionToFloat(x - htmlParentCtm.e()), narrowPrecisionToFloat(y - htmlParentCtm.f()));
174  rects.append(enclosingIntRect(absoluteTransform().mapRect(boxRect)));
175  }
176  }
177 }
178 
179 void RenderSVGText::paint(PaintInfo &paintInfo, int, int)
180 {
181  RenderObject::PaintInfo pi(paintInfo);
182  //FIXME khtml pi.rect = absoluteTransform().inverse().mapRect(pi.rect);
183  RenderBlock::paint(pi, 0, 0);
184 }
185 
186 FloatRect RenderSVGText::relativeBBox(bool includeStroke) const
187 {
188  FloatRect repaintRect;
189 
190  for (InlineRunBox *runBox = firstLineBox(); runBox; runBox = runBox->nextLineBox()) {
191  ASSERT(runBox->isInlineFlowBox());
192 
193  InlineFlowBox *flowBox = static_cast<InlineFlowBox *>(runBox);
194  for (InlineBox *box = flowBox->firstChild(); box; box = box->nextOnLine()) {
195  repaintRect.unite(FloatRect(box->xPos(), box->yPos(), box->width(), box->height()));
196  }
197  }
198 
199  // SVG needs to include the strokeWidth(), not the textStrokeWidth().
200  if (includeStroke && style()->svgStyle()->hasStroke()) {
201  float strokeWidth = SVGRenderStyle::cssPrimitiveToLength(this, style()->svgStyle()->strokeWidth(), 0.0f);
202 
203 #if ENABLE(SVG_FONTS)
204  /*FIXME khtml const Font& font = style()->font();
205  if (font.primaryFont()->isSVGFont()) {
206  float scale = font.unitsPerEm() > 0 ? font.size() / font.unitsPerEm() : 0.0f;
207 
208  if (scale != 0.0f)
209  strokeWidth /= scale;
210  }*/
211 #endif
212 
213  repaintRect.inflate(strokeWidth);
214  }
215 
216  repaintRect.move(xPos(), yPos());
217  return repaintRect;
218 }
219 
220 }
221 
222 #endif // ENABLE(SVG)
223 
QFuture< void > filter(Sequence &sequence, KeepFunctor filterFunction)
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Sat Oct 16 2021 22:48:01 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.