Implement filter function shorthands
authordino@apple.com <dino@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 17 Nov 2011 07:24:01 +0000 (07:24 +0000)
committerdino@apple.com <dino@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 17 Nov 2011 07:24:01 +0000 (07:24 +0000)
https://bugs.webkit.org/show_bug.cgi?id=68475

Reviewed by Simon Fraser.

Source/WebCore:

Implement the shorthand functions for filter effects.
This includes grayscale, sepia, invert, hue-rotate, saturate,
opacity, gamma, drop-shadow and blur. At the moment sharpen
and url are not supported.

CSSParser needed to be updated because it was mistakenly
clamping saturation values to [0,1]. Any positive number
is allowed so you can produce super-saturated images.

The biggest change was the API to FilterEffectRenderer. It now
builds a list of effects and applies the filter itself.

Note that the drop-shadow and blur operations don't yet
provide accurate results because they produce an output image
that is larger than the input. See
https://bugs.webkit.org/show_bug.cgi?id=71929
https://bugs.webkit.org/show_bug.cgi?id=71930

While I was there, I fixed a small style issue in
CustomFilterOperation.

Tests: css3/filters/effect-blur.html
       css3/filters/effect-combined.html
       css3/filters/effect-drop-shadow.html
       css3/filters/effect-gamma.html
       css3/filters/effect-grayscale.html
       css3/filters/effect-hue-rotate.html
       css3/filters/effect-invert.html
       css3/filters/effect-opacity.html
       css3/filters/effect-saturate.html
       css3/filters/effect-sepia.html

* WebCore.xcodeproj/project.pbxproj: Add StyleShader.h to
the project (missing from earlier commit).
* css/CSSParser.cpp:
(WebCore::CSSParser::isValidFilterArgument): Don't clamp
saturate to [0,1]
* platform/graphics/filters/CustomFilterOperation.h:
* rendering/FilterEffectRenderer.cpp:
(WebCore::endMatrixRow):
(WebCore::lastMatrixRow):
(WebCore::FilterEffectRenderer::FilterEffectRenderer):
(WebCore::FilterEffectRenderer::inputContext):
(WebCore::FilterEffectRenderer::build):
(WebCore::FilterEffectRenderer::prepare):
(WebCore::FilterEffectRenderer::apply):
* rendering/FilterEffectRenderer.h:
(WebCore::FilterEffectRenderer::setSourceImageRect):
(WebCore::FilterEffectRenderer::output):
(WebCore::FilterEffectRenderer::setMaxEffectRects):
(WebCore::FilterEffectRenderer::lastEffect):
* rendering/RenderLayer.cpp:
(WebCore::RenderLayer::paintLayer):
(WebCore::RenderLayer::updateOrRemoveFilterEffect):
(WebCore::RenderLayer::updateFilterBackingStore):

LayoutTests:

Test the shorthand functions for filter effects.
This includes grayscale, sepia, invert, hue-rotate, saturate,
opacity, gamma, drop-shadow and blur. At the moment sharpen
and url are not supported.

Note that the drop-shadow and blur operations don't yet
provide accurate results because they produce an output image
that is larger than the input. See
https://bugs.webkit.org/show_bug.cgi?id=71929
https://bugs.webkit.org/show_bug.cgi?id=71930

* css3/filters/effect-blur-expected.png: Added.
* css3/filters/effect-blur-expected.txt: Added.
* css3/filters/effect-blur.html: Added.
* css3/filters/effect-combined-expected.png: Added.
* css3/filters/effect-combined-expected.txt: Added.
* css3/filters/effect-combined.html: Added.
* css3/filters/effect-drop-shadow-expected.png: Added.
* css3/filters/effect-drop-shadow-expected.txt: Added.
* css3/filters/effect-drop-shadow.html: Added.
* css3/filters/effect-gamma-expected.png: Added.
* css3/filters/effect-gamma-expected.txt: Added.
* css3/filters/effect-gamma.html: Added.
* css3/filters/effect-grayscale-expected.png: Added.
* css3/filters/effect-grayscale-expected.txt: Added.
* css3/filters/effect-grayscale.html: Added.
* css3/filters/effect-hue-rotate-expected.png: Added.
* css3/filters/effect-hue-rotate-expected.txt: Added.
* css3/filters/effect-hue-rotate.html: Added.
* css3/filters/effect-invert-expected.png: Added.
* css3/filters/effect-invert-expected.txt: Added.
* css3/filters/effect-invert.html: Added.
* css3/filters/effect-opacity-expected.png: Added.
* css3/filters/effect-opacity-expected.txt: Added.
* css3/filters/effect-opacity.html: Added.
* css3/filters/effect-saturate-expected.png: Added.
* css3/filters/effect-saturate-expected.txt: Added.
* css3/filters/effect-saturate.html: Added.
* css3/filters/effect-sepia-expected.png: Added.
* css3/filters/effect-sepia-expected.txt: Added.
* css3/filters/effect-sepia.html: Added.
* css3/filters/resources/reference.png: Added.
* css3/filters/script-tests/filter-property-parsing-invalid.js:
* css3/filters/script-tests/filter-property-parsing.js:

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

43 files changed:
LayoutTests/ChangeLog
LayoutTests/css3/filters/effect-blur-expected.png [new file with mode: 0644]
LayoutTests/css3/filters/effect-blur-expected.txt [new file with mode: 0644]
LayoutTests/css3/filters/effect-blur.html [new file with mode: 0644]
LayoutTests/css3/filters/effect-combined-expected.png [new file with mode: 0644]
LayoutTests/css3/filters/effect-combined-expected.txt [new file with mode: 0644]
LayoutTests/css3/filters/effect-combined.html [new file with mode: 0644]
LayoutTests/css3/filters/effect-drop-shadow-expected.png [new file with mode: 0644]
LayoutTests/css3/filters/effect-drop-shadow-expected.txt [new file with mode: 0644]
LayoutTests/css3/filters/effect-drop-shadow.html [new file with mode: 0644]
LayoutTests/css3/filters/effect-gamma-expected.png [new file with mode: 0644]
LayoutTests/css3/filters/effect-gamma-expected.txt [new file with mode: 0644]
LayoutTests/css3/filters/effect-gamma.html [new file with mode: 0644]
LayoutTests/css3/filters/effect-grayscale-expected.png [new file with mode: 0644]
LayoutTests/css3/filters/effect-grayscale-expected.txt [new file with mode: 0644]
LayoutTests/css3/filters/effect-grayscale.html [new file with mode: 0644]
LayoutTests/css3/filters/effect-hue-rotate-expected.png [new file with mode: 0644]
LayoutTests/css3/filters/effect-hue-rotate-expected.txt [new file with mode: 0644]
LayoutTests/css3/filters/effect-hue-rotate.html [new file with mode: 0644]
LayoutTests/css3/filters/effect-invert-expected.png [new file with mode: 0644]
LayoutTests/css3/filters/effect-invert-expected.txt [new file with mode: 0644]
LayoutTests/css3/filters/effect-invert.html [new file with mode: 0644]
LayoutTests/css3/filters/effect-opacity-expected.png [new file with mode: 0644]
LayoutTests/css3/filters/effect-opacity-expected.txt [new file with mode: 0644]
LayoutTests/css3/filters/effect-opacity.html [new file with mode: 0644]
LayoutTests/css3/filters/effect-saturate-expected.png [new file with mode: 0644]
LayoutTests/css3/filters/effect-saturate-expected.txt [new file with mode: 0644]
LayoutTests/css3/filters/effect-saturate.html [new file with mode: 0644]
LayoutTests/css3/filters/effect-sepia-expected.png [new file with mode: 0644]
LayoutTests/css3/filters/effect-sepia-expected.txt [new file with mode: 0644]
LayoutTests/css3/filters/effect-sepia.html [new file with mode: 0644]
LayoutTests/css3/filters/filter-property-parsing-expected.txt
LayoutTests/css3/filters/filter-property-parsing-invalid-expected.txt
LayoutTests/css3/filters/resources/reference.png [new file with mode: 0644]
LayoutTests/css3/filters/script-tests/filter-property-parsing-invalid.js
LayoutTests/css3/filters/script-tests/filter-property-parsing.js
Source/WebCore/ChangeLog
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/css/CSSParser.cpp
Source/WebCore/platform/graphics/filters/CustomFilterOperation.h
Source/WebCore/rendering/FilterEffectRenderer.cpp
Source/WebCore/rendering/FilterEffectRenderer.h
Source/WebCore/rendering/RenderLayer.cpp

index c531796..15d289c 100644 (file)
@@ -1,3 +1,55 @@
+2011-11-16  Dean Jackson  <dino@apple.com>
+
+        Implement filter function shorthands
+        https://bugs.webkit.org/show_bug.cgi?id=68475
+
+        Reviewed by Simon Fraser.
+
+        Test the shorthand functions for filter effects.
+        This includes grayscale, sepia, invert, hue-rotate, saturate,
+        opacity, gamma, drop-shadow and blur. At the moment sharpen
+        and url are not supported.
+
+        Note that the drop-shadow and blur operations don't yet
+        provide accurate results because they produce an output image
+        that is larger than the input. See
+        https://bugs.webkit.org/show_bug.cgi?id=71929
+        https://bugs.webkit.org/show_bug.cgi?id=71930
+
+        * css3/filters/effect-blur-expected.png: Added.
+        * css3/filters/effect-blur-expected.txt: Added.
+        * css3/filters/effect-blur.html: Added.
+        * css3/filters/effect-combined-expected.png: Added.
+        * css3/filters/effect-combined-expected.txt: Added.
+        * css3/filters/effect-combined.html: Added.
+        * css3/filters/effect-drop-shadow-expected.png: Added.
+        * css3/filters/effect-drop-shadow-expected.txt: Added.
+        * css3/filters/effect-drop-shadow.html: Added.
+        * css3/filters/effect-gamma-expected.png: Added.
+        * css3/filters/effect-gamma-expected.txt: Added.
+        * css3/filters/effect-gamma.html: Added.
+        * css3/filters/effect-grayscale-expected.png: Added.
+        * css3/filters/effect-grayscale-expected.txt: Added.
+        * css3/filters/effect-grayscale.html: Added.
+        * css3/filters/effect-hue-rotate-expected.png: Added.
+        * css3/filters/effect-hue-rotate-expected.txt: Added.
+        * css3/filters/effect-hue-rotate.html: Added.
+        * css3/filters/effect-invert-expected.png: Added.
+        * css3/filters/effect-invert-expected.txt: Added.
+        * css3/filters/effect-invert.html: Added.
+        * css3/filters/effect-opacity-expected.png: Added.
+        * css3/filters/effect-opacity-expected.txt: Added.
+        * css3/filters/effect-opacity.html: Added.
+        * css3/filters/effect-saturate-expected.png: Added.
+        * css3/filters/effect-saturate-expected.txt: Added.
+        * css3/filters/effect-saturate.html: Added.
+        * css3/filters/effect-sepia-expected.png: Added.
+        * css3/filters/effect-sepia-expected.txt: Added.
+        * css3/filters/effect-sepia.html: Added.
+        * css3/filters/resources/reference.png: Added.
+        * css3/filters/script-tests/filter-property-parsing-invalid.js:
+        * css3/filters/script-tests/filter-property-parsing.js:
+
 2011-11-16  James Robinson  <jamesr@chromium.org>
 
         [chromium] Update more chromium baselines and expectations
diff --git a/LayoutTests/css3/filters/effect-blur-expected.png b/LayoutTests/css3/filters/effect-blur-expected.png
new file mode 100644 (file)
index 0000000..49ef713
Binary files /dev/null and b/LayoutTests/css3/filters/effect-blur-expected.png differ
diff --git a/LayoutTests/css3/filters/effect-blur-expected.txt b/LayoutTests/css3/filters/effect-blur-expected.txt
new file mode 100644 (file)
index 0000000..bac9c71
--- /dev/null
@@ -0,0 +1 @@
+   
diff --git a/LayoutTests/css3/filters/effect-blur.html b/LayoutTests/css3/filters/effect-blur.html
new file mode 100644 (file)
index 0000000..1d53c30
--- /dev/null
@@ -0,0 +1,8 @@
+<script>
+if (window.layoutTestController)
+    window.layoutTestController.dumpAsText();
+</script>
+<img style="-webkit-filter: blur(0)" src="resources/reference.png">
+<img style="-webkit-filter: blur(2px)" src="resources/reference.png">
+<img style="-webkit-filter: blur(3px 3px)" src="resources/reference.png">
+<img style="-webkit-filter: blur(10px)" src="resources/reference.png">
diff --git a/LayoutTests/css3/filters/effect-combined-expected.png b/LayoutTests/css3/filters/effect-combined-expected.png
new file mode 100644 (file)
index 0000000..b000db6
Binary files /dev/null and b/LayoutTests/css3/filters/effect-combined-expected.png differ
diff --git a/LayoutTests/css3/filters/effect-combined-expected.txt b/LayoutTests/css3/filters/effect-combined-expected.txt
new file mode 100644 (file)
index 0000000..163b4d3
--- /dev/null
@@ -0,0 +1 @@
+    
diff --git a/LayoutTests/css3/filters/effect-combined.html b/LayoutTests/css3/filters/effect-combined.html
new file mode 100644 (file)
index 0000000..3d359f2
--- /dev/null
@@ -0,0 +1,9 @@
+<script>
+if (window.layoutTestController)
+    window.layoutTestController.dumpAsText();
+</script>
+<img style="-webkit-filter: sepia() saturate(3) hue-rotate(180deg)" src="resources/reference.png">
+<img style="-webkit-filter: saturate(3) hue-rotate(90deg)" src="resources/reference.png">
+<img style="-webkit-filter: grayscale() blur(3px)" src="resources/reference.png">
+<img style="-webkit-filter: blur(3px) hue-rotate(-90deg) sepia()" src="resources/reference.png">
+<img style="-webkit-filter: blur(3px) opacity(0.5) hue-rotate(-90deg) sepia()" src="resources/reference.png">
diff --git a/LayoutTests/css3/filters/effect-drop-shadow-expected.png b/LayoutTests/css3/filters/effect-drop-shadow-expected.png
new file mode 100644 (file)
index 0000000..18b6a6f
Binary files /dev/null and b/LayoutTests/css3/filters/effect-drop-shadow-expected.png differ
diff --git a/LayoutTests/css3/filters/effect-drop-shadow-expected.txt b/LayoutTests/css3/filters/effect-drop-shadow-expected.txt
new file mode 100644 (file)
index 0000000..163b4d3
--- /dev/null
@@ -0,0 +1 @@
+    
diff --git a/LayoutTests/css3/filters/effect-drop-shadow.html b/LayoutTests/css3/filters/effect-drop-shadow.html
new file mode 100644 (file)
index 0000000..12e630d
--- /dev/null
@@ -0,0 +1,9 @@
+<script>
+if (window.layoutTestController)
+    window.layoutTestController.dumpAsText();
+</script>
+<img style="-webkit-filter: drop-shadow(0 0 0 black)" src="resources/reference.png">
+<img style="-webkit-filter: drop-shadow(5px 5px 2px black)" src="resources/reference.png">
+<img style="-webkit-filter: drop-shadow(5px 5px 0px red)" src="resources/reference.png">
+<img style="-webkit-filter: drop-shadow(10px 10px 0px red)" src="resources/reference.png">
+<img style="-webkit-filter: drop-shadow(5px 5px 10px blue)" src="resources/reference.png">
diff --git a/LayoutTests/css3/filters/effect-gamma-expected.png b/LayoutTests/css3/filters/effect-gamma-expected.png
new file mode 100644 (file)
index 0000000..2cd78a6
Binary files /dev/null and b/LayoutTests/css3/filters/effect-gamma-expected.png differ
diff --git a/LayoutTests/css3/filters/effect-gamma-expected.txt b/LayoutTests/css3/filters/effect-gamma-expected.txt
new file mode 100644 (file)
index 0000000..b055673
--- /dev/null
@@ -0,0 +1 @@
+     
diff --git a/LayoutTests/css3/filters/effect-gamma.html b/LayoutTests/css3/filters/effect-gamma.html
new file mode 100644 (file)
index 0000000..37a9e99
--- /dev/null
@@ -0,0 +1,10 @@
+<script>
+if (window.layoutTestController)
+    window.layoutTestController.dumpAsText();
+</script>
+<img style="-webkit-filter: gamma(1 1 0)" src="resources/reference.png">
+<img style="-webkit-filter: gamma(2 1 0)" src="resources/reference.png">
+<img style="-webkit-filter: gamma(1 1 0.2)" src="resources/reference.png">
+<img style="-webkit-filter: gamma(0.5 1 0)" src="resources/reference.png">
+<img style="-webkit-filter: gamma(1 2 0.4)" src="resources/reference.png">
+<img style="-webkit-filter: gamma(1 3 0)" src="resources/reference.png">
diff --git a/LayoutTests/css3/filters/effect-grayscale-expected.png b/LayoutTests/css3/filters/effect-grayscale-expected.png
new file mode 100644 (file)
index 0000000..2c0cc5a
Binary files /dev/null and b/LayoutTests/css3/filters/effect-grayscale-expected.png differ
diff --git a/LayoutTests/css3/filters/effect-grayscale-expected.txt b/LayoutTests/css3/filters/effect-grayscale-expected.txt
new file mode 100644 (file)
index 0000000..b055673
--- /dev/null
@@ -0,0 +1 @@
+     
diff --git a/LayoutTests/css3/filters/effect-grayscale.html b/LayoutTests/css3/filters/effect-grayscale.html
new file mode 100644 (file)
index 0000000..6b9f25b
--- /dev/null
@@ -0,0 +1,10 @@
+<script>
+if (window.layoutTestController)
+    window.layoutTestController.dumpAsText();
+</script>
+<img style="-webkit-filter: grayscale(0)" src="resources/reference.png">
+<img style="-webkit-filter: grayscale(0.2)" src="resources/reference.png">
+<img style="-webkit-filter: grayscale(0.4)" src="resources/reference.png">
+<img style="-webkit-filter: grayscale(0.6)" src="resources/reference.png">
+<img style="-webkit-filter: grayscale(0.8)" src="resources/reference.png">
+<img style="-webkit-filter: grayscale(1.0)" src="resources/reference.png">
diff --git a/LayoutTests/css3/filters/effect-hue-rotate-expected.png b/LayoutTests/css3/filters/effect-hue-rotate-expected.png
new file mode 100644 (file)
index 0000000..decb860
Binary files /dev/null and b/LayoutTests/css3/filters/effect-hue-rotate-expected.png differ
diff --git a/LayoutTests/css3/filters/effect-hue-rotate-expected.txt b/LayoutTests/css3/filters/effect-hue-rotate-expected.txt
new file mode 100644 (file)
index 0000000..b055673
--- /dev/null
@@ -0,0 +1 @@
+     
diff --git a/LayoutTests/css3/filters/effect-hue-rotate.html b/LayoutTests/css3/filters/effect-hue-rotate.html
new file mode 100644 (file)
index 0000000..db162fb
--- /dev/null
@@ -0,0 +1,10 @@
+<script>
+if (window.layoutTestController)
+    window.layoutTestController.dumpAsText();
+</script>
+<img style="-webkit-filter: hue-rotate(0deg)" src="resources/reference.png">
+<img style="-webkit-filter: hue-rotate(45deg)" src="resources/reference.png">
+<img style="-webkit-filter: hue-rotate(90deg)" src="resources/reference.png">
+<img style="-webkit-filter: hue-rotate(180deg)" src="resources/reference.png">
+<img style="-webkit-filter: hue-rotate(270deg)" src="resources/reference.png">
+<img style="-webkit-filter: hue-rotate(360deg)" src="resources/reference.png">
diff --git a/LayoutTests/css3/filters/effect-invert-expected.png b/LayoutTests/css3/filters/effect-invert-expected.png
new file mode 100644 (file)
index 0000000..cf8507d
Binary files /dev/null and b/LayoutTests/css3/filters/effect-invert-expected.png differ
diff --git a/LayoutTests/css3/filters/effect-invert-expected.txt b/LayoutTests/css3/filters/effect-invert-expected.txt
new file mode 100644 (file)
index 0000000..b055673
--- /dev/null
@@ -0,0 +1 @@
+     
diff --git a/LayoutTests/css3/filters/effect-invert.html b/LayoutTests/css3/filters/effect-invert.html
new file mode 100644 (file)
index 0000000..708ba9c
--- /dev/null
@@ -0,0 +1,10 @@
+<script>
+if (window.layoutTestController)
+    window.layoutTestController.dumpAsText();
+</script>
+<img style="-webkit-filter: invert(0)" src="resources/reference.png">
+<img style="-webkit-filter: invert(0.2)" src="resources/reference.png">
+<img style="-webkit-filter: invert(0.4)" src="resources/reference.png">
+<img style="-webkit-filter: invert(0.6)" src="resources/reference.png">
+<img style="-webkit-filter: invert(0.8)" src="resources/reference.png">
+<img style="-webkit-filter: invert(1.0)" src="resources/reference.png">
diff --git a/LayoutTests/css3/filters/effect-opacity-expected.png b/LayoutTests/css3/filters/effect-opacity-expected.png
new file mode 100644 (file)
index 0000000..e56abd9
Binary files /dev/null and b/LayoutTests/css3/filters/effect-opacity-expected.png differ
diff --git a/LayoutTests/css3/filters/effect-opacity-expected.txt b/LayoutTests/css3/filters/effect-opacity-expected.txt
new file mode 100644 (file)
index 0000000..b055673
--- /dev/null
@@ -0,0 +1 @@
+     
diff --git a/LayoutTests/css3/filters/effect-opacity.html b/LayoutTests/css3/filters/effect-opacity.html
new file mode 100644 (file)
index 0000000..e9d6bb2
--- /dev/null
@@ -0,0 +1,10 @@
+<script>
+if (window.layoutTestController)
+    window.layoutTestController.dumpAsText();
+</script>
+<img style="-webkit-filter: opacity(0)" src="resources/reference.png">
+<img style="-webkit-filter: opacity(0.2)" src="resources/reference.png">
+<img style="-webkit-filter: opacity(0.4)" src="resources/reference.png">
+<img style="-webkit-filter: opacity(0.6)" src="resources/reference.png">
+<img style="-webkit-filter: opacity(0.8)" src="resources/reference.png">
+<img style="-webkit-filter: opacity(1.0)" src="resources/reference.png">
diff --git a/LayoutTests/css3/filters/effect-saturate-expected.png b/LayoutTests/css3/filters/effect-saturate-expected.png
new file mode 100644 (file)
index 0000000..1cb2335
Binary files /dev/null and b/LayoutTests/css3/filters/effect-saturate-expected.png differ
diff --git a/LayoutTests/css3/filters/effect-saturate-expected.txt b/LayoutTests/css3/filters/effect-saturate-expected.txt
new file mode 100644 (file)
index 0000000..b055673
--- /dev/null
@@ -0,0 +1 @@
+     
diff --git a/LayoutTests/css3/filters/effect-saturate.html b/LayoutTests/css3/filters/effect-saturate.html
new file mode 100644 (file)
index 0000000..2425ebd
--- /dev/null
@@ -0,0 +1,10 @@
+<script>
+if (window.layoutTestController)
+    window.layoutTestController.dumpAsText();
+</script>
+<img style="-webkit-filter: saturate(0)" src="resources/reference.png">
+<img style="-webkit-filter: saturate(0.5)" src="resources/reference.png">
+<img style="-webkit-filter: saturate(1.0)" src="resources/reference.png">
+<img style="-webkit-filter: saturate(2)" src="resources/reference.png">
+<img style="-webkit-filter: saturate(5)" src="resources/reference.png">
+<img style="-webkit-filter: saturate(10)" src="resources/reference.png">
diff --git a/LayoutTests/css3/filters/effect-sepia-expected.png b/LayoutTests/css3/filters/effect-sepia-expected.png
new file mode 100644 (file)
index 0000000..4904407
Binary files /dev/null and b/LayoutTests/css3/filters/effect-sepia-expected.png differ
diff --git a/LayoutTests/css3/filters/effect-sepia-expected.txt b/LayoutTests/css3/filters/effect-sepia-expected.txt
new file mode 100644 (file)
index 0000000..b055673
--- /dev/null
@@ -0,0 +1 @@
+     
diff --git a/LayoutTests/css3/filters/effect-sepia.html b/LayoutTests/css3/filters/effect-sepia.html
new file mode 100644 (file)
index 0000000..a4bd8f8
--- /dev/null
@@ -0,0 +1,10 @@
+<script>
+if (window.layoutTestController)
+    window.layoutTestController.dumpAsText();
+</script>
+<img style="-webkit-filter: sepia(0)" src="resources/reference.png">
+<img style="-webkit-filter: sepia(0.2)" src="resources/reference.png">
+<img style="-webkit-filter: sepia(0.4)" src="resources/reference.png">
+<img style="-webkit-filter: sepia(0.6)" src="resources/reference.png">
+<img style="-webkit-filter: sepia(0.8)" src="resources/reference.png">
+<img style="-webkit-filter: sepia(1.0)" src="resources/reference.png">
index 9b048da..c1a15a5 100644 (file)
@@ -201,6 +201,17 @@ PASS filterRule.length is 1
 PASS subRule.operationType is WebKitCSSFilterValue.CSS_FILTER_SATURATE
 PASS subRule.cssText is 'saturate(1)'
 
+Input value > 1 : saturate(5.5)
+PASS cssRule.type is 1
+PASS declaration.length is 1
+PASS declaration.getPropertyValue('-webkit-filter') is 'saturate(5.5)'
+PASS jsWrapperClass(filterRule) is 'CSSValueList'
+PASS jsWrapperClass(filterRule.__proto__) is 'CSSValueListPrototype'
+PASS jsWrapperClass(filterRule.constructor) is 'CSSValueListConstructor'
+PASS filterRule.length is 1
+PASS subRule.operationType is WebKitCSSFilterValue.CSS_FILTER_SATURATE
+PASS subRule.cssText is 'saturate(5.5)'
+
 Zero value : saturate(0)
 PASS cssRule.type is 1
 PASS declaration.length is 1
index c05739c..6603505 100644 (file)
@@ -94,11 +94,6 @@ PASS cssRule.type is 1
 PASS declaration.length is 0
 PASS declaration.getPropertyValue('-webkit-filter') is null
 
-Parameter out of bounds : saturate(1.5)
-PASS cssRule.type is 1
-PASS declaration.length is 0
-PASS declaration.getPropertyValue('-webkit-filter') is null
-
 Bare number : hue-rotate(10)
 PASS cssRule.type is 1
 PASS declaration.length is 0
diff --git a/LayoutTests/css3/filters/resources/reference.png b/LayoutTests/css3/filters/resources/reference.png
new file mode 100644 (file)
index 0000000..d17c7c9
Binary files /dev/null and b/LayoutTests/css3/filters/resources/reference.png differ
index 4e9e817..428e9dc 100644 (file)
@@ -40,7 +40,6 @@ testInvalidFilterRule("Too many parameters", "saturate(0.5 0.5)");
 testInvalidFilterRule("Too many parameters and commas", "saturate(0.5, 0.5)");
 testInvalidFilterRule("Trailing comma", "saturate(0.5,)");
 testInvalidFilterRule("Negative parameter", "saturate(-0.5)");
-testInvalidFilterRule("Parameter out of bounds", "saturate(1.5)");
 
 testInvalidFilterRule("Bare number", "hue-rotate(10)");
 testInvalidFilterRule("Length", "hue-rotate(10px)");
index 378eacd..99578b4 100644 (file)
@@ -136,6 +136,11 @@ testFilterRule("Float value converts to integer",
                ["WebKitCSSFilterValue.CSS_FILTER_SATURATE"],
                ["saturate(1)"]);
 
+testFilterRule("Input value > 1",
+               "saturate(5.5)", 1, "saturate(5.5)",
+               ["WebKitCSSFilterValue.CSS_FILTER_SATURATE"],
+               ["saturate(5.5)"]);
+
 testFilterRule("Zero value",
                "saturate(0)", 1, "saturate(0)",
                ["WebKitCSSFilterValue.CSS_FILTER_SATURATE"],
index 7d313ed..6e03dcd 100644 (file)
@@ -1,3 +1,66 @@
+2011-11-16  Dean Jackson  <dino@apple.com>
+
+        Implement filter function shorthands
+        https://bugs.webkit.org/show_bug.cgi?id=68475
+
+        Reviewed by Simon Fraser.
+
+        Implement the shorthand functions for filter effects.
+        This includes grayscale, sepia, invert, hue-rotate, saturate,
+        opacity, gamma, drop-shadow and blur. At the moment sharpen
+        and url are not supported.
+
+        CSSParser needed to be updated because it was mistakenly
+        clamping saturation values to [0,1]. Any positive number
+        is allowed so you can produce super-saturated images.
+
+        The biggest change was the API to FilterEffectRenderer. It now
+        builds a list of effects and applies the filter itself.
+
+        Note that the drop-shadow and blur operations don't yet
+        provide accurate results because they produce an output image
+        that is larger than the input. See
+        https://bugs.webkit.org/show_bug.cgi?id=71929
+        https://bugs.webkit.org/show_bug.cgi?id=71930
+
+        While I was there, I fixed a small style issue in
+        CustomFilterOperation.
+
+        Tests: css3/filters/effect-blur.html
+               css3/filters/effect-combined.html
+               css3/filters/effect-drop-shadow.html
+               css3/filters/effect-gamma.html
+               css3/filters/effect-grayscale.html
+               css3/filters/effect-hue-rotate.html
+               css3/filters/effect-invert.html
+               css3/filters/effect-opacity.html
+               css3/filters/effect-saturate.html
+               css3/filters/effect-sepia.html
+
+        * WebCore.xcodeproj/project.pbxproj: Add StyleShader.h to
+        the project (missing from earlier commit).
+        * css/CSSParser.cpp:
+        (WebCore::CSSParser::isValidFilterArgument): Don't clamp
+        saturate to [0,1]
+        * platform/graphics/filters/CustomFilterOperation.h:
+        * rendering/FilterEffectRenderer.cpp:
+        (WebCore::endMatrixRow):
+        (WebCore::lastMatrixRow):
+        (WebCore::FilterEffectRenderer::FilterEffectRenderer):
+        (WebCore::FilterEffectRenderer::inputContext):
+        (WebCore::FilterEffectRenderer::build):
+        (WebCore::FilterEffectRenderer::prepare):
+        (WebCore::FilterEffectRenderer::apply):
+        * rendering/FilterEffectRenderer.h:
+        (WebCore::FilterEffectRenderer::setSourceImageRect):
+        (WebCore::FilterEffectRenderer::output):
+        (WebCore::FilterEffectRenderer::setMaxEffectRects):
+        (WebCore::FilterEffectRenderer::lastEffect):
+        * rendering/RenderLayer.cpp:
+        (WebCore::RenderLayer::paintLayer):
+        (WebCore::RenderLayer::updateOrRemoveFilterEffect):
+        (WebCore::RenderLayer::updateFilterBackingStore):
+
 2011-11-16  Kentaro Hara  <haraken@chromium.org>
 
         Remove all custom constructors of Events from JSC
index f3bed2d..373ce00 100644 (file)
                31288E750E3005D6003619AE /* WebKitCSSKeyframesRule.h in Headers */ = {isa = PBXBuildFile; fileRef = 31288E710E3005D6003619AE /* WebKitCSSKeyframesRule.h */; };
                31313F651443B35F006E2A90 /* FilterEffectRenderer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 31313F631443B35E006E2A90 /* FilterEffectRenderer.cpp */; };
                31313F661443B35F006E2A90 /* FilterEffectRenderer.h in Headers */ = {isa = PBXBuildFile; fileRef = 31313F641443B35E006E2A90 /* FilterEffectRenderer.h */; };
+               3138A9E51474434600B0ED12 /* StyleShader.h in Headers */ = {isa = PBXBuildFile; fileRef = 3138A9E41474434600B0ED12 /* StyleShader.h */; };
                31611E5A0E1C4DE000F6A579 /* JSWebKitCSSTransformValue.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 31611E580E1C4DE000F6A579 /* JSWebKitCSSTransformValue.cpp */; };
                31611E5B0E1C4DE000F6A579 /* JSWebKitCSSTransformValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 31611E590E1C4DE000F6A579 /* JSWebKitCSSTransformValue.h */; };
                31611E610E1C4E1400F6A579 /* DOMWebKitCSSTransformValue.h in Headers */ = {isa = PBXBuildFile; fileRef = 31611E5E0E1C4E1400F6A579 /* DOMWebKitCSSTransformValue.h */; };
                31288E710E3005D6003619AE /* WebKitCSSKeyframesRule.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebKitCSSKeyframesRule.h; sourceTree = "<group>"; };
                31313F631443B35E006E2A90 /* FilterEffectRenderer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FilterEffectRenderer.cpp; sourceTree = "<group>"; };
                31313F641443B35E006E2A90 /* FilterEffectRenderer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FilterEffectRenderer.h; sourceTree = "<group>"; };
+               3138A9E41474434600B0ED12 /* StyleShader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = StyleShader.h; path = style/StyleShader.h; sourceTree = "<group>"; };
                31611E540E1C4D4A00F6A579 /* WebKitCSSTransformValue.idl */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = WebKitCSSTransformValue.idl; sourceTree = "<group>"; };
                31611E580E1C4DE000F6A579 /* JSWebKitCSSTransformValue.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = JSWebKitCSSTransformValue.cpp; sourceTree = "<group>"; };
                31611E590E1C4DE000F6A579 /* JSWebKitCSSTransformValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = JSWebKitCSSTransformValue.h; sourceTree = "<group>"; };
                                BC2272BA0E82EAAE00E7F975 /* StyleRareNonInheritedData.cpp */,
                                BC2272BB0E82EAAE00E7F975 /* StyleRareNonInheritedData.h */,
                                BC2272860E82E70700E7F975 /* StyleReflection.h */,
+                               3138A9E41474434600B0ED12 /* StyleShader.h */,
                                BC5EB5E60E81BFEF00B25965 /* StyleSurroundData.cpp */,
                                BC5EB5E40E81BF6D00B25965 /* StyleSurroundData.h */,
                                BC5EB80D0E81F2CE00B25965 /* StyleTransformData.cpp */,
                                5038BE301472AD230095E0D1 /* StyleCachedShader.h in Headers */,
                                5038BE411472AD980095E0D1 /* CachedShader.h in Headers */,
                                A3E2643114748991005A8588 /* WorkerEventQueue.h in Headers */,
+                               3138A9E51474434600B0ED12 /* StyleShader.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index 1b69f18..dca2e22 100644 (file)
@@ -6713,14 +6713,14 @@ bool CSSParser::isValidFilterArgument(CSSParserValue* argument, WebKitCSSFilterV
     // Check parameter values.
     if (filterType == WebKitCSSFilterValue::GrayscaleFilterOperation
         || filterType == WebKitCSSFilterValue::SepiaFilterOperation
-        || filterType == WebKitCSSFilterValue::SaturateFilterOperation
         || filterType == WebKitCSSFilterValue::InvertFilterOperation
         || filterType == WebKitCSSFilterValue::OpacityFilterOperation) {
         // Arguments must be within [0,1].
         double amount = argument->fValue;
         if (amount < 0 || amount > 1)
             return false;
-    } else if (filterType == WebKitCSSFilterValue::GammaFilterOperation
+    } else if (filterType == WebKitCSSFilterValue::SaturateFilterOperation
+               || filterType == WebKitCSSFilterValue::GammaFilterOperation
                || filterType == WebKitCSSFilterValue::BlurFilterOperation) {
         // Arguments must be positive
         double amount = argument->fValue;
index 5f31a3b..4a628b0 100644 (file)
@@ -39,7 +39,7 @@ namespace WebCore {
 
 // CSS Shaders
 
-class CustomFilterOperation: public FilterOperation {
+class CustomFilterOperation : public FilterOperation {
 public:
     static PassRefPtr<CustomFilterOperation> create(PassRefPtr<StyleShader> vertexShader, PassRefPtr<StyleShader> fragmentShader)
     {
index a71b547..227434a 100644 (file)
 #include "config.h"
 #include "FilterEffectRenderer.h"
 
+#include "FEColorMatrix.h"
+#include "FEComponentTransfer.h"
+#include "FEDropShadow.h"
+#include "FEGaussianBlur.h"
+#include "FEMerge.h"
+#include "FloatConversion.h"
+
+#include <algorithm>
+#include <wtf/MathExtras.h>
+
 #if ENABLE(CSS_FILTERS)
 
 namespace WebCore {
 
+static inline void endMatrixRow(Vector<float>& parameters)
+{
+    parameters.append(0);
+    parameters.append(0);
+}
+
+static inline void lastMatrixRow(Vector<float>& parameters)
+{
+    parameters.append(0);
+    parameters.append(0);
+    parameters.append(0);
+    parameters.append(1);
+    parameters.append(0);
+}
+
 FilterEffectRenderer::FilterEffectRenderer()
+    : m_graphicsBufferAttached(false)
 {
     setFilterResolution(FloatSize(1, 1));
+    m_sourceGraphic = SourceGraphic::create(this);
 }
 
 FilterEffectRenderer::~FilterEffectRenderer()
 {
 }
 
+GraphicsContext* FilterEffectRenderer::inputContext()
+{
+    return sourceImage()->context();
+}
+
+void FilterEffectRenderer::build(const FilterOperations& operations, const LayoutRect& borderBox)
+{
+    RefPtr<FilterEffect> effect;
+    RefPtr<FilterEffect> previousEffect;
+    for (size_t i = 0; i < operations.operations().size(); ++i) {
+        FilterOperation* filterOperation = operations.operations().at(i).get();
+        switch (filterOperation->getOperationType()) {
+        case FilterOperation::REFERENCE: {
+            // FIXME: Not yet implemented.
+            // https://bugs.webkit.org/show_bug.cgi?id=72443
+            break;
+        }
+        case FilterOperation::GRAYSCALE: {
+            BasicColorMatrixFilterOperation* colorMatrixOperation = static_cast<BasicColorMatrixFilterOperation*>(filterOperation);
+            Vector<float> inputParameters;
+            float oneMinusAmount = clampTo(1 - narrowPrecisionToFloat(colorMatrixOperation->amount()), 0.0, 1.0);
+
+            // See https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html#grayscaleEquivalent
+            // for information on parameters.
+
+            inputParameters.append(0.2126 + 0.7874 * oneMinusAmount);
+            inputParameters.append(0.7152 - 0.7152 * oneMinusAmount);
+            inputParameters.append(0.0722 - 0.0722 * oneMinusAmount);
+            endMatrixRow(inputParameters);
+
+            inputParameters.append(0.2126 - 0.2126 * oneMinusAmount);
+            inputParameters.append(0.7152 + 0.2848 * oneMinusAmount);
+            inputParameters.append(0.0722 - 0.0722 * oneMinusAmount);
+            endMatrixRow(inputParameters);
+
+            inputParameters.append(0.2126 - 0.2126 * oneMinusAmount);
+            inputParameters.append(0.7152 - 0.7152 * oneMinusAmount);
+            inputParameters.append(0.0722 + 0.9278 * oneMinusAmount);
+            endMatrixRow(inputParameters);
+
+            lastMatrixRow(inputParameters);
+
+            effect = FEColorMatrix::create(this, FECOLORMATRIX_TYPE_MATRIX, inputParameters);
+            break;
+        }
+        case FilterOperation::SEPIA: {
+            BasicColorMatrixFilterOperation* colorMatrixOperation = static_cast<BasicColorMatrixFilterOperation*>(filterOperation);
+            Vector<float> inputParameters;
+            float oneMinusAmount = clampTo(1 - narrowPrecisionToFloat(colorMatrixOperation->amount()), 0.0, 1.0);
+
+            // See https://dvcs.w3.org/hg/FXTF/raw-file/tip/filters/index.html#sepiaEquivalent
+            // for information on parameters.
+
+            inputParameters.append(0.393 + 0.607 * oneMinusAmount);
+            inputParameters.append(0.769 - 0.769 * oneMinusAmount);
+            inputParameters.append(0.189 - 0.189 * oneMinusAmount);
+            endMatrixRow(inputParameters);
+
+            inputParameters.append(0.349 - 0.349 * oneMinusAmount);
+            inputParameters.append(0.686 + 0.314 * oneMinusAmount);
+            inputParameters.append(0.168 - 0.168 * oneMinusAmount);
+            endMatrixRow(inputParameters);
+
+            inputParameters.append(0.272 - 0.272 * oneMinusAmount);
+            inputParameters.append(0.534 - 0.534 * oneMinusAmount);
+            inputParameters.append(0.131 + 0.869 * oneMinusAmount);
+            endMatrixRow(inputParameters);
+
+            lastMatrixRow(inputParameters);
+
+            effect = FEColorMatrix::create(this, FECOLORMATRIX_TYPE_MATRIX, inputParameters);
+            break;
+        }
+        case FilterOperation::SATURATE: {
+            BasicColorMatrixFilterOperation* colorMatrixOperation = static_cast<BasicColorMatrixFilterOperation*>(filterOperation);
+            Vector<float> inputParameters;
+            inputParameters.append(narrowPrecisionToFloat(colorMatrixOperation->amount()));
+            effect = FEColorMatrix::create(this, FECOLORMATRIX_TYPE_SATURATE, inputParameters);
+            break;
+        }
+        case FilterOperation::HUE_ROTATE: {
+            BasicColorMatrixFilterOperation* colorMatrixOperation = static_cast<BasicColorMatrixFilterOperation*>(filterOperation);
+            Vector<float> inputParameters;
+            inputParameters.append(narrowPrecisionToFloat(colorMatrixOperation->amount()));
+            effect = FEColorMatrix::create(this, FECOLORMATRIX_TYPE_HUEROTATE, inputParameters);
+            break;
+        }
+        case FilterOperation::INVERT: {
+            BasicComponentTransferFilterOperation* componentTransferOperation = static_cast<BasicComponentTransferFilterOperation*>(filterOperation);
+            ComponentTransferFunction transferFunction;
+            transferFunction.type = FECOMPONENTTRANSFER_TYPE_TABLE;
+            Vector<float> transferParameters;
+            transferParameters.append(narrowPrecisionToFloat(componentTransferOperation->amount()));
+            transferParameters.append(1.0 - narrowPrecisionToFloat(componentTransferOperation->amount()));
+            transferFunction.tableValues = transferParameters;
+
+            ComponentTransferFunction nullFunction;
+            effect = FEComponentTransfer::create(this, transferFunction, transferFunction, transferFunction, nullFunction);
+            break;
+        }
+        case FilterOperation::OPACITY: {
+            BasicComponentTransferFilterOperation* componentTransferOperation = static_cast<BasicComponentTransferFilterOperation*>(filterOperation);
+            ComponentTransferFunction transferFunction;
+            transferFunction.type = FECOMPONENTTRANSFER_TYPE_TABLE;
+            Vector<float> transferParameters;
+            transferParameters.append(0);
+            transferParameters.append(narrowPrecisionToFloat(componentTransferOperation->amount()));
+            transferFunction.tableValues = transferParameters;
+
+            ComponentTransferFunction nullFunction;
+            effect = FEComponentTransfer::create(this, nullFunction, nullFunction, nullFunction, transferFunction);
+            break;
+        }
+        case FilterOperation::GAMMA: {
+            GammaFilterOperation* gammaOperation = static_cast<GammaFilterOperation*>(filterOperation);
+            ComponentTransferFunction transferFunction;
+            transferFunction.type = FECOMPONENTTRANSFER_TYPE_GAMMA;
+            transferFunction.amplitude = narrowPrecisionToFloat(gammaOperation->amplitude());
+            transferFunction.exponent = narrowPrecisionToFloat(gammaOperation->exponent());
+            transferFunction.offset = narrowPrecisionToFloat(gammaOperation->offset());
+
+            ComponentTransferFunction nullFunction;
+            effect = FEComponentTransfer::create(this, transferFunction, transferFunction, transferFunction, nullFunction);
+            break;
+        }
+        case FilterOperation::BLUR: {
+            BlurFilterOperation* blurOperation = static_cast<BlurFilterOperation*>(filterOperation);
+            float stdDeviationX = blurOperation->stdDeviationX().calcFloatValue(borderBox.width());
+            float stdDeviationY = blurOperation->stdDeviationY().calcFloatValue(borderBox.height());
+            effect = FEGaussianBlur::create(this, stdDeviationX, stdDeviationY);
+            break;
+        }
+        case FilterOperation::SHARPEN: {
+            // FIXME: Currently unimplemented.
+            // https://bugs.webkit.org/show_bug.cgi?id=72442
+            break;
+        }
+        case FilterOperation::DROP_SHADOW: {
+            DropShadowFilterOperation* dropShadowOperation = static_cast<DropShadowFilterOperation*>(filterOperation);
+            effect = FEDropShadow::create(this, dropShadowOperation->stdDeviation(), dropShadowOperation->stdDeviation(),
+                                                dropShadowOperation->x(), dropShadowOperation->y(), dropShadowOperation->color(), 1);
+            break;
+        }
+#if ENABLE(CSS_SHADERS)
+        case FilterOperation::CUSTOM: {
+            // Not implemented in the software path.
+            break;
+        }
+#endif
+        default:
+            break;
+        }
+
+        if (effect) {
+            if (previousEffect)
+                effect->inputEffects().append(previousEffect);
+            m_effects.append(effect);
+            previousEffect = effect;
+        }
+    }
+
+    // If we didn't make a real filter, create a null-op (FEMerge with one input).
+    if (!effect)
+        m_effects.append(FEMerge::create(this));
+
+    m_effects.first()->inputEffects().append(m_sourceGraphic);
+    m_graphicsBufferAttached = false;
+}
+
+void FilterEffectRenderer::prepare()
+{
+    // At this point the effect chain has been built, and the
+    // source image sizes set. We just need to attach the graphic
+    // buffer if we have not yet done so.
+    if (!m_graphicsBufferAttached) {
+        setSourceImage(m_sourceGraphicBuffer.release());
+        m_graphicsBufferAttached = true;
+    }
+    m_sourceGraphic->clearResult();
+    lastEffect()->clearResult();
+}
+
+void FilterEffectRenderer::apply()
+{
+    lastEffect()->apply();
+}
+
 } // namespace WebCore
 
 #endif // ENABLE(CSS_FILTERS)
index 267ad32..66b907a 100644 (file)
 
 #include "Filter.h"
 #include "FilterEffect.h"
+#include "FilterOperations.h"
 #include "FloatRect.h"
+#include "GraphicsContext.h"
+#include "ImageBuffer.h"
+#include "SVGFilterBuilder.h"
 #include "SourceGraphic.h"
 
 #include <wtf/PassRefPtr.h>
@@ -39,6 +43,8 @@
 
 namespace WebCore {
 
+typedef Vector<RefPtr<FilterEffect> > FilterEffectList;
+
 class FilterEffectRenderer : public Filter {
 public:
     static PassRefPtr<FilterEffectRenderer> create()
@@ -49,31 +55,50 @@ public:
     virtual void setSourceImageRect(const FloatRect& sourceImageRect)
     { 
         m_sourceDrawingRegion = sourceImageRect;
-        if (m_effect)
-            effect()->setMaxEffectRect(sourceImageRect);
+        setMaxEffectRects(sourceImageRect);
         setFilterRegion(sourceImageRect);
+        m_sourceGraphicBuffer = ImageBuffer::create(IntSize(sourceImageRect.width(), sourceImageRect.height()));
+        m_graphicsBufferAttached = false;
     }
     virtual FloatRect sourceImageRect() const { return m_sourceDrawingRegion; }
 
     virtual void setFilterRegion(const FloatRect& filterRegion) { m_filterRegion = filterRegion; }
     virtual FloatRect filterRegion() const { return m_filterRegion; }
 
-    virtual void setEffect(PassRefPtr<FilterEffect> effect) { m_effect = effect; }
-    virtual RefPtr<FilterEffect> effect() const { return m_effect; }
+    GraphicsContext* inputContext();
+    ImageBuffer* output() const { return lastEffect()->asImageBuffer(); }
 
-    virtual void setSourceGraphic(PassRefPtr<SourceGraphic> sourceGraphic) { m_sourceGraphic = sourceGraphic; }
-    virtual RefPtr<SourceGraphic> sourceGraphic() const { return m_sourceGraphic; }
+    void build(const FilterOperations&, const LayoutRect&);
+    void prepare();
+    void apply();
     
 private:
+
+    void setMaxEffectRects(const FloatRect& effectRect)
+    {
+        for (size_t i = 0; i < m_effects.size(); ++i) {
+            RefPtr<FilterEffect> effect = m_effects.at(i);
+            effect->setMaxEffectRect(effectRect);
+        }
+    }
+    PassRefPtr<FilterEffect> lastEffect() const
+    {
+        if (m_effects.size() > 0)
+            return m_effects.last();
+        return 0;
+    }
+
     FilterEffectRenderer();
     virtual ~FilterEffectRenderer();
-
+    
     FloatRect m_sourceDrawingRegion;
     FloatRect m_filterRegion;
     
-    RefPtr<FilterEffect> m_effect;
+    FilterEffectList m_effects;
     RefPtr<SourceGraphic> m_sourceGraphic;
-    GraphicsContext* m_savedContext;
+    OwnPtr<ImageBuffer> m_sourceGraphicBuffer;
+    
+    bool m_graphicsBufferAttached;
 };
 
 } // namespace WebCore
index a99dea7..0f806bb 100644 (file)
@@ -2694,10 +2694,12 @@ void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p,
 #if ENABLE(CSS_FILTERS)
     if (!p->paintingDisabled() && hasFilter() && !size().isZero() && !(paintFlags & PaintLayerPaintingFilter)) {
         // Update the filter's image if necessary.
+        // The filter is always built at this point.
         updateFilterBackingStore();
+        m_filter->prepare();
         
         // Paint into the context that represents the SourceGraphic of the filter.
-        GraphicsContext* sourceGraphicsContext = m_filter->sourceImage()->context();
+        GraphicsContext* sourceGraphicsContext = m_filter->inputContext();
 
         FloatRect paintRect = FloatRect(FloatPoint(), size());
         sourceGraphicsContext->clearRect(paintRect);
@@ -2705,17 +2707,14 @@ void RenderLayer::paintLayer(RenderLayer* rootLayer, GraphicsContext* p,
         // Now do the regular paint into the SourceGraphic.
         paintLayer(this, sourceGraphicsContext, paintDirtyRect, paintBehavior, paintingRoot, region, overlapTestRequests, paintFlags | PaintLayerPaintingFilter);
             
-        // Invalidate the filter so that it executes again.
-        m_filter->sourceGraphic()->clearResult();
-        m_filter->effect()->clearResult();
-        m_filter->effect()->apply();
+        m_filter->apply();
         
         LayoutPoint layerOrigin;
         convertToLayerCoords(rootLayer, layerOrigin);
         LayoutRect filterBounds = LayoutRect(layerOrigin.x(), layerOrigin.y(), size().width(), size().height());
         
         // Get the filtered output and draw it in place.
-        p->drawImageBuffer(m_filter->effect()->asImageBuffer(), renderer()->style()->colorSpace(), filterBounds, CompositeSourceOver);
+        p->drawImageBuffer(m_filter->output(), renderer()->style()->colorSpace(), filterBounds, CompositeSourceOver);
         return;
     }
 #endif
@@ -4387,31 +4386,7 @@ void RenderLayer::updateOrRemoveFilterEffect()
         if (!m_filter)
             m_filter = FilterEffectRenderer::create();
 
-        // For the moment we only support a single hue-rotate() filter.
-        // See https://bugs.webkit.org/show_bug.cgi?id=68474 and
-        // https://bugs.webkit.org/show_bug.cgi?id=68475
-
-        RefPtr<FilterEffect> effect;
-        FilterOperations filterOperations = renderer()->style()->filter();
-        if (filterOperations.size() == 1) {
-            const FilterOperation* operation = filterOperations.at(0);
-            if (operation->getOperationType() == FilterOperation::HUE_ROTATE) {
-                const BasicColorMatrixFilterOperation* colorMatrixOperation = static_cast<const BasicColorMatrixFilterOperation*>(operation);
-                Vector<float> inputParameters;
-                inputParameters.append(narrowPrecisionToFloat(colorMatrixOperation->amount()));
-                effect = FEColorMatrix::create(m_filter.get(), FECOLORMATRIX_TYPE_HUEROTATE, inputParameters);
-            }
-        }
-
-        // If we didn't make a real filter, create a null-op (FEMerge with one input).
-        if (!effect)
-            effect = FEMerge::create(m_filter.get());
-
-        RefPtr<SourceGraphic> sourceGraphic = SourceGraphic::create(m_filter.get());
-        m_filter->setSourceGraphic(sourceGraphic);
-
-        effect->inputEffects().append(sourceGraphic);
-        m_filter->setEffect(effect);
+        m_filter->build(renderer()->style()->filter(), toRenderBox(renderer())->borderBoxRect());
     } else {
         m_filter = 0;
     }
@@ -4423,10 +4398,8 @@ void RenderLayer::updateFilterBackingStore()
     if (!layoutSize.isZero()) {
         FloatRect size = FloatRect(0, 0, layoutSize.width(), layoutSize.height());
         FloatRect currentSourceSize = m_filter->sourceImageRect();
-        if (size != currentSourceSize) {
+        if (size != currentSourceSize)
             m_filter->setSourceImageRect(size);
-            m_filter->setSourceImage(ImageBuffer::create(layoutSize));
-        }
     }
 }