1 /* 2 * Copyright (C) 2004, 2005, 2008 Nikolas Zimmermann <zimmermann (at) kde.org> 3 * Copyright (C) 2004, 2005, 2006 Rob Buis <buis (at) 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 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 42 SVGStyledTransformableElement::~SVGStyledTransformableElement() 43 { 44 } 45 46 AffineTransform SVGStyledTransformableElement::getCTM(StyleUpdateStrategy styleUpdateStrategy) const 47 { 48 return SVGLocatable::computeCTM(this, SVGLocatable::NearestViewportScope, styleUpdateStrategy); 49 } 50 51 AffineTransform SVGStyledTransformableElement::getScreenCTM(StyleUpdateStrategy styleUpdateStrategy) const 52 { 53 return SVGLocatable::computeCTM(this, SVGLocatable::ScreenScope, styleUpdateStrategy); 54 } 55 56 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 65 AffineTransform* SVGStyledTransformableElement::supplementalTransform() 66 { 67 if (!m_supplementalTransform) 68 m_supplementalTransform.set(new AffineTransform()); 69 return m_supplementalTransform.get(); 70 } 71 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 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 99 void SVGStyledTransformableElement::synchronizeProperty(const QualifiedName& attrName) 100 { 101 SVGStyledLocatableElement::synchronizeProperty(attrName); 102 103 if (attrName == anyQName() || SVGTransformable::isKnownAttribute(attrName)) 104 synchronizeTransform(); 105 } 106 107 bool SVGStyledTransformableElement::isKnownAttribute(const QualifiedName& attrName) 108 { 109 return SVGTransformable::isKnownAttribute(attrName) || SVGStyledLocatableElement::isKnownAttribute(attrName); 110 } 111 112 SVGElement* SVGStyledTransformableElement::nearestViewportElement() const 113 { 114 return SVGTransformable::nearestViewportElement(this); 115 } 116 117 SVGElement* SVGStyledTransformableElement::farthestViewportElement() const 118 { 119 return SVGTransformable::farthestViewportElement(this); 120 } 121 122 FloatRect SVGStyledTransformableElement::getBBox(StyleUpdateStrategy styleUpdateStrategy) const 123 { 124 return SVGTransformable::getBBox(this, styleUpdateStrategy); 125 } 126 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 133 void SVGStyledTransformableElement::fillPassedAttributeToPropertyTypeMap(AttributeToPropertyTypeMap& attributeToPropertyTypeMap) 134 { 135 SVGStyledElement::fillPassedAttributeToPropertyTypeMap(attributeToPropertyTypeMap); 136 137 attributeToPropertyTypeMap.set(SVGNames::transformAttr, AnimatedTransformList); 138 } 139 140 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