bbc1ee5b4a2027eb1253cfbefed1f6588b53ec8c
[WebKit-https.git] / WebCore / ksvg2 / svg / SVGSVGElement.cpp
1 /*
2     Copyright (C) 2004, 2005 Nikolas Zimmermann <wildfox@kde.org>
3                   2004, 2005, 2006 Rob Buis <buis@kde.org>
4
5     This file is part of the KDE project
6
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.
11
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.
16
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.
21 */
22
23 #include "config.h"
24 #ifdef SVG_SUPPORT
25 #include "SVGSVGElement.h"
26
27 #include "CSSPropertyNames.h"
28 #include "Document.h"
29 #include "EventListener.h"
30 #include "EventNames.h"
31 #include "HTMLNames.h"
32 #include "KSVGTimeScheduler.h"
33 #include "RenderSVGContainer.h"
34 #include "SVGAngle.h"
35 #include "SVGLength.h"
36 #include "SVGMatrix.h"
37 #include "SVGPreserveAspectRatio.h"
38 #include "SVGTransform.h"
39 #include "SVGZoomEvent.h"
40 #include "TextStream.h"
41
42 namespace WebCore {
43
44 using namespace HTMLNames;
45 using namespace EventNames;
46
47 SVGSVGElement::SVGSVGElement(const QualifiedName& tagName, Document* doc)
48     : SVGStyledLocatableElement(tagName, doc)
49     , SVGTests()
50     , SVGLangSpace()
51     , SVGExternalResourcesRequired()
52     , SVGFitToViewBox()
53     , SVGZoomAndPan()
54     , m_useCurrentView(false)
55     , m_timeScheduler(new TimeScheduler(doc))
56 {
57     const SVGElement* viewport = ownerDocument()->documentElement() == this ? this : viewportElement();
58     const SVGStyledElement* context = ownerDocument()->documentElement() == this ? 0 : this;
59
60     m_x = new SVGLength(context, LM_WIDTH, viewport);
61     m_y = new SVGLength(context, LM_HEIGHT, viewport);
62     m_width = new SVGLength(context, LM_WIDTH, viewport);
63     m_height = new SVGLength(context, LM_HEIGHT, viewport);
64
65     m_width->setValueAsString("100%");
66     m_height->setValueAsString("100%");
67 }
68
69 SVGSVGElement::~SVGSVGElement()
70 {
71     delete m_timeScheduler;
72 }
73
74 ANIMATED_PROPERTY_DEFINITIONS(SVGSVGElement, SVGLength*, Length, length, X, x, SVGNames::xAttr.localName(), m_x.get())
75 ANIMATED_PROPERTY_DEFINITIONS(SVGSVGElement, SVGLength*, Length, length, Y, y, SVGNames::yAttr.localName(), m_y.get())
76 ANIMATED_PROPERTY_DEFINITIONS(SVGSVGElement, SVGLength*, Length, length, Width, width, SVGNames::widthAttr.localName(), m_width.get())
77 ANIMATED_PROPERTY_DEFINITIONS(SVGSVGElement, SVGLength*, Length, length, Height, height, SVGNames::heightAttr.localName(), m_height.get())
78
79 AtomicString SVGSVGElement::contentScriptType() const
80 {
81     return tryGetAttribute("contentScriptType", "text/ecmascript");
82 }
83
84 void SVGSVGElement::setContentScriptType(const AtomicString& type)
85 {
86     setAttribute(SVGNames::contentScriptTypeAttr, type);
87 }
88
89 AtomicString SVGSVGElement::contentStyleType() const
90 {
91     return tryGetAttribute("contentStyleType", "text/css");
92 }
93
94 void SVGSVGElement::setContentStyleType(const AtomicString& type)
95 {
96     setAttribute(SVGNames::contentStyleTypeAttr, type);
97 }
98
99 FloatRect SVGSVGElement::viewport() const
100 {
101     double _x = x()->value();
102     double _y = y()->value();
103     double w = width()->value();
104     double h = height()->value();
105     RefPtr<SVGMatrix> viewBox = viewBoxToViewTransform(w, h);
106     viewBox->matrix().map(_x, _y, &_x, &_y);
107     viewBox->matrix().map(w, h, &w, &h);
108     return FloatRect(_x, _y, w, h);
109 }
110
111 float SVGSVGElement::pixelUnitToMillimeterX() const
112 {
113     // FIXME: Implement me (see bug 11273)
114     return .28;
115 }
116
117 float SVGSVGElement::pixelUnitToMillimeterY() const
118 {
119     // FIXME: Implement me (see bug 11273)
120     return .28;
121 }
122
123 float SVGSVGElement::screenPixelToMillimeterX() const
124 {
125     return pixelUnitToMillimeterX();
126 }
127
128 float SVGSVGElement::screenPixelToMillimeterY() const
129 {
130     return pixelUnitToMillimeterY();
131 }
132
133 bool SVGSVGElement::useCurrentView() const
134 {
135     return m_useCurrentView;
136 }
137
138 void SVGSVGElement::setUseCurrentView(bool currentView)
139 {
140     m_useCurrentView = currentView;
141 }
142
143 float SVGSVGElement::currentScale() const
144 {
145     // FIXME: Return the current zoom/scale value (see bug 11272)
146     return 1.;
147 }
148
149 void SVGSVGElement::setCurrentScale(float scale)
150 {
151     // FIXME: Set the current zoom/scale value (see bug 11272)
152 }
153
154 FloatPoint SVGSVGElement::currentTranslate() const
155 {
156     // FIXME: Return the current pan/translate value (see bug 11272)
157     return FloatPoint();
158 }
159
160 void SVGSVGElement::addSVGWindowEventListner(const AtomicString& eventType, const Attribute* attr)
161 {
162     // FIXME: None of these should be window events long term.
163     // Once we propertly support SVGLoad, etc.
164     RefPtr<EventListener> listener = document()->accessSVGExtensions()->
165         createSVGEventListener(attr->localName().domString(), attr->value(), this);
166     document()->setHTMLWindowEventListener(eventType, listener.release());
167 }
168
169 void SVGSVGElement::parseMappedAttribute(MappedAttribute* attr)
170 {
171     const AtomicString& value = attr->value();
172     if (!nearestViewportElement()) {
173         // Only handle events if we're the outermost <svg> element
174         if (attr->name() == onunloadAttr)
175             addSVGWindowEventListner(unloadEvent, attr);
176         else if (attr->name() == onabortAttr)
177             addSVGWindowEventListner(abortEvent, attr);
178         else if (attr->name() == onerrorAttr)
179             addSVGWindowEventListner(errorEvent, attr);
180         else if (attr->name() == onresizeAttr)
181             addSVGWindowEventListner(resizeEvent, attr);
182         else if (attr->name() == onscrollAttr)
183             addSVGWindowEventListner(scrollEvent, attr);
184         else if (attr->name() == SVGNames::onzoomAttr)
185             addSVGWindowEventListner(zoomEvent, attr);
186     }
187     if (attr->name() == SVGNames::xAttr) {
188         xBaseValue()->setValueAsString(value);
189     } else if (attr->name() == SVGNames::yAttr) {
190         yBaseValue()->setValueAsString(value);
191     } else if (attr->name() == SVGNames::widthAttr) {
192         widthBaseValue()->setValueAsString(value);
193         addCSSProperty(attr, CSS_PROP_WIDTH, value);
194     } else if (attr->name() == SVGNames::heightAttr) {
195         heightBaseValue()->setValueAsString(value);
196         addCSSProperty(attr, CSS_PROP_HEIGHT, value);
197     } else {
198         if (SVGTests::parseMappedAttribute(attr))
199             return;
200         if (SVGLangSpace::parseMappedAttribute(attr))
201             return;
202         if (SVGExternalResourcesRequired::parseMappedAttribute(attr))
203             return;
204         if (SVGFitToViewBox::parseMappedAttribute(attr) && renderer())
205             static_cast<RenderSVGContainer*>(renderer())->setViewBox(viewBox());
206         if (SVGZoomAndPan::parseMappedAttribute(attr))
207             return;
208
209         SVGStyledLocatableElement::parseMappedAttribute(attr);
210     }
211 }
212
213 unsigned long SVGSVGElement::suspendRedraw(unsigned long /* max_wait_milliseconds */)
214 {
215     // FIXME: Implement me (see bug 11275)
216     return 0;
217 }
218
219 void SVGSVGElement::unsuspendRedraw(unsigned long /* suspend_handle_id */, ExceptionCode& ec)
220 {
221     // if suspend_handle_id is not found, throw exception
222     // FIXME: Implement me (see bug 11275)
223 }
224
225 void SVGSVGElement::unsuspendRedrawAll()
226 {
227     // FIXME: Implement me (see bug 11275)
228 }
229
230 void SVGSVGElement::forceRedraw()
231 {
232     // FIXME: Implement me (see bug 11275)
233 }
234
235 NodeList* SVGSVGElement::getIntersectionList(const FloatRect& rect, SVGElement*)
236 {
237     // FIXME: Implement me (see bug 11274)
238     return 0;
239 }
240
241 NodeList* SVGSVGElement::getEnclosureList(const FloatRect& rect, SVGElement*)
242 {
243     // FIXME: Implement me (see bug 11274)
244     return 0;
245 }
246
247 bool SVGSVGElement::checkIntersection(SVGElement* element, const FloatRect& rect)
248 {
249     // TODO : take into account pointer-events?
250     // FIXME: Why is element ignored??
251     // FIXME: Implement me (see bug 11274)
252     return rect.intersects(getBBox());
253 }
254
255 bool SVGSVGElement::checkEnclosure(SVGElement* element, const FloatRect& rect)
256 {
257     // TODO : take into account pointer-events?
258     // FIXME: Why is element ignored??
259     // FIXME: Implement me (see bug 11274)
260     return rect.contains(getBBox());
261 }
262
263 void SVGSVGElement::deselectAll()
264 {
265     // FIXME: Implement me (see bug 11275)
266 }
267
268 float SVGSVGElement::createSVGNumber()
269 {
270     return 0;
271 }
272
273 SVGLength* SVGSVGElement::createSVGLength()
274 {
275     return new SVGLength(0);
276 }
277
278 SVGAngle* SVGSVGElement::createSVGAngle()
279 {
280     return new SVGAngle(0);
281 }
282
283 FloatPoint SVGSVGElement::createSVGPoint()
284 {
285     return FloatPoint();
286 }
287
288 SVGMatrix* SVGSVGElement::createSVGMatrix()
289 {
290     return new SVGMatrix();
291 }
292
293 FloatRect SVGSVGElement::createSVGRect()
294 {
295     return FloatRect();
296 }
297
298 SVGTransform* SVGSVGElement::createSVGTransform()
299 {
300     return new SVGTransform();
301 }
302
303 SVGTransform* SVGSVGElement::createSVGTransformFromMatrix(SVGMatrix* matrix)
304 {    
305     SVGTransform* obj = SVGSVGElement::createSVGTransform();
306     obj->setMatrix(matrix);
307     return obj;
308 }
309
310 SVGMatrix* SVGSVGElement::getCTM() const
311 {
312     SVGMatrix* mat = createSVGMatrix();
313     if (mat) {
314         mat->translate(x()->value(), y()->value());
315
316         if (attributes()->getNamedItem(SVGNames::viewBoxAttr)) {
317             RefPtr<SVGMatrix> viewBox = viewBoxToViewTransform(width()->value(), height()->value());
318             mat->multiply(viewBox.get());
319         }
320     }
321
322     return mat;
323 }
324
325 SVGMatrix* SVGSVGElement::getScreenCTM() const
326 {
327     SVGMatrix* mat = SVGStyledLocatableElement::getScreenCTM();
328     if (mat) {
329         mat->translate(x()->value(), y()->value());
330
331         if (attributes()->getNamedItem(SVGNames::viewBoxAttr)) {
332             RefPtr<SVGMatrix> viewBox = viewBoxToViewTransform(width()->value(), height()->value());
333             mat->multiply(viewBox.get());
334         }
335     }
336
337     return mat;
338 }
339
340 RenderObject* SVGSVGElement::createRenderer(RenderArena* arena, RenderStyle*)
341 {
342     RenderSVGContainer* rootContainer = new (arena) RenderSVGContainer(this);
343
344     // FIXME: All this setup should be done after attributesChanged, not here.
345     rootContainer->setViewBox(viewBox());
346     rootContainer->setAlign(KCAlign(preserveAspectRatio()->align() - 1));
347     rootContainer->setSlice(preserveAspectRatio()->meetOrSlice() == SVGPreserveAspectRatio::SVG_MEETORSLICE_SLICE);
348     
349     return rootContainer;
350 }
351
352 void SVGSVGElement::insertedIntoDocument()
353 {
354     document()->accessSVGExtensions()->addTimeContainer(this);
355     SVGStyledLocatableElement::insertedIntoDocument();
356 }
357
358 void SVGSVGElement::removedFromDocument()
359 {
360     document()->accessSVGExtensions()->removeTimeContainer(this);
361     SVGStyledLocatableElement::removedFromDocument();
362 }
363
364 void SVGSVGElement::setZoomAndPan(unsigned short zoomAndPan)
365 {
366     SVGZoomAndPan::setZoomAndPan(zoomAndPan);
367     //canvasView()->enableZoomAndPan(zoomAndPan == SVG_ZOOMANDPAN_MAGNIFY);
368 }
369
370 void SVGSVGElement::pauseAnimations()
371 {
372     if (!m_timeScheduler->animationsPaused())
373         m_timeScheduler->toggleAnimations();
374 }
375
376 void SVGSVGElement::unpauseAnimations()
377 {
378     if (m_timeScheduler->animationsPaused())
379         m_timeScheduler->toggleAnimations();
380 }
381
382 bool SVGSVGElement::animationsPaused() const
383 {
384     return m_timeScheduler->animationsPaused();
385 }
386
387 float SVGSVGElement::getCurrentTime() const
388 {
389     return m_timeScheduler->elapsed();
390 }
391
392 void SVGSVGElement::setCurrentTime(float /* seconds */)
393 {
394     // FIXME: Implement me
395 }
396
397 void SVGSVGElement::attributeChanged(Attribute* attr, bool preserveDecls)
398 {
399     if (attr->name() == SVGNames::xAttr ||
400         attr->name() == SVGNames::yAttr ||
401         attr->name() == SVGNames::widthAttr ||
402         attr->name() == SVGNames::heightAttr)
403         if (renderer())
404             renderer()->setNeedsLayout(true);
405
406     SVGStyledElement::attributeChanged(attr, preserveDecls);
407 }
408
409 }
410
411 // vim:ts=4:noet
412 #endif // SVG_SUPPORT
413