Title: [102855] trunk
Revision
102855
Author
simon.fra...@apple.com
Date
2011-12-14 17:30:35 -0800 (Wed, 14 Dec 2011)

Log Message

Filter amounts should accept percentages
https://bugs.webkit.org/show_bug.cgi?id=74531

Source/WebCore:

Reviewed by Chris Marrin.

Support percentage arguments for some filter functions, using the FPercent flag
to validUnit(). Fix CSSStyleSelector::createFilterOperations() to do the divide by 100
for percentages.

Replaced isValidFilterArgument(), which just tested arguments one by one for validity, with
parseBuiltinFilterArguments() which tests and creates the CSSValues at the same time, which
is a little more efficient. It also allows filter-specific behavior to be more localized in this
method.

Covered by existing tests.

* css/CSSParser.cpp:
(WebCore::CSSParser::parseBuiltinFilterArguments):
(WebCore::CSSParser::parseFilter):
* css/CSSParser.h:
* css/CSSStyleSelector.cpp:
(WebCore::CSSStyleSelector::createFilterOperations):

LayoutTests:

Reviewed by Chris Marrin.

Adjust test results now that percentages are allowed for some
filter arguments, and add testing of percentage arguments to filter-property-computed-style.js

* css3/filters/filter-property-computed-style-expected.txt:
* css3/filters/filter-property-parsing-invalid-expected.txt:
* css3/filters/script-tests/filter-property-computed-style.js:
* css3/filters/script-tests/filter-property-parsing-invalid.js:

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (102854 => 102855)


--- trunk/LayoutTests/ChangeLog	2011-12-15 01:24:18 UTC (rev 102854)
+++ trunk/LayoutTests/ChangeLog	2011-12-15 01:30:35 UTC (rev 102855)
@@ -1,3 +1,18 @@
+2011-12-14  Simon Fraser  <simon.fra...@apple.com>
+
+        Filter amounts should accept percentages
+        https://bugs.webkit.org/show_bug.cgi?id=74531
+
+        Reviewed by Chris Marrin.
+        
+        Adjust test results now that percentages are allowed for some
+        filter arguments, and add testing of percentage arguments to filter-property-computed-style.js
+
+        * css3/filters/filter-property-computed-style-expected.txt:
+        * css3/filters/filter-property-parsing-invalid-expected.txt:
+        * css3/filters/script-tests/filter-property-computed-style.js:
+        * css3/filters/script-tests/filter-property-parsing-invalid.js:
+
 2011-12-14  Enrica Casucci  <enr...@apple.com>
 
         Updating test results after r102846

Modified: trunk/LayoutTests/css3/filters/filter-property-computed-style-expected.txt (102854 => 102855)


--- trunk/LayoutTests/css3/filters/filter-property-computed-style-expected.txt	2011-12-15 01:24:18 UTC (rev 102854)
+++ trunk/LayoutTests/css3/filters/filter-property-computed-style-expected.txt	2011-12-15 01:30:35 UTC (rev 102855)
@@ -338,8 +338,8 @@
 PASS subRule.operationType is WebKitCSSFilterValue.CSS_FILTER_DROP_SHADOW
 PASS subRule.cssText is 'drop-shadow(rgba(0, 0, 0, 0) 1px 2px 0px)'
 
-Multiple operations : grayscale(0.5) sepia(0.25) saturate(0.75) hue-rotate(35deg) invert(0.2) opacity(0.9) gamma(2 1.1 1) blur(5px 2em) sharpen(0.5 3px 2)
-PASS filterStyle.length is 9
+Multiple operations : grayscale(0.5) sepia(0.25) saturate(0.75) hue-rotate(35deg) invert(0.2) opacity(0.9) gamma(2 1.1 1) blur(5px 2em)
+PASS filterStyle.length is 8
 PASS subRule.operationType is WebKitCSSFilterValue.CSS_FILTER_GRAYSCALE
 PASS subRule.cssText is 'grayscale(0.5)'
 PASS subRule.operationType is WebKitCSSFilterValue.CSS_FILTER_SEPIA
@@ -356,8 +356,19 @@
 PASS subRule.cssText is 'gamma(2 1.1 1)'
 PASS subRule.operationType is WebKitCSSFilterValue.CSS_FILTER_BLUR
 PASS subRule.cssText is 'blur(5px 32px)'
-PASS subRule.operationType is WebKitCSSFilterValue.CSS_FILTER_SHARPEN
-PASS subRule.cssText is 'sharpen(0.5 3px 2)'
+
+Percentage values : grayscale(50%) sepia(25%) saturate(75%) invert(20%) opacity(90%)
+PASS filterStyle.length is 5
+PASS subRule.operationType is WebKitCSSFilterValue.CSS_FILTER_GRAYSCALE
+PASS subRule.cssText is 'grayscale(0.5)'
+PASS subRule.operationType is WebKitCSSFilterValue.CSS_FILTER_SEPIA
+PASS subRule.cssText is 'sepia(0.25)'
+PASS subRule.operationType is WebKitCSSFilterValue.CSS_FILTER_SATURATE
+PASS subRule.cssText is 'saturate(0.75)'
+PASS subRule.operationType is WebKitCSSFilterValue.CSS_FILTER_INVERT
+PASS subRule.cssText is 'invert(0.2)'
+PASS subRule.operationType is WebKitCSSFilterValue.CSS_FILTER_OPACITY
+PASS subRule.cssText is 'opacity(0.9)'
 PASS successfullyParsed is true
 
 TEST COMPLETE

Modified: trunk/LayoutTests/css3/filters/filter-property-parsing-invalid-expected.txt (102854 => 102855)


--- trunk/LayoutTests/css3/filters/filter-property-parsing-invalid-expected.txt	2011-12-15 01:24:18 UTC (rev 102854)
+++ trunk/LayoutTests/css3/filters/filter-property-parsing-invalid-expected.txt	2011-12-15 01:30:35 UTC (rev 102855)
@@ -39,11 +39,6 @@
 PASS declaration.length is 0
 PASS declaration.getPropertyValue('-webkit-filter') is null
 
-Length instead of number : sepia(1%)
-PASS cssRule.type is 1
-PASS declaration.length is 0
-PASS declaration.getPropertyValue('-webkit-filter') is null
-
 Too many parameters : sepia(0.5 0.5 3.0)
 PASS cssRule.type is 1
 PASS declaration.length is 0

Modified: trunk/LayoutTests/css3/filters/script-tests/filter-property-computed-style.js (102854 => 102855)


--- trunk/LayoutTests/css3/filters/script-tests/filter-property-computed-style.js	2011-12-15 01:24:18 UTC (rev 102854)
+++ trunk/LayoutTests/css3/filters/script-tests/filter-property-computed-style.js	2011-12-15 01:30:35 UTC (rev 102855)
@@ -332,7 +332,7 @@
                        ["drop-shadow(rgba(0, 0, 0, 0) 1px 2px 0px)"]);
 
 testComputedFilterRule("Multiple operations",
-                       "grayscale(0.5) sepia(0.25) saturate(0.75) hue-rotate(35deg) invert(0.2) opacity(0.9) gamma(2 1.1 1) blur(5px 2em) sharpen(0.5 3px 2)", 9,
+                       "grayscale(0.5) sepia(0.25) saturate(0.75) hue-rotate(35deg) invert(0.2) opacity(0.9) gamma(2 1.1 1) blur(5px 2em)", 8,
                        [
                            "WebKitCSSFilterValue.CSS_FILTER_GRAYSCALE",
                            "WebKitCSSFilterValue.CSS_FILTER_SEPIA",
@@ -342,7 +342,6 @@
                            "WebKitCSSFilterValue.CSS_FILTER_OPACITY",
                            "WebKitCSSFilterValue.CSS_FILTER_GAMMA",
                            "WebKitCSSFilterValue.CSS_FILTER_BLUR",
-                           "WebKitCSSFilterValue.CSS_FILTER_SHARPEN"
                ],
                        [
                            "grayscale(0.5)",
@@ -352,8 +351,24 @@
                            "invert(0.2)",
                            "opacity(0.9)",
                            "gamma(2 1.1 1)",
-                           "blur(5px 32px)",
-                           "sharpen(0.5 3px 2)"
+                           "blur(5px 32px)"
                ]);
 
+testComputedFilterRule("Percentage values",
+                      "grayscale(50%) sepia(25%) saturate(75%) invert(20%) opacity(90%)", 5,
+                      [
+                          "WebKitCSSFilterValue.CSS_FILTER_GRAYSCALE",
+                          "WebKitCSSFilterValue.CSS_FILTER_SEPIA",
+                          "WebKitCSSFilterValue.CSS_FILTER_SATURATE",
+                          "WebKitCSSFilterValue.CSS_FILTER_INVERT",
+                          "WebKitCSSFilterValue.CSS_FILTER_OPACITY"
+              ],
+                      [
+                          "grayscale(0.5)",
+                          "sepia(0.25)",
+                          "saturate(0.75)",
+                          "invert(0.2)",
+                          "opacity(0.9)",
+              ]);
+
 successfullyParsed = true;

Modified: trunk/LayoutTests/css3/filters/script-tests/filter-property-parsing-invalid.js (102854 => 102855)


--- trunk/LayoutTests/css3/filters/script-tests/filter-property-parsing-invalid.js	2011-12-15 01:24:18 UTC (rev 102854)
+++ trunk/LayoutTests/css3/filters/script-tests/filter-property-parsing-invalid.js	2011-12-15 01:30:35 UTC (rev 102855)
@@ -28,7 +28,6 @@
 testInvalidFilterRule("Negative parameter", "grayscale(-0.5)");
 testInvalidFilterRule("Parameter out of bounds", "grayscale(1.5)");
 
-testInvalidFilterRule("Length instead of number", "sepia(1%)");
 testInvalidFilterRule("Too many parameters", "sepia(0.5 0.5 3.0)");
 testInvalidFilterRule("Too many parameters and commas", "sepia(0.1, 0.1)");
 testInvalidFilterRule("Trailing comma", "sepia(0.5,)");

Modified: trunk/Source/WebCore/ChangeLog (102854 => 102855)


--- trunk/Source/WebCore/ChangeLog	2011-12-15 01:24:18 UTC (rev 102854)
+++ trunk/Source/WebCore/ChangeLog	2011-12-15 01:30:35 UTC (rev 102855)
@@ -1,3 +1,28 @@
+2011-12-14  Simon Fraser  <simon.fra...@apple.com>
+
+        Filter amounts should accept percentages
+        https://bugs.webkit.org/show_bug.cgi?id=74531
+
+        Reviewed by Chris Marrin.
+        
+        Support percentage arguments for some filter functions, using the FPercent flag
+        to validUnit(). Fix CSSStyleSelector::createFilterOperations() to do the divide by 100
+        for percentages.
+        
+        Replaced isValidFilterArgument(), which just tested arguments one by one for validity, with
+        parseBuiltinFilterArguments() which tests and creates the CSSValues at the same time, which
+        is a little more efficient. It also allows filter-specific behavior to be more localized in this
+        method.
+
+        Covered by existing tests.
+
+        * css/CSSParser.cpp:
+        (WebCore::CSSParser::parseBuiltinFilterArguments):
+        (WebCore::CSSParser::parseFilter):
+        * css/CSSParser.h:
+        * css/CSSStyleSelector.cpp:
+        (WebCore::CSSStyleSelector::createFilterOperations):
+
 2011-12-14  Enrica Casucci  <enr...@apple.com>
 
         Build fix.

Modified: trunk/Source/WebCore/css/CSSParser.cpp (102854 => 102855)


--- trunk/Source/WebCore/css/CSSParser.cpp	2011-12-15 01:24:18 UTC (rev 102854)
+++ trunk/Source/WebCore/css/CSSParser.cpp	2011-12-15 01:30:35 UTC (rev 102855)
@@ -6766,52 +6766,124 @@
 }
 #endif
 
-bool CSSParser::isValidFilterArgument(CSSParserValue* argument, WebKitCSSFilterValue::FilterOperationType& filterType, unsigned argumentCount)
+PassRefPtr<WebKitCSSFilterValue> CSSParser::parseBuiltinFilterArguments(CSSParserValueList* args, WebKitCSSFilterValue::FilterOperationType filterType)
 {
-    // Check parameter types.
-    if (filterType == WebKitCSSFilterValue::HueRotateFilterOperation && !argumentCount) {
-        // 1st parameter of hue-rotate() is an angle.
-        if (!validUnit(argument, FAngle, true))
-            return false;
-    } else if (filterType == WebKitCSSFilterValue::BlurFilterOperation) {
-        // parameters of blur() are lengths.
-        if (!validUnit(argument, FLength | FPercent, true))
-            return false;
-    } else if (filterType == WebKitCSSFilterValue::SharpenFilterOperation && argumentCount == 1) {
-        // 2nd parameter of sharpen() is a length.
-        if (!validUnit(argument, FLength | FPercent, true))
-            return false;
-    } else if (!validUnit(argument, FNumber, true))
-        return false;
+    RefPtr<WebKitCSSFilterValue> filterValue = WebKitCSSFilterValue::create(filterType);
+    ASSERT(args);
 
-    // Check parameter values.
-    if (filterType == WebKitCSSFilterValue::GrayscaleFilterOperation
-        || filterType == WebKitCSSFilterValue::SepiaFilterOperation
-        || 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::SaturateFilterOperation
-               || filterType == WebKitCSSFilterValue::GammaFilterOperation
-               || filterType == WebKitCSSFilterValue::BlurFilterOperation) {
-        // Arguments must be positive
-        double amount = argument->fValue;
-        if (amount < 0)
-            return false;
-    } else if (filterType == WebKitCSSFilterValue::SharpenFilterOperation) {
-        // Arguments must be positive
-        double amount = argument->fValue;
-        if (!argumentCount) {
-            if (amount < 0 || amount > 1)
-                return false;
-        } else {
-            if (amount < 0)
-                return false;
+    switch (filterType) {    
+    case WebKitCSSFilterValue::GrayscaleFilterOperation:
+    case WebKitCSSFilterValue::SepiaFilterOperation:
+    case WebKitCSSFilterValue::SaturateFilterOperation:
+    case WebKitCSSFilterValue::InvertFilterOperation:
+    case WebKitCSSFilterValue::OpacityFilterOperation: {
+        // One optional argument, 0-1 or 0%-100%, if missing use 100%.
+        if (args->size() > 1)
+            return 0;
+
+        if (args->size()) {
+            CSSParserValue* value = args->current();
+            if (!validUnit(value, FNumber | FPercent | FNonNeg, true))
+                return 0;
+                
+            double amount = value->fValue;
+            
+            // Saturate allows values over 100%.
+            if (filterType != WebKitCSSFilterValue::SaturateFilterOperation) {
+                double maxAllowed = value->unit == CSSPrimitiveValue::CSS_PERCENTAGE ? 100.0 : 1.0;
+                if (amount > maxAllowed)
+                    return 0;
+            }
+
+            filterValue->append(cssValuePool()->createValue(amount, static_cast<CSSPrimitiveValue::UnitTypes>(value->unit)));
         }
+        break;
     }
-    return true;
+    case WebKitCSSFilterValue::HueRotateFilterOperation: {
+        // hue-rotate() takes one optional angle.
+        if (args->size() > 1)
+            return 0;
+        
+        if (args->size()) {
+            CSSParserValue* argument = args->current();
+            if (!validUnit(argument, FAngle, true))
+                return 0;
+        
+            filterValue->append(createPrimitiveNumericValue(argument));
+        }
+        break;
+    }
+    case WebKitCSSFilterValue::GammaFilterOperation:
+        // Three optional arguments, values unlimited.
+        if (args->size() > 3)
+            return 0;
+
+        for (CSSParserValue* value = args->current(); value; value = args->next()) {
+            if (!validUnit(value, FNumber | FNonNeg, true))
+                return 0;
+                
+            filterValue->append(createPrimitiveNumericValue(value));
+        }
+        break;
+    case WebKitCSSFilterValue::BlurFilterOperation: {
+        // Blur takes one or two lengths. Zero parameters are allowed.
+        if (args->size() > 2)
+            return 0;
+
+        for (CSSParserValue* value = args->current(); value; value = args->next()) {
+            if (!validUnit(value, FLength | FPercent | FNonNeg, true))
+                return 0;
+
+            filterValue->append(createPrimitiveNumericValue(value));
+        }
+        break;
+    }
+    // FIXME: sharpen will be removed.
+    case WebKitCSSFilterValue::SharpenFilterOperation: {
+        // Sharpen has up to 3 arguments: 0-1 (or percentage) defaulting to 0, radius (a length, default 0), and optional threshold (0-1, defaults to 1).
+        if (args->size() > 3)
+            return 0;
+
+        CSSParserValue* value = args->current();
+        if (args->size() > 0) {
+            if (!validUnit(value, FNumber | FPercent, true))
+                return 0;
+
+            double maxAllowed = value->unit == CSSPrimitiveValue::CSS_PERCENTAGE ? 100.0 : 1.0;
+            double amount = max<double>(min<double>(value->fValue, maxAllowed), 0);
+            filterValue->append(cssValuePool()->createValue(amount, static_cast<CSSPrimitiveValue::UnitTypes>(value->unit)));
+        }
+        
+        if (args->size() > 1) {
+            value = args->next();
+            if (!validUnit(value, FLength | FNonNeg, true))
+                return 0;
+
+            filterValue->append(createPrimitiveNumericValue(value));
+        }
+
+        if (args->size() > 2) {
+            value = args->next();
+            if (!validUnit(value, FNumber, true))
+                return 0;
+
+            filterValue->append(createPrimitiveNumericValue(value));
+        }
+        break;
+    }
+    case WebKitCSSFilterValue::DropShadowFilterOperation: {
+        // drop-shadow() takes a single shadow.
+        RefPtr<CSSValueList> shadowValueList = parseShadow(args, CSSPropertyWebkitFilter);
+        if (!shadowValueList || shadowValueList->length() != 1)
+            return 0;
+        
+        filterValue->append((shadowValueList.release())->itemWithoutBoundsCheck(0));
+        break;
+    }
+    default:
+        ASSERT_NOT_REACHED();
+    }
+    return filterValue.release();
 }
 
 PassRefPtr<CSSValueList> CSSParser::parseFilter()
@@ -6850,39 +6922,15 @@
                 continue;
             }
 #endif
-
             CSSParserValueList* args = value->function->args.get();
-            if (!args || args->size() > maximumArgumentCount)
+            if (!args)
                 return 0;
+
+            RefPtr<WebKitCSSFilterValue> filterValue = parseBuiltinFilterArguments(args, filterType);
+            if (!filterValue)
+                return 0;
             
-            // Create the new WebKitCSSFilterValue for this operation and add it to our list.
-            RefPtr<WebKitCSSFilterValue> filterValue = WebKitCSSFilterValue::create(filterType);
             list->append(filterValue);
-            
-            if (filterType == WebKitCSSFilterValue::DropShadowFilterOperation) {
-                RefPtr<CSSValueList> shadowValueList = parseShadow(args, CSSPropertyWebkitFilter);
-                if (shadowValueList && shadowValueList->length() == 1)
-                    filterValue->append((shadowValueList.release())->itemWithoutBoundsCheck(0));
-                else
-                    return 0;
-            } else {
-
-                CSSParserValue* argument = args->current();
-                unsigned argumentCount = 0;
-
-                while (argument) {
-                    if (!isValidFilterArgument(argument, filterType, argumentCount))
-                        return 0;
-
-                    filterValue->append(createPrimitiveNumericValue(argument));
-
-                    argument = args->next();
-                    if (!argument)
-                        break;
-
-                    ++argumentCount;
-                }
-            }
         }
     }
 

Modified: trunk/Source/WebCore/css/CSSParser.h (102854 => 102855)


--- trunk/Source/WebCore/css/CSSParser.h	2011-12-15 01:24:18 UTC (rev 102854)
+++ trunk/Source/WebCore/css/CSSParser.h	2011-12-15 01:30:35 UTC (rev 102855)
@@ -192,8 +192,8 @@
     bool parseCrossfade(CSSParserValueList*, RefPtr<CSSValue>&);
 
 #if ENABLE(CSS_FILTERS)
-    bool isValidFilterArgument(CSSParserValue* argument, WebKitCSSFilterValue::FilterOperationType&, unsigned argumentCount);
     PassRefPtr<CSSValueList> parseFilter();
+    PassRefPtr<WebKitCSSFilterValue> parseBuiltinFilterArguments(CSSParserValueList*, WebKitCSSFilterValue::FilterOperationType);
 #if ENABLE(CSS_SHADERS)
     PassRefPtr<WebKitCSSFilterValue> parseCustomFilter(CSSParserValue*);
 #endif

Modified: trunk/Source/WebCore/css/CSSStyleSelector.cpp (102854 => 102855)


--- trunk/Source/WebCore/css/CSSStyleSelector.cpp	2011-12-15 01:24:18 UTC (rev 102854)
+++ trunk/Source/WebCore/css/CSSStyleSelector.cpp	2011-12-15 01:30:35 UTC (rev 102855)
@@ -5324,8 +5324,11 @@
         case WebKitCSSFilterValue::SepiaFilterOperation:
         case WebKitCSSFilterValue::SaturateFilterOperation: {
             double amount = 1;
-            if (filterValue->length() == 1)
+            if (filterValue->length() == 1) {
                 amount = firstValue->getDoubleValue();
+                if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE)
+                    amount /= 100;
+            }
 
             operations.operations().append(BasicColorMatrixFilterOperation::create(amount, operationType));
             break;
@@ -5348,8 +5351,11 @@
         case WebKitCSSFilterValue::InvertFilterOperation:
         case WebKitCSSFilterValue::OpacityFilterOperation: {
             double amount = 1;
-            if (filterValue->length() == 1)
+            if (filterValue->length() == 1) {
                 amount = firstValue->getDoubleValue();
+                if (firstValue->primitiveType() == CSSPrimitiveValue::CSS_PERCENTAGE)
+                    amount /= 100;
+            }
 
             operations.operations().append(BasicComponentTransferFilterOperation::create(amount, operationType));
             break;
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to