KHtml

RenderSVGContainer.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 
26 #if ENABLE(SVG)
27 #include "RenderSVGContainer.h"
28 
29 /*#include "AXObjectCache.h"
30 #include "GraphicsContext.h"*/
31 #include "RenderView.h"
32 #include "SVGRenderSupport.h"
33 #include "SVGResourceFilter.h"
34 #include "SVGStyledElement.h"
35 #include "SVGURIReference.h"
36 
37 namespace WebCore
38 {
39 
40 RenderSVGContainer::RenderSVGContainer(SVGStyledElement *node)
41  : RenderObject(node)
42  , m_firstChild(nullptr)
43  , m_lastChild(nullptr)
44  , m_width(0)
45  , m_height(0)
46  , m_drawsContents(true)
47 {
48  setReplaced(true);
49 }
50 
51 RenderSVGContainer::~RenderSVGContainer()
52 {
53 }
54 
55 bool RenderSVGContainer::canHaveChildren() const
56 {
57  return true;
58 }
59 
60 void RenderSVGContainer::addChild(RenderObject *newChild, RenderObject *beforeChild)
61 {
62  insertChildNode(newChild, beforeChild);
63 }
64 
65 void RenderSVGContainer::removeChild(RenderObject *oldChild)
66 {
67  // We do this here instead of in removeChildNode, since the only extremely low-level uses of remove/appendChildNode
68  // cannot affect the positioned object list, and the floating object list is irrelevant (since the list gets cleared on
69  // layout anyway).
70  oldChild->removeFromObjectLists();
71 
72  removeChildNode(oldChild);
73 }
74 
75 void RenderSVGContainer::destroy()
76 {
77  /*destroyLeftoverChildren();
78  RenderObject::destroy();*/
79 }
80 
81 void RenderSVGContainer::destroyLeftoverChildren()
82 {
83  /*while (m_firstChild) {
84  // Destroy any anonymous children remaining in the render tree, as well as implicit (shadow) DOM elements like those used in the engine-based text fields.
85  if (m_firstChild->element())
86  m_firstChild->element()->setRenderer(0);
87 
88  m_firstChild->destroy();
89  }*/
90 }
91 
92 RenderObject *RenderSVGContainer::removeChildNode(RenderObject *oldChild)
93 {
94  ASSERT(oldChild->parent() == this);
95  bool inCleanup = documentBeingDestroyed();
96 
97  // So that we'll get the appropriate dirty bit set (either that a normal flow child got yanked or
98  // that a positioned child got yanked). We also repaint, so that the area exposed when the child
99  // disappears gets repainted properly.
100 
101  if (!inCleanup) {
102  oldChild->setNeedsLayoutAndMinMaxRecalc(); // Dirty the containing block chain
103  oldChild->setNeedsLayout(false); // The child itself does not need to layout - it's going away.
104  oldChild->repaint();
105  }
106 
107  // detach the place holder box
108  if (oldChild->isBox()) {
109  RenderBox *rb = static_cast<RenderBox *>(oldChild);
110  InlineBox *ph = rb->placeHolderBox();
111  if (ph) {
112  ph->detach(rb->renderArena(), inCleanup /*NoRemove*/);
113  rb->setPlaceHolderBox(nullptr);
114  }
115  }
116 
117  if (!inCleanup) {
118  // If oldChild is the start or end of the selection, then clear the selection to
119  // avoid problems of invalid pointers.
120  // FIXME: The SelectionController should be responsible for this when it
121  // is notified of DOM mutations.
122  /* FIXME if (oldChild->isSelectionBorder())
123  view()->clearSelection();*/
124  if (oldChild->isSelectionBorder()) {
125  canvas()->clearSelection();
126  }
127  }
128 
129  // remove the child
130  if (oldChild->previousSibling()) {
131  oldChild->previousSibling()->setNextSibling(oldChild->nextSibling());
132  }
133  if (oldChild->nextSibling()) {
134  oldChild->nextSibling()->setPreviousSibling(oldChild->previousSibling());
135  }
136 
137  if (m_firstChild == oldChild) {
138  m_firstChild = oldChild->nextSibling();
139  }
140  if (m_lastChild == oldChild) {
141  m_lastChild = oldChild->previousSibling();
142  }
143 
144  oldChild->setPreviousSibling(nullptr);
145  oldChild->setNextSibling(nullptr);
146  oldChild->setParent(nullptr);
147 
148  /*if (AXObjectCache::accessibilityEnabled())
149  document()->axObjectCache()->childrenChanged(this);*/
150 
151  return oldChild;
152 }
153 
154 void RenderSVGContainer::appendChildNode(RenderObject *newChild)
155 {
156  ASSERT(!newChild->parent());
157  /*khtml vtokarevASSERT(newChild->element()->isSVGElement());*/
158  // remove it when I have SVG render text; SVGInlineText
159 
160  newChild->setParent(this);
161  RenderObject *lChild = m_lastChild;
162 
163  if (lChild) {
164  newChild->setPreviousSibling(lChild);
165  lChild->setNextSibling(newChild);
166  } else {
167  m_firstChild = newChild;
168  }
169 
170  m_lastChild = newChild;
171 
172  newChild->setNeedsLayoutAndMinMaxRecalc(); // Goes up the containing block hierarchy.*/
173  if (!normalChildNeedsLayout()) {
174  setChildNeedsLayout(true); // We may supply the static position for an absolute positioned child.
175  }
176 
177  /*if (AXObjectCache::accessibilityEnabled())
178  document()->axObjectCache()->childrenChanged(this);*/
179 }
180 
181 void RenderSVGContainer::insertChildNode(RenderObject *child, RenderObject *beforeChild)
182 {
183  if (!beforeChild) {
184  appendChildNode(child);
185  return;
186  }
187 
188  ASSERT(!child->parent());
189  ASSERT(beforeChild->parent() == this);
190  ASSERT(child->element()->isSVGElement());
191 
192  if (beforeChild == m_firstChild) {
193  m_firstChild = child;
194  }
195 
196  RenderObject *prev = beforeChild->previousSibling();
197  child->setNextSibling(beforeChild);
198  beforeChild->setPreviousSibling(child);
199  if (prev) {
200  prev->setNextSibling(child);
201  }
202  child->setPreviousSibling(prev);
203 
204  child->setParent(this);
205 
206  child->setNeedsLayoutAndMinMaxRecalc();
207  if (!normalChildNeedsLayout()) {
208  setChildNeedsLayout(true); // We may supply the static position for an absolute positioned child.
209  }
210 
211  /*if (AXObjectCache::accessibilityEnabled())
212  document()->axObjectCache()->childrenChanged(this);*/
213 }
214 
215 bool RenderSVGContainer::drawsContents() const
216 {
217  return m_drawsContents;
218 }
219 
220 void RenderSVGContainer::setDrawsContents(bool drawsContents)
221 {
222  m_drawsContents = drawsContents;
223 }
224 
225 AffineTransform RenderSVGContainer::localTransform() const
226 {
227  return m_localTransform;
228 }
229 
230 bool RenderSVGContainer::requiresLayer() const
231 {
232  // Only allow an <svg> element to generate a layer when it's positioned in a non-SVG context
233  return false;
234 }
235 
236 short RenderSVGContainer::lineHeight(bool b) const
237 {
238  Q_UNUSED(b);
239  return height() + marginTop() + marginBottom();
240 }
241 
242 short RenderSVGContainer::baselinePosition(bool b) const
243 {
244  Q_UNUSED(b);
245  return height() + marginTop() + marginBottom();
246 }
247 
248 bool RenderSVGContainer::calculateLocalTransform()
249 {
250  // subclasses can override this to add transform support
251  return false;
252 }
253 
254 void RenderSVGContainer::layout()
255 {
256  ASSERT(needsLayout());
257 
258  // Arbitrary affine transforms are incompatible with LayoutState.
259  /*canvas()->disableLayoutState();*/
260 
261  /*IntRect oldBounds;
262  IntRect oldOutlineBox;
263  bool checkForRepaint = checkForRepaintDuringLayout() && selfWillPaint();
264  if (checkForRepaint) {
265  oldBounds = m_absoluteBounds;
266  oldOutlineBox = absoluteOutlineBox();
267  }*/
268 
269  calculateLocalTransform();
270 
271  for (RenderObject *child = firstChild(); child; child = child->nextSibling()) {
272  // ### TODO: we only want to relayout if our size/transform changed kids
273  if (child->isText()) {
274  continue;
275  }
276  child->setNeedsLayout(true);
277  child->layoutIfNeeded();
278  ASSERT(!child->needsLayout());
279  }
280 
281  calcBounds();
282 
283  /*if (checkForRepaint)
284  repaintAfterLayoutIfNeeded(oldBounds, oldOutlineBox);*/
285 
286  /*canvas()->enableLayoutState();*/
287  setNeedsLayout(false);
288 }
289 
290 int RenderSVGContainer::calcReplacedWidth() const
291 {
292  switch (style()->width().type()) {
293  case Fixed:
294  return qMax(0, style()->width().value());
295  case Percent: {
296  const int cw = containingBlockWidth();
297  return cw > 0 ? qMax(0, style()->width().minWidth(cw)) : 0;
298  }
299  default:
300  return 0;
301  }
302 }
303 
304 int RenderSVGContainer::calcReplacedHeight() const
305 {
306  switch (style()->height().type()) {
307  case Fixed:
308  return qMax(0, style()->height().value());
309  case Percent: {
310  RenderBlock *cb = containingBlock();
311  return style()->height().width(cb->availableHeight());
312  }
313  default:
314  return 0;
315  }
316 }
317 
318 void RenderSVGContainer::applyContentTransforms(PaintInfo &paintInfo)
319 {
320  if (!localTransform().isIdentity()) {
321  paintInfo.p->setWorldMatrix(localTransform(), true);
322  }
323  /*paintInfo.context->concatCTM(localTransform());*/
324 }
325 
326 void RenderSVGContainer::applyAdditionalTransforms(PaintInfo &paintInfo)
327 {
328  Q_UNUSED(paintInfo);
329  // no-op
330 }
331 
332 void RenderSVGContainer::calcBounds()
333 {
334  m_width = calcReplacedWidth();
335  m_height = calcReplacedHeight();
336  //m_absoluteBounds = absoluteClippedOverflowRect();
337 }
338 
339 bool RenderSVGContainer::selfWillPaint() const
340 {
341 #if ENABLE(SVG_FILTERS)
342  const SVGRenderStyle *svgStyle = style()->svgStyle();
343  AtomicString filterId(SVGURIReference::getTarget(svgStyle->filter()));
344  SVGResourceFilter *filter = getFilterById(document(), filterId);
345  if (filter) {
346  return true;
347  }
348 #endif
349  return false;
350 }
351 
352 void RenderSVGContainer::paint(PaintInfo &paintInfo, int parentX, int parentY)
353 {
354  Q_UNUSED(parentX);
355  Q_UNUSED(parentY);
356  if (/*paintInfo.context->paintingDisabled() || */!drawsContents()) {
357  return;
358  }
359 
360  // Spec: groups w/o children still may render filter content.
361  /*if (!firstChild() && !selfWillPaint())
362  return;*/
363 
364  paintInfo.p->save();
365  applyContentTransforms(paintInfo);
366 
367  SVGResourceFilter *filter = nullptr;
368  /*PaintInfo savedInfo(paintInfo);*/
369 
370  FloatRect boundingBox = relativeBBox(true);
371  /*if (paintInfo.phase == PaintPhaseForeground)*/
372  prepareToRenderSVGContent(this, paintInfo, boundingBox, filter);
373 
374  applyAdditionalTransforms(paintInfo);
375 
376  // default implementation. Just pass paint through to the children
377  PaintInfo childInfo(paintInfo);
378  /*childInfo.paintingRoot = paintingRootForChildren(paintInfo);*/
379  for (RenderObject *child = firstChild(); child; child = child->nextSibling()) {
380  child->paint(childInfo, 0, 0);
381  }
382 
383  /*if (paintInfo.phase == PaintPhaseForeground)
384  finishRenderSVGContent(this, paintInfo, boundingBox, filter, savedInfo.context);*/
385 
386  paintInfo.p->restore();
387 
388  /*if ((paintInfo.phase == PaintPhaseOutline || paintInfo.phase == PaintPhaseSelfOutline) && style()->outlineWidth() && style()->visibility() == VISIBLE)
389  paintOutline(paintInfo.context, m_absoluteBounds.x(), m_absoluteBounds.y(), m_absoluteBounds.width(), m_absoluteBounds.height(), style());*/
390 }
391 
392 AffineTransform RenderSVGContainer::viewportTransform() const
393 {
394  return AffineTransform();
395 }
396 
397 IntRect RenderSVGContainer::absoluteClippedOverflowRect()
398 {
399  /*FloatRect repaintRect;
400 
401  for (RenderObject* current = firstChild(); current != 0; current = current->nextSibling())
402  repaintRect.unite(current->absoluteClippedOverflowRect());
403 
404  #if ENABLE(SVG_FILTERS)
405  // Filters can expand the bounding box
406  SVGResourceFilter* filter = getFilterById(document(), SVGURIReference::getTarget(style()->svgStyle()->filter()));
407  if (filter)
408  repaintRect.unite(filter->filterBBoxForItemBBox(repaintRect));
409  #endif
410 
411  if (!repaintRect.isEmpty())
412  repaintRect.inflate(1); // inflate 1 pixel for antialiasing
413 
414  return enclosingIntRect(repaintRect);*/
415  ASSERT(false);
416  return IntRect();
417 }
418 
419 void RenderSVGContainer::absoluteRects(Vector<IntRect> &rects, int, int, bool)
420 {
421  Q_UNUSED(rects);
422  //FIXME rects.append(absoluteClippedOverflowRect());
423 }
424 
425 FloatRect RenderSVGContainer::relativeBBox(bool includeStroke) const
426 {
427  FloatRect rect;
428 
429  RenderObject *current = firstChild();
430  for (; current != nullptr; current = current->nextSibling()) {
431  FloatRect childBBox = current->relativeBBox(includeStroke);
432  FloatRect mappedBBox = current->localTransform().mapRect(childBBox);
433 
434  // <svg> can have a viewBox contributing to the bbox
435  if (current->isSVGContainer()) {
436  mappedBBox = static_cast<RenderSVGContainer *>(current)->viewportTransform().mapRect(mappedBBox);
437  }
438 
439  rect.unite(mappedBBox);
440  }
441 
442  return rect;
443 }
444 
445 /*bool RenderSVGContainer::nodeAtPoint(const HitTestRequest& request, HitTestResult& result, int _x, int _y, int _tx, int _ty, HitTestAction hitTestAction)
446 {
447  for (RenderObject* child = lastChild(); child; child = child->previousSibling()) {
448  if (child->nodeAtPoint(request, result, _x, _y, _tx, _ty, hitTestAction)) {
449  updateHitTestResult(result, IntPoint(_x - _tx, _y - _ty));
450  return true;
451  }
452  }
453 
454  // Spec: Only graphical elements can be targeted by the mouse, period.
455  // 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."
456  return false;
457 }*/
458 
459 }
460 
461 #endif // ENABLE(SVG)
462 
Type type(const QSqlDatabase &db)
MESSAGECORE_EXPORT KMime::Content * firstChild(const KMime::Content *node)
QFuture< void > filter(Sequence &sequence, KeepFunctor filterFunction)
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Tue Oct 26 2021 22:48:09 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.