don't discard iframe children.
[kdelibs.git] / khtml / svg / SVGSVGElement.cpp
blob2bb68a272f9d71a51d81a7fe41b8e2fe85b7737f
1 /*
2 Copyright (C) 2004, 2005, 2006 Nikolas Zimmermann <zimmermann@kde.org>
3 2004, 2005, 2006, 2007 Rob Buis <buis@kde.org>
4 2007 Apple Inc. All rights reserved.
6 This file is part of the KDE project
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.
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.
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.
24 #include "config.h"
25 #include <wtf/Platform.h>
27 #if ENABLE(SVG)
28 #include "SVGSVGElement.h"
30 #include "AffineTransform.h"
31 /*#include "CSSHelper.h"*/
32 #include "css/csshelper.h"
33 /*#include "CSSPropertyNames.h"*/
34 #include "Document.h"
35 //#include "EventListener.h"
36 #include "dom/dom2_events.h"
37 /*#include "EventNames.h"*/
38 #include "FloatConversion.h"
39 #include "FloatRect.h"
40 /*#include "Frame.h"
41 #include "HTMLNames.h"
42 #include "RenderSVGViewportContainer.h"*/
43 #include "RenderSVGRoot.h"
44 #include "SVGAngle.h"
45 #include "SVGLength.h"
46 #include "SVGNames.h"
47 #include "SVGPreserveAspectRatio.h"
48 #include "SVGTransform.h"
49 #include "SVGTransformList.h"
50 /*#include "SVGViewElement.h"*/
51 #include "SVGViewSpec.h"
52 /*#include "SVGZoomEvent.h"
53 #include "SelectionController.h"
54 #include "SMILTimeContainer.h"*/
56 namespace WebCore {
58 /*using namespace HTMLNames;
59 using namespace EventNames;*/
60 using namespace SVGNames;
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 , m_containerSize(300, 150)
77 /*, m_hasSetContainerSize(false)*/
79 setWidthBaseValue(SVGLength(this, LengthModeWidth, "100%"));
80 setHeightBaseValue(SVGLength(this, LengthModeHeight, "100%"));
81 //doc->registerForCacheCallbacks(this);
84 SVGSVGElement::~SVGSVGElement()
86 /*document()->unregisterForCacheCallbacks(this);
87 // There are cases where removedFromDocument() is not called.
88 // see ContainerNode::removeAllChildren, called by it's destructor.
89 document()->accessSVGExtensions()->removeTimeContainer(this);*/
92 ANIMATED_PROPERTY_DEFINITIONS(SVGSVGElement, SVGLength, Length, length, X, x, SVGNames::xAttr, m_x)
93 ANIMATED_PROPERTY_DEFINITIONS(SVGSVGElement, SVGLength, Length, length, Y, y, SVGNames::yAttr, m_y)
94 ANIMATED_PROPERTY_DEFINITIONS(SVGSVGElement, SVGLength, Length, length, Width, width, SVGNames::widthAttr, m_width)
95 ANIMATED_PROPERTY_DEFINITIONS(SVGSVGElement, SVGLength, Length, length, Height, height, SVGNames::heightAttr, m_height)
97 const AtomicString& SVGSVGElement::contentScriptType() const
99 /*static const AtomicString defaultValue("text/ecmascript");
100 const AtomicString& n = getAttribute(contentScriptTypeAttr);
101 return n.isNull() ? defaultValue : n;*/
102 ASSERT(false);
103 return "";
106 void SVGSVGElement::setContentScriptType(const AtomicString& type)
108 setAttribute(SVGNames::contentScriptTypeAttr, type);
111 const AtomicString& SVGSVGElement::contentStyleType() const
113 /*static const AtomicString defaultValue("text/css");
114 const AtomicString& n = getAttribute(contentStyleTypeAttr);
115 return n.isNull() ? defaultValue : n;*/
116 ASSERT(false);
117 return "";
120 void SVGSVGElement::setContentStyleType(const AtomicString& type)
122 setAttribute(SVGNames::contentStyleTypeAttr, type);
125 FloatRect SVGSVGElement::viewport() const
127 double _x = 0.0;
128 double _y = 0.0;
129 if (!isOutermostSVG()) {
130 _x = x().value();
131 _y = y().value();
133 float w = width().value();
134 float h = height().value();
135 AffineTransform viewBox = viewBoxToViewTransform(w, h);
136 double wDouble = w;
137 double hDouble = h;
138 viewBox.map(_x, _y, &_x, &_y);
139 viewBox.map(w, h, &wDouble, &hDouble);
140 return FloatRect::narrowPrecision(_x, _y, wDouble, hDouble);
143 int SVGSVGElement::relativeWidthValue() const
145 SVGLength w = width();
146 if (w.unitType() != LengthTypePercentage)
147 return 0;
149 return static_cast<int>(w.valueAsPercentage() * m_containerSize.width());
152 int SVGSVGElement::relativeHeightValue() const
154 SVGLength h = height();
155 if (h.unitType() != LengthTypePercentage)
156 return 0;
158 return static_cast<int>(h.valueAsPercentage() * m_containerSize.height());
161 float SVGSVGElement::pixelUnitToMillimeterX() const
163 // 2.54 / cssPixelsPerInch gives CM.
164 return (2.54f / cssPixelsPerInch) * 10.0f;
167 float SVGSVGElement::pixelUnitToMillimeterY() const
169 // 2.54 / cssPixelsPerInch gives CM.
170 return (2.54f / cssPixelsPerInch) * 10.0f;
173 float SVGSVGElement::screenPixelToMillimeterX() const
175 return pixelUnitToMillimeterX();
178 float SVGSVGElement::screenPixelToMillimeterY() const
180 return pixelUnitToMillimeterY();
183 bool SVGSVGElement::useCurrentView() const
185 return m_useCurrentView;
188 void SVGSVGElement::setUseCurrentView(bool currentView)
190 m_useCurrentView = currentView;
193 SVGViewSpec* SVGSVGElement::currentView() const
195 if (!m_viewSpec)
196 m_viewSpec.set(new SVGViewSpec(this));
198 return m_viewSpec.get();
201 float SVGSVGElement::currentScale() const
203 /*if (document() && document()->frame())
204 return document()->frame()->zoomFactor();*/
205 return 1.0f;
208 void SVGSVGElement::setCurrentScale(float scale)
210 /*if (document() && document()->frame())
211 document()->frame()->setZoomFactor(scale, true);*/
214 FloatPoint SVGSVGElement::currentTranslate() const
216 return m_translation;
219 void SVGSVGElement::setCurrentTranslate(const FloatPoint &translation)
221 m_translation = translation;
222 if (parentNode() == document() && document()->renderer())
223 document()->renderer()->repaint();
226 void SVGSVGElement::addSVGWindowEventListener(const AtomicString& eventType, const Attribute* attr)
228 // FIXME: None of these should be window events long term.
229 // Once we propertly support SVGLoad, etc.
230 RefPtr<EventListener> listener = document()->accessSVGExtensions()->
231 createSVGEventListener(attr->localName().string(), attr->value(), this);
232 //document()->setHTMLWindowEventListener(eventType, listener.release());
235 void SVGSVGElement::parseMappedAttribute(MappedAttribute* attr)
237 kDebug() << "parse attribute: " << attr->localName() << attr->value() << endl;
238 if (!nearestViewportElement()) {
239 // Only handle events if we're the outermost <svg> element
240 /*if (attr->name() == onunloadAttr)
241 addSVGWindowEventListener(unloadEvent, attr);
242 else if (attr->name() == onabortAttr)
243 addSVGWindowEventListener(abortEvent, attr);
244 else if (attr->name() == onerrorAttr)
245 addSVGWindowEventListener(errorEvent, attr);
246 else if (attr->name() == onresizeAttr)
247 addSVGWindowEventListener(resizeEvent, attr);
248 else if (attr->name() == onscrollAttr)
249 addSVGWindowEventListener(scrollEvent, attr);
250 else if (attr->name() == SVGNames::onzoomAttr)
251 addSVGWindowEventListener(zoomEvent, attr);*/
253 if (attr->name() == SVGNames::xAttr)
254 setXBaseValue(SVGLength(this, LengthModeWidth, attr->value()));
255 else if (attr->name() == SVGNames::yAttr)
256 setYBaseValue(SVGLength(this, LengthModeHeight, attr->value()));
257 else if (attr->name() == SVGNames::widthAttr) {
258 kDebug() << "set width" << attr->value() << endl;
259 setWidthBaseValue(SVGLength(this, LengthModeWidth, attr->value()));
260 addCSSProperty(attr, CSSPropertyWidth, attr->value());
261 /*if (width().value() < 0.0)
262 document()->accessSVGExtensions()->reportError("A negative value for svg attribute <width> is not allowed");*/
263 } else if (attr->name() == SVGNames::heightAttr) {
264 kDebug() << "set height" << attr->value() << endl;
265 setHeightBaseValue(SVGLength(this, LengthModeHeight, attr->value()));
266 addCSSProperty(attr, CSSPropertyHeight, attr->value());
267 /*if (height().value() < 0.0)
268 document()->accessSVGExtensions()->reportError("A negative value for svg attribute <height> is not allowed");*/
269 } else {
270 /*if (SVGTests::parseMappedAttribute(attr))
271 return;
272 if (SVGLangSpace::parseMappedAttribute(attr))
273 return;
274 if (SVGExternalResourcesRequired::parseMappedAttribute(attr))
275 return;
276 if (SVGFitToViewBox::parseMappedAttribute(attr))
277 return;
278 if (SVGZoomAndPan::parseMappedAttribute(attr))
279 return;*/
281 SVGStyledLocatableElement::parseMappedAttribute(attr);
285 void SVGSVGElement::svgAttributeChanged(const QualifiedName& attrName)
287 SVGStyledElement::svgAttributeChanged(attrName);
289 if (!renderer())
290 return;
292 /*if (attrName == SVGNames::xAttr || attrName == SVGNames::yAttr ||
293 attrName == SVGNames::widthAttr || attrName == SVGNames::heightAttr ||
294 SVGTests::isKnownAttribute(attrName) ||
295 SVGLangSpace::isKnownAttribute(attrName) ||
296 SVGExternalResourcesRequired::isKnownAttribute(attrName) ||
297 SVGFitToViewBox::isKnownAttribute(attrName) ||
298 SVGZoomAndPan::isKnownAttribute(attrName) ||
299 SVGStyledLocatableElement::isKnownAttribute(attrName))
300 renderer()->setNeedsLayout(true);*/
303 unsigned long SVGSVGElement::suspendRedraw(unsigned long /* max_wait_milliseconds */)
305 // FIXME: Implement me (see bug 11275)
306 return 0;
309 void SVGSVGElement::unsuspendRedraw(unsigned long /* suspend_handle_id */, ExceptionCode& ec)
311 // if suspend_handle_id is not found, throw exception
312 // FIXME: Implement me (see bug 11275)
315 void SVGSVGElement::unsuspendRedrawAll()
317 // FIXME: Implement me (see bug 11275)
320 void SVGSVGElement::forceRedraw()
322 // FIXME: Implement me (see bug 11275)
325 NodeList* SVGSVGElement::getIntersectionList(const FloatRect& rect, SVGElement*)
327 // FIXME: Implement me (see bug 11274)
328 return 0;
331 NodeList* SVGSVGElement::getEnclosureList(const FloatRect& rect, SVGElement*)
333 // FIXME: Implement me (see bug 11274)
334 return 0;
337 bool SVGSVGElement::checkIntersection(SVGElement* element, const FloatRect& rect)
339 // TODO : take into account pointer-events?
340 // FIXME: Why is element ignored??
341 // FIXME: Implement me (see bug 11274)
342 return rect.intersects(getBBox());
345 bool SVGSVGElement::checkEnclosure(SVGElement* element, const FloatRect& rect)
347 // TODO : take into account pointer-events?
348 // FIXME: Why is element ignored??
349 // FIXME: Implement me (see bug 11274)
350 return rect.contains(getBBox());
353 void SVGSVGElement::deselectAll()
355 //document()->frame()->selectionController()->clear();
358 float SVGSVGElement::createSVGNumber()
360 return 0.0f;
363 SVGLength SVGSVGElement::createSVGLength()
365 return SVGLength();
368 SVGAngle* SVGSVGElement::createSVGAngle()
370 return new SVGAngle();
373 FloatPoint SVGSVGElement::createSVGPoint()
375 return FloatPoint();
378 AffineTransform SVGSVGElement::createSVGMatrix()
380 return AffineTransform();
383 FloatRect SVGSVGElement::createSVGRect()
385 return FloatRect();
388 SVGTransform SVGSVGElement::createSVGTransform()
390 return SVGTransform();
393 SVGTransform SVGSVGElement::createSVGTransformFromMatrix(const AffineTransform& matrix)
395 return SVGTransform(matrix);
398 AffineTransform SVGSVGElement::getCTM() const
400 AffineTransform mat;
401 if (!isOutermostSVG())
402 mat.translate(x().value(), y().value());
404 if (attributes()->getNamedItem(SVGNames::viewBoxAttr)) {
405 AffineTransform viewBox = viewBoxToViewTransform(width().value(), height().value());
406 mat = viewBox * mat;
409 return mat;
412 AffineTransform SVGSVGElement::getScreenCTM() const
414 /*document()->updateLayoutIgnorePendingStylesheets();
415 float rootX = 0.0f;
416 float rootY = 0.0f;
418 if (RenderObject* renderer = this->renderer()) {
419 renderer = renderer->parent();
420 if (isOutermostSVG()) {
421 int tx = 0;
422 int ty = 0;
423 if (renderer)
424 renderer->absolutePosition(tx, ty, true);
425 rootX += tx;
426 rootY += ty;
427 } else {
428 rootX += x().value();
429 rootY += y().value();
433 AffineTransform mat = SVGStyledLocatableElement::getScreenCTM();
434 mat.translate(rootX, rootY);
436 if (attributes()->getNamedItem(SVGNames::viewBoxAttr)) {
437 AffineTransform viewBox = viewBoxToViewTransform(width().value(), height().value());
438 mat = viewBox * mat;
441 return mat;*/
442 ASSERT(false);
443 return AffineTransform();
446 RenderObject* SVGSVGElement::createRenderer(RenderArena* arena, RenderStyle*)
448 kDebug() << "create RenderSVGRoot from <svg> element" << endl;
449 return new (arena) RenderSVGRoot(this);
450 /*if (isOutermostSVG())
451 return new (arena) RenderSVGRoot(this);
452 else
453 return new (arena) RenderSVGViewportContainer(this);*/
456 void SVGSVGElement::insertedIntoDocument()
458 document()->accessSVGExtensions()->addTimeContainer(this);
459 SVGStyledLocatableElement::insertedIntoDocument();
462 void SVGSVGElement::removedFromDocument()
464 document()->accessSVGExtensions()->removeTimeContainer(this);
465 SVGStyledLocatableElement::removedFromDocument();
468 void SVGSVGElement::pauseAnimations()
470 /*if (!m_timeContainer->isPaused())
471 m_timeContainer->pause();*/
474 void SVGSVGElement::unpauseAnimations()
476 /*if (m_timeContainer->isPaused())
477 m_timeContainer->resume();*/
480 bool SVGSVGElement::animationsPaused() const
482 //return m_timeContainer->isPaused();
483 ASSERT(false);
484 return false;
487 float SVGSVGElement::getCurrentTime() const
489 //return narrowPrecisionToFloat(m_timeContainer->elapsed().value());
490 ASSERT(false);
491 return 0.0;
494 void SVGSVGElement::setCurrentTime(float /* seconds */)
496 // FIXME: Implement me, bug 12073
499 bool SVGSVGElement::hasRelativeValues() const
501 return (x().isRelative() || width().isRelative() ||
502 y().isRelative() || height().isRelative());
505 bool SVGSVGElement::isOutermostSVG() const
507 // This is true whenever this is the outermost SVG, even if there are HTML elements outside it
508 return !parentNode()->isSVGElement();
511 AffineTransform SVGSVGElement::viewBoxToViewTransform(float viewWidth, float viewHeight) const
513 FloatRect viewBoxRect;
514 if (useCurrentView()) {
515 if (currentView()) // what if we should use it but it is not set?
516 viewBoxRect = currentView()->viewBox();
517 } else
518 viewBoxRect = viewBox();
519 if (!viewBoxRect.width() || !viewBoxRect.height())
520 return AffineTransform();
522 AffineTransform ctm = preserveAspectRatio()->getCTM(viewBoxRect.x(),
523 viewBoxRect.y(), viewBoxRect.width(), viewBoxRect.height(),
524 0, 0, viewWidth, viewHeight);
526 if (useCurrentView() && currentView())
527 return currentView()->transform()->concatenate().matrix() * ctm;
529 return ctm;
532 /*void SVGSVGElement::inheritViewAttributes(SVGViewElement* viewElement)
534 setUseCurrentView(true);
535 if (viewElement->hasAttribute(SVGNames::viewBoxAttr))
536 currentView()->setViewBox(viewElement->viewBox());
537 else
538 currentView()->setViewBox(viewBox());
539 if (viewElement->hasAttribute(SVGNames::preserveAspectRatioAttr)) {
540 currentView()->preserveAspectRatio()->setAlign(viewElement->preserveAspectRatio()->align());
541 currentView()->preserveAspectRatio()->setMeetOrSlice(viewElement->preserveAspectRatio()->meetOrSlice());
542 } else {
543 currentView()->preserveAspectRatio()->setAlign(preserveAspectRatio()->align());
544 currentView()->preserveAspectRatio()->setMeetOrSlice(preserveAspectRatio()->meetOrSlice());
546 if (viewElement->hasAttribute(SVGNames::zoomAndPanAttr))
547 currentView()->setZoomAndPan(viewElement->zoomAndPan());
548 renderer()->setNeedsLayout(true);
551 void SVGSVGElement::willSaveToCache()
553 //pauseAnimations();
556 void SVGSVGElement::willRestoreFromCache()
558 //unpauseAnimations();
561 // KHTML stuff
562 quint32 SVGSVGElement::id() const { return SVGNames::svgTag.id(); }
566 #endif // ENABLE(SVG)
568 // vim:ts=4:noet