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.
22 #include "core/svg/SVGTextPathElement.h"
24 #include "core/XLinkNames.h"
25 #include "core/layout/svg/LayoutSVGTextPath.h"
26 #include "core/svg/SVGDocumentExtensions.h"
30 template<> const SVGEnumerationStringEntries
& getStaticStringEntries
<SVGTextPathMethodType
>()
32 DEFINE_STATIC_LOCAL(SVGEnumerationStringEntries
, entries
, ());
33 if (entries
.isEmpty()) {
34 entries
.append(std::make_pair(SVGTextPathMethodAlign
, "align"));
35 entries
.append(std::make_pair(SVGTextPathMethodStretch
, "stretch"));
40 template<> const SVGEnumerationStringEntries
& getStaticStringEntries
<SVGTextPathSpacingType
>()
42 DEFINE_STATIC_LOCAL(SVGEnumerationStringEntries
, entries
, ());
43 if (entries
.isEmpty()) {
44 entries
.append(std::make_pair(SVGTextPathSpacingAuto
, "auto"));
45 entries
.append(std::make_pair(SVGTextPathSpacingExact
, "exact"));
50 inline SVGTextPathElement::SVGTextPathElement(Document
& document
)
51 : SVGTextContentElement(SVGNames::textPathTag
, document
)
52 , SVGURIReference(this)
53 , m_startOffset(SVGAnimatedLength::create(this, SVGNames::startOffsetAttr
, SVGLength::create(SVGLengthMode::Width
), AllowNegativeLengths
))
54 , m_method(SVGAnimatedEnumeration
<SVGTextPathMethodType
>::create(this, SVGNames::methodAttr
, SVGTextPathMethodAlign
))
55 , m_spacing(SVGAnimatedEnumeration
<SVGTextPathSpacingType
>::create(this, SVGNames::spacingAttr
, SVGTextPathSpacingExact
))
57 addToPropertyMap(m_startOffset
);
58 addToPropertyMap(m_method
);
59 addToPropertyMap(m_spacing
);
62 DEFINE_NODE_FACTORY(SVGTextPathElement
)
64 SVGTextPathElement::~SVGTextPathElement()
67 clearResourceReferences();
71 DEFINE_TRACE(SVGTextPathElement
)
73 visitor
->trace(m_startOffset
);
74 visitor
->trace(m_method
);
75 visitor
->trace(m_spacing
);
76 SVGTextContentElement::trace(visitor
);
77 SVGURIReference::trace(visitor
);
80 void SVGTextPathElement::clearResourceReferences()
82 removeAllOutgoingReferences();
85 void SVGTextPathElement::svgAttributeChanged(const QualifiedName
& attrName
)
87 if (SVGURIReference::isKnownAttribute(attrName
)) {
88 SVGElement::InvalidationGuard
invalidationGuard(this);
89 buildPendingResource();
93 if (attrName
== SVGNames::startOffsetAttr
)
94 updateRelativeLengthsInformation();
96 if (attrName
== SVGNames::startOffsetAttr
97 || attrName
== SVGNames::methodAttr
98 || attrName
== SVGNames::spacingAttr
) {
99 SVGElement::InvalidationGuard
invalidationGuard(this);
100 if (LayoutObject
* object
= layoutObject())
101 markForLayoutAndParentResourceInvalidation(object
);
106 SVGTextContentElement::svgAttributeChanged(attrName
);
109 LayoutObject
* SVGTextPathElement::createLayoutObject(const ComputedStyle
&)
111 return new LayoutSVGTextPath(this);
114 bool SVGTextPathElement::layoutObjectIsNeeded(const ComputedStyle
& style
)
116 if (parentNode() && (isSVGAElement(*parentNode()) || isSVGTextElement(*parentNode())))
117 return Element::layoutObjectIsNeeded(style
);
122 void SVGTextPathElement::buildPendingResource()
124 clearResourceReferences();
129 Element
* target
= SVGURIReference::targetElementFromIRIString(hrefString(), treeScope(), &id
);
131 // Do not register as pending if we are already pending this resource.
132 if (document().accessSVGExtensions().isElementPendingResource(this, id
))
136 document().accessSVGExtensions().addPendingResource(id
, this);
137 ASSERT(hasPendingResources());
139 } else if (isSVGPathElement(*target
)) {
140 // Register us with the target in the dependencies map. Any change of hrefElement
141 // that leads to relayout/repainting now informs us, so we can react to it.
142 addReferenceTo(toSVGElement((target
)));
146 Node::InsertionNotificationRequest
SVGTextPathElement::insertedInto(ContainerNode
* rootParent
)
148 SVGTextContentElement::insertedInto(rootParent
);
149 buildPendingResource();
150 return InsertionDone
;
153 void SVGTextPathElement::removedFrom(ContainerNode
* rootParent
)
155 SVGTextContentElement::removedFrom(rootParent
);
156 if (rootParent
->inDocument())
157 clearResourceReferences();
160 bool SVGTextPathElement::selfHasRelativeLengths() const
162 return m_startOffset
->currentValue()->isRelative()
163 || SVGTextContentElement::selfHasRelativeLengths();