1 /*
2  * Copyright (C) 2004, 2005, 2008 Nikolas Zimmermann <zimmermann@kde.org>
3  * Copyright (C) 2004, 2005, 2006 Rob Buis <buis@kde.org>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public License
16  * along with this library; see the file COPYING.LIB.  If not, write to
17  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20 
21 #include "config.h"
22 
23 #if ENABLE(SVG)
24 #include "SVGStyledTransformableElement.h"
25 
26 #include "AffineTransform.h"
27 #include "Attribute.h"
28 #include "RenderSVGPath.h"
29 #include "RenderSVGResource.h"
30 #include "SVGNames.h"
31 
32 namespace WebCore {
33 
34 // Animated property definitions
DEFINE_ANIMATED_TRANSFORM_LIST(SVGStyledTransformableElement,SVGNames::transformAttr,Transform,transform)35 DEFINE_ANIMATED_TRANSFORM_LIST(SVGStyledTransformableElement, SVGNames::transformAttr, Transform, transform)
36 
37 SVGStyledTransformableElement::SVGStyledTransformableElement(const QualifiedName& tagName, Document* document)
38     : SVGStyledLocatableElement(tagName, document)
39 {
40 }
41 
~SVGStyledTransformableElement()42 SVGStyledTransformableElement::~SVGStyledTransformableElement()
43 {
44 }
45 
getCTM(StyleUpdateStrategy styleUpdateStrategy) const46 AffineTransform SVGStyledTransformableElement::getCTM(StyleUpdateStrategy styleUpdateStrategy) const
47 {
48     return SVGLocatable::computeCTM(this, SVGLocatable::NearestViewportScope, styleUpdateStrategy);
49 }
50 
getScreenCTM(StyleUpdateStrategy styleUpdateStrategy) const51 AffineTransform SVGStyledTransformableElement::getScreenCTM(StyleUpdateStrategy styleUpdateStrategy) const
52 {
53     return SVGLocatable::computeCTM(this, SVGLocatable::ScreenScope, styleUpdateStrategy);
54 }
55 
animatedLocalTransform() const56 AffineTransform SVGStyledTransformableElement::animatedLocalTransform() const
57 {
58     AffineTransform matrix;
59     transform().concatenate(matrix);
60     if (m_supplementalTransform)
61         matrix *= *m_supplementalTransform;
62     return matrix;
63 }
64 
supplementalTransform()65 AffineTransform* SVGStyledTransformableElement::supplementalTransform()
66 {
67     if (!m_supplementalTransform)
68         m_supplementalTransform = adoptPtr(new AffineTransform);
69     return m_supplementalTransform.get();
70 }
71 
parseMappedAttribute(Attribute * attr)72 void SVGStyledTransformableElement::parseMappedAttribute(Attribute* attr)
73 {
74     if (SVGTransformable::isKnownAttribute(attr->name())) {
75         SVGTransformList newList;
76         if (!SVGTransformable::parseTransformAttribute(newList, attr->value()))
77             newList.clear();
78         detachAnimatedTransformListWrappers(newList.size());
79         setTransformBaseValue(newList);
80     } else
81         SVGStyledLocatableElement::parseMappedAttribute(attr);
82 }
83 
svgAttributeChanged(const QualifiedName & attrName)84 void SVGStyledTransformableElement::svgAttributeChanged(const QualifiedName& attrName)
85 {
86     SVGStyledLocatableElement::svgAttributeChanged(attrName);
87 
88     if (!SVGStyledTransformableElement::isKnownAttribute(attrName))
89         return;
90 
91     RenderObject* object = renderer();
92     if (!object)
93         return;
94 
95     object->setNeedsTransformUpdate();
96     RenderSVGResource::markForLayoutAndParentResourceInvalidation(object);
97 }
98 
synchronizeProperty(const QualifiedName & attrName)99 void SVGStyledTransformableElement::synchronizeProperty(const QualifiedName& attrName)
100 {
101     SVGStyledLocatableElement::synchronizeProperty(attrName);
102 
103     if (attrName == anyQName() || SVGTransformable::isKnownAttribute(attrName))
104         synchronizeTransform();
105 }
106 
isKnownAttribute(const QualifiedName & attrName)107 bool SVGStyledTransformableElement::isKnownAttribute(const QualifiedName& attrName)
108 {
109     return SVGTransformable::isKnownAttribute(attrName) || SVGStyledLocatableElement::isKnownAttribute(attrName);
110 }
111 
nearestViewportElement() const112 SVGElement* SVGStyledTransformableElement::nearestViewportElement() const
113 {
114     return SVGTransformable::nearestViewportElement(this);
115 }
116 
farthestViewportElement() const117 SVGElement* SVGStyledTransformableElement::farthestViewportElement() const
118 {
119     return SVGTransformable::farthestViewportElement(this);
120 }
121 
getBBox(StyleUpdateStrategy styleUpdateStrategy) const122 FloatRect SVGStyledTransformableElement::getBBox(StyleUpdateStrategy styleUpdateStrategy) const
123 {
124     return SVGTransformable::getBBox(this, styleUpdateStrategy);
125 }
126 
createRenderer(RenderArena * arena,RenderStyle *)127 RenderObject* SVGStyledTransformableElement::createRenderer(RenderArena* arena, RenderStyle*)
128 {
129     // By default, any subclass is expected to do path-based drawing
130     return new (arena) RenderSVGPath(this);
131 }
132 
fillPassedAttributeToPropertyTypeMap(AttributeToPropertyTypeMap & attributeToPropertyTypeMap)133 void SVGStyledTransformableElement::fillPassedAttributeToPropertyTypeMap(AttributeToPropertyTypeMap& attributeToPropertyTypeMap)
134 {
135     SVGStyledElement::fillPassedAttributeToPropertyTypeMap(attributeToPropertyTypeMap);
136 
137     attributeToPropertyTypeMap.set(SVGNames::transformAttr, AnimatedTransformList);
138 }
139 
toClipPath(Path & path) const140 void SVGStyledTransformableElement::toClipPath(Path& path) const
141 {
142     toPathData(path);
143     // FIXME: How do we know the element has done a layout?
144     path.transform(animatedLocalTransform());
145 }
146 
147 }
148 
149 #endif // ENABLE(SVG)
150