1/* 2 * Copyright (C) 2013 Adobe Systems Incorporated. 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 THE COPYRIGHT HOLDER "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 THE COPYRIGHT HOLDER BE 17 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 18 * 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 21 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 22 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 23 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27#include "config.h" 28#include "CSSFilterImageValue.h" 29 30#if ENABLE(CSS_FILTERS) 31 32#include "CSSImageValue.h" 33#include "CachedImage.h" 34#include "CachedResourceLoader.h" 35#include "CrossfadeGeneratedImage.h" 36#include "FilterEffectRenderer.h" 37#include "ImageBuffer.h" 38#include "RenderElement.h" 39#include "StyleCachedImage.h" 40#include "StyleGeneratedImage.h" 41#include "StyleResolver.h" 42#include <wtf/text/StringBuilder.h> 43 44namespace WebCore { 45 46CSSFilterImageValue::~CSSFilterImageValue() 47{ 48 if (m_cachedImage) 49 m_cachedImage->removeClient(&m_filterSubimageObserver); 50} 51 52String CSSFilterImageValue::customCSSText() const 53{ 54 StringBuilder result; 55 result.appendLiteral("-webkit-filter("); 56 result.append(m_imageValue->cssText()); 57 result.appendLiteral(", "); 58 result.append(m_filterValue->cssText()); 59 result.append(')'); 60 return result.toString(); 61} 62 63FloatSize CSSFilterImageValue::fixedSize(const RenderElement* renderer) 64{ 65 CachedResourceLoader* cachedResourceLoader = renderer->document().cachedResourceLoader(); 66 CachedImage* cachedImage = cachedImageForCSSValue(m_imageValue.get(), cachedResourceLoader); 67 68 if (!cachedImage) 69 return FloatSize(); 70 71 return cachedImage->imageForRenderer(renderer)->size(); 72} 73 74bool CSSFilterImageValue::isPending() const 75{ 76 return CSSImageGeneratorValue::subimageIsPending(m_imageValue.get()); 77} 78 79bool CSSFilterImageValue::knownToBeOpaque(const RenderElement*) const 80{ 81 return false; 82} 83 84void CSSFilterImageValue::loadSubimages(CachedResourceLoader* cachedResourceLoader) 85{ 86 CachedResourceHandle<CachedImage> oldCachedImage = m_cachedImage; 87 88 m_cachedImage = CSSImageGeneratorValue::cachedImageForCSSValue(m_imageValue.get(), cachedResourceLoader); 89 90 if (m_cachedImage != oldCachedImage) { 91 if (oldCachedImage) 92 oldCachedImage->removeClient(&m_filterSubimageObserver); 93 if (m_cachedImage) 94 m_cachedImage->addClient(&m_filterSubimageObserver); 95 } 96 97 m_filterSubimageObserver.setReady(true); 98} 99 100PassRefPtr<Image> CSSFilterImageValue::image(RenderElement* renderer, const FloatSize& size) 101{ 102 if (size.isEmpty()) 103 return 0; 104 105 CachedResourceLoader* cachedResourceLoader = renderer->document().cachedResourceLoader(); 106 CachedImage* cachedImage = cachedImageForCSSValue(m_imageValue.get(), cachedResourceLoader); 107 108 if (!cachedImage) 109 return Image::nullImage(); 110 111 Image* image = cachedImage->imageForRenderer(renderer); 112 113 if (!image) 114 return Image::nullImage(); 115 116 // Transform Image into ImageBuffer. 117 std::unique_ptr<ImageBuffer> texture = ImageBuffer::create(size); 118 if (!texture) 119 return Image::nullImage(); 120 texture->context()->drawImage(image, ColorSpaceDeviceRGB, IntPoint()); 121 122 RefPtr<FilterEffectRenderer> filterRenderer = FilterEffectRenderer::create(); 123 filterRenderer->setSourceImage(WTF::move(texture)); 124 filterRenderer->setSourceImageRect(FloatRect(FloatPoint(), size)); 125 filterRenderer->setFilterRegion(FloatRect(FloatPoint(), size)); 126 if (!filterRenderer->build(renderer, m_filterOperations, FilterFunction)) 127 return Image::nullImage(); 128 filterRenderer->apply(); 129 130 m_generatedImage = filterRenderer->output()->copyImage(); 131 132 return m_generatedImage.release(); 133} 134 135void CSSFilterImageValue::filterImageChanged(const IntRect&) 136{ 137 for (auto it = clients().begin(), end = clients().end(); it != end; ++it) 138 it->key->imageChanged(static_cast<WrappedImagePtr>(this)); 139} 140 141void CSSFilterImageValue::createFilterOperations(StyleResolver* resolver) 142{ 143 m_filterOperations.clear(); 144 resolver->createFilterOperations(m_filterValue.get(), m_filterOperations); 145} 146 147void CSSFilterImageValue::FilterSubimageObserverProxy::imageChanged(CachedImage*, const IntRect* rect) 148{ 149 if (m_ready) 150 m_ownerValue->filterImageChanged(*rect); 151} 152 153bool CSSFilterImageValue::hasFailedOrCanceledSubresources() const 154{ 155 if (m_cachedImage && m_cachedImage->loadFailedOrCanceled()) 156 return true; 157 return false; 158} 159 160bool CSSFilterImageValue::equals(const CSSFilterImageValue& other) const 161{ 162 return equalInputImages(other) && compareCSSValuePtr(m_filterValue, other.m_filterValue); 163} 164 165bool CSSFilterImageValue::equalInputImages(const CSSFilterImageValue& other) const 166{ 167 return compareCSSValuePtr(m_imageValue, other.m_imageValue); 168} 169 170} // namespace WebCore 171 172#endif // ENABLE(CSS_FILTERS) 173