Reviewed by Darin
[WebKit-https.git] / WebCore / ksvg2 / svg / SVGLocatable.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 "SVGLocatable.h"
26
27 #include "RenderPath.h"
28 #include "SVGMatrix.h"
29 #include "SVGSVGElement.h"
30
31 namespace WebCore {
32
33 SVGLocatable::SVGLocatable()
34 {
35 }
36
37 SVGLocatable::~SVGLocatable()
38 {
39 }
40
41 SVGElement* SVGLocatable::nearestViewportElement(const SVGStyledElement* e)
42 {
43     Node* n = e->parentNode();
44     while (n && !n->isDocumentNode()) {
45         if (n->hasTagName(SVGNames::svgTag) || n->hasTagName(SVGNames::symbolTag) ||
46             n->hasTagName(SVGNames::imageTag) || n->hasTagName(SVGNames::foreignObjectTag))
47             return static_cast<SVGElement*>(n);
48
49         n = n->parentNode();
50     }
51
52     return 0;
53 }
54
55 SVGElement* SVGLocatable::farthestViewportElement(const SVGStyledElement* e)
56 {
57     // FIXME : likely this will be always the <svg> farthest away.
58     // If we have a different implementation of documentElement(), one
59     // that give the documentElement() of the svg fragment, it could be
60     // used instead. This depends on cdf demands though(Rob.)
61     SVGElement* farthest = 0;
62     Node* n = e->parentNode();
63     while (n && !n->isDocumentNode()) {
64         if (n->hasTagName(SVGNames::svgTag) || n->hasTagName(SVGNames::symbolTag) ||
65             n->hasTagName(SVGNames::imageTag) || n->hasTagName(SVGNames::foreignObjectTag))
66             farthest = static_cast<SVGElement*>(n);
67
68         n = n->parentNode();
69     }
70
71     return farthest;
72 }
73
74 // Spec:
75 // http://www.w3.org/TR/2005/WD-SVGMobile12-20050413/svgudom.html#svg::SVGLocatable
76 FloatRect SVGLocatable::getBBox(const SVGStyledElement* e)
77 {
78     FloatRect bboxRect;
79     
80     if (e && e->renderer()) {
81         bboxRect = e->renderer()->relativeBBox(false);
82         bboxRect.setSize(bboxRect.size() - FloatSize(1, 1)); // FIXME: Why -1 here?
83     }
84
85     return bboxRect;
86 }
87
88 SVGMatrix* SVGLocatable::getCTM(const SVGElement* element)
89 {
90     if (!element)
91         return 0;
92
93     SVGMatrix* ctm = SVGSVGElement::createSVGMatrix();
94
95     Node* parent = element->parentNode();
96     if (parent && parent->isElementNode()) {
97         SVGElement* parentElement = svg_dynamic_cast(parent);
98         if (parentElement && parentElement->isStyledLocatable()) {
99             RefPtr<SVGMatrix> parentCTM = static_cast<SVGStyledLocatableElement*>(parentElement)->getCTM();
100             ctm->multiply(parentCTM.get());
101         }
102     }
103
104     return ctm;
105 }
106
107 SVGMatrix* SVGLocatable::getScreenCTM(const SVGElement* element)
108 {
109     if (!element)
110         return 0;
111
112     SVGMatrix* ctm = SVGSVGElement::createSVGMatrix();
113
114     Node* parent = element->parentNode();
115     if (parent && parent->isElementNode()) {
116         SVGElement* parentElement = static_cast<SVGElement*>(parent);
117         if (parentElement->isStyledLocatable()) {
118             RefPtr<SVGMatrix> parentCTM = static_cast<SVGStyledLocatableElement*>(parentElement)->getScreenCTM();
119             ctm->multiply(parentCTM.get());
120         }
121     }
122
123     return ctm;
124 }
125
126 SVGMatrix* SVGLocatable::getTransformToElement(SVGElement* target, ExceptionCode& ec) const
127 {
128     RefPtr<SVGMatrix> startctm(getCTM());
129     SVGMatrix* ctm = SVGSVGElement::createSVGMatrix();
130     ctm->multiply(startctm.get());
131
132     SVGElement* targetElement = svg_dynamic_cast(target);
133     if (targetElement && targetElement->isStyledLocatable()) {
134         RefPtr<SVGMatrix> targetCTM = static_cast<SVGStyledLocatableElement*>(targetElement)->getCTM();
135         targetCTM.get()->inverse(ec);
136         if (ec)
137             return ctm;
138         ctm->postMultiply(targetCTM.get());
139     }
140
141     return ctm;
142 }
143
144 }
145
146 #endif // SVG_SUPPORT
147
148 // vim:ts=4:noet