2 Copyright (C) 2004, 2005 Nikolas Zimmermann <wildfox@kde.org>
3 2004, 2005 Rob Buis <buis@kde.org>
5 This file is part of the KDE project
7 This library is free software; you can redistribute it and/or
8 modify it under the terms of the GNU Library General Public
9 License as published by the Free Software Foundation; either
10 version 2 of the License, or (at your option) any later version.
12 This library is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Library General Public License for more details.
17 You should have received a copy of the GNU Library General Public License
18 along with this library; see the file COPYING.LIB. If not, write to
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA.
25 #include "SVGSVGElement.h"
27 #include "CSSPropertyNames.h"
29 #include "EventListener.h"
30 #include "EventNames.h"
31 #include "HTMLNames.h"
32 #include "KCanvasRenderingStyle.h"
33 #include "KSVGTimeScheduler.h"
35 #include "SVGLength.h"
36 #include "SVGPreserveAspectRatio.h"
37 #include "SVGDocumentExtensions.h"
38 #include "SVGMatrix.h"
39 #include "SVGTransform.h"
40 #include "SVGZoomEvent.h"
42 #include <kcanvas/RenderSVGContainer.h>
43 #include <kcanvas/device/KRenderingDevice.h>
44 #include "TextStream.h"
48 using namespace HTMLNames;
49 using namespace EventNames;
51 SVGSVGElement::SVGSVGElement(const QualifiedName& tagName, Document *doc)
52 : SVGStyledLocatableElement(tagName, doc)
55 , SVGExternalResourcesRequired()
58 , m_useCurrentView(false)
59 , m_timeScheduler(new TimeScheduler(doc))
61 const SVGElement* viewport = ownerDocument()->documentElement() == this ? this : viewportElement();
62 const SVGStyledElement* context = ownerDocument()->documentElement() == this ? 0 : this;
64 m_x = new SVGLength(context, LM_WIDTH, viewport);
65 m_y = new SVGLength(context, LM_HEIGHT, viewport);
66 m_width = new SVGLength(context, LM_WIDTH, viewport);
67 m_height = new SVGLength(context, LM_HEIGHT, viewport);
69 m_width->setValueAsString("100%");
70 m_height->setValueAsString("100%");
73 SVGSVGElement::~SVGSVGElement()
75 delete m_timeScheduler;
78 ANIMATED_PROPERTY_DEFINITIONS(SVGSVGElement, SVGLength*, Length, length, X, x, SVGNames::xAttr.localName(), m_x.get())
79 ANIMATED_PROPERTY_DEFINITIONS(SVGSVGElement, SVGLength*, Length, length, Y, y, SVGNames::yAttr.localName(), m_y.get())
80 ANIMATED_PROPERTY_DEFINITIONS(SVGSVGElement, SVGLength*, Length, length, Width, width, SVGNames::widthAttr.localName(), m_width.get())
81 ANIMATED_PROPERTY_DEFINITIONS(SVGSVGElement, SVGLength*, Length, length, Height, height, SVGNames::heightAttr.localName(), m_height.get())
83 AtomicString SVGSVGElement::contentScriptType() const
85 return tryGetAttribute("contentScriptType", "text/ecmascript");
88 void SVGSVGElement::setContentScriptType(const AtomicString& type)
90 setAttribute(SVGNames::contentScriptTypeAttr, type);
93 AtomicString SVGSVGElement::contentStyleType() const
95 return tryGetAttribute("contentStyleType", "text/css");
98 void SVGSVGElement::setContentStyleType(const AtomicString& type)
100 setAttribute(SVGNames::contentStyleTypeAttr, type);
103 FloatRect SVGSVGElement::viewport() const
105 double _x = x()->value();
106 double _y = y()->value();
107 double w = width()->value();
108 double h = height()->value();
109 RefPtr<SVGMatrix> viewBox = viewBoxToViewTransform(w, h);
110 viewBox->matrix().map(_x, _y, &_x, &_y);
111 viewBox->matrix().map(w, h, &w, &h);
112 return FloatRect(_x, _y, w, h);
115 float SVGSVGElement::pixelUnitToMillimeterX() const
118 if(ownerDocument() && ownerDocument()->paintDeviceMetrics())
120 Q3PaintDeviceMetrics *metrics = ownerDocument()->paintDeviceMetrics();
121 return float(metrics->widthMM()) / float(metrics->width());
128 float SVGSVGElement::pixelUnitToMillimeterY() const
131 if(ownerDocument() && ownerDocument()->paintDeviceMetrics())
133 Q3PaintDeviceMetrics *metrics = ownerDocument()->paintDeviceMetrics();
134 return float(metrics->heightMM()) / float(metrics->height());
141 float SVGSVGElement::screenPixelToMillimeterX() const
143 return pixelUnitToMillimeterX();
146 float SVGSVGElement::screenPixelToMillimeterY() const
148 return pixelUnitToMillimeterY();
151 bool SVGSVGElement::useCurrentView() const
153 return m_useCurrentView;
156 void SVGSVGElement::setUseCurrentView(bool currentView)
158 m_useCurrentView = currentView;
161 float SVGSVGElement::currentScale() const
166 //return canvasView()->zoom();
169 void SVGSVGElement::setCurrentScale(float scale)
173 // float oldzoom = canvasView()->zoom();
174 // canvasView()->setZoom(scale);
175 // document()->dispatchZoomEvent(oldzoom, scale);
179 FloatPoint SVGSVGElement::currentTranslate() const
184 //return createSVGPoint(canvasView()->pan());
187 void SVGSVGElement::addSVGWindowEventListner(const AtomicString& eventType, const Attribute* attr)
189 // FIXME: None of these should be window events long term.
190 // Once we propertly support SVGLoad, etc.
191 RefPtr<EventListener> listener = document()->accessSVGExtensions()->
192 createSVGEventListener(attr->localName().domString(), attr->value(), this);
193 document()->setHTMLWindowEventListener(eventType, listener.release());
196 void SVGSVGElement::parseMappedAttribute(MappedAttribute *attr)
198 const AtomicString& value = attr->value();
199 if (!nearestViewportElement()) {
200 // Only handle events if we're the outermost <svg> element
201 if (attr->name() == onunloadAttr)
202 addSVGWindowEventListner(unloadEvent, attr);
203 else if (attr->name() == onabortAttr)
204 addSVGWindowEventListner(abortEvent, attr);
205 else if (attr->name() == onerrorAttr)
206 addSVGWindowEventListner(errorEvent, attr);
207 else if (attr->name() == onresizeAttr)
208 addSVGWindowEventListner(resizeEvent, attr);
209 else if (attr->name() == onscrollAttr)
210 addSVGWindowEventListner(scrollEvent, attr);
211 else if (attr->name() == SVGNames::onzoomAttr)
212 addSVGWindowEventListner(zoomEvent, attr);
214 if (attr->name() == SVGNames::xAttr) {
215 xBaseValue()->setValueAsString(value);
216 } else if (attr->name() == SVGNames::yAttr) {
217 yBaseValue()->setValueAsString(value);
218 } else if (attr->name() == SVGNames::widthAttr) {
219 widthBaseValue()->setValueAsString(value);
220 addCSSProperty(attr, CSS_PROP_WIDTH, value);
221 } else if (attr->name() == SVGNames::heightAttr) {
222 heightBaseValue()->setValueAsString(value);
223 addCSSProperty(attr, CSS_PROP_HEIGHT, value);
225 if (SVGTests::parseMappedAttribute(attr))
227 if (SVGLangSpace::parseMappedAttribute(attr))
229 if (SVGExternalResourcesRequired::parseMappedAttribute(attr))
231 if (SVGFitToViewBox::parseMappedAttribute(attr) && renderer())
232 static_cast<RenderSVGContainer*>(renderer())->setViewBox(viewBox());
233 if (SVGZoomAndPan::parseMappedAttribute(attr))
236 SVGStyledLocatableElement::parseMappedAttribute(attr);
240 unsigned long SVGSVGElement::suspendRedraw(unsigned long /* max_wait_milliseconds */)
246 void SVGSVGElement::unsuspendRedraw(unsigned long /* suspend_handle_id */, ExceptionCode& ec)
248 // if suspend_handle_id is not found, throw exception
252 void SVGSVGElement::unsuspendRedrawAll()
257 void SVGSVGElement::forceRedraw()
262 NodeList *SVGSVGElement::getIntersectionList(const FloatRect& rect, SVGElement*)
269 NodeList *SVGSVGElement::getEnclosureList(const FloatRect& rect, SVGElement*)
275 bool SVGSVGElement::checkIntersection(SVGElement* element, const FloatRect& rect)
277 // TODO : take into account pointer-events?
278 // FIXME: Why is element ignored??
279 return rect.intersects(getBBox());
282 bool SVGSVGElement::checkEnclosure(SVGElement* element, const FloatRect& rect)
284 // TODO : take into account pointer-events?
285 // FIXME: Why is element ignored??
286 return rect.contains(getBBox());
289 void SVGSVGElement::deselectAll()
294 float SVGSVGElement::createSVGNumber()
299 SVGLength *SVGSVGElement::createSVGLength()
301 return new SVGLength(0);
304 SVGAngle *SVGSVGElement::createSVGAngle()
306 return new SVGAngle(0);
309 FloatPoint SVGSVGElement::createSVGPoint(const IntPoint &p)
311 return FloatPoint(p);
314 SVGMatrix *SVGSVGElement::createSVGMatrix()
316 return new SVGMatrix();
319 FloatRect SVGSVGElement::createSVGRect()
324 SVGTransform *SVGSVGElement::createSVGTransform()
326 return new SVGTransform();
329 SVGTransform *SVGSVGElement::createSVGTransformFromMatrix(SVGMatrix *matrix)
331 SVGTransform *obj = SVGSVGElement::createSVGTransform();
332 obj->setMatrix(matrix);
336 SVGMatrix *SVGSVGElement::getCTM() const
338 SVGMatrix *mat = createSVGMatrix();
341 mat->translate(x()->value(), y()->value());
343 if(attributes()->getNamedItem(SVGNames::viewBoxAttr))
345 RefPtr<SVGMatrix> viewBox = viewBoxToViewTransform(width()->value(), height()->value());
346 mat->multiply(viewBox.get());
353 SVGMatrix *SVGSVGElement::getScreenCTM() const
355 SVGMatrix *mat = SVGStyledLocatableElement::getScreenCTM();
357 mat->translate(x()->value(), y()->value());
359 if (attributes()->getNamedItem(SVGNames::viewBoxAttr)) {
360 RefPtr<SVGMatrix> viewBox = viewBoxToViewTransform(width()->value(), height()->value());
361 mat->multiply(viewBox.get());
368 RenderObject* SVGSVGElement::createRenderer(RenderArena* arena, RenderStyle*)
370 RenderSVGContainer* rootContainer = new (arena) RenderSVGContainer(this);
372 // FIXME: all this setup should be done after attributesChanged, not here.
373 rootContainer->setViewport(FloatRect(x()->value(), y()->value(), width()->value(), height()->value()));
374 rootContainer->setViewBox(viewBox());
375 rootContainer->setAlign(KCAlign(preserveAspectRatio()->align() - 1));
376 rootContainer->setSlice(preserveAspectRatio()->meetOrSlice() == SVGPreserveAspectRatio::SVG_MEETORSLICE_SLICE);
378 return rootContainer;
381 void SVGSVGElement::insertedIntoDocument()
383 document()->accessSVGExtensions()->addTimeContainer(this);
384 SVGStyledLocatableElement::insertedIntoDocument();
387 void SVGSVGElement::removedFromDocument()
389 document()->accessSVGExtensions()->removeTimeContainer(this);
390 SVGStyledLocatableElement::removedFromDocument();
393 void SVGSVGElement::setZoomAndPan(unsigned short zoomAndPan)
395 SVGZoomAndPan::setZoomAndPan(zoomAndPan);
396 //canvasView()->enableZoomAndPan(zoomAndPan == SVG_ZOOMANDPAN_MAGNIFY);
399 void SVGSVGElement::pauseAnimations()
401 if (!m_timeScheduler->animationsPaused())
402 m_timeScheduler->toggleAnimations();
405 void SVGSVGElement::unpauseAnimations()
407 if (m_timeScheduler->animationsPaused())
408 m_timeScheduler->toggleAnimations();
411 bool SVGSVGElement::animationsPaused() const
413 return m_timeScheduler->animationsPaused();
416 float SVGSVGElement::getCurrentTime() const
418 return m_timeScheduler->elapsed();
421 void SVGSVGElement::setCurrentTime(float /* seconds */)
429 #endif // SVG_SUPPORT