1 /*
2 * Copyright (C) 2008 Apple Inc. All rights reserved.
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 #include "core/css/CSSImageGeneratorValue.h"
28
29 #include "core/css/CSSCanvasValue.h"
30 #include "core/css/CSSCrossfadeValue.h"
31 #include "core/css/CSSGradientValue.h"
32 #include "platform/graphics/Image.h"
33
34 namespace blink {
35
CSSImageGeneratorValue(ClassType classType)36 CSSImageGeneratorValue::CSSImageGeneratorValue(ClassType classType)
37 : CSSValue(classType)
38 {
39 }
40
~CSSImageGeneratorValue()41 CSSImageGeneratorValue::~CSSImageGeneratorValue()
42 {
43 }
44
addClient(RenderObject * renderer,const IntSize & size)45 void CSSImageGeneratorValue::addClient(RenderObject* renderer, const IntSize& size)
46 {
47 ASSERT(renderer);
48 #if !ENABLE(OILPAN)
49 ref();
50 #else
51 if (m_clients.isEmpty()) {
52 ASSERT(!m_keepAlive);
53 m_keepAlive = adoptPtr(new Persistent<CSSImageGeneratorValue>(this));
54 }
55 #endif
56
57 if (!size.isEmpty())
58 m_sizes.add(size);
59
60 RenderObjectSizeCountMap::iterator it = m_clients.find(renderer);
61 if (it == m_clients.end())
62 m_clients.add(renderer, SizeAndCount(size, 1));
63 else {
64 SizeAndCount& sizeCount = it->value;
65 ++sizeCount.count;
66 }
67 }
68
removeClient(RenderObject * renderer)69 void CSSImageGeneratorValue::removeClient(RenderObject* renderer)
70 {
71 ASSERT(renderer);
72 RenderObjectSizeCountMap::iterator it = m_clients.find(renderer);
73 ASSERT_WITH_SECURITY_IMPLICATION(it != m_clients.end());
74
75 IntSize removedImageSize;
76 SizeAndCount& sizeCount = it->value;
77 IntSize size = sizeCount.size;
78 if (!size.isEmpty()) {
79 m_sizes.remove(size);
80 if (!m_sizes.contains(size))
81 m_images.remove(size);
82 }
83
84 if (!--sizeCount.count)
85 m_clients.remove(renderer);
86
87 #if !ENABLE(OILPAN)
88 deref();
89 #else
90 if (m_clients.isEmpty()) {
91 ASSERT(m_keepAlive);
92 m_keepAlive = nullptr;
93 }
94 #endif
95 }
96
getImage(RenderObject * renderer,const IntSize & size)97 Image* CSSImageGeneratorValue::getImage(RenderObject* renderer, const IntSize& size)
98 {
99 RenderObjectSizeCountMap::iterator it = m_clients.find(renderer);
100 if (it != m_clients.end()) {
101 SizeAndCount& sizeCount = it->value;
102 IntSize oldSize = sizeCount.size;
103 if (oldSize != size) {
104 #if !ENABLE_OILPAN
105 RefPtr<CSSImageGeneratorValue> protect(this);
106 #endif
107 removeClient(renderer);
108 addClient(renderer, size);
109 }
110 }
111
112 // Don't generate an image for empty sizes.
113 if (size.isEmpty())
114 return 0;
115
116 // Look up the image in our cache.
117 return m_images.get(size);
118 }
119
putImage(const IntSize & size,PassRefPtr<Image> image)120 void CSSImageGeneratorValue::putImage(const IntSize& size, PassRefPtr<Image> image)
121 {
122 m_images.add(size, image);
123 }
124
image(RenderObject * renderer,const IntSize & size)125 PassRefPtr<Image> CSSImageGeneratorValue::image(RenderObject* renderer, const IntSize& size)
126 {
127 switch (classType()) {
128 case CanvasClass:
129 return toCSSCanvasValue(this)->image(renderer, size);
130 case CrossfadeClass:
131 return toCSSCrossfadeValue(this)->image(renderer, size);
132 case LinearGradientClass:
133 return toCSSLinearGradientValue(this)->image(renderer, size);
134 case RadialGradientClass:
135 return toCSSRadialGradientValue(this)->image(renderer, size);
136 default:
137 ASSERT_NOT_REACHED();
138 }
139 return nullptr;
140 }
141
isFixedSize() const142 bool CSSImageGeneratorValue::isFixedSize() const
143 {
144 switch (classType()) {
145 case CanvasClass:
146 return toCSSCanvasValue(this)->isFixedSize();
147 case CrossfadeClass:
148 return toCSSCrossfadeValue(this)->isFixedSize();
149 case LinearGradientClass:
150 return toCSSLinearGradientValue(this)->isFixedSize();
151 case RadialGradientClass:
152 return toCSSRadialGradientValue(this)->isFixedSize();
153 default:
154 ASSERT_NOT_REACHED();
155 }
156 return false;
157 }
158
fixedSize(const RenderObject * renderer)159 IntSize CSSImageGeneratorValue::fixedSize(const RenderObject* renderer)
160 {
161 switch (classType()) {
162 case CanvasClass:
163 return toCSSCanvasValue(this)->fixedSize(renderer);
164 case CrossfadeClass:
165 return toCSSCrossfadeValue(this)->fixedSize(renderer);
166 case LinearGradientClass:
167 return toCSSLinearGradientValue(this)->fixedSize(renderer);
168 case RadialGradientClass:
169 return toCSSRadialGradientValue(this)->fixedSize(renderer);
170 default:
171 ASSERT_NOT_REACHED();
172 }
173 return IntSize();
174 }
175
isPending() const176 bool CSSImageGeneratorValue::isPending() const
177 {
178 switch (classType()) {
179 case CrossfadeClass:
180 return toCSSCrossfadeValue(this)->isPending();
181 case CanvasClass:
182 return toCSSCanvasValue(this)->isPending();
183 case LinearGradientClass:
184 return toCSSLinearGradientValue(this)->isPending();
185 case RadialGradientClass:
186 return toCSSRadialGradientValue(this)->isPending();
187 default:
188 ASSERT_NOT_REACHED();
189 }
190 return false;
191 }
192
knownToBeOpaque(const RenderObject * renderer) const193 bool CSSImageGeneratorValue::knownToBeOpaque(const RenderObject* renderer) const
194 {
195 switch (classType()) {
196 case CrossfadeClass:
197 return toCSSCrossfadeValue(this)->knownToBeOpaque(renderer);
198 case CanvasClass:
199 return false;
200 case LinearGradientClass:
201 return toCSSLinearGradientValue(this)->knownToBeOpaque(renderer);
202 case RadialGradientClass:
203 return toCSSRadialGradientValue(this)->knownToBeOpaque(renderer);
204 default:
205 ASSERT_NOT_REACHED();
206 }
207 return false;
208 }
209
loadSubimages(ResourceFetcher * fetcher)210 void CSSImageGeneratorValue::loadSubimages(ResourceFetcher* fetcher)
211 {
212 switch (classType()) {
213 case CrossfadeClass:
214 toCSSCrossfadeValue(this)->loadSubimages(fetcher);
215 break;
216 case CanvasClass:
217 toCSSCanvasValue(this)->loadSubimages(fetcher);
218 break;
219 case LinearGradientClass:
220 toCSSLinearGradientValue(this)->loadSubimages(fetcher);
221 break;
222 case RadialGradientClass:
223 toCSSRadialGradientValue(this)->loadSubimages(fetcher);
224 break;
225 default:
226 ASSERT_NOT_REACHED();
227 }
228 }
229
230 } // namespace blink
231