2
* Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
3
* Copyright (C) 2010 Rob Buis <rwlbuis@gmail.com>
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.
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.
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.
24
#include "SVGTextPathElement.h"
26
#include "Attribute.h"
27
#include "NodeRenderingContext.h"
28
#include "RenderSVGResource.h"
29
#include "RenderSVGTextPath.h"
30
#include "SVGElementInstance.h"
35
// Animated property definitions
36
DEFINE_ANIMATED_LENGTH(SVGTextPathElement, SVGNames::startOffsetAttr, StartOffset, startOffset)
37
DEFINE_ANIMATED_ENUMERATION(SVGTextPathElement, SVGNames::methodAttr, Method, method, SVGTextPathMethodType)
38
DEFINE_ANIMATED_ENUMERATION(SVGTextPathElement, SVGNames::spacingAttr, Spacing, spacing, SVGTextPathSpacingType)
39
DEFINE_ANIMATED_STRING(SVGTextPathElement, XLinkNames::hrefAttr, Href, href)
41
BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGTextPathElement)
42
REGISTER_LOCAL_ANIMATED_PROPERTY(startOffset)
43
REGISTER_LOCAL_ANIMATED_PROPERTY(method)
44
REGISTER_LOCAL_ANIMATED_PROPERTY(spacing)
45
REGISTER_LOCAL_ANIMATED_PROPERTY(href)
46
REGISTER_PARENT_ANIMATED_PROPERTIES(SVGTextContentElement)
47
END_REGISTER_ANIMATED_PROPERTIES
49
inline SVGTextPathElement::SVGTextPathElement(const QualifiedName& tagName, Document* document)
50
: SVGTextContentElement(tagName, document)
51
, m_startOffset(LengthModeOther)
52
, m_method(SVGTextPathMethodAlign)
53
, m_spacing(SVGTextPathSpacingExact)
55
ASSERT(hasTagName(SVGNames::textPathTag));
56
registerAnimatedPropertiesForSVGTextPathElement();
59
PassRefPtr<SVGTextPathElement> SVGTextPathElement::create(const QualifiedName& tagName, Document* document)
61
return adoptRef(new SVGTextPathElement(tagName, document));
64
SVGTextPathElement::~SVGTextPathElement()
66
clearResourceReferences();
69
void SVGTextPathElement::clearResourceReferences()
72
document()->accessSVGExtensions()->removeAllTargetReferencesForElement(this);
75
bool SVGTextPathElement::isSupportedAttribute(const QualifiedName& attrName)
77
DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ());
78
if (supportedAttributes.isEmpty()) {
79
SVGURIReference::addSupportedAttributes(supportedAttributes);
80
supportedAttributes.add(SVGNames::startOffsetAttr);
81
supportedAttributes.add(SVGNames::methodAttr);
82
supportedAttributes.add(SVGNames::spacingAttr);
84
return supportedAttributes.contains<QualifiedName, SVGAttributeHashTranslator>(attrName);
87
void SVGTextPathElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
89
SVGParsingError parseError = NoError;
91
if (!isSupportedAttribute(name))
92
SVGTextContentElement::parseAttribute(name, value);
93
else if (name == SVGNames::startOffsetAttr)
94
setStartOffsetBaseValue(SVGLength::construct(LengthModeOther, value, parseError));
95
else if (name == SVGNames::methodAttr) {
96
SVGTextPathMethodType propertyValue = SVGPropertyTraits<SVGTextPathMethodType>::fromString(value);
97
if (propertyValue > 0)
98
setMethodBaseValue(propertyValue);
99
} else if (name == SVGNames::spacingAttr) {
100
SVGTextPathSpacingType propertyValue = SVGPropertyTraits<SVGTextPathSpacingType>::fromString(value);
101
if (propertyValue > 0)
102
setSpacingBaseValue(propertyValue);
103
} else if (SVGURIReference::parseAttribute(name, value)) {
105
ASSERT_NOT_REACHED();
107
reportAttributeParsingError(parseError, name, value);
110
void SVGTextPathElement::svgAttributeChanged(const QualifiedName& attrName)
112
if (!isSupportedAttribute(attrName)) {
113
SVGTextContentElement::svgAttributeChanged(attrName);
117
SVGElementInstance::InvalidationGuard invalidationGuard(this);
119
if (SVGURIReference::isKnownAttribute(attrName)) {
120
buildPendingResource();
124
if (attrName == SVGNames::startOffsetAttr)
125
updateRelativeLengthsInformation();
127
if (RenderObject* object = renderer())
128
RenderSVGResource::markForLayoutAndParentResourceInvalidation(object);
131
RenderObject* SVGTextPathElement::createRenderer(RenderArena* arena, RenderStyle*)
133
return new (arena) RenderSVGTextPath(this);
136
bool SVGTextPathElement::childShouldCreateRenderer(const NodeRenderingContext& childContext) const
138
if (childContext.node()->isTextNode()
139
|| childContext.node()->hasTagName(SVGNames::aTag)
140
|| childContext.node()->hasTagName(SVGNames::trefTag)
141
|| childContext.node()->hasTagName(SVGNames::tspanTag))
147
bool SVGTextPathElement::rendererIsNeeded(const NodeRenderingContext& context)
150
&& (parentNode()->hasTagName(SVGNames::aTag)
151
|| parentNode()->hasTagName(SVGNames::textTag)))
152
return StyledElement::rendererIsNeeded(context);
157
void SVGTextPathElement::buildPendingResource()
159
clearResourceReferences();
164
Element* target = SVGURIReference::targetElementFromIRIString(href(), document(), &id);
166
if (hasPendingResources() || id.isEmpty())
169
document()->accessSVGExtensions()->addPendingResource(id, this);
170
ASSERT(hasPendingResources());
171
} else if (target->isSVGElement()) {
172
// Register us with the target in the dependencies map. Any change of hrefElement
173
// that leads to relayout/repainting now informs us, so we can react to it.
174
document()->accessSVGExtensions()->addElementReferencingTarget(this, static_cast<SVGElement*>(target));
178
Node::InsertionNotificationRequest SVGTextPathElement::insertedInto(ContainerNode* rootParent)
180
SVGTextContentElement::insertedInto(rootParent);
181
buildPendingResource();
182
return InsertionDone;
185
void SVGTextPathElement::removedFrom(ContainerNode* rootParent)
187
SVGTextContentElement::removedFrom(rootParent);
188
if (rootParent->inDocument())
189
clearResourceReferences();
192
bool SVGTextPathElement::selfHasRelativeLengths() const
194
return startOffset().isRelative()
195
|| SVGTextContentElement::selfHasRelativeLengths();
200
#endif // ENABLE(SVG)