Changeset 35545 in webkit
- Timestamp:
- Aug 4, 2008 6:54:46 PM (16 years ago)
- Location:
- trunk
- Files:
-
- 3 added
- 28 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r35541 r35545 1 2008-08-04 Dean Jackson <dino@apple.com> 2 3 Reviewed by Dave Hyatt 4 5 Update expected computed style results for the following bug 6 Improve AnimationController 7 https://bugs.webkit.org/show_bug.cgi?id=19938 8 9 * fast/css/computed-style-expected.txt: 10 * fast/css/computed-style-without-renderer-expected.txt: 11 * svg/css/getComputedStyle-basic-expected.txt: 12 1 13 2008-08-04 Sam Weinig <sam@webkit.org> 2 14 -
trunk/LayoutTests/fast/css/computed-style-expected.txt
r35239 r35545 139 139 -webkit-transform-origin-x: 392px; 140 140 -webkit-transform-origin-y: 288px; 141 -webkit-transition-delay: 0s; 142 -webkit-transition-duration: 0s; 143 -webkit-transition-property: all; 144 -webkit-transition-timing-function: cubic-bezier(0.25, 0.1, 0.25, 1); 141 145 -webkit-user-drag: auto; 142 146 -webkit-user-modify: read-only; -
trunk/LayoutTests/fast/css/computed-style-without-renderer-expected.txt
r35239 r35545 138 138 -webkit-transform-origin-x: 50% 139 139 -webkit-transform-origin-y: 50% 140 -webkit-transition-delay: 0s 141 -webkit-transition-duration: 0s 142 -webkit-transition-property: all 143 -webkit-transition-timing-function: cubic-bezier(0.25, 0.1, 0.25, 1) 140 144 -webkit-user-drag: auto 141 145 -webkit-user-modify: read-only -
trunk/LayoutTests/svg/css/getComputedStyle-basic-expected.txt
r35307 r35545 275 275 rect: style.getPropertyValue(-webkit-transform-origin-y) : 0px 276 276 rect: style.getPropertyCSSValue(-webkit-transform-origin-y) : [object CSSPrimitiveValue] 277 rect: style.getPropertyValue(-webkit-transition-delay) : 0s 278 rect: style.getPropertyCSSValue(-webkit-transition-delay) : [object CSSValueList] 279 rect: style.getPropertyValue(-webkit-transition-duration) : 0s 280 rect: style.getPropertyCSSValue(-webkit-transition-duration) : [object CSSValueList] 281 rect: style.getPropertyValue(-webkit-transition-property) : all 282 rect: style.getPropertyCSSValue(-webkit-transition-property) : [object CSSValueList] 283 rect: style.getPropertyValue(-webkit-transition-timing-function) : cubic-bezier(0.25, 0.1, 0.25, 1) 284 rect: style.getPropertyCSSValue(-webkit-transition-timing-function) : [object CSSValueList] 277 285 rect: style.getPropertyValue(-webkit-user-drag) : auto 278 286 rect: style.getPropertyCSSValue(-webkit-user-drag) : [object CSSPrimitiveValue] … … 643 651 g: style.getPropertyValue(-webkit-transform-origin-y) : 0px 644 652 g: style.getPropertyCSSValue(-webkit-transform-origin-y) : [object CSSPrimitiveValue] 653 g: style.getPropertyValue(-webkit-transition-delay) : 0s 654 g: style.getPropertyCSSValue(-webkit-transition-delay) : [object CSSValueList] 655 g: style.getPropertyValue(-webkit-transition-duration) : 0s 656 g: style.getPropertyCSSValue(-webkit-transition-duration) : [object CSSValueList] 657 g: style.getPropertyValue(-webkit-transition-property) : all 658 g: style.getPropertyCSSValue(-webkit-transition-property) : [object CSSValueList] 659 g: style.getPropertyValue(-webkit-transition-timing-function) : cubic-bezier(0.25, 0.1, 0.25, 1) 660 g: style.getPropertyCSSValue(-webkit-transition-timing-function) : [object CSSValueList] 645 661 g: style.getPropertyValue(-webkit-user-drag) : auto 646 662 g: style.getPropertyCSSValue(-webkit-user-drag) : [object CSSPrimitiveValue] -
trunk/WebCore/ChangeLog
r35544 r35545 1 2008-05-12 Mike Belshe <mike@belshe.com> 2 3 Reviewed by Antti. 4 5 Currently we create two copies of script in the HTMLTokenizer. 6 One copy gets passed into the javascript engine, the other gets 7 stored in the DOM. Modify the HTMLParser so that it does not 8 chunk the string into it's normal 64K chunks for script code, 9 and modify the HTMLTokenizer to pass that same string into the 10 JS engine. On some sites (e.g. GMail), which have hundreds of 11 KB of inline JS, this saves more than a MB of RAM to run the page. 12 (Strings use 16bit strings, so 600KB of JS code == 1.2MB of memory) 13 14 * html\HTMLParser.cpp 15 * html\HTMLTokenizer.cpp 1 2008-08-04 Dean Jackson <dino@apple.com> 2 3 Reviewed by Dave Hyatt. 4 5 Improve AnimationController 6 https://bugs.webkit.org/show_bug.cgi?id=19938 7 8 - Transition class is now called Animation 9 - new state-based AnimationController that can support CSS Animations 10 - add support for -webkit-transition-delay 11 - remove -webkit-transition-repeat-count (since it never existed officially) 12 - updates the -webkit-transition shorthand to reflect removing repeat count 13 - updates the Transition class so that properties can be shared with animations 14 - adds a "now" keyword for -webkit-transition-delay 15 - adds a new change type for style (changed by animation) 16 - adds new event names (although they are not dispatched yet) 17 - makes text stroke and text fill colors returned by RenderStyle const 18 19 Tests: 20 - manual-tests/transition-left.html 21 - manual-tests/transition-delay.html 22 - manual-tests/transition-timing-functions.html 23 24 * css/CSSComputedStyleDeclaration.cpp: 25 * css/CSSParser.cpp: 26 * css/CSSParser.h: 27 * css/CSSPropertyNames.in: 28 * css/CSSStyleSelector.cpp: 29 * css/CSSStyleSelector.h: 30 * css/CSSTimingFunctionValue.h: 31 * css/CSSValue.h: 32 * css/CSSValueKeywords.in: 33 * css/WebKitCSSTransformValue.cpp: 34 * dom/Document.cpp: 35 * dom/Document.h: 36 * dom/Element.cpp: 37 * dom/EventNames.h: 38 * dom/Node.cpp: 39 * dom/Node.h: 40 * history/CachedPage.cpp: 41 * page/AnimationController.cpp: 42 * page/AnimationController.h: 43 * page/Frame.cpp: 44 * rendering/RenderObject.cpp: 45 * rendering/RenderWidget.cpp: 46 * rendering/style/RenderStyle.cpp: 47 * rendering/style/RenderStyle.h: 16 48 17 49 2008-08-04 Sam Weinig <sam@webkit.org> -
trunk/WebCore/css/CSSComputedStyleDeclaration.cpp
r35240 r35545 30 30 #include "CSSPropertyNames.h" 31 31 #include "CSSReflectValue.h" 32 #include "CSSTimingFunctionValue.h" 32 33 #include "CSSValueList.h" 33 34 #include "CachedImage.h" … … 188 189 CSSPropertyWebkitTransformOriginX, 189 190 CSSPropertyWebkitTransformOriginY, 191 CSSPropertyWebkitTransitionDelay, 192 CSSPropertyWebkitTransitionDuration, 193 CSSPropertyWebkitTransitionProperty, 194 CSSPropertyWebkitTransitionTimingFunction, 190 195 CSSPropertyWebkitUserDrag, 191 196 CSSPropertyWebkitUserModify, … … 1056 1061 else 1057 1062 return CSSPrimitiveValue::create(style->transformOriginY()); 1063 case CSSPropertyWebkitTransitionDelay: { 1064 RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); 1065 const AnimationList* t = style->transitions(); 1066 if (t) { 1067 for (size_t i = 0; i < t->size(); ++i) 1068 list->append(CSSPrimitiveValue::create((*t)[i]->delay(), CSSPrimitiveValue::CSS_S)); 1069 } 1070 else 1071 list->append(CSSPrimitiveValue::create(RenderStyle::initialDelay(), CSSPrimitiveValue::CSS_S)); 1072 return list.release(); 1073 } 1074 case CSSPropertyWebkitTransitionDuration: { 1075 RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); 1076 const AnimationList* t = style->transitions(); 1077 if (t) { 1078 for (size_t i = 0; i < t->size(); ++i) 1079 list->append(CSSPrimitiveValue::create((*t)[i]->duration(), CSSPrimitiveValue::CSS_S)); 1080 } 1081 else 1082 list->append(CSSPrimitiveValue::create(RenderStyle::initialDuration(), CSSPrimitiveValue::CSS_S)); 1083 return list.release(); 1084 } 1085 case CSSPropertyWebkitTransitionTimingFunction: { 1086 RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); 1087 const AnimationList* t = style->transitions(); 1088 if (t) { 1089 for (size_t i = 0; i < t->size(); ++i) { 1090 const TimingFunction& tf = (*t)[i]->timingFunction(); 1091 list->append(CSSTimingFunctionValue::create(tf.x1(), tf.y1(), tf.x2(), tf.y2())); 1092 } 1093 } 1094 else { 1095 const TimingFunction& tf = RenderStyle::initialTimingFunction(); 1096 list->append(CSSTimingFunctionValue::create(tf.x1(), tf.y1(), tf.x2(), tf.y2())); 1097 } 1098 return list.release(); 1099 } 1100 case CSSPropertyWebkitTransitionProperty: { 1101 RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated(); 1102 const AnimationList* t = style->transitions(); 1103 if (t) { 1104 for (size_t i = 0; i < t->size(); ++i) { 1105 int prop = (*t)[i]->property(); 1106 const char* name; 1107 if (prop == cAnimateNone) 1108 name = "none"; 1109 else if (prop == cAnimateAll) 1110 name = "all"; 1111 else 1112 name = getPropertyName(static_cast<CSSPropertyID>(prop)); 1113 list->append(CSSPrimitiveValue::create(name, CSSPrimitiveValue::CSS_STRING)); 1114 } 1115 } 1116 else 1117 list->append(CSSPrimitiveValue::create("all", CSSPrimitiveValue::CSS_STRING)); 1118 return list.release(); 1119 } 1058 1120 case CSSPropertyBackground: 1059 1121 case CSSPropertyBorder: … … 1113 1175 case CSSPropertyWebkitPaddingStart: 1114 1176 case CSSPropertyWebkitTextStroke: 1115 case CSSPropertyWebkitTransition:1116 case CSSPropertyWebkitTransitionDuration:1117 case CSSPropertyWebkitTransitionProperty:1118 case CSSPropertyWebkitTransitionRepeatCount:1119 case CSSPropertyWebkitTransitionTimingFunction:1120 1177 // FIXME: The above are unimplemented. 1121 1178 break; -
trunk/WebCore/css/CSSParser.cpp
r35414 r35545 1295 1295 return false; 1296 1296 } 1297 case CSSPropertyWebkitTransitionDelay: 1297 1298 case CSSPropertyWebkitTransitionDuration: 1298 case CSSPropertyWebkitTransitionRepeatCount:1299 1299 case CSSPropertyWebkitTransitionTimingFunction: 1300 1300 case CSSPropertyWebkitTransitionProperty: { … … 1710 1710 bool CSSParser::parseTransitionShorthand(bool important) 1711 1711 { 1712 const int properties[] = { CSSPropertyWebkitTransitionProperty, CSSPropertyWebkitTransitionDuration, 1713 CSSPropertyWebkitTransitionTimingFunction, CSSPropertyWebkitTransitionRepeatCount }; 1712 const int properties[] = { CSSPropertyWebkitTransitionProperty, 1713 CSSPropertyWebkitTransitionDuration, 1714 CSSPropertyWebkitTransitionTimingFunction }; 1714 1715 const int numProperties = sizeof(properties) / sizeof(properties[0]); 1715 1716 … … 2207 2208 } 2208 2209 2209 PassRefPtr<CSSValue> CSSParser::parse TransitionDuration()2210 PassRefPtr<CSSValue> CSSParser::parseDelay() 2210 2211 { 2211 2212 CSSParserValue* value = m_valueList->current(); 2213 if (value->id == CSSValueNow) 2214 return CSSPrimitiveValue::createIdentifier(value->id); 2212 2215 if (validUnit(value, FTime, m_strict)) 2213 2216 return CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit); … … 2215 2218 } 2216 2219 2217 PassRefPtr<CSSValue> CSSParser::parse TransitionRepeatCount()2220 PassRefPtr<CSSValue> CSSParser::parseDuration() 2218 2221 { 2219 2222 CSSParserValue* value = m_valueList->current(); 2220 if (value->id == CSSValueInfinite) 2221 return CSSPrimitiveValue::createIdentifier(value->id); 2222 if (validUnit(value, FInteger|FNonNeg, m_strict)) 2223 if (validUnit(value, FTime|FNonNeg, m_strict)) 2223 2224 return CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit); 2224 2225 return 0; … … 2243 2244 } 2244 2245 2245 PassRefPtr<CSSValue> CSSParser::parseT ransitionTimingFunction()2246 PassRefPtr<CSSValue> CSSParser::parseTimingFunction() 2246 2247 { 2247 2248 CSSParserValue* value = m_valueList->current(); … … 2307 2308 else { 2308 2309 switch (propId) { 2309 case CSSPropertyWebkitTransitionD uration:2310 currValue = parse TransitionDuration();2310 case CSSPropertyWebkitTransitionDelay: 2311 currValue = parseDelay(); 2311 2312 if (currValue) 2312 2313 m_valueList->next(); 2313 2314 break; 2314 case CSSPropertyWebkitTransition RepeatCount:2315 currValue = parse TransitionRepeatCount();2315 case CSSPropertyWebkitTransitionDuration: 2316 currValue = parseDuration(); 2316 2317 if (currValue) 2317 2318 m_valueList->next(); 2318 2319 break; 2319 2320 case CSSPropertyWebkitTransitionTimingFunction: 2320 currValue = parseT ransitionTimingFunction();2321 currValue = parseTimingFunction(); 2321 2322 if (currValue) 2322 2323 m_valueList->next(); … … 3908 3909 // The transform is a list of functional primitives that specify transform operations. 3909 3910 // We collect a list of WebKitCSSTransformValues, where each value specifies a single operation. 3910 RefPtr<CSSValueList> list = CSSValueList::create CommaSeparated();3911 RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated(); 3911 3912 for (CSSParserValue* value = m_valueList->current(); value; value = m_valueList->next()) { 3912 3913 if (value->unit != CSSParserValue::Function || !value->function) -
trunk/WebCore/css/CSSParser.h
r35414 r35545 85 85 86 86 void addTransitionValue(RefPtr<CSSValue>& lval, PassRefPtr<CSSValue> rval); 87 PassRefPtr<CSSValue> parseTransitionDuration(); 88 PassRefPtr<CSSValue> parseTransitionRepeatCount(); 89 PassRefPtr<CSSValue> parseTransitionTimingFunction(); 87 88 PassRefPtr<CSSValue> parseDelay(); 89 PassRefPtr<CSSValue> parseDuration(); 90 PassRefPtr<CSSValue> parseTimingFunction(); 91 PassRefPtr<CSSValue> parseTransitionProperty(); 92 90 93 bool parseTimingFunctionValue(CSSParserValueList*& args, double& result); 91 PassRefPtr<CSSValue> parseTransitionProperty();92 94 bool parseTransitionProperty(int propId, RefPtr<CSSValue>&); 93 95 bool parseTransitionShorthand(bool important); -
trunk/WebCore/css/CSSPropertyNames.in
r35414 r35545 143 143 z-index 144 144 zoom 145 -webkit-transition146 -webkit-transition-duration147 -webkit-transition-property148 -webkit-transition-repeat-count149 -webkit-transition-timing-function150 145 -webkit-appearance 151 146 -webkit-background-clip … … 226 221 -webkit-transform-origin-x 227 222 -webkit-transform-origin-y 223 -webkit-transition 224 -webkit-transition-delay 225 -webkit-transition-duration 226 -webkit-transition-property 227 -webkit-transition-timing-function 228 228 -webkit-user-drag 229 229 -webkit-user-modify -
trunk/WebCore/css/CSSStyleSelector.cpp
r35438 r35545 185 185 #define HANDLE_TRANSITION_INHERIT_AND_INITIAL(prop, Prop) \ 186 186 if (isInherit) { \ 187 Transition* currChild = m_style->accessTransitions(); \ 188 Transition* prevChild = 0; \ 189 const Transition* currParent = m_parentStyle->transitions(); \ 190 while (currParent && currParent->is##Prop##Set()) { \ 191 if (!currChild) { \ 192 /* Need to make a new layer.*/ \ 193 currChild = new Transition(); \ 194 prevChild->setNext(currChild); \ 195 } \ 196 currChild->set##Prop(currParent->prop()); \ 197 prevChild = currChild; \ 198 currChild = prevChild->next(); \ 199 currParent = currParent->next(); \ 187 AnimationList* list = m_style->accessTransitions(); \ 188 const AnimationList* parentList = m_parentStyle->transitions(); \ 189 size_t i = 0; \ 190 for ( ; i < parentList->size() && (*parentList)[i]->is##Prop##Set(); ++i) { \ 191 if (list->size() <= i) \ 192 list->append(Animation::create()); \ 193 (*list)[i]->set##Prop((*parentList)[i]->prop()); \ 200 194 } \ 201 195 \ 202 while (currChild) { \ 203 /* Reset any remaining layers to not have the property set. */ \ 204 currChild->clear##Prop(); \ 205 currChild = currChild->next(); \ 206 } \ 207 } else if (isInitial) { \ 208 Transition* currChild = m_style->accessTransitions(); \ 209 currChild->set##Prop(RenderStyle::initialTransition##Prop()); \ 210 for (currChild = currChild->next(); currChild; currChild = currChild->next()) \ 211 currChild->clear##Prop(); \ 196 /* Reset any remaining layers to not have the property set. */ \ 197 for ( ; i < list->size(); ++i) \ 198 (*list)[i]->clear##Prop(); \ 199 } \ 200 if (isInitial) { \ 201 AnimationList* list = m_style->accessTransitions(); \ 202 (*list)[0]->set##Prop(RenderStyle::initial##Prop()); \ 203 for (size_t i = 1; i < list->size(); ++i) \ 204 (*list)[0]->clear##Prop(); \ 212 205 } 213 206 … … 216 209 if (isInherit || isInitial) \ 217 210 return; \ 218 Transition* currChild= m_style->accessTransitions(); \219 Transition* prevChild= 0; \211 AnimationList* list = m_style->accessTransitions(); \ 212 size_t childIndex = 0; \ 220 213 if (value->isValueList()) { \ 221 214 /* Walk each value and put it into a layer, creating new layers as needed. */ \ 222 215 CSSValueList* valueList = static_cast<CSSValueList*>(value); \ 223 216 for (unsigned int i = 0; i < valueList->length(); i++) { \ 224 if (!currChild) { \ 225 /* Need to make a new layer to hold this value */ \ 226 currChild = new Transition(); \ 227 prevChild->setNext(currChild); \ 228 } \ 229 mapTransition##Prop(currChild, valueList->itemWithoutBoundsCheck(i)); \ 230 prevChild = currChild; \ 231 currChild = currChild->next(); \ 217 if (childIndex <= list->size()) \ 218 list->append(Animation::create()); \ 219 map##Prop((*list)[childIndex].get(), valueList->itemWithoutBoundsCheck(i)); \ 220 ++childIndex; \ 232 221 } \ 233 222 } else { \ 234 mapTransition##Prop(currChild, value); \ 235 currChild = currChild->next(); \ 223 if (list->isEmpty()) \ 224 list->append(Animation::create()); \ 225 map##Prop((*list)[childIndex].get(), value); \ 226 childIndex = 1; \ 236 227 } \ 237 while (currChild) { \228 for ( ; childIndex < list->size(); ++childIndex) { \ 238 229 /* Reset all remaining layers to not have the property set. */ \ 239 currChild->clear##Prop(); \240 currChild = currChild->next();\241 } }230 (*list)[childIndex]->clear##Prop(); \ 231 } \ 232 } 242 233 243 234 #define HANDLE_INHERIT_COND(propID, prop, Prop) \ … … 4759 4750 m_style->inheritTransitions(m_parentStyle->transitions()); 4760 4751 return; 4752 case CSSPropertyWebkitTransitionDelay: 4753 HANDLE_TRANSITION_VALUE(delay, Delay, value) 4754 return; 4761 4755 case CSSPropertyWebkitTransitionDuration: 4762 4756 HANDLE_TRANSITION_VALUE(duration, Duration, value) 4763 4757 return; 4764 case CSSPropertyWebkitTransition RepeatCount:4765 HANDLE_TRANSITION_VALUE( repeatCount, RepeatCount, value)4758 case CSSPropertyWebkitTransitionProperty: 4759 HANDLE_TRANSITION_VALUE(property, Property, value) 4766 4760 return; 4767 4761 case CSSPropertyWebkitTransitionTimingFunction: 4768 4762 HANDLE_TRANSITION_VALUE(timingFunction, TimingFunction, value) 4769 return;4770 case CSSPropertyWebkitTransitionProperty:4771 HANDLE_TRANSITION_VALUE(property, Property, value)4772 4763 return; 4773 4764 case CSSPropertyInvalid: … … 5011 5002 } 5012 5003 5013 void CSSStyleSelector::map TransitionDuration(Transition* transition, CSSValue* value)5004 void CSSStyleSelector::mapDuration(Animation* transition, CSSValue* value) 5014 5005 { 5015 5006 if (value->cssValueType() == CSSValue::CSS_INITIAL) { 5016 transition->setDuration(RenderStyle::initial TransitionDuration());5007 transition->setDuration(RenderStyle::initialDuration()); 5017 5008 return; 5018 5009 } … … 5023 5014 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); 5024 5015 if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_S) 5025 transition->setDuration( int(1000*primitiveValue->getFloatValue()));5016 transition->setDuration(primitiveValue->getFloatValue()); 5026 5017 else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_MS) 5027 transition->setDuration( int(primitiveValue->getFloatValue()));5028 } 5029 5030 void CSSStyleSelector::map TransitionRepeatCount(Transition* transition, CSSValue* value)5018 transition->setDuration(primitiveValue->getFloatValue()/1000.0f); 5019 } 5020 5021 void CSSStyleSelector::mapDelay(Animation* transition, CSSValue* value) 5031 5022 { 5032 5023 if (value->cssValueType() == CSSValue::CSS_INITIAL) { 5033 transition->setRepeatCount(RenderStyle::initialTransitionRepeatCount()); 5034 return; 5035 } 5036 5037 if (!value->isPrimitiveValue()) 5038 return; 5024 transition->setDelay(RenderStyle::initialDelay()); 5025 return; 5026 } 5039 5027 5040 5028 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); 5041 if (primitiveValue->getIdent() == CSSValueInfinite) 5042 transition->setRepeatCount(-1); 5043 else 5044 transition->setRepeatCount(int(primitiveValue->getFloatValue())); 5045 } 5046 5047 void CSSStyleSelector::mapTransitionTimingFunction(Transition* transition, CSSValue* value) 5029 if (primitiveValue->getIdent() == CSSValueNow) 5030 transition->setDelay(0); 5031 else { 5032 if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_S) 5033 transition->setDelay(primitiveValue->getFloatValue()); 5034 else 5035 transition->setDelay(primitiveValue->getFloatValue()/1000.0f); 5036 } 5037 } 5038 5039 void CSSStyleSelector::mapTimingFunction(Animation* transition, CSSValue* value) 5048 5040 { 5049 5041 if (value->cssValueType() == CSSValue::CSS_INITIAL) { 5050 transition->setTimingFunction(RenderStyle::initialT ransitionTimingFunction());5051 return; 5052 } 5053 5042 transition->setTimingFunction(RenderStyle::initialTimingFunction()); 5043 return; 5044 } 5045 5054 5046 if (value->isPrimitiveValue()) { 5055 5047 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); … … 5073 5065 return; 5074 5066 } 5075 5076 if (value->isT ransitionTimingFunctionValue()) {5067 5068 if (value->isTimingFunctionValue()) { 5077 5069 CSSTimingFunctionValue* timingFunction = static_cast<CSSTimingFunctionValue*>(value); 5078 5070 transition->setTimingFunction(TimingFunction(CubicBezierTimingFunction, timingFunction->x1(), timingFunction->y1(), timingFunction->x2(), timingFunction->y2())); … … 5080 5072 } 5081 5073 5082 void CSSStyleSelector::map TransitionProperty(Transition* transition, CSSValue* value)5074 void CSSStyleSelector::mapProperty(Animation* transition, CSSValue* value) 5083 5075 { 5084 5076 if (value->cssValueType() == CSSValue::CSS_INITIAL) { 5085 transition->setProperty(RenderStyle::initial TransitionProperty());5077 transition->setProperty(RenderStyle::initialProperty()); 5086 5078 return; 5087 5079 } … … 5091 5083 5092 5084 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value); 5093 transition->setProperty( primitiveValue->getIdent());5085 transition->setProperty(static_cast<CSSPropertyID>(primitiveValue->getIdent())); 5094 5086 } 5095 5087 -
trunk/WebCore/css/CSSStyleSelector.h
r35414 r35545 206 206 void mapFillYPosition(FillLayer*, CSSValue*); 207 207 208 void map TransitionDuration(Transition*, CSSValue*);209 void map TransitionRepeatCount(Transition*, CSSValue*);210 void mapT ransitionTimingFunction(Transition*, CSSValue*);211 void map TransitionProperty(Transition*, CSSValue*);208 void mapDelay(Animation*, CSSValue*); 209 void mapDuration(Animation*, CSSValue*); 210 void mapTimingFunction(Animation*, CSSValue*); 211 void mapProperty(Animation*, CSSValue*); 212 212 213 213 void mapNinePieceImage(CSSValue*, NinePieceImage&); -
trunk/WebCore/css/CSSTimingFunctionValue.h
r34627 r35545 55 55 } 56 56 57 virtual bool isT ransitionTimingFunctionValue() { return true; }57 virtual bool isTimingFunctionValue() { return true; } 58 58 59 59 double m_x1; -
trunk/WebCore/css/CSSValue.h
r34666 r35545 53 53 virtual bool isImplicitInitialValue() const { return false; } 54 54 virtual bool isPrimitiveValue() const { return false; } 55 virtual bool isT ransitionTimingFunctionValue() { return false; }55 virtual bool isTimingFunctionValue() { return false; } 56 56 virtual bool isValueList() { return false; } 57 57 -
trunk/WebCore/css/CSSValueKeywords.in
r34910 r35545 564 564 565 565 # 566 # CSS_PROP__WEBKIT_TRANSITION_DELAY 567 # 568 now 569 570 # 566 571 # CSS_PROP__WEBKIT_TRANSITION_TIMING_FUNCTION 567 572 # -
trunk/WebCore/dom/Document.cpp
r35478 r35545 25 25 #include "Document.h" 26 26 27 #include "AnimationController.h" 27 28 #include "AXObjectCache.h" 28 29 #include "CDATASection.h" … … 1163 1164 if (hasChangedChild()) 1164 1165 recalcStyle(NoChange); 1166 1167 // tell the animation controller that the style is available and it can start animations 1168 if (m_frame) 1169 m_frame->animation()->styleAvailable(); 1165 1170 } 1166 1171 -
trunk/WebCore/dom/Document.h
r35172 r35545 751 751 void updateFocusAppearanceSoon(); 752 752 void cancelFocusAppearanceUpdate(); 753 753 754 754 // FF method for accessing the selection added for compatability. 755 755 DOMSelection* getSelection() const; … … 1047 1047 bool m_inLowBandwidthDisplay; 1048 1048 #endif 1049 1049 1050 }; 1050 1051 -
trunk/WebCore/dom/Element.cpp
r35332 r35545 786 786 } 787 787 788 if (ch != NoChange) 788 if (ch != NoChange) { 789 789 setRenderStyle(newStyle); 790 else if (changed() && (document()->usesSiblingRules() || document()->usesDescendantRules())) {790 } else if (changed() && (styleChangeType() != AnimationStyleChange) && (document()->usesSiblingRules() || document()->usesDescendantRules())) { 791 791 // Although no change occurred, we use the new style so that the cousin style sharing code won't get 792 792 // fooled into believing this style is the same. This is only necessary if the document actually uses … … 797 797 else 798 798 setRenderStyle(newStyle); 799 } 799 } else if (styleChangeType() == AnimationStyleChange) 800 setRenderStyle(newStyle); 800 801 801 802 newStyle->deref(document()->renderArena()); 802 803 803 804 if (change != Force) { 804 if ((document()->usesDescendantRules() || hasPositionalRules) && styleChangeType() == FullStyleChange)805 if ((document()->usesDescendantRules() || hasPositionalRules) && styleChangeType() >= FullStyleChange) 805 806 change = Force; 806 807 else -
trunk/WebCore/dom/EventNames.h
r34775 r35545 120 120 macro(stalled) \ 121 121 \ 122 macro(webkitAnimationEnd) \ 123 macro(webkitAnimationStart) \ 124 macro(webkitAnimationIteration) \ 125 \ 126 macro(webkitTransitionEnd) \ 127 \ 122 128 // end of DOM_EVENT_NAMES_FOR_EACH 123 129 -
trunk/WebCore/dom/Node.cpp
r35478 r35545 413 413 return; 414 414 415 if (!(changeType == InlineStyleChange && m_styleChange == FullStyleChange))415 if (!(changeType == InlineStyleChange && (m_styleChange == FullStyleChange || m_styleChange == AnimationStyleChange))) 416 416 m_styleChange = changeType; 417 417 -
trunk/WebCore/dom/Node.h
r35332 r35545 62 62 typedef int ExceptionCode; 63 63 64 enum StyleChangeType { NoStyleChange, InlineStyleChange, FullStyleChange };64 enum StyleChangeType { NoStyleChange, InlineStyleChange, FullStyleChange, AnimationStyleChange }; 65 65 66 66 const unsigned short DOCUMENT_POSITION_EQUIVALENT = 0x00; -
trunk/WebCore/history/CachedPage.cpp
r35478 r35545 123 123 #endif 124 124 125 mainFrame->animation()->resumeAnimations( );125 mainFrame->animation()->resumeAnimations(m_document.get()); 126 126 127 127 mainFrame->eventHandler()->setMousePressNode(mousePressNode()); -
trunk/WebCore/page/AnimationController.cpp
r35207 r35545 31 31 32 32 #include "CSSPropertyNames.h" 33 #include "CString.h" 33 34 #include "Document.h" 35 #include "EventNames.h" 34 36 #include "FloatConversion.h" 35 37 #include "Frame.h" … … 44 46 static const double cAnimationTimerDelay = 0.025; 45 47 48 static void setChanged(Node* node) 49 { 50 ASSERT(!node || (node->document() && !node->document()->inPageCache())); 51 node->setChanged(AnimationStyleChange); 52 } 53 46 54 // The epsilon value we pass to UnitBezier::solve given that the animation is going to run over |dur| seconds. The longer the 47 55 // animation, the more precision we need in the timing function result to avoid ugly discontinuities. … … 56 64 } 57 65 58 class CompositeImplicitAnimation; 59 60 class ImplicitAnimation : public Noncopyable { 66 class CompositeAnimation; 67 class AnimationBase; 68 69 class AnimationTimerBase { 61 70 public: 62 ImplicitAnimation(const Transition*); 63 ~ImplicitAnimation(); 64 65 void animate(CompositeImplicitAnimation*, RenderObject*, RenderStyle* currentStyle, RenderStyle* targetStyle, RenderStyle*& animatedStyle); 66 67 void reset(RenderObject*, RenderStyle* from, RenderStyle* to); 68 69 double progress() const; 70 71 AnimationTimerBase(AnimationBase* anim) 72 : m_timer(this, &AnimationTimerBase::timerFired) 73 , m_anim(anim) 74 { 75 m_timer.startOneShot(0); 76 } 77 virtual ~AnimationTimerBase() 78 { 79 } 80 81 void startTimer(double timeout=0) 82 { 83 m_timer.startOneShot(timeout); 84 } 85 86 void cancelTimer() 87 { 88 m_timer.stop(); 89 } 90 91 virtual void timerFired(Timer<AnimationTimerBase>*) = 0; 92 93 private: 94 Timer<AnimationTimerBase> m_timer; 95 96 protected: 97 AnimationBase* m_anim; 98 }; 99 100 class AnimationEventDispatcher : public AnimationTimerBase { 101 public: 102 AnimationEventDispatcher(AnimationBase* anim) 103 : AnimationTimerBase(anim) 104 , m_property(CSSPropertyInvalid) 105 , m_reset(false) 106 , m_elapsedTime(-1) 107 { 108 } 109 110 virtual ~AnimationEventDispatcher() 111 { 112 } 113 114 void startTimer(Element* element, const AtomicString& name, int property, bool reset, 115 const AtomicString& eventType, double elapsedTime) 116 { 117 m_element = element; 118 m_name = name; 119 m_property = property; 120 m_reset = reset; 121 m_eventType = eventType; 122 m_elapsedTime = elapsedTime; 123 AnimationTimerBase::startTimer(); 124 } 125 126 virtual void timerFired(Timer<AnimationTimerBase>*); 127 128 private: 129 RefPtr<Element> m_element; 130 AtomicString m_name; 131 int m_property; 132 bool m_reset; 133 AtomicString m_eventType; 134 double m_elapsedTime; 135 }; 136 137 class AnimationTimerCallback : public AnimationTimerBase { 138 public: 139 AnimationTimerCallback(AnimationBase* anim) 140 : AnimationTimerBase(anim) 141 , m_elapsedTime(0) 142 { } 143 virtual ~AnimationTimerCallback() { } 144 145 virtual void timerFired(Timer<AnimationTimerBase>*); 146 147 void startTimer(double timeout, const AtomicString& eventType, double elapsedTime) 148 { 149 m_eventType = eventType; 150 m_elapsedTime = elapsedTime; 151 AnimationTimerBase::startTimer(timeout); 152 } 153 154 private: 155 AtomicString m_eventType; 156 double m_elapsedTime; 157 }; 158 159 class ImplicitAnimation; 160 class AnimationControllerPrivate; 161 162 // A CompositeAnimation represents a collection of animations that 163 // are running, such as a number of properties transitioning at once. 164 165 class CompositeAnimation : public Noncopyable { 166 public: 167 CompositeAnimation(AnimationControllerPrivate* animationController) 168 : m_suspended(false) 169 , m_animationController(animationController) 170 , m_numStyleAvailableWaiters(0) 171 { } 172 173 ~CompositeAnimation() 174 { 175 deleteAllValues(m_transitions); 176 } 177 178 RenderStyle* animate(RenderObject*, RenderStyle* currentStyle, RenderStyle* targetStyle); 179 180 void setAnimating(bool inAnimating); 181 bool animating(); 182 183 bool hasAnimationForProperty(int prop) const { return m_transitions.contains(prop); } 184 185 void setTransitionStartTime(int property, double t); 186 187 void resetTransitions(RenderObject*); 188 void resetAnimations(RenderObject*); 189 190 void cleanupFinishedAnimations(RenderObject*); 191 192 void suspendAnimations(); 193 void resumeAnimations(); 194 bool suspended() const { return m_suspended; } 195 196 void overrideImplicitAnimations(int property); 197 void resumeOverriddenImplicitAnimations(int property); 198 199 void styleAvailable(); 200 201 bool isAnimatingProperty(int property) const; 202 203 void setWaitingForStyleAvailable(bool waiting); 204 protected: 205 void updateTransitions(RenderObject* renderer, RenderStyle* currentStyle, RenderStyle* targetStyle); 206 207 private: 208 typedef HashMap<int, ImplicitAnimation*> CSSPropertyTransitionsMap; 209 210 CSSPropertyTransitionsMap m_transitions; 211 bool m_suspended; 212 AnimationControllerPrivate* m_animationController; 213 uint32_t m_numStyleAvailableWaiters; 214 }; 215 216 class AnimationBase : public Noncopyable { 217 public: 218 AnimationBase(const Animation* transition, RenderObject* renderer, CompositeAnimation* compAnim); 219 virtual ~AnimationBase() 220 { 221 if (m_animState == STATE_START_WAIT_STYLE_AVAILABLE) 222 m_compAnim->setWaitingForStyleAvailable(false); 223 } 224 225 RenderObject* renderer() const { return m_object; } 226 double startTime() const { return m_startTime; } 227 double duration() const { return m_animation->duration(); } 228 229 void cancelTimers() 230 { 231 m_animationTimerCallback.cancelTimer(); 232 m_animationEventDispatcher.cancelTimer(); 233 } 234 235 // Animations and Transitions go through the states below. When entering the STARTED state 236 // the animation is started. This may or may not require deferred response from the animator. 237 // If so, we stay in this state until that response is received (and it returns the start time). 238 // Otherwise, we use the current time as the start time and go immediately to the LOOPING or 239 // ENDING state. 240 enum AnimState { 241 STATE_NEW, // animation just created, animation not running yet 242 STATE_START_WAIT_TIMER, // start timer running, waiting for fire 243 STATE_START_WAIT_STYLE_AVAILABLE, // waiting for style setup so we can start animations 244 STATE_START_WAIT_RESPONSE, // animation started, waiting for response 245 STATE_LOOPING, // response received, animation running, loop timer running, waiting for fire 246 STATE_ENDING, // response received, animation running, end timer running, waiting for fire 247 STATE_PAUSED_WAIT_TIMER, // animation in pause mode when animation started 248 STATE_PAUSED_WAIT_RESPONSE, // animation paused when in STARTING state 249 STATE_PAUSED_RUN, // animation paused when in LOOPING or ENDING state 250 STATE_DONE // end timer fired, animation finished and removed 251 }; 252 253 enum AnimStateInput { 254 STATE_INPUT_MAKE_NEW, // reset back to new from any state 255 STATE_INPUT_START_ANIMATION, // animation requests a start 256 STATE_INPUT_RESTART_ANIMATION, // force a restart from any state 257 STATE_INPUT_START_TIMER_FIRED, // start timer fired 258 STATE_INPUT_STYLE_AVAILABLE, // style is setup, ready to start animating 259 STATE_INPUT_START_TIME_SET, // m_startTime was set 260 STATE_INPUT_LOOP_TIMER_FIRED, // loop timer fired 261 STATE_INPUT_END_TIMER_FIRED, // end timer fired 262 STATE_INPUT_PAUSE_OVERRIDE, // pause an animation due to override 263 STATE_INPUT_RESUME_OVERRIDE, // resume an overridden animation 264 STATE_INPUT_PLAY_STATE_RUNNING, // play state paused -> running 265 STATE_INPUT_PLAY_STATE_PAUSED, // play state running -> paused 266 STATE_INPUT_END_ANIMATION // force an end from any state 267 }; 268 269 // Called when animation is in NEW state to start animation 270 void updateStateMachine(AnimStateInput input, double param); 271 272 // Animation has actually started, at passed time 273 // This is a callback and is only received when RenderObject::startAnimation() or RenderObject::startTransition() 274 // returns true. If RenderObject:: 275 void onAnimationStartResponse(double startTime); 276 277 // Called to change to or from paused state 278 void updatePlayState(bool running); 279 bool playStatePlaying() const { return m_animation; } 280 281 bool waitingToStart() const { return m_animState == STATE_NEW || m_animState == STATE_START_WAIT_TIMER; } 282 bool preactive() const 283 { return m_animState == STATE_NEW || 284 m_animState == STATE_START_WAIT_TIMER || 285 m_animState == STATE_START_WAIT_STYLE_AVAILABLE || 286 m_animState == STATE_START_WAIT_RESPONSE; 287 } 288 bool postactive() const { return m_animState == STATE_DONE; } 289 bool active() const { return !postactive() && !preactive(); } 290 bool running() const { return !isnew() && !postactive(); } 291 bool paused() const { return m_pauseTime >= 0; } 292 bool isnew() const { return m_animState == STATE_NEW; } 293 bool waitingForStartTime() const { return m_animState == STATE_START_WAIT_RESPONSE; } 294 bool waitingForStyleAvailable() const { return m_animState == STATE_START_WAIT_STYLE_AVAILABLE; } 295 bool waitingForEndEvent() const { return m_waitingForEndEvent; } 296 297 // "animating" means that something is running that requires a timer to keep firing 298 // (e.g. a software animation) 299 void setAnimating(bool inAnimating = true) { m_animating = inAnimating; } 300 bool animating() const { return m_animating; } 301 302 double progress(double scale, double offset) const; 303 304 virtual void animate(CompositeAnimation*, RenderObject*, const RenderStyle* currentStyle, 305 const RenderStyle* targetStyle, RenderStyle*& ioAnimatedStyle) { } 306 virtual void reset(RenderObject* renderer, const RenderStyle* from = 0, const RenderStyle* to = 0) { } 307 308 virtual bool shouldFireEvents() const { return false; } 309 310 void animationTimerCallbackFired(const AtomicString& eventType, double elapsedTime); 311 void animationEventDispatcherFired(Element* element, const AtomicString& name, int property, bool reset, 312 const AtomicString& eventType, double elapsedTime); 313 314 bool animationsMatch(const Animation* anim) const { return m_animation->animationsMatch(anim); } 315 316 void setAnimation(const Animation* anim) { m_animation = const_cast<Animation*>(anim); } 317 318 // Return true if this animation is overridden. This will only be the case for 319 // ImplicitAnimations and is used to determine whether or not we should force 320 // set the start time. If an animation is overridden, it will probably not get 321 // back the START_TIME event. 322 virtual bool overridden() const { return false; } 323 324 // Does this animation/transition involve the given property? 325 virtual bool affectsProperty(int property) const { return false; } 326 bool isAnimatingProperty(int property) const 327 { 328 return (!waitingToStart() && !postactive()) && affectsProperty(property); 329 } 330 331 protected: 332 Element* elementForEventDispatch() 333 { 334 if (m_object->node() && m_object->node()->isElementNode()) 335 return static_cast<Element*>(m_object->node()); 336 return 0; 337 } 338 339 virtual void overrideAnimations() { } 340 virtual void resumeOverriddenAnimations() { } 341 342 CompositeAnimation* compositeAnimation() { return m_compAnim; } 343 344 // These are called when the corresponding timer fires so subclasses can do any extra work 345 virtual void onAnimationStart(double elapsedTime) { } 346 virtual void onAnimationIteration(double elapsedTime) { } 347 virtual void onAnimationEnd(double elapsedTime) { } 348 virtual bool startAnimation(double beginTime) { return false; } 349 virtual void endAnimation(bool reset) { } 350 351 void primeEventTimers(); 352 353 protected: 354 AnimState m_animState; 355 int m_iteration; 356 357 bool m_animating; // transition/animation requires continual timer firing 358 bool m_waitedForResponse; 359 double m_startTime; 360 double m_pauseTime; 361 RenderObject* m_object; 362 363 AnimationTimerCallback m_animationTimerCallback; 364 AnimationEventDispatcher m_animationEventDispatcher; 365 RefPtr<Animation> m_animation; 366 CompositeAnimation* m_compAnim; 367 bool m_waitingForEndEvent; 368 }; 369 370 class ImplicitAnimation : public AnimationBase { 371 public: 372 ImplicitAnimation(const Animation* transition, RenderObject* renderer, CompositeAnimation* compAnim) 373 : AnimationBase(transition, renderer, compAnim) 374 , m_property(transition->property()) 375 , m_overridden(false) 376 , m_fromStyle(0) 377 , m_toStyle(0) 378 { 379 } 380 381 virtual ~ImplicitAnimation() 382 { 383 ASSERT(!m_fromStyle && !m_toStyle); 384 385 // If we were waiting for an end event, we need to finish the animation to make sure no old 386 // animations stick around in the lower levels 387 if (waitingForEndEvent() && m_object) 388 ASSERT(0); 389 390 // Do the cleanup here instead of in the base class so the specialized methods get called 391 if (!postactive()) 392 updateStateMachine(STATE_INPUT_END_ANIMATION, -1); 393 } 394 71 395 int property() const { return m_property; } 72 396 73 bool finished() const { return m_finished; } 74 void setFinished(bool f) { m_finished = f; } 75 76 bool stale() const { return m_stale; } 77 void setStale() { m_stale = true; } 78 397 virtual void onAnimationEnd(double inElapsedTime); 398 virtual bool startAnimation(double beginTime); 399 virtual void endAnimation(bool reset); 400 401 virtual void animate(CompositeAnimation*, RenderObject*, const RenderStyle* currentStyle, 402 const RenderStyle* targetStyle, RenderStyle*& ioAnimatedStyle); 403 virtual void reset(RenderObject* renderer, const RenderStyle* from = 0, const RenderStyle* to = 0); 404 405 void setOverridden(bool b); 406 virtual bool overridden() const { return m_overridden; } 407 408 virtual bool shouldFireEvents() const { return true; } 409 410 virtual bool affectsProperty(int property) const; 411 412 bool hasStyle() const { return m_fromStyle && m_toStyle; } 413 414 bool isTargetPropertyEqual(int prop, RenderStyle* targetStyle); 415 416 void blendPropertyValueInStyle(int prop, RenderStyle* currentStyle); 417 418 protected: 419 bool shouldSendEventForListener(Document::ListenerType inListenerType) 420 { 421 return m_object->document()->hasListenerType(inListenerType); 422 } 423 424 bool sendTransitionEvent(const AtomicString& inEventType, double inElapsedTime); 425 79 426 private: 427 int m_property; 428 bool m_overridden; 429 80 430 // The two styles that we are blending. 81 431 RenderStyle* m_fromStyle; 82 432 RenderStyle* m_toStyle; 83 84 int m_property;85 TimingFunction m_function;86 double m_duration;87 88 int m_repeatCount;89 int m_iteration;90 91 bool m_finished;92 double m_startTime;93 bool m_paused;94 double m_pauseTime;95 96 bool m_stale;97 433 }; 98 434 99 class CompositeImplicitAnimation : public Noncopyable { 100 public: 101 ~CompositeImplicitAnimation() { deleteAllValues(m_animations); } 102 103 RenderStyle* animate(RenderObject*, RenderStyle* currentStyle, RenderStyle* targetStyle); 104 105 bool animating() const; 106 107 void reset(RenderObject*); 108 109 private: 110 HashMap<int, ImplicitAnimation*> m_animations; 111 }; 112 113 ImplicitAnimation::ImplicitAnimation(const Transition* transition) 114 : m_fromStyle(0) 115 , m_toStyle(0) 116 , m_property(transition->property()) 117 , m_function(transition->timingFunction()) 118 , m_duration(transition->duration() / 1000.0) 119 , m_repeatCount(transition->repeatCount()) 435 void AnimationTimerCallback::timerFired(Timer<AnimationTimerBase>*) 436 { 437 m_anim->animationTimerCallbackFired(m_eventType, m_elapsedTime); 438 } 439 440 void AnimationEventDispatcher::timerFired(Timer<AnimationTimerBase>*) 441 { 442 m_anim->animationEventDispatcherFired(m_element.get(), m_name, m_property, m_reset, m_eventType, m_elapsedTime); 443 } 444 445 AnimationBase::AnimationBase(const Animation* transition, RenderObject* renderer, CompositeAnimation* compAnim) 446 : m_animState(STATE_NEW) 120 447 , m_iteration(0) 121 , m_finished(false) 122 , m_startTime(currentTime()) 123 , m_paused(false) 124 , m_pauseTime(m_startTime) 125 , m_stale(false) 126 { 127 } 128 129 ImplicitAnimation::~ImplicitAnimation() 130 { 131 ASSERT(!m_fromStyle && !m_toStyle); 132 } 133 134 void ImplicitAnimation::reset(RenderObject* renderer, RenderStyle* from, RenderStyle* to) 135 { 136 setFinished(false); 137 138 if (m_fromStyle) 139 m_fromStyle->deref(renderer->renderArena()); 140 if (m_toStyle) 141 m_toStyle->deref(renderer->renderArena()); 142 m_fromStyle = from; 143 if (m_fromStyle) 144 m_fromStyle->ref(); 145 m_toStyle = to; 146 if (m_toStyle) 147 m_toStyle->ref(); 148 if (from || to) 149 m_startTime = currentTime(); 448 , m_animating(false) 449 , m_waitedForResponse(false) 450 , m_startTime(0) 451 , m_pauseTime(-1) 452 , m_object(renderer) 453 , m_animationTimerCallback(const_cast<AnimationBase*>(this)) 454 , m_animationEventDispatcher(const_cast<AnimationBase*>(this)) 455 , m_animation(const_cast<Animation*>(transition)) 456 , m_compAnim(compAnim) 457 , m_waitingForEndEvent(false) 458 { 459 } 460 461 void AnimationBase::updateStateMachine(AnimStateInput input, double param) 462 { 463 // if we get a RESTART then we force a new animation, regardless of state 464 if (input == STATE_INPUT_MAKE_NEW) { 465 if (m_animState == STATE_START_WAIT_STYLE_AVAILABLE) 466 m_compAnim->setWaitingForStyleAvailable(false); 467 m_animState = STATE_NEW; 468 m_startTime = 0; 469 m_pauseTime = -1; 470 m_waitedForResponse = false; 471 endAnimation(false); 472 return; 473 } 474 else if (input == STATE_INPUT_RESTART_ANIMATION) { 475 cancelTimers(); 476 if (m_animState == STATE_START_WAIT_STYLE_AVAILABLE) 477 m_compAnim->setWaitingForStyleAvailable(false); 478 m_animState = STATE_NEW; 479 m_startTime = 0; 480 m_pauseTime = -1; 481 endAnimation(false); 150 482 151 // If we are stale, attempt to update to a new transition using the new |to| style. If we are able to find a new transition, 152 // then we will unmark ourselves for death. 153 if (stale() && from && to) { 154 for (const Transition* transition = to->transitions(); transition; transition = transition->next()) { 155 if (m_property != transition->property()) 156 continue; 157 int duration = transition->duration(); 158 int repeatCount = transition->repeatCount(); 159 if (duration && repeatCount) { 160 m_duration = duration / 1000.0; 161 m_repeatCount = repeatCount; 162 m_stale = false; 163 break; 483 if (!paused()) 484 updateStateMachine(STATE_INPUT_START_ANIMATION, -1); 485 return; 486 } 487 else if (input == STATE_INPUT_END_ANIMATION) { 488 cancelTimers(); 489 if (m_animState == STATE_START_WAIT_STYLE_AVAILABLE) 490 m_compAnim->setWaitingForStyleAvailable(false); 491 m_animState = STATE_DONE; 492 endAnimation(true); 493 return; 494 } 495 else if (input == STATE_INPUT_PAUSE_OVERRIDE) { 496 if (m_animState == STATE_START_WAIT_RESPONSE) { 497 // If we are in the WAIT_RESPONSE state, the animation will get canceled before 498 // we get a response, so move to the next state 499 endAnimation(false); 500 updateStateMachine(STATE_INPUT_START_TIME_SET, currentTime()); 501 } 502 return; 503 } 504 else if (input == STATE_INPUT_RESUME_OVERRIDE) { 505 if (m_animState == STATE_LOOPING || m_animState == STATE_ENDING) { 506 // Start the animation 507 startAnimation(m_startTime); 508 } 509 return; 510 } 511 512 // execute state machine 513 switch(m_animState) { 514 case STATE_NEW: 515 ASSERT(input == STATE_INPUT_START_ANIMATION || input == STATE_INPUT_PLAY_STATE_RUNNING || input == STATE_INPUT_PLAY_STATE_PAUSED); 516 if (input == STATE_INPUT_START_ANIMATION || input == STATE_INPUT_PLAY_STATE_RUNNING) { 517 // Set the start timer to the initial delay (0 if no delay) 518 m_waitedForResponse = false; 519 m_animState = STATE_START_WAIT_TIMER; 520 m_animationTimerCallback.startTimer(m_animation->delay(), EventNames::webkitAnimationStartEvent, m_animation->delay()); 164 521 } 165 } 166 } 167 168 // If we did not find a new transition, then mark ourselves as being finished so that we can be removed. 169 if (stale()) 170 setFinished(true); 171 } 172 173 double ImplicitAnimation::progress() const 174 { 175 double elapsedTime = currentTime() - m_startTime; 176 177 if (m_finished || !m_duration || elapsedTime >= m_duration) 522 break; 523 case STATE_START_WAIT_TIMER: 524 ASSERT(input == STATE_INPUT_START_TIMER_FIRED || input == STATE_INPUT_PLAY_STATE_PAUSED); 525 526 if (input == STATE_INPUT_START_TIMER_FIRED) { 527 ASSERT(param >= 0); 528 // Start timer has fired, tell the animation to start and wait for it to respond with start time 529 m_animState = STATE_START_WAIT_STYLE_AVAILABLE; 530 m_compAnim->setWaitingForStyleAvailable(true); 531 532 // Trigger a render so we can start the animation 533 setChanged(m_object->element()); 534 m_object->animation()->startUpdateRenderingDispatcher(); 535 } 536 else { 537 ASSERT(running()); 538 // We're waiting for the start timer to fire and we got a pause. Cancel the timer, pause and wait 539 m_pauseTime = currentTime(); 540 cancelTimers(); 541 m_animState = STATE_PAUSED_WAIT_TIMER; 542 } 543 break; 544 case STATE_START_WAIT_STYLE_AVAILABLE: 545 ASSERT(input == STATE_INPUT_STYLE_AVAILABLE || input == STATE_INPUT_PLAY_STATE_PAUSED); 546 547 m_compAnim->setWaitingForStyleAvailable(false); 548 549 if (input == STATE_INPUT_STYLE_AVAILABLE) { 550 // Start timer has fired, tell the animation to start and wait for it to respond with start time 551 m_animState = STATE_START_WAIT_RESPONSE; 552 553 overrideAnimations(); 554 555 // Send start event, if needed 556 onAnimationStart(0.0f); // the elapsedTime is always 0 here 557 558 // Start the animation 559 if (overridden() || !startAnimation(0)) { 560 // We're not going to get a startTime callback, so fire the start time here 561 m_animState = STATE_START_WAIT_RESPONSE; 562 updateStateMachine(STATE_INPUT_START_TIME_SET, currentTime()); 563 } 564 else 565 m_waitedForResponse = true; 566 } 567 else { 568 ASSERT(running()); 569 // We're waiting for the a notification that the style has been setup. If we're asked to wait 570 // at this point, the style must have been processed, so we can deal with this like we would 571 // for WAIT_RESPONSE, except that we don't need to do an endAnimation(). 572 m_pauseTime = 0; 573 m_animState = STATE_START_WAIT_RESPONSE; 574 } 575 break; 576 case STATE_START_WAIT_RESPONSE: 577 ASSERT(input == STATE_INPUT_START_TIME_SET || input == STATE_INPUT_PLAY_STATE_PAUSED); 578 579 if (input == STATE_INPUT_START_TIME_SET) { 580 ASSERT(param >= 0); 581 // We have a start time, set it, unless the startTime is already set 582 if (m_startTime <= 0) 583 m_startTime = param; 584 585 // Decide when the end or loop event needs to fire 586 primeEventTimers(); 587 588 // Trigger a render so we can start the animation 589 setChanged(m_object->element()); 590 m_object->animation()->startUpdateRenderingDispatcher(); 591 } 592 else { 593 // We are pausing while waiting for a start response. Cancel the animation and wait. When 594 // we unpause, we will act as though the start timer just fired 595 m_pauseTime = 0; 596 endAnimation(false); 597 m_animState = STATE_PAUSED_WAIT_RESPONSE; 598 } 599 break; 600 case STATE_LOOPING: 601 ASSERT(input == STATE_INPUT_LOOP_TIMER_FIRED || input == STATE_INPUT_PLAY_STATE_PAUSED); 602 603 if (input == STATE_INPUT_LOOP_TIMER_FIRED) { 604 ASSERT(param >= 0); 605 // Loop timer fired, loop again or end. 606 onAnimationIteration(param); 607 primeEventTimers(); 608 } 609 else { 610 // We are pausing while running. Cancel the animation and wait 611 m_pauseTime = currentTime(); 612 cancelTimers(); 613 endAnimation(false); 614 m_animState = STATE_PAUSED_RUN; 615 } 616 break; 617 case STATE_ENDING: 618 ASSERT(input == STATE_INPUT_END_TIMER_FIRED || input == STATE_INPUT_PLAY_STATE_PAUSED); 619 620 if (input == STATE_INPUT_END_TIMER_FIRED) { 621 ASSERT(param >= 0); 622 // End timer fired, finish up 623 onAnimationEnd(param); 624 625 resumeOverriddenAnimations(); 626 627 // Fire off another style change so we can set the final value 628 setChanged(m_object->element()); 629 m_animState = STATE_DONE; 630 m_object->animation()->startUpdateRenderingDispatcher(); 631 // |this| may be deleted here when we've been called from timerFired() 632 } 633 else { 634 // We are pausing while running. Cancel the animation and wait 635 m_pauseTime = currentTime(); 636 cancelTimers(); 637 endAnimation(false); 638 m_animState = STATE_PAUSED_RUN; 639 } 640 // |this| may be deleted here 641 break; 642 case STATE_PAUSED_WAIT_TIMER: 643 ASSERT(input == STATE_INPUT_PLAY_STATE_RUNNING); 644 ASSERT(!running()); 645 // Update the times 646 m_startTime += currentTime() - m_pauseTime; 647 m_pauseTime = -1; 648 649 // we were waiting for the start timer to fire, go back and wait again 650 m_animState = STATE_NEW; 651 updateStateMachine(STATE_INPUT_START_ANIMATION, 0); 652 break; 653 case STATE_PAUSED_WAIT_RESPONSE: 654 case STATE_PAUSED_RUN: 655 // We treat these two cases the same. The only difference is that, when we are in the WAIT_RESPONSE 656 // state, we don't yet have a valid startTime, so we send 0 to startAnimation. When the START_TIME 657 // event comes in qnd we were in the RUN state, we will notice that we have already set the 658 // startTime and will ignore it. 659 ASSERT(input == STATE_INPUT_PLAY_STATE_RUNNING); 660 ASSERT(!running()); 661 // Update the times 662 if (m_animState == STATE_PAUSED_RUN) 663 m_startTime += currentTime() - m_pauseTime; 664 else 665 m_startTime = 0; 666 m_pauseTime = -1; 667 668 // We were waiting for a begin time response from the animation, go back and wait again 669 m_animState = STATE_START_WAIT_RESPONSE; 670 671 // Start the animation 672 if (overridden() || !startAnimation(m_startTime)) { 673 // We're not going to get a startTime callback, so fire the start time here 674 updateStateMachine(STATE_INPUT_START_TIME_SET, currentTime()); 675 } 676 else 677 m_waitedForResponse = true; 678 break; 679 case STATE_DONE: 680 // We're done. Stay in this state until we are deleted 681 break; 682 } 683 // |this| may be deleted here if we came out of STATE_ENDING when we've been called from timerFired() 684 } 685 686 void AnimationBase::animationTimerCallbackFired(const AtomicString& eventType, double elapsedTime) 687 { 688 ASSERT(m_object->document() && !m_object->document()->inPageCache()); 689 690 // FIXME: use an enum 691 if (eventType == EventNames::webkitAnimationStartEvent) 692 updateStateMachine(STATE_INPUT_START_TIMER_FIRED, elapsedTime); 693 else if (eventType == EventNames::webkitAnimationIterationEvent) 694 updateStateMachine(STATE_INPUT_LOOP_TIMER_FIRED, elapsedTime); 695 else if (eventType == EventNames::webkitAnimationEndEvent) { 696 updateStateMachine(STATE_INPUT_END_TIMER_FIRED, elapsedTime); 697 // |this| may be deleted here 698 } 699 } 700 701 void AnimationBase::animationEventDispatcherFired(Element* element, const AtomicString& name, int property, 702 bool reset, const AtomicString& eventType, double elapsedTime) 703 { 704 m_waitingForEndEvent = false; 705 706 // Keep an atomic string on the stack to keep it alive until we exit this method 707 // (since dispatching the event may cause |this| to be deleted, therefore removing 708 // the last ref to the atomic string). 709 AtomicString animName(name); 710 AtomicString animEventType(eventType); 711 // Make sure the element sticks around too 712 RefPtr<Element> elementRetainer(element); 713 714 ASSERT(!element || (element->document() && !element->document()->inPageCache())); 715 if (!element) 716 return; 717 } 718 719 void AnimationBase::updatePlayState(bool run) 720 { 721 if (paused() == run || isnew()) 722 updateStateMachine(run ? STATE_INPUT_PLAY_STATE_RUNNING : STATE_INPUT_PLAY_STATE_PAUSED, -1); 723 } 724 725 double AnimationBase::progress(double scale, double offset) const 726 { 727 if (preactive()) 728 return 0; 729 730 double elapsedTime = running() ? (currentTime() - m_startTime) : (m_pauseTime - m_startTime); 731 if (running() && elapsedTime < 0) 732 return 0; 733 734 double dur = m_animation->duration(); 735 736 if (postactive() || !m_animation->duration() || elapsedTime >= dur) 178 737 return 1.0; 179 180 if (m_function.type() == LinearTimingFunction) 181 return elapsedTime / m_duration; 738 739 // Compute the fractional time, taking into account direction. 740 // There is no need to worry about iterations, we assume that we would have 741 // short circuited above if we were done 742 double t = elapsedTime / m_animation->duration(); 743 int i = (int) t; 744 t -= i; 745 746 if (scale != 1 || offset != 0) 747 t = (t - offset) * scale; 748 749 if (m_animation->timingFunction().type() == LinearTimingFunction) 750 return t; 182 751 183 752 // Cubic bezier. 184 return solveCubicBezierFunction(m_function.x1(), m_function.y1(), 185 m_function.x2(), m_function.y2(), 186 elapsedTime / m_duration, m_duration); 753 double tt = solveCubicBezierFunction(m_animation->timingFunction().x1(), 754 m_animation->timingFunction().y1(), 755 m_animation->timingFunction().x2(), 756 m_animation->timingFunction().y2(), 757 t, m_animation->duration()); 758 return tt; 759 } 760 761 void AnimationBase::primeEventTimers() 762 { 763 // Decide when the end or loop event needs to fire 764 double ct = currentTime(); 765 const double elapsedDuration = ct - m_startTime; 766 ASSERT(elapsedDuration >= 0); 767 768 double totalDuration = m_animation->duration(); 769 double durationLeft = 0; 770 double nextIterationTime = totalDuration; 771 if (totalDuration < 0 || elapsedDuration < totalDuration) { 772 durationLeft = m_animation->duration() - fmod(elapsedDuration, m_animation->duration()); 773 nextIterationTime = elapsedDuration + durationLeft; 774 } 775 776 // At this point, we may have 0 durationLeft, if we've gotten the event late and we are already 777 // past totalDuration. In this case we still fire an end timer before processing the end. 778 // This defers the call to sendAnimationEvents to avoid re-entrant calls that destroy 779 // the RenderObject, and therefore |this| before we're done with it. 780 if (totalDuration < 0 || nextIterationTime < totalDuration) { 781 // We are not at the end yet, send a loop event 782 ASSERT(nextIterationTime > 0); 783 m_animState = STATE_LOOPING; 784 m_animationTimerCallback.startTimer(durationLeft, EventNames::webkitAnimationIterationEvent, nextIterationTime); 785 } 786 else { 787 // We are at the end, send an end event 788 m_animState = STATE_ENDING; 789 m_animationTimerCallback.startTimer(durationLeft, EventNames::webkitAnimationEndEvent, nextIterationTime); 790 } 187 791 } 188 792 … … 224 828 { 225 829 ASSERT(from && to); 226 return new ShadowData(blendFunc(from->x, to->x, progress), blendFunc(from->y, to->y, progress), blendFunc(from->blur, to->blur, progress), blendFunc(from->color, to->color, progress)); 830 return new ShadowData(blendFunc(from->x, to->x, progress), blendFunc(from->y, to->y, progress), 831 blendFunc(from->blur, to->blur, progress), blendFunc(from->color, to->color, progress)); 227 832 } 228 833 … … 238 843 TransformOperation* toOp = i < toSize ? to[i].get() : 0; 239 844 TransformOperation* blendedOp = toOp ? toOp->blend(fromOp, progress) : fromOp->blend(0, progress, true); 240 result.append(blendedOp); 845 if (blendedOp) 846 result.append(blendedOp); 241 847 } 242 848 return result; … … 255 861 } 256 862 257 #define BLEND(prop, getter, setter) \ 258 if (m_property == prop && m_toStyle->getter() != targetStyle->getter()) {\ 259 reset(renderer, currentStyle, targetStyle); \ 260 if (stale()) \ 261 return; \ 262 } \ 263 if (m_property == cAnimateAll || m_property == prop) { \ 264 if (m_fromStyle->getter() != m_toStyle->getter()) {\ 265 setFinished(false); \ 266 if (!animatedStyle) \ 267 animatedStyle = new (renderer->renderArena()) RenderStyle(*targetStyle); \ 268 animatedStyle->setter(blendFunc(m_fromStyle->getter(), m_toStyle->getter(), progress()));\ 269 if (m_property == prop) \ 270 return; \ 271 }\ 272 }\ 273 274 #define BLEND_MAYBE_INVALID_COLOR(prop, getter, setter) \ 275 if (m_property == prop && m_toStyle->getter() != targetStyle->getter()) { \ 276 reset(renderer, currentStyle, targetStyle); \ 277 if (stale()) \ 278 return; \ 279 } \ 280 if (m_property == cAnimateAll || m_property == prop) { \ 281 Color fromColor = m_fromStyle->getter(); \ 282 Color toColor = m_toStyle->getter(); \ 283 if (fromColor.isValid() || toColor.isValid()) { \ 284 if (!fromColor.isValid()) \ 285 fromColor = m_fromStyle->color(); \ 286 if (!toColor.isValid()) \ 287 toColor = m_toStyle->color(); \ 288 if (fromColor != toColor) {\ 289 setFinished(false); \ 290 if (!animatedStyle) \ 291 animatedStyle = new (renderer->renderArena()) RenderStyle(*targetStyle); \ 292 animatedStyle->setter(blendFunc(fromColor, toColor, progress()));\ 293 if (m_property == prop) \ 294 return; \ 295 }\ 296 }\ 297 }\ 298 299 #define BLEND_SHADOW(prop, getter, setter) \ 300 if (m_property == prop && (!m_toStyle->getter() || !targetStyle->getter() || *m_toStyle->getter() != *targetStyle->getter())) { \ 301 reset(renderer, currentStyle, targetStyle); \ 302 if (stale()) \ 303 return; \ 304 } \ 305 if (m_property == cAnimateAll || m_property == prop) { \ 306 if (m_fromStyle->getter() && m_toStyle->getter() && *m_fromStyle->getter() != *m_toStyle->getter()) {\ 307 setFinished(false); \ 308 if (!animatedStyle) \ 309 animatedStyle = new (renderer->renderArena()) RenderStyle(*targetStyle); \ 310 animatedStyle->setter(blendFunc(m_fromStyle->getter(), m_toStyle->getter(), progress()));\ 311 if (m_property == prop) \ 312 return; \ 313 }\ 314 } 315 316 void ImplicitAnimation::animate(CompositeImplicitAnimation* animation, RenderObject* renderer, RenderStyle* currentStyle, RenderStyle* targetStyle, RenderStyle*& animatedStyle) 317 { 318 // FIXME: If we have no transition-property, then the only way to tell if our goal state changed is to check 319 // every single animatable property. For now we'll just diff the styles to ask that question, 320 // but we should really exclude non-animatable properties. 321 if (!m_toStyle || (m_property == cAnimateAll && targetStyle->diff(m_toStyle))) { 322 reset(renderer, currentStyle, targetStyle); 323 if (stale()) 324 return; 325 } 326 327 // FIXME: Blow up shorthands so that they can be honored. 328 setFinished(true); 329 BLEND(CSSPropertyLeft, left, setLeft); 330 BLEND(CSSPropertyRight, right, setRight); 331 BLEND(CSSPropertyTop, top, setTop); 332 BLEND(CSSPropertyBottom, bottom, setBottom); 333 BLEND(CSSPropertyWidth, width, setWidth); 334 BLEND(CSSPropertyHeight, height, setHeight); 335 BLEND(CSSPropertyBorderLeftWidth, borderLeftWidth, setBorderLeftWidth); 336 BLEND(CSSPropertyBorderRightWidth, borderRightWidth, setBorderRightWidth); 337 BLEND(CSSPropertyBorderTopWidth, borderTopWidth, setBorderTopWidth); 338 BLEND(CSSPropertyBorderBottomWidth, borderBottomWidth, setBorderBottomWidth); 339 BLEND(CSSPropertyMarginLeft, marginLeft, setMarginLeft); 340 BLEND(CSSPropertyMarginRight, marginRight, setMarginRight); 341 BLEND(CSSPropertyMarginTop, marginTop, setMarginTop); 342 BLEND(CSSPropertyMarginBottom, marginBottom, setMarginBottom); 343 BLEND(CSSPropertyPaddingLeft, paddingLeft, setPaddingLeft); 344 BLEND(CSSPropertyPaddingRight, paddingRight, setPaddingRight); 345 BLEND(CSSPropertyPaddingTop, paddingTop, setPaddingTop); 346 BLEND(CSSPropertyPaddingBottom, paddingBottom, setPaddingBottom); 347 BLEND(CSSPropertyOpacity, opacity, setOpacity); 348 BLEND(CSSPropertyColor, color, setColor); 349 BLEND(CSSPropertyBackgroundColor, backgroundColor, setBackgroundColor); 350 BLEND_MAYBE_INVALID_COLOR(CSSPropertyWebkitColumnRuleColor, columnRuleColor, setColumnRuleColor); 351 BLEND(CSSPropertyWebkitColumnRuleWidth, columnRuleWidth, setColumnRuleWidth); 352 BLEND(CSSPropertyWebkitColumnGap, columnGap, setColumnGap); 353 BLEND(CSSPropertyWebkitColumnCount, columnCount, setColumnCount); 354 BLEND(CSSPropertyWebkitColumnWidth, columnWidth, setColumnWidth); 355 BLEND_MAYBE_INVALID_COLOR(CSSPropertyWebkitTextStrokeColor, textStrokeColor, setTextStrokeColor); 356 BLEND_MAYBE_INVALID_COLOR(CSSPropertyWebkitTextFillColor, textFillColor, setTextFillColor); 357 BLEND(CSSPropertyWebkitBorderHorizontalSpacing, horizontalBorderSpacing, setHorizontalBorderSpacing); 358 BLEND(CSSPropertyWebkitBorderVerticalSpacing, verticalBorderSpacing, setVerticalBorderSpacing); 359 BLEND_MAYBE_INVALID_COLOR(CSSPropertyBorderLeftColor, borderLeftColor, setBorderLeftColor); 360 BLEND_MAYBE_INVALID_COLOR(CSSPropertyBorderRightColor, borderRightColor, setBorderRightColor); 361 BLEND_MAYBE_INVALID_COLOR(CSSPropertyBorderTopColor, borderTopColor, setBorderTopColor); 362 BLEND_MAYBE_INVALID_COLOR(CSSPropertyBorderBottomColor, borderBottomColor, setBorderBottomColor); 363 BLEND(CSSPropertyZIndex, zIndex, setZIndex); 364 BLEND(CSSPropertyLineHeight, lineHeight, setLineHeight); 365 BLEND_MAYBE_INVALID_COLOR(CSSPropertyOutlineColor, outlineColor, setOutlineColor); 366 BLEND(CSSPropertyOutlineOffset, outlineOffset, setOutlineOffset); 367 BLEND(CSSPropertyOutlineWidth, outlineWidth, setOutlineWidth); 368 BLEND(CSSPropertyLetterSpacing, letterSpacing, setLetterSpacing); 369 BLEND(CSSPropertyWordSpacing, wordSpacing, setWordSpacing); 370 BLEND_SHADOW(CSSPropertyWebkitBoxShadow, boxShadow, setBoxShadow); 371 BLEND_SHADOW(CSSPropertyTextShadow, textShadow, setTextShadow); 372 BLEND(CSSPropertyWebkitTransform, transform, setTransform); 373 BLEND(CSSPropertyWebkitTransformOriginX, transformOriginX, setTransformOriginX); 374 BLEND(CSSPropertyWebkitTransformOriginY, transformOriginY, setTransformOriginY); 375 BLEND(CSSPropertyWebkitBorderTopLeftRadius, borderTopLeftRadius, setBorderTopLeftRadius); 376 BLEND(CSSPropertyWebkitBorderTopRightRadius, borderTopRightRadius, setBorderTopRightRadius); 377 BLEND(CSSPropertyWebkitBorderBottomLeftRadius, borderBottomLeftRadius, setBorderBottomLeftRadius); 378 BLEND(CSSPropertyWebkitBorderBottomRightRadius, borderBottomRightRadius, setBorderBottomRightRadius); 379 BLEND(CSSPropertyVisibility, visibility, setVisibility); 380 BLEND(CSSPropertyZoom, zoom, setZoom); 381 } 382 383 RenderStyle* CompositeImplicitAnimation::animate(RenderObject* renderer, RenderStyle* currentStyle, RenderStyle* targetStyle) 384 { 385 const Transition* currentTransitions = currentStyle->transitions(); 386 const Transition* targetTransitions = targetStyle->transitions(); 387 bool transitionsChanged = m_animations.isEmpty() || (currentTransitions != targetTransitions && !(currentTransitions && targetTransitions && *currentTransitions == *targetTransitions)); 388 389 if (transitionsChanged) { 390 HashMap<int, ImplicitAnimation*>::iterator end = m_animations.end(); 391 392 for (HashMap<int, ImplicitAnimation*>::iterator it = m_animations.begin(); it != end; ++it) 393 // Mark any running animations as stale if the set of transitions changed. Stale animations continue 394 // to blend on a timer, and then remove themselves when finished. 395 it->second->setStale(); 396 397 // If our transitions changed we need to add new animations for any transitions that 398 // don't exist yet. If a new transition conflicts with a currently running stale transition, then we will not add it. 399 // The stale transition is responsible for updating itself to the new transition if it ever gets reset or finishes. 400 for (const Transition* transition = targetTransitions; transition; transition = transition->next()) { 401 int property = transition->property(); 402 int duration = transition->duration(); 403 int repeatCount = transition->repeatCount(); 404 if (property && duration && repeatCount && !m_animations.contains(property)) { 405 ImplicitAnimation* animation = new ImplicitAnimation(transition); 406 m_animations.set(property, animation); 407 } 408 } 409 } 410 411 // Now that we have animation objects ready, let them know about the new goal state. We want them 412 // to fill in a RenderStyle*& only if needed. 413 RenderStyle* result = 0; 414 HashMap<int, ImplicitAnimation*>::iterator end = m_animations.end(); 415 Vector<int> obsoleteTransitions; 416 417 // Look at the "all" animation first. 418 ImplicitAnimation* allAnimation = m_animations.get(cAnimateAll); 419 if (allAnimation) { 420 allAnimation->animate(this, renderer, currentStyle, targetStyle, result); 421 422 // If the animation is done and we are marked as stale, then we can be removed after the 423 // iteration of the hashmap is finished. 424 if (allAnimation->finished() && allAnimation->stale()) 425 obsoleteTransitions.append(cAnimateAll); 426 } 427 428 // Now look at the specialized animations. 429 for (HashMap<int, ImplicitAnimation*>::iterator it = m_animations.begin(); it != end; ++it) { 430 // Skip over the "all" animation, since we animated it already. 431 if (it->second->property() == cAnimateAll) 432 continue; 863 class PropertyWrapperBase { 864 public: 865 PropertyWrapperBase(int prop) 866 : m_prop(prop) 867 { } 868 virtual ~PropertyWrapperBase() { } 869 virtual bool equals(const RenderStyle* a, const RenderStyle* b) const=0; 870 virtual void blend(RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double prog) const=0; 871 872 int property() const { return m_prop; } 873 874 private: 875 int m_prop; 876 }; 877 878 template <typename T> 879 class PropertyWrapperGetter : public PropertyWrapperBase { 880 public: 881 PropertyWrapperGetter(int prop, T (RenderStyle::*getter)() const) 882 : PropertyWrapperBase(prop) 883 , m_getter(getter) 884 { } 885 886 virtual bool equals(const RenderStyle* a, const RenderStyle* b) const 887 { 888 return (a->*m_getter)() == (b->*m_getter)(); 889 } 890 891 protected: 892 T (RenderStyle::*m_getter)() const; 893 }; 894 895 template <typename T> 896 class PropertyWrapper : public PropertyWrapperGetter<T> { 897 public: 898 PropertyWrapper(int prop, T (RenderStyle::*getter)() const, void (RenderStyle::*setter)(T)) 899 : PropertyWrapperGetter<T>(prop, getter) 900 , m_setter(setter) 901 { } 902 903 virtual void blend(RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double prog) const 904 { 905 (dst->*m_setter)(blendFunc((a->*PropertyWrapperGetter<T>::m_getter)(), (b->*PropertyWrapperGetter<T>::m_getter)(), prog)); 906 } 907 908 protected: 909 void (RenderStyle::*m_setter)(T); 910 }; 911 912 class PropertyWrapperShadow : public PropertyWrapperGetter<ShadowData*> { 913 public: 914 PropertyWrapperShadow(int prop, ShadowData* (RenderStyle::*getter)() const, void (RenderStyle::*setter)(ShadowData*, bool)) 915 : PropertyWrapperGetter<ShadowData*>(prop, getter) 916 , m_setter(setter) 917 { } 918 919 virtual bool equals(const RenderStyle* a, const RenderStyle* b) const 920 { 921 ShadowData* shadowa = (a->*m_getter)(); 922 ShadowData* shadowb = (b->*m_getter)(); 433 923 434 it->second->animate(this, renderer, currentStyle, targetStyle, result); 435 436 // If the animation is done and we are marked as stale, then we can be removed after the 437 // iteration of the hashmap is finished. 438 if (it->second->finished() && it->second->stale()) 439 obsoleteTransitions.append(it->second->property()); 440 441 } 442 443 // Now cull out any stale animations that are finished. 444 for (unsigned i = 0; i < obsoleteTransitions.size(); ++i) { 445 ImplicitAnimation* animation = m_animations.take(obsoleteTransitions[i]); 446 animation->reset(renderer, 0, 0); 447 delete animation; 448 } 449 450 if (result) 451 return result; 452 453 return targetStyle; 454 } 455 456 bool CompositeImplicitAnimation::animating() const 457 { 458 HashMap<int, ImplicitAnimation*>::const_iterator end = m_animations.end(); 459 for (HashMap<int, ImplicitAnimation*>::const_iterator it = m_animations.begin(); it != end; ++it) 460 if (!it->second->finished()) 461 return true; 462 return false; 463 } 464 465 void CompositeImplicitAnimation::reset(RenderObject* renderer) 466 { 467 HashMap<int, ImplicitAnimation*>::const_iterator end = m_animations.end(); 468 for (HashMap<int, ImplicitAnimation*>::const_iterator it = m_animations.begin(); it != end; ++it) 469 it->second->reset(renderer, 0, 0); 470 } 924 if (!shadowa && shadowb || shadowa && !shadowb) 925 return false; 926 if (shadowa && shadowb && (*shadowa != *shadowb)) 927 return false; 928 return true; 929 } 930 931 virtual void blend(RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double prog) const 932 { 933 ShadowData* shadowa = (a->*m_getter)(); 934 ShadowData* shadowb = (b->*m_getter)(); 935 ShadowData defaultShadowData(0, 0, 0, Color::transparent); 936 937 if (!shadowa) 938 shadowa = &defaultShadowData; 939 if (!shadowb) 940 shadowb = &defaultShadowData; 941 942 (dst->*m_setter)(blendFunc(shadowa, shadowb, prog), false); 943 } 944 945 private: 946 void (RenderStyle::*m_setter)(ShadowData*, bool); 947 }; 948 949 class PropertyWrapperIntSize : public PropertyWrapperGetter<IntSize> { 950 public: 951 PropertyWrapperIntSize(int prop, IntSize (RenderStyle::*getter)() const, void (RenderStyle::*setter)(const IntSize&)) 952 : PropertyWrapperGetter<IntSize>(prop, getter) 953 , m_setter(setter) 954 { } 955 956 virtual bool equals(const RenderStyle* a, const RenderStyle* b) const 957 { 958 IntSize sizea = (a->*m_getter)(); 959 IntSize sizeb = (b->*m_getter)(); 960 961 return (sizea == sizeb); 962 } 963 964 virtual void blend(RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double prog) const 965 { 966 IntSize sizea = (a->*m_getter)(); 967 IntSize sizeb = (b->*m_getter)(); 968 969 (dst->*m_setter)(blendFunc(sizea, sizeb, prog)); 970 } 971 972 private: 973 void (RenderStyle::*m_setter)(const IntSize&); 974 }; 975 976 class PropertyWrapperMaybeInvalidColor : public PropertyWrapperBase { 977 public: 978 PropertyWrapperMaybeInvalidColor(int prop, const Color& (RenderStyle::*getter)() const, void (RenderStyle::*setter)(const Color&)) 979 : PropertyWrapperBase(prop) 980 , m_getter(getter) 981 , m_setter(setter) 982 { } 983 984 virtual bool equals(const RenderStyle* a, const RenderStyle* b) const 985 { 986 Color fromColor = (a->*m_getter)(); 987 Color toColor = (b->*m_getter)(); 988 if (!fromColor.isValid()) 989 fromColor = a->color(); 990 if (!toColor.isValid()) 991 toColor = b->color(); 992 993 return fromColor == toColor; 994 } 995 996 virtual void blend(RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double prog) const 997 { 998 Color fromColor = (a->*m_getter)(); 999 Color toColor = (b->*m_getter)(); 1000 if (!fromColor.isValid()) 1001 fromColor = a->color(); 1002 if (!toColor.isValid()) 1003 toColor = b->color(); 1004 (dst->*m_setter)(blendFunc(fromColor, toColor, prog)); 1005 } 1006 1007 private: 1008 const Color& (RenderStyle::*m_getter)() const; 1009 void (RenderStyle::*m_setter)(const Color&); 1010 }; 471 1011 472 1012 class AnimationControllerPrivate { … … 474 1014 AnimationControllerPrivate(Frame*); 475 1015 ~AnimationControllerPrivate(); 476 477 Composite ImplicitAnimation* get(RenderObject*, RenderStyle*);1016 1017 CompositeAnimation* accessCompositeAnimation(RenderObject*); 478 1018 bool clear(RenderObject*); 479 1019 480 void timerFired(Timer<AnimationControllerPrivate>*); 481 void updateTimer(); 482 483 bool hasImplicitAnimations() const { return !m_animations.isEmpty(); } 484 1020 void animationTimerFired(Timer<AnimationControllerPrivate>*); 1021 void updateAnimationTimer(); 1022 1023 void updateRenderingDispatcherFired(Timer<AnimationControllerPrivate>*); 1024 void startUpdateRenderingDispatcher(); 1025 1026 bool hasAnimations() const { return !m_compositeAnimations.isEmpty(); } 1027 1028 void suspendAnimations(Document* document); 1029 void resumeAnimations(Document* document); 1030 1031 void styleAvailable(); 1032 1033 bool isAnimatingPropertyOnRenderer(RenderObject* obj, int property) const; 1034 1035 static bool propertiesEqual(int prop, const RenderStyle* a, const RenderStyle* b); 1036 static int getPropertyAtIndex(int i); 1037 static int getNumProperties() { return gPropertyWrappers->size(); } 1038 1039 // Return true if we need to start software animation timers 1040 static bool blendProperties(int prop, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double prog); 1041 1042 void setWaitingForStyleAvailable(bool waiting) { if (waiting) m_numStyleAvailableWaiters++; else m_numStyleAvailableWaiters--; } 1043 485 1044 private: 486 HashMap<RenderObject*, CompositeImplicitAnimation*> m_animations; 487 Timer<AnimationControllerPrivate> m_timer; 1045 static void ensurePropertyMap(); 1046 1047 typedef HashMap<RenderObject*, CompositeAnimation*> RenderObjectAnimationMap; 1048 1049 RenderObjectAnimationMap m_compositeAnimations; 1050 Timer<AnimationControllerPrivate> m_animationTimer; 1051 Timer<AnimationControllerPrivate> m_updateRenderingDispatcher; 488 1052 Frame* m_frame; 1053 uint32_t m_numStyleAvailableWaiters; 1054 1055 static Vector<PropertyWrapperBase*>* gPropertyWrappers; 1056 static int gPropertyWrapperMap[numCSSProperties]; 489 1057 }; 490 1058 1059 Vector<PropertyWrapperBase*>* AnimationControllerPrivate::gPropertyWrappers = 0; 1060 int AnimationControllerPrivate::gPropertyWrapperMap[]; 1061 491 1062 AnimationControllerPrivate::AnimationControllerPrivate(Frame* frame) 492 : m_timer(this, &AnimationControllerPrivate::timerFired) 493 , m_frame(frame) 494 { 1063 : m_animationTimer(this, &AnimationControllerPrivate::animationTimerFired) 1064 , m_updateRenderingDispatcher(this, &AnimationControllerPrivate::updateRenderingDispatcherFired) 1065 , m_frame(frame) 1066 , m_numStyleAvailableWaiters(0) 1067 { 1068 ensurePropertyMap(); 495 1069 } 496 1070 497 1071 AnimationControllerPrivate::~AnimationControllerPrivate() 498 1072 { 499 deleteAllValues(m_animations); 500 } 501 502 CompositeImplicitAnimation* AnimationControllerPrivate::get(RenderObject* renderer, RenderStyle* targetStyle) 503 { 504 CompositeImplicitAnimation* animation = m_animations.get(renderer); 505 if (!animation && targetStyle->transitions()) { 506 animation = new CompositeImplicitAnimation(); 507 m_animations.set(renderer, animation); 1073 deleteAllValues(m_compositeAnimations); 1074 } 1075 1076 // static 1077 void AnimationControllerPrivate::ensurePropertyMap() 1078 { 1079 // FIXME: This data is never destroyed. Maybe we should ref count it and toss it when the last AnimationController is destroyed? 1080 if (gPropertyWrappers == 0) { 1081 gPropertyWrappers = new Vector<PropertyWrapperBase*>(); 1082 1083 // build the list of property wrappers to do the comparisons and blends 1084 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyLeft, &RenderStyle::left, &RenderStyle::setLeft)); 1085 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyRight, &RenderStyle::right, &RenderStyle::setRight)); 1086 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyTop, &RenderStyle::top, &RenderStyle::setTop)); 1087 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyBottom, &RenderStyle::bottom, &RenderStyle::setBottom)); 1088 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyWidth, &RenderStyle::width, &RenderStyle::setWidth)); 1089 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyHeight, &RenderStyle::height, &RenderStyle::setHeight)); 1090 gPropertyWrappers->append(new PropertyWrapper<unsigned short>(CSSPropertyBorderLeftWidth, &RenderStyle::borderLeftWidth, &RenderStyle::setBorderLeftWidth)); 1091 gPropertyWrappers->append(new PropertyWrapper<unsigned short>(CSSPropertyBorderRightWidth, &RenderStyle::borderRightWidth, &RenderStyle::setBorderRightWidth)); 1092 gPropertyWrappers->append(new PropertyWrapper<unsigned short>(CSSPropertyBorderTopWidth, &RenderStyle::borderTopWidth, &RenderStyle::setBorderTopWidth)); 1093 gPropertyWrappers->append(new PropertyWrapper<unsigned short>(CSSPropertyBorderBottomWidth, &RenderStyle::borderBottomWidth, &RenderStyle::setBorderBottomWidth)); 1094 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMarginLeft, &RenderStyle::marginLeft, &RenderStyle::setMarginLeft)); 1095 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMarginRight, &RenderStyle::marginRight, &RenderStyle::setMarginRight)); 1096 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMarginTop, &RenderStyle::marginTop, &RenderStyle::setMarginTop)); 1097 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMarginBottom, &RenderStyle::marginBottom, &RenderStyle::setMarginBottom)); 1098 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyPaddingLeft, &RenderStyle::paddingLeft, &RenderStyle::setPaddingLeft)); 1099 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyPaddingRight, &RenderStyle::paddingRight, &RenderStyle::setPaddingRight)); 1100 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyPaddingTop, &RenderStyle::paddingTop, &RenderStyle::setPaddingTop)); 1101 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyPaddingBottom, &RenderStyle::paddingBottom, &RenderStyle::setPaddingBottom)); 1102 gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyOpacity, &RenderStyle::opacity, &RenderStyle::setOpacity)); 1103 gPropertyWrappers->append(new PropertyWrapper<const Color&>(CSSPropertyColor, &RenderStyle::color, &RenderStyle::setColor)); 1104 gPropertyWrappers->append(new PropertyWrapper<const Color&>(CSSPropertyBackgroundColor, &RenderStyle::backgroundColor, &RenderStyle::setBackgroundColor)); 1105 gPropertyWrappers->append(new PropertyWrapper<unsigned short>(CSSPropertyWebkitColumnRuleWidth, &RenderStyle::columnRuleWidth, &RenderStyle::setColumnRuleWidth)); 1106 gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyWebkitColumnGap, &RenderStyle::columnGap, &RenderStyle::setColumnGap)); 1107 gPropertyWrappers->append(new PropertyWrapper<unsigned short>(CSSPropertyWebkitColumnCount, &RenderStyle::columnCount, &RenderStyle::setColumnCount)); 1108 gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyWebkitColumnWidth, &RenderStyle::columnWidth, &RenderStyle::setColumnWidth)); 1109 gPropertyWrappers->append(new PropertyWrapper<short>(CSSPropertyWebkitBorderHorizontalSpacing, &RenderStyle::horizontalBorderSpacing, &RenderStyle::setHorizontalBorderSpacing)); 1110 gPropertyWrappers->append(new PropertyWrapper<short>(CSSPropertyWebkitBorderVerticalSpacing, &RenderStyle::verticalBorderSpacing, &RenderStyle::setVerticalBorderSpacing)); 1111 gPropertyWrappers->append(new PropertyWrapper<int>(CSSPropertyZIndex, &RenderStyle::zIndex, &RenderStyle::setZIndex)); 1112 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyLineHeight, &RenderStyle::lineHeight, &RenderStyle::setLineHeight)); 1113 gPropertyWrappers->append(new PropertyWrapper<int>(CSSPropertyOutlineOffset, &RenderStyle::outlineOffset, &RenderStyle::setOutlineOffset)); 1114 gPropertyWrappers->append(new PropertyWrapper<unsigned short>(CSSPropertyOutlineWidth, &RenderStyle::outlineWidth, &RenderStyle::setOutlineWidth)); 1115 gPropertyWrappers->append(new PropertyWrapper<int>(CSSPropertyLetterSpacing, &RenderStyle::letterSpacing, &RenderStyle::setLetterSpacing)); 1116 gPropertyWrappers->append(new PropertyWrapper<int>(CSSPropertyWordSpacing, &RenderStyle::wordSpacing, &RenderStyle::setWordSpacing)); 1117 gPropertyWrappers->append(new PropertyWrapper<const TransformOperations&>(CSSPropertyWebkitTransform, &RenderStyle::transform, &RenderStyle::setTransform)); 1118 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyWebkitTransformOriginX, &RenderStyle::transformOriginX, &RenderStyle::setTransformOriginX)); 1119 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyWebkitTransformOriginY, &RenderStyle::transformOriginY, &RenderStyle::setTransformOriginY)); 1120 gPropertyWrappers->append(new PropertyWrapperIntSize(CSSPropertyWebkitBorderTopLeftRadius, &RenderStyle::borderTopLeftRadius, &RenderStyle::setBorderTopLeftRadius)); 1121 gPropertyWrappers->append(new PropertyWrapperIntSize(CSSPropertyWebkitBorderTopRightRadius, &RenderStyle::borderTopRightRadius, &RenderStyle::setBorderTopRightRadius)); 1122 gPropertyWrappers->append(new PropertyWrapperIntSize(CSSPropertyWebkitBorderBottomLeftRadius, &RenderStyle::borderBottomLeftRadius, &RenderStyle::setBorderBottomLeftRadius)); 1123 gPropertyWrappers->append(new PropertyWrapperIntSize(CSSPropertyWebkitBorderBottomRightRadius, &RenderStyle::borderBottomRightRadius, &RenderStyle::setBorderBottomRightRadius)); 1124 gPropertyWrappers->append(new PropertyWrapper<EVisibility>(CSSPropertyVisibility, &RenderStyle::visibility, &RenderStyle::setVisibility)); 1125 gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyZoom, &RenderStyle::zoom, &RenderStyle::setZoom)); 1126 1127 // FIXME: these might be invalid colors, need to check for that 1128 gPropertyWrappers->append(new PropertyWrapperMaybeInvalidColor(CSSPropertyWebkitColumnRuleColor, &RenderStyle::columnRuleColor, &RenderStyle::setColumnRuleColor)); 1129 gPropertyWrappers->append(new PropertyWrapperMaybeInvalidColor(CSSPropertyWebkitTextStrokeColor, &RenderStyle::textStrokeColor, &RenderStyle::setTextStrokeColor)); 1130 gPropertyWrappers->append(new PropertyWrapperMaybeInvalidColor(CSSPropertyWebkitTextFillColor, &RenderStyle::textFillColor, &RenderStyle::setTextFillColor)); 1131 gPropertyWrappers->append(new PropertyWrapperMaybeInvalidColor(CSSPropertyBorderLeftColor, &RenderStyle::borderLeftColor, &RenderStyle::setBorderLeftColor)); 1132 gPropertyWrappers->append(new PropertyWrapperMaybeInvalidColor(CSSPropertyBorderRightColor, &RenderStyle::borderRightColor, &RenderStyle::setBorderRightColor)); 1133 gPropertyWrappers->append(new PropertyWrapperMaybeInvalidColor(CSSPropertyBorderTopColor, &RenderStyle::borderTopColor, &RenderStyle::setBorderTopColor)); 1134 gPropertyWrappers->append(new PropertyWrapperMaybeInvalidColor(CSSPropertyBorderBottomColor, &RenderStyle::borderBottomColor, &RenderStyle::setBorderBottomColor)); 1135 gPropertyWrappers->append(new PropertyWrapperMaybeInvalidColor(CSSPropertyOutlineColor, &RenderStyle::outlineColor, &RenderStyle::setOutlineColor)); 1136 1137 // These are for shadows 1138 gPropertyWrappers->append(new PropertyWrapperShadow(CSSPropertyWebkitBoxShadow, &RenderStyle::boxShadow, &RenderStyle::setBoxShadow)); 1139 gPropertyWrappers->append(new PropertyWrapperShadow(CSSPropertyTextShadow, &RenderStyle::textShadow, &RenderStyle::setTextShadow)); 1140 1141 // Make sure unused slots have a value 1142 for (unsigned int i = 0; i < (unsigned int) numCSSProperties; ++i) 1143 gPropertyWrapperMap[i] = CSSPropertyInvalid; 1144 1145 size_t n = gPropertyWrappers->size(); 1146 for (unsigned int i = 0; i < n; ++i) { 1147 ASSERT((*gPropertyWrappers)[i]->property() - firstCSSProperty < numCSSProperties); 1148 gPropertyWrapperMap[(*gPropertyWrappers)[i]->property() - firstCSSProperty] = i; 1149 } 1150 } 1151 } 1152 1153 // static 1154 bool AnimationControllerPrivate::propertiesEqual(int prop, const RenderStyle* a, const RenderStyle* b) 1155 { 1156 if (prop == cAnimateAll) { 1157 size_t n = gPropertyWrappers->size(); 1158 for (unsigned int i = 0; i < n; ++i) { 1159 if (!(*gPropertyWrappers)[i]->equals(a, b)) 1160 return false; 1161 } 1162 } 1163 else { 1164 int propIndex = prop - firstCSSProperty; 1165 1166 if (propIndex >= 0 && propIndex < numCSSProperties) { 1167 int i = gPropertyWrapperMap[propIndex]; 1168 return (i >= 0) ? (*gPropertyWrappers)[i]->equals(a, b) : true; 1169 } 1170 } 1171 return true; 1172 } 1173 1174 // static 1175 int AnimationControllerPrivate::getPropertyAtIndex(int i) 1176 { 1177 if (i < 0 || i >= (int) gPropertyWrappers->size()) 1178 return CSSPropertyInvalid; 1179 1180 return (*gPropertyWrappers)[i]->property(); 1181 } 1182 1183 // static - return true if we need to start software animation timers 1184 bool AnimationControllerPrivate::blendProperties(int prop, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double prog) 1185 { 1186 if (prop == cAnimateAll) { 1187 bool needsTimer = false; 1188 1189 size_t n = gPropertyWrappers->size(); 1190 for (unsigned int i = 0; i < n; ++i) { 1191 PropertyWrapperBase* wrapper = (*gPropertyWrappers)[i]; 1192 if (!wrapper->equals(a, b)) { 1193 wrapper->blend(dst, a, b, prog); 1194 needsTimer = true; 1195 } 1196 } 1197 return needsTimer; 1198 } 1199 1200 int propIndex = prop - firstCSSProperty; 1201 if (propIndex >= 0 && propIndex < numCSSProperties) { 1202 int i = gPropertyWrapperMap[propIndex]; 1203 if (i >= 0) { 1204 PropertyWrapperBase* wrapper = (*gPropertyWrappers)[i]; 1205 wrapper->blend(dst, a, b, prog); 1206 return true; 1207 } 1208 } 1209 1210 return false; 1211 } 1212 1213 CompositeAnimation* AnimationControllerPrivate::accessCompositeAnimation(RenderObject* renderer) 1214 { 1215 CompositeAnimation* animation = m_compositeAnimations.get(renderer); 1216 if (!animation) { 1217 animation = new CompositeAnimation(this); 1218 m_compositeAnimations.set(renderer, animation); 508 1219 } 509 1220 return animation; … … 512 1223 bool AnimationControllerPrivate::clear(RenderObject* renderer) 513 1224 { 514 CompositeImplicitAnimation* animation = m_animations.take(renderer); 1225 // Return false if we didn't do anything OR we are suspended (so we don't try to 1226 // do a setChanged() when suspended 1227 CompositeAnimation* animation = m_compositeAnimations.take(renderer); 515 1228 if (!animation) 516 1229 return false; 517 animation->reset(renderer); 1230 animation->resetTransitions(renderer); 1231 bool wasSuspended = animation->suspended(); 518 1232 delete animation; 519 return true; 520 } 521 522 void AnimationControllerPrivate::updateTimer() 1233 return !wasSuspended; 1234 } 1235 1236 void AnimationControllerPrivate::styleAvailable() 1237 { 1238 if (m_numStyleAvailableWaiters == 0) 1239 return; 1240 1241 RenderObjectAnimationMap::const_iterator animationsEnd = m_compositeAnimations.end(); 1242 for (RenderObjectAnimationMap::const_iterator it = m_compositeAnimations.begin(); 1243 it != animationsEnd; ++it) { 1244 it->second->styleAvailable(); 1245 } 1246 } 1247 1248 void AnimationControllerPrivate::updateAnimationTimer() 523 1249 { 524 1250 bool animating = false; 525 HashMap<RenderObject*, CompositeImplicitAnimation*>::iterator end = m_animations.end(); 526 for (HashMap<RenderObject*, CompositeImplicitAnimation*>::iterator it = m_animations.begin(); it != end; ++it) { 527 if (it->second->animating()) { 1251 1252 RenderObjectAnimationMap::const_iterator animationsEnd = m_compositeAnimations.end(); 1253 for (RenderObjectAnimationMap::const_iterator it = m_compositeAnimations.begin(); 1254 it != animationsEnd; ++it) { 1255 CompositeAnimation* compAnim = it->second; 1256 if (!compAnim->suspended() && compAnim->animating()) { 528 1257 animating = true; 529 1258 break; … … 532 1261 533 1262 if (animating) { 534 if (!m_timer.isActive()) 535 m_timer.startRepeating(cAnimationTimerDelay); 536 } else if (m_timer.isActive()) 537 m_timer.stop(); 538 } 539 540 void AnimationControllerPrivate::timerFired(Timer<AnimationControllerPrivate>* timer) 1263 if (!m_animationTimer.isActive()) 1264 m_animationTimer.startRepeating(cAnimationTimerDelay); 1265 } else if (m_animationTimer.isActive()) 1266 m_animationTimer.stop(); 1267 } 1268 1269 void AnimationControllerPrivate::updateRenderingDispatcherFired(Timer<AnimationControllerPrivate>*) 1270 { 1271 if (m_frame && m_frame->document()) { 1272 m_frame->document()->updateRendering(); 1273 } 1274 } 1275 1276 void AnimationControllerPrivate::startUpdateRenderingDispatcher() 1277 { 1278 if (!m_updateRenderingDispatcher.isActive()) { 1279 m_updateRenderingDispatcher.startOneShot(0); 1280 } 1281 } 1282 1283 void AnimationControllerPrivate::animationTimerFired(Timer<AnimationControllerPrivate>* timer) 541 1284 { 542 1285 // When the timer fires, all we do is call setChanged on all DOM nodes with running animations and then do an immediate 543 1286 // updateRendering. It will then call back to us with new information. 544 1287 bool animating = false; 545 HashMap<RenderObject*, CompositeImplicitAnimation*>::iterator end = m_animations.end(); 546 for (HashMap<RenderObject*, CompositeImplicitAnimation*>::iterator it = m_animations.begin(); it != end; ++it) { 547 if (it->second->animating()) { 1288 RenderObjectAnimationMap::const_iterator animationsEnd = m_compositeAnimations.end(); 1289 for (RenderObjectAnimationMap::const_iterator it = m_compositeAnimations.begin(); 1290 it != animationsEnd; ++it) { 1291 RenderObject* renderer = it->first; 1292 CompositeAnimation* compAnim = it->second; 1293 if (!compAnim->suspended() && compAnim->animating()) { 548 1294 animating = true; 549 it->first->element()->setChanged(); 1295 compAnim->setAnimating(false); 1296 setChanged(renderer->element()); 550 1297 } 551 1298 } … … 553 1300 m_frame->document()->updateRendering(); 554 1301 555 updateTimer(); 556 } 1302 updateAnimationTimer(); 1303 } 1304 1305 bool AnimationControllerPrivate::isAnimatingPropertyOnRenderer(RenderObject* obj, int property) const 1306 { 1307 CompositeAnimation* animation = m_compositeAnimations.get(obj); 1308 if (!animation) return false; 1309 1310 return animation->isAnimatingProperty(property); 1311 } 1312 1313 void AnimationControllerPrivate::suspendAnimations(Document* document) 1314 { 1315 RenderObjectAnimationMap::const_iterator animationsEnd = m_compositeAnimations.end(); 1316 for (RenderObjectAnimationMap::const_iterator it = m_compositeAnimations.begin(); 1317 it != animationsEnd; ++it) { 1318 RenderObject* renderer = it->first; 1319 CompositeAnimation* compAnim = it->second; 1320 if (renderer->document() == document) 1321 compAnim->suspendAnimations(); 1322 } 1323 1324 updateAnimationTimer(); 1325 } 1326 1327 void AnimationControllerPrivate::resumeAnimations(Document* document) 1328 { 1329 RenderObjectAnimationMap::const_iterator animationsEnd = m_compositeAnimations.end(); 1330 for (RenderObjectAnimationMap::const_iterator it = m_compositeAnimations.begin(); 1331 it != animationsEnd; ++it) { 1332 RenderObject* renderer = it->first; 1333 CompositeAnimation* compAnim = it->second; 1334 if (renderer->document() == document) 1335 compAnim->resumeAnimations(); 1336 } 1337 1338 updateAnimationTimer(); 1339 } 1340 1341 void CompositeAnimation::updateTransitions(RenderObject* renderer, RenderStyle* currentStyle, RenderStyle* targetStyle) 1342 { 1343 // If currentStyle is null, we don't do transitions 1344 if (!currentStyle || !targetStyle->transitions()) 1345 return; 1346 1347 // Check to see if we need to update the active transitions 1348 for (size_t i = 0; i < targetStyle->transitions()->size(); ++i) { 1349 const Animation* anim = (*targetStyle->transitions())[i].get(); 1350 double duration = anim->duration(); 1351 double delay = anim->delay(); 1352 1353 // If this is an empty transition, skip it 1354 if (duration == 0 && delay <= 0) 1355 continue; 1356 1357 int prop = anim->property(); 1358 bool all = prop == cAnimateAll; 1359 1360 // Handle both the 'all' and single property cases. For the single prop case, we make only one pass 1361 // through the loop 1362 for (int i = 0; ; ++i) { 1363 if (all) { 1364 if (i >= AnimationControllerPrivate::getNumProperties()) 1365 break; 1366 // get the next prop 1367 prop = AnimationControllerPrivate::getPropertyAtIndex(i); 1368 } 1369 1370 // See if there is a current transition for this prop 1371 ImplicitAnimation* implAnim = m_transitions.get(prop); 1372 bool equal = true; 1373 1374 if (implAnim) { 1375 // There is one, has our target changed? 1376 if (!implAnim->isTargetPropertyEqual(prop, targetStyle)) { 1377 // It has changed - toss it and start over 1378 // Opacity is special since it can pop in and out of RenderLayers. We need to compute 1379 // the blended opacity value between the previous from and to styles and put that in the currentStyle, which 1380 // will become the new fromStyle. This is changing a const RenderStyle, but we know what we are doing, really :-) 1381 if (prop == CSSPropertyOpacity) { 1382 // get the blended value of opacity into the currentStyle (which will be the new fromStyle) 1383 implAnim->blendPropertyValueInStyle(CSSPropertyOpacity, currentStyle); 1384 } 1385 1386 implAnim->reset(renderer); 1387 delete implAnim; 1388 m_transitions.remove(prop); 1389 equal = false; 1390 } 1391 } 1392 else 1393 // See if we need to start a new transition 1394 equal = AnimationControllerPrivate::propertiesEqual(prop, currentStyle, targetStyle); 1395 1396 if (!equal) { 1397 // AAdd the new transition 1398 ImplicitAnimation* animation = new ImplicitAnimation(const_cast<Animation*>(anim), renderer, this); 1399 m_transitions.set(prop, animation); 1400 } 1401 1402 // We only need one pass for the single prop case 1403 if (!all) 1404 break; 1405 } 1406 } 1407 } 1408 1409 RenderStyle* CompositeAnimation::animate(RenderObject* renderer, RenderStyle* currentStyle, RenderStyle* targetStyle) 1410 { 1411 RenderStyle* resultStyle = 0; 1412 1413 // We don't do any transitions if we don't have a currentStyle (on startup) 1414 updateTransitions(renderer, currentStyle, targetStyle); 1415 1416 if (currentStyle) { 1417 // Now that we have transition objects ready, let them know about the new goal state. We want them 1418 // to fill in a RenderStyle*& only if needed. 1419 CSSPropertyTransitionsMap::const_iterator end = m_transitions.end(); 1420 for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it) { 1421 ImplicitAnimation* anim = it->second; 1422 if (anim) { 1423 anim->animate(this, renderer, currentStyle, targetStyle, resultStyle); 1424 } 1425 } 1426 } 1427 1428 cleanupFinishedAnimations(renderer); 1429 1430 return resultStyle ? resultStyle : targetStyle; 1431 } 1432 1433 // "animating" means that something is running that requires the timer to keep firing 1434 // (e.g. a transition) 1435 void CompositeAnimation::setAnimating(bool inAnimating) 1436 { 1437 CSSPropertyTransitionsMap::const_iterator end = m_transitions.end(); 1438 for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it) { 1439 ImplicitAnimation* transition = it->second; 1440 transition->setAnimating(inAnimating); 1441 } 1442 } 1443 1444 bool CompositeAnimation::animating() 1445 { 1446 CSSPropertyTransitionsMap::const_iterator end = m_transitions.end(); 1447 for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it) { 1448 ImplicitAnimation* transition = it->second; 1449 if (transition && transition->animating() && transition->running()) 1450 return true; 1451 } 1452 return false; 1453 } 1454 1455 void CompositeAnimation::resetTransitions(RenderObject* renderer) 1456 { 1457 CSSPropertyTransitionsMap::const_iterator end = m_transitions.end(); 1458 for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it) { 1459 ImplicitAnimation* transition = it->second; 1460 transition->reset(renderer); 1461 delete transition; 1462 } 1463 m_transitions.clear(); 1464 } 1465 1466 void CompositeAnimation::cleanupFinishedAnimations(RenderObject* renderer) 1467 { 1468 if (suspended()) 1469 return; 1470 1471 // Make a list of transitions to be deleted 1472 Vector<int> finishedTransitions; 1473 CSSPropertyTransitionsMap::const_iterator end = m_transitions.end(); 1474 1475 for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it) { 1476 ImplicitAnimation* anim = it->second; 1477 if (!anim) 1478 continue; 1479 if (anim->postactive() && !anim->waitingForEndEvent()) 1480 finishedTransitions.append(anim->property()); 1481 } 1482 1483 // Delete them 1484 for (Vector<int>::iterator it = finishedTransitions.begin(); it != finishedTransitions.end(); ++it) { 1485 ImplicitAnimation* anim = m_transitions.get(*it); 1486 if (anim) { 1487 anim->reset(renderer); 1488 delete anim; 1489 } 1490 m_transitions.remove(*it); 1491 } 1492 } 1493 1494 void CompositeAnimation::setTransitionStartTime(int property, double t) 1495 { 1496 // Set the start time for given property transition 1497 CSSPropertyTransitionsMap::const_iterator end = m_transitions.end(); 1498 for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it) { 1499 ImplicitAnimation* anim = it->second; 1500 if (anim && anim->waitingForStartTime() && 1501 (anim->property() == property || anim->property() == cAnimateAll)) 1502 anim->updateStateMachine(AnimationBase::STATE_INPUT_START_TIME_SET, t); 1503 } 1504 } 1505 1506 void CompositeAnimation::suspendAnimations() 1507 { 1508 if (m_suspended) 1509 return; 1510 1511 m_suspended = true; 1512 1513 CSSPropertyTransitionsMap::const_iterator end = m_transitions.end(); 1514 for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it) { 1515 ImplicitAnimation* anim = it->second; 1516 if (anim && anim->hasStyle()) { 1517 anim->updatePlayState(false); 1518 } 1519 } 1520 } 1521 1522 void CompositeAnimation::resumeAnimations() 1523 { 1524 if (!m_suspended) 1525 return; 1526 1527 m_suspended = false; 1528 1529 CSSPropertyTransitionsMap::const_iterator end = m_transitions.end(); 1530 for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it) { 1531 ImplicitAnimation* anim = it->second; 1532 if (anim && anim->hasStyle()) { 1533 anim->updatePlayState(true); 1534 } 1535 } 1536 } 1537 1538 void CompositeAnimation::overrideImplicitAnimations(int property) 1539 { 1540 CSSPropertyTransitionsMap::const_iterator end = m_transitions.end(); 1541 for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it) { 1542 ImplicitAnimation* anim = it->second; 1543 if (anim && (anim->property() == property || anim->property() == cAnimateAll)) 1544 anim->setOverridden(true); 1545 } 1546 } 1547 1548 void CompositeAnimation::resumeOverriddenImplicitAnimations(int property) 1549 { 1550 CSSPropertyTransitionsMap::const_iterator end = m_transitions.end(); 1551 for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it) { 1552 ImplicitAnimation* anim = it->second; 1553 if (anim && (anim->property() == property || anim->property() == cAnimateAll)) 1554 anim->setOverridden(false); 1555 } 1556 } 1557 1558 void CompositeAnimation::styleAvailable() 1559 { 1560 if (m_numStyleAvailableWaiters == 0) 1561 return; 1562 1563 CSSPropertyTransitionsMap::const_iterator end = m_transitions.end(); 1564 for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it) { 1565 ImplicitAnimation* anim = it->second; 1566 if (anim && anim->waitingForStyleAvailable()) 1567 anim->updateStateMachine(AnimationBase::STATE_INPUT_STYLE_AVAILABLE, -1); 1568 } 1569 } 1570 1571 bool CompositeAnimation::isAnimatingProperty(int property) const 1572 { 1573 CSSPropertyTransitionsMap::const_iterator end = m_transitions.end(); 1574 for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it) { 1575 ImplicitAnimation* anim = it->second; 1576 if (anim && anim->isAnimatingProperty(property)) 1577 return true; 1578 } 1579 return false; 1580 } 1581 1582 void ImplicitAnimation::animate(CompositeAnimation* animation, RenderObject* renderer, const RenderStyle* currentStyle, 1583 const RenderStyle* targetStyle, RenderStyle*& ioAnimatedStyle) 1584 { 1585 if (paused()) 1586 return; 1587 1588 // If we get this far and the animation is done, it means we are cleaning up a just finished animation. 1589 // If so, send back the targetStyle (it will get tossed later) 1590 if (postactive()) { 1591 if (!ioAnimatedStyle) 1592 ioAnimatedStyle = const_cast<RenderStyle*>(targetStyle); 1593 return; 1594 } 1595 1596 // Reset to start the transition if we are new 1597 if (isnew()) 1598 reset(renderer, currentStyle, targetStyle); 1599 1600 // Run a cycle of animation. 1601 // We know we will need a new render style, so make one if needed 1602 if (!ioAnimatedStyle) 1603 ioAnimatedStyle = new (renderer->renderArena()) RenderStyle(*targetStyle); 1604 1605 double prog = progress(1, 0); 1606 bool needsAnim = AnimationControllerPrivate::blendProperties(m_property, ioAnimatedStyle, m_fromStyle, m_toStyle, prog); 1607 if (needsAnim) 1608 setAnimating(); 1609 } 1610 1611 bool ImplicitAnimation::startAnimation(double beginTime) 1612 { 1613 return false; 1614 } 1615 1616 void ImplicitAnimation::endAnimation(bool reset) 1617 { 1618 } 1619 1620 void ImplicitAnimation::onAnimationEnd(double inElapsedTime) 1621 { 1622 // we're converting the animation into a transition here 1623 if (!sendTransitionEvent(EventNames::webkitTransitionEndEvent, inElapsedTime)) { 1624 // we didn't dispatch an event, which would call endAnimation(), so we'll just end 1625 // it here. 1626 endAnimation(true); 1627 } 1628 } 1629 1630 bool ImplicitAnimation::sendTransitionEvent(const AtomicString& inEventType, double inElapsedTime) 1631 { 1632 return false; // didn't dispatch an event 1633 } 1634 1635 void ImplicitAnimation::reset(RenderObject* renderer, const RenderStyle* from /* = 0 */, const RenderStyle* to /* = 0 */) 1636 { 1637 ASSERT((!m_toStyle && !to) || m_toStyle != to); 1638 ASSERT((!m_fromStyle && !from) || m_fromStyle != from); 1639 if (m_fromStyle) 1640 m_fromStyle->deref(renderer->renderArena()); 1641 if (m_toStyle) 1642 m_toStyle->deref(renderer->renderArena()); 1643 1644 m_fromStyle = const_cast<RenderStyle*>(from); // it is read-only, other than the ref 1645 if (m_fromStyle) 1646 m_fromStyle->ref(); 1647 1648 m_toStyle = const_cast<RenderStyle*>(to); // it is read-only, other than the ref 1649 if (m_toStyle) 1650 m_toStyle->ref(); 1651 1652 // restart the transition 1653 if (from && to) 1654 updateStateMachine(STATE_INPUT_RESTART_ANIMATION, -1); 1655 } 1656 1657 void ImplicitAnimation::setOverridden(bool b) 1658 { 1659 if (b != m_overridden) { 1660 m_overridden = b; 1661 updateStateMachine(m_overridden ? STATE_INPUT_PAUSE_OVERRIDE : STATE_INPUT_RESUME_OVERRIDE, -1); 1662 } 1663 } 1664 1665 bool ImplicitAnimation::affectsProperty(int property) const 1666 { 1667 return m_property == property || 1668 (m_property == cAnimateAll && !AnimationControllerPrivate::propertiesEqual(property, m_fromStyle, m_toStyle)); 1669 } 1670 1671 bool ImplicitAnimation::isTargetPropertyEqual(int prop, RenderStyle* targetStyle) 1672 { 1673 return AnimationControllerPrivate::propertiesEqual(prop, m_toStyle, targetStyle); 1674 } 1675 1676 void ImplicitAnimation::blendPropertyValueInStyle(int prop, RenderStyle* currentStyle) 1677 { 1678 double prog = progress(1, 0); 1679 AnimationControllerPrivate::blendProperties(prop, currentStyle, m_fromStyle, m_toStyle, prog); 1680 } 557 1681 558 1682 AnimationController::AnimationController(Frame* frame) 559 : m_data(new AnimationControllerPrivate(frame))560 { 561 1683 : m_data(new AnimationControllerPrivate(frame)) 1684 { 1685 562 1686 } 563 1687 … … 567 1691 } 568 1692 569 void AnimationController::cancel ImplicitAnimations(RenderObject* renderer)570 { 571 if (!m_data->has ImplicitAnimations())1693 void AnimationController::cancelAnimations(RenderObject* renderer) 1694 { 1695 if (!m_data->hasAnimations()) 572 1696 return; 573 1697 574 1698 if (m_data->clear(renderer)) 575 renderer->element()->setChanged(); 576 } 577 578 RenderStyle* AnimationController::updateImplicitAnimations(RenderObject* renderer, RenderStyle* newStyle) 579 { 1699 setChanged(renderer->element()); 1700 } 1701 1702 RenderStyle* AnimationController::updateAnimations(RenderObject* renderer, RenderStyle* newStyle) 1703 { 1704 // don't do anything if we're in the cache 1705 if (!renderer->document() || renderer->document()->inPageCache()) 1706 return newStyle; 1707 1708 RenderStyle* oldStyle = renderer->style(); 1709 1710 if ((!oldStyle || !oldStyle->transitions()) && !newStyle->transitions()) 1711 return newStyle; 1712 1713 RenderStyle* blendedStyle = newStyle; 1714 580 1715 // Fetch our current set of implicit animations from a hashtable. We then compare them 581 1716 // against the animations in the style and make sure we're in sync. If destination values … … 583 1718 // a new style. 584 1719 ASSERT(renderer->element()); // FIXME: We do not animate generated content yet. 585 586 CompositeImplicitAnimation* animation = m_data->get(renderer, newStyle); 587 if (!animation && !newStyle->transitions()) 588 return newStyle; 589 590 RenderStyle* blendedStyle = animation->animate(renderer, renderer->style(), newStyle); 591 m_data->updateTimer(); 592 1720 1721 CompositeAnimation* rendererAnimations = m_data->accessCompositeAnimation(renderer); 1722 blendedStyle = rendererAnimations->animate(renderer, oldStyle, newStyle); 1723 1724 m_data->updateAnimationTimer(); 1725 593 1726 if (blendedStyle != newStyle) { 594 // Do some of the work that CSSStyleSelector::adjustRenderStyle() does, to impose rules 595 // like opacity creating stacking context. 1727 // If the animations/transitions change opacity or transform, we neeed to update 1728 // the style to impose the stacking rules. Note that this is also 1729 // done in CSSStyleSelector::adjustRenderStyle(). 596 1730 if (blendedStyle->hasAutoZIndex() && (blendedStyle->opacity() < 1.0f || blendedStyle->hasTransform())) 597 1731 blendedStyle->setZIndex(0); 598 1732 } 599 600 1733 return blendedStyle; 601 1734 } 602 1735 603 void AnimationController::suspendAnimations() 604 { 605 // FIXME: Walk the whole hashtable and call pause on each animation. 606 // Kill our timer. 607 } 608 609 void AnimationController::resumeAnimations() 610 { 611 // FIXME: Walk the whole hashtable and call resume on each animation. 612 // Start our timer. 613 } 614 615 } 1736 bool AnimationController::isAnimatingPropertyOnRenderer(RenderObject* obj, int property) const 1737 { 1738 return m_data->isAnimatingPropertyOnRenderer(obj, property); 1739 } 1740 1741 void AnimationController::suspendAnimations(Document* document) 1742 { 1743 #ifdef DEBUG_STATE_MACHINE 1744 fprintf(stderr, "AnimationController %p suspendAnimations for document %p\n", this, document); 1745 #endif 1746 m_data->suspendAnimations(document); 1747 } 1748 1749 void AnimationController::resumeAnimations(Document* document) 1750 { 1751 #ifdef DEBUG_STATE_MACHINE 1752 fprintf(stderr, "AnimationController %p resumeAnimations for document %p\n", this, document); 1753 #endif 1754 m_data->resumeAnimations(document); 1755 } 1756 1757 void AnimationController::startUpdateRenderingDispatcher() 1758 { 1759 m_data->startUpdateRenderingDispatcher(); 1760 } 1761 1762 void AnimationController::styleAvailable() 1763 { 1764 m_data->styleAvailable(); 1765 } 1766 1767 void CompositeAnimation::setWaitingForStyleAvailable(bool waiting) 1768 { 1769 if (waiting) 1770 m_numStyleAvailableWaiters++; 1771 else 1772 m_numStyleAvailableWaiters--; 1773 m_animationController->setWaitingForStyleAvailable(waiting); 1774 } 1775 1776 } -
trunk/WebCore/page/AnimationController.h
r29663 r35545 30 30 #define AnimationController_h 31 31 32 #include "CSSPropertyNames.h" 33 32 34 namespace WebCore { 33 35 34 36 class AnimationControllerPrivate; 37 class Document; 35 38 class Frame; 36 39 class RenderObject; … … 43 46 ~AnimationController(); 44 47 45 void cancel ImplicitAnimations(RenderObject*);46 RenderStyle* update ImplicitAnimations(RenderObject*, RenderStyle* newStyle);48 void cancelAnimations(RenderObject*); 49 RenderStyle* updateAnimations(RenderObject*, RenderStyle* newStyle); 47 50 48 void suspendAnimations(); 49 void resumeAnimations(); 51 bool isAnimatingPropertyOnRenderer(RenderObject* obj, int property) const; 52 53 void suspendAnimations(Document* document); 54 void resumeAnimations(Document* document); 55 void updateAnimationTimer(); 56 57 void startUpdateRenderingDispatcher(); 58 59 void styleAvailable(); 50 60 51 61 private: 52 62 AnimationControllerPrivate* m_data; 63 53 64 }; 54 65 -
trunk/WebCore/page/Frame.cpp
r35499 r35545 1483 1483 if (document && document->renderer() && document->renderer()->hasLayer()) 1484 1484 document->renderer()->layer()->suspendMarquees(); 1485 view->frame()->animation()->suspendAnimations( );1485 view->frame()->animation()->suspendAnimations(document); 1486 1486 view->frame()->eventHandler()->stopAutoscrollTimer(); 1487 1487 } -
trunk/WebCore/rendering/RenderObject.cpp
r35433 r35545 2157 2157 { 2158 2158 if (!isText() && m_style && style) 2159 style = animation()->update ImplicitAnimations(this, style);2159 style = animation()->updateAnimations(this, style); 2160 2160 2161 2161 setStyle(style); … … 2536 2536 document()->axObjectCache()->remove(this); 2537 2537 2538 animation()->cancel ImplicitAnimations(this);2538 animation()->cancelAnimations(this); 2539 2539 2540 2540 // By default no ref-counting. RenderWidget::destroy() doesn't call -
trunk/WebCore/rendering/RenderWidget.cpp
r34589 r35545 73 73 // both RenderBox::destroy() and RenderObject::destroy(). 74 74 // Fix originally made for <rdar://problem/4228818>. 75 animation()->cancel ImplicitAnimations(this);75 animation()->cancelAnimations(this); 76 76 77 77 if (RenderView* v = view()) -
trunk/WebCore/rendering/style/RenderStyle.cpp
r35238 r35545 665 665 } 666 666 667 Transition::Transition()668 : m_duration(RenderStyle::initial TransitionDuration())669 , m_ repeatCount(RenderStyle::initialTransitionRepeatCount())670 , m_ timingFunction(RenderStyle::initialTransitionTimingFunction())671 , m_property(RenderStyle::initial TransitionProperty())667 Animation::Animation() 668 : m_duration(RenderStyle::initialDuration()) 669 , m_timingFunction(RenderStyle::initialTimingFunction()) 670 , m_delay(RenderStyle::initialDelay()) 671 , m_property(RenderStyle::initialProperty()) 672 672 , m_durationSet(false) 673 , m_repeatCountSet(false)674 673 , m_timingFunctionSet(false) 674 , m_delaySet(false) 675 675 , m_propertySet(false) 676 , m_next(0) 677 { 678 } 679 680 Transition::Transition(const Transition& o) 681 : m_duration(o.m_duration) 682 , m_repeatCount(o.m_repeatCount) 676 { 677 } 678 679 Animation::Animation(const Animation& o) 680 : RefCounted<Animation>() 681 , m_duration(o.m_duration) 683 682 , m_timingFunction(o.m_timingFunction) 683 , m_delay(o.m_delay) 684 684 , m_property(o.m_property) 685 685 , m_durationSet(o.m_durationSet) 686 , m_repeatCountSet(o.m_repeatCountSet)687 686 , m_timingFunctionSet(o.m_timingFunctionSet) 687 , m_delaySet(o.m_delaySet) 688 688 , m_propertySet(o.m_propertySet) 689 , m_next(o.m_next ? new Transition(*o.m_next) : 0) 690 { 691 } 692 693 Transition::~Transition() 694 { 695 delete m_next; 696 } 697 698 Transition& Transition::operator=(const Transition& o) 699 { 700 if (m_next != o.m_next) { 701 delete m_next; 702 m_next = o.m_next ? new Transition(*o.m_next) : 0; 703 } 704 689 { 690 } 691 692 Animation& Animation::operator=(const Animation& o) 693 { 694 m_delay = o.m_delay; 705 695 m_duration = o.m_duration; 706 m_repeatCount = o.m_repeatCount;707 696 m_timingFunction = o.m_timingFunction; 708 697 m_property = o.m_property; 709 698 699 m_delaySet = o.m_delaySet; 710 700 m_durationSet = o.m_durationSet; 711 m_repeatCountSet = o.m_repeatCountSet;712 701 m_timingFunctionSet = o.m_timingFunctionSet; 713 702 m_propertySet = o.m_propertySet; … … 716 705 } 717 706 718 bool Transition::operator==(const Transition& o) const 719 { 720 return m_duration == o.m_duration && m_repeatCount == o.m_repeatCount && m_timingFunction == o.m_timingFunction && 721 m_property == o.m_property && m_durationSet == o.m_durationSet && m_repeatCountSet == o.m_repeatCountSet && 722 m_timingFunctionSet == o.m_timingFunctionSet && m_propertySet == o.m_propertySet && 723 ((m_next && o.m_next) ? *m_next == *o.m_next : m_next == o.m_next); 724 } 725 726 void Transition::fillUnsetProperties() 727 { 728 Transition* curr; 729 for (curr = this; curr && curr->isDurationSet(); curr = curr->next()) { } 730 if (curr && curr != this) { 731 // We need to fill in the remaining values with the pattern specified. 732 for (Transition* pattern = this; curr; curr = curr->next()) { 733 curr->m_duration = pattern->m_duration; 734 pattern = pattern->next(); 735 if (pattern == curr || !pattern) 736 pattern = this; 737 } 738 } 739 740 for (curr = this; curr && curr->isRepeatCountSet(); curr = curr->next()) { } 741 if (curr && curr != this) { 742 // We need to fill in the remaining values with the pattern specified. 743 for (Transition* pattern = this; curr; curr = curr->next()) { 744 curr->m_repeatCount = pattern->m_repeatCount; 745 pattern = pattern->next(); 746 if (pattern == curr || !pattern) 747 pattern = this; 748 } 749 } 750 751 for (curr = this; curr && curr->isTimingFunctionSet(); curr = curr->next()) { } 752 if (curr && curr != this) { 753 // We need to fill in the remaining values with the pattern specified. 754 for (Transition* pattern = this; curr; curr = curr->next()) { 755 curr->m_timingFunction = pattern->m_timingFunction; 756 pattern = pattern->next(); 757 if (pattern == curr || !pattern) 758 pattern = this; 759 } 760 } 761 762 for (curr = this; curr && curr->isPropertySet(); curr = curr->next()) { } 763 if (curr && curr != this) { 764 // We need to fill in the remaining values with the pattern specified. 765 for (Transition* pattern = this; curr; curr = curr->next()) { 766 curr->m_property = pattern->m_property; 767 pattern = pattern->next(); 768 if (pattern == curr || !pattern) 769 pattern = this; 770 } 771 } 707 bool Animation::animationsMatch(const Animation* o) const 708 { 709 if (!o) 710 return false; 711 712 bool result = m_duration == o->m_duration && 713 m_timingFunction == o->m_timingFunction && 714 m_delay == o->m_delay && 715 m_property == o->m_property && 716 m_durationSet == o->m_durationSet && 717 m_timingFunctionSet == o->m_timingFunctionSet && 718 m_delaySet == o->m_delaySet && 719 m_propertySet == o->m_propertySet; 720 721 return result; 722 } 723 724 #define FILL_UNSET_PROPERTY(test, propGet, propSet) \ 725 for (i = 0; i < size() && (*this)[i]->test(); ++i) { } \ 726 if (i < size() && i != 0) { \ 727 for (size_t j = 0; i < size(); ++i, ++j) \ 728 (*this)[i]->propSet((*this)[j]->propGet()); \ 729 } 730 731 void AnimationList::fillUnsetProperties() 732 { 733 size_t i; 734 FILL_UNSET_PROPERTY(isDelaySet, delay, setDelay); 735 FILL_UNSET_PROPERTY(isDurationSet, duration, setDuration); 736 FILL_UNSET_PROPERTY(isTimingFunctionSet, timingFunction, setTimingFunction); 737 FILL_UNSET_PROPERTY(isPropertySet, property, setProperty); 738 } 739 740 bool AnimationList::operator==(const AnimationList& o) const 741 { 742 if (size() != o.size()) 743 return false; 744 for (size_t i = 0; i < size(); ++i) 745 if (*at(i) != *o.at(i)) 746 return false; 747 return true; 772 748 } 773 749 … … 785 761 , m_borderFit(RenderStyle::initialBorderFit()) 786 762 , m_boxShadow(0) 787 , m_transition (0)763 , m_transitions(0) 788 764 , m_mask(FillLayer(MaskFillLayer)) 789 765 #if ENABLE(XBL) … … 812 788 , m_boxShadow(o.m_boxShadow ? new ShadowData(*o.m_boxShadow) : 0) 813 789 , m_boxReflect(o.m_boxReflect) 814 , m_transition (o.m_transition ? new Transition(*o.m_transition) : 0)790 , m_transitions(o.m_transitions ? new AnimationList(*o.m_transitions) : 0) 815 791 , m_mask(o.m_mask) 816 792 , m_maskBoxImage(o.m_maskBoxImage) … … 826 802 delete m_counterDirectives; 827 803 delete m_boxShadow; 828 delete m_transition;829 804 #if ENABLE(XBL) 830 805 delete bindingURI; … … 897 872 bool StyleRareNonInheritedData::transitionDataEquivalent(const StyleRareNonInheritedData& o) const 898 873 { 899 if (!m_transition && o.m_transition || m_transition && !o.m_transition)900 return false; 901 if (m_transition && o.m_transition && (*m_transition != *o.m_transition))874 if (!m_transitions && o.m_transitions || m_transitions && !o.m_transitions) 875 return false; 876 if (m_transitions && o.m_transitions && (*m_transitions != *o.m_transitions)) 902 877 return false; 903 878 return true; … … 1495 1470 // so they don't need to cause any repaint or layout. 1496 1471 1497 // Transitions don't need to be checked either. We always set the new style on the RenderObject, so we will get a chance to fire off1472 // Animations don't need to be checked either. We always set the new style on the RenderObject, so we will get a chance to fire off 1498 1473 // the resulting transition properly. 1499 1474 return Equal; … … 1871 1846 void RenderStyle::adjustTransitions() 1872 1847 { 1873 if (transitions()) { 1874 if (transitions()->isEmpty()) { 1875 clearTransitions(); 1876 return; 1848 AnimationList* transitionList = rareNonInheritedData->m_transitions; 1849 if (!transitionList) 1850 return; 1851 1852 if (transitionList->size() == 0) { 1853 clearTransitions(); 1854 return; 1855 } 1856 1857 // get rid of empty transitions and anything beyond them 1858 for (size_t i = 0; i < transitionList->size(); ++i) { 1859 if ((*transitionList)[i]->isEmpty()) { 1860 transitionList->resize(i); 1861 break; 1877 1862 } 1878 1879 Transition* next; 1880 for (Transition* p = accessTransitions(); p; p = next) { 1881 next = p->m_next; 1882 if (next && next->isEmpty()) { 1883 delete next; 1884 p->m_next = 0; 1885 break; 1863 } 1864 1865 if (transitionList->size() == 0) { 1866 clearTransitions(); 1867 return; 1868 } 1869 1870 // Repeat patterns into layers that don't have some properties set. 1871 transitionList->fillUnsetProperties(); 1872 1873 // Make sure there are no duplicate properties. This is an O(n^2) algorithm 1874 // but the lists tend to be very short, so it is probably ok 1875 for (size_t i = 0; i < transitionList->size(); ++i) { 1876 for (size_t j = i+1; j < transitionList->size(); ++j) { 1877 if ((*transitionList)[i]->property() == (*transitionList)[j]->property()) { 1878 // toss i 1879 transitionList->remove(i); 1880 j = i; 1886 1881 } 1887 1882 } 1888 1889 // Repeat patterns into layers that don't have some properties set. 1890 accessTransitions()->fillUnsetProperties(); 1891 } 1892 } 1893 1894 Transition* RenderStyle::accessTransitions() 1895 { 1896 Transition* layer = rareNonInheritedData.access()->m_transition; 1897 if (!layer) 1898 rareNonInheritedData.access()->m_transition = new Transition(); 1899 return rareNonInheritedData->m_transition; 1900 } 1901 1902 } 1883 } 1884 } 1885 1886 AnimationList* RenderStyle::accessTransitions() 1887 { 1888 AnimationList* list = rareNonInheritedData.access()->m_transitions; 1889 if (!list) 1890 rareNonInheritedData.access()->m_transitions = new AnimationList(); 1891 return rareNonInheritedData->m_transitions; 1892 } 1893 1894 } -
trunk/WebCore/rendering/style/RenderStyle.h
r35026 r35545 1258 1258 }; 1259 1259 1260 struct Transition { 1261 public: 1262 Transition(); 1263 ~Transition(); 1264 1265 Transition* next() const { return m_next; } 1266 Transition* next() { return m_next; } 1267 1260 class Animation : public RefCounted<Animation> { 1261 public: 1262 1263 static PassRefPtr<Animation> create() { return adoptRef(new Animation); }; 1264 1265 bool isDelaySet() const { return m_delaySet; } 1268 1266 bool isDurationSet() const { return m_durationSet; } 1269 bool isRepeatCountSet() const { return m_repeatCountSet; }1270 1267 bool isTimingFunctionSet() const { return m_timingFunctionSet; } 1271 1268 bool isPropertySet() const { return m_propertySet; } 1272 1273 bool isEmpty() const { return !m_durationSet && !m_repeatCountSet && !m_timingFunctionSet && !m_propertySet; } 1269 1270 bool isEmpty() const 1271 { 1272 return (!m_durationSet && !m_delaySet && !m_timingFunctionSet && !m_propertySet); 1273 } 1274 1275 bool isEmptyOrZeroDuration() const 1276 { 1277 return isEmpty() || (m_duration == 0 && m_delay <= 0); 1278 } 1279 1280 void clearDelay() { m_delaySet = false; } 1274 1281 void clearDuration() { m_durationSet = false; } 1275 void clearRepeatCount() { m_repeatCountSet = false; }1276 1282 void clearTimingFunction() { m_timingFunctionSet = false; } 1283 1277 1284 void clearProperty() { m_propertySet = false; } 1278 1285 1279 int duration() const { return m_duration; }1280 int repeatCount() const { return m_repeatCount; }1286 double delay() const { return m_delay; } 1287 double duration() const { return m_duration; } 1281 1288 const TimingFunction& timingFunction() const { return m_timingFunction; } 1282 1289 int property() const { return m_property; } 1283 1284 void setD uration(int d) { m_duration = d; m_durationSet = true; }1285 void set RepeatCount(int c) { m_repeatCount = c; m_repeatCountSet = true; }1290 1291 void setDelay(double c) { m_delay = c; m_delaySet = true; } 1292 void setDuration(double d) { ASSERT(d >= 0); m_duration = d; m_durationSet = true; } 1286 1293 void setTimingFunction(const TimingFunction& f) { m_timingFunction = f; m_timingFunctionSet = true; } 1287 1294 void setProperty(int t) { m_property = t; m_propertySet = true; } 1288 1295 1289 void setNext(Transition* n) { if (m_next != n) { delete m_next; m_next = n; } } 1290 1291 Transition& operator=(const Transition& o); 1292 Transition(const Transition& o); 1293 1294 bool operator==(const Transition& o) const; 1295 bool operator!=(const Transition& o) const { 1296 return !(*this == o); 1297 } 1298 1296 Animation& operator=(const Animation& o); 1297 1298 // return true if all members of this class match (excluding m_next) 1299 bool animationsMatch(const Animation* t) const; 1300 1301 // return true every Animation in the chain (defined by m_next) match 1302 bool operator==(const Animation& o) const { return animationsMatch(&o); } 1303 bool operator!=(const Animation& o) const { return !(*this == o); } 1304 1305 private: 1306 Animation(); 1307 Animation(const Animation& o); 1308 1309 double m_duration; 1310 TimingFunction m_timingFunction; 1311 double m_delay; 1312 int m_property; 1313 1314 bool m_durationSet : 1; 1315 bool m_timingFunctionSet : 1; 1316 bool m_delaySet : 1; 1317 bool m_propertySet : 1; 1318 }; 1319 1320 class AnimationList : public Vector<RefPtr<Animation> > 1321 { 1322 public: 1299 1323 void fillUnsetProperties(); 1300 1301 int m_duration; 1302 int m_repeatCount; 1303 TimingFunction m_timingFunction; 1304 int m_property; 1305 1306 bool m_durationSet; 1307 bool m_repeatCountSet; 1308 bool m_timingFunctionSet; 1309 bool m_propertySet; 1310 1311 Transition* m_next; 1312 }; 1324 bool operator==(const AnimationList& o) const; 1325 }; 1326 1313 1327 1314 1328 class StyleReflection : public RefCounted<StyleReflection> { … … 1390 1404 RefPtr<StyleReflection> m_boxReflect; 1391 1405 1392 Transition* m_transition;1406 AnimationList* m_transitions; 1393 1407 1394 1408 FillLayer m_mask; … … 2031 2045 } 2032 2046 ShadowData* textShadow() const { return rareInheritedData->textShadow; } 2033 ColortextStrokeColor() const { return rareInheritedData->textStrokeColor; }2047 const Color& textStrokeColor() const { return rareInheritedData->textStrokeColor; } 2034 2048 float textStrokeWidth() const { return rareInheritedData->textStrokeWidth; } 2035 ColortextFillColor() const { return rareInheritedData->textFillColor; }2049 const Color& textFillColor() const { return rareInheritedData->textFillColor; } 2036 2050 float opacity() const { return rareNonInheritedData->opacity; } 2037 2051 EAppearance appearance() const { return static_cast<EAppearance>(rareNonInheritedData->m_appearance); } … … 2088 2102 2089 2103 // Apple-specific property getter methods 2090 Transition* accessTransitions(); 2091 const Transition* transitions() const { return rareNonInheritedData->m_transition; } 2104 AnimationList* accessTransitions(); 2105 const AnimationList* transitions() const { return rareNonInheritedData->m_transitions; } 2106 bool hasTransitions() const { return rareNonInheritedData->m_transitions && rareNonInheritedData->m_transitions->size() > 0; } 2107 2092 2108 int lineClamp() const { return rareNonInheritedData->lineClamp; } 2093 2109 bool textSizeAdjust() const { return rareInheritedData->textSizeAdjust; } … … 2351 2367 void setTransformOriginY(Length l) { SET_VAR(rareNonInheritedData.access()->m_transform, m_y, l); } 2352 2368 // End CSS3 Setters 2353 2369 2354 2370 // Apple-specific property setters 2355 void clearTransitions() { delete rareNonInheritedData.access()->m_transition; rareNonInheritedData.access()->m_transition = 0; } 2356 void inheritTransitions(const Transition* parent) { clearTransitions(); if (parent) rareNonInheritedData.access()->m_transition = new Transition(*parent); } 2371 void clearTransitions() 2372 { 2373 if (rareNonInheritedData.access()->m_transitions) { 2374 delete rareNonInheritedData.access()->m_transitions; 2375 rareNonInheritedData.access()->m_transitions = 0; 2376 } 2377 } 2378 2379 void inheritTransitions(const AnimationList* parent) { clearTransitions(); if (parent) rareNonInheritedData.access()->m_transitions = new AnimationList(*parent); } 2357 2380 void adjustTransitions(); 2358 2381 void setLineClamp(int c) { SET_VAR(rareNonInheritedData, lineClamp, c); } … … 2512 2535 2513 2536 // Keep these at the end. 2514 static int initialTransitionDuration() { return 0; }2515 static int initialTransitionRepeatCount() { return 1; }2516 static TimingFunction initialT ransitionTimingFunction() { return TimingFunction(); }2517 static int initial TransitionProperty() { return cAnimateAll; }2537 static float initialDelay() { return 0; } 2538 static double initialDuration() { return 0; } 2539 static TimingFunction initialTimingFunction() { return TimingFunction(); } 2540 static int initialProperty() { return cAnimateAll; } 2518 2541 static int initialLineClamp() { return -1; } 2519 2542 static bool initialTextSizeAdjust() { return true; }
Note: See TracChangeset
for help on using the changeset viewer.