2009-01-19 Simon Fraser <simon.fraser@apple.com>
authorsimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 19 Jan 2009 22:23:34 +0000 (22:23 +0000)
committersimon.fraser@apple.com <simon.fraser@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 19 Jan 2009 22:23:34 +0000 (22:23 +0000)
        Reviewed by Dave Hyatt

        https://bugs.webkit.org/show_bug.cgi?id=18078

        Support animations and transitions of shorthand properties by creating
        PropertyWrappers that simply wrap a vector of atomci wrappers, and implement
        equal() and blend(). Build that collection of shorthand wrappers using the
        shorthand map that CSSMutableStyleDeclaration already has. Skip comparing these
        shorthand wrappers during 'all' transitions.

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

18 files changed:
LayoutTests/ChangeLog
LayoutTests/transitions/transform-op-list-match.html
LayoutTests/transitions/transform-op-list-no-match.html
LayoutTests/transitions/transition-test-helpers.js
LayoutTests/transitions/zero-duration-in-list.html
WebCore/ChangeLog
WebCore/GNUmakefile.am
WebCore/WebCore.pro
WebCore/WebCore.scons
WebCore/WebCore.vcproj/WebCore.vcproj
WebCore/WebCore.xcodeproj/project.pbxproj
WebCore/WebCoreSources.bkl
WebCore/css/CSSMutableStyleDeclaration.cpp
WebCore/css/CSSPropertyLonghand.cpp [new file with mode: 0644]
WebCore/css/CSSPropertyLonghand.h [new file with mode: 0644]
WebCore/page/animation/AnimationBase.cpp
WebCore/page/animation/AnimationBase.h
WebCore/page/animation/CompositeAnimation.cpp

index db07882..66e304c 100644 (file)
@@ -1,3 +1,20 @@
+2009-01-19  Simon Fraser  <simon.fraser@apple.com>
+
+        Reviewed by Dave Hyatt
+
+        https://bugs.webkit.org/show_bug.cgi?id=18078
+        
+        Fix transition-test-helpers.js to handle more kinds
+        of CSS properties, like lists and colors, and to
+        optionally not use the pause API.
+
+        * transitions/transform-op-list-match.html:
+        * transitions/transform-op-list-no-match.html:
+        * transitions/transition-test-helpers.js:
+        (runTransitionTest.checkExpectedValue):
+        (runTransitionTest.runTest):
+        * transitions/zero-duration-in-list.html:
+
 2009-01-19  Alexey Proskuryakov  <ap@webkit.org>
 
         Update test results for https://bugs.webkit.org/show_bug.cgi?id=23417.
index 3d385a2..ce96a8e 100644 (file)
@@ -36,7 +36,7 @@
       box.style.webkitTransform = 'translateX(0px) rotate(540deg)';
     }
     
-    runTransitionTest(expectedValues, setupTest);
+    runTransitionTest(expectedValues, setupTest, true);
     
   </script>
 </head>
index bb1bbc1..14165d0 100644 (file)
@@ -36,7 +36,7 @@
       box.style.webkitTransform = 'rotate(540deg)';
     }
     
-    runTransitionTest(expectedValues, setupTest);
+    runTransitionTest(expectedValues, setupTest, true);
     
   </script>
 </head>
index a4ecc29..5caa1b5 100644 (file)
@@ -26,7 +26,7 @@ function roundNumber(num, decimalPlaces)
   return Math.round(num * Math.pow(10, decimalPlaces)) / Math.pow(10, decimalPlaces);
 }
 
-function runTransitionTest(expected, callback)
+function runTransitionTest(expected, callback, usePauseAPI)
 {
     var result = "";
     var hasPauseTransitionAPI = ('layoutTestController' in window) && ('pauseTransitionAtTimeOnElementWithId' in layoutTestController);
@@ -46,10 +46,10 @@ function runTransitionTest(expected, callback)
         var tolerance = expected[index][4];
 
         var computedValue;
-        var pass;
-        if (!property.indexOf("-webkit-transform")) {
+        var pass = false;
+        var transformRegExp = /^-webkit-transform(\.\d+)?$/;
+        if (transformRegExp.test(property)) {
             computedValue = window.getComputedStyle(document.getElementById(elementId)).webkitTransform;
-
             if (typeof expectedValue == "string")
                 pass = (computedValue == expectedValue);
             else if (typeof expectedValue == "number") {
@@ -68,10 +68,42 @@ function runTransitionTest(expected, callback)
         } else if (property == "lineHeight") {
             computedValue = parseInt(window.getComputedStyle(document.getElementById(elementId)).lineHeight);
             pass = isCloseEnough(computedValue, expectedValue, tolerance);
-        } else {    
+        } else {
             var computedStyle = window.getComputedStyle(document.getElementById(elementId)).getPropertyCSSValue(property);
-            computedValue = computedStyle.getFloatValue(CSSPrimitiveValue.CSS_NUMBER);
-            pass = isCloseEnough(computedValue, expectedValue, tolerance);
+            if (computedStyle.cssValueType == CSSValue.CSS_VALUE_LIST) {
+                // For now, assume that value lists are simple lists of number values (e.g. transform-origin)
+                var values = [];
+                for (var i = 0; i < computedStyle.length; ++i) {
+                    values.push(computedStyle[i].getFloatValue(CSSPrimitiveValue.CSS_NUMBER));
+                }
+                computedValue = values.join(',');
+                pass = true;
+                for (var i = 0; i < values.length; ++i)
+                    pass &= isCloseEnough(values[i], expectedValue[i], tolerance);
+            } else if (computedStyle.cssValueType == CSSValue.CSS_PRIMITIVE_VALUE) {
+                switch (computedStyle.primitiveType) {
+                    case CSSPrimitiveValue.CSS_STRING:
+                        computedValue = computedStyle.getStringValue();
+                        pass = computedValue == expectedValue;
+                        break;
+                    case CSSPrimitiveValue.CSS_RGBCOLOR:
+                        var rgbColor = computedStyle.getRGBColorValue();
+                        computedValue = [rgbColor.red.getFloatValue(CSSPrimitiveValue.CSS_NUMBER),
+                                         rgbColor.green.getFloatValue(CSSPrimitiveValue.CSS_NUMBER),
+                                         rgbColor.blue.getFloatValue(CSSPrimitiveValue.CSS_NUMBER)]; // alpha is not exposed to JS
+                        pass = true;
+                        for (var i = 0; i < 3; ++i)
+                            pass &= isCloseEnough(computedValue[i], expectedValue[i], tolerance);
+                        break;
+                    case CSSPrimitiveValue.CSS_RECT:
+                        computedValue = computedStyle.getRectValue();
+                        pass = computedValue == expectedValue;
+                        break;
+                    default:
+                        computedValue = computedStyle.getFloatValue(CSSPrimitiveValue.CSS_NUMBER);
+                        pass = isCloseEnough(computedValue, expectedValue, tolerance);
+                }
+            }
         }
 
         if (pass)
@@ -105,7 +137,7 @@ function runTransitionTest(expected, callback)
             property = "-webkit-transform";
 
             // We can only use the transition fast-forward mechanism if DRT implements pauseTransitionAtTimeOnElementWithId()
-            if (hasPauseTransitionAPI) {
+            if (hasPauseTransitionAPI && usePauseAPI) {
                 layoutTestController.pauseTransitionAtTimeOnElementWithId(property, time, elementId);
                 checkExpectedValue(expected, i);
             }
index b90e61a..fbe2f5c 100644 (file)
@@ -32,7 +32,7 @@
       box.style.left = '100px';
     }
     
-    runTransitionTest(expectedValues, setupTest);
+    runTransitionTest(expectedValues, setupTest, true);
     
   </script>
 </head>
index db99c95..4591e53 100644 (file)
@@ -1,3 +1,61 @@
+2009-01-19  Simon Fraser  <simon.fraser@apple.com>
+
+        Reviewed by Dave Hyatt
+
+        https://bugs.webkit.org/show_bug.cgi?id=18078
+
+        Support animations and transitions of shorthand properties by creating
+        PropertyWrappers that simply wrap a vector of atomci wrappers, and implement
+        equal() and blend(). Build that collection of shorthand wrappers using the
+        shorthand map that CSSMutableStyleDeclaration already has. Skip comparing these
+        shorthand wrappers during 'all' transitions.
+
+        * GNUmakefile.am:
+        * WebCore.pro:
+        * WebCore.scons:
+        * WebCore.vcproj/WebCore.vcproj:
+        * WebCore.xcodeproj/project.pbxproj:
+        * WebCoreSources.bkl:
+        Add CSSPropertyLonghand.h/cpp.
+        
+        * css/CSSMutableStyleDeclaration.cpp:
+        (WebCore::CSSMutableStyleDeclaration::removeShorthandProperty):
+        Move CSSPropertyLonghand to its own file.
+        
+        * css/CSSPropertyLonghand.cpp: Added.
+        (WebCore::initShorthandMap):
+        (WebCore::longhandForProperty):
+        * css/CSSPropertyLonghand.h: Added.
+        (WebCore::CSSPropertyLonghand::CSSPropertyLonghand):
+        (WebCore::CSSPropertyLonghand::properties):
+        (WebCore::CSSPropertyLonghand::length):
+        Code moved from CSSMutableStyleDeclaration.h/cpp
+
+        * page/animation/AnimationBase.cpp:
+        (WebCore::PropertyWrapperBase::isShorthandWrapper):
+        (WebCore::ShorthandPropertyWrapper::ShorthandPropertyWrapper):
+        (WebCore::ShorthandPropertyWrapper::isShorthandWrapper):
+        (WebCore::ShorthandPropertyWrapper::equals):
+        (WebCore::ShorthandPropertyWrapper::blend):
+        Add a wrapper class for shorthand properties that simply wraps an
+        array of atomic property wrappers.
+
+        (WebCore::ensurePropertyMap):
+        (WebCore::addPropertyWrapper):
+        (WebCore::addShorthandProperties):
+        (WebCore::wrapperForProperty):
+        (WebCore::AnimationBase::propertiesEqual):
+        (WebCore::AnimationBase::getPropertyAtIndex):
+        Some minor refactoring to re-use wrapperForProperty(), and ensure that gPropertyWrapperMap
+        is filled with an invalid index (-1), not 0.
+
+        (WebCore::AnimationBase::blendProperties):
+        * page/animation/AnimationBase.h:
+        * page/animation/CompositeAnimation.cpp:
+        (WebCore::CompositeAnimationPrivate::updateTransitions):
+        When doing 'all' transitions, skip shorthand wrappers, since 'all' transitions
+        just need to compare all the atomic property wrappers.
+
 2009-01-19  Oliver Hunt  <oliver@apple.com>
 
         Reviewed by NOBODY (Build fix).
index 5bad24a..c831a8d 100644 (file)
@@ -452,6 +452,8 @@ webcore_sources += \
        WebCore/css/CSSPrimitiveValueMappings.h \
        WebCore/css/CSSProperty.cpp \
        WebCore/css/CSSProperty.h \
+       WebCore/css/CSSPropertyLonghand.cpp \
+       WebCore/css/CSSPropertyLonghand.h \
        WebCore/css/CSSQuirkPrimitiveValue.h \
        WebCore/css/CSSReflectValue.cpp \
        WebCore/css/CSSReflectValue.h \
index 5fc782c..d2b2859 100644 (file)
@@ -518,6 +518,7 @@ SOURCES += \
     css/CSSParserValues.cpp \
     css/CSSPrimitiveValue.cpp \
     css/CSSProperty.cpp \
+    css/CSSPropertyLonghand.cpp \
     css/CSSReflectValue.cpp \
     css/CSSRule.cpp \
     css/CSSRuleList.cpp \
index 1aa4286..d24fa5d 100644 (file)
@@ -26,6 +26,7 @@ sources['css'] = [
     'css/CSSParser.cpp',
     'css/CSSParserValues.cpp',
     'css/CSSPrimitiveValue.cpp',
+    'css/CSSPropertyLonghand.cpp',
     'css/CSSProperty.cpp',
     'css/CSSReflectValue.cpp',
     'css/CSSRule.cpp',
index 8f2e85e..43a70db 100644 (file)
                                >\r
                        </File>\r
                        <File\r
+                               RelativePath="..\css\CSSPropertyLonghand.cpp"\r
+                               >\r
+                               <FileConfiguration\r
+                                       Name="Release_PGO|Win32"\r
+                                       >\r
+                                       <Tool\r
+                                               Name="VCCLCompilerTool"\r
+                                               WholeProgramOptimization="true"\r
+                                       />\r
+                               </FileConfiguration>\r
+                       </File>\r
+                       <File\r
+                               RelativePath="..\css\CSSPropertyLonghand.h"\r
+                               >\r
+                       </File>\r
+                       <File\r
                                RelativePath="..\css\CSSPropertyNames.in"\r
                                >\r
                        </File>\r
index 7a31c7c..4cf9ef5 100644 (file)
                0BA5D3860F240FB4009B870B /* GenericWorkerTask.h in Headers */ = {isa = PBXBuildFile; fileRef = 0BA5D3850F240FB4009B870B /* GenericWorkerTask.h */; };
                0F56028F0E4B76580065B038 /* RenderMarquee.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F56028D0E4B76580065B038 /* RenderMarquee.h */; };
                0F5602900E4B76580065B038 /* RenderMarquee.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F56028E0E4B76580065B038 /* RenderMarquee.cpp */; };
+               0F6ECD450F252F3700BDE271 /* CSSPropertyLonghand.h in Headers */ = {isa = PBXBuildFile; fileRef = 0F6ECD430F252F3700BDE271 /* CSSPropertyLonghand.h */; };
+               0F6ECD460F252F3700BDE271 /* CSSPropertyLonghand.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0F6ECD440F252F3700BDE271 /* CSSPropertyLonghand.cpp */; };
                0FC705210EB1815600B90AD8 /* AtomicStringHash.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FC705200EB1815600B90AD8 /* AtomicStringHash.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0FD723820EC8BD9300CA5DD7 /* FloatQuad.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FD723800EC8BD9300CA5DD7 /* FloatQuad.h */; settings = {ATTRIBUTES = (Private, ); }; };
                0FD723830EC8BD9300CA5DD7 /* FloatQuad.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 0FD723810EC8BD9300CA5DD7 /* FloatQuad.cpp */; };
                0BA5D3850F240FB4009B870B /* GenericWorkerTask.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GenericWorkerTask.h; sourceTree = "<group>"; };
                0F56028D0E4B76580065B038 /* RenderMarquee.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RenderMarquee.h; sourceTree = "<group>"; };
                0F56028E0E4B76580065B038 /* RenderMarquee.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = RenderMarquee.cpp; sourceTree = "<group>"; };
+               0F6ECD430F252F3700BDE271 /* CSSPropertyLonghand.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSPropertyLonghand.h; sourceTree = "<group>"; };
+               0F6ECD440F252F3700BDE271 /* CSSPropertyLonghand.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = CSSPropertyLonghand.cpp; sourceTree = "<group>"; };
                0FC705200EB1815600B90AD8 /* AtomicStringHash.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AtomicStringHash.h; sourceTree = "<group>"; };
                0FD723800EC8BD9300CA5DD7 /* FloatQuad.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FloatQuad.h; sourceTree = "<group>"; };
                0FD723810EC8BD9300CA5DD7 /* FloatQuad.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = FloatQuad.cpp; sourceTree = "<group>"; };
                                E1ED8AC20CC49BE000BFC557 /* CSSPrimitiveValueMappings.h */,
                                A80E6CCD0A1989CA007FB8C5 /* CSSProperty.cpp */,
                                A80E6CD50A1989CA007FB8C5 /* CSSProperty.h */,
+                               0F6ECD440F252F3700BDE271 /* CSSPropertyLonghand.cpp */,
+                               0F6ECD430F252F3700BDE271 /* CSSPropertyLonghand.h */,
                                BCEA4789097CAAC80094C9E4 /* CSSPropertyNames.in */,
                                A80E6CC00A1989CA007FB8C5 /* CSSQuirkPrimitiveValue.h */,
                                BC5A12DD0DC0414800C9AFAD /* CSSReflectValue.cpp */,
                                1A569D230D7E2B82007C3983 /* runtime_object.h in Headers */,
                                1A569D250D7E2B82007C3983 /* runtime_root.h in Headers */,
                                93309E1E099E64920056E581 /* visible_units.h in Headers */,
+                               E10BB3780F14B62200560E13 /* DOMStringList.h in Headers */,
+                               E10BB3860F14B95000560E13 /* JSDOMStringList.h in Headers */,
+                               E181B3510F15008A00FB7847 /* StaticStringList.h in Headers */,
+                               498391400F1E767500C23782 /* JSWebKitCSSMatrix.h in Headers */,
+                               498391500F1E76B400C23782 /* DOMWebKitCSSMatrix.h in Headers */,
+                               498391520F1E76B400C23782 /* DOMWebKitCSSMatrixInternal.h in Headers */,
+                               498391590F1E776900C23782 /* WebKitCSSMatrix.h in Headers */,
+                               498391640F1E8EE100C23782 /* JSWebKitCSSMatrixConstructor.h in Headers */,
+                               0F6ECD450F252F3700BDE271 /* CSSPropertyLonghand.h in Headers */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
                                1A569D220D7E2B82007C3983 /* runtime_object.cpp in Sources */,
                                1A569D240D7E2B82007C3983 /* runtime_root.cpp in Sources */,
                                93309E1D099E64920056E581 /* visible_units.cpp in Sources */,
+                               E10BB37B0F14B64100560E13 /* DOMStringList.cpp in Sources */,
+                               E10BB3870F14B95000560E13 /* JSDOMStringList.cpp in Sources */,
+                               E181B2570F14C1A600FB7847 /* JSDOMStringListCustom.cpp in Sources */,
+                               E181B3560F1500D700FB7847 /* StaticStringList.cpp in Sources */,
+                               4983913F0F1E767500C23782 /* JSWebKitCSSMatrix.cpp in Sources */,
+                               498391510F1E76B400C23782 /* DOMWebKitCSSMatrix.mm in Sources */,
+                               498391580F1E776900C23782 /* WebKitCSSMatrix.cpp in Sources */,
+                               498391630F1E8EE100C23782 /* JSWebKitCSSMatrixConstructor.cpp in Sources */,
+                               0F6ECD460F252F3700BDE271 /* CSSPropertyLonghand.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
                };
index 3fb165c..b52449b 100644 (file)
@@ -166,6 +166,7 @@ This file contains the list of files needed to build WebCore.
         css/CSSParserValues.cpp
         css/CSSPrimitiveValue.cpp
         css/CSSProperty.cpp
+        css/CSSPropertyLonghand.cpp
         css/CSSReflectValue.cpp
         css/CSSRule.cpp
         css/CSSRuleList.cpp
index 6b12ced..2e2064a 100644 (file)
@@ -24,6 +24,7 @@
 #include "CSSImageValue.h"
 #include "CSSParser.h"
 #include "CSSProperty.h"
+#include "CSSPropertyLonghand.h"
 #include "CSSPropertyNames.h"
 #include "CSSRule.h"
 #include "CSSStyleSheet.h"
@@ -31,7 +32,6 @@
 #include "Document.h"
 #include "ExceptionCode.h"
 #include "StyledElement.h"
-#include <wtf/StdLibExtras.h>
 
 using namespace std;
 
@@ -363,207 +363,9 @@ PassRefPtr<CSSValue> CSSMutableStyleDeclaration::getPropertyCSSValue(int propert
     return property ? property->value() : 0;
 }
 
-struct PropertyLonghand {
-    PropertyLonghand()
-        : m_properties(0)
-        , m_length(0)
-    {
-    }
-
-    PropertyLonghand(const int* firstProperty, unsigned numProperties)
-        : m_properties(firstProperty)
-        , m_length(numProperties)
-    {
-    }
-
-    const int* properties() const { return m_properties; }
-    unsigned length() const { return m_length; }
-
-private:
-    const int* m_properties;
-    unsigned m_length;
-};
-    
-typedef HashMap<int, PropertyLonghand> ShorthandMap;
-
-static void initShorthandMap(ShorthandMap& shorthandMap)
-{
-    #define SET_SHORTHAND_MAP_ENTRY(map, propID, array) \
-        map.set(propID, PropertyLonghand(array, sizeof(array) / sizeof(array[0])))
-
-    // FIXME: The 'font' property has "shorthand nature" but is not parsed as a shorthand.
-
-    // Do not change the order of the following four shorthands, and keep them together.
-    static const int borderProperties[4][3] = {
-        { CSSPropertyBorderTopColor, CSSPropertyBorderTopStyle, CSSPropertyBorderTopWidth },
-        { CSSPropertyBorderRightColor, CSSPropertyBorderRightStyle, CSSPropertyBorderRightWidth },
-        { CSSPropertyBorderBottomColor, CSSPropertyBorderBottomStyle, CSSPropertyBorderBottomWidth },
-        { CSSPropertyBorderLeftColor, CSSPropertyBorderLeftStyle, CSSPropertyBorderLeftWidth }
-    };
-    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyBorderTop, borderProperties[0]);
-    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyBorderRight, borderProperties[1]);
-    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyBorderBottom, borderProperties[2]);
-    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyBorderLeft, borderProperties[3]);
-
-    shorthandMap.set(CSSPropertyBorder, PropertyLonghand(borderProperties[0], sizeof(borderProperties) / sizeof(borderProperties[0][0])));
-
-    static const int borderColorProperties[] = {
-        CSSPropertyBorderTopColor,
-        CSSPropertyBorderRightColor,
-        CSSPropertyBorderBottomColor,
-        CSSPropertyBorderLeftColor
-    };
-    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyBorderColor, borderColorProperties);
-
-    static const int borderStyleProperties[] = {
-        CSSPropertyBorderTopStyle,
-        CSSPropertyBorderRightStyle,
-        CSSPropertyBorderBottomStyle,
-        CSSPropertyBorderLeftStyle
-    };
-    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyBorderStyle, borderStyleProperties);
-
-    static const int borderWidthProperties[] = {
-        CSSPropertyBorderTopWidth,
-        CSSPropertyBorderRightWidth,
-        CSSPropertyBorderBottomWidth,
-        CSSPropertyBorderLeftWidth
-    };
-    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyBorderWidth, borderWidthProperties);
-
-    static const int backgroundPositionProperties[] = { CSSPropertyBackgroundPositionX, CSSPropertyBackgroundPositionY };
-    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyBackgroundPosition, backgroundPositionProperties);
-
-    static const int borderSpacingProperties[] = { CSSPropertyWebkitBorderHorizontalSpacing, CSSPropertyWebkitBorderVerticalSpacing };
-    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyBorderSpacing, borderSpacingProperties);
-
-    static const int listStyleProperties[] = {
-        CSSPropertyListStyleImage,
-        CSSPropertyListStylePosition,
-        CSSPropertyListStyleType
-    };
-    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyListStyle, listStyleProperties);
-
-    static const int marginProperties[] = {
-        CSSPropertyMarginTop,
-        CSSPropertyMarginRight,
-        CSSPropertyMarginBottom,
-        CSSPropertyMarginLeft
-    };
-    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyMargin, marginProperties);
-
-    static const int marginCollapseProperties[] = { CSSPropertyWebkitMarginTopCollapse, CSSPropertyWebkitMarginBottomCollapse };
-    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyWebkitMarginCollapse, marginCollapseProperties);
-
-    static const int marqueeProperties[] = {
-        CSSPropertyWebkitMarqueeDirection,
-        CSSPropertyWebkitMarqueeIncrement,
-        CSSPropertyWebkitMarqueeRepetition,
-        CSSPropertyWebkitMarqueeStyle,
-        CSSPropertyWebkitMarqueeSpeed
-    };
-    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyWebkitMarquee, marqueeProperties);
-
-    static const int outlineProperties[] = {
-        CSSPropertyOutlineColor,
-        CSSPropertyOutlineOffset,
-        CSSPropertyOutlineStyle,
-        CSSPropertyOutlineWidth
-    };
-    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyOutline, outlineProperties);
-
-    static const int paddingProperties[] = {
-        CSSPropertyPaddingTop,
-        CSSPropertyPaddingRight,
-        CSSPropertyPaddingBottom,
-        CSSPropertyPaddingLeft
-    };
-    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyPadding, paddingProperties);
-
-    static const int textStrokeProperties[] = { CSSPropertyWebkitTextStrokeColor, CSSPropertyWebkitTextStrokeWidth };
-    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyWebkitTextStroke, textStrokeProperties);
-
-    static const int backgroundProperties[] = {
-        CSSPropertyBackgroundAttachment,
-        CSSPropertyWebkitBackgroundClip,
-        CSSPropertyBackgroundColor,
-        CSSPropertyBackgroundImage,
-        CSSPropertyWebkitBackgroundOrigin,
-        CSSPropertyBackgroundPositionX,
-        CSSPropertyBackgroundPositionY,
-        CSSPropertyBackgroundRepeat,
-    };
-    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyBackground, backgroundProperties);
-
-    static const int columnsProperties[] = { CSSPropertyWebkitColumnWidth, CSSPropertyWebkitColumnCount };
-    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyWebkitColumns, columnsProperties);
-
-    static const int columnRuleProperties[] = {
-        CSSPropertyWebkitColumnRuleColor,
-        CSSPropertyWebkitColumnRuleStyle,
-        CSSPropertyWebkitColumnRuleWidth
-    };
-    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyWebkitColumnRule, columnRuleProperties);
-
-    static const int overflowProperties[] = { CSSPropertyOverflowX, CSSPropertyOverflowY };
-    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyOverflow, overflowProperties);
-
-    static const int borderRadiusProperties[] = {
-        CSSPropertyWebkitBorderTopRightRadius,
-        CSSPropertyWebkitBorderTopLeftRadius,
-        CSSPropertyWebkitBorderBottomLeftRadius,
-        CSSPropertyWebkitBorderBottomRightRadius
-    };
-    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyWebkitBorderRadius, borderRadiusProperties);
-
-    static const int maskPositionProperties[] = { CSSPropertyWebkitMaskPositionX, CSSPropertyWebkitMaskPositionY };
-    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyWebkitMaskPosition, maskPositionProperties);
-
-    static const int maskProperties[] = {
-        CSSPropertyWebkitMaskAttachment,
-        CSSPropertyWebkitMaskClip,
-        CSSPropertyWebkitMaskImage,
-        CSSPropertyWebkitMaskOrigin,
-        CSSPropertyWebkitMaskPositionX,
-        CSSPropertyWebkitMaskPositionY,
-        CSSPropertyWebkitMaskRepeat,
-    };
-    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyWebkitMask, maskProperties);
-
-    static const int animationProperties[] = {
-        CSSPropertyWebkitAnimationName,
-        CSSPropertyWebkitAnimationDuration,
-        CSSPropertyWebkitAnimationTimingFunction,
-        CSSPropertyWebkitAnimationDelay,
-        CSSPropertyWebkitAnimationIterationCount,
-        CSSPropertyWebkitAnimationDirection
-    };
-    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyWebkitAnimation, animationProperties);
-
-    static const int transitionProperties[] = {
-        CSSPropertyWebkitTransitionProperty,
-        CSSPropertyWebkitTransitionDuration,
-        CSSPropertyWebkitTransitionTimingFunction,
-        CSSPropertyWebkitTransitionDelay
-    };
-    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyWebkitTransition, transitionProperties);
-
-    static const int transformOriginProperties[] = {
-        CSSPropertyWebkitTransformOriginX,
-        CSSPropertyWebkitTransformOriginY
-    };
-    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyWebkitTransformOrigin, transformOriginProperties);
-    
-    #undef SET_SHORTHAND_MAP_ENTRY
-}
-
 bool CSSMutableStyleDeclaration::removeShorthandProperty(int propertyID, bool notifyChanged) 
 {
-    DEFINE_STATIC_LOCAL(ShorthandMap, shorthandMap, ());
-    if (shorthandMap.isEmpty())
-        initShorthandMap(shorthandMap);
-
-    PropertyLonghand longhand = shorthandMap.get(propertyID);
+    CSSPropertyLonghand longhand = longhandForProperty(propertyID);
     if (longhand.length()) {
         removePropertiesInSet(longhand.properties(), longhand.length(), notifyChanged);
         return true;
diff --git a/WebCore/css/CSSPropertyLonghand.cpp b/WebCore/css/CSSPropertyLonghand.cpp
new file mode 100644 (file)
index 0000000..310f90e
--- /dev/null
@@ -0,0 +1,213 @@
+/*
+ * (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2007, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "CSSPropertyLonghand.h"
+
+#include "CSSPropertyNames.h"
+#include <wtf/HashMap.h>
+#include <wtf/StdLibExtras.h>
+
+namespace WebCore {
+
+typedef HashMap<int, CSSPropertyLonghand> ShorthandMap;
+
+static void initShorthandMap(ShorthandMap& shorthandMap)
+{
+    #define SET_SHORTHAND_MAP_ENTRY(map, propID, array) \
+        map.set(propID, CSSPropertyLonghand(array, sizeof(array) / sizeof(array[0])))
+
+    // FIXME: The 'font' property has "shorthand nature" but is not parsed as a shorthand.
+
+    // Do not change the order of the following four shorthands, and keep them together.
+    static const int borderProperties[4][3] = {
+        { CSSPropertyBorderTopColor, CSSPropertyBorderTopStyle, CSSPropertyBorderTopWidth },
+        { CSSPropertyBorderRightColor, CSSPropertyBorderRightStyle, CSSPropertyBorderRightWidth },
+        { CSSPropertyBorderBottomColor, CSSPropertyBorderBottomStyle, CSSPropertyBorderBottomWidth },
+        { CSSPropertyBorderLeftColor, CSSPropertyBorderLeftStyle, CSSPropertyBorderLeftWidth }
+    };
+    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyBorderTop, borderProperties[0]);
+    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyBorderRight, borderProperties[1]);
+    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyBorderBottom, borderProperties[2]);
+    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyBorderLeft, borderProperties[3]);
+
+    shorthandMap.set(CSSPropertyBorder, CSSPropertyLonghand(borderProperties[0], sizeof(borderProperties) / sizeof(borderProperties[0][0])));
+
+    static const int borderColorProperties[] = {
+        CSSPropertyBorderTopColor,
+        CSSPropertyBorderRightColor,
+        CSSPropertyBorderBottomColor,
+        CSSPropertyBorderLeftColor
+    };
+    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyBorderColor, borderColorProperties);
+
+    static const int borderStyleProperties[] = {
+        CSSPropertyBorderTopStyle,
+        CSSPropertyBorderRightStyle,
+        CSSPropertyBorderBottomStyle,
+        CSSPropertyBorderLeftStyle
+    };
+    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyBorderStyle, borderStyleProperties);
+
+    static const int borderWidthProperties[] = {
+        CSSPropertyBorderTopWidth,
+        CSSPropertyBorderRightWidth,
+        CSSPropertyBorderBottomWidth,
+        CSSPropertyBorderLeftWidth
+    };
+    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyBorderWidth, borderWidthProperties);
+
+    static const int backgroundPositionProperties[] = { CSSPropertyBackgroundPositionX, CSSPropertyBackgroundPositionY };
+    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyBackgroundPosition, backgroundPositionProperties);
+
+    static const int borderSpacingProperties[] = { CSSPropertyWebkitBorderHorizontalSpacing, CSSPropertyWebkitBorderVerticalSpacing };
+    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyBorderSpacing, borderSpacingProperties);
+
+    static const int listStyleProperties[] = {
+        CSSPropertyListStyleImage,
+        CSSPropertyListStylePosition,
+        CSSPropertyListStyleType
+    };
+    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyListStyle, listStyleProperties);
+
+    static const int marginProperties[] = {
+        CSSPropertyMarginTop,
+        CSSPropertyMarginRight,
+        CSSPropertyMarginBottom,
+        CSSPropertyMarginLeft
+    };
+    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyMargin, marginProperties);
+
+    static const int marginCollapseProperties[] = { CSSPropertyWebkitMarginTopCollapse, CSSPropertyWebkitMarginBottomCollapse };
+    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyWebkitMarginCollapse, marginCollapseProperties);
+
+    static const int marqueeProperties[] = {
+        CSSPropertyWebkitMarqueeDirection,
+        CSSPropertyWebkitMarqueeIncrement,
+        CSSPropertyWebkitMarqueeRepetition,
+        CSSPropertyWebkitMarqueeStyle,
+        CSSPropertyWebkitMarqueeSpeed
+    };
+    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyWebkitMarquee, marqueeProperties);
+
+    static const int outlineProperties[] = {
+        CSSPropertyOutlineColor,
+        CSSPropertyOutlineOffset,
+        CSSPropertyOutlineStyle,
+        CSSPropertyOutlineWidth
+    };
+    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyOutline, outlineProperties);
+
+    static const int paddingProperties[] = {
+        CSSPropertyPaddingTop,
+        CSSPropertyPaddingRight,
+        CSSPropertyPaddingBottom,
+        CSSPropertyPaddingLeft
+    };
+    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyPadding, paddingProperties);
+
+    static const int textStrokeProperties[] = { CSSPropertyWebkitTextStrokeColor, CSSPropertyWebkitTextStrokeWidth };
+    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyWebkitTextStroke, textStrokeProperties);
+
+    static const int backgroundProperties[] = {
+        CSSPropertyBackgroundAttachment,
+        CSSPropertyWebkitBackgroundClip,
+        CSSPropertyBackgroundColor,
+        CSSPropertyBackgroundImage,
+        CSSPropertyWebkitBackgroundOrigin,
+        CSSPropertyBackgroundPositionX,
+        CSSPropertyBackgroundPositionY,
+        CSSPropertyBackgroundRepeat,
+    };
+    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyBackground, backgroundProperties);
+
+    static const int columnsProperties[] = { CSSPropertyWebkitColumnWidth, CSSPropertyWebkitColumnCount };
+    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyWebkitColumns, columnsProperties);
+
+    static const int columnRuleProperties[] = {
+        CSSPropertyWebkitColumnRuleColor,
+        CSSPropertyWebkitColumnRuleStyle,
+        CSSPropertyWebkitColumnRuleWidth
+    };
+    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyWebkitColumnRule, columnRuleProperties);
+
+    static const int overflowProperties[] = { CSSPropertyOverflowX, CSSPropertyOverflowY };
+    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyOverflow, overflowProperties);
+
+    static const int borderRadiusProperties[] = {
+        CSSPropertyWebkitBorderTopRightRadius,
+        CSSPropertyWebkitBorderTopLeftRadius,
+        CSSPropertyWebkitBorderBottomLeftRadius,
+        CSSPropertyWebkitBorderBottomRightRadius
+    };
+    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyWebkitBorderRadius, borderRadiusProperties);
+
+    static const int maskPositionProperties[] = { CSSPropertyWebkitMaskPositionX, CSSPropertyWebkitMaskPositionY };
+    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyWebkitMaskPosition, maskPositionProperties);
+
+    static const int maskProperties[] = {
+        CSSPropertyWebkitMaskAttachment,
+        CSSPropertyWebkitMaskClip,
+        CSSPropertyWebkitMaskImage,
+        CSSPropertyWebkitMaskOrigin,
+        CSSPropertyWebkitMaskPositionX,
+        CSSPropertyWebkitMaskPositionY,
+        CSSPropertyWebkitMaskRepeat,
+    };
+    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyWebkitMask, maskProperties);
+
+    static const int animationProperties[] = {
+        CSSPropertyWebkitAnimationName,
+        CSSPropertyWebkitAnimationDuration,
+        CSSPropertyWebkitAnimationTimingFunction,
+        CSSPropertyWebkitAnimationDelay,
+        CSSPropertyWebkitAnimationIterationCount,
+        CSSPropertyWebkitAnimationDirection
+    };
+    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyWebkitAnimation, animationProperties);
+
+    static const int transitionProperties[] = {
+        CSSPropertyWebkitTransitionProperty,
+        CSSPropertyWebkitTransitionDuration,
+        CSSPropertyWebkitTransitionTimingFunction,
+        CSSPropertyWebkitTransitionDelay
+    };
+    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyWebkitTransition, transitionProperties);
+
+    static const int transformOriginProperties[] = {
+        CSSPropertyWebkitTransformOriginX,
+        CSSPropertyWebkitTransformOriginY
+    };
+    SET_SHORTHAND_MAP_ENTRY(shorthandMap, CSSPropertyWebkitTransformOrigin, transformOriginProperties);
+    
+    #undef SET_SHORTHAND_MAP_ENTRY
+}
+
+CSSPropertyLonghand longhandForProperty(int propertyID)
+{
+    DEFINE_STATIC_LOCAL(ShorthandMap, shorthandMap, ());
+    if (shorthandMap.isEmpty())
+        initShorthandMap(shorthandMap);
+
+    return shorthandMap.get(propertyID);
+}
+
+
+} // namespace WebCore
diff --git a/WebCore/css/CSSPropertyLonghand.h b/WebCore/css/CSSPropertyLonghand.h
new file mode 100644 (file)
index 0000000..9633c02
--- /dev/null
@@ -0,0 +1,53 @@
+/*
+ * (C) 1999-2003 Lars Knoll (knoll@kde.org)
+ * Copyright (C) 2004, 2005, 2006, 2008 Apple Inc. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef CSSPropertyLonghand_h
+#define CSSPropertyLonghand_h
+
+namespace WebCore {
+
+class CSSPropertyLonghand {
+public:
+    CSSPropertyLonghand()
+        : m_properties(0)
+        , m_length(0)
+    {
+    }
+
+    CSSPropertyLonghand(const int* firstProperty, unsigned numProperties)
+        : m_properties(firstProperty)
+        , m_length(numProperties)
+    {
+    }
+
+    const int* properties() const { return m_properties; }
+    unsigned length() const { return m_length; }
+
+private:
+    const int* m_properties;
+    unsigned m_length;
+};
+
+// Returns an empty list if the property is not a shorthand
+CSSPropertyLonghand longhandForProperty(int);
+
+} // namespace WebCore
+
+#endif // CSSPropertyLonghand_h
index b7ae4e1..72bf16a 100644 (file)
@@ -30,6 +30,8 @@
 #include "AnimationBase.h"
 
 #include "AnimationController.h"
+#include "CSSMutableStyleDeclaration.h"
+#include "CSSPropertyLonghand.h"
 #include "CSSPropertyNames.h"
 #include "CString.h"
 #include "CompositeAnimation.h"
@@ -154,6 +156,11 @@ static inline EVisibility blendFunc(const AnimationBase* anim, EVisibility from,
     return result > 0. ? VISIBLE : (to != VISIBLE ? to : from);
 }
 
+class PropertyWrapperBase;
+
+static void addShorthandProperties();
+static PropertyWrapperBase* wrapperForProperty(int propertyID);
+
 class PropertyWrapperBase {
 public:
     PropertyWrapperBase(int prop)
@@ -162,6 +169,8 @@ public:
     }
 
     virtual ~PropertyWrapperBase() { }
+    
+    virtual bool isShorthandWrapper() const { return false; }
     virtual bool equals(const RenderStyle* a, const RenderStyle* b) const = 0;
     virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const = 0;
 
@@ -288,9 +297,48 @@ private:
     void (RenderStyle::*m_setter)(const Color&);
 };
 
+class ShorthandPropertyWrapper : public PropertyWrapperBase {
+public:
+    ShorthandPropertyWrapper(int property, const CSSPropertyLonghand& longhand)
+        : PropertyWrapperBase(property)
+    {
+        for (unsigned i = 0; i < longhand.length(); ++i) {
+            PropertyWrapperBase* wrapper = wrapperForProperty(longhand.properties()[i]);
+            if (wrapper)
+                m_propertyWrappers.append(wrapper);
+        }
+    }
+
+    virtual bool isShorthandWrapper() const { return true; }
+
+    virtual bool equals(const RenderStyle* a, const RenderStyle* b) const
+    {
+        Vector<PropertyWrapperBase*>::const_iterator end = m_propertyWrappers.end();
+        for (Vector<PropertyWrapperBase*>::const_iterator it = m_propertyWrappers.begin(); it != end; ++it) {
+            if (!(*it)->equals(a, b))
+                return false;
+        }
+        return true;
+    }
+
+    virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const
+    {
+        Vector<PropertyWrapperBase*>::const_iterator end = m_propertyWrappers.end();
+        for (Vector<PropertyWrapperBase*>::const_iterator it = m_propertyWrappers.begin(); it != end; ++it)
+            (*it)->blend(anim, dst, a, b, progress);
+    }
+
+private:
+    Vector<PropertyWrapperBase*> m_propertyWrappers;
+};
+
+
 static Vector<PropertyWrapperBase*>* gPropertyWrappers = 0;
 static int gPropertyWrapperMap[numCSSProperties];
 
+static const int cInvalidPropertyWrapperIndex = -1;
+
+
 static void ensurePropertyMap()
 {
     // FIXME: This data is never destroyed. Maybe we should ref count it and toss it when the last AnimationController is destroyed?
@@ -360,18 +408,98 @@ static void ensurePropertyMap()
         gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyStrokeOpacity, &RenderStyle::strokeOpacity, &RenderStyle::setStrokeOpacity));
 #endif
 
+        // TODO:
+        // 
+        //  CSSPropertyBackground, CSSPropertyBackgroundPosition
+        //  CSSPropertyMinWidth, CSSPropertyMaxWidth, CSSPropertyMinHeight, CSSPropertyMaxHeight
+        //  CSSPropertyTextIndent
+        //  CSSPropertyVerticalAlign
+        //  CSSPropertyWebkitBackgroundOrigin
+        //  CSSPropertyWebkitBackgroundSize
+        //  CSSPropertyWebkitMaskPosition
+        //  CSSPropertyWebkitMaskOrigin
+        //  CSSPropertyWebkitMaskSize
+        // 
+        // Compound properties that have components that should be animatable:
+        // 
+        //  CSSPropertyWebkitColumns
+        //  CSSPropertyWebkitMask
+        //  CSSPropertyWebkitBoxReflect
+
         // Make sure unused slots have a value
-        for (unsigned int i = 0; i < (unsigned int) numCSSProperties; ++i)
-            gPropertyWrapperMap[i] = CSSPropertyInvalid;
+        for (unsigned int i = 0; i < static_cast<unsigned int>(numCSSProperties); ++i)
+            gPropertyWrapperMap[i] = cInvalidPropertyWrapperIndex;
 
+        // First we put the non-shorthand property wrappers into the map, so the shorthand-building
+        // code can find them.
         size_t n = gPropertyWrappers->size();
         for (unsigned int i = 0; i < n; ++i) {
             ASSERT((*gPropertyWrappers)[i]->property() - firstCSSProperty < numCSSProperties);
             gPropertyWrapperMap[(*gPropertyWrappers)[i]->property() - firstCSSProperty] = i;
         }
+        
+        // Now add the shorthand wrappers.
+        addShorthandProperties();
     }
 }
 
+static void addPropertyWrapper(int propertyID, PropertyWrapperBase* wrapper)
+{
+    int propIndex = propertyID - firstCSSProperty;
+
+    ASSERT(gPropertyWrapperMap[propIndex] == cInvalidPropertyWrapperIndex);
+
+    unsigned wrapperIndex = gPropertyWrappers->size();
+    gPropertyWrappers->append(wrapper);
+    gPropertyWrapperMap[propIndex] = wrapperIndex;
+}
+
+static void addShorthandProperties()
+{
+    static const int animatableShorthandProperties[] = {
+        CSSPropertyBackground,      // for background-color
+        CSSPropertyBorderTop, CSSPropertyBorderRight, CSSPropertyBorderBottom, CSSPropertyBorderLeft,
+        CSSPropertyBorderColor, 
+        CSSPropertyBorderWidth,
+        CSSPropertyBorder,
+        CSSPropertyBorderSpacing,
+        CSSPropertyMargin,
+        CSSPropertyOutline,
+        CSSPropertyPadding,
+        CSSPropertyWebkitTextStroke,
+        CSSPropertyWebkitColumnRule,
+        CSSPropertyWebkitBorderRadius,
+        CSSPropertyWebkitTransformOrigin
+    };
+
+    for (unsigned i = 0; i < sizeof(animatableShorthandProperties) / sizeof(animatableShorthandProperties[0]); ++i) {
+        int propertyID = animatableShorthandProperties[i];
+        CSSPropertyLonghand longhand = longhandForProperty(propertyID);
+        if (longhand.length() > 0)
+            addPropertyWrapper(propertyID, new ShorthandPropertyWrapper(propertyID, longhand));
+    }
+
+    // 'font' is not in the shorthand map.
+    static const int animatableFontProperties[] = {
+        CSSPropertyFontSize,
+        CSSPropertyFontWeight
+    };
+
+    CSSPropertyLonghand fontLonghand(animatableFontProperties, sizeof(animatableFontProperties) / sizeof(animatableFontProperties[0]));
+    addPropertyWrapper(CSSPropertyFont, new ShorthandPropertyWrapper(CSSPropertyFont, fontLonghand));
+}
+
+static PropertyWrapperBase* wrapperForProperty(int propertyID)
+{
+    int propIndex = propertyID - firstCSSProperty;
+    if (propIndex >= 0 && propIndex < numCSSProperties) {
+        int wrapperIndex = gPropertyWrapperMap[propIndex];
+        if (wrapperIndex >= 0)
+            return (*gPropertyWrappers)[wrapperIndex];
+    }
+    return 0;
+}
+
 AnimationBase::AnimationBase(const Animation* transition, RenderObject* renderer, CompositeAnimation* compAnim)
     : m_animState(AnimationStateNew)
     , m_isAnimating(false)
@@ -403,27 +531,28 @@ bool AnimationBase::propertiesEqual(int prop, const RenderStyle* a, const Render
     if (prop == cAnimateAll) {
         size_t n = gPropertyWrappers->size();
         for (unsigned int i = 0; i < n; ++i) {
-            if (!(*gPropertyWrappers)[i]->equals(a, b))
+            PropertyWrapperBase* wrapper = (*gPropertyWrappers)[i];
+            // No point comparing shorthand wrappers for 'all'.
+            if (!wrapper->isShorthandWrapper() && !wrapper->equals(a, b))
                 return false;
         }
     } else {
-        int propIndex = prop - firstCSSProperty;
-
-        if (propIndex >= 0 && propIndex < numCSSProperties) {
-            int i = gPropertyWrapperMap[propIndex];
-            return i >= 0 ? (*gPropertyWrappers)[i]->equals(a, b) : true;
-        }
+        PropertyWrapperBase* wrapper = wrapperForProperty(prop);
+        if (wrapper)
+            return wrapper->equals(a, b);
     }
     return true;
 }
 
-int AnimationBase::getPropertyAtIndex(int i)
+int AnimationBase::getPropertyAtIndex(int i, bool& isShorthand)
 {
     ensurePropertyMap();
     if (i < 0 || i >= static_cast<int>(gPropertyWrappers->size()))
         return CSSPropertyInvalid;
 
-    return (*gPropertyWrappers)[i]->property();
+    PropertyWrapperBase* wrapper = (*gPropertyWrappers)[i];
+    isShorthand = wrapper->isShorthandWrapper();
+    return wrapper->property();
 }
 
 int AnimationBase::getNumProperties()
@@ -436,31 +565,12 @@ int AnimationBase::getNumProperties()
 bool AnimationBase::blendProperties(const AnimationBase* anim, int prop, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress)
 {
     ASSERT(prop != cAnimateAll);
-    // FIXME: Why can this happen?
-    
-    ensurePropertyMap();
-    if (prop == cAnimateAll) {
-        bool needsTimer = false;
 
-        size_t n = gPropertyWrappers->size();
-        for (unsigned int i = 0; i < n; ++i) {
-            PropertyWrapperBase* wrapper = (*gPropertyWrappers)[i];
-            if (!wrapper->equals(a, b)) {
-                wrapper->blend(anim, dst, a, b, progress);
-                needsTimer = true;
-            }
-        }
-        return needsTimer;
-    }
-
-    int propIndex = prop - firstCSSProperty;
-    if (propIndex >= 0 && propIndex < numCSSProperties) {
-        int i = gPropertyWrapperMap[propIndex];
-        if (i >= 0) {
-            PropertyWrapperBase* wrapper = (*gPropertyWrappers)[i];
-            wrapper->blend(anim, dst, a, b, progress);
-            return true;
-        }
+    ensurePropertyMap();
+    PropertyWrapperBase* wrapper = wrapperForProperty(prop);
+    if (wrapper) {
+        wrapper->blend(anim, dst, a, b, progress);
+        return true;
     }
 
     return false;
index 97612e5..eab1f43 100644 (file)
@@ -172,7 +172,7 @@ protected:
     void goIntoEndingOrLoopingState();
 
     static bool propertiesEqual(int prop, const RenderStyle* a, const RenderStyle* b);
-    static int getPropertyAtIndex(int);
+    static int getPropertyAtIndex(int, bool& isShorthand);
     static int getNumProperties();
 
     // Return true if we need to start software animation timers
index c7bfea9..8b5c12e 100644 (file)
@@ -148,12 +148,15 @@ void CompositeAnimationPrivate::updateTransitions(RenderObject* renderer, Render
         // through the loop.
         for (int propertyIndex = 0; propertyIndex < AnimationBase::getNumProperties(); ++propertyIndex) {
             if (all) {
-                // Get the next property
-                prop = AnimationBase::getPropertyAtIndex(propertyIndex);
+                // Get the next property which is not a shorthand.
+                bool isShorthand;
+                prop = AnimationBase::getPropertyAtIndex(propertyIndex, isShorthand);
+                if (isShorthand)
+                    continue;
             }
 
             // ImplicitAnimations are always hashed by actual properties, never cAnimateAll
-            ASSERT(prop > firstCSSProperty && prop < (firstCSSProperty + numCSSProperties));
+            ASSERT(prop >= firstCSSProperty && prop < (firstCSSProperty + numCSSProperties));
 
             // If there is a running animation for this property, the transition is overridden
             // and we have to use the unanimatedStyle from the animation. We do the test