2
* Copyright (C) 2011 Apple Inc. All rights reserved.
4
* Redistribution and use in source and binary forms, with or without
5
* modification, are permitted provided that the following conditions
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.
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.
27
#include "CSSCrossfadeValue.h"
29
#include "CSSImageValue.h"
30
#include "CachedImage.h"
31
#include "CachedResourceLoader.h"
32
#include "CrossfadeGeneratedImage.h"
33
#include "ImageBuffer.h"
34
#include "RenderObject.h"
35
#include "StyleCachedImage.h"
36
#include "StyleGeneratedImage.h"
37
#include "WebCoreMemoryInstrumentation.h"
38
#include <wtf/text/StringBuilder.h>
42
static bool subimageIsPending(CSSValue* value)
44
if (value->isImageValue())
45
return static_cast<CSSImageValue*>(value)->cachedOrPendingImage()->isPendingImage();
47
if (value->isImageGeneratorValue())
48
return static_cast<CSSImageGeneratorValue*>(value)->isPending();
55
static bool subimageHasAlpha(CSSValue* value, const RenderObject* renderer)
57
if (value->isImageValue())
58
return static_cast<CSSImageValue*>(value)->hasAlpha(renderer);
60
if (value->isImageGeneratorValue())
61
return static_cast<CSSImageGeneratorValue*>(value)->hasAlpha(renderer);
68
static CachedImage* cachedImageForCSSValue(CSSValue* value, CachedResourceLoader* cachedResourceLoader)
73
if (value->isImageValue()) {
74
StyleCachedImage* styleCachedImage = static_cast<CSSImageValue*>(value)->cachedImage(cachedResourceLoader);
75
if (!styleCachedImage)
78
return styleCachedImage->cachedImage();
81
if (value->isImageGeneratorValue()) {
82
static_cast<CSSImageGeneratorValue*>(value)->loadSubimages(cachedResourceLoader);
83
// FIXME: Handle CSSImageGeneratorValue (and thus cross-fades with gradients and canvas).
92
CSSCrossfadeValue::~CSSCrossfadeValue()
94
if (m_cachedFromImage)
95
m_cachedFromImage->removeClient(&m_crossfadeSubimageObserver);
97
m_cachedToImage->removeClient(&m_crossfadeSubimageObserver);
100
String CSSCrossfadeValue::customCssText() const
102
StringBuilder result;
103
result.appendLiteral("-webkit-cross-fade(");
104
result.append(m_fromValue->cssText());
105
result.appendLiteral(", ");
106
result.append(m_toValue->cssText());
107
result.appendLiteral(", ");
108
result.append(m_percentageValue->cssText());
110
return result.toString();
113
IntSize CSSCrossfadeValue::fixedSize(const RenderObject* renderer)
115
float percentage = m_percentageValue->getFloatValue();
116
float inversePercentage = 1 - percentage;
118
CachedResourceLoader* cachedResourceLoader = renderer->document()->cachedResourceLoader();
119
CachedImage* cachedFromImage = cachedImageForCSSValue(m_fromValue.get(), cachedResourceLoader);
120
CachedImage* cachedToImage = cachedImageForCSSValue(m_toValue.get(), cachedResourceLoader);
122
if (!cachedFromImage || !cachedToImage)
125
IntSize fromImageSize = cachedFromImage->imageForRenderer(renderer)->size();
126
IntSize toImageSize = cachedToImage->imageForRenderer(renderer)->size();
128
// Rounding issues can cause transitions between images of equal size to return
129
// a different fixed size; avoid performing the interpolation if the images are the same size.
130
if (fromImageSize == toImageSize)
131
return fromImageSize;
133
return IntSize(fromImageSize.width() * inversePercentage + toImageSize.width() * percentage,
134
fromImageSize.height() * inversePercentage + toImageSize.height() * percentage);
137
bool CSSCrossfadeValue::isPending() const
139
return subimageIsPending(m_fromValue.get()) || subimageIsPending(m_toValue.get());
142
bool CSSCrossfadeValue::hasAlpha(const RenderObject* renderer) const
144
return subimageHasAlpha(m_fromValue.get(), renderer) || subimageHasAlpha(m_toValue.get(), renderer);
147
void CSSCrossfadeValue::loadSubimages(CachedResourceLoader* cachedResourceLoader)
149
m_cachedFromImage = cachedImageForCSSValue(m_fromValue.get(), cachedResourceLoader);
150
m_cachedToImage = cachedImageForCSSValue(m_toValue.get(), cachedResourceLoader);
152
if (m_cachedFromImage)
153
m_cachedFromImage->addClient(&m_crossfadeSubimageObserver);
155
m_cachedToImage->addClient(&m_crossfadeSubimageObserver);
157
m_crossfadeSubimageObserver.setReady(true);
160
void CSSCrossfadeValue::reportDescendantMemoryUsage(MemoryObjectInfo* memoryObjectInfo) const
162
MemoryClassInfo info(memoryObjectInfo, this, WebCoreMemoryTypes::CSS);
163
CSSImageGeneratorValue::reportBaseClassMemoryUsage(memoryObjectInfo);
164
info.addMember(m_fromValue);
165
info.addMember(m_toValue);
166
info.addMember(m_percentageValue);
167
// FIXME: add instrumentation for
173
PassRefPtr<Image> CSSCrossfadeValue::image(RenderObject* renderer, const IntSize& size)
178
CachedResourceLoader* cachedResourceLoader = renderer->document()->cachedResourceLoader();
179
CachedImage* cachedFromImage = cachedImageForCSSValue(m_fromValue.get(), cachedResourceLoader);
180
CachedImage* cachedToImage = cachedImageForCSSValue(m_toValue.get(), cachedResourceLoader);
182
if (!cachedFromImage || !cachedToImage)
183
return Image::nullImage();
185
Image* fromImage = cachedFromImage->imageForRenderer(renderer);
186
Image* toImage = cachedToImage->imageForRenderer(renderer);
188
if (!fromImage || !toImage)
189
return Image::nullImage();
191
m_generatedImage = CrossfadeGeneratedImage::create(fromImage, toImage, m_percentageValue->getFloatValue(), fixedSize(renderer), size);
193
return m_generatedImage.release();
196
void CSSCrossfadeValue::crossfadeChanged(const IntRect&)
198
RenderObjectSizeCountMap::const_iterator end = clients().end();
199
for (RenderObjectSizeCountMap::const_iterator curr = clients().begin(); curr != end; ++curr) {
200
RenderObject* client = const_cast<RenderObject*>(curr->key);
201
client->imageChanged(static_cast<WrappedImagePtr>(this));
205
void CSSCrossfadeValue::CrossfadeSubimageObserverProxy::imageChanged(CachedImage*, const IntRect* rect)
208
m_ownerValue->crossfadeChanged(*rect);
211
bool CSSCrossfadeValue::hasFailedOrCanceledSubresources() const
213
if (m_cachedFromImage && m_cachedFromImage->loadFailedOrCanceled())
215
if (m_cachedToImage && m_cachedToImage->loadFailedOrCanceled())
220
} // namespace WebCore