Support interpolation between cross-fade() images
authorkrit@webkit.org <krit@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 5 Sep 2013 06:50:05 +0000 (06:50 +0000)
committerkrit@webkit.org <krit@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 5 Sep 2013 06:50:05 +0000 (06:50 +0000)
https://bugs.webkit.org/show_bug.cgi?id=119955

Reviewed by Darin Adler.

Source/WebCore:

With this patch, CSS can animate from one -webkit-cross-fade
function to another, when the input images are the same in the
same order.

* css/CSSCrossfadeValue.cpp: Added blend function.
(WebCore::blendFunc):
(WebCore::CSSCrossfadeValue::blend):
(WebCore::CSSCrossfadeValue::equals):
(WebCore::CSSCrossfadeValue::equalInputImages):
* css/CSSCrossfadeValue.h: Added save casting functions.
(WebCore::toCSSCrossfadeValue):
* css/CSSValue.h:
(WebCore::CSSValue::isCrossfadeValue):
* page/animation/CSSPropertyAnimation.cpp: Add another condition to
    interpolate between two -webkit-cross-fade functions.
(WebCore::blendFunc):

LayoutTests:

Test interpolation from one cross-fade function to another. Changed pixel test
to a ref test.

* animations/cross-fade-background-image.html:
* animations/cross-fade-background-image-expected.html: Added.
* platform/mac/animations/cross-fade-background-image-expected.png: Removed.
* platform/mac/animations/cross-fade-background-image-expected.txt: Removed.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@155100 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/animations/cross-fade-background-image-expected.html [new file with mode: 0644]
LayoutTests/animations/cross-fade-background-image.html
LayoutTests/platform/mac/animations/cross-fade-background-image-expected.png [deleted file]
LayoutTests/platform/mac/animations/cross-fade-background-image-expected.txt [deleted file]
Source/WebCore/ChangeLog
Source/WebCore/css/CSSCrossfadeValue.cpp
Source/WebCore/css/CSSCrossfadeValue.h
Source/WebCore/css/CSSValue.h
Source/WebCore/page/animation/CSSPropertyAnimation.cpp

index b371d80..5df7ff6 100644 (file)
@@ -1,3 +1,18 @@
+2013-09-04  Dirk Schulze  <krit@webkit.org>
+
+        Support interpolation between cross-fade() images
+        https://bugs.webkit.org/show_bug.cgi?id=119955
+
+        Reviewed by Darin Adler.
+
+        Test interpolation from one cross-fade function to another. Changed pixel test
+        to a ref test.
+
+        * animations/cross-fade-background-image.html:
+        * animations/cross-fade-background-image-expected.html: Added.
+        * platform/mac/animations/cross-fade-background-image-expected.png: Removed.
+        * platform/mac/animations/cross-fade-background-image-expected.txt: Removed.
+
 2013-09-04  Zoltan Herczeg  <zherczeg@webkit.org>
 
         <https://webkit.org/b/118553> Hash navigation doesn't affect history when the page is retrieved from appcache
diff --git a/LayoutTests/animations/cross-fade-background-image-expected.html b/LayoutTests/animations/cross-fade-background-image-expected.html
new file mode 100644 (file)
index 0000000..d4a8363
--- /dev/null
@@ -0,0 +1,25 @@
+<html>
+<head>
+  <style>
+#rect {
+    position: absolute;
+    top: 200px;
+    left: 100px;
+    width: 200px;
+    height: 300px;
+    background-color: #049196;
+}
+  </style>
+</head>
+<body>
+<div id="rect"></div>
+<div id="result">
+PASS - "backgroundImage" property for "box" element at 2.5s saw something close to: -webkit-cross-fade(url(blue-100.png), url(green-100.png), 50%)<br>
+PASS - "backgroundImage" property for "box" and "boxStatic" elements at 2.5s are close enough to each other<br>
+PASS - "backgroundImage" property for "boxShorthand" and "boxStatic" elements at 2.5s are close enough to each other<br>
+PASS - "backgroundImage" property for "boxAnim1" element at 2.5s saw something close to: -webkit-cross-fade(url(resources/blue-100.png), url(resources/green-100.png), 0.5)<br>
+PASS - "backgroundImage" property for "boxAnim2" element at 2.5s saw something close to: -webkit-cross-fade(url(resources/green-100.png), url(resources/blue-100.png), 50%)<br>
+PASS - "backgroundImage" property for "boxAnim3" element at 2.5s saw something close to: -webkit-cross-fade(url(resources/blue-100.png), url(resources/green-100.png), 50%)<br>
+</div>
+</body>
+</html>
\ No newline at end of file
index af0bbda..3448a5e 100644 (file)
@@ -4,7 +4,7 @@
     #box {
         position: absolute;
         left: 100px;
-        top: 100px;
+        top: 200px;
         height: 100px;
         width: 100px;
         background-color: red;
@@ -13,7 +13,7 @@
     #boxShorthand {
         position: absolute;
         left: 100px;
-        top: 200px;
+        top: 300px;
         height: 100px;
         width: 100px;
         background-color: red;
     #boxStatic {
         position: absolute;
         left: 100px;
-        top: 300px;
+        top: 400px;
         height: 100px;
         width: 100px;
         background-color: red;
         background-image: -webkit-cross-fade(url(resources/blue-100.png), url(resources/green-100.png), 50%);
     }
+    #boxAnim1 {
+        position: absolute;
+        left: 200px;
+        top: 200px;
+        height: 100px;
+        width: 100px;
+        background-color: red;
+        -webkit-animation: animCross1 1s linear infinite;
+    }
+    #boxAnim2 {
+        position: absolute;
+        left: 200px;
+        top: 300px;
+        height: 100px;
+        width: 100px;
+        background-color: red;
+        -webkit-animation: animCross2 1s linear infinite;
+    }
+    #boxAnim3 {
+        position: absolute;
+        left: 200px;
+        top: 400px;
+        height: 100px;
+        width: 100px;
+        background-color: red;
+        -webkit-animation: animCross3 1s linear infinite;
+    }
     @-webkit-keyframes anim {
         from { background-image: url(resources/blue-100.png); }
         to   { background-image: url(resources/green-100.png); }
         from { background: url(resources/blue-100.png); }
         to   { background: url(resources/green-100.png); }
     }
+    @-webkit-keyframes animCross1 {
+        from { background-image: -webkit-cross-fade(url(resources/blue-100.png), url(resources/green-100.png), 20%); }
+        to   { background-image: -webkit-cross-fade(url(resources/blue-100.png), url(resources/green-100.png), 0.8); }
+    }
+    @-webkit-keyframes animCross2 {
+        /* Image inputs are not identical - no animation.*/
+        from { background-image: -webkit-cross-fade(url(resources/blue-100.png), url(resources/green-100.png), 20%); }
+        to   { background-image: -webkit-cross-fade(url(resources/green-100.png), url(resources/blue-100.png), 50%); }
+    }
+    @-webkit-keyframes animCross3 {
+        /* Direct image inputs are not identical - no animation.*/
+        from { background-image: -webkit-cross-fade(-webkit-filter(url(resources/blue-100.png), contrast(0.5)), url(resources/green-100.png), 20%); }
+        to   { background-image: -webkit-cross-fade(url(resources/blue-100.png), url(resources/green-100.png), 50%); }
+    }
   </style>
   <script src="resources/animation-test-helpers.js" type="text/javascript" charset="utf-8"></script>
   <script type="text/javascript" charset="utf-8">
@@ -44,6 +85,9 @@
       ["anim", 2.5, "box", "backgroundImage", "-webkit-cross-fade(url(blue-100.png), url(green-100.png), 50%)", 0.05],
       ["anim", 2.5, ["box", "static:boxStatic"], "backgroundImage", "-webkit-cross-fade(url(blue-100.png), url(green-100.png), 50%)", 0.05],
       ["animShorthand", 2.5, ["boxShorthand", "static:boxStatic"], "backgroundImage", "-webkit-cross-fade(url(blue-100.png), url(green-100.png), 50%)", 0.05],
+      ["animCross1", 2.5, "boxAnim1", "backgroundImage", "-webkit-cross-fade(url(resources/blue-100.png), url(resources/green-100.png), 0.5)", 0.05],
+      ["animCross2", 2.5, "boxAnim2", "backgroundImage", "-webkit-cross-fade(url(resources/green-100.png), url(resources/blue-100.png), 50%)", 0],
+      ["animCross3", 2.5, "boxAnim3", "backgroundImage", "-webkit-cross-fade(url(resources/blue-100.png), url(resources/green-100.png), 50%)", 0],
     ];
 
     var doPixelTest = true;
@@ -55,6 +99,9 @@
 <div id="box"></div>
 <div id="boxStatic"></div>
 <div id="boxShorthand"></div>
+<div id="boxAnim1"></div>
+<div id="boxAnim2"></div>
+<div id="boxAnim3"></div>
 <div id="result"></div>
 </body>
 </html>
diff --git a/LayoutTests/platform/mac/animations/cross-fade-background-image-expected.png b/LayoutTests/platform/mac/animations/cross-fade-background-image-expected.png
deleted file mode 100644 (file)
index 8973ebf..0000000
Binary files a/LayoutTests/platform/mac/animations/cross-fade-background-image-expected.png and /dev/null differ
diff --git a/LayoutTests/platform/mac/animations/cross-fade-background-image-expected.txt b/LayoutTests/platform/mac/animations/cross-fade-background-image-expected.txt
deleted file mode 100644 (file)
index b60e2b1..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-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 784x72
-        RenderText {#text} at (0,0) size 733x36
-          text run at (0,0) width 733: "PASS - \"backgroundImage\" property for \"box\" element at 2.5s saw something close to: -webkit-cross-fade(url(blue-"
-          text run at (0,18) width 226: "100.png), url(green-100.png), 50%)"
-        RenderBR {BR} at (226,32) size 0x0
-        RenderText {#text} at (0,36) size 704x18
-          text run at (0,36) width 704: "PASS - \"backgroundImage\" property for \"box\" and \"boxStatic\" elements at 2.5s are close enough to each other"
-        RenderBR {BR} at (704,50) size 0x0
-        RenderText {#text} at (0,54) size 769x18
-          text run at (0,54) width 769: "PASS - \"backgroundImage\" property for \"boxShorthand\" and \"boxStatic\" elements at 2.5s are close enough to each other"
-        RenderBR {BR} at (769,68) size 0x0
-layer at (100,100) size 100x100
-  RenderBlock (positioned) {DIV} at (100,100) size 100x100 [bgcolor=#FF0000]
-layer at (100,300) size 100x100
-  RenderBlock (positioned) {DIV} at (100,300) size 100x100 [bgcolor=#FF0000]
-layer at (100,200) size 100x100
-  RenderBlock (positioned) {DIV} at (100,200) size 100x100
index ad879cb..7fbbc93 100644 (file)
@@ -1,3 +1,27 @@
+2013-09-04  Dirk Schulze  <krit@webkit.org>
+
+        Support interpolation between cross-fade() images
+        https://bugs.webkit.org/show_bug.cgi?id=119955
+
+        Reviewed by Darin Adler.
+
+        With this patch, CSS can animate from one -webkit-cross-fade
+        function to another, when the input images are the same in the
+        same order.
+
+        * css/CSSCrossfadeValue.cpp: Added blend function.
+        (WebCore::blendFunc):
+        (WebCore::CSSCrossfadeValue::blend):
+        (WebCore::CSSCrossfadeValue::equals):
+        (WebCore::CSSCrossfadeValue::equalInputImages):
+        * css/CSSCrossfadeValue.h: Added save casting functions.
+        (WebCore::toCSSCrossfadeValue):
+        * css/CSSValue.h:
+        (WebCore::CSSValue::isCrossfadeValue):
+        * page/animation/CSSPropertyAnimation.cpp: Add another condition to
+            interpolate between two -webkit-cross-fade functions.
+        (WebCore::blendFunc):
+
 2013-09-04  Zoltan Herczeg  <zherczeg@webkit.org>
 
         <https://webkit.org/b/118553> Hash navigation doesn't affect history when the page is retrieved from appcache
index f000c23..aef60a1 100644 (file)
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2011 Apple Inc.  All rights reserved.
+ * Copyright (C) 2013 Adobe Systems Incorporated. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -26,6 +27,7 @@
 #include "config.h"
 #include "CSSCrossfadeValue.h"
 
+#include "AnimationUtilities.h"
 #include "CSSImageValue.h"
 #include "CachedResourceLoader.h"
 #include "CrossfadeGeneratedImage.h"
 
 namespace WebCore {
 
+static inline double blendFunc(double from, double to, double progress)
+{
+    return blend(from, to, progress);
+}
+
 static bool subimageKnownToBeOpaque(CSSValue* value, const RenderObject* renderer)
 {
     if (value->isImageValue())
@@ -178,11 +185,38 @@ bool CSSCrossfadeValue::hasFailedOrCanceledSubresources() const
     return false;
 }
 
+PassRefPtr<CSSCrossfadeValue> CSSCrossfadeValue::blend(const CSSCrossfadeValue& from, double progress) const
+{
+    ASSERT(equalInputImages(from));
+    RefPtr<StyleCachedImage> toStyledImage = StyleCachedImage::create(m_cachedToImage.get());
+    RefPtr<StyleCachedImage> fromStyledImage = StyleCachedImage::create(m_cachedFromImage.get());
+
+    RefPtr<CSSImageValue> fromImageValue = CSSImageValue::create(m_cachedFromImage->url(), fromStyledImage.get());
+    RefPtr<CSSImageValue> toImageValue = CSSImageValue::create(m_cachedToImage->url(), toStyledImage.get());
+
+    RefPtr<CSSCrossfadeValue> crossfadeValue = CSSCrossfadeValue::create(fromImageValue, toImageValue);
+
+    double fromPercentage = from.m_percentageValue->getDoubleValue();
+    if (from.m_percentageValue->isPercentage())
+        fromPercentage /= 100.0;
+    double toPercentage = m_percentageValue->getDoubleValue();
+    if (m_percentageValue->isPercentage())
+        toPercentage /= 100.0;
+    crossfadeValue->setPercentage(CSSPrimitiveValue::create(blendFunc(fromPercentage, toPercentage, progress), CSSPrimitiveValue::CSS_NUMBER));
+    return crossfadeValue.release();
+}
+
 bool CSSCrossfadeValue::equals(const CSSCrossfadeValue& other) const
 {
-    return compareCSSValuePtr(m_fromValue, other.m_fromValue)
-        && compareCSSValuePtr(m_toValue, other.m_toValue)
+    return equalInputImages(other)
         && compareCSSValuePtr(m_percentageValue, other.m_percentageValue);
 }
 
+
+bool CSSCrossfadeValue::equalInputImages(const CSSCrossfadeValue& other) const
+{
+    return compareCSSValuePtr(m_fromValue, other.m_fromValue)
+        && compareCSSValuePtr(m_toValue, other.m_toValue);
+}
+
 } // namespace WebCore
index 43302d5..f9dbbac 100644 (file)
@@ -65,8 +65,12 @@ public:
 
     bool hasFailedOrCanceledSubresources() const;
 
+    PassRefPtr<CSSCrossfadeValue> blend(const CSSCrossfadeValue&, double) const;
+
     bool equals(const CSSCrossfadeValue&) const;
 
+    bool equalInputImages(const CSSCrossfadeValue&) const;
+
 private:
     CSSCrossfadeValue(PassRefPtr<CSSValue> fromValue, PassRefPtr<CSSValue> toValue)
         : CSSImageGeneratorValue(CrossfadeClass)
@@ -106,6 +110,12 @@ private:
     CrossfadeSubimageObserverProxy m_crossfadeSubimageObserver;
 };
 
+inline CSSCrossfadeValue* toCSSCrossfadeValue(CSSImageGeneratorValue* value)
+{
+    ASSERT_WITH_SECURITY_IMPLICATION(!value || value->isCrossfadeValue());
+    return static_cast<CSSCrossfadeValue*>(value);
+}
+
 } // namespace WebCore
 
 #endif // CSSCrossfadeValue_h
index c6952c5..5d4a218 100644 (file)
@@ -71,6 +71,7 @@ public:
 
     bool isAspectRatioValue() const { return m_classType == AspectRatioClass; }
     bool isBorderImageSliceValue() const { return m_classType == BorderImageSliceClass; }
+    bool isCrossfadeValue() const { return m_classType == CrossfadeClass; }
     bool isCursorImageValue() const { return m_classType == CursorImageClass; }
     bool isFontFeatureValue() const { return m_classType == FontFeatureClass; }
     bool isFontValue() const { return m_classType == FontClass; }
index 7d2a538..3c0fa62 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2007, 2008, 2009, 2013 Apple Inc. All rights reserved.
- * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved.
+ * Copyright (C) 2012, 2013 Adobe Systems Incorporated. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -316,21 +316,23 @@ static inline PassRefPtr<StyleImage> blendFunc(const AnimationBase* anim, StyleI
         if (fromGenerated->isFilterImageValue() && toGenerated->isFilterImageValue()) {
             // Animation of generated images just possible if input images are equal.
             // Otherwise fall back to cross fade animation.
-            CSSFilterImageValue* fromFitler = toCSSFilterImageValue(fromGenerated);
-            CSSFilterImageValue* toFitler = toCSSFilterImageValue(toGenerated);
-            if (fromFitler->equalInputImages(*toFitler))
+            CSSFilterImageValue& fromFitler = *toCSSFilterImageValue(fromGenerated);
+            CSSFilterImageValue& toFitler = *toCSSFilterImageValue(toGenerated);
+            if (fromFitler.equalInputImages(toFitler))
                 return filterBlend(anim, from, to, progress);
         }
-#else
-        UNUSED_PARAM(fromGenerated);
-        UNUSED_PARAM(toGenerated);
 #endif
-        // FIXME: Add support for animation between two cross-fade() functions.
-        // https://bugs.webkit.org/show_bug.cgi?id=119955
+
+        if (fromGenerated->isCrossfadeValue() && toGenerated->isCrossfadeValue()) {
+            CSSCrossfadeValue& fromCrossfade = *toCSSCrossfadeValue(fromGenerated);
+            CSSCrossfadeValue& toCrossfade = *toCSSCrossfadeValue(toGenerated);
+            if (fromCrossfade.equalInputImages(toCrossfade))
+                return StyleGeneratedImage::create(toCrossfade.blend(fromCrossfade, progress).get());
+        }
 
         // FIXME: Add support for animation between two *gradient() functions.
         // https://bugs.webkit.org/show_bug.cgi?id=119956
-}
+    }
 
     // FIXME: Add support cross fade between cached and generated images.
     // https://bugs.webkit.org/show_bug.cgi?id=78293