1 /*
2 Copyright (C) 2004, 2005 Nikolas Zimmermann <wildfox@kde.org>
3 2004, 2005, 2006 Rob Buis <buis@kde.org>
4 Copyright (C) 2009 Google, Inc. All rights reserved.
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public License
17 along with this library; see the file COPYING.LIB. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 Boston, MA 02110-1301, USA.
20 */
21
22 #include "config.h"
23 #if ENABLE(SVG)
24
25 #include "SVGLocatable.h"
26
27 #include "AffineTransform.h"
28 #include "RenderPath.h"
29 #include "SVGException.h"
30 #include "SVGSVGElement.h"
31
32 namespace WebCore {
33
SVGLocatable()34 SVGLocatable::SVGLocatable()
35 {
36 }
37
~SVGLocatable()38 SVGLocatable::~SVGLocatable()
39 {
40 }
41
isViewportElement(Node * node)42 static bool isViewportElement(Node* node)
43 {
44 return (node->hasTagName(SVGNames::svgTag)
45 || node->hasTagName(SVGNames::symbolTag)
46 #if ENABLE(SVG_FOREIGN_OBJECT)
47 || node->hasTagName(SVGNames::foreignObjectTag)
48 #endif
49 || node->hasTagName(SVGNames::imageTag));
50 }
51
nearestViewportElement(const SVGElement * element)52 SVGElement* SVGLocatable::nearestViewportElement(const SVGElement* element)
53 {
54 ASSERT(element);
55 for (Node* n = element->parentNode(); n && !n->isDocumentNode(); n = n->parentNode()) {
56 if (isViewportElement(n))
57 return static_cast<SVGElement*>(n);
58 }
59
60 return 0;
61 }
62
farthestViewportElement(const SVGElement * element)63 SVGElement* SVGLocatable::farthestViewportElement(const SVGElement* element)
64 {
65 ASSERT(element);
66 SVGElement* farthest = 0;
67 for (Node* n = element->parentNode(); n && !n->isDocumentNode(); n = n->parentNode()) {
68 if (isViewportElement(n))
69 farthest = static_cast<SVGElement*>(n);
70 }
71 return farthest;
72 }
73
getBBox(const SVGElement * element)74 FloatRect SVGLocatable::getBBox(const SVGElement* element)
75 {
76 element->document()->updateLayoutIgnorePendingStylesheets();
77
78 // FIXME: Eventually we should support getBBox for detached elements.
79 if (!element->renderer())
80 return FloatRect();
81
82 return element->renderer()->objectBoundingBox();
83 }
84
getCTM(const SVGElement * element)85 AffineTransform SVGLocatable::getCTM(const SVGElement* element)
86 {
87 ASSERT(element);
88 AffineTransform ctm;
89
90 Node* parent = element->parentNode();
91 if (parent && parent->isSVGElement()) {
92 SVGElement* parentElement = static_cast<SVGElement*>(parent);
93 if (parentElement && parentElement->isStyledLocatable()) {
94 AffineTransform parentCTM = static_cast<SVGStyledLocatableElement*>(parentElement)->getCTM();
95 ctm = parentCTM * ctm;
96 }
97 }
98
99 return ctm;
100 }
101
getScreenCTM(const SVGElement * element)102 AffineTransform SVGLocatable::getScreenCTM(const SVGElement* element)
103 {
104 ASSERT(element);
105 AffineTransform ctm;
106
107 Node* parent = element->parentNode();
108 if (parent && parent->isSVGElement()) {
109 SVGElement* parentElement = static_cast<SVGElement*>(parent);
110 if (parentElement && parentElement->isStyledLocatable()) {
111 AffineTransform parentCTM = static_cast<SVGStyledLocatableElement*>(parentElement)->getScreenCTM();
112 ctm = parentCTM * ctm;
113 }
114 }
115
116 return ctm;
117 }
118
getTransformToElement(SVGElement * target,ExceptionCode & ec) const119 AffineTransform SVGLocatable::getTransformToElement(SVGElement* target, ExceptionCode& ec) const
120 {
121 AffineTransform ctm = getCTM();
122
123 if (target && target->isStyledLocatable()) {
124 AffineTransform targetCTM = static_cast<SVGStyledLocatableElement*>(target)->getCTM();
125 if (!targetCTM.isInvertible()) {
126 ec = SVGException::SVG_MATRIX_NOT_INVERTABLE;
127 return ctm;
128 }
129 ctm *= targetCTM.inverse();
130 }
131
132 return ctm;
133 }
134
135 }
136
137 #endif // ENABLE(SVG)
138
139 // vim:ts=4:noet
140