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 36 CSSImageGeneratorValue::CSSImageGeneratorValue(ClassType classType) 37 : CSSValue(classType) 38 { 39 } 40 41 CSSImageGeneratorValue::~CSSImageGeneratorValue() 42 { 43 } 44 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 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 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 120 void CSSImageGeneratorValue::putImage(const IntSize& size, PassRefPtr<Image> image) 121 { 122 m_images.add(size, image); 123 } 124 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 142 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 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 176 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 193 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 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