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#include "SVGTextPositioningElement.h" 23 24#include "Attribute.h" 25#include "RenderSVGResource.h" 26#include "RenderSVGText.h" 27#include "SVGElementInstance.h" 28#include "SVGLengthList.h" 29#include "SVGNames.h" 30#include "SVGNumberList.h" 31#include <wtf/NeverDestroyed.h> 32 33namespace WebCore { 34 35// Animated property definitions 36DEFINE_ANIMATED_LENGTH_LIST(SVGTextPositioningElement, SVGNames::xAttr, X, x) 37DEFINE_ANIMATED_LENGTH_LIST(SVGTextPositioningElement, SVGNames::yAttr, Y, y) 38DEFINE_ANIMATED_LENGTH_LIST(SVGTextPositioningElement, SVGNames::dxAttr, Dx, dx) 39DEFINE_ANIMATED_LENGTH_LIST(SVGTextPositioningElement, SVGNames::dyAttr, Dy, dy) 40DEFINE_ANIMATED_NUMBER_LIST(SVGTextPositioningElement, SVGNames::rotateAttr, Rotate, rotate) 41 42BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGTextPositioningElement) 43 REGISTER_LOCAL_ANIMATED_PROPERTY(x) 44 REGISTER_LOCAL_ANIMATED_PROPERTY(y) 45 REGISTER_LOCAL_ANIMATED_PROPERTY(dx) 46 REGISTER_LOCAL_ANIMATED_PROPERTY(dy) 47 REGISTER_LOCAL_ANIMATED_PROPERTY(rotate) 48 REGISTER_PARENT_ANIMATED_PROPERTIES(SVGTextContentElement) 49END_REGISTER_ANIMATED_PROPERTIES 50 51SVGTextPositioningElement::SVGTextPositioningElement(const QualifiedName& tagName, Document& document) 52 : SVGTextContentElement(tagName, document) 53{ 54 registerAnimatedPropertiesForSVGTextPositioningElement(); 55} 56 57bool SVGTextPositioningElement::isSupportedAttribute(const QualifiedName& attrName) 58{ 59 static NeverDestroyed<HashSet<QualifiedName>> supportedAttributes; 60 if (supportedAttributes.get().isEmpty()) { 61 supportedAttributes.get().add(SVGNames::xAttr); 62 supportedAttributes.get().add(SVGNames::yAttr); 63 supportedAttributes.get().add(SVGNames::dxAttr); 64 supportedAttributes.get().add(SVGNames::dyAttr); 65 supportedAttributes.get().add(SVGNames::rotateAttr); 66 } 67 return supportedAttributes.get().contains<SVGAttributeHashTranslator>(attrName); 68} 69 70void SVGTextPositioningElement::parseAttribute(const QualifiedName& name, const AtomicString& value) 71{ 72 if (!isSupportedAttribute(name)) { 73 SVGTextContentElement::parseAttribute(name, value); 74 return; 75 } 76 77 if (name == SVGNames::xAttr) { 78 SVGLengthList newList; 79 newList.parse(value, LengthModeWidth); 80 detachAnimatedXListWrappers(newList.size()); 81 setXBaseValue(newList); 82 return; 83 } 84 85 if (name == SVGNames::yAttr) { 86 SVGLengthList newList; 87 newList.parse(value, LengthModeHeight); 88 detachAnimatedYListWrappers(newList.size()); 89 setYBaseValue(newList); 90 return; 91 } 92 93 if (name == SVGNames::dxAttr) { 94 SVGLengthList newList; 95 newList.parse(value, LengthModeWidth); 96 detachAnimatedDxListWrappers(newList.size()); 97 setDxBaseValue(newList); 98 return; 99 } 100 101 if (name == SVGNames::dyAttr) { 102 SVGLengthList newList; 103 newList.parse(value, LengthModeHeight); 104 detachAnimatedDyListWrappers(newList.size()); 105 setDyBaseValue(newList); 106 return; 107 } 108 109 if (name == SVGNames::rotateAttr) { 110 SVGNumberList newList; 111 newList.parse(value); 112 detachAnimatedRotateListWrappers(newList.size()); 113 setRotateBaseValue(newList); 114 return; 115 } 116 117 ASSERT_NOT_REACHED(); 118} 119 120void SVGTextPositioningElement::svgAttributeChanged(const QualifiedName& attrName) 121{ 122 if (!isSupportedAttribute(attrName)) { 123 SVGTextContentElement::svgAttributeChanged(attrName); 124 return; 125 } 126 127 SVGElementInstance::InvalidationGuard invalidationGuard(this); 128 129 bool updateRelativeLengths = attrName == SVGNames::xAttr 130 || attrName == SVGNames::yAttr 131 || attrName == SVGNames::dxAttr 132 || attrName == SVGNames::dyAttr; 133 134 if (updateRelativeLengths) 135 updateRelativeLengthsInformation(); 136 137 auto renderer = this->renderer(); 138 if (!renderer) 139 return; 140 141 if (updateRelativeLengths || attrName == SVGNames::rotateAttr) { 142 if (auto* textAncestor = RenderSVGText::locateRenderSVGTextAncestor(*renderer)) 143 textAncestor->setNeedsPositioningValuesUpdate(); 144 RenderSVGResource::markForLayoutAndParentResourceInvalidation(*renderer); 145 return; 146 } 147 148 ASSERT_NOT_REACHED(); 149} 150 151SVGTextPositioningElement* SVGTextPositioningElement::elementFromRenderer(RenderObject* renderer) 152{ 153 if (!renderer) 154 return 0; 155 156 if (!renderer->isSVGText() && !renderer->isSVGInline()) 157 return 0; 158 159 Node* node = renderer->node(); 160 ASSERT(node); 161 ASSERT(node->isSVGElement()); 162 163 if (!node->hasTagName(SVGNames::textTag) 164 && !node->hasTagName(SVGNames::tspanTag) 165#if ENABLE(SVG_FONTS) 166 && !node->hasTagName(SVGNames::altGlyphTag) 167#endif 168 && !node->hasTagName(SVGNames::trefTag)) 169 return 0; 170 171 return static_cast<SVGTextPositioningElement*>(node); 172} 173 174} 175