2 * Copyright (C) 2012 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 INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
27 #include "CSSImageSetValue.h"
29 #if ENABLE(CSS_IMAGE_SET)
31 #include "CSSImageValue.h"
32 #include "CSSPrimitiveValue.h"
33 #include "CachedResourceLoader.h"
36 #include "StyleCachedImageSet.h"
37 #include "StylePendingImage.h"
41 CSSImageSetValue::CSSImageSetValue()
42 : CSSValueList(ImageSetClass, CommaSeparator)
43 , m_accessedBestFitImage(false)
48 CSSImageSetValue::~CSSImageSetValue()
52 void CSSImageSetValue::fillImageSet()
54 size_t length = this->length();
57 CSSValue* imageValue = item(i);
58 ASSERT(imageValue->isImageValue());
59 String imageURL = static_cast<CSSImageValue*>(imageValue)->url();
63 CSSValue* scaleFactorValue = item(i);
64 ASSERT(scaleFactorValue->isPrimitiveValue());
65 float scaleFactor = static_cast<CSSPrimitiveValue*>(scaleFactorValue)->getFloatValue();
68 image.imageURL = imageURL;
69 image.scaleFactor = scaleFactor;
70 m_imagesInSet.append(image);
74 // Sort the images so that they are stored in order from lowest resolution to highest.
75 std::sort(m_imagesInSet.begin(), m_imagesInSet.end(), CSSImageSetValue::compareByScaleFactor);
78 CSSImageSetValue::ImageWithScale CSSImageSetValue::bestImageForScaleFactor()
81 size_t numberOfImages = m_imagesInSet.size();
82 for (size_t i = 0; i < numberOfImages; ++i) {
83 image = m_imagesInSet.at(i);
84 if (image.scaleFactor >= m_scaleFactor)
90 StyleCachedImageSet* CSSImageSetValue::cachedImageSet(CachedResourceLoader* loader)
94 Document* document = loader->document();
95 if (Page* page = document->page())
96 m_scaleFactor = page->deviceScaleFactor();
100 if (!m_imagesInSet.size())
103 if (!m_accessedBestFitImage) {
104 // FIXME: In the future, we want to take much more than deviceScaleFactor into acount here.
105 // All forms of scale should be included: Page::pageScaleFactor(), Frame::pageZoomFactor(),
106 // and any CSS transforms. https://bugs.webkit.org/show_bug.cgi?id=81698
107 ImageWithScale image = bestImageForScaleFactor();
108 ResourceRequest request(loader->document()->completeURL(image.imageURL));
109 if (CachedResourceHandle<CachedImage> cachedImage = loader->requestImage(request)) {
110 m_imageSet = StyleCachedImageSet::create(cachedImage.get(), image.scaleFactor, this);
111 m_accessedBestFitImage = true;
115 return (m_imageSet && m_imageSet->isCachedImageSet()) ? static_cast<StyleCachedImageSet*>(m_imageSet.get()) : 0;
118 StyleImage* CSSImageSetValue::cachedOrPendingImageSet(Document* document)
121 m_imageSet = StylePendingImage::create(this);
122 else if (document && !m_imageSet->isPendingImage()) {
123 float deviceScaleFactor = 1;
124 if (Page* page = document->page())
125 deviceScaleFactor = page->deviceScaleFactor();
127 // If the deviceScaleFactor has changed, we may not have the best image loaded, so we have to re-assess.
128 if (deviceScaleFactor != m_scaleFactor) {
129 m_accessedBestFitImage = false;
130 m_imageSet = StylePendingImage::create(this);
134 return m_imageSet.get();
137 String CSSImageSetValue::customCssText() const
139 return "-webkit-image-set(" + CSSValueList::customCssText() + ")";
142 CSSImageSetValue::CSSImageSetValue(const CSSImageSetValue& cloneFrom)
143 : CSSValueList(cloneFrom)
144 , m_accessedBestFitImage(false)
147 // Non-CSSValueList data is not accessible through CSS OM, no need to clone.
150 PassRefPtr<CSSImageSetValue> CSSImageSetValue::cloneForCSSOM() const
152 return adoptRef(new CSSImageSetValue(*this));
155 } // namespace WebCore
157 #endif // ENABLE(CSS_IMAGE_SET)