Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / svg / SVGTextPathElement.cpp
1 /*
2  * Copyright (C) 2007 Nikolas Zimmermann <zimmermann@kde.org>
3  * Copyright (C) 2010 Rob Buis <rwlbuis@gmail.com>
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 "core/svg/SVGTextPathElement.h"
23
24 #include "core/XLinkNames.h"
25 #include "core/rendering/svg/RenderSVGTextPath.h"
26 #include "core/svg/SVGDocumentExtensions.h"
27
28 namespace blink {
29
30 template<> const SVGEnumerationStringEntries& getStaticStringEntries<SVGTextPathMethodType>()
31 {
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"));
36     }
37     return entries;
38 }
39
40 template<> const SVGEnumerationStringEntries& getStaticStringEntries<SVGTextPathSpacingType>()
41 {
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"));
46     }
47     return entries;
48 }
49
50 inline SVGTextPathElement::SVGTextPathElement(Document& document)
51     : SVGTextContentElement(SVGNames::textPathTag, document)
52     , SVGURIReference(this)
53     , m_startOffset(SVGAnimatedLength::create(this, SVGNames::startOffsetAttr, SVGLength::create(LengthModeOther), AllowNegativeLengths))
54     , m_method(SVGAnimatedEnumeration<SVGTextPathMethodType>::create(this, SVGNames::methodAttr, SVGTextPathMethodAlign))
55     , m_spacing(SVGAnimatedEnumeration<SVGTextPathSpacingType>::create(this, SVGNames::spacingAttr, SVGTextPathSpacingExact))
56 {
57     addToPropertyMap(m_startOffset);
58     addToPropertyMap(m_method);
59     addToPropertyMap(m_spacing);
60 }
61
62 DEFINE_NODE_FACTORY(SVGTextPathElement)
63
64 SVGTextPathElement::~SVGTextPathElement()
65 {
66 #if !ENABLE(OILPAN)
67     clearResourceReferences();
68 #endif
69 }
70
71 void SVGTextPathElement::clearResourceReferences()
72 {
73     removeAllOutgoingReferences();
74 }
75
76 bool SVGTextPathElement::isSupportedAttribute(const QualifiedName& attrName)
77 {
78     DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ());
79     if (supportedAttributes.isEmpty()) {
80         SVGURIReference::addSupportedAttributes(supportedAttributes);
81         supportedAttributes.add(SVGNames::startOffsetAttr);
82         supportedAttributes.add(SVGNames::methodAttr);
83         supportedAttributes.add(SVGNames::spacingAttr);
84     }
85     return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName);
86 }
87
88 void SVGTextPathElement::svgAttributeChanged(const QualifiedName& attrName)
89 {
90     if (!isSupportedAttribute(attrName)) {
91         SVGTextContentElement::svgAttributeChanged(attrName);
92         return;
93     }
94
95     SVGElement::InvalidationGuard invalidationGuard(this);
96
97     if (SVGURIReference::isKnownAttribute(attrName)) {
98         buildPendingResource();
99         return;
100     }
101
102     if (attrName == SVGNames::startOffsetAttr)
103         updateRelativeLengthsInformation();
104
105     if (RenderObject* object = renderer())
106         markForLayoutAndParentResourceInvalidation(object);
107 }
108
109 RenderObject* SVGTextPathElement::createRenderer(RenderStyle*)
110 {
111     return new RenderSVGTextPath(this);
112 }
113
114 bool SVGTextPathElement::rendererIsNeeded(const RenderStyle& style)
115 {
116     if (parentNode() && (isSVGAElement(*parentNode()) || isSVGTextElement(*parentNode())))
117         return Element::rendererIsNeeded(style);
118
119     return false;
120 }
121
122 void SVGTextPathElement::buildPendingResource()
123 {
124     clearResourceReferences();
125     if (!inDocument())
126         return;
127
128     AtomicString id;
129     Element* target = SVGURIReference::targetElementFromIRIString(hrefString(), treeScope(), &id);
130     if (!target) {
131         // Do not register as pending if we are already pending this resource.
132         if (document().accessSVGExtensions().isElementPendingResource(this, id))
133             return;
134
135         if (!id.isEmpty()) {
136             document().accessSVGExtensions().addPendingResource(id, this);
137             ASSERT(hasPendingResources());
138         }
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)));
143     }
144 }
145
146 Node::InsertionNotificationRequest SVGTextPathElement::insertedInto(ContainerNode* rootParent)
147 {
148     SVGTextContentElement::insertedInto(rootParent);
149     buildPendingResource();
150     return InsertionDone;
151 }
152
153 void SVGTextPathElement::removedFrom(ContainerNode* rootParent)
154 {
155     SVGTextContentElement::removedFrom(rootParent);
156     if (rootParent->inDocument())
157         clearResourceReferences();
158 }
159
160 bool SVGTextPathElement::selfHasRelativeLengths() const
161 {
162     return m_startOffset->currentValue()->isRelative()
163         || SVGTextContentElement::selfHasRelativeLengths();
164 }
165
166 } // namespace blink