https://bugs.webkit.org/show_bug.cgi?id=80322
authorbdakin@apple.com <bdakin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 22 Mar 2012 01:36:29 +0000 (01:36 +0000)
committerbdakin@apple.com <bdakin@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 22 Mar 2012 01:36:29 +0000 (01:36 +0000)
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: https://svn.webkit.org/repository/webkit/trunk@111637 268f45cc-cd09-0410-ab3c-d52691b4dbfc

71 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/css/image-set-parsing-expected.txt [new file with mode: 0644]
LayoutTests/fast/css/image-set-parsing-invalid-expected.txt [new file with mode: 0644]
LayoutTests/fast/css/image-set-parsing-invalid.html [new file with mode: 0644]
LayoutTests/fast/css/image-set-parsing.html [new file with mode: 0644]
LayoutTests/fast/css/script-tests/image-set-parsing-invalid.js [new file with mode: 0644]
LayoutTests/fast/css/script-tests/image-set-parsing.js [new file with mode: 0644]
LayoutTests/fast/hidpi/image-set-as-background.html [new file with mode: 0644]
LayoutTests/fast/hidpi/image-set-background-repeat-without-size.html [new file with mode: 0644]
LayoutTests/fast/hidpi/image-set-background-repeat.html [new file with mode: 0644]
LayoutTests/fast/hidpi/image-set-border-image-simple.html [new file with mode: 0644]
LayoutTests/fast/hidpi/image-set-out-of-order.html [new file with mode: 0644]
LayoutTests/fast/hidpi/image-set-simple.html [new file with mode: 0644]
LayoutTests/fast/hidpi/image-set-without-specified-width.html [new file with mode: 0644]
LayoutTests/fast/hidpi/resources/blue-100-px-square.png [new file with mode: 0644]
LayoutTests/fast/hidpi/resources/deleteButton-2x.png [new file with mode: 0644]
LayoutTests/fast/hidpi/resources/deleteButton.png [new file with mode: 0644]
LayoutTests/fast/hidpi/resources/green-200-px-square.png [new file with mode: 0644]
LayoutTests/platform/chromium/test_expectations.txt
LayoutTests/platform/efl/Skipped
LayoutTests/platform/gtk/Skipped
LayoutTests/platform/mac/fast/hidpi/broken-image-icon-hidpi-expected.png
LayoutTests/platform/mac/fast/hidpi/broken-image-with-size-hidpi-expected.png
LayoutTests/platform/mac/fast/hidpi/clip-text-in-hidpi-expected.png
LayoutTests/platform/mac/fast/hidpi/focus-rings-expected.png
LayoutTests/platform/mac/fast/hidpi/image-set-as-background-expected.png [new file with mode: 0644]
LayoutTests/platform/mac/fast/hidpi/image-set-as-background-expected.txt [new file with mode: 0644]
LayoutTests/platform/mac/fast/hidpi/image-set-background-repeat-expected.png [new file with mode: 0644]
LayoutTests/platform/mac/fast/hidpi/image-set-background-repeat-expected.txt [new file with mode: 0644]
LayoutTests/platform/mac/fast/hidpi/image-set-background-repeat-without-size-expected.png [new file with mode: 0644]
LayoutTests/platform/mac/fast/hidpi/image-set-background-repeat-without-size-expected.txt [new file with mode: 0644]
LayoutTests/platform/mac/fast/hidpi/image-set-border-image-simple-expected.png [new file with mode: 0644]
LayoutTests/platform/mac/fast/hidpi/image-set-border-image-simple-expected.txt [new file with mode: 0644]
LayoutTests/platform/mac/fast/hidpi/image-set-out-of-order-expected.png [new file with mode: 0644]
LayoutTests/platform/mac/fast/hidpi/image-set-out-of-order-expected.txt [new file with mode: 0644]
LayoutTests/platform/mac/fast/hidpi/image-set-simple-expected.png [new file with mode: 0644]
LayoutTests/platform/mac/fast/hidpi/image-set-simple-expected.txt [new file with mode: 0644]
LayoutTests/platform/mac/fast/hidpi/image-set-without-specified-width-expected.png [new file with mode: 0644]
LayoutTests/platform/mac/fast/hidpi/image-set-without-specified-width-expected.txt [new file with mode: 0644]
LayoutTests/platform/mac/fast/hidpi/resize-corner-hidpi-expected.png
LayoutTests/platform/mac/fast/hidpi/video-controls-in-hidpi-expected.png
LayoutTests/platform/qt/Skipped
LayoutTests/platform/win/Skipped
LayoutTests/platform/wincairo/Skipped
Source/WTF/ChangeLog
Source/WTF/wtf/Platform.h
Source/WebCore/ChangeLog
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/css/CSSImageSetValue.cpp [new file with mode: 0644]
Source/WebCore/css/CSSImageSetValue.h [new file with mode: 0644]
Source/WebCore/css/CSSParser.cpp
Source/WebCore/css/CSSParser.h
Source/WebCore/css/CSSStyleApplyProperty.cpp
Source/WebCore/css/CSSStyleSelector.cpp
Source/WebCore/css/CSSStyleSelector.h
Source/WebCore/css/CSSValue.cpp
Source/WebCore/css/CSSValue.h
Source/WebCore/loader/cache/CachedImage.cpp
Source/WebCore/loader/cache/CachedImage.h
Source/WebCore/platform/graphics/GeneratedImage.h
Source/WebCore/platform/graphics/GeneratorGeneratedImage.cpp
Source/WebCore/platform/graphics/Image.cpp
Source/WebCore/platform/graphics/Image.h
Source/WebCore/platform/graphics/cg/PDFDocumentImage.cpp
Source/WebCore/platform/graphics/cg/PDFDocumentImage.h
Source/WebCore/rendering/style/StyleCachedImageSet.cpp [new file with mode: 0644]
Source/WebCore/rendering/style/StyleCachedImageSet.h [new file with mode: 0644]
Source/WebCore/rendering/style/StyleImage.h
Source/WebCore/rendering/style/StylePendingImage.h
Source/WebCore/svg/graphics/SVGImage.cpp
Source/WebCore/svg/graphics/SVGImage.h

index 118b7e5..84f5327 100644 (file)
@@ -1,3 +1,52 @@
+2012-03-21  Beth Dakin  <bdakin@apple.com>
+
+        https://bugs.webkit.org/show_bug.cgi?id=80322
+        Implement image-set
+
+        Reviewed by Dean Jackson.
+
+        * 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:
+
 2012-03-21  Emil A Eklund  <eae@chromium.org>
 
         Unreviewed test_expectations update for chromium.
diff --git a/LayoutTests/fast/css/image-set-parsing-expected.txt b/LayoutTests/fast/css/image-set-parsing-expected.txt
new file mode 100644 (file)
index 0000000..a3eb9ad
--- /dev/null
@@ -0,0 +1,93 @@
+Test the parsing of the -webkit-image-set function.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+
+Single value for background-image : url('#a') 1x
+PASS jsWrapperClass(imageSetRule) is 'CSSValueList'
+PASS jsWrapperClass(imageSetRule.__proto__) is 'CSSValueListPrototype'
+PASS jsWrapperClass(imageSetRule.constructor) is 'CSSValueListConstructor'
+PASS imageSetRule.length is 2
+PASS subRule is 'a'
+PASS subRule.cssText is '1'
+
+Multiple values for background-image : url('#a') 1x, url('#b') 2x
+PASS jsWrapperClass(imageSetRule) is 'CSSValueList'
+PASS jsWrapperClass(imageSetRule.__proto__) is 'CSSValueListPrototype'
+PASS jsWrapperClass(imageSetRule.constructor) is 'CSSValueListConstructor'
+PASS imageSetRule.length is 4
+PASS subRule is 'a'
+PASS subRule.cssText is '1'
+PASS subRule is 'b'
+PASS subRule.cssText is '2'
+
+Multiple values for background-image, out of order : url('#c') 3x, url('#b') 2x, url('#a') 1x
+PASS jsWrapperClass(imageSetRule) is 'CSSValueList'
+PASS jsWrapperClass(imageSetRule.__proto__) is 'CSSValueListPrototype'
+PASS jsWrapperClass(imageSetRule.constructor) is 'CSSValueListConstructor'
+PASS imageSetRule.length is 6
+PASS subRule is 'c'
+PASS subRule.cssText is '3'
+PASS subRule is 'b'
+PASS subRule.cssText is '2'
+PASS subRule is 'a'
+PASS subRule.cssText is '1'
+
+Single value for content : url('#a') 1x
+PASS jsWrapperClass(imageSetRule) is 'CSSValueList'
+PASS jsWrapperClass(imageSetRule.__proto__) is 'CSSValueListPrototype'
+PASS jsWrapperClass(imageSetRule.constructor) is 'CSSValueListConstructor'
+PASS imageSetRule.length is 2
+PASS subRule is 'a'
+PASS subRule.cssText is '1'
+
+Multiple values for content : url('#a') 1x, url('#b') 2x
+PASS jsWrapperClass(imageSetRule) is 'CSSValueList'
+PASS jsWrapperClass(imageSetRule.__proto__) is 'CSSValueListPrototype'
+PASS jsWrapperClass(imageSetRule.constructor) is 'CSSValueListConstructor'
+PASS imageSetRule.length is 4
+PASS subRule is 'a'
+PASS subRule.cssText is '1'
+PASS subRule is 'b'
+PASS subRule.cssText is '2'
+
+Single value for border-image : url('#a') 1x
+PASS jsWrapperClass(imageSetRule) is 'CSSValueList'
+PASS jsWrapperClass(imageSetRule.__proto__) is 'CSSValueListPrototype'
+PASS jsWrapperClass(imageSetRule.constructor) is 'CSSValueListConstructor'
+PASS imageSetRule.length is 2
+PASS subRule is 'a'
+PASS subRule.cssText is '1'
+
+Multiple values for border-image : url('#a') 1x, url('#b') 2x
+PASS jsWrapperClass(imageSetRule) is 'CSSValueList'
+PASS jsWrapperClass(imageSetRule.__proto__) is 'CSSValueListPrototype'
+PASS jsWrapperClass(imageSetRule.constructor) is 'CSSValueListConstructor'
+PASS imageSetRule.length is 4
+PASS subRule is 'a'
+PASS subRule.cssText is '1'
+PASS subRule is 'b'
+PASS subRule.cssText is '2'
+
+Single value for -webkit-mask-box-image : url('#a') 1x
+PASS jsWrapperClass(imageSetRule) is 'CSSValueList'
+PASS jsWrapperClass(imageSetRule.__proto__) is 'CSSValueListPrototype'
+PASS jsWrapperClass(imageSetRule.constructor) is 'CSSValueListConstructor'
+PASS imageSetRule.length is 2
+PASS subRule is 'a'
+PASS subRule.cssText is '1'
+
+Multiple values for -webkit-mask-box-image : url('#a') 1x, url('#b') 2x
+PASS jsWrapperClass(imageSetRule) is 'CSSValueList'
+PASS jsWrapperClass(imageSetRule.__proto__) is 'CSSValueListPrototype'
+PASS jsWrapperClass(imageSetRule.constructor) is 'CSSValueListConstructor'
+PASS imageSetRule.length is 4
+PASS subRule is 'a'
+PASS subRule.cssText is '1'
+PASS subRule is 'b'
+PASS subRule.cssText is '2'
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/css/image-set-parsing-invalid-expected.txt b/LayoutTests/fast/css/image-set-parsing-invalid-expected.txt
new file mode 100644 (file)
index 0000000..9239558
--- /dev/null
@@ -0,0 +1,27 @@
+Test the parsing of the -webkit-image-set function.
+
+On success, you will see a series of "PASS" messages, followed by "TEST COMPLETE".
+
+
+
+Too many url parameters : url(#a #b)
+PASS cssRule is null
+
+No x : url('#a') 1
+PASS cssRule is null
+
+No comma : url('#a') 1x url('#b') 2x
+PASS cssRule is null
+
+Too many scale factor parameters : url('#a') 1x 2x
+PASS cssRule is null
+
+Scale factor is 0 : url('#a') 0x
+PASS cssRule is null
+
+No url function : '#a' 1x
+PASS cssRule is null
+PASS successfullyParsed is true
+
+TEST COMPLETE
+
diff --git a/LayoutTests/fast/css/image-set-parsing-invalid.html b/LayoutTests/fast/css/image-set-parsing-invalid.html
new file mode 100644 (file)
index 0000000..869df66
--- /dev/null
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../js/resources/js-test-pre.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script src="script-tests/image-set-parsing-invalid.js"></script>
+<script src="../js/resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/fast/css/image-set-parsing.html b/LayoutTests/fast/css/image-set-parsing.html
new file mode 100644 (file)
index 0000000..daa2f1e
--- /dev/null
@@ -0,0 +1,12 @@
+<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
+<html>
+<head>
+<script src="../js/resources/js-test-pre.js"></script>
+</head>
+<body>
+<p id="description"></p>
+<div id="console"></div>
+<script src="script-tests/image-set-parsing.js"></script>
+<script src="../js/resources/js-test-post.js"></script>
+</body>
+</html>
diff --git a/LayoutTests/fast/css/script-tests/image-set-parsing-invalid.js b/LayoutTests/fast/css/script-tests/image-set-parsing-invalid.js
new file mode 100644 (file)
index 0000000..a84205e
--- /dev/null
@@ -0,0 +1,28 @@
+description("Test the parsing of the -webkit-image-set function.");
+
+// These have to be global for the test helpers to see them.
+var cssRule;
+
+function testInvalidImageSet(description, property, rule)
+{
+    debug("");
+    debug(description + " : " + rule);
+
+    var div = document.createElement("div");
+    div.setAttribute("style", property + ": -webkit-image-set(" + rule + ")");
+    document.body.appendChild(div);
+
+    cssRule = div.style.getPropertyCSSValue(property);
+    shouldBe("cssRule", "null");
+
+    document.body.removeChild(div);
+}
+
+testInvalidImageSet("Too many url parameters", "background-image", "url(#a #b)");
+testInvalidImageSet("No x", "background-image", "url('#a') 1");
+testInvalidImageSet("No comma", "background-image", "url('#a') 1x url('#b') 2x");
+testInvalidImageSet("Too many scale factor parameters", "background-image", "url('#a') 1x 2x");
+testInvalidImageSet("Scale factor is 0", "background-image", "url('#a') 0x");
+testInvalidImageSet("No url function", "background-image", "'#a' 1x");
+
+successfullyParsed = true;
diff --git a/LayoutTests/fast/css/script-tests/image-set-parsing.js b/LayoutTests/fast/css/script-tests/image-set-parsing.js
new file mode 100644 (file)
index 0000000..666abdc
--- /dev/null
@@ -0,0 +1,110 @@
+description("Test the parsing of the -webkit-image-set function.");
+
+function jsWrapperClass(node)
+{
+    if (!node)
+        return "[null]";
+    var string = Object.prototype.toString.apply(node);
+    return string.substr(8, string.length - 9);
+}
+
+function shouldBeType(expression, className, prototypeName, constructorName)
+{
+    if (!prototypeName)
+        prototypeName = className + "Prototype";
+    if (!constructorName)
+        constructorName = className + "Constructor";
+    shouldBe("jsWrapperClass(" + expression + ")", "'" + className + "'");
+    shouldBe("jsWrapperClass(" + expression + ".__proto__)", "'" + prototypeName + "'");
+    shouldBe("jsWrapperClass(" + expression + ".constructor)", "'" + constructorName + "'");
+}
+
+// These have to be global for the test helpers to see them.
+var imageSetRule, subRule;
+
+function testImageSetRule(description, property, rule, expectedLength, expectedTexts)
+{
+    debug("");
+    debug(description + " : " + rule);
+
+    var div = document.createElement("div");
+    div.setAttribute("style", property + ": -webkit-image-set(" + rule + ")");
+    document.body.appendChild(div);
+
+    imageSetRule = div.style.getPropertyCSSValue(property);
+    shouldBeType("imageSetRule", "CSSValueList");
+
+    if (imageSetRule) {
+        if (jsWrapperClass(imageSetRule[0]) == "CSSValueList") {
+            // The content property returns a CSSValueList anyway, so to get to the 
+            // imageSet CSS value list, we have to look at the first entry in the 
+            // content value list.
+            imageSetRule = imageSetRule[0];
+        }
+    }
+
+    shouldBe("imageSetRule.length", "" + expectedLength); // shouldBe expects string arguments
+
+    if (imageSetRule) {
+        for (var i = 0; i < expectedLength; i++) {
+            string = imageSetRule[i];
+            if (i % 2 == 0) {
+                subRule = string.cssText.split('#')[1];
+                subRule = subRule.split(')')[0];
+                shouldBe("subRule", "'" + expectedTexts[i] + "'");
+            } else {
+                subRule = string;
+                shouldBe("subRule.cssText", "'" + expectedTexts[i] + "'");
+            }
+        }
+    }
+
+    document.body.removeChild(div);
+}
+
+testImageSetRule("Single value for background-image",
+                "background-image",
+                "url('#a') 1x", 2,
+                ["a", "1"]);
+
+testImageSetRule("Multiple values for background-image",
+                "background-image",
+                "url('#a') 1x, url('#b') 2x", 4,
+                ["a", "1", "b", "2"]);
+
+testImageSetRule("Multiple values for background-image, out of order",
+                "background-image",
+                "url('#c') 3x, url('#b') 2x, url('#a') 1x", 6,
+                ["c", "3", "b", "2", "a", "1"]);
+
+testImageSetRule("Single value for content",
+                "content",
+                "url('#a') 1x", 2,
+                ["a", "1"]);
+
+testImageSetRule("Multiple values for content",
+                "content",
+                "url('#a') 1x, url('#b') 2x", 4,
+                ["a", "1", "b", "2"]);
+
+testImageSetRule("Single value for border-image",
+                "-webkit-border-image",
+                "url('#a') 1x", 2,
+                ["a", "1"]);
+
+testImageSetRule("Multiple values for border-image",
+                "-webkit-border-image",
+                "url('#a') 1x, url('#b') 2x", 4,
+                ["a", "1", "b", "2"]);
+
+testImageSetRule("Single value for -webkit-mask-box-image",
+                "-webkit-mask-box-image",
+                "url('#a') 1x", 2,
+                ["a", "1"]);
+
+testImageSetRule("Multiple values for -webkit-mask-box-image",
+                "-webkit-mask-box-image",
+                "url('#a') 1x, url('#b') 2x", 4,
+                ["a", "1", "b", "2"]);
+
+successfullyParsed = true;
diff --git a/LayoutTests/fast/hidpi/image-set-as-background.html b/LayoutTests/fast/hidpi/image-set-as-background.html
new file mode 100644 (file)
index 0000000..382c402
--- /dev/null
@@ -0,0 +1,45 @@
+<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;
+        background-image: -webkit-image-set(url('resources/blue-100-px-square.png') 1x, url('resources/green-200-px-square.png') 2x);
+    }
+</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>
diff --git a/LayoutTests/fast/hidpi/image-set-background-repeat-without-size.html b/LayoutTests/fast/hidpi/image-set-background-repeat-without-size.html
new file mode 100644 (file)
index 0000000..867acf2
--- /dev/null
@@ -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:90px;
+        height:90px;
+        background-image: -webkit-image-set(url('resources/deleteButton.png') 1x, url('resources/deleteButton-2x.png') 2x);
+        background-repeat: repeat;
+    }
+</style>
+</head>
+
+<body id="body">
+    <div>This test passes if the div below contains 9 evenly spaced delete buttons, and if the high resolution resource is used when the deviceScaleFactor is 2.</div>
+    <div id=foo></div>
+</body>
+</html>
diff --git a/LayoutTests/fast/hidpi/image-set-background-repeat.html b/LayoutTests/fast/hidpi/image-set-background-repeat.html
new file mode 100644 (file)
index 0000000..b51716d
--- /dev/null
@@ -0,0 +1,47 @@
+<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:90px;
+        height:90px;
+        background-image: -webkit-image-set(url('resources/deleteButton.png') 1x, url('resources/deleteButton-2x.png') 2x);
+        background-repeat: repeat;
+        background-size: 30 30;
+    }
+</style>
+</head>
+
+<body id="body">
+    <div>This test passes if the div below contains 9 evenly spaced delete buttons, and if the high resolution resource is used when the deviceScaleFactor is 2.</div>
+    <div id=foo></div>
+</body>
+</html>
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 (file)
index 0000000..211f50d
--- /dev/null
@@ -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>
diff --git a/LayoutTests/fast/hidpi/image-set-out-of-order.html b/LayoutTests/fast/hidpi/image-set-out-of-order.html
new file mode 100644 (file)
index 0000000..670c652
--- /dev/null
@@ -0,0 +1,45 @@
+<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;
+        content: -webkit-image-set(url('resources/green-200-px-square.png') 2x, url('resources/blue-100-px-square.png') 1x);
+    }
+</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>
diff --git a/LayoutTests/fast/hidpi/image-set-simple.html b/LayoutTests/fast/hidpi/image-set-simple.html
new file mode 100644 (file)
index 0000000..1b12b8d
--- /dev/null
@@ -0,0 +1,45 @@
+<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;
+        content: -webkit-image-set(url('resources/blue-100-px-square.png') 1x, url('resources/green-200-px-square.png') 2x);
+    }
+</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>
diff --git a/LayoutTests/fast/hidpi/image-set-without-specified-width.html b/LayoutTests/fast/hidpi/image-set-without-specified-width.html
new file mode 100644 (file)
index 0000000..b808547
--- /dev/null
@@ -0,0 +1,43 @@
+<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 {
+        content: -webkit-image-set(url('resources/blue-100-px-square.png') 1x, url('resources/green-200-px-square.png') 2x);
+    }
+</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>
diff --git a/LayoutTests/fast/hidpi/resources/blue-100-px-square.png b/LayoutTests/fast/hidpi/resources/blue-100-px-square.png
new file mode 100644 (file)
index 0000000..d771cf4
Binary files /dev/null and b/LayoutTests/fast/hidpi/resources/blue-100-px-square.png differ
diff --git a/LayoutTests/fast/hidpi/resources/deleteButton-2x.png b/LayoutTests/fast/hidpi/resources/deleteButton-2x.png
new file mode 100644 (file)
index 0000000..e6046d4
Binary files /dev/null and b/LayoutTests/fast/hidpi/resources/deleteButton-2x.png differ
diff --git a/LayoutTests/fast/hidpi/resources/deleteButton.png b/LayoutTests/fast/hidpi/resources/deleteButton.png
new file mode 100644 (file)
index 0000000..67e2240
Binary files /dev/null and b/LayoutTests/fast/hidpi/resources/deleteButton.png differ
diff --git a/LayoutTests/fast/hidpi/resources/green-200-px-square.png b/LayoutTests/fast/hidpi/resources/green-200-px-square.png
new file mode 100644 (file)
index 0000000..5f611cc
Binary files /dev/null and b/LayoutTests/fast/hidpi/resources/green-200-px-square.png differ
index 7963321..13e41e7 100644 (file)
@@ -3598,6 +3598,10 @@ BUGWK70210 : fast/js/stack-overflow-arrity-catch.html = TEXT
 BUGWK70066 SKIP : fast/hidpi = TIMEOUT
 BUGWK70151 : fast/css/clip-text-in-scaled-div.html = FAIL
 
+// CSS image-set support not yet enabled (needs ENABLE_CSS_IMAGE_SET).
+BUGWK81859 SKIP : fast/css/image-set-parsing.html = FAIL
+BUGWK81859 SKIP : fast/css/image-set-parsing-invalid.html = FAIL
+
 // Flaky tests from ~r97647
 BUGWK70298 : fast/images/pdf-as-background.html = FAIL TIMEOUT PASS
 BUGWK70298 : fast/table/border-collapsing/cached-69296.html = IMAGE PASS
index 66e5bc0..49c3642 100644 (file)
@@ -1956,6 +1956,10 @@ fast/dom/shadow/multiple-shadowroot-adopt.html
 # https://bugs.webkit.org/show_bug.cgi?id=68469
 css3/filters
 
+# CSS image-set support not yet enabled (needs ENABLE_CSS_IMAGE_SET).
+fast/css/image-set-parsing.html
+fast/css/image-set-parsing-invalid.html
+
 # ENABLE_INPUT_TYPE_* are not enabled.
 # https://bugs.webkit.org/show_bug.cgi?id=29359
 # https://bugs.webkit.org/show_bug.cgi?id=68971
index de4c764..a20430d 100644 (file)
@@ -387,6 +387,10 @@ http/tests/security/text-track-crossorigin.html
 # CSS Filters is disabled
 css3/filters
 
+# CSS image-set support not yet enabled (needs ENABLE_CSS_IMAGE_SET).
+fast/css/image-set-parsing.html
+fast/css/image-set-parsing-invalid.html
+
 # Needs layoutTestController.enableAutoResizeMode()
 fast/autoresize
 
index bcb01d0..0d82ac3 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/hidpi/broken-image-icon-hidpi-expected.png and b/LayoutTests/platform/mac/fast/hidpi/broken-image-icon-hidpi-expected.png differ
index 3290e9b..14461d0 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/hidpi/broken-image-with-size-hidpi-expected.png and b/LayoutTests/platform/mac/fast/hidpi/broken-image-with-size-hidpi-expected.png differ
index 41f6a52..e4ef297 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/hidpi/clip-text-in-hidpi-expected.png and b/LayoutTests/platform/mac/fast/hidpi/clip-text-in-hidpi-expected.png differ
index c86f6f8..a4894d8 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/hidpi/focus-rings-expected.png and b/LayoutTests/platform/mac/fast/hidpi/focus-rings-expected.png differ
diff --git a/LayoutTests/platform/mac/fast/hidpi/image-set-as-background-expected.png b/LayoutTests/platform/mac/fast/hidpi/image-set-as-background-expected.png
new file mode 100644 (file)
index 0000000..d8c567d
Binary files /dev/null and b/LayoutTests/platform/mac/fast/hidpi/image-set-as-background-expected.png differ
diff --git a/LayoutTests/platform/mac/fast/hidpi/image-set-as-background-expected.txt b/LayoutTests/platform/mac/fast/hidpi/image-set-as-background-expected.txt
new file mode 100644 (file)
index 0000000..7c54108
--- /dev/null
@@ -0,0 +1,10 @@
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  RenderBlock {HTML} at (0,0) size 800x600
+    RenderBody {BODY} at (8,8) size 784x584
+      RenderBlock {DIV} at (0,0) size 784x36
+        RenderText {#text} at (0,0) size 761x36
+          text run at (0,0) width 761: "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"
+          text run at (0,18) width 207: "when the deviceScaleFactor is 2."
+      RenderBlock {DIV} at (0,36) size 100x100
diff --git a/LayoutTests/platform/mac/fast/hidpi/image-set-background-repeat-expected.png b/LayoutTests/platform/mac/fast/hidpi/image-set-background-repeat-expected.png
new file mode 100644 (file)
index 0000000..6846c3d
Binary files /dev/null and b/LayoutTests/platform/mac/fast/hidpi/image-set-background-repeat-expected.png differ
diff --git a/LayoutTests/platform/mac/fast/hidpi/image-set-background-repeat-expected.txt b/LayoutTests/platform/mac/fast/hidpi/image-set-background-repeat-expected.txt
new file mode 100644 (file)
index 0000000..c06dc43
--- /dev/null
@@ -0,0 +1,10 @@
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  RenderBlock {HTML} at (0,0) size 800x600
+    RenderBody {BODY} at (8,8) size 784x584
+      RenderBlock {DIV} at (0,0) size 784x36
+        RenderText {#text} at (0,0) size 783x36
+          text run at (0,0) width 783: "This test passes if the div below contains 9 evenly spaced delete buttons, and if the high resolution resource is used when the"
+          text run at (0,18) width 145: "deviceScaleFactor is 2."
+      RenderBlock {DIV} at (0,36) size 90x90
diff --git a/LayoutTests/platform/mac/fast/hidpi/image-set-background-repeat-without-size-expected.png b/LayoutTests/platform/mac/fast/hidpi/image-set-background-repeat-without-size-expected.png
new file mode 100644 (file)
index 0000000..6846c3d
Binary files /dev/null and b/LayoutTests/platform/mac/fast/hidpi/image-set-background-repeat-without-size-expected.png differ
diff --git a/LayoutTests/platform/mac/fast/hidpi/image-set-background-repeat-without-size-expected.txt b/LayoutTests/platform/mac/fast/hidpi/image-set-background-repeat-without-size-expected.txt
new file mode 100644 (file)
index 0000000..c06dc43
--- /dev/null
@@ -0,0 +1,10 @@
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  RenderBlock {HTML} at (0,0) size 800x600
+    RenderBody {BODY} at (8,8) size 784x584
+      RenderBlock {DIV} at (0,0) size 784x36
+        RenderText {#text} at (0,0) size 783x36
+          text run at (0,0) width 783: "This test passes if the div below contains 9 evenly spaced delete buttons, and if the high resolution resource is used when the"
+          text run at (0,18) width 145: "deviceScaleFactor is 2."
+      RenderBlock {DIV} at (0,36) size 90x90
diff --git a/LayoutTests/platform/mac/fast/hidpi/image-set-border-image-simple-expected.png b/LayoutTests/platform/mac/fast/hidpi/image-set-border-image-simple-expected.png
new file mode 100644 (file)
index 0000000..9163c60
Binary files /dev/null and b/LayoutTests/platform/mac/fast/hidpi/image-set-border-image-simple-expected.png differ
diff --git a/LayoutTests/platform/mac/fast/hidpi/image-set-border-image-simple-expected.txt b/LayoutTests/platform/mac/fast/hidpi/image-set-border-image-simple-expected.txt
new file mode 100644 (file)
index 0000000..bbe3823
--- /dev/null
@@ -0,0 +1,10 @@
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  RenderBlock {HTML} at (0,0) size 800x600
+    RenderBody {BODY} at (8,8) size 784x584
+      RenderBlock {DIV} at (0,0) size 784x36
+        RenderText {#text} at (0,0) size 761x36
+          text run at (0,0) width 761: "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"
+          text run at (0,18) width 207: "when the deviceScaleFactor is 2."
+      RenderBlock {DIV} at (0,36) size 120x120 [border: (10px none #000000)]
diff --git a/LayoutTests/platform/mac/fast/hidpi/image-set-out-of-order-expected.png b/LayoutTests/platform/mac/fast/hidpi/image-set-out-of-order-expected.png
new file mode 100644 (file)
index 0000000..d8c567d
Binary files /dev/null and b/LayoutTests/platform/mac/fast/hidpi/image-set-out-of-order-expected.png differ
diff --git a/LayoutTests/platform/mac/fast/hidpi/image-set-out-of-order-expected.txt b/LayoutTests/platform/mac/fast/hidpi/image-set-out-of-order-expected.txt
new file mode 100644 (file)
index 0000000..49a77f8
--- /dev/null
@@ -0,0 +1,10 @@
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  RenderBlock {HTML} at (0,0) size 800x600
+    RenderBody {BODY} at (8,8) size 784x584
+      RenderBlock {DIV} at (0,0) size 784x36
+        RenderText {#text} at (0,0) size 761x36
+          text run at (0,0) width 761: "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"
+          text run at (0,18) width 207: "when the deviceScaleFactor is 2."
+      RenderImage {DIV} at (0,36) size 100x100
diff --git a/LayoutTests/platform/mac/fast/hidpi/image-set-simple-expected.png b/LayoutTests/platform/mac/fast/hidpi/image-set-simple-expected.png
new file mode 100644 (file)
index 0000000..d8c567d
Binary files /dev/null and b/LayoutTests/platform/mac/fast/hidpi/image-set-simple-expected.png differ
diff --git a/LayoutTests/platform/mac/fast/hidpi/image-set-simple-expected.txt b/LayoutTests/platform/mac/fast/hidpi/image-set-simple-expected.txt
new file mode 100644 (file)
index 0000000..49a77f8
--- /dev/null
@@ -0,0 +1,10 @@
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  RenderBlock {HTML} at (0,0) size 800x600
+    RenderBody {BODY} at (8,8) size 784x584
+      RenderBlock {DIV} at (0,0) size 784x36
+        RenderText {#text} at (0,0) size 761x36
+          text run at (0,0) width 761: "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"
+          text run at (0,18) width 207: "when the deviceScaleFactor is 2."
+      RenderImage {DIV} at (0,36) size 100x100
diff --git a/LayoutTests/platform/mac/fast/hidpi/image-set-without-specified-width-expected.png b/LayoutTests/platform/mac/fast/hidpi/image-set-without-specified-width-expected.png
new file mode 100644 (file)
index 0000000..d8c567d
Binary files /dev/null and b/LayoutTests/platform/mac/fast/hidpi/image-set-without-specified-width-expected.png differ
diff --git a/LayoutTests/platform/mac/fast/hidpi/image-set-without-specified-width-expected.txt b/LayoutTests/platform/mac/fast/hidpi/image-set-without-specified-width-expected.txt
new file mode 100644 (file)
index 0000000..49a77f8
--- /dev/null
@@ -0,0 +1,10 @@
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  RenderBlock {HTML} at (0,0) size 800x600
+    RenderBody {BODY} at (8,8) size 784x584
+      RenderBlock {DIV} at (0,0) size 784x36
+        RenderText {#text} at (0,0) size 761x36
+          text run at (0,0) width 761: "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"
+          text run at (0,18) width 207: "when the deviceScaleFactor is 2."
+      RenderImage {DIV} at (0,36) size 100x100
index 349e6c9..13caeae 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/hidpi/resize-corner-hidpi-expected.png and b/LayoutTests/platform/mac/fast/hidpi/resize-corner-hidpi-expected.png differ
index 61f5114..60db138 100644 (file)
Binary files a/LayoutTests/platform/mac/fast/hidpi/video-controls-in-hidpi-expected.png and b/LayoutTests/platform/mac/fast/hidpi/video-controls-in-hidpi-expected.png differ
index a688071..e5d99a9 100644 (file)
@@ -301,6 +301,10 @@ css3/filters/filter-property-parsing.html
 css3/filters/filter-property.html
 css3/filters/filter-repaint.html
 
+# CSS image-set support not yet enabled (needs ENABLE_CSS_IMAGE_SET).
+fast/css/image-set-parsing.html
+fast/css/image-set-parsing-invalid.html
+
 # CSS shaders
 css3/filters/custom
 
index 80fb88f..1aec58d 100644 (file)
@@ -40,6 +40,10 @@ css3/filters/effect-sepia-hw.html
 # Custom filters not yet supported on Windows
 css3/filters/custom
 
+# CSS image-set support not yet enabled (needs ENABLE_CSS_IMAGE_SET).
+fast/css/image-set-parsing.html
+fast/css/image-set-parsing-invalid.html
+
 # https://bugs.webkit.org/show_bug.cgi?id=77645
 css3/filters/filtered-compositing-descendant.html
 
index 1216b19..aef7982 100644 (file)
@@ -576,6 +576,10 @@ css3/filters/effect-saturate-hw.html
 css3/filters/effect-sepia-hw.html
 css3/filters/custom
 
+# CSS image-set support not yet enabled (needs ENABLE_CSS_IMAGE_SET).
+fast/css/image-set-parsing.html
+fast/css/image-set-parsing-invalid.html
+
 # Should be moved to platform/mac <rdar://5621425>
 http/tests/misc/willCacheResponse-delegate-callback.html
 
index d5b708d..e07e040 100644 (file)
@@ -1,3 +1,16 @@
+2012-03-21  Beth Dakin  <bdakin@apple.com>
+
+        https://bugs.webkit.org/show_bug.cgi?id=80322
+        Implement image-set
+
+        Reviewed by Dean Jackson.
+
+        For the time being, image-set is opt-in since the implementation is 
+        incomplete. 
+
+        Add an ENABLE flag for image-set.
+        * wtf/Platform.h:
+
 2012-03-21  Jessie Berlin  <jberlin@apple.com>
 
         Fix the Windows build after r111504.
index 6b9e023..50ebbcb 100644 (file)
 #define WTF_USE_ACCELERATED_COMPOSITING 1
 #endif
 
+#if PLATFORM(MAC) || PLATFORM(IOS)
+#define ENABLE_CSS_IMAGE_SET 1
+#endif
+
 /* Compositing on the UI-process in WebKit2 */
 #if PLATFORM(QT)
 #define WTF_USE_UI_SIDE_COMPOSITING 1
index 0cd8a89..09197b4 100644 (file)
@@ -1,3 +1,130 @@
+2012-03-21  Beth Dakin  <bdakin@apple.com>
+
+        https://bugs.webkit.org/show_bug.cgi?id=80322
+        Implement image-set
+
+        Reviewed by Dean Jackson.
+
+        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):
+
 2012-03-21  David Barton  <dbarton@mathscribe.com>
 
         MathML internals - improve naming in RenderMathMLSquareRoot.cpp and RenderMathMLRoot.cpp
index 2bab787..e60a79c 100644 (file)
                9392F1440AD185FE00691BD4 /* RenderCounter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9392F1430AD185FE00691BD4 /* RenderCounter.cpp */; };
                9392F14C0AD1861B00691BD4 /* CounterNode.h in Headers */ = {isa = PBXBuildFile; fileRef = 9392F14B0AD1861B00691BD4 /* CounterNode.h */; };
                9392F1500AD1862300691BD4 /* CounterNode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9392F14F0AD1862300691BD4 /* CounterNode.cpp */; };
+               9393E5FF151A99F200066F06 /* CSSImageSetValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9393E5FD151A99F200066F06 /* CSSImageSetValue.cpp */; };
+               9393E600151A99F200066F06 /* CSSImageSetValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 9393E5FE151A99F200066F06 /* CSSImageSetValue.h */; settings = {ATTRIBUTES = (Private, ); }; };
+               9393E604151A9A1800066F06 /* StyleCachedImageSet.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9393E602151A9A1800066F06 /* StyleCachedImageSet.cpp */; };
+               9393E605151A9A1800066F06 /* StyleCachedImageSet.h in Headers */ = {isa = PBXBuildFile; fileRef = 9393E603151A9A1800066F06 /* StyleCachedImageSet.h */; };
                939885C308B7E3D100E707C4 /* EventNames.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 939885C108B7E3D100E707C4 /* EventNames.cpp */; };
                939885C408B7E3D100E707C4 /* EventNames.h in Headers */ = {isa = PBXBuildFile; fileRef = 939885C208B7E3D100E707C4 /* EventNames.h */; settings = {ATTRIBUTES = (Private, ); }; };
                939B02EE0EA2DBC400C54570 /* WidthIterator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 939B02EC0EA2DBC400C54570 /* WidthIterator.cpp */; };
                9392F1430AD185FE00691BD4 /* RenderCounter.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = RenderCounter.cpp; sourceTree = "<group>"; };
                9392F14B0AD1861B00691BD4 /* CounterNode.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = CounterNode.h; sourceTree = "<group>"; };
                9392F14F0AD1862300691BD4 /* CounterNode.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = CounterNode.cpp; sourceTree = "<group>"; };
+               9393E5FD151A99F200066F06 /* CSSImageSetValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CSSImageSetValue.cpp; sourceTree = "<group>"; };
+               9393E5FE151A99F200066F06 /* CSSImageSetValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSImageSetValue.h; sourceTree = "<group>"; };
+               9393E602151A9A1800066F06 /* StyleCachedImageSet.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = StyleCachedImageSet.cpp; path = style/StyleCachedImageSet.cpp; sourceTree = "<group>"; };
+               9393E603151A9A1800066F06 /* StyleCachedImageSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StyleCachedImageSet.h; path = style/StyleCachedImageSet.h; sourceTree = "<group>"; };
                93955A4103D72932008635CE /* RenderTreeAsText.h */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = RenderTreeAsText.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
                93955A4203D72932008635CE /* RenderTreeAsText.cpp */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderTreeAsText.cpp; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
                939885C108B7E3D100E707C4 /* EventNames.cpp */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.cpp; path = EventNames.cpp; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
                                BC5EB67A0E81D3BE00B25965 /* StyleBoxData.h */,
                                BCEF44790E6747D0001C1287 /* StyleCachedImage.cpp */,
                                BCEF444C0E674628001C1287 /* StyleCachedImage.h */,
+                               9393E602151A9A1800066F06 /* StyleCachedImageSet.cpp */,
+                               9393E603151A9A1800066F06 /* StyleCachedImageSet.h */,
                                5038BE2D1472AD230095E0D1 /* StyleCachedShader.cpp */,
                                5038BE2E1472AD230095E0D1 /* StyleCachedShader.h */,
                                503D0CAD14B5B0BA00F32F57 /* StyleCustomFilterProgram.h */,
                                BC772B360C4EA91E0083285F /* CSSHelper.h */,
                                BC23E76B0DAE88A9009FDC91 /* CSSImageGeneratorValue.cpp */,
                                BC23EE910DAED2BC009FDC91 /* CSSImageGeneratorValue.h */,
+                               9393E5FD151A99F200066F06 /* CSSImageSetValue.cpp */,
+                               9393E5FE151A99F200066F06 /* CSSImageSetValue.h */,
                                A80E6CD40A1989CA007FB8C5 /* CSSImageValue.cpp */,
                                A80E6CD00A1989CA007FB8C5 /* CSSImageValue.h */,
                                A80E6CC10A1989CA007FB8C5 /* CSSImportRule.cpp */,
                                BCE32B9C1517C0B200F542EC /* RenderMultiColumnSet.h in Headers */,
                                BCE93F451517C567008CCF74 /* RenderRegionSet.h in Headers */,
                                1AF89A421518FDEA00E547B5 /* TiledBacking.h in Headers */,
+                               9393E600151A99F200066F06 /* CSSImageSetValue.h in Headers */,
+                               9393E605151A9A1800066F06 /* StyleCachedImageSet.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                FD537352137B651800008DCE /* ZeroPole.cpp in Sources */,
                                BCE32B9E1517C22700F542EC /* RenderMultiColumnSet.cpp in Sources */,
                                BCE93F471517C6D5008CCF74 /* RenderRegionSet.cpp in Sources */,
+                               9393E5FF151A99F200066F06 /* CSSImageSetValue.cpp in Sources */,
+                               9393E604151A9A1800066F06 /* StyleCachedImageSet.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
diff --git a/Source/WebCore/css/CSSImageSetValue.cpp b/Source/WebCore/css/CSSImageSetValue.cpp
new file mode 100644 (file)
index 0000000..99326f5
--- /dev/null
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "CSSImageSetValue.h"
+
+#if ENABLE(CSS_IMAGE_SET)
+
+#include "CSSImageValue.h"
+#include "CSSPrimitiveValue.h"
+#include "CachedResourceLoader.h"
+#include "Document.h"
+#include "Page.h"
+#include "StyleCachedImageSet.h"
+#include "StylePendingImage.h"
+
+namespace WebCore {
+
+CSSImageSetValue::CSSImageSetValue()
+    : CSSValueList(ImageSetClass, CommaSeparator)
+    , m_accessedBestFitImage(false)
+{
+}
+
+CSSImageSetValue::~CSSImageSetValue()
+{
+}
+
+void CSSImageSetValue::fillImageSet()
+{
+    size_t length = this->length();
+    size_t i = 0;
+    while (i < length) {
+        CSSValue* imageValue = item(i);
+        ASSERT(imageValue->isImageValue());
+        String imageURL = static_cast<CSSImageValue*>(imageValue)->url();
+
+        ++i;
+        ASSERT(i < length);
+        CSSValue* scaleFactorValue = item(i);
+        ASSERT(scaleFactorValue->isPrimitiveValue());
+        float scaleFactor = static_cast<CSSPrimitiveValue*>(scaleFactorValue)->getFloatValue();
+
+        ImageWithScale image;
+        image.imageURL = imageURL;
+        image.scaleFactor = scaleFactor;
+        m_imagesInSet.append(image);
+        ++i;
+    }
+
+    // Sort the images so that they are stored in order from lowest resolution to highest.
+    std::sort(m_imagesInSet.begin(), m_imagesInSet.end(), CSSImageSetValue::compareByScaleFactor);
+}
+
+CSSImageSetValue::ImageWithScale CSSImageSetValue::bestImageForScaleFactor(float scaleFactor)
+{
+    ImageWithScale image;
+    size_t numberOfImages = m_imagesInSet.size();
+    for (size_t i = 0; i < numberOfImages; ++i) {
+        image = m_imagesInSet.at(i);
+        if (image.scaleFactor >= scaleFactor)
+            return image;
+    }
+    return image;
+}
+
+StyleCachedImageSet* CSSImageSetValue::cachedImageSet(CachedResourceLoader* loader)
+{
+    Document* document = loader->document();
+    float deviceScaleFactor = 1;
+    if (Page* page = document->page())
+        deviceScaleFactor = page->deviceScaleFactor();
+
+    if (!m_imagesInSet.size())
+        fillImageSet();
+
+    // FIXME: In the future, we want to take much more than deviceScaleFactor into acount here. 
+    // All forms of scale should be included: Page::pageScaleFactor(), Frame::pageZoomFactor(), 
+    // and any CSS transforms. https://bugs.webkit.org/show_bug.cgi?id=81698
+    return cachedImageSet(loader, bestImageForScaleFactor(deviceScaleFactor));
+}
+
+StyleCachedImageSet* CSSImageSetValue::cachedImageSet(CachedResourceLoader* loader, ImageWithScale image)
+{
+    ASSERT(loader);
+
+    if (!m_accessedBestFitImage) {
+        ResourceRequest request(loader->document()->completeURL(image.imageURL));
+        if (CachedImage* cachedImage = loader->requestImage(request)) {
+            m_imageSet = StyleCachedImageSet::create(cachedImage, image.scaleFactor, this);
+            m_accessedBestFitImage = true;
+        }
+    }
+
+    return (m_imageSet && m_imageSet->isCachedImageSet()) ? static_cast<StyleCachedImageSet*>(m_imageSet.get()) : 0;
+}
+
+StyleImage* CSSImageSetValue::cachedOrPendingImageSet()
+{
+    if (!m_imageSet)
+        m_imageSet = StylePendingImage::create(this);
+
+    return m_imageSet.get();
+}
+
+String CSSImageSetValue::customCssText() const
+{
+    return "-webkit-image-set(" + CSSValueList::customCssText() + ")";
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(CSS_IMAGE_SET)
diff --git a/Source/WebCore/css/CSSImageSetValue.h b/Source/WebCore/css/CSSImageSetValue.h
new file mode 100644 (file)
index 0000000..b7418c7
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CSSImageSetValue_h
+#define CSSImageSetValue_h
+
+#if ENABLE(CSS_IMAGE_SET)
+
+#include "CSSValueList.h"
+
+namespace WebCore {
+
+class CachedResourceLoader;
+class StyleCachedImageSet;
+class StyleImage;
+
+class CSSImageSetValue : public CSSValueList {
+public:
+
+    static PassRefPtr<CSSImageSetValue> create()
+    {
+        return adoptRef(new CSSImageSetValue());
+    }
+    ~CSSImageSetValue();
+
+    StyleCachedImageSet* cachedImageSet(CachedResourceLoader*);
+
+    // Returns a StyleCachedImageSet if the best fit image has been cached already, otherwise a StylePendingImage.
+    StyleImage* cachedOrPendingImageSet();
+
+    String customCssText() const;
+
+    bool isPending() const { return !m_accessedBestFitImage; }
+
+    struct ImageWithScale {
+        String imageURL;
+        float scaleFactor;
+    };
+
+protected:
+    ImageWithScale bestImageForScaleFactor(float);
+    StyleCachedImageSet* cachedImageSet(CachedResourceLoader*, ImageWithScale);
+
+private:
+    CSSImageSetValue();
+
+    void fillImageSet();
+    static inline bool compareByScaleFactor(ImageWithScale first, ImageWithScale second) { return first.scaleFactor < second.scaleFactor; }
+
+    RefPtr<StyleImage> m_imageSet;
+    bool m_accessedBestFitImage;
+
+    Vector<ImageWithScale> m_imagesInSet;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(CSS_IMAGE_SET)
+
+#endif // CSSImageSetValue_h
index 9b66bbc..7850475 100644 (file)
@@ -36,6 +36,9 @@
 #include "CSSFontFaceSrcValue.h"
 #include "CSSFunctionValue.h"
 #include "CSSGradientValue.h"
+#if ENABLE(CSS_IMAGE_SET)
+#include "CSSImageSetValue.h"
+#endif
 #include "CSSImageValue.h"
 #include "CSSImportRule.h"
 #include "CSSInheritedValue.h"
@@ -1674,6 +1677,14 @@ bool CSSParser::parseValue(int propId, bool important)
             else
                 return false;
         }
+#if ENABLE(CSS_IMAGE_SET)
+        else if (value->unit == CSSParserValue::Function && equalIgnoringCase(value->function->name, "-webkit-image-set(")) {
+            parsedValue = parseImageSet(m_valueList.get());
+            if (!parsedValue)
+                return false;
+            m_valueList->next();
+        }
+#endif
         break;
 
     case CSSPropertyWebkitTextStrokeWidth:
@@ -3120,6 +3131,12 @@ bool CSSParser::parseContent(int propId, bool important)
                 parsedValue = parseCounterContent(args, true);
                 if (!parsedValue)
                     return false;
+#if ENABLE(CSS_IMAGE_SET)
+            } else if (equalIgnoringCase(val->function->name, "-webkit-image-set(")) {
+                parsedValue = parseImageSet(m_valueList.get());
+                if (!parsedValue)
+                    return false;
+#endif
             } else if (isGeneratedImageValue(val)) {
                 if (!parseGeneratedImage(m_valueList.get(), parsedValue))
                     return false;
@@ -3210,6 +3227,14 @@ bool CSSParser::parseFillImage(CSSParserValueList* valueList, RefPtr<CSSValue>&
 
     if (isGeneratedImageValue(valueList->current()))
         return parseGeneratedImage(valueList, value);
+    
+#if ENABLE(CSS_IMAGE_SET)
+    if (valueList->current()->unit == CSSParserValue::Function && equalIgnoringCase(valueList->current()->function->name, "-webkit-image-set(")) {
+        value = parseImageSet(m_valueList.get());
+        if (value)
+            return true;
+    }
+#endif
 
     return false;
 }
@@ -5735,6 +5760,14 @@ bool CSSParser::parseBorderImage(int propId, RefPtr<CSSValue>& result, bool impo
                     context.commitImage(value);
                 else
                     return false;
+#if ENABLE(CSS_IMAGE_SET)
+            } else if (val->unit == CSSParserValue::Function && equalIgnoringCase(val->function->name, "-webkit-image-set(")) {
+                RefPtr<CSSValue> value = parseImageSet(m_valueList.get());
+                if (value)
+                    context.commitImage(value);
+                else
+                    return false;
+#endif
             } else if (val->id == CSSValueNone)
                 context.commitImage(cssValuePool()->createIdentifierValue(CSSValueNone));
         }
@@ -6769,6 +6802,57 @@ bool CSSParser::parseCanvas(CSSParserValueList* valueList, RefPtr<CSSValue>& can
     return true;
 }
 
+#if ENABLE(CSS_IMAGE_SET)
+PassRefPtr<CSSValue> CSSParser::parseImageSet(CSSParserValueList* valueList)
+{
+    CSSParserValue* function = valueList->current();
+
+    if (function->unit != CSSParserValue::Function)
+        return 0;
+
+    CSSParserValueList* functionArgs = valueList->current()->function->args.get();
+    if (!functionArgs || !functionArgs->size() || !functionArgs->current())
+        return 0;
+
+    RefPtr<CSSImageSetValue> imageSet = CSSImageSetValue::create();
+
+    while (CSSParserValue* arg = functionArgs->current()) { 
+        if (arg->unit != CSSPrimitiveValue::CSS_URI)
+            return 0;
+
+        RefPtr<CSSImageValue> image = CSSImageValue::create(m_styleSheet->completeURL(arg->string));
+        imageSet->append(image);
+    
+        arg = functionArgs->next();
+        if (!arg || arg->unit != CSSPrimitiveValue::CSS_DIMENSION)
+            return 0;
+
+        double imageScaleFactor = 0;
+        const String& string = arg->string;
+        const UChar* current = string.characters();
+        const UChar* end = current + string.length();
+        parseDouble(current, end, 'x', imageScaleFactor);
+        if (imageScaleFactor <= 0)
+            return 0;
+        imageSet->append(cssValuePool()->createValue(imageScaleFactor, CSSPrimitiveValue::CSS_NUMBER));
+
+        // If there are no more arguments, we're done.
+        arg = functionArgs->next();
+        if (!arg)
+            break;
+
+        // If there are more arguments, they should be after a comma.
+        if (arg->unit != CSSParserValue::Operator || arg->iValue != ',')
+            return 0;
+
+        // Skip the comma and move on to the next argument.
+        arg = functionArgs->next();
+    }
+
+    return imageSet;
+}
+#endif
+
 class TransformOperationInfo {
 public:
     TransformOperationInfo(const CSSParserString& name)
index 45c5a44..2134b13 100644 (file)
@@ -195,6 +195,10 @@ public:
 
     bool parseCrossfade(CSSParserValueList*, RefPtr<CSSValue>&);
 
+#if ENABLE(CSS_IMAGE_SET)
+    PassRefPtr<CSSValue> parseImageSet(CSSParserValueList*);
+#endif
+
 #if ENABLE(CSS_FILTERS)
     PassRefPtr<CSSValueList> parseFilter();
     PassRefPtr<WebKitCSSFilterValue> parseBuiltinFilterArguments(CSSParserValueList*, WebKitCSSFilterValue::FilterOperationType);
index b0e25b6..5a1ec71 100644 (file)
@@ -537,7 +537,11 @@ public:
     {
         FillLayer* currChild = (selector->style()->*accessLayersFunction)();
         FillLayer* prevChild = 0;
-        if (value->isValueList()) {
+        if (value->isValueList()
+#if ENABLE(CSS_IMAGE_SET)
+        && !value->isImageSetValue()
+#endif
+        ) {
             /* Walk each value and put it into a layer, creating new layers as needed. */
             CSSValueList* valueList = static_cast<CSSValueList*>(value);
             for (unsigned int i = 0; i < valueList->length(); i++) {
index de8d930..6f5d33e 100644 (file)
 #include "WebKitCSSShaderValue.h"
 #endif
 
+#if ENABLE(CSS_IMAGE_SET)
+#include "CSSImageSetValue.h"
+#include "StyleCachedImageSet.h"
+#endif
+
 using namespace std;
 
 namespace WebCore {
@@ -3039,6 +3044,11 @@ void CSSStyleSelector::applyProperty(int id, CSSValue *value)
             if (item->isImageGeneratorValue()) {
                 m_style->setContent(StyleGeneratedImage::create(static_cast<CSSImageGeneratorValue*>(item)), didSet);
                 didSet = true;
+#if ENABLE(CSS_IMAGE_SET)
+            } else if (item->isImageSetValue()) {
+                m_style->setContent(setOrPendingFromValue(CSSPropertyContent, static_cast<CSSImageSetValue*>(item)), didSet);
+                didSet = true;
+#endif
             }
 
             if (item->isImageValue()) {
@@ -4124,6 +4134,11 @@ PassRefPtr<StyleImage> CSSStyleSelector::styleImage(CSSPropertyID property, CSSV
     if (value->isImageGeneratorValue())
         return generatedOrPendingFromValue(property, static_cast<CSSImageGeneratorValue*>(value));
 
+#if ENABLE(CSS_IMAGE_SET)
+    if (value->isImageSetValue())
+        return setOrPendingFromValue(property, static_cast<CSSImageSetValue*>(value));
+#endif
+
     return 0;
 }
 
@@ -4144,6 +4159,16 @@ PassRefPtr<StyleImage> CSSStyleSelector::generatedOrPendingFromValue(CSSProperty
     return StyleGeneratedImage::create(value);
 }
 
+#if ENABLE(CSS_IMAGE_SET)
+PassRefPtr<StyleImage> CSSStyleSelector::setOrPendingFromValue(CSSPropertyID property, CSSImageSetValue* value)
+{
+    RefPtr<StyleImage> image = value->cachedOrPendingImageSet();
+    if (image && image->isPendingImage())
+        m_pendingImageProperties.add(property);
+    return image.release();
+}
+#endif
+
 void CSSStyleSelector::mapFillImage(CSSPropertyID property, FillLayer* layer, CSSValue* value)
 {
     if (value->isInitialValue()) {
@@ -4496,7 +4521,11 @@ void CSSStyleSelector::mapNinePieceImage(CSSPropertyID property, CSSValue* value
     for (unsigned i = 0 ; i < borderImage->length() ; ++i) {
         CSSValue* current = borderImage->item(i);
 
-        if (current->isImageValue() || current->isImageGeneratorValue())
+        if (current->isImageValue() || current->isImageGeneratorValue()
+#if ENABLE(CSS_IMAGE_SET)
+            || current->isImageSetValue()
+#endif
+            )
             image.setImage(styleImage(imageProperty, current));
         else if (current->isBorderImageSliceValue())
             mapNinePieceImageSlice(current, image);
@@ -5610,6 +5639,13 @@ PassRefPtr<StyleImage> CSSStyleSelector::loadPendingImage(StylePendingImage* pen
         return StyleGeneratedImage::create(imageGeneratorValue);
     }
 
+#if ENABLE(CSS_IMAGE_SET)
+    if (pendingImage->cssImageSetValue()) {
+        CSSImageSetValue* imageSetValue = pendingImage->cssImageSetValue();
+        return imageSetValue->cachedImageSet(cachedResourceLoader);
+    }
+#endif
+
     return 0;
 }
 
index 099a9a7..d2d1755 100644 (file)
@@ -44,6 +44,7 @@ class CSSProperty;
 class CSSFontFace;
 class CSSFontFaceRule;
 class CSSImageGeneratorValue;
+class CSSImageSetValue;
 class CSSImageValue;
 class CSSRuleList;
 class CSSSelector;
@@ -358,6 +359,9 @@ public:
     PassRefPtr<StyleImage> styleImage(CSSPropertyID, CSSValue*);
     PassRefPtr<StyleImage> cachedOrPendingFromValue(CSSPropertyID, CSSImageValue*);
     PassRefPtr<StyleImage> generatedOrPendingFromValue(CSSPropertyID, CSSImageGeneratorValue*);
+#if ENABLE(CSS_IMAGE_SET)
+    PassRefPtr<StyleImage> setOrPendingFromValue(CSSPropertyID, CSSImageSetValue*);
+#endif
 
     bool applyPropertyToRegularStyle() const { return m_applyPropertyToRegularStyle; }
     bool applyPropertyToVisitedLinkStyle() const { return m_applyPropertyToVisitedLinkStyle; }
index aea4ee4..c392b09 100644 (file)
@@ -38,6 +38,7 @@
 #include "CSSFunctionValue.h"
 #include "CSSGradientValue.h"
 #include "CSSImageGeneratorValue.h"
+#include "CSSImageSetValue.h"
 #include "CSSImageValue.h"
 #include "CSSInheritedValue.h"
 #include "CSSInitialValue.h"
@@ -149,6 +150,10 @@ String CSSValue::cssText() const
         return static_cast<const CSSFlexValue*>(this)->customCssText();
     case CalculationClass:
         return static_cast<const CSSCalcValue*>(this)->customCssText();
+#if ENABLE(CSS_IMAGE_SET)
+    case ImageSetClass:
+        return static_cast<const CSSImageSetValue*>(this)->customCssText();
+#endif
 #if ENABLE(CSS_FILTERS)
     case WebKitCSSFilterClass:
         return static_cast<const WebKitCSSFilterValue*>(this)->customCssText();
@@ -249,6 +254,11 @@ void CSSValue::destroy()
     case CalculationClass:
         delete static_cast<CSSCalcValue*>(this);
         return;
+#if ENABLE(CSS_IMAGE_SET)
+    case ImageSetClass:
+        delete static_cast<CSSImageSetValue*>(this);
+        return;
+#endif
 #if ENABLE(CSS_FILTERS)
     case WebKitCSSFilterClass:
         delete static_cast<WebKitCSSFilterValue*>(this);
index 0bbdc36..3eb094d 100644 (file)
@@ -65,6 +65,9 @@ public:
     bool isFontFeatureValue() const { return m_classType == FontFeatureClass; }
     bool isFontValue() const { return m_classType == FontClass; }
     bool isImageGeneratorValue() const { return m_classType >= CanvasClass && m_classType <= RadialGradientClass; }
+#if ENABLE(CSS_IMAGE_SET)
+    bool isImageSetValue() const { return m_classType == ImageSetClass; }
+#endif
     bool isImageValue() const { return m_classType == ImageClass || m_classType == CursorImageClass; }
     bool isImplicitInitialValue() const;
     bool isInheritedValue() const { return m_classType == InheritedClass; }
@@ -137,6 +140,9 @@ protected:
 
         // List class types must appear after ValueListClass.
         ValueListClass,
+#if ENABLE(CSS_IMAGE_SET)
+        ImageSetClass,
+#endif
 #if ENABLE(CSS_FILTERS)
         WebKitCSSFilterClass,
 #endif
index 5b77301..44e210a 100644 (file)
@@ -275,10 +275,10 @@ IntSize CachedImage::imageSizeForRenderer(const RenderObject* renderer, float mu
     return IntSize(width, height);
 }
 
-void CachedImage::computeIntrinsicDimensions(Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio)
+void CachedImage::computeIntrinsicDimensions(Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio, float scaleFactor)
 {
     if (m_image)
-        m_image->computeIntrinsicDimensions(intrinsicWidth, intrinsicHeight, intrinsicRatio);
+        m_image->computeIntrinsicDimensions(intrinsicWidth, intrinsicHeight, intrinsicRatio, scaleFactor);
 }
 
 void CachedImage::notifyObservers(const IntRect* changeRect)
index e7184e1..9639949 100644 (file)
@@ -65,7 +65,7 @@ public:
     
     // This method takes a zoom multiplier that can be used to increase the natural size of the image by the zoom.
     IntSize imageSizeForRenderer(const RenderObject*, float multiplier); // returns the size of the complete image.
-    void computeIntrinsicDimensions(Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio);
+    void computeIntrinsicDimensions(Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio, float scaleFactor = 1);
 
     void removeClientForRenderer(RenderObject*);
     virtual void didAddClient(CachedResourceClient*);
index bec343c..05c178e 100644 (file)
@@ -42,7 +42,7 @@ public:
     virtual bool usesContainerSize() const { return true; }
     virtual bool hasRelativeWidth() const { return true; }
     virtual bool hasRelativeHeight() const { return true; }
-    virtual void computeIntrinsicDimensions(Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio);
+    virtual void computeIntrinsicDimensions(Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio, float scaleFactor = 1);
 
     virtual IntSize size() const { return m_size; }
 
index ad1165f..3757ce3 100644 (file)
@@ -74,9 +74,9 @@ void GeneratorGeneratedImage::drawPattern(GraphicsContext* destContext, const Fl
     imageBuffer->drawPattern(destContext, adjustedSrcRect, adjustedPatternCTM, phase, styleColorSpace, compositeOp, destRect);
 }
 
-void GeneratedImage::computeIntrinsicDimensions(Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio)
+void GeneratedImage::computeIntrinsicDimensions(Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio, float scaleFactor)
 {
-    Image::computeIntrinsicDimensions(intrinsicWidth, intrinsicHeight, intrinsicRatio);
+    Image::computeIntrinsicDimensions(intrinsicWidth, intrinsicHeight, intrinsicRatio, scaleFactor);
     intrinsicRatio = FloatSize();
 }
 
index bb7d3f7..b8d3241 100644 (file)
@@ -167,9 +167,10 @@ void Image::drawTiled(GraphicsContext* ctxt, const FloatRect& dstRect, const Flo
     startAnimation();
 }
 
-void Image::computeIntrinsicDimensions(Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio)
+void Image::computeIntrinsicDimensions(Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio, float scaleFactor)
 {
     intrinsicRatio = size();
+    intrinsicRatio.scale(1 / scaleFactor);
     intrinsicWidth = Length(intrinsicRatio.width(), Fixed);
     intrinsicHeight = Length(intrinsicRatio.height(), Fixed);
 }
index b78fc7d..727b804 100644 (file)
@@ -101,7 +101,7 @@ public:
     virtual bool usesContainerSize() const { return false; }
     virtual bool hasRelativeWidth() const { return false; }
     virtual bool hasRelativeHeight() const { return false; }
-    virtual void computeIntrinsicDimensions(Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio);
+    virtual void computeIntrinsicDimensions(Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio, float scaleFactor = 1);
 
     virtual IntSize size() const = 0;
     IntRect rect() const { return IntRect(IntPoint(), size()); }
index 14fdfc1..616ca5e 100644 (file)
@@ -76,7 +76,7 @@ IntSize PDFDocumentImage::size() const
     return IntSize((int)(fabsf(rotWidth) + 0.5f), (int)(fabsf(rotHeight) + 0.5f));
 }
 
-void PDFDocumentImage::computeIntrinsicDimensions(Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio)
+void PDFDocumentImage::computeIntrinsicDimensions(Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio, float)
 {
     // FIXME: If we want size negotiation with PDF documents as-image, this is the place to implement it (https://bugs.webkit.org/show_bug.cgi?id=12095).
     Image::computeIntrinsicDimensions(intrinsicWidth, intrinsicHeight, intrinsicRatio);
index 4a28e37..eb398d7 100644 (file)
@@ -59,7 +59,7 @@ namespace WebCore {
         virtual void destroyDecodedData(bool /*destroyAll*/ = true) { }
         virtual unsigned decodedSize() const { return 0; }
 
-        virtual void computeIntrinsicDimensions(Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio);
+        virtual void computeIntrinsicDimensions(Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio, float scaleFactor = 1);
         virtual IntSize size() const;
 
         PDFDocumentImage();
diff --git a/Source/WebCore/rendering/style/StyleCachedImageSet.cpp b/Source/WebCore/rendering/style/StyleCachedImageSet.cpp
new file mode 100644 (file)
index 0000000..aa8f85e
--- /dev/null
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "StyleCachedImageSet.h"
+
+#if ENABLE(CSS_IMAGE_SET)
+
+#include "CSSImageSetValue.h"
+#include "CachedImage.h"
+#include "RenderObject.h"
+
+namespace WebCore {
+
+StyleCachedImageSet::StyleCachedImageSet(CachedImage* image, float imageScaleFactor, PassRefPtr<CSSImageSetValue> value)
+    : m_bestFitImage(image)
+    , m_imageScaleFactor(imageScaleFactor)
+    , m_imageSetValue(value)  
+{
+    m_isCachedImageSet = true;
+}
+
+PassRefPtr<CSSValue> StyleCachedImageSet::cssValue() const
+{
+    return m_imageSetValue;
+}
+
+bool StyleCachedImageSet::canRender(const RenderObject* renderer, float multiplier) const
+{
+    return m_bestFitImage->canRender(renderer, multiplier);
+}
+
+bool StyleCachedImageSet::isLoaded() const
+{
+    return m_bestFitImage->isLoaded();
+}
+
+bool StyleCachedImageSet::errorOccurred() const
+{
+    return m_bestFitImage->errorOccurred();
+}
+
+IntSize StyleCachedImageSet::imageSize(const RenderObject* renderer, float multiplier) const
+{
+    IntSize scaledImageSize = m_bestFitImage->imageSizeForRenderer(renderer, multiplier);
+    scaledImageSize.scale(1 / m_imageScaleFactor);
+    return scaledImageSize;
+}
+
+bool StyleCachedImageSet::imageHasRelativeWidth() const
+{
+    return m_bestFitImage->imageHasRelativeWidth();
+}
+
+bool StyleCachedImageSet::imageHasRelativeHeight() const
+{
+    return m_bestFitImage->imageHasRelativeHeight();
+}
+
+void StyleCachedImageSet::computeIntrinsicDimensions(const RenderObject*, Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio)
+{
+    m_bestFitImage->computeIntrinsicDimensions(intrinsicWidth, intrinsicHeight, intrinsicRatio, m_imageScaleFactor);
+}
+
+bool StyleCachedImageSet::usesImageContainerSize() const
+{
+    return m_bestFitImage->usesImageContainerSize();
+}
+
+void StyleCachedImageSet::setContainerSizeForRenderer(const RenderObject* renderer, const IntSize& imageContainerSize, float imageContainerZoomFactor)
+{
+    m_bestFitImage->setContainerSizeForRenderer(renderer, imageContainerSize, imageContainerZoomFactor);
+}
+
+void StyleCachedImageSet::addClient(RenderObject* renderer)
+{
+    m_bestFitImage->addClient(renderer);
+}
+
+void StyleCachedImageSet::removeClient(RenderObject* renderer)
+{
+    m_bestFitImage->removeClientForRenderer(renderer);
+}
+
+PassRefPtr<Image> StyleCachedImageSet::image(RenderObject* renderer, const IntSize&) const
+{
+    return m_bestFitImage->imageForRenderer(renderer);
+}
+
+} // namespace WebCore
+
+#endif // ENABLE(CSS_IMAGE_SET)
diff --git a/Source/WebCore/rendering/style/StyleCachedImageSet.h b/Source/WebCore/rendering/style/StyleCachedImageSet.h
new file mode 100644 (file)
index 0000000..9c74aa5
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * Copyright (C) 2012 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef StyleCachedImageSet_h
+#define StyleCachedImageSet_h
+
+#if ENABLE(CSS_IMAGE_SET)
+
+#include "CachedResourceHandle.h"
+#include "StyleImage.h"
+
+namespace WebCore {
+
+class CachedImage;
+class CSSImageSetValue;
+
+// This class keeps one cached image and has access to a set of alternatives.
+
+class StyleCachedImageSet : public StyleImage {
+public:
+    static PassRefPtr<StyleCachedImageSet> create(CachedImage* image, float imageScaleFactor, CSSImageSetValue* value)
+    {
+        return adoptRef(new StyleCachedImageSet(image, imageScaleFactor, value));
+    }
+
+    virtual PassRefPtr<CSSValue> cssValue() const;
+
+    // FIXME: This is used by StyleImage for equals comparison, but this implementation
+    // only looks at the image from the set that we have loaded. I'm not sure if that is
+    // meaningful enough or not.
+    virtual WrappedImagePtr data() const { return m_bestFitImage.get(); }
+
+    CachedImage* cachedImage() const { return m_bestFitImage.get(); }
+
+    virtual bool canRender(const RenderObject*, float multiplier) const;
+    virtual bool isLoaded() const;
+    virtual bool errorOccurred() const;
+    virtual IntSize imageSize(const RenderObject*, float multiplier) const;
+    virtual bool imageHasRelativeWidth() const;
+    virtual bool imageHasRelativeHeight() const;
+    virtual void computeIntrinsicDimensions(const RenderObject*, Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio);
+    virtual bool usesImageContainerSize() const;
+    virtual void setContainerSizeForRenderer(const RenderObject*, const IntSize&, float);
+    virtual void addClient(RenderObject*);
+    virtual void removeClient(RenderObject*);
+    virtual PassRefPtr<Image> image(RenderObject*, const IntSize&) const;
+    
+private:
+    StyleCachedImageSet(CachedImage*, float imageScaleFactor, PassRefPtr<CSSImageSetValue>);
+
+    CachedResourceHandle<CachedImage> m_bestFitImage;
+    float m_imageScaleFactor;
+    RefPtr<CSSImageSetValue> m_imageSetValue;
+};
+
+} // namespace WebCore
+
+#endif // ENABLE(CSS_IMAGE_SET)
+
+#endif // StyleCachedImageSet_h
index 0a5766b..55537fa 100644 (file)
@@ -66,6 +66,7 @@ public:
     ALWAYS_INLINE bool isCachedImage() const { return m_isCachedImage; }
     ALWAYS_INLINE bool isPendingImage() const { return m_isPendingImage; }
     ALWAYS_INLINE bool isGeneratedImage() const { return m_isGeneratedImage; }
+    ALWAYS_INLINE bool isCachedImageSet() const { return m_isCachedImageSet; }
     
     static  bool imagesEquivalent(StyleImage* image1, StyleImage* image2)
     {
@@ -82,11 +83,13 @@ protected:
         : m_isCachedImage(false)
         , m_isPendingImage(false)
         , m_isGeneratedImage(false)
+        , m_isCachedImageSet(false)
     {
     }
     bool m_isCachedImage:1;
     bool m_isPendingImage:1;
     bool m_isGeneratedImage:1;
+    bool m_isCachedImageSet:1;
 };
 
 }
index 9aa0e20..6badc92 100644 (file)
@@ -27,6 +27,9 @@
 #define StylePendingImage_h
 
 #include "CSSImageGeneratorValue.h"
+#if ENABLE(CSS_IMAGE_SET)
+#include "CSSImageSetValue.h"
+#endif
 #include "CSSImageValue.h"
 #include "Image.h"
 #include "StyleImage.h"
@@ -46,6 +49,9 @@ public:
     virtual PassRefPtr<CSSValue> cssValue() const { return m_value; }
     CSSImageValue* cssImageValue() const { return m_value->isImageValue() ? static_cast<CSSImageValue*>(m_value) : 0; }
     CSSImageGeneratorValue* cssImageGeneratorValue() const { return m_value->isImageGeneratorValue() ? static_cast<CSSImageGeneratorValue*>(m_value) : 0; }
+#if ENABLE(CSS_IMAGE_SET)
+    CSSImageSetValue* cssImageSetValue() const { return m_value->isImageSetValue() ? static_cast<CSSImageSetValue*>(m_value) : 0; }
+#endif
     
     virtual IntSize imageSize(const RenderObject*, float /*multiplier*/) const { return IntSize(); }
     virtual bool imageHasRelativeWidth() const { return false; }
index 5080605..45ea294 100644 (file)
@@ -292,7 +292,7 @@ bool SVGImage::hasRelativeHeight() const
     return rootElement->intrinsicHeight().isPercent();
 }
 
-void SVGImage::computeIntrinsicDimensions(Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio)
+void SVGImage::computeIntrinsicDimensions(Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio, float)
 {
     if (!m_page)
         return;
index 0fe7b69..bc8d16a 100644 (file)
@@ -70,7 +70,7 @@ private:
 
     virtual void setContainerSize(const IntSize&);
     virtual bool usesContainerSize() const;
-    virtual void computeIntrinsicDimensions(Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio);
+    virtual void computeIntrinsicDimensions(Length& intrinsicWidth, Length& intrinsicHeight, FloatSize& intrinsicRatio, float scaleFactor = 1);
 
     virtual bool dataChanged(bool allDataReceived);