1 /*
2 * Copyright (C) 2006, 2008 Nikolas Zimmermann <zimmermann@kde.org>
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 #include "wtf/Platform.h"
27
28 #if ENABLE(SVG)
29 #include "SVGResource.h"
30
31 #include "RenderPath.h"
32 #include "SVGElement.h"
33 #include "SVGStyledElement.h"
34
35 namespace WebCore
36 {
37
SVGResource()38 SVGResource::SVGResource()
39 {
40 }
41
42 struct ResourceSet {
ResourceSetWebCore::ResourceSet43 ResourceSet()
44 {
45 for (int i = 0; i < _ResourceTypeCount; i++) {
46 resources[i] = nullptr;
47 }
48 }
49 SVGResource *resources[_ResourceTypeCount];
50 };
51
clientMap()52 static HashMap<SVGStyledElement *, ResourceSet *> &clientMap()
53 {
54 static HashMap<SVGStyledElement *, ResourceSet *> map;
55 return map;
56 }
57
~SVGResource()58 SVGResource::~SVGResource()
59 {
60 int type = -1;
61 HashSet<SVGStyledElement *>::iterator itr = m_clients.begin();
62
63 for (; type < 0 && itr != m_clients.end(); ++itr) {
64 ResourceSet *target = clientMap().get(*itr);
65 if (!target) {
66 continue;
67 }
68
69 for (int i = 0; i < _ResourceTypeCount; i++) {
70 if (target->resources[i] != this) {
71 continue;
72 }
73 type = i;
74 target->resources[i] = nullptr;
75 break;
76 }
77 }
78
79 if (type < 0) {
80 return;
81 }
82
83 for (; itr != m_clients.end(); ++itr) {
84 ResourceSet *target = clientMap().get(*itr);
85 if (!target) {
86 continue;
87 }
88
89 if (target->resources[type] == this) {
90 target->resources[type] = nullptr;
91 }
92 }
93 }
94
invalidate()95 void SVGResource::invalidate()
96 {
97 HashSet<SVGStyledElement *>::const_iterator it = m_clients.begin();
98 const HashSet<SVGStyledElement *>::const_iterator end = m_clients.end();
99
100 for (; it != end; ++it) {
101 SVGStyledElement *cur = *it;
102
103 if (cur->renderer()) {
104 cur->renderer()->setNeedsLayout(true);
105 }
106
107 cur->invalidateResourcesInAncestorChain();
108 }
109 }
110
invalidateClients(HashSet<SVGStyledElement * > clients)111 void SVGResource::invalidateClients(HashSet<SVGStyledElement *> clients)
112 {
113 HashSet<SVGStyledElement *>::const_iterator it = clients.begin();
114 const HashSet<SVGStyledElement *>::const_iterator end = clients.end();
115
116 for (; it != end; ++it) {
117 SVGStyledElement *cur = *it;
118
119 if (cur->renderer()) {
120 cur->renderer()->setNeedsLayout(true);
121 }
122
123 cur->invalidateResourcesInAncestorChain();
124 }
125 }
126
removeClient(SVGStyledElement * item)127 void SVGResource::removeClient(SVGStyledElement *item)
128 {
129 HashMap<SVGStyledElement *, ResourceSet *>::iterator resourcePtr = clientMap().find(item);
130 if (resourcePtr == clientMap().end()) {
131 return;
132 }
133
134 ResourceSet *set = resourcePtr->second;
135 ASSERT(set);
136
137 clientMap().remove(resourcePtr);
138
139 for (int i = 0; i < _ResourceTypeCount; i++)
140 if (set->resources[i]) {
141 set->resources[i]->m_clients.remove(item);
142 }
143
144 delete set;
145 }
146
addClient(SVGStyledElement * item)147 void SVGResource::addClient(SVGStyledElement *item)
148 {
149 if (m_clients.contains(item)) {
150 return;
151 }
152
153 m_clients.add(item);
154
155 ResourceSet *target = clientMap().get(item);
156 if (!target) {
157 target = new ResourceSet;
158 }
159
160 SVGResourceType type = resourceType();
161 if (SVGResource *oldResource = target->resources[type]) {
162 oldResource->m_clients.remove(item);
163 }
164
165 target->resources[type] = this;
166 clientMap().set(item, target);
167 }
168
169 /*TextStream& SVGResource::externalRepresentation(TextStream& ts) const
170 {
171 return ts;
172 }*/
173
getResourceById(Document * document,const AtomicString & id)174 SVGResource *getResourceById(Document *document, const AtomicString &id)
175 {
176 if (id.isEmpty()) {
177 return nullptr;
178 }
179
180 Element *element = document->getElementById(id);
181 SVGElement *svgElement = nullptr;
182 if (element && element->isSVGElement()) {
183 svgElement = static_cast<SVGElement *>(element);
184 }
185
186 if (svgElement && svgElement->isStyled()) {
187 return static_cast<SVGStyledElement *>(svgElement)->canvasResource();
188 }
189
190 return nullptr;
191 }
192
193 /*TextStream& operator<<(TextStream& ts, const SVGResource& r)
194 {
195 return r.externalRepresentation(ts);
196 }*/
197
198 }
199
200 #endif
201