260e90f4509ee78a5ae542ceafd2dd20dc113304
[WebKit-https.git] / WebCore / ksvg2 / svg / SVGSVGElement.cpp
1 /*
2     Copyright (C) 2004, 2005 Nikolas Zimmermann <wildfox@kde.org>
3                   2004, 2005 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 "KCanvasRenderingStyle.h"
33 #include "KSVGTimeScheduler.h"
34 #include "SVGAngle.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"
41 #include "ksvg.h"
42 #include <kcanvas/RenderSVGContainer.h>
43 #include <kcanvas/device/KRenderingDevice.h>
44 #include "TextStream.h"
45
46 namespace WebCore {
47
48 using namespace HTMLNames;
49 using namespace EventNames;
50
51 SVGSVGElement::SVGSVGElement(const QualifiedName& tagName, Document *doc)
52     : SVGStyledLocatableElement(tagName, doc)
53     , SVGTests()
54     , SVGLangSpace()
55     , SVGExternalResourcesRequired()
56     , SVGFitToViewBox()
57     , SVGZoomAndPan()
58     , m_useCurrentView(false)
59     , m_timeScheduler(new TimeScheduler(doc))
60 {
61     const SVGElement* viewport = ownerDocument()->documentElement() == this ? this : viewportElement();
62     const SVGStyledElement* context = ownerDocument()->documentElement() == this ? 0 : this;
63
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);
68
69     m_width->setValueAsString("100%");
70     m_height->setValueAsString("100%");
71 }
72
73 SVGSVGElement::~SVGSVGElement()
74 {
75     delete m_timeScheduler;
76 }
77
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())
82
83 AtomicString SVGSVGElement::contentScriptType() const
84 {
85     return tryGetAttribute("contentScriptType", "text/ecmascript");
86 }
87
88 void SVGSVGElement::setContentScriptType(const AtomicString& type)
89 {
90     setAttribute(SVGNames::contentScriptTypeAttr, type);
91 }
92
93 AtomicString SVGSVGElement::contentStyleType() const
94 {
95     return tryGetAttribute("contentStyleType", "text/css");
96 }
97
98 void SVGSVGElement::setContentStyleType(const AtomicString& type)
99 {
100     setAttribute(SVGNames::contentStyleTypeAttr, type);
101 }
102
103 FloatRect SVGSVGElement::viewport() const
104 {
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);
113 }
114
115 float SVGSVGElement::pixelUnitToMillimeterX() const
116 {
117 #if 0
118     if(ownerDocument() && ownerDocument()->paintDeviceMetrics())
119     {
120         Q3PaintDeviceMetrics *metrics = ownerDocument()->paintDeviceMetrics();
121         return float(metrics->widthMM()) / float(metrics->width());
122     }
123 #endif
124
125     return .28;
126 }
127
128 float SVGSVGElement::pixelUnitToMillimeterY() const
129 {
130 #if 0
131     if(ownerDocument() && ownerDocument()->paintDeviceMetrics())
132     {
133         Q3PaintDeviceMetrics *metrics = ownerDocument()->paintDeviceMetrics();
134         return float(metrics->heightMM()) / float(metrics->height());
135     }
136 #endif
137
138     return .28;
139 }
140
141 float SVGSVGElement::screenPixelToMillimeterX() const
142 {
143     return pixelUnitToMillimeterX();
144 }
145
146 float SVGSVGElement::screenPixelToMillimeterY() const
147 {
148     return pixelUnitToMillimeterY();
149 }
150
151 bool SVGSVGElement::useCurrentView() const
152 {
153     return m_useCurrentView;
154 }
155
156 void SVGSVGElement::setUseCurrentView(bool currentView)
157 {
158     m_useCurrentView = currentView;
159 }
160
161 float SVGSVGElement::currentScale() const
162 {
163     //if(!canvasView())
164         return 1.;
165
166     //return canvasView()->zoom();
167 }
168
169 void SVGSVGElement::setCurrentScale(float scale)
170 {
171 //    if(canvasView())
172 //    {
173 //        float oldzoom = canvasView()->zoom();
174 //        canvasView()->setZoom(scale);
175 //        document()->dispatchZoomEvent(oldzoom, scale);
176 //    }
177 }
178
179 FloatPoint SVGSVGElement::currentTranslate() const
180 {
181     //if(!view())
182         return FloatPoint();
183
184     //return createSVGPoint(canvasView()->pan());
185 }
186
187 void SVGSVGElement::addSVGWindowEventListner(const AtomicString& eventType, const Attribute* attr)
188 {
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());
194 }
195
196 void SVGSVGElement::parseMappedAttribute(MappedAttribute *attr)
197 {
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);
213     }
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);
224     } else {
225         if (SVGTests::parseMappedAttribute(attr))
226             return;
227         if (SVGLangSpace::parseMappedAttribute(attr))
228             return;
229         if (SVGExternalResourcesRequired::parseMappedAttribute(attr))
230             return;
231         if (SVGFitToViewBox::parseMappedAttribute(attr) && renderer())
232             static_cast<RenderSVGContainer*>(renderer())->setViewBox(viewBox());
233         if (SVGZoomAndPan::parseMappedAttribute(attr))
234             return;
235
236         SVGStyledLocatableElement::parseMappedAttribute(attr);
237     }
238 }
239
240 unsigned long SVGSVGElement::suspendRedraw(unsigned long /* max_wait_milliseconds */)
241 {
242     // TODO
243     return 0;
244 }
245
246 void SVGSVGElement::unsuspendRedraw(unsigned long /* suspend_handle_id */, ExceptionCode& ec)
247 {
248     // if suspend_handle_id is not found, throw exception
249     // TODO
250 }
251
252 void SVGSVGElement::unsuspendRedrawAll()
253 {
254     // TODO
255 }
256
257 void SVGSVGElement::forceRedraw()
258 {
259     // TODO
260 }
261
262 NodeList *SVGSVGElement::getIntersectionList(const FloatRect& rect, SVGElement*)
263 {
264     //NodeList *list;
265     // TODO
266     return 0;
267 }
268
269 NodeList *SVGSVGElement::getEnclosureList(const FloatRect& rect, SVGElement*)
270 {
271     // TODO
272     return 0;
273 }
274
275 bool SVGSVGElement::checkIntersection(SVGElement* element, const FloatRect& rect)
276 {
277     // TODO : take into account pointer-events?
278     // FIXME: Why is element ignored??
279     return rect.intersects(getBBox());
280 }
281
282 bool SVGSVGElement::checkEnclosure(SVGElement* element, const FloatRect& rect)
283 {
284     // TODO : take into account pointer-events?
285     // FIXME: Why is element ignored??
286     return rect.contains(getBBox());
287 }
288
289 void SVGSVGElement::deselectAll()
290 {
291     // TODO
292 }
293
294 float SVGSVGElement::createSVGNumber()
295 {
296     return 0;
297 }
298
299 SVGLength *SVGSVGElement::createSVGLength()
300 {
301     return new SVGLength(0);
302 }
303
304 SVGAngle *SVGSVGElement::createSVGAngle()
305 {
306     return new SVGAngle(0);
307 }
308
309 FloatPoint SVGSVGElement::createSVGPoint(const IntPoint &p)
310 {
311     return FloatPoint(p);
312 }
313
314 SVGMatrix *SVGSVGElement::createSVGMatrix()
315 {
316     return new SVGMatrix();
317 }
318
319 FloatRect SVGSVGElement::createSVGRect()
320 {
321     return FloatRect();
322 }
323
324 SVGTransform *SVGSVGElement::createSVGTransform()
325 {
326     return new SVGTransform();
327 }
328
329 SVGTransform *SVGSVGElement::createSVGTransformFromMatrix(SVGMatrix *matrix)
330 {    
331     SVGTransform *obj = SVGSVGElement::createSVGTransform();
332     obj->setMatrix(matrix);
333     return obj;
334 }
335
336 SVGMatrix *SVGSVGElement::getCTM() const
337 {
338     SVGMatrix *mat = createSVGMatrix();
339     if(mat)
340     {
341         mat->translate(x()->value(), y()->value());
342
343         if(attributes()->getNamedItem(SVGNames::viewBoxAttr))
344         {
345             RefPtr<SVGMatrix> viewBox = viewBoxToViewTransform(width()->value(), height()->value());
346             mat->multiply(viewBox.get());
347         }
348     }
349
350     return mat;
351 }
352
353 SVGMatrix *SVGSVGElement::getScreenCTM() const
354 {
355     SVGMatrix *mat = SVGStyledLocatableElement::getScreenCTM();
356     if(mat) {
357         mat->translate(x()->value(), y()->value());
358
359         if (attributes()->getNamedItem(SVGNames::viewBoxAttr)) {
360             RefPtr<SVGMatrix> viewBox = viewBoxToViewTransform(width()->value(), height()->value());
361             mat->multiply(viewBox.get());
362         }
363     }
364
365     return mat;
366 }
367
368 RenderObject* SVGSVGElement::createRenderer(RenderArena* arena, RenderStyle*)
369 {
370     RenderSVGContainer* rootContainer = new (arena) RenderSVGContainer(this);
371
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);
377     
378     return rootContainer;
379 }
380
381 void SVGSVGElement::insertedIntoDocument()
382 {
383     document()->accessSVGExtensions()->addTimeContainer(this);
384     SVGStyledLocatableElement::insertedIntoDocument();
385 }
386
387 void SVGSVGElement::removedFromDocument()
388 {
389     document()->accessSVGExtensions()->removeTimeContainer(this);
390     SVGStyledLocatableElement::removedFromDocument();
391 }
392
393 void SVGSVGElement::setZoomAndPan(unsigned short zoomAndPan)
394 {
395     SVGZoomAndPan::setZoomAndPan(zoomAndPan);
396     //canvasView()->enableZoomAndPan(zoomAndPan == SVG_ZOOMANDPAN_MAGNIFY);
397 }
398
399 void SVGSVGElement::pauseAnimations()
400 {
401     if (!m_timeScheduler->animationsPaused())
402         m_timeScheduler->toggleAnimations();
403 }
404
405 void SVGSVGElement::unpauseAnimations()
406 {
407     if (m_timeScheduler->animationsPaused())
408         m_timeScheduler->toggleAnimations();
409 }
410
411 bool SVGSVGElement::animationsPaused() const
412 {
413     return m_timeScheduler->animationsPaused();
414 }
415
416 float SVGSVGElement::getCurrentTime() const
417 {
418     return m_timeScheduler->elapsed();
419 }
420
421 void SVGSVGElement::setCurrentTime(float /* seconds */)
422 {
423     // TODO
424 }
425
426 }
427
428 // vim:ts=4:noet
429 #endif // SVG_SUPPORT
430