KHtml

SVGSVGElement.cpp
1 /*
2  Copyright (C) 2004, 2005, 2006 Nikolas Zimmermann <[email protected]>
3  2004, 2005, 2006, 2007 Rob Buis <[email protected]>
4  2007 Apple Inc. All rights reserved.
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  along 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 "SVGSVGElement.h"
28 
29 #include "AffineTransform.h"
30 /*#include "CSSHelper.h"*/
31 #include "css/csshelper.h"
32 /*#include "CSSPropertyNames.h"*/
33 #include "Document.h"
34 //#include "EventListener.h"
35 #include "dom/dom2_events.h"
36 /*#include "EventNames.h"*/
37 #include "FloatConversion.h"
38 /*#include "Frame.h"
39 #include "HTMLNames.h"
40 #include "RenderSVGViewportContainer.h"*/
41 #include "RenderSVGRoot.h"
42 #include "SVGAngle.h"
43 #include "SVGLength.h"
44 #include "SVGNames.h"
45 #include "SVGPreserveAspectRatio.h"
46 #include "SVGTransform.h"
47 #include "SVGTransformList.h"
48 /*#include "SVGViewElement.h"*/
49 #include "SVGViewSpec.h"
50 /*#include "SVGZoomEvent.h"
51 #include "SelectionController.h"
52 #include "SMILTimeContainer.h"*/
53 #include "khtml_part.h"
54 
55 namespace WebCore
56 {
57 
58 /*using namespace HTMLNames;
59 using namespace EventNames;*/
60 using namespace SVGNames;
61 
62 SVGSVGElement::SVGSVGElement(const QualifiedName &tagName, Document *doc)
63  : SVGStyledLocatableElement(tagName, doc)
64  , SVGTests()
65  , SVGLangSpace()
66  , SVGExternalResourcesRequired()
67  , SVGFitToViewBox()
68  , SVGZoomAndPan()
69  , m_x(this, LengthModeWidth)
70  , m_y(this, LengthModeHeight)
71  , m_width(this, LengthModeWidth)
72  , m_height(this, LengthModeHeight)
73  , m_useCurrentView(false)
74 /*, m_timeContainer(SMILTimeContainer::create(this))
75 , m_viewSpec(0)*/
76 {
77  setWidthBaseValue(SVGLength(this, LengthModeWidth, "100%"));
78  setHeightBaseValue(SVGLength(this, LengthModeHeight, "100%"));
79  //doc->registerForCacheCallbacks(this);
80 }
81 
82 SVGSVGElement::~SVGSVGElement()
83 {
84  /*document()->unregisterForCacheCallbacks(this);
85  // There are cases where removedFromDocument() is not called.
86  // see ContainerNode::removeAllChildren, called by it's destructor.
87  document()->accessSVGExtensions()->removeTimeContainer(this);*/
88 }
89 
90 ANIMATED_PROPERTY_DEFINITIONS(SVGSVGElement, SVGLength, Length, length, X, x, SVGNames::xAttr, m_x)
91 ANIMATED_PROPERTY_DEFINITIONS(SVGSVGElement, SVGLength, Length, length, Y, y, SVGNames::yAttr, m_y)
92 ANIMATED_PROPERTY_DEFINITIONS(SVGSVGElement, SVGLength, Length, length, Width, width, SVGNames::widthAttr, m_width)
93 ANIMATED_PROPERTY_DEFINITIONS(SVGSVGElement, SVGLength, Length, length, Height, height, SVGNames::heightAttr, m_height)
94 
95 DOMString SVGSVGElement::contentScriptType() const
96 {
97  static const DOMString defaultValue("text/ecmascript");
98  DOMString n = getAttribute(contentScriptTypeAttr);
99  return n.isNull() ? defaultValue : n;
100 }
101 
102 void SVGSVGElement::setContentScriptType(const DOMString &type)
103 {
104  setAttribute(SVGNames::contentScriptTypeAttr, type);
105 }
106 
107 DOMString SVGSVGElement::contentStyleType() const
108 {
109  static const DOMString defaultValue("text/css");
110  const DOMString n = getAttribute(contentStyleTypeAttr);
111  return n.isNull() ? defaultValue : n;
112 }
113 
114 void SVGSVGElement::setContentStyleType(const DOMString &type)
115 {
116  setAttribute(SVGNames::contentStyleTypeAttr, type);
117 }
118 
119 bool SVGSVGElement::hasSetContainerSize() const
120 {
121  // For now, we interpret % dimensions only if we're a top-level SVG element nested inside
122  // an another part. ### might even want to check if we're the documentElement; this
123  // will also need changes with <img> handling
124  return isOutermostSVG() && document()->part()->parentPart();
125 }
126 
127 IntSize SVGSVGElement::containerSize() const
128 {
129  if (KHTMLView *v = document()->view()) {
130  return IntSize(v->visibleWidth(), v->visibleHeight());
131  } else {
132  return IntSize(300, 150);
133  }
134 }
135 
136 FloatRect SVGSVGElement::viewport() const
137 {
138  double _x = 0.0;
139  double _y = 0.0;
140  if (!isOutermostSVG()) {
141  _x = x().value();
142  _y = y().value();
143  }
144  float w = width().value();
145  float h = height().value();
146  AffineTransform viewBox = viewBoxToViewTransform(w, h);
147  double wDouble = w;
148  double hDouble = h;
149  viewBox.map(_x, _y, &_x, &_y);
150  viewBox.map(w, h, &wDouble, &hDouble);
151  return FloatRect::narrowPrecision(_x, _y, wDouble, hDouble);
152 }
153 
154 int SVGSVGElement::relativeWidthValue() const
155 {
156  SVGLength w = width();
157  if (w.unitType() != LengthTypePercentage) {
158  return 0;
159  }
160 
161  return static_cast<int>(w.valueAsPercentage() * containerSize().width());
162 }
163 
164 int SVGSVGElement::relativeHeightValue() const
165 {
166  SVGLength h = height();
167  if (h.unitType() != LengthTypePercentage) {
168  return 0;
169  }
170 
171  return static_cast<int>(h.valueAsPercentage() * containerSize().height());
172 }
173 
174 float SVGSVGElement::pixelUnitToMillimeterX() const
175 {
176  // 2.54 / cssPixelsPerInch gives CM.
177  return (2.54f / cssPixelsPerInch) * 10.0f;
178 }
179 
180 float SVGSVGElement::pixelUnitToMillimeterY() const
181 {
182  // 2.54 / cssPixelsPerInch gives CM.
183  return (2.54f / cssPixelsPerInch) * 10.0f;
184 }
185 
186 float SVGSVGElement::screenPixelToMillimeterX() const
187 {
188  return pixelUnitToMillimeterX();
189 }
190 
191 float SVGSVGElement::screenPixelToMillimeterY() const
192 {
193  return pixelUnitToMillimeterY();
194 }
195 
196 bool SVGSVGElement::useCurrentView() const
197 {
198  return m_useCurrentView;
199 }
200 
201 void SVGSVGElement::setUseCurrentView(bool currentView)
202 {
203  m_useCurrentView = currentView;
204 }
205 
206 SVGViewSpec *SVGSVGElement::currentView() const
207 {
208  if (!m_viewSpec) {
209  m_viewSpec.set(new SVGViewSpec(this));
210  }
211 
212  return m_viewSpec.get();
213 }
214 
215 float SVGSVGElement::currentScale() const
216 {
217  /*if (document() && document()->frame())
218  return document()->frame()->zoomFactor();*/
219  return 1.0f;
220 }
221 
222 void SVGSVGElement::setCurrentScale(float scale)
223 {
224  Q_UNUSED(scale);
225  /*if (document() && document()->frame())
226  document()->frame()->setZoomFactor(scale, true);*/
227 }
228 
229 FloatPoint SVGSVGElement::currentTranslate() const
230 {
231  return m_translation;
232 }
233 
234 void SVGSVGElement::setCurrentTranslate(const FloatPoint &translation)
235 {
236  m_translation = translation;
237  if (parentNode() == document() && document()->renderer()) {
238  document()->renderer()->repaint();
239  }
240 }
241 
242 void SVGSVGElement::addSVGWindowEventListener(const AtomicString &eventType, const Attribute *attr)
243 {
244  Q_UNUSED(eventType);
245  // FIXME: None of these should be window events long term.
246  // Once we propertly support SVGLoad, etc.
247  RefPtr<EventListener> listener = document()->accessSVGExtensions()->
248  createSVGEventListener(attr->localName().string(), attr->value(), this);
249  //document()->setHTMLWindowEventListener(eventType, listener.release());
250 }
251 
252 void SVGSVGElement::parseMappedAttribute(MappedAttribute *attr)
253 {
254  // qCDebug(KHTML_LOG) << "parse attribute: " << attr->localName() << attr->value();
255  if (!nearestViewportElement()) {
256  // Only handle events if we're the outermost <svg> element
257  /*if (attr->name() == onunloadAttr)
258  addSVGWindowEventListener(unloadEvent, attr);
259  else if (attr->name() == onabortAttr)
260  addSVGWindowEventListener(abortEvent, attr);
261  else if (attr->name() == onerrorAttr)
262  addSVGWindowEventListener(errorEvent, attr);
263  else if (attr->name() == onresizeAttr)
264  addSVGWindowEventListener(resizeEvent, attr);
265  else if (attr->name() == onscrollAttr)
266  addSVGWindowEventListener(scrollEvent, attr);
267  else if (attr->name() == SVGNames::onzoomAttr)
268  addSVGWindowEventListener(zoomEvent, attr);*/
269  }
270  if (attr->name() == SVGNames::xAttr) {
271  setXBaseValue(SVGLength(this, LengthModeWidth, attr->value()));
272  } else if (attr->name() == SVGNames::yAttr) {
273  setYBaseValue(SVGLength(this, LengthModeHeight, attr->value()));
274  } else if (attr->name() == SVGNames::widthAttr) {
275  // qCDebug(KHTML_LOG) << "set width" << attr->value();
276  setWidthBaseValue(SVGLength(this, LengthModeWidth, attr->value()));
277  addCSSProperty(attr, CSSPropertyWidth, attr->value());
278  /*if (width().value() < 0.0)
279  document()->accessSVGExtensions()->reportError("A negative value for svg attribute <width> is not allowed");*/
280  } else if (attr->name() == SVGNames::heightAttr) {
281  // qCDebug(KHTML_LOG) << "set height" << attr->value();
282  setHeightBaseValue(SVGLength(this, LengthModeHeight, attr->value()));
283  addCSSProperty(attr, CSSPropertyHeight, attr->value());
284  /*if (height().value() < 0.0)
285  document()->accessSVGExtensions()->reportError("A negative value for svg attribute <height> is not allowed");*/
286  } else {
287  /*if (SVGTests::parseMappedAttribute(attr))
288  return;
289  if (SVGLangSpace::parseMappedAttribute(attr))
290  return;
291  if (SVGExternalResourcesRequired::parseMappedAttribute(attr))
292  return;
293  if (SVGFitToViewBox::parseMappedAttribute(attr))
294  return;
295  if (SVGZoomAndPan::parseMappedAttribute(attr))
296  return;*/
297 
298  SVGStyledLocatableElement::parseMappedAttribute(attr);
299  }
300 }
301 
302 void SVGSVGElement::svgAttributeChanged(const QualifiedName &attrName)
303 {
304  SVGStyledElement::svgAttributeChanged(attrName);
305 
306  if (!renderer()) {
307  return;
308  }
309 
310  /*if (attrName == SVGNames::xAttr || attrName == SVGNames::yAttr ||
311  attrName == SVGNames::widthAttr || attrName == SVGNames::heightAttr ||
312  SVGTests::isKnownAttribute(attrName) ||
313  SVGLangSpace::isKnownAttribute(attrName) ||
314  SVGExternalResourcesRequired::isKnownAttribute(attrName) ||
315  SVGFitToViewBox::isKnownAttribute(attrName) ||
316  SVGZoomAndPan::isKnownAttribute(attrName) ||
317  SVGStyledLocatableElement::isKnownAttribute(attrName))
318  renderer()->setNeedsLayout(true);*/
319 }
320 
321 unsigned long SVGSVGElement::suspendRedraw(unsigned long /* max_wait_milliseconds */)
322 {
323  // FIXME: Implement me (see bug 11275)
324  return 0;
325 }
326 
327 void SVGSVGElement::unsuspendRedraw(unsigned long /* suspend_handle_id */, ExceptionCode & /*ec*/)
328 {
329  // if suspend_handle_id is not found, throw exception
330  // FIXME: Implement me (see bug 11275)
331 }
332 
333 void SVGSVGElement::unsuspendRedrawAll()
334 {
335  // FIXME: Implement me (see bug 11275)
336 }
337 
338 void SVGSVGElement::forceRedraw()
339 {
340  // FIXME: Implement me (see bug 11275)
341 }
342 
343 DOM::NodeListImpl *SVGSVGElement::getIntersectionList(const FloatRect &rect, SVGElement *)
344 {
345  Q_UNUSED(rect);
346  // FIXME: Implement me (see bug 11274)
347  return nullptr;
348 }
349 
350 DOM::NodeListImpl *SVGSVGElement::getEnclosureList(const FloatRect &rect, SVGElement *)
351 {
352  Q_UNUSED(rect);
353  // FIXME: Implement me (see bug 11274)
354  return nullptr;
355 }
356 
357 bool SVGSVGElement::checkIntersection(SVGElement *element, const FloatRect &rect)
358 {
359  Q_UNUSED(element);
360  // TODO : take into account pointer-events?
361  // FIXME: Why is element ignored??
362  // FIXME: Implement me (see bug 11274)
363  return rect.intersects(getBBox());
364 }
365 
366 bool SVGSVGElement::checkEnclosure(SVGElement *element, const FloatRect &rect)
367 {
368  Q_UNUSED(element);
369  // TODO : take into account pointer-events?
370  // FIXME: Why is element ignored??
371  // FIXME: Implement me (see bug 11274)
372  return rect.contains(getBBox());
373 }
374 
375 void SVGSVGElement::deselectAll()
376 {
377  //document()->frame()->selectionController()->clear();
378 }
379 
380 float SVGSVGElement::createSVGNumber()
381 {
382  return 0.0f;
383 }
384 
385 SVGLength SVGSVGElement::createSVGLength()
386 {
387  return SVGLength();
388 }
389 
390 SVGAngle *SVGSVGElement::createSVGAngle()
391 {
392  return new SVGAngle();
393 }
394 
395 FloatPoint SVGSVGElement::createSVGPoint()
396 {
397  return FloatPoint();
398 }
399 
400 AffineTransform SVGSVGElement::createSVGMatrix()
401 {
402  return AffineTransform();
403 }
404 
405 FloatRect SVGSVGElement::createSVGRect()
406 {
407  return FloatRect();
408 }
409 
410 SVGTransform SVGSVGElement::createSVGTransform()
411 {
412  return SVGTransform();
413 }
414 
415 SVGTransform SVGSVGElement::createSVGTransformFromMatrix(const AffineTransform &matrix)
416 {
417  return SVGTransform(matrix);
418 }
419 
420 AffineTransform SVGSVGElement::getCTM() const
421 {
422  AffineTransform mat;
423  if (!isOutermostSVG()) {
424  mat.translate(x().value(), y().value());
425  }
426 
427  if (attributes()->getNamedItem(SVGNames::viewBoxAttr)) {
428  AffineTransform viewBox = viewBoxToViewTransform(width().value(), height().value());
429  mat = viewBox * mat;
430  }
431 
432  return mat;
433 }
434 
435 AffineTransform SVGSVGElement::getScreenCTM() const
436 {
437  /*document()->updateLayoutIgnorePendingStylesheets();
438  float rootX = 0.0f;
439  float rootY = 0.0f;
440 
441  if (RenderObject* renderer = this->renderer()) {
442  renderer = renderer->parent();
443  if (isOutermostSVG()) {
444  int tx = 0;
445  int ty = 0;
446  if (renderer)
447  renderer->absolutePosition(tx, ty, true);
448  rootX += tx;
449  rootY += ty;
450  } else {
451  rootX += x().value();
452  rootY += y().value();
453  }
454  }
455 
456  AffineTransform mat = SVGStyledLocatableElement::getScreenCTM();
457  mat.translate(rootX, rootY);
458 
459  if (attributes()->getNamedItem(SVGNames::viewBoxAttr)) {
460  AffineTransform viewBox = viewBoxToViewTransform(width().value(), height().value());
461  mat = viewBox * mat;
462  }
463 
464  return mat;*/
465  ASSERT(false);
466  return AffineTransform();
467 }
468 
469 RenderObject *SVGSVGElement::createRenderer(RenderArena *arena, RenderStyle *)
470 {
471  // qCDebug(KHTML_LOG) << "create RenderSVGRoot from <svg> element";
472  return new(arena) RenderSVGRoot(this);
473  /*if (isOutermostSVG())
474  return new (arena) RenderSVGRoot(this);
475  else
476  return new (arena) RenderSVGViewportContainer(this);*/
477 }
478 
479 void SVGSVGElement::insertedIntoDocument()
480 {
481  document()->accessSVGExtensions()->addTimeContainer(this);
482  SVGStyledLocatableElement::insertedIntoDocument();
483 }
484 
485 void SVGSVGElement::removedFromDocument()
486 {
487  document()->accessSVGExtensions()->removeTimeContainer(this);
488  SVGStyledLocatableElement::removedFromDocument();
489 }
490 
491 void SVGSVGElement::pauseAnimations()
492 {
493  /*if (!m_timeContainer->isPaused())
494  m_timeContainer->pause();*/
495 }
496 
497 void SVGSVGElement::unpauseAnimations()
498 {
499  /*if (m_timeContainer->isPaused())
500  m_timeContainer->resume();*/
501 }
502 
503 bool SVGSVGElement::animationsPaused() const
504 {
505  //return m_timeContainer->isPaused();
506  ASSERT(false);
507  return false;
508 }
509 
510 float SVGSVGElement::getCurrentTime() const
511 {
512  //return narrowPrecisionToFloat(m_timeContainer->elapsed().value());
513  ASSERT(false);
514  return 0.0;
515 }
516 
517 void SVGSVGElement::setCurrentTime(float /* seconds */)
518 {
519  // FIXME: Implement me, bug 12073
520 }
521 
522 bool SVGSVGElement::hasRelativeValues() const
523 {
524  return (x().isRelative() || width().isRelative() ||
525  y().isRelative() || height().isRelative());
526 }
527 
528 bool SVGSVGElement::isOutermostSVG() const
529 {
530  // This is true whenever this is the outermost SVG, even if there are HTML elements outside it
531  return !parentNode()->isSVGElement();
532 }
533 
534 AffineTransform SVGSVGElement::viewBoxToViewTransform(float viewWidth, float viewHeight) const
535 {
536  FloatRect viewBoxRect;
537  if (useCurrentView()) {
538  if (currentView()) { // what if we should use it but it is not set?
539  viewBoxRect = currentView()->viewBox();
540  }
541  } else {
542  viewBoxRect = viewBox();
543  }
544  if (!viewBoxRect.width() || !viewBoxRect.height()) {
545  return AffineTransform();
546  }
547 
548  AffineTransform ctm = preserveAspectRatio()->getCTM(viewBoxRect.x(),
549  viewBoxRect.y(), viewBoxRect.width(), viewBoxRect.height(),
550  0, 0, viewWidth, viewHeight);
551 
552  if (useCurrentView() && currentView()) {
553  return currentView()->transform()->concatenate().matrix() * ctm;
554  }
555 
556  return ctm;
557 }
558 
559 /*void SVGSVGElement::inheritViewAttributes(SVGViewElement* viewElement)
560 {
561  setUseCurrentView(true);
562  if (viewElement->hasAttribute(SVGNames::viewBoxAttr))
563  currentView()->setViewBox(viewElement->viewBox());
564  else
565  currentView()->setViewBox(viewBox());
566  if (viewElement->hasAttribute(SVGNames::preserveAspectRatioAttr)) {
567  currentView()->preserveAspectRatio()->setAlign(viewElement->preserveAspectRatio()->align());
568  currentView()->preserveAspectRatio()->setMeetOrSlice(viewElement->preserveAspectRatio()->meetOrSlice());
569  } else {
570  currentView()->preserveAspectRatio()->setAlign(preserveAspectRatio()->align());
571  currentView()->preserveAspectRatio()->setMeetOrSlice(preserveAspectRatio()->meetOrSlice());
572  }
573  if (viewElement->hasAttribute(SVGNames::zoomAndPanAttr))
574  currentView()->setZoomAndPan(viewElement->zoomAndPan());
575  renderer()->setNeedsLayout(true);
576 }*/
577 
578 void SVGSVGElement::willSaveToCache()
579 {
580  //pauseAnimations();
581 }
582 
583 void SVGSVGElement::willRestoreFromCache()
584 {
585  //unpauseAnimations();
586 }
587 
588 // KHTML stuff
589 quint32 SVGSVGElement::id() const
590 {
591  return SVGNames::svgTag.id();
592 }
593 
594 }
595 
596 #endif // ENABLE(SVG)
597 
Renders and displays HTML in a QScrollArea.
Definition: khtmlview.h:97
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Tue Oct 26 2021 22:48:10 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.