Reviewed by Mitz.
[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         // Need this to make sure we have render object dimensions.
82         // See bug 11686.
83         e->document()->updateLayoutIgnorePendingStylesheets();
84         bboxRect = e->renderer()->relativeBBox(false);
85         bboxRect.setSize(bboxRect.size() - FloatSize(1, 1)); // FIXME: Why -1 here?
86     }
87
88     return bboxRect;
89 }
90
91 SVGMatrix* SVGLocatable::getCTM(const SVGElement* element)
92 {
93     if (!element)
94         return 0;
95
96     SVGMatrix* ctm = SVGSVGElement::createSVGMatrix();
97
98     Node* parent = element->parentNode();
99     if (parent && parent->isElementNode()) {
100         SVGElement* parentElement = svg_dynamic_cast(parent);
101         if (parentElement && parentElement->isStyledLocatable()) {
102             RefPtr<SVGMatrix> parentCTM = static_cast<SVGStyledLocatableElement*>(parentElement)->getCTM();
103             ctm->multiply(parentCTM.get());
104         }
105     }
106
107     return ctm;
108 }
109
110 SVGMatrix* SVGLocatable::getScreenCTM(const SVGElement* element)
111 {
112     if (!element)
113         return 0;
114
115     SVGMatrix* ctm = SVGSVGElement::createSVGMatrix();
116
117     Node* parent = element->parentNode();
118     if (parent && parent->isElementNode()) {
119         SVGElement* parentElement = static_cast<SVGElement*>(parent);
120         if (parentElement->isStyledLocatable()) {
121             RefPtr<SVGMatrix> parentCTM = static_cast<SVGStyledLocatableElement*>(parentElement)->getScreenCTM();
122             ctm->multiply(parentCTM.get());
123         }
124     }
125
126     return ctm;
127 }
128
129 SVGMatrix* SVGLocatable::getTransformToElement(SVGElement* target, ExceptionCode& ec) const
130 {
131     RefPtr<SVGMatrix> startctm(getCTM());
132     SVGMatrix* ctm = SVGSVGElement::createSVGMatrix();
133     ctm->multiply(startctm.get());
134
135     SVGElement* targetElement = svg_dynamic_cast(target);
136     if (targetElement && targetElement->isStyledLocatable()) {
137         RefPtr<SVGMatrix> targetCTM = static_cast<SVGStyledLocatableElement*>(targetElement)->getCTM();
138         targetCTM.get()->inverse(ec);
139         if (ec)
140             return ctm;
141         ctm->postMultiply(targetCTM.get());
142     }
143
144     return ctm;
145 }
146
147 }
148
149 #endif // SVG_SUPPORT
150
151 // vim:ts=4:noet