KHtml

RenderSVGRoot.cpp
1 /*
2  Copyright (C) 2004, 2005, 2007 Nikolas Zimmermann <[email protected]>
3  2004, 2005, 2007 Rob Buis <[email protected]>
4  2007 Eric Seidel <[email protected]>
5 
6  This file is part of the KDE project
7 
8  This library is free software; you can redistribute it and/or
9  modify it under the terms of the GNU Library General Public
10  License as published by the Free Software Foundation; either
11  version 2 of the License, or (at your option) any later version.
12 
13  This library is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  Library General Public License for more details.
17 
18  You should have received a copy of the GNU Library General Public License
19  aint with this library; see the file COPYING.LIB. If not, write to
20  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21  Boston, MA 02110-1301, USA.
22 */
23 
24 #include "wtf/Platform.h"
25 #include "Document.h"
26 
27 #if ENABLE(SVG)
28 #include "RenderSVGRoot.h"
29 
30 /*#include "GraphicsContext.h"
31 #include "RenderPath.h"
32 #include "RenderSVGContainer.h"
33 #include "RenderView.h"*/
34 #include "SVGLength.h"
35 /*#include "SVGRenderSupport.h"
36 #include "SVGResourceClipper.h"
37 #include "SVGResourceFilter.h"
38 #include "SVGResourceMasker.h"*/
39 #include "SVGSVGElement.h"
40 #include "SVGStyledElement.h"
41 /*#include "SVGURIReference.h"*/
42 
43 namespace WebCore
44 {
45 
46 RenderSVGRoot::RenderSVGRoot(SVGStyledElement *node)
47  : RenderBox(node) /*RenderContainer(node)*/
48 {
49  setReplaced(true);
50 }
51 
52 RenderSVGRoot::~RenderSVGRoot()
53 {
54 }
55 
56 short RenderSVGRoot::lineHeight(bool b) const
57 {
58  Q_UNUSED(b);
59  return height() + marginTop() + marginBottom();
60 }
61 
62 short RenderSVGRoot::baselinePosition(bool b) const
63 {
64  Q_UNUSED(b);
65  return height() + marginTop() + marginBottom();
66 }
67 
68 void RenderSVGRoot::calcMinMaxWidth()
69 {
70 // KHTMLAssert( !minMaxKnown() );
71 
72  int width = calcReplacedWidth() + paddingLeft() + paddingRight() + borderLeft() + borderRight();
73  if (style()->width().isPercent() || (style()->width().isAuto() && style()->height().isPercent())) {
74  m_minWidth = 0;
75  m_maxWidth = width;
76  } else {
77  m_minWidth = m_maxWidth = width;
78  }
79 
80  setMinMaxKnown();
81 }
82 
83 void RenderSVGRoot::layout()
84 {
85  ASSERT(needsLayout());
86 
87  calcViewport();
88 
89  // Arbitrary affine transforms are incompatible with LayoutState.
90  //FIXME vtokarev: view()->disableLayoutState();
91  //canvas()->disableLayoutState();
92 
93  /*IntRect oldBounds = m_absoluteBounds;
94  IntRect oldOutlineBox;
95  bool checkForRepaint = checkForRepaintDuringLayout() && selfNeedsLayout();
96  if (checkForRepaint)
97  oldOutlineBox = absoluteOutlineBox();*/
98 
99  calcWidth();
100  calcHeight();
101 
102  //m_absoluteBounds = absoluteClippedOverflowRect();
103  SVGSVGElement *svg = static_cast<SVGSVGElement *>(element());
104  m_width = static_cast<int>(m_width * svg->currentScale());
105  m_height = static_cast<int>(m_height * svg->currentScale());
106 
107  for (RenderObject *child = firstChild(); child; child = child->nextSibling()) {
108  // ### TODO: we only want to relayout if our size/transform changed kids
109  if (child->isText()) {
110  continue;
111  }
112  child->setNeedsLayout(true);
113  child->layoutIfNeeded();
114  // ASSERT(!child->needsLayout());
115  }
116 
117  /*if (checkForRepaint)
118  repaintAfterLayoutIfNeeded(oldBounds, oldOutlineBox);*/
119 
120  //FIXME vtokarev view()->enableLayoutState();
121  //canvas()->enableLayoutState();
122  setNeedsLayout(false);
123 }
124 
125 /*void RenderSVGRoot::applyContentTransforms(PaintInfo& paintInfo, int parentX, int parentY)
126 {
127  // Translate from parent offsets (html renderers) to a relative transform (svg renderers)
128  IntPoint origin;
129  origin.move(parentX, parentY);
130  origin.move(m_x, m_y);
131  origin.move(borderLeft(), borderTop());
132  origin.move(paddingLeft(), paddingTop());
133 
134  if (origin.x() || origin.y()) {
135  paintInfo.context->concatCTM(AffineTransform().translate(origin.x(), origin.y()));
136  paintInfo.rect.move(-origin.x(), -origin.y());
137  }
138 
139  // Respect scroll offset caused by html parents
140  AffineTransform ctm = RenderContainer::absoluteTransform();
141  paintInfo.rect.move(static_cast<int>(ctm.e()), static_cast<int>(ctm.f()));
142 
143  SVGSVGElement* svg = static_cast<SVGSVGElement*>(element());
144  paintInfo.context->concatCTM(AffineTransform().scale(svg->currentScale()));
145 
146  if (!viewport().isEmpty()) {
147  if (style()->overflowX() != OVISIBLE)
148  paintInfo.context->clip(enclosingIntRect(viewport())); // FIXME: Eventually we'll want float-precision clipping
149 
150  paintInfo.context->concatCTM(AffineTransform().translate(viewport().x(), viewport().y()));
151  }
152 
153  paintInfo.context->concatCTM(AffineTransform().translate(svg->currentTranslate().x(), svg->currentTranslate().y()));
154 }*/
155 
156 void RenderSVGRoot::paint(PaintInfo &paintInfo, int parentX, int parentY)
157 {
158  calcViewport();
159 
160  //SVGSVGElement* svg = static_cast<SVGSVGElement*>(element());
161  if (viewport().width() <= 0. || viewport().height() <= 0.) {
162  return;
163  }
164 
165  if (shouldPaintBackgroundOrBorder()) {
166  paintBoxDecorations(paintInfo, m_x + parentX, m_y + parentY);
167  }
168 
169  RenderObject::PaintInfo childPaintInfo(paintInfo);
170  childPaintInfo.p->save();
171  childPaintInfo.p->setRenderHint(QPainter::Antialiasing);
172  childPaintInfo.p->setRenderHint(QPainter::SmoothPixmapTransform);
173 
174  RenderBox::paint(childPaintInfo, 0, 0);
175 
176  childPaintInfo.p->restore();
177 
178 #if 0
179  // qCDebug(KHTML_LOG) << "in paint()";
180  /*if (!paintInfo.context) {
181  GraphicsContext context(paintInfo.p);
182  paintInfo.context = &context;
183  // qCDebug(KHTML_LOG) << "context:" << &context;
184  }*/
185  if (paintInfo.context->paintingDisabled()) {
186  return;
187  }
188 
189  calcViewport();
190 
191  SVGSVGElement *svg = static_cast<SVGSVGElement *>(element());
192  // A value of zero disables rendering of the element.
193  // qCDebug(KHTML_LOG) << "viewport:" << viewport().width() << viewport().height();
194  if (viewport().width() <= 0. || viewport().height() <= 0.) {
195  return;
196  }
197  // qCDebug(KHTML_LOG) << "painting:" << parentX << parentY << viewport().width() << viewport().height();
198 
199  // This should only exist for <svg> renderers
200  /*if (hasBoxDecorations() && (paintInfo.phase == PaintPhaseForeground || paintInfo.phase == PaintPhaseSelection))*/
201  paintBoxDecorations(paintInfo, m_x + parentX, m_y + parentY);
202 
203  /*if (!firstChild()) {
204  #if ENABLE(SVG_FILTERS)
205  // Spec: groups w/o children still may render filter content.
206  const SVGRenderStyle* svgStyle = style()->svgStyle();
207  AtomicString filterId(SVGURIReference::getTarget(svgStyle->filter()));
208  SVGResourceFilter* filter = getFilterById(document(), filterId);
209  if (!filter)
210  #endif
211  return;
212  }*/
213  paintInfo.p->fillRect(parentX, parentY, viewport().width(), viewport().height(), QBrush(Qt::green));
214 
215  RenderObject::PaintInfo childPaintInfo(paintInfo);
216  childPaintInfo.context->save();
217  // qCDebug(KHTML_LOG) << "context= " << childPaintInfo.context << "parent=" << paintInfo.context;
218 
219  /*applyContentTransforms(childPaintInfo, parentX, parentY);
220 
221  SVGResourceFilter* filter = 0;
222 
223  FloatRect boundingBox = relativeBBox(true);
224  if (childPaintInfo.phase == PaintPhaseForeground)
225  prepareToRenderSVGContent(this, childPaintInfo, boundingBox, filter);*/
226 
227  //childPaintInfo.context->concatCTM(svg->viewBoxToViewTransform(width(), height()));
228  /*RenderContainer*/RenderBox::paint(childPaintInfo, 0, 0);
229 
230  /*if (childPaintInfo.phase == PaintPhaseForeground)
231  finishRenderSVGContent(this, childPaintInfo, boundingBox, filter, paintInfo.context);*/
232 
233  childPaintInfo.context->restore();
234 
235  /*if ((childPaintInfo.phase == PaintPhaseOutline || childPaintInfo.phase == PaintPhaseSelfOutline) && style()->outlineWidth() && style()->visibility() == VISIBLE)
236  paintOutline(childPaintInfo.context, m_absoluteBounds.x(), m_absoluteBounds.y(), m_absoluteBounds.width(), m_absoluteBounds.height(), style());*/
237 #endif
238 }
239 
240 FloatRect RenderSVGRoot::viewport() const
241 {
242  return m_viewport;
243 }
244 
245 void RenderSVGRoot::calcViewport()
246 {
247  SVGElement *svgelem = static_cast<SVGElement *>(element());
248  if (svgelem->hasTagName(SVGNames::svgTag)) {
249  SVGSVGElement *svg = static_cast<SVGSVGElement *>(element());
250 
251  if (!selfNeedsLayout() && !svg->hasRelativeValues()) {
252  return;
253  }
254 
255  float w, h;
256  SVGLength width = svg->width();
257  if (width.unitType() == LengthTypePercentage && svg->hasSetContainerSize()) {
258  w = svg->relativeWidthValue();
259  } else {
260  w = width.value();
261  }
262 
263  SVGLength height = svg->height();
264  if (height.unitType() == LengthTypePercentage && svg->hasSetContainerSize()) {
265  h = svg->relativeHeightValue();
266  } else {
267  h = height.value();
268  }
269  m_viewport = FloatRect(0, 0, w, h);
270  }
271 }
272 
273 IntRect RenderSVGRoot::absoluteClippedOverflowRect()
274 {
275  /*IntRect repaintRect;
276 
277  for (RenderObject* current = firstChild(); current != 0; current = current->nextSibling())
278  repaintRect.unite(current->absoluteClippedOverflowRect());
279 
280  #if ENABLE(SVG_FILTERS)
281  // Filters can expand the bounding box
282  SVGResourceFilter* filter = getFilterById(document(), SVGURIReference::getTarget(style()->svgStyle()->filter()));
283  if (filter)
284  repaintRect.unite(enclosingIntRect(filter->filterBBoxForItemBBox(repaintRect)));
285  #endif
286 
287  return repaintRect;*/
288  ASSERT(false);
289  return IntRect();
290 }
291 
292 /*void RenderSVGRoot::addFocusRingRects(GraphicsContext* graphicsContext, int, int)
293 {
294  graphicsContext->addFocusRingRect(m_absoluteBounds);
295 }*/
296 
297 void RenderSVGRoot::absoluteRects(Vector<IntRect> &rects, int, int)
298 {
299  Q_UNUSED(rects);
300  /*for (RenderObject* current = firstChild(); current != 0; current = current->nextSibling())
301  current->absoluteRects(rects, 0, 0);*/
302 }
303 
304 AffineTransform RenderSVGRoot::absoluteTransform() const
305 {
306  AffineTransform ctm = RenderContainer::absoluteTransform();
307  ctm.translate(m_x, m_y);
308  SVGSVGElement *svg = static_cast<SVGSVGElement *>(element());
309  ctm.scale(svg->currentScale());
310  ctm.translate(svg->currentTranslate().x(), svg->currentTranslate().y());
311  ctm.translate(viewport().x(), viewport().y());
312  return svg->viewBoxToViewTransform(width(), height()) * ctm;
313 }
314 
315 FloatRect RenderSVGRoot::relativeBBox(bool includeStroke) const
316 {
317  Q_UNUSED(includeStroke);
318  FloatRect rect;
319 
320  //RenderObject* current = firstChild();
321  /*for (; current != 0; current = current->nextSibling()) {
322  FloatRect childBBox = current->relativeBBox(includeStroke);
323  FloatRect mappedBBox = current->localTransform().mapRect(childBBox);
324  // <svg> can have a viewBox contributing to the bbox
325  if (current->isSVGContainer())
326  mappedBBox = static_cast<RenderSVGContainer*>(current)->viewportTransform().mapRect(mappedBBox);
327  rect.unite(mappedBBox);
328  }*/
329 
330  return rect;
331 }
332 
333 AffineTransform RenderSVGRoot::localTransform() const
334 {
335  return AffineTransform();
336 }
337 
338 /*bool RenderSVGRoot::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction)
339 {
340  AffineTransform ctm = RenderContainer::absoluteTransform();
341 
342  int sx = (_tx - static_cast<int>(ctm.e())); // scroll offset
343  int sy = (_ty - static_cast<int>(ctm.f())); // scroll offset
344 
345  if (!viewport().isEmpty()
346  && style()->overflowX() == OHIDDEN
347  && style()->overflowY() == OHIDDEN) {
348  int tx = m_x - _tx + sx;
349  int ty = m_y - _ty + sy;
350 
351  // Check if we need to do anything at all.
352  IntRect overflowBox = overflowRect(false);
353  overflowBox.move(tx, ty);
354  ctm.translate(viewport().x(), viewport().y());
355  double localX, localY;
356  ctm.inverse().map(_x - _tx, _y - _ty, &localX, &localY);
357  if (!overflowBox.contains((int)localX, (int)localY))
358  return false;
359  }
360 
361  for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
362  if (child->nodeAtPoint(request, result, _x - sx, _y - sy, 0, 0, hitTestAction)) {
363  updateHitTestResult(result, IntPoint(_x - _tx, _y - _ty));
364  return true;
365  }
366  }
367 
368  // Spec: Only graphical elements can be targeted by the mouse, period.
369  // 16.4: "If there are no graphics elements whose relevant graphics content is under the pointer (i.e., there is no target element), the event is not dispatched."
370  return false;
371 }*/
372 
373 }
374 
375 #endif // ENABLE(SVG)
376 
MESSAGECORE_EXPORT KMime::Content * firstChild(const KMime::Content *node)
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Mon Oct 25 2021 22:48:22 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.