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 "config.h"
27
28 #if ENABLE(SVG)
29 #include "SVGResource.h"
30
31 #include "RenderPath.h"
32 #include "SVGElement.h"
33 #include "SVGStyledElement.h"
34 #include <wtf/StdLibExtras.h>
35
36 namespace WebCore {
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] = 0;
47 }
48 SVGResource* resources[_ResourceTypeCount];
49 };
50
51 typedef HashMap<SVGStyledElement*, ResourceSet*> ResourceClientMap;
52
clientMap()53 static ResourceClientMap& clientMap()
54 {
55 DEFINE_STATIC_LOCAL(ResourceClientMap, map, ());
56 return map;
57 }
58
~SVGResource()59 SVGResource::~SVGResource()
60 {
61 int type = -1;
62 HashSet<SVGStyledElement*>::iterator itr = m_clients.begin();
63
64 for (; type < 0 && itr != m_clients.end(); ++itr) {
65 ResourceSet* target = clientMap().get(*itr);
66 if (!target)
67 continue;
68
69 for (int i = 0; i < _ResourceTypeCount; i++) {
70 if (target->resources[i] != this)
71 continue;
72 type = i;
73 target->resources[i] = 0;
74 break;
75 }
76 }
77
78 if (type < 0)
79 return;
80
81 for (; itr != m_clients.end(); ++itr) {
82 ResourceSet* target = clientMap().get(*itr);
83 if (!target)
84 continue;
85
86 if (target->resources[type] == this)
87 target->resources[type] = 0;
88 }
89 }
90
invalidate()91 void SVGResource::invalidate()
92 {
93 HashSet<SVGStyledElement*>::const_iterator it = m_clients.begin();
94 const HashSet<SVGStyledElement*>::const_iterator end = m_clients.end();
95
96 for (; it != end; ++it) {
97 SVGStyledElement* cur = *it;
98
99 if (cur->renderer())
100 cur->renderer()->setNeedsLayout(true);
101
102 cur->invalidateResourcesInAncestorChain();
103 }
104 }
105
invalidateClients(HashSet<SVGStyledElement * > clients)106 void SVGResource::invalidateClients(HashSet<SVGStyledElement*> clients)
107 {
108 HashSet<SVGStyledElement*>::const_iterator it = clients.begin();
109 const HashSet<SVGStyledElement*>::const_iterator end = clients.end();
110
111 for (; it != end; ++it) {
112 SVGStyledElement* cur = *it;
113
114 if (cur->renderer())
115 cur->renderer()->setNeedsLayout(true);
116
117 cur->invalidateResourcesInAncestorChain();
118 }
119 }
120
removeClient(SVGStyledElement * item)121 void SVGResource::removeClient(SVGStyledElement* item)
122 {
123 ResourceClientMap::iterator resourcePtr = clientMap().find(item);
124 if (resourcePtr == clientMap().end())
125 return;
126
127 ResourceSet* set = resourcePtr->second;
128 ASSERT(set);
129
130 clientMap().remove(resourcePtr);
131
132 for (int i = 0; i < _ResourceTypeCount; i++)
133 if (set->resources[i])
134 set->resources[i]->m_clients.remove(item);
135
136 delete set;
137 }
138
addClient(SVGStyledElement * item)139 void SVGResource::addClient(SVGStyledElement* item)
140 {
141 if (m_clients.contains(item))
142 return;
143
144 m_clients.add(item);
145
146 ResourceSet* target = clientMap().get(item);
147 if (!target)
148 target = new ResourceSet;
149
150 SVGResourceType type = resourceType();
151 if (SVGResource* oldResource = target->resources[type])
152 oldResource->m_clients.remove(item);
153
154 target->resources[type] = this;
155 clientMap().set(item, target);
156 }
157
externalRepresentation(TextStream & ts) const158 TextStream& SVGResource::externalRepresentation(TextStream& ts) const
159 {
160 return ts;
161 }
162
getResourceById(Document * document,const AtomicString & id)163 SVGResource* getResourceById(Document* document, const AtomicString& id)
164 {
165 if (id.isEmpty())
166 return 0;
167
168 Element* element = document->getElementById(id);
169 SVGElement* svgElement = 0;
170 if (element && element->isSVGElement())
171 svgElement = static_cast<SVGElement*>(element);
172
173 if (svgElement && svgElement->isStyled())
174 return static_cast<SVGStyledElement*>(svgElement)->canvasResource();
175
176 return 0;
177 }
178
operator <<(TextStream & ts,const SVGResource & r)179 TextStream& operator<<(TextStream& ts, const SVGResource& r)
180 {
181 return r.externalRepresentation(ts);
182 }
183
184 }
185
186 #endif
187