https://bugs.webkit.org/show_bug.cgi?id=80322
Implement image-set

Reviewed by Dean Jackson.

Source/WebCore: 

This initial implementation of -webkit-image-set. 
http://lists.w3.org/Archives/Public/www-style/2012Feb/1103.html
The idea behind the feature is to allow authors to provide multiple variants 
of the same image at differing resolutions, and to allow the User Agent to 
choose the resource that is most appropriate at the time. This patch will 
choose the most appropriate image based on device scale factor.

CSSImageSetValue inherits from CSSValueList and behaves a lot like 
CSSImageValue.
* WebCore.xcodeproj/project.pbxproj:
* css/CSSImageSetValue.h: Added.
(WebCore):
(CSSImageSetValue):
(WebCore::CSSImageSetValue::create):
(WebCore::CSSImageSetValue::isPending):
(ImageWithScale):
(WebCore::CSSImageSetValue::compareByScaleFactor):
* css/CSSImageSetValue.cpp: Added.
(WebCore):
(WebCore::CSSImageSetValue::CSSImageSetValue):
(WebCore::CSSImageSetValue::~CSSImageSetValue):
(WebCore::CSSImageSetValue::cachedOrPendingImageSet):
(WebCore::CSSImageSetValue::customCssText):

fillImageSet() iterates through the value list and turns the information into 
a sorted Vector of ImageWithScales (which is a struct containing image URLs 
and scale factors).
(WebCore::CSSImageSetValue::fillImageSet):

cachedImageSet() finds which image is most appropriate based on the device 
scale factor, and it loads only that image. In the future, additional scale 
factors will be taken into account.
(WebCore::CSSImageSetValue::bestImageForScaleFactor):
(WebCore::CSSImageSetValue::cachedImageSet):

parseImageSet() is called everywhere in the CSSParser that a regular image or 
generated image can be found.
* css/CSSParser.cpp:
(WebCore::CSSParser::parseValue):
(WebCore::CSSParser::parseContent):
(WebCore::CSSParser::parseFillImage):
(WebCore::CSSParser::parseBorderImage):
(WebCore):
(WebCore::CSSParser::parseImageSet):
* css/CSSParser.h:

Since CSSImageSetValue is implemented as a value list, 
ApplyPropertyFillLayer::applyValue() needs to be more specific when it's 
looking for a list of multiple URLs.
* css/CSSStyleApplyProperty.cpp:
(WebCore::ApplyPropertyFillLayer::applyValue):

Handle image-set as a valid image value.
* css/CSSStyleSelector.cpp:
(WebCore::CSSStyleSelector::collectMatchingRulesForList):
* css/CSSStyleSelector.h:
(CSSStyleSelector):
* css/CSSValue.cpp:
(WebCore::CSSValue::cssText):
(WebCore::CSSValue::destroy):
* css/CSSValue.h:
(CSSValue):
(WebCore::CSSValue::isImageSetValue):

computeIntrinsicDimensions() now takes an optional scaleFactor parameter that represents the author-enforced "intrinsic" scale factor of the image.
* loader/cache/CachedImage.cpp:
(WebCore::CachedImage::computeIntrinsicDimensions):
* loader/cache/CachedImage.h:
(CachedImage):
* platform/graphics/GeneratedImage.h:
(GeneratedImage):
* platform/graphics/GeneratorGeneratedImage.cpp:
(WebCore::GeneratedImage::computeIntrinsicDimensions):
* platform/graphics/Image.cpp:
(WebCore::Image::computeIntrinsicDimensions):
* platform/graphics/Image.h:
(Image):
* platform/graphics/cg/PDFDocumentImage.cpp:
(WebCore::PDFDocumentImage::computeIntrinsicDimensions):
* platform/graphics/cg/PDFDocumentImage.h:
(PDFDocumentImage):
* svg/graphics/SVGImage.cpp:
(WebCore::SVGImage::computeIntrinsicDimensions):
* svg/graphics/SVGImage.h:
(SVGImage):

Inherits from StyleImage and returns a scaled size for imageSize() and 
computeIntrinsicDimensions().
* rendering/style/StyleCachedImageSet.cpp: Added.
(WebCore):
(WebCore::StyleCachedImageSet::StyleCachedImageSet):
(WebCore::StyleCachedImageSet::cssValue):
(WebCore::StyleCachedImageSet::canRender):
(WebCore::StyleCachedImageSet::isLoaded):
(WebCore::StyleCachedImageSet::errorOccurred):
(WebCore::StyleCachedImageSet::imageSize):
(WebCore::StyleCachedImageSet::imageHasRelativeWidth):
(WebCore::StyleCachedImageSet::imageHasRelativeHeight):
(WebCore::StyleCachedImageSet::computeIntrinsicDimensions):
(WebCore::StyleCachedImageSet::usesImageContainerSize):
(WebCore::StyleCachedImageSet::setContainerSizeForRenderer):
(WebCore::StyleCachedImageSet::addClient):
(WebCore::StyleCachedImageSet::removeClient):
(WebCore::StyleCachedImageSet::image):
* rendering/style/StyleCachedImageSet.h: Added.
(WebCore):
(StyleCachedImageSet):
(WebCore::StyleCachedImageSet::create):
(WebCore::StyleCachedImageSet::data):
(WebCore::StyleCachedImageSet::cachedImage):

Handle image-set.
* rendering/style/StyleImage.h:
(WebCore::StyleImage::isCachedImageSet):
(WebCore::StyleImage::StyleImage):
(StyleImage):
* rendering/style/StylePendingImage.h:
(StylePendingImage):
(WebCore::StylePendingImage::cssImageSetValue):

Source/WTF: 

For the time being, image-set is opt-in since the implementation is 
incomplete. 

Add an ENABLE flag for image-set.
* wtf/Platform.h:

LayoutTests: 

* fast/css/image-set-parsing-expected.txt: Added.
* fast/css/image-set-parsing-invalid-expected.txt: Added.
* fast/css/image-set-parsing-invalid.html: Added.
* fast/css/image-set-parsing.html: Added.
* fast/css/script-tests/image-set-parsing-invalid.js: Added.
(testInvalidImageSet):
* fast/css/script-tests/image-set-parsing.js: Added.
(jsWrapperClass):
(shouldBeType):
(testImageSetRule):
* fast/hidpi/image-set-as-background.html: Added.
* fast/hidpi/image-set-background-repeat-without-size.html: Added.
* fast/hidpi/image-set-background-repeat.html: Added.
* fast/hidpi/image-set-border-image-simple.html: Added.
* fast/hidpi/image-set-out-of-order.html: Added.
* fast/hidpi/image-set-simple.html: Added.
* fast/hidpi/image-set-without-specified-width.html: Added.
* fast/hidpi/resources: Added.
* fast/hidpi/resources/blue-100-px-square.png: Added.
* fast/hidpi/resources/deleteButton-2x.png: Added.
* fast/hidpi/resources/deleteButton.png: Added.
* fast/hidpi/resources/red-200-px-square.png: Added.
* platform/efl/Skipped:
* platform/gtk/Skipped:
* platform/mac/fast/hidpi/image-set-as-background-expected.png: Added.
* platform/mac/fast/hidpi/image-set-as-background-expected.txt: Added.
* platform/mac/fast/hidpi/image-set-background-repeat-expected.png: Added.
* platform/mac/fast/hidpi/image-set-background-repeat-expected.txt: Added.
* platform/mac/fast/hidpi/image-set-background-repeat-without-size-expected.png: Added.
* platform/mac/fast/hidpi/image-set-background-repeat-without-size-expected.txt: Added.
* platform/mac/fast/hidpi/image-set-border-image-simple-expected.png: Added.
* platform/mac/fast/hidpi/image-set-border-image-simple-expected.txt: Added.
* platform/mac/fast/hidpi/image-set-out-of-order-expected.png: Added.
* platform/mac/fast/hidpi/image-set-out-of-order-expected.txt: Added.
* platform/mac/fast/hidpi/image-set-simple-expected.png: Added.
* platform/mac/fast/hidpi/image-set-simple-expected.txt: Added.
* platform/mac/fast/hidpi/image-set-without-specified-width-expected.png: Added.
* platform/mac/fast/hidpi/image-set-without-specified-width-expected.txt: Added.
* platform/qt/Skipped:
* platform/win/Skipped:
* platform/wincairo/Skipped:



git-svn-id: http://svn.webkit.org/repository/webkit/trunk@111637 268f45cc-cd09-0410-ab3c-d52691b4dbfc
diff --git a/LayoutTests/fast/hidpi/image-set-border-image-simple.html b/LayoutTests/fast/hidpi/image-set-border-image-simple.html
new file mode 100644
index 0000000..211f50d
--- /dev/null
+++ b/LayoutTests/fast/hidpi/image-set-border-image-simple.html
@@ -0,0 +1,46 @@
+<html>
+<head>
+<script>
+    function runTest() {
+        if (!window.layoutTestController || !window.sessionStorage)
+            return;
+
+        if (!sessionStorage.scaleFactorIsSet) {
+            layoutTestController.waitUntilDone();
+            layoutTestController.setBackingScaleFactor(2, scaleFactorIsSet);
+        }
+        
+        if (sessionStorage.pageReloaded && sessionStorage.scaleFactorIsSet) {
+            delete sessionStorage.pageReloaded;
+            delete sessionStorage.scaleFactorIsSet;
+            layoutTestController.notifyDone();
+        } else {
+            // Right now there is a bug that image-set does not properly deal with dynamic changes to the scale factor,
+            // so to work around that, we must reload the page to get the 2x image.
+            sessionStorage.pageReloaded = true;
+            document.location.reload(true);
+        }
+    }
+    
+    function scaleFactorIsSet() {
+        sessionStorage.scaleFactorIsSet = true;
+    }
+
+    window.onload = runTest;
+</script>
+    
+<style>
+    #foo {
+        width:100px;
+        height:100px;
+        border-width: 10px;
+        -webkit-border-image: -webkit-image-set(url('resources/blue-100-px-square.png') 1x, url('resources/green-200-px-square.png') 2x) 10 10 10 10 stretch stretch;
+    }
+</style>
+</head>
+
+<body id="body">
+    <div>This test passes if the div below is a blue 100px square when the deviceScaleFactor is 1, and if it is a 100px green square when the deviceScaleFactor is 2.</div>
+    <div id=foo></div>
+</body>
+</html>