Changeset 154906 in webkit


Ignore:
Timestamp:
Aug 30, 2013 12:29:03 PM (11 years ago)
Author:
krit@webkit.org
Message:

Animate CSS Image filter() function
https://bugs.webkit.org/show_bug.cgi?id=119938

Reviewed by Simon Fraser.

Source/WebCore:

With this patch, the new introduced CSS Image function filter() can be
animated. According to the spec, just filter functions can be
interpolated.

The patch also prepares StyleImage blending for interpolation of other
generated images like gradients or cross-fade().

http://dev.w3.org/fxtf/filters/#interpolating-filter-image

Test: fast/filter-image/filter-image-animation.html

  • css/CSSComputedStyleDeclaration.cpp: Reuse the code that creates a

CSSValueList from ComputeStyle logic.

(WebCore::valueForPixel):

For StyleRules we want to have not-adjusted length values.

(WebCore::ComputedStyleExtractor::valueForShadow):

Add argument to switch between adjusted and not-adjusted length.

(WebCore::ComputedStyleExtractor::valueForFilter):

Ditto.

(WebCore::ComputedStyleExtractor::propertyValue):

  • css/CSSComputedStyleDeclaration.h:
  • css/CSSFilterImageValue.h: Add helper functions

for animating filters. We need to pass the FilterOperations for
the image generation and the CSSValueList for StyleRule.

(WebCore::CSSFilterImageValue::filterOperations):
(WebCore::CSSFilterImageValue::setFilterOperations):
(WebCore::CSSFilterImageValue::cachedImage):

  • page/animation/CSSPropertyAnimation.cpp:

Add animation code to support animations between two filter()
function values.

(WebCore::blendFilterOperations):
(WebCore::blendFunc):
(WebCore::filterBlend):

  • rendering/style/StyleGeneratedImage.h: Add helper functions.

(WebCore::CSSFilterImageValue::imageValue):

LayoutTests:

Add tests to test animation between two filter() function values.
Furthermore, extended animation-test-helpers.js to parse all kind of CSS
image function where we support animations. CSS Image function can be
deeply nested as well now:

-wekit-filter(-webkit-cross-fade(url(a.png), url(b.png), 50%), sepia(0.5))

Even the 50% can now be checked with a tolerance. If we should ever support
animations on nested CSS Images, the new code in animation-test-helpers.js
is prepared for it.

Fixed a bunch of tests that passed by accident or needed an update to the new
infrastructure.

  • animations/resources/animation-test-helpers.js:

(parseCSSImage): For parsing of all kind of supported CSS Image functions.

Currently supported: -webkit-cross-fade, -webkit-filter, url, none
Still missing: linear and radial gradients (can not be animated yet).
CSS Image functions are allowed to be nested as deep JS allows.

(parseCrossFade): Add parsing of input CSS images.
(parseFilterImage): Parse -webkit-filter image function as well as input images.
(parseFilterFunctionList): Parse filter function list. We now parse the

function name as well. Added rudimentary support for drop-shadow and url.

(parseDeprecatedCustomFilterFunction): Special case old syntax of custom

filter function. Shall be removed in the future.

(compareCSSImages): Compares all kind (even deep nested) CSS images.
(compareFilterFunctions): Now compare filter function names as well.
(comparePropertyValue): Use new compareCSSImages function.

  • fast/filter-image/filter-image-animation-expected.txt: Added.
  • fast/filter-image/filter-image-animation.html: Added.
Location:
trunk
Files:
3 added
35 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r154896 r154906  
     12013-08-30  Dirk Schulze  <krit@webkit.org>
     2
     3        Animate CSS Image filter() function
     4        https://bugs.webkit.org/show_bug.cgi?id=119938
     5
     6        Reviewed by Simon Fraser.
     7
     8        Add tests to test animation between two filter() function values.
     9        Furthermore, extended animation-test-helpers.js to parse all kind of CSS
     10        image function where we support animations. CSS Image function can be
     11        deeply nested as well now:
     12
     13            -wekit-filter(-webkit-cross-fade(url(a.png), url(b.png), 50%), sepia(0.5))
     14
     15        Even the 50% can now be checked with a tolerance. If we should ever support
     16        animations on nested CSS Images, the new code in animation-test-helpers.js
     17        is prepared for it.
     18
     19        Fixed a bunch of tests that passed by accident or needed an update to the new
     20        infrastructure.
     21
     22        * animations/resources/animation-test-helpers.js:
     23        (parseCSSImage): For parsing of all kind of supported CSS Image functions.
     24            Currently supported: -webkit-cross-fade, -webkit-filter, url, none
     25            Still missing: linear and radial gradients (can not be animated yet).
     26            CSS Image functions are allowed to be nested as deep JS allows.
     27        (parseCrossFade): Add parsing of input CSS images.
     28        (parseFilterImage): Parse -webkit-filter image function as well as input images.
     29        (parseFilterFunctionList): Parse filter function list. We now parse the
     30            function name as well. Added rudimentary support for drop-shadow and url.
     31        (parseDeprecatedCustomFilterFunction): Special case old syntax of custom
     32            filter function. Shall be removed in the future.
     33        (compareCSSImages): Compares all kind (even deep nested) CSS images.
     34        (compareFilterFunctions): Now compare filter function names as well.
     35        (comparePropertyValue): Use new compareCSSImages function.
     36        * fast/filter-image/filter-image-animation-expected.txt: Added.
     37        * fast/filter-image/filter-image-animation.html: Added.
     38
    1392013-08-30  Rob Buis  <rwlbuis@webkit.org>
    240
  • trunk/LayoutTests/animations/cross-fade-background-image.html

    r102388 r154906  
    4242    const expectedValues = [
    4343      // [animation-name, time, element-id, property, expected-value, tolerance]
    44       ["anim", 2.5, "box", "backgroundImage", 0.5, 0.05],
    45       ["anim", 2.5, ["box", "static:boxStatic"], "backgroundImage", 0.5, 0.05],
    46       ["animShorthand", 2.5, ["boxShorthand", "static:boxStatic"], "backgroundImage", 0.5, 0.05],
     44      ["anim", 2.5, "box", "backgroundImage", "-webkit-cross-fade(url(blue-100.png), url(green-100.png), 50%)", 0.05],
     45      ["anim", 2.5, ["box", "static:boxStatic"], "backgroundImage", "-webkit-cross-fade(url(blue-100.png), url(green-100.png), 50%)", 0.05],
     46      ["animShorthand", 2.5, ["boxShorthand", "static:boxStatic"], "backgroundImage", "-webkit-cross-fade(url(blue-100.png), url(green-100.png), 50%)", 0.05],
    4747    ];
    4848
  • trunk/LayoutTests/animations/cross-fade-border-image-source.html

    r102388 r154906  
    4444      // [animation-name, time, element-id, property, expected-value, tolerance]
    4545      // FIXME: We can't test reading the borderImage shorthand because of bug #13658.
    46       ["anim", 2.5, "box", "borderImageSource", 0.5, 0.05],
    47       ["anim", 2.5, ["box", "static:boxStatic"], "borderImageSource", 0.5, 0.05],
    48       ["animShorthand", 2.5, ["boxShorthand", "static:boxStatic"], "borderImageSource", 0.5, 0.05],
     46      ["anim", 2.5, "box", "borderImageSource", "-webkit-cross-fade(url(stripes-100.png), url(green-100.png), 0.5)", 0.05],
     47      ["anim", 2.5, ["box", "static:boxStatic"], "borderImageSource", "-webkit-cross-fade(url(stripes-100.png), url(green-100.png), 50%)", 0.05],
     48      ["animShorthand", 2.5, ["boxShorthand", "static:boxStatic"], "borderImageSource", "-webkit-cross-fade(url(stripes-100), url(green-100.png), 50%)", 0.05],
    4949    ];
    5050
  • trunk/LayoutTests/animations/cross-fade-list-style-image.html

    r102388 r154906  
    3939    const expectedValues = [
    4040      // [animation-name, time, element-id, property, expected-value, tolerance]
    41       ["anim", 2.5, "box", "listStyleImage", 0.5, 0.05],
    42       ["anim", 2.5, ["box", "static:boxStatic"], "listStyleImage", 0.5, 0.05],
    43       ["animShorthand", 2.5, ["boxShorthand", "static:boxStatic"], "listStyleImage", 0.5, 0.05],
     41      ["anim", 2.5, "box", "listStyleImage", "-webkit-cross-fade(url(blue-100.png), url(green-100.png), 50%)", 0.05],
     42      ["anim", 2.5, ["box", "static:boxStatic"], "listStyleImage", "-webkit-cross-fade(url(blue-100.png), url(green-100.png), 50%)", 0.05],
     43      ["animShorthand", 2.5, ["boxShorthand", "static:boxStatic"], "listStyleImage", "-webkit-cross-fade(url(blue-100.png), url(green-100.png), 50%)", 0.05],
    4444    ];
    4545
  • trunk/LayoutTests/animations/cross-fade-webkit-mask-box-image.html

    r104851 r154906  
    2929    const expectedValues = [
    3030      // [animation-name, time, element-id, property, expected-value, tolerance]
    31       ["anim", 2.25, "box", "webkitMaskBoxImage", 0.25, 0.05],
    32       ["anim", 2.25, ["box", "static:boxStatic"], "webkitMaskBoxImage", 0.25, 0.05]
     31      ["anim", 2.25, "box", "webkitMaskBoxImage", "-webkit-cross-fade(url(stripes-100.png), url(green-100.png), 25%)", 0.05],
     32      ["anim", 2.25, ["box", "static:boxStatic"], "webkitMaskBoxImage", "-webkit-cross-fade(url(stripes-100.png), url(green-100.png), 25%)", 0.05]
    3333    ];
    3434
  • trunk/LayoutTests/animations/cross-fade-webkit-mask-image.html

    r102388 r154906  
    2929    const expectedValues = [
    3030      // [animation-name, time, element-id, property, expected-value, tolerance]
    31       ["anim", 2.25, "box", "webkitMaskImage", 0.25, 0.05],
    32       ["anim", 2.25, ["box", "static:boxStatic"], "webkitMaskImage", 0.25, 0.05]
     31      ["anim", 2.25, "box", "webkitMaskImage", "-webkit-cross-fade(url(stripes-100.png), url(green-100.png), 25%)", 0.05],
     32      ["anim", 2.25, ["box", "static:boxStatic"], "webkitMaskImage", "-webkit-cross-fade(url(stripes-100.png), url(green-100.png), 25%)", 0.05]
    3333    ];
    3434
  • trunk/LayoutTests/animations/resources/animation-test-helpers.js

    r142171 r154906  
    3535*/
    3636
    37 function isCloseEnough(actual, desired, tolerance)
    38 {
    39     var diff = Math.abs(actual - desired);
     37function isCloseEnough(actual, expected, tolerance)
     38{
     39    if (isNaN(actual) || isNaN(expected))
     40        return false;
     41    var diff = Math.abs(actual - expected);
    4042    return diff <= tolerance;
    4143}
     
    5052}
    5153
     54function parseCSSImage(s)
     55{
     56    // Special case none.
     57    if (s == "none")
     58        return ["none"];
     59
     60    // Separate function name from function value.
     61    var matches = s.match("([\\w\\-]+)\\((.*)\\)");
     62    if (!matches){
     63        console.error("Parsing error. Value not a CSS Image function ", s);
     64        return false;
     65    }
     66
     67    var functionName = matches[1];
     68    var functionValue = matches[2];
     69
     70    // Generator functions can have CSS images as values themself.
     71    // These functions will call parseCSSImage for each CSS Image.
     72    switch (functionName) {
     73    case "-webkit-filter":
     74        return parseFilterImage(functionValue);
     75    case "-webkit-cross-fade":
     76        return parseCrossFade(functionValue);
     77    case "url":
     78        return ["url", functionValue];
     79    // FIXME: Add support for linear and redial gradient.
     80    default:
     81        // All supported filter functions must be listed above.
     82        return false;
     83    }
     84}
     85
     86// This should just be called by parseCSSImage.
    5287function parseCrossFade(s)
    5388{
    54     var matches = s.match("-webkit-cross-fade\\((.*)\\s*,\\s*(.*)\\s*,\\s*(.*)\\)");
    55 
    56     if (!matches)
    57         return null;
    58 
    59     return {"from": matches[1], "to": matches[2], "percent": parseFloat(matches[3])}
     89    var matches = s.match("(.*)\\s*,\\s*(.*)\\s*,\\s*(.*)\\s*");
     90    if (!matches) {
     91        console.error("Parsing error on '-webkit-cross-fade()'.");
     92        return null;
     93    }
     94
     95    var from = parseCSSImage(matches[1]);
     96    var to = parseCSSImage(matches[2]);
     97    if (!from || !to) {
     98        console.error("Parsing error on images passed to '-webkit-cross-fade()' ", s);
     99        return null;
     100    }
     101
     102    var fadeValue = matches[3];
     103    var percent;
     104    if (isNaN(fadeValue)) {
     105        // Check if last char is '%' and rip it off.
     106        // Normalize it to number.
     107        if (fadeValue.search('%') != fadeValue.length - 1) {
     108            console.error("Passed value to '-webkit-cross-fade()' is not a number or percentage ", fadeValue);
     109            return null;
     110        }
     111        fadeValue = fadeValue.slice(0, fadeValue.length - 1);
     112        if (isNaN(fadeValue)) {
     113            console.error("Passed value to '-webkit-cross-fade()' is not a number or percentage ", fadeValue);
     114            return null;
     115        }
     116        percent = parseFloat(fadeValue) / 100;
     117    } else
     118        percent = parseFloat(fadeValue);
     119
     120    return ["-webkit-cross-fade", from, to, percent];
     121}
     122
     123// This should just be called by parseCSSImage.
     124function parseFilterImage(s)
     125{
     126    // Separate image value from filter function list.
     127    var matches = s.match("([\\-\\w]+\\(.*\\))\\s*,\\s*(.*)\\s*");
     128    if (!matches) {
     129        console.error("Parsing error on 'fitler()' ", s);
     130        return false;
     131    }
     132
     133    var image = parseCSSImage(matches[1]);
     134    if (!image) {
     135        console.error("Parsing error on image passed to 'fitler()' ", s);
     136        return false;
     137    }
     138
     139    var filterFunctionList = parseFilterFunctionList(matches[2]);
     140    if (!filterFunctionList) {
     141        console.error("Parsing error on filter function list passed to 'fitler()' ", s);
     142        return false;
     143    }
     144
     145    return ["-webkit-filter", image, filterFunctionList];
     146}
     147
     148function parseFilterFunctionList(s)
     149{
     150    var reg = /\)*\s*(blur|brightness|contrast|custom|drop\-shadow|grayscale|hue\-rotate|invert|opacity|saturate|sepia|url)\(/
     151    var matches = s.split(reg);
     152
     153    // First item must be empty. All other items are of functionName, functionValue.
     154    if (!matches || matches.shift() != "")
     155        return null;
     156
     157    // RegEx above can not handle deprecated custom() function
     158    var customPos = matches.indexOf("custom");
     159    if (customPos >= 0 && matches[customPos+1] === "")
     160        return parseDeprecatedCustomFilterFunction(s);
     161
     162    // Odd items are the function name, even items the function value.
     163    if (!matches.length || matches.length % 2)
     164        return null;
     165
     166    var functionList = [];
     167    for (var i = 0; i < matches.length; i += 2) {
     168        var functionName = matches[i];
     169        var functionValue = matches[i+1];
     170        functionList.push(functionName);
     171        if (functionName == "drop-shadow" || functionName == "url") {
     172            // FIXME: Support parsing of drop-shadow.
     173            functionList.push(functionValue);
     174            continue;
     175        } else if (functionName == "custom") {
     176            var filterParams;
     177            if (!window.getCustomFilterParameters)
     178                throw new Error("getCustomFilterParameters not found. Did you include custom-filter-parser.js?");
     179            var filterParams = getCustomFilterParameters(functionValue);
     180            if (!filterParams) {
     181                console.error("Error on parsing custom filter parameters ", functionValue);
     182                return null;
     183            }
     184            functionList.push(filterParams);
     185            continue;
     186        }
     187        functionList.push(parseFloat(functionValue));
     188    }
     189    return functionList;
     190}
     191
     192// FIXME: Remove function and caller when we removed the deprecated syntax of
     193// the custom filter function.
     194function parseDeprecatedCustomFilterFunction(s)
     195{
     196    var filterResult = s.match(/(\w+)\((.+)\)/);
     197    var filterParams = filterResult[2];
     198
     199    if (filterResult[1] != "custom")
     200        return null;
     201
     202    if (!window.getCustomFilterParameters)
     203        throw new Error("getCustomFilterParameters not found. Did you include custom-filter-parser.js?");
     204    return ["custom", getCustomFilterParameters(filterParams)];
    60205}
    61206
     
    100245}
    101246
     247function compareCSSImages(computedValue, expectedValue, tolerance)
     248{
     249    var actual = typeof computedValue === "string" ? parseCSSImage(computedValue) : computedValue;
     250    var expected = typeof expectedValue === "string" ? parseCSSImage(expectedValue) : expectedValue;
     251    if (!actual || !Array.isArray(actual)         // Check that: actual is an array,
     252        || !expected || !Array.isArray(expected)  // expected is an array,
     253        || actual[0] != expected[0]) {            // and image function names are the same.
     254        console.error("Unexpected mismatch between CSS Image functions.");
     255        return false;
     256    }
     257    switch (actual[0]) {
     258    case "none":
     259        return true;
     260    case "-webkit-filter":
     261        return compareCSSImages(actual[1], expected[1], tolerance)
     262            && compareFilterFunctions(actual[2], expected[2], tolerance);
     263    case "-webkit-cross-fade":
     264        return compareCSSImages(actual[1], expected[1], tolerance)
     265            && compareCSSImages(actual[2], expected[2], tolerance)
     266            && isCloseEnough(actual[3], expected[3], tolerance);
     267    case "url":
     268        return actual[1].search(expected[1]) >= 0;
     269    default:
     270        console.error("Unknown CSS Image function ", actual[0]);
     271        return false;
     272    }
     273}
     274
     275// Called by CSS Image function filter() as well as filter property.
     276function compareFilterFunctions(computedValue, expectedValue, tolerance)
     277{
     278    var actual = typeof computedValue === "string" ? parseFilterFunctionList(computedValue) : computedValue;
     279    var expected = typeof expectedValue === "string" ? parseFilterFunctionList(expectedValue) : expectedValue;
     280    if (!actual || !Array.isArray(actual)         // Check that: actual is an array,
     281        || !expected || !Array.isArray(expected)  // expected is an array,
     282        || !actual.length                         // actual array has entries,
     283        || actual.length != expected.length       // actual and expected have same length
     284        || actual.length % 2 == 1)                // and image function names are the same.
     285        return false;
     286
     287    for (var i = 0; i < actual.length; i += 2) {
     288        if (actual[i] != expected[i]) {
     289            console.error("Filter functions do not match.");
     290            return false;
     291        }
     292        if (actual[i] == "custom") {
     293            if (!customFilterParameterMatch(actual[i+1], expected[i+1], tolerance)) {
     294                console.error("Custom filter parameters do not match.");
     295                return false;
     296            }
     297            continue;
     298        }
     299        if (!isCloseEnough(actual[i+1], expected[i+1], tolerance)) {
     300            console.error("Filter function values do not match.");
     301            return false;
     302        }
     303    }
     304    return true;
     305}
     306
    102307function basicShapeParametersMatch(paramList1, paramList2, tolerance)
    103308{
     
    113318    }
    114319    return true;
    115 }
    116 
    117 // Return an array of numeric filter params in 0-1.
    118 function getFilterParameters(s)
    119 {
    120     var filterResult = s.match(/(\w+)\((.+)\)/);
    121     if (!filterResult)
    122         throw new Error("There's no filter in \"" + s + "\"");
    123     var filterParams = filterResult[2];
    124     if (filterResult[1] == "custom") {
    125         if (!window.getCustomFilterParameters)
    126             throw new Error("getCustomFilterParameters not found. Did you include custom-filter-parser.js?");
    127         return getCustomFilterParameters(filterParams);
    128     }
    129     var paramList = filterParams.split(' '); // FIXME: the spec may allow comma separation at some point.
    130    
    131     // Normalize percentage values.
    132     for (var i = 0; i < paramList.length; ++i) {
    133         var param = paramList[i];
    134         paramList[i] = parseFloat(paramList[i]);
    135         if (param.indexOf('%') != -1)
    136             paramList[i] = paramList[i] / 100;
    137     }
    138 
    139     return paramList;
    140320}
    141321
     
    183363}
    184364
    185 function filterParametersMatch(paramList1, paramList2, tolerance)
    186 {
    187     if (paramList1.length != paramList2.length)
    188         return false;
    189     for (var i = 0; i < paramList1.length; ++i) {
    190         var param1 = paramList1[i],
    191             param2 = paramList2[i];
    192         if (typeof param1 == "object") {
    193             // This is a custom filter parameter.
    194             if (!customFilterParameterMatch(param1, param2, tolerance))
    195                 return false;
    196             continue;
    197         }
    198         var match = isCloseEnough(param1, param2, tolerance);
    199         if (!match)
    200             return false;
    201     }
    202     return true;
    203 }
    204 
    205365function checkExpectedValue(expected, index)
    206366{
     
    330490        }
    331491    } else if (property == "webkitFilter") {
    332         var filterParameters = getFilterParameters(computedValue);
    333         var filter2Parameters = getFilterParameters(expectedValue);
    334         result = filterParametersMatch(filterParameters, filter2Parameters, tolerance);
     492        var filterParameters = parseFilterFunctionList(computedValue);
     493        var filter2Parameters = parseFilterFunctionList(expectedValue);
     494        result = compareFilterFunctions(filterParameters, filter2Parameters, tolerance);
    335495    } else if (property == "webkitClipPath" || property == "webkitShapeInside") {
    336496        var clipPathParameters = parseBasicShape(computedValue);
     
    343503               || property == "listStyleImage"
    344504               || property == "webkitMaskImage"
    345                || property == "webkitMaskBoxImage") {
    346         var computedCrossFade = parseCrossFade(computedValue);
    347 
    348         if (!computedCrossFade) {
    349             result = false;
    350         } else {
    351             if (typeof expectedValue == "string") {
    352                 var computedCrossFade2 = parseCrossFade(expectedValue);
    353                 result = isCloseEnough(computedCrossFade.percent, computedCrossFade2.percent, tolerance) && computedCrossFade.from == computedCrossFade2.from && computedCrossFade.to == computedCrossFade2.to;
    354             } else {
    355                 result = isCloseEnough(computedCrossFade.percent, expectedValue, tolerance)
    356             }
    357         }
    358     } else {
     505               || property == "webkitMaskBoxImage")
     506        result = compareCSSImages(computedValue, expectedValue, tolerance);
     507    else {
    359508        result = isCloseEnough(computedValue, expectedValue, tolerance);
    360509    }
  • trunk/LayoutTests/css3/filters/filter-animation-expected.txt

    r103125 r154906  
    33PASS - "webkitFilter" property for "sepia-box" element at 1s saw something close to: sepia(0.5)
    44PASS - "webkitFilter" property for "saturate-box" element at 1s saw something close to: saturate(0.5)
    5 PASS - "webkitFilter" property for "huerotate-box" element at 1s saw something close to: huerotate(90deg)
     5PASS - "webkitFilter" property for "huerotate-box" element at 1s saw something close to: hue-rotate(90deg)
    66PASS - "webkitFilter" property for "invert-box" element at 1s saw something close to: invert(0.5)
    77PASS - "webkitFilter" property for "opacity-box" element at 1s saw something close to: opacity(0.5)
  • trunk/LayoutTests/css3/filters/filter-animation-from-none-expected.txt

    r103586 r154906  
    33PASS - "webkitFilter" property for "sepia-box" element at 0.5s saw something close to: sepia(0.25)
    44PASS - "webkitFilter" property for "saturate-box" element at 0.5s saw something close to: saturate(0.75)
    5 PASS - "webkitFilter" property for "huerotate-box" element at 0.5s saw something close to: huerotate(45deg)
     5PASS - "webkitFilter" property for "huerotate-box" element at 0.5s saw something close to: hue-rotate(45deg)
    66PASS - "webkitFilter" property for "invert-box" element at 0.5s saw something close to: invert(0.25)
    77PASS - "webkitFilter" property for "opacity-box" element at 0.5s saw something close to: opacity(0.75)
  • trunk/LayoutTests/css3/filters/filter-animation-from-none-hw-expected.txt

    r107422 r154906  
    33PASS - "webkitFilter" property for "sepia-box" element at 1s saw something close to: sepia(0.5)
    44PASS - "webkitFilter" property for "saturate-box" element at 1s saw something close to: saturate(0.5)
    5 PASS - "webkitFilter" property for "huerotate-box" element at 1s saw something close to: huerotate(90deg)
     5PASS - "webkitFilter" property for "huerotate-box" element at 1s saw something close to: hue-rotate(90deg)
    66PASS - "webkitFilter" property for "invert-box" element at 1s saw something close to: invert(0.5)
    77PASS - "webkitFilter" property for "opacity-box" element at 1s saw something close to: opacity(0.5)
  • trunk/LayoutTests/css3/filters/filter-animation-from-none-hw.html

    r107422 r154906  
    112112      ["sepia-anim",  1, "sepia-box", "webkitFilter", 'sepia(0.5)', 0.05],
    113113      ["saturate-anim",  1, "saturate-box", "webkitFilter", 'saturate(0.5)', 0.05],
    114       ["huerotate-anim",  1, "huerotate-box", "webkitFilter", 'huerotate(90deg)', 5],
     114      ["huerotate-anim",  1, "huerotate-box", "webkitFilter", 'hue-rotate(90deg)', 5],
    115115      ["invert-anim",  1, "invert-box", "webkitFilter", 'invert(0.5)', 0.05],
    116116      ["opacity-anim",  1, "opacity-box", "webkitFilter", 'opacity(0.5)', 0.05],
  • trunk/LayoutTests/css3/filters/filter-animation-from-none-multi-expected.txt

    r107422 r154906  
    33PASS - "webkitFilter" property for "sepia-box" element at 0.5s saw something close to: sepia(0.25)
    44PASS - "webkitFilter" property for "saturate-box" element at 0.5s saw something close to: saturate(0.75)
    5 PASS - "webkitFilter" property for "huerotate-box" element at 0.5s saw something close to: huerotate(45deg)
     5PASS - "webkitFilter" property for "huerotate-box" element at 0.5s saw something close to: hue-rotate(45deg)
    66PASS - "webkitFilter" property for "invert-box" element at 0.5s saw something close to: invert(0.25)
    77PASS - "webkitFilter" property for "opacity-box" element at 0.5s saw something close to: opacity(0.75)
  • trunk/LayoutTests/css3/filters/filter-animation-from-none-multi-hw-expected.txt

    r107422 r154906  
    33PASS - "webkitFilter" property for "sepia-box" element at 0.5s saw something close to: sepia(0.25)
    44PASS - "webkitFilter" property for "saturate-box" element at 0.5s saw something close to: saturate(0.75)
    5 PASS - "webkitFilter" property for "huerotate-box" element at 0.5s saw something close to: huerotate(45deg)
     5PASS - "webkitFilter" property for "huerotate-box" element at 0.5s saw something close to: hue-rotate(45deg)
    66PASS - "webkitFilter" property for "invert-box" element at 0.5s saw something close to: invert(0.25)
    77PASS - "webkitFilter" property for "opacity-box" element at 0.5s saw something close to: opacity(0.75)
  • trunk/LayoutTests/css3/filters/filter-animation-from-none-multi-hw.html

    r107422 r154906  
    121121      ["sepia-anim",  0.5, "sepia-box", "webkitFilter", 'sepia(0.25)', 0.05],
    122122      ["saturate-anim",  0.5, "saturate-box", "webkitFilter", 'saturate(0.75)', 0.05],
    123       ["huerotate-anim",  0.5, "huerotate-box", "webkitFilter", 'huerotate(45deg)', 3],
     123      ["huerotate-anim",  0.5, "huerotate-box", "webkitFilter", 'hue-rotate(45deg)', 3],
    124124      ["invert-anim",  0.5, "invert-box", "webkitFilter", 'invert(0.25)', 0.05],
    125125      ["opacity-anim",  0.5, "opacity-box", "webkitFilter", 'opacity(0.75)', 0.05],
  • trunk/LayoutTests/css3/filters/filter-animation-from-none-multi.html

    r107422 r154906  
    121121      ["sepia-anim",  0.5, "sepia-box", "webkitFilter", 'sepia(0.25)', 0.05],
    122122      ["saturate-anim",  0.5, "saturate-box", "webkitFilter", 'saturate(0.75)', 0.05],
    123       ["huerotate-anim",  0.5, "huerotate-box", "webkitFilter", 'huerotate(45deg)', 5],
     123      ["huerotate-anim",  0.5, "huerotate-box", "webkitFilter", 'hue-rotate(45deg)', 5],
    124124      ["invert-anim",  0.5, "invert-box", "webkitFilter", 'invert(0.25)', 0.05],
    125125      ["opacity-anim",  0.5, "opacity-box", "webkitFilter", 'opacity(0.75)', 0.05],
  • trunk/LayoutTests/css3/filters/filter-animation-from-none.html

    r103586 r154906  
    111111      ["sepia-anim",  0.5, "sepia-box", "webkitFilter", 'sepia(0.25)', 0.05],
    112112      ["saturate-anim",  0.5, "saturate-box", "webkitFilter", 'saturate(0.75)', 0.05],
    113       ["huerotate-anim",  0.5, "huerotate-box", "webkitFilter", 'huerotate(45deg)', 3],
     113      ["huerotate-anim",  0.5, "huerotate-box", "webkitFilter", 'hue-rotate(45deg)', 3],
    114114      ["invert-anim",  0.5, "invert-box", "webkitFilter", 'invert(0.25)', 0.05],
    115115      ["opacity-anim",  0.5, "opacity-box", "webkitFilter", 'opacity(0.75)', 0.05],
  • trunk/LayoutTests/css3/filters/filter-animation-hw-expected.txt

    r107422 r154906  
    33PASS - "webkitFilter" property for "sepia-box" element at 1s saw something close to: sepia(0.5)
    44PASS - "webkitFilter" property for "saturate-box" element at 1s saw something close to: saturate(0.5)
    5 PASS - "webkitFilter" property for "huerotate-box" element at 1s saw something close to: huerotate(90deg)
     5PASS - "webkitFilter" property for "huerotate-box" element at 1s saw something close to: hue-rotate(90deg)
    66PASS - "webkitFilter" property for "invert-box" element at 1s saw something close to: invert(0.5)
    77PASS - "webkitFilter" property for "opacity-box" element at 1s saw something close to: opacity(0.5)
  • trunk/LayoutTests/css3/filters/filter-animation-hw.html

    r107422 r154906  
    113113      ["sepia-anim",  1, "sepia-box", "webkitFilter", 'sepia(0.5)', 0.05],
    114114      ["saturate-anim",  1, "saturate-box", "webkitFilter", 'saturate(0.5)', 0.05],
    115       ["huerotate-anim",  1, "huerotate-box", "webkitFilter", 'huerotate(90deg)', 2],
     115      ["huerotate-anim",  1, "huerotate-box", "webkitFilter", 'hue-rotate(90deg)', 2],
    116116      ["invert-anim",  1, "invert-box", "webkitFilter", 'invert(0.5)', 0.05],
    117117      ["opacity-anim",  1, "opacity-box", "webkitFilter", 'opacity(0.5)', 0.05],
  • trunk/LayoutTests/css3/filters/filter-animation-multi-expected.txt

    r107422 r154906  
    33PASS - "webkitFilter" property for "sepia-box" element at 1s saw something close to: sepia(0.5)
    44PASS - "webkitFilter" property for "saturate-box" element at 1s saw something close to: saturate(0.5)
    5 PASS - "webkitFilter" property for "huerotate-box" element at 1s saw something close to: huerotate(90deg)
     5PASS - "webkitFilter" property for "huerotate-box" element at 1s saw something close to: hue-rotate(90deg)
    66PASS - "webkitFilter" property for "invert-box" element at 1s saw something close to: invert(0.5)
    77PASS - "webkitFilter" property for "opacity-box" element at 1s saw something close to: opacity(0.5)
  • trunk/LayoutTests/css3/filters/filter-animation-multi-hw-expected.txt

    r107422 r154906  
    33PASS - "webkitFilter" property for "sepia-box" element at 1s saw something close to: sepia(0.5)
    44PASS - "webkitFilter" property for "saturate-box" element at 1s saw something close to: saturate(0.5)
    5 PASS - "webkitFilter" property for "huerotate-box" element at 1s saw something close to: huerotate(90deg)
     5PASS - "webkitFilter" property for "huerotate-box" element at 1s saw something close to: hue-rotate(90deg)
    66PASS - "webkitFilter" property for "invert-box" element at 1s saw something close to: invert(0.5)
    77PASS - "webkitFilter" property for "opacity-box" element at 1s saw something close to: opacity(0.5)
  • trunk/LayoutTests/css3/filters/filter-animation-multi-hw.html

    r107422 r154906  
    121121      ["sepia-anim",  1, "sepia-box", "webkitFilter", 'sepia(0.5)', 0.05],
    122122      ["saturate-anim",  1, "saturate-box", "webkitFilter", 'saturate(0.5)', 0.05],
    123       ["huerotate-anim",  1, "huerotate-box", "webkitFilter", 'huerotate(90deg)', 2],
     123      ["huerotate-anim",  1, "huerotate-box", "webkitFilter", 'hue-rotate(90deg)', 2],
    124124      ["invert-anim",  1, "invert-box", "webkitFilter", 'invert(0.5)', 0.05],
    125125      ["opacity-anim",  1, "opacity-box", "webkitFilter", 'opacity(0.5)', 0.05],
  • trunk/LayoutTests/css3/filters/filter-animation-multi.html

    r107422 r154906  
    121121      ["sepia-anim",  1, "sepia-box", "webkitFilter", 'sepia(0.5)', 0.05],
    122122      ["saturate-anim",  1, "saturate-box", "webkitFilter", 'saturate(0.5)', 0.05],
    123       ["huerotate-anim",  1, "huerotate-box", "webkitFilter", 'huerotate(90deg)', 2],
     123      ["huerotate-anim",  1, "huerotate-box", "webkitFilter", 'hue-rotate(90deg)', 2],
    124124      ["invert-anim",  1, "invert-box", "webkitFilter", 'invert(0.5)', 0.05],
    125125      ["opacity-anim",  1, "opacity-box", "webkitFilter", 'opacity(0.5)', 0.05],
  • trunk/LayoutTests/css3/filters/filter-animation.html

    r103586 r154906  
    111111      ["sepia-anim",  1, "sepia-box", "webkitFilter", 'sepia(0.5)', 0.05],
    112112      ["saturate-anim",  1, "saturate-box", "webkitFilter", 'saturate(0.5)', 0.05],
    113       ["huerotate-anim",  1, "huerotate-box", "webkitFilter", 'huerotate(90deg)', 2],
     113      ["huerotate-anim",  1, "huerotate-box", "webkitFilter", 'hue-rotate(90deg)', 2],
    114114      ["invert-anim",  1, "invert-box", "webkitFilter", 'invert(0.5)', 0.05],
    115115      ["opacity-anim",  1, "opacity-box", "webkitFilter", 'opacity(0.5)', 0.05],
  • trunk/LayoutTests/platform/mac/animations/cross-fade-background-image-expected.txt

    r110096 r154906  
    44  RenderBlock {HTML} at (0,0) size 800x600
    55    RenderBody {BODY} at (8,8) size 784x584
    6       RenderBlock {DIV} at (0,0) size 784x54
    7         RenderText {#text} at (0,0) size 577x18
    8           text run at (0,0) width 577: "PASS - \"backgroundImage\" property for \"box\" element at 2.5s saw something close to: 0.5"
    9         RenderBR {BR} at (577,14) size 0x0
    10         RenderText {#text} at (0,18) size 704x18
    11           text run at (0,18) width 704: "PASS - \"backgroundImage\" property for \"box\" and \"boxStatic\" elements at 2.5s are close enough to each other"
    12         RenderBR {BR} at (704,32) size 0x0
    13         RenderText {#text} at (0,36) size 769x18
    14           text run at (0,36) width 769: "PASS - \"backgroundImage\" property for \"boxShorthand\" and \"boxStatic\" elements at 2.5s are close enough to each other"
    15         RenderBR {BR} at (769,50) size 0x0
     6      RenderBlock {DIV} at (0,0) size 784x72
     7        RenderText {#text} at (0,0) size 733x36
     8          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-"
     9          text run at (0,18) width 226: "100.png), url(green-100.png), 50%)"
     10        RenderBR {BR} at (226,32) size 0x0
     11        RenderText {#text} at (0,36) size 704x18
     12          text run at (0,36) width 704: "PASS - \"backgroundImage\" property for \"box\" and \"boxStatic\" elements at 2.5s are close enough to each other"
     13        RenderBR {BR} at (704,50) size 0x0
     14        RenderText {#text} at (0,54) size 769x18
     15          text run at (0,54) width 769: "PASS - \"backgroundImage\" property for \"boxShorthand\" and \"boxStatic\" elements at 2.5s are close enough to each other"
     16        RenderBR {BR} at (769,68) size 0x0
    1617layer at (100,100) size 100x100
    1718  RenderBlock (positioned) {DIV} at (100,100) size 100x100 [bgcolor=#FF0000]
  • trunk/LayoutTests/platform/mac/animations/cross-fade-border-image-source-expected.txt

    r126704 r154906  
    44  RenderBlock {HTML} at (0,0) size 800x600
    55    RenderBody {BODY} at (8,8) size 784x584
    6       RenderBlock {DIV} at (0,0) size 784x54
    7         RenderText {#text} at (0,0) size 587x18
    8           text run at (0,0) width 587: "PASS - \"borderImageSource\" property for \"box\" element at 2.5s saw something close to: 0.5"
    9         RenderBR {BR} at (587,14) size 0x0
    10         RenderText {#text} at (0,18) size 714x18
    11           text run at (0,18) width 714: "PASS - \"borderImageSource\" property for \"box\" and \"boxStatic\" elements at 2.5s are close enough to each other"
    12         RenderBR {BR} at (714,32) size 0x0
    13         RenderText {#text} at (0,36) size 779x18
    14           text run at (0,36) width 779: "PASS - \"borderImageSource\" property for \"boxShorthand\" and \"boxStatic\" elements at 2.5s are close enough to each other"
    15         RenderBR {BR} at (779,50) size 0x0
     6      RenderBlock {DIV} at (0,0) size 784x72
     7        RenderText {#text} at (0,0) size 756x36
     8          text run at (0,0) width 756: "PASS - \"borderImageSource\" property for \"box\" element at 2.5s saw something close to: -webkit-cross-fade(url(stripes-"
     9          text run at (0,18) width 217: "100.png), url(green-100.png), 0.5)"
     10        RenderBR {BR} at (217,32) size 0x0
     11        RenderText {#text} at (0,36) size 714x18
     12          text run at (0,36) width 714: "PASS - \"borderImageSource\" property for \"box\" and \"boxStatic\" elements at 2.5s are close enough to each other"
     13        RenderBR {BR} at (714,50) size 0x0
     14        RenderText {#text} at (0,54) size 779x18
     15          text run at (0,54) width 779: "PASS - \"borderImageSource\" property for \"boxShorthand\" and \"boxStatic\" elements at 2.5s are close enough to each other"
     16        RenderBR {BR} at (779,68) size 0x0
    1617layer at (100,100) size 106x106
    1718  RenderBlock (positioned) {DIV} at (100,100) size 106x106 [bgcolor=#008000] [border: (3px none #000000)]
  • trunk/LayoutTests/platform/mac/animations/cross-fade-list-style-image-expected.txt

    r110096 r154906  
    44  RenderBlock {HTML} at (0,0) size 800x600
    55    RenderBody {BODY} at (8,8) size 784x584
    6       RenderBlock {DIV} at (0,0) size 784x54
    7         RenderText {#text} at (0,0) size 552x18
    8           text run at (0,0) width 552: "PASS - \"listStyleImage\" property for \"box\" element at 2.5s saw something close to: 0.5"
    9         RenderBR {BR} at (552,14) size 0x0
    10         RenderText {#text} at (0,18) size 679x18
    11           text run at (0,18) width 679: "PASS - \"listStyleImage\" property for \"box\" and \"boxStatic\" elements at 2.5s are close enough to each other"
    12         RenderBR {BR} at (679,32) size 0x0
    13         RenderText {#text} at (0,36) size 744x18
    14           text run at (0,36) width 744: "PASS - \"listStyleImage\" property for \"boxShorthand\" and \"boxStatic\" elements at 2.5s are close enough to each other"
    15         RenderBR {BR} at (744,50) size 0x0
     6      RenderBlock {DIV} at (0,0) size 784x72
     7        RenderText {#text} at (0,0) size 769x36
     8          text run at (0,0) width 769: "PASS - \"listStyleImage\" property for \"box\" element at 2.5s saw something close to: -webkit-cross-fade(url(blue-100.png),"
     9          text run at (0,18) width 161: "url(green-100.png), 50%)"
     10        RenderBR {BR} at (161,32) size 0x0
     11        RenderText {#text} at (0,36) size 679x18
     12          text run at (0,36) width 679: "PASS - \"listStyleImage\" property for \"box\" and \"boxStatic\" elements at 2.5s are close enough to each other"
     13        RenderBR {BR} at (679,50) size 0x0
     14        RenderText {#text} at (0,54) size 744x18
     15          text run at (0,54) width 744: "PASS - \"listStyleImage\" property for \"boxShorthand\" and \"boxStatic\" elements at 2.5s are close enough to each other"
     16        RenderBR {BR} at (744,68) size 0x0
    1617layer at (100,116) size 140x100
    1718  RenderBlock (positioned) {UL} at (100,116) size 140x100
  • trunk/LayoutTests/platform/mac/animations/cross-fade-webkit-mask-box-image-expected.txt

    r104884 r154906  
    44  RenderBlock {HTML} at (0,0) size 800x600
    55    RenderBody {BODY} at (8,8) size 784x584
    6       RenderBlock {DIV} at (0,0) size 784x36
    7         RenderText {#text} at (0,0) size 623x18
    8           text run at (0,0) width 623: "PASS - \"webkitMaskBoxImage\" property for \"box\" element at 2.25s saw something close to: 0.25"
    9         RenderBR {BR} at (623,14) size 0x0
    10         RenderText {#text} at (0,18) size 742x18
    11           text run at (0,18) width 742: "PASS - \"webkitMaskBoxImage\" property for \"box\" and \"boxStatic\" elements at 2.25s are close enough to each other"
    12         RenderBR {BR} at (742,32) size 0x0
     6      RenderBlock {DIV} at (0,0) size 784x54
     7        RenderText {#text} at (0,0) size 784x36
     8          text run at (0,0) width 784: "PASS - \"webkitMaskBoxImage\" property for \"box\" element at 2.25s saw something close to: -webkit-cross-fade(url(stripes-"
     9          text run at (0,18) width 226: "100.png), url(green-100.png), 25%)"
     10        RenderBR {BR} at (226,32) size 0x0
     11        RenderText {#text} at (0,36) size 742x18
     12          text run at (0,36) width 742: "PASS - \"webkitMaskBoxImage\" property for \"box\" and \"boxStatic\" elements at 2.25s are close enough to each other"
     13        RenderBR {BR} at (742,50) size 0x0
    1314layer at (100,100) size 200x200
    1415  RenderImage {IMG} at (100,100) size 200x200 [bgcolor=#FF0000]
  • trunk/LayoutTests/platform/mac/animations/cross-fade-webkit-mask-image-expected.txt

    r110096 r154906  
    44  RenderBlock {HTML} at (0,0) size 800x600
    55    RenderBody {BODY} at (8,8) size 784x584
    6       RenderBlock {DIV} at (0,0) size 784x36
    7         RenderText {#text} at (0,0) size 596x18
    8           text run at (0,0) width 596: "PASS - \"webkitMaskImage\" property for \"box\" element at 2.25s saw something close to: 0.25"
    9         RenderBR {BR} at (596,14) size 0x0
    10         RenderText {#text} at (0,18) size 715x18
    11           text run at (0,18) width 715: "PASS - \"webkitMaskImage\" property for \"box\" and \"boxStatic\" elements at 2.25s are close enough to each other"
    12         RenderBR {BR} at (715,32) size 0x0
     6      RenderBlock {DIV} at (0,0) size 784x54
     7        RenderText {#text} at (0,0) size 757x36
     8          text run at (0,0) width 757: "PASS - \"webkitMaskImage\" property for \"box\" element at 2.25s saw something close to: -webkit-cross-fade(url(stripes-"
     9          text run at (0,18) width 226: "100.png), url(green-100.png), 25%)"
     10        RenderBR {BR} at (226,32) size 0x0
     11        RenderText {#text} at (0,36) size 715x18
     12          text run at (0,36) width 715: "PASS - \"webkitMaskImage\" property for \"box\" and \"boxStatic\" elements at 2.25s are close enough to each other"
     13        RenderBR {BR} at (715,50) size 0x0
    1314layer at (100,100) size 100x100
    1415  RenderImage {IMG} at (100,100) size 100x100 [bgcolor=#FF0000]
  • trunk/Source/WebCore/ChangeLog

    r154905 r154906  
     12013-08-30  Dirk Schulze  <krit@webkit.org>
     2
     3        Animate CSS Image filter() function
     4        https://bugs.webkit.org/show_bug.cgi?id=119938
     5
     6        Reviewed by Simon Fraser.
     7
     8        With this patch, the new introduced CSS Image function filter() can be
     9        animated. According to the spec, just filter functions can be
     10        interpolated.
     11
     12        The patch also prepares StyleImage blending for interpolation of other
     13        generated images like gradients or cross-fade().
     14
     15        http://dev.w3.org/fxtf/filters/#interpolating-filter-image
     16
     17        Test: fast/filter-image/filter-image-animation.html
     18
     19        * css/CSSComputedStyleDeclaration.cpp: Reuse the code that creates a
     20            CSSValueList from ComputeStyle logic.
     21        (WebCore::valueForPixel):
     22            For StyleRules we want to have not-adjusted length values.
     23        (WebCore::ComputedStyleExtractor::valueForShadow):
     24            Add argument to switch between adjusted and not-adjusted length.
     25        (WebCore::ComputedStyleExtractor::valueForFilter):
     26            Ditto.
     27        (WebCore::ComputedStyleExtractor::propertyValue):
     28        * css/CSSComputedStyleDeclaration.h:
     29        * css/CSSFilterImageValue.h: Add helper functions
     30            for animating filters. We need to pass the FilterOperations for
     31            the image generation and the CSSValueList for StyleRule.
     32        (WebCore::CSSFilterImageValue::filterOperations):
     33        (WebCore::CSSFilterImageValue::setFilterOperations):
     34        (WebCore::CSSFilterImageValue::cachedImage):
     35        * page/animation/CSSPropertyAnimation.cpp:
     36            Add animation code to support animations between two filter()
     37            function values.
     38        (WebCore::blendFilterOperations):
     39        (WebCore::blendFunc):
     40        (WebCore::filterBlend):
     41        * rendering/style/StyleGeneratedImage.h: Add helper functions.
     42        (WebCore::CSSFilterImageValue::imageValue):
     43
     44
    1452013-08-30  Leo Yang  <leoyang@blackberry.com>
    246
  • trunk/Source/WebCore/css/CSSComputedStyleDeclaration.cpp

    r154877 r154906  
    901901#endif // ENABLE(CSS_SHADERS)
    902902
     903static inline PassRefPtr<CSSPrimitiveValue> adjustLengthForZoom(double length, const RenderStyle* style, AdjustPixelValuesForComputedStyle adjust)
     904{
     905    return adjust == AdjustPixelValues ? zoomAdjustedPixelValue(length, style) : cssValuePool().createValue(length, CSSPrimitiveValue::CSS_PX);
     906}
     907
     908static inline PassRefPtr<CSSPrimitiveValue> adjustLengthForZoom(const Length& length, const RenderStyle* style, AdjustPixelValuesForComputedStyle adjust)
     909{
     910    return adjust == AdjustPixelValues ? zoomAdjustedPixelValue(length.value(), style) : cssValuePool().createValue(length);
     911}
     912
     913PassRefPtr<CSSValue> ComputedStyleExtractor::valueForShadow(const ShadowData* shadow, CSSPropertyID propertyID, const RenderStyle* style, AdjustPixelValuesForComputedStyle adjust)
     914{
     915    if (!shadow)
     916        return cssValuePool().createIdentifierValue(CSSValueNone);
     917
     918    RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
     919    for (const ShadowData* currShadowData = shadow; currShadowData; currShadowData = currShadowData->next()) {
     920        RefPtr<CSSPrimitiveValue> x = adjustLengthForZoom(currShadowData->x(), style, adjust);
     921        RefPtr<CSSPrimitiveValue> y = adjustLengthForZoom(currShadowData->y(), style, adjust);
     922        RefPtr<CSSPrimitiveValue> blur = adjustLengthForZoom(currShadowData->radius(), style, adjust);
     923        RefPtr<CSSPrimitiveValue> spread = propertyID == CSSPropertyTextShadow ? PassRefPtr<CSSPrimitiveValue>() : adjustLengthForZoom(currShadowData->spread(), style, adjust);
     924        RefPtr<CSSPrimitiveValue> style = propertyID == CSSPropertyTextShadow || currShadowData->style() == Normal ? PassRefPtr<CSSPrimitiveValue>() : cssValuePool().createIdentifierValue(CSSValueInset);
     925        RefPtr<CSSPrimitiveValue> color = cssValuePool().createColorValue(currShadowData->color().rgb());
     926        list->prepend(ShadowValue::create(x.release(), y.release(), blur.release(), spread.release(), style.release(), color.release()));
     927    }
     928    return list.release();
     929}
     930
    903931#if ENABLE(CSS_FILTERS)
    904 PassRefPtr<CSSValue> ComputedStyleExtractor::valueForFilter(const RenderObject* renderer, const RenderStyle* style) const
     932PassRefPtr<CSSValue> ComputedStyleExtractor::valueForFilter(const RenderObject* renderer, const RenderStyle* style, const FilterOperations& filterOperations, AdjustPixelValuesForComputedStyle adjust)
    905933{
    906934#if !ENABLE(CSS_SHADERS)
    907935    UNUSED_PARAM(renderer);
    908936#endif
    909     if (style->filter().operations().isEmpty())
     937    if (filterOperations.operations().isEmpty())
    910938        return cssValuePool().createIdentifierValue(CSSValueNone);
    911939
     
    914942    RefPtr<WebKitCSSFilterValue> filterValue;
    915943
    916     Vector<RefPtr<FilterOperation> >::const_iterator end = style->filter().operations().end();
    917     for (Vector<RefPtr<FilterOperation> >::const_iterator it = style->filter().operations().begin(); it != end; ++it) {
     944    Vector<RefPtr<FilterOperation> >::const_iterator end = filterOperations.operations().end();
     945    for (Vector<RefPtr<FilterOperation> >::const_iterator it = filterOperations.operations().begin(); it != end; ++it) {
    918946        FilterOperation* filterOperation = (*it).get();
    919947        switch (filterOperation->getOperationType()) {
     
    9751003            BlurFilterOperation* blurOperation = static_cast<BlurFilterOperation*>(filterOperation);
    9761004            filterValue = WebKitCSSFilterValue::create(WebKitCSSFilterValue::BlurFilterOperation);
    977             filterValue->append(zoomAdjustedPixelValue(blurOperation->stdDeviation().value(), style));
     1005            filterValue->append(adjustLengthForZoom(blurOperation->stdDeviation(), style, adjust));
    9781006            break;
    9791007        }
     
    9831011            // We want our computed style to look like that of a text shadow (has neither spread nor inset style).
    9841012            ShadowData shadowData = ShadowData(dropShadowOperation->location(), dropShadowOperation->stdDeviation(), 0, Normal, false, dropShadowOperation->color());
    985             filterValue->append(valueForShadow(&shadowData, CSSPropertyTextShadow, style));
     1013            filterValue->append(valueForShadow(&shadowData, CSSPropertyTextShadow, style, adjust));
    9861014            break;
    9871015        }
     
    13291357}
    13301358
    1331 PassRefPtr<CSSValue> ComputedStyleExtractor::valueForShadow(const ShadowData* shadow, CSSPropertyID propertyID, const RenderStyle* style) const
    1332 {
    1333     if (!shadow)
    1334         return cssValuePool().createIdentifierValue(CSSValueNone);
    1335 
    1336     RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
    1337     for (const ShadowData* s = shadow; s; s = s->next()) {
    1338         RefPtr<CSSPrimitiveValue> x = zoomAdjustedPixelValue(s->x(), style);
    1339         RefPtr<CSSPrimitiveValue> y = zoomAdjustedPixelValue(s->y(), style);
    1340         RefPtr<CSSPrimitiveValue> blur = zoomAdjustedPixelValue(s->radius(), style);
    1341         RefPtr<CSSPrimitiveValue> spread = propertyID == CSSPropertyTextShadow ? PassRefPtr<CSSPrimitiveValue>() : zoomAdjustedPixelValue(s->spread(), style);
    1342         RefPtr<CSSPrimitiveValue> style = propertyID == CSSPropertyTextShadow || s->style() == Normal ? PassRefPtr<CSSPrimitiveValue>() : cssValuePool().createIdentifierValue(CSSValueInset);
    1343         RefPtr<CSSPrimitiveValue> color = cssValuePool().createColorValue(s->color().rgb());
    1344         list->prepend(ShadowValue::create(x.release(), y.release(), blur.release(), spread.release(), style.release(), color.release()));
    1345     }
    1346     return list.release();
    1347 }
    13481359
    13491360static CSSValueID identifierForFamily(const AtomicString& family)
     
    28332844#if ENABLE(CSS_FILTERS)
    28342845        case CSSPropertyWebkitFilter:
    2835             return valueForFilter(renderer, style.get());
     2846            return valueForFilter(renderer, style.get(), style->filter());
    28362847#endif
    28372848#if ENABLE(CSS_COMPOSITING)
  • trunk/Source/WebCore/css/CSSComputedStyleDeclaration.h

    r150960 r154906  
    3232class CSSValueList;
    3333class Color;
     34class FilterOperations;
    3435class MutableStylePropertySet;
    3536class Node;
     
    4849enum EUpdateLayout { DoNotUpdateLayout = false, UpdateLayout = true };
    4950
     51enum AdjustPixelValuesForComputedStyle { AdjustPixelValues, DoNotAdjustPixelValues };
     52
    5053class ComputedStyleExtractor {
    5154public:
     
    6164    bool propertyMatches(CSSPropertyID, const CSSValue*) const;
    6265
     66#if ENABLE(CSS_FILTERS)
     67    static PassRefPtr<CSSValue> valueForFilter(const RenderObject*, const RenderStyle*, const FilterOperations&, AdjustPixelValuesForComputedStyle = AdjustPixelValues);
     68#endif
     69
    6370private:
    6471    // The styled node is either the node passed into computedPropertyValue, or the
     
    7380#endif
    7481
    75     PassRefPtr<CSSValue> valueForShadow(const ShadowData*, CSSPropertyID, const RenderStyle*) const;
     82    static PassRefPtr<CSSValue> valueForShadow(const ShadowData*, CSSPropertyID, const RenderStyle*, AdjustPixelValuesForComputedStyle = AdjustPixelValues);
    7683    PassRefPtr<CSSPrimitiveValue> currentColorOrValidColor(RenderStyle*, const Color&) const;
    77 
    78 #if ENABLE(CSS_FILTERS)
    79     PassRefPtr<CSSValue> valueForFilter(const RenderObject*, const RenderStyle*) const;
    80 #endif
    8184
    8285    PassRefPtr<CSSValueList> getCSSPropertyValuesForShorthandProperties(const StylePropertyShorthand&) const;
  • trunk/Source/WebCore/css/CSSFilterImageValue.cpp

    r154580 r154906  
    163163bool CSSFilterImageValue::equals(const CSSFilterImageValue& other) const
    164164{
    165     return compareCSSValuePtr(m_imageValue, other.m_imageValue)
    166         && compareCSSValuePtr(m_filterValue, other.m_filterValue);
     165    return equalInputImages(other) && compareCSSValuePtr(m_filterValue, other.m_filterValue);
     166}
     167
     168bool CSSFilterImageValue::equalInputImages(const CSSFilterImageValue& other) const
     169{
     170    return compareCSSValuePtr(m_imageValue, other.m_imageValue);
    167171}
    168172
  • trunk/Source/WebCore/css/CSSFilterImageValue.h

    r154133 r154906  
    7171    bool equals(const CSSFilterImageValue&) const;
    7272
     73    bool equalInputImages(const CSSFilterImageValue&) const;
     74
    7375    void createFilterOperations(StyleResolver*);
     76
     77    const FilterOperations& filterOperations() const { return m_filterOperations; }
     78    void setFilterOperations(const FilterOperations& filterOperations)
     79    {
     80        m_filterOperations = filterOperations;
     81    }
     82    CachedImage* cachedImage() const { return m_cachedImage.get(); }
    7483
    7584private:
     
    111120};
    112121
     122inline CSSFilterImageValue* toCSSFilterImageValue(CSSImageGeneratorValue* value)
     123{
     124    ASSERT_WITH_SECURITY_IMPLICATION(!value || value->isFilterImageValue());
     125    return static_cast<CSSFilterImageValue*>(value);
     126}
     127
    113128} // namespace WebCore
    114129
  • trunk/Source/WebCore/page/animation/CSSPropertyAnimation.cpp

    r153764 r154906  
    3232
    3333#include "AnimationBase.h"
     34#include "CSSComputedStyleDeclaration.h"
    3435#include "CSSCrossfadeValue.h"
     36#include "CSSFilterImageValue.h"
    3537#include "CSSImageGeneratorValue.h"
    3638#include "CSSImageValue.h"
     
    173175}
    174176
     177static inline void blendFilterOperations(const AnimationBase* anim, FilterOperations& result, const FilterOperations& from, const FilterOperations& to, double progress)
     178{
     179    size_t fromSize = from.operations().size();
     180    size_t toSize = to.operations().size();
     181    size_t size = max(fromSize, toSize);
     182    for (size_t i = 0; i < size; i++) {
     183        RefPtr<FilterOperation> fromOp = (i < fromSize) ? from.operations()[i].get() : 0;
     184        RefPtr<FilterOperation> toOp = (i < toSize) ? to.operations()[i].get() : 0;
     185        RefPtr<FilterOperation> blendedOp = toOp ? blendFunc(anim, fromOp.get(), toOp.get(), progress) : (fromOp ? blendFunc(anim, 0, fromOp.get(), progress, true) : 0);
     186        if (blendedOp)
     187            result.operations().append(blendedOp);
     188        else {
     189            RefPtr<FilterOperation> identityOp = PassthroughFilterOperation::create();
     190            if (progress > 0.5)
     191                result.operations().append(toOp ? toOp : identityOp);
     192            else
     193                result.operations().append(fromOp ? fromOp : identityOp);
     194        }
     195    }
     196}
     197
    175198static inline FilterOperations blendFunc(const AnimationBase* anim, const FilterOperations& from, const FilterOperations& to, double progress)
    176199{
     
    178201
    179202    // If we have a filter function list, use that to do a per-function animation.
    180     if (anim->filterFunctionListsMatch()) {
    181         size_t fromSize = from.operations().size();
    182         size_t toSize = to.operations().size();
    183         size_t size = max(fromSize, toSize);
    184         for (size_t i = 0; i < size; i++) {
    185             RefPtr<FilterOperation> fromOp = (i < fromSize) ? from.operations()[i].get() : 0;
    186             RefPtr<FilterOperation> toOp = (i < toSize) ? to.operations()[i].get() : 0;
    187             RefPtr<FilterOperation> blendedOp = toOp ? blendFunc(anim, fromOp.get(), toOp.get(), progress) : (fromOp ? blendFunc(anim, 0, fromOp.get(), progress, true) : 0);
    188             if (blendedOp)
    189                 result.operations().append(blendedOp);
    190             else {
    191                 RefPtr<FilterOperation> identityOp = PassthroughFilterOperation::create();
    192                 if (progress > 0.5)
    193                     result.operations().append(toOp ? toOp : identityOp);
    194                 else
    195                     result.operations().append(fromOp ? fromOp : identityOp);
    196             }
    197         }
    198     } else {
     203    if (anim->filterFunctionListsMatch())
     204        blendFilterOperations(anim, result, from, to, progress);
     205    else {
    199206        // If the filter function lists don't match, we could try to cross-fade, but don't yet have a way to represent that in CSS.
    200207        // For now we'll just fail to animate.
     
    203210
    204211    return result;
     212}
     213
     214static inline PassRefPtr<StyleImage> filterBlend(const AnimationBase* anim, StyleImage* from, StyleImage* to, double progress)
     215{
     216    CSSFilterImageValue* fromValue = static_cast<CSSFilterImageValue*>(from->data());
     217    CSSFilterImageValue* toValue = static_cast<CSSFilterImageValue*>(to->data());
     218
     219    FilterOperations filterOperationsResult;
     220    blendFilterOperations(anim, filterOperationsResult, fromValue->filterOperations(), toValue->filterOperations(), progress);
     221    if (!toValue->cachedImage())
     222        return to;
     223
     224    RefPtr<StyleCachedImage> styledImage = StyleCachedImage::create(toValue->cachedImage());
     225
     226    RefPtr<CSSImageValue> imageValue = CSSImageValue::create(toValue->cachedImage()->url(), styledImage.get());
     227    RefPtr<CSSValue> filterValue = ComputedStyleExtractor::valueForFilter(anim->renderer(), anim->renderer()->style(),
     228        filterOperationsResult, DoNotAdjustPixelValues);
     229    RefPtr<CSSFilterImageValue> result = CSSFilterImageValue::create(imageValue, filterValue);
     230    result->setFilterOperations(filterOperationsResult);
     231
     232    return StyleGeneratedImage::create(result.get());
    205233}
    206234#endif // ENABLE(CSS_FILTERS)
     
    280308        return to;
    281309
     310    // Animation between two generated images. Cross fade for all other cases.
     311    if (from->isGeneratedImage() && to->isGeneratedImage()) {
     312        CSSImageGeneratorValue* fromGenerated = toStyleGeneratedImage(from)->imageValue();
     313        CSSImageGeneratorValue* toGenerated = toStyleGeneratedImage(to)->imageValue();
     314
     315#if ENABLE(CSS_FILTERS)
     316        if (fromGenerated->isFilterImageValue() && toGenerated->isFilterImageValue()) {
     317            // Animation of generated images just possible if input images are equal.
     318            // Otherwise fall back to cross fade animation.
     319            CSSFilterImageValue* fromFitler = toCSSFilterImageValue(fromGenerated);
     320            CSSFilterImageValue* toFitler = toCSSFilterImageValue(toGenerated);
     321            if (fromFitler->equalInputImages(*toFitler))
     322                return filterBlend(anim, from, to, progress);
     323        }
     324#else
     325        UNUSED_PARAM(fromGenerated);
     326        UNUSED_PARAM(toGenerated);
     327#endif
     328        // FIXME: Add support for animation between two cross-fade() functions.
     329        // https://bugs.webkit.org/show_bug.cgi?id=119955
     330
     331        // FIXME: Add support for animation between two *gradient() functions.
     332        // https://bugs.webkit.org/show_bug.cgi?id=119956
     333}
     334
     335    // FIXME: Add support cross fade between cached and generated images.
     336    // https://bugs.webkit.org/show_bug.cgi?id=78293
    282337    if (from->isCachedImage() && to->isCachedImage())
    283338        return crossfadeBlend(anim, static_cast<StyleCachedImage*>(from), static_cast<StyleCachedImage*>(to), progress);
    284 
    285     // FIXME: Support transitioning generated images as well. (gradients, etc.)
    286339
    287340    return to;
  • trunk/Source/WebCore/rendering/style/StyleGeneratedImage.h

    r141637 r154906  
    4040
    4141    virtual WrappedImagePtr data() const { return m_imageGeneratorValue.get(); }
     42    CSSImageGeneratorValue* imageValue() const { return m_imageGeneratorValue.get(); }
    4243
    4344    virtual PassRefPtr<CSSValue> cssValue() const;
     
    6263};
    6364
     65inline StyleGeneratedImage* toStyleGeneratedImage(StyleImage* image)
     66{
     67    ASSERT_WITH_SECURITY_IMPLICATION(!image || image->isGeneratedImage());
     68    return static_cast<StyleGeneratedImage*>(image);
     69}
     70
    6471}
    6572#endif
Note: See TracChangeset for help on using the changeset viewer.