1 /*
2 * Copyright (C) 2004, 2005, 2008 Nikolas Zimmermann <zimmermann@kde.org>
3 * Copyright (C) 2004, 2005, 2006, 2007, 2008 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 "SVGTextPositioningElement.h"
25
26 #include "Attribute.h"
27 #include "RenderSVGResource.h"
28 #include "RenderSVGText.h"
29 #include "SVGLengthList.h"
30 #include "SVGNames.h"
31 #include "SVGNumberList.h"
32
33 namespace WebCore {
34
35 // Animated property definitions
DEFINE_ANIMATED_LENGTH_LIST(SVGTextPositioningElement,SVGNames::xAttr,X,x)36 DEFINE_ANIMATED_LENGTH_LIST(SVGTextPositioningElement, SVGNames::xAttr, X, x)
37 DEFINE_ANIMATED_LENGTH_LIST(SVGTextPositioningElement, SVGNames::yAttr, Y, y)
38 DEFINE_ANIMATED_LENGTH_LIST(SVGTextPositioningElement, SVGNames::dxAttr, Dx, dx)
39 DEFINE_ANIMATED_LENGTH_LIST(SVGTextPositioningElement, SVGNames::dyAttr, Dy, dy)
40 DEFINE_ANIMATED_NUMBER_LIST(SVGTextPositioningElement, SVGNames::rotateAttr, Rotate, rotate)
41
42 SVGTextPositioningElement::SVGTextPositioningElement(const QualifiedName& tagName, Document* document)
43 : SVGTextContentElement(tagName, document)
44 {
45 }
46
parseMappedAttribute(Attribute * attr)47 void SVGTextPositioningElement::parseMappedAttribute(Attribute* attr)
48 {
49 if (attr->name() == SVGNames::xAttr) {
50 SVGLengthList newList;
51 newList.parse(attr->value(), LengthModeWidth);
52 detachAnimatedXListWrappers(newList.size());
53 setXBaseValue(newList);
54 } else if (attr->name() == SVGNames::yAttr) {
55 SVGLengthList newList;
56 newList.parse(attr->value(), LengthModeHeight);
57 detachAnimatedYListWrappers(newList.size());
58 setYBaseValue(newList);
59 } else if (attr->name() == SVGNames::dxAttr) {
60 SVGLengthList newList;
61 newList.parse(attr->value(), LengthModeWidth);
62 detachAnimatedDxListWrappers(newList.size());
63 setDxBaseValue(newList);
64 } else if (attr->name() == SVGNames::dyAttr) {
65 SVGLengthList newList;
66 newList.parse(attr->value(), LengthModeHeight);
67 detachAnimatedDyListWrappers(newList.size());
68 setDyBaseValue(newList);
69 } else if (attr->name() == SVGNames::rotateAttr) {
70 SVGNumberList newList;
71 newList.parse(attr->value());
72 detachAnimatedRotateListWrappers(newList.size());
73 setRotateBaseValue(newList);
74 } else
75 SVGTextContentElement::parseMappedAttribute(attr);
76 }
77
updatePositioningValuesInRenderer(RenderObject * renderer)78 static inline void updatePositioningValuesInRenderer(RenderObject* renderer)
79 {
80 RenderSVGText* textRenderer = 0;
81
82 if (renderer->isSVGText())
83 textRenderer = toRenderSVGText(renderer);
84 else {
85 // Locate RenderSVGText parent renderer.
86 RenderObject* parent = renderer->parent();
87 while (parent && !parent->isSVGText())
88 parent = parent->parent();
89
90 if (parent) {
91 ASSERT(parent->isSVGText());
92 textRenderer = toRenderSVGText(parent);
93 }
94 }
95
96 if (!textRenderer)
97 return;
98
99 textRenderer->setNeedsPositioningValuesUpdate();
100 }
101
svgAttributeChanged(const QualifiedName & attrName)102 void SVGTextPositioningElement::svgAttributeChanged(const QualifiedName& attrName)
103 {
104 SVGTextContentElement::svgAttributeChanged(attrName);
105
106 bool updateRelativeLengths = attrName == SVGNames::xAttr
107 || attrName == SVGNames::yAttr
108 || attrName == SVGNames::dxAttr
109 || attrName == SVGNames::dyAttr;
110
111 if (updateRelativeLengths)
112 updateRelativeLengthsInformation();
113
114 RenderObject* renderer = this->renderer();
115 if (!renderer)
116 return;
117
118 if (updateRelativeLengths || attrName == SVGNames::rotateAttr) {
119 updatePositioningValuesInRenderer(renderer);
120 RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer);
121 return;
122 }
123 }
124
childrenChanged(bool changedByParser,Node * beforeChange,Node * afterChange,int childCountDelta)125 void SVGTextPositioningElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
126 {
127 SVGTextContentElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta);
128
129 if (changedByParser)
130 return;
131
132 if (RenderObject* object = renderer())
133 updatePositioningValuesInRenderer(object);
134 }
135
synchronizeProperty(const QualifiedName & attrName)136 void SVGTextPositioningElement::synchronizeProperty(const QualifiedName& attrName)
137 {
138 SVGTextContentElement::synchronizeProperty(attrName);
139
140 if (attrName == anyQName()) {
141 synchronizeX();
142 synchronizeY();
143 synchronizeDx();
144 synchronizeDy();
145 synchronizeRotate();
146 return;
147 }
148
149 if (attrName == SVGNames::xAttr)
150 synchronizeX();
151 else if (attrName == SVGNames::yAttr)
152 synchronizeY();
153 else if (attrName == SVGNames::dxAttr)
154 synchronizeDx();
155 else if (attrName == SVGNames::dyAttr)
156 synchronizeDy();
157 else if (attrName == SVGNames::rotateAttr)
158 synchronizeRotate();
159 }
160
fillPassedAttributeToPropertyTypeMap(AttributeToPropertyTypeMap & attributeToPropertyTypeMap)161 void SVGTextPositioningElement::fillPassedAttributeToPropertyTypeMap(AttributeToPropertyTypeMap& attributeToPropertyTypeMap)
162 {
163 SVGTextContentElement::fillPassedAttributeToPropertyTypeMap(attributeToPropertyTypeMap);
164
165 attributeToPropertyTypeMap.set(SVGNames::xAttr, AnimatedNumberList);
166 attributeToPropertyTypeMap.set(SVGNames::yAttr, AnimatedNumberList);
167 attributeToPropertyTypeMap.set(SVGNames::dxAttr, AnimatedNumberList);
168 attributeToPropertyTypeMap.set(SVGNames::dyAttr, AnimatedNumberList);
169 attributeToPropertyTypeMap.set(SVGNames::rotateAttr, AnimatedNumberList);
170 }
171
elementFromRenderer(RenderObject * renderer)172 SVGTextPositioningElement* SVGTextPositioningElement::elementFromRenderer(RenderObject* renderer)
173 {
174 if (!renderer)
175 return 0;
176
177 if (!renderer->isSVGText() && !renderer->isSVGInline())
178 return 0;
179
180 Node* node = renderer->node();
181 ASSERT(node);
182 ASSERT(node->isSVGElement());
183
184 if (!node->hasTagName(SVGNames::textTag)
185 && !node->hasTagName(SVGNames::tspanTag)
186 #if ENABLE(SVG_FONTS)
187 && !node->hasTagName(SVGNames::altGlyphTag)
188 #endif
189 && !node->hasTagName(SVGNames::trefTag))
190 return 0;
191
192 return static_cast<SVGTextPositioningElement*>(node);
193 }
194
195 }
196
197 #endif // ENABLE(SVG)
198