1 /* 2 * Copyright (C) 2004, 2005, 2008 Nikolas Zimmermann <zimmermann (at) kde.org> 3 * Copyright (C) 2004, 2005, 2006, 2007, 2008 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 "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 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 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 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 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 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 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 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 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