WebCore/css/CSSComputedStyleDeclaration.cpp

2929#include "CSSPrimitiveValueMappings.h"
3030#include "CSSPropertyNames.h"
3131#include "CSSReflectValue.h"
 32#include "CSSTimingFunctionValue.h"
3233#include "CSSValueList.h"
3334#include "CachedImage.h"
3435#include "Document.h"

@@static const int computedProperties[] = {
187188 CSSPropertyWebkitTransform,
188189 CSSPropertyWebkitTransformOriginX,
189190 CSSPropertyWebkitTransformOriginY,
 191 CSSPropertyWebkitTransitionDelay,
 192 CSSPropertyWebkitTransitionDuration,
 193 CSSPropertyWebkitTransitionProperty,
 194 CSSPropertyWebkitTransitionTimingFunction,
190195 CSSPropertyWebkitUserDrag,
191196 CSSPropertyWebkitUserModify,
192197 CSSPropertyWebkitUserSelect,

@@PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper
10551060 }
10561061 else
10571062 return CSSPrimitiveValue::create(style->transformOriginY());
 1063 case CSSPropertyWebkitTransitionDelay: {
 1064 RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
 1065 const Animation* t = style->transitions();
 1066 if (t) {
 1067 for ( ; t; t = t->next())
 1068 list->append(CSSPrimitiveValue::create(t->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 Animation* t = style->transitions();
 1077 if (t) {
 1078 for ( ; t; t = t->next())
 1079 list->append(CSSPrimitiveValue::create(t->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 Animation* t = style->transitions();
 1088 if (t) {
 1089 for ( ; t; t = t->next()) {
 1090 const TimingFunction& tf = t->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 Animation* t = style->transitions();
 1103 if (t) {
 1104 for ( ; t; t = t->next()) {
 1105 int prop = t->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 }
10581120 case CSSPropertyBackground:
10591121 case CSSPropertyBorder:
10601122 case CSSPropertyBorderBottom:

@@PassRefPtr<CSSValue> CSSComputedStyleDeclaration::getPropertyCSSValue(int proper
11121174 case CSSPropertyWebkitMask:
11131175 case CSSPropertyWebkitPaddingStart:
11141176 case CSSPropertyWebkitTextStroke:
1115  case CSSPropertyWebkitTransition:
1116  case CSSPropertyWebkitTransitionDuration:
1117  case CSSPropertyWebkitTransitionProperty:
1118  case CSSPropertyWebkitTransitionRepeatCount:
1119  case CSSPropertyWebkitTransitionTimingFunction:
11201177 // FIXME: The above are unimplemented.
11211178 break;
11221179#if ENABLE(SVG)

WebCore/css/CSSParser.cpp

@@bool CSSParser::parseValue(int propId, bool important)
12941294 }
12951295 return false;
12961296 }
 1297 case CSSPropertyWebkitTransitionDelay:
12971298 case CSSPropertyWebkitTransitionDuration:
1298  case CSSPropertyWebkitTransitionRepeatCount:
12991299 case CSSPropertyWebkitTransitionTimingFunction:
13001300 case CSSPropertyWebkitTransitionProperty: {
13011301 RefPtr<CSSValue> val;

@@void CSSParser::addTransitionValue(RefPtr<CSSValue>& lval, PassRefPtr<CSSValue>
17091709
17101710bool CSSParser::parseTransitionShorthand(bool important)
17111711{
1712  const int properties[] = { CSSPropertyWebkitTransitionProperty, CSSPropertyWebkitTransitionDuration,
1713  CSSPropertyWebkitTransitionTimingFunction, CSSPropertyWebkitTransitionRepeatCount };
 1712 const int properties[] = { CSSPropertyWebkitTransitionProperty,
 1713 CSSPropertyWebkitTransitionDuration,
 1714 CSSPropertyWebkitTransitionTimingFunction };
17141715 const int numProperties = sizeof(properties) / sizeof(properties[0]);
17151716
17161717 ShorthandScope scope(this, CSSPropertyWebkitTransition);

@@bool CSSParser::parseFillProperty(int propId, int& propId1, int& propId2,
22062207 return false;
22072208}
22082209
2209 PassRefPtr<CSSValue> CSSParser::parseTransitionDuration()
 2210PassRefPtr<CSSValue> CSSParser::parseDelay()
22102211{
22112212 CSSParserValue* value = m_valueList->current();
 2213 if (value->id == CSSValueNow)
 2214 return CSSPrimitiveValue::createIdentifier(value->id);
22122215 if (validUnit(value, FTime, m_strict))
22132216 return CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit);
22142217 return 0;
22152218}
22162219
2217 PassRefPtr<CSSValue> CSSParser::parseTransitionRepeatCount()
 2220PassRefPtr<CSSValue> CSSParser::parseDuration()
22182221{
22192222 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))
22232224 return CSSPrimitiveValue::create(value->fValue, (CSSPrimitiveValue::UnitTypes)value->unit);
22242225 return 0;
22252226}

@@bool CSSParser::parseTimingFunctionValue(CSSParserValueList*& args, double& resu
22422243 return true;
22432244}
22442245
2245 PassRefPtr<CSSValue> CSSParser::parseTransitionTimingFunction()
 2246PassRefPtr<CSSValue> CSSParser::parseTimingFunction()
22462247{
22472248 CSSParserValue* value = m_valueList->current();
22482249 if (value->id == CSSValueEase || value->id == CSSValueLinear || value->id == CSSValueEaseIn || value->id == CSSValueEaseOut || value->id == CSSValueEaseInOut)

@@bool CSSParser::parseTransitionProperty(int propId, RefPtr<CSSValue>& result)
23062307 }
23072308 else {
23082309 switch (propId) {
2309  case CSSPropertyWebkitTransitionDuration:
2310  currValue = parseTransitionDuration();
 2310 case CSSPropertyWebkitTransitionDelay:
 2311 currValue = parseDelay();
23112312 if (currValue)
23122313 m_valueList->next();
23132314 break;
2314  case CSSPropertyWebkitTransitionRepeatCount:
2315  currValue = parseTransitionRepeatCount();
 2315 case CSSPropertyWebkitTransitionDuration:
 2316 currValue = parseDuration();
23162317 if (currValue)
23172318 m_valueList->next();
23182319 break;
23192320 case CSSPropertyWebkitTransitionTimingFunction:
2320  currValue = parseTransitionTimingFunction();
 2321 currValue = parseTimingFunction();
23212322 if (currValue)
23222323 m_valueList->next();
23232324 break;

@@PassRefPtr<CSSValueList> CSSParser::parseTransform()
39073908
39083909 // The transform is a list of functional primitives that specify transform operations.
39093910 // We collect a list of WebKitCSSTransformValues, where each value specifies a single operation.
3910  RefPtr<CSSValueList> list = CSSValueList::createCommaSeparated();
 3911 RefPtr<CSSValueList> list = CSSValueList::createSpaceSeparated();
39113912 for (CSSParserValue* value = m_valueList->current(); value; value = m_valueList->next()) {
39123913 if (value->unit != CSSParserValue::Function || !value->function)
39133914 return 0;

WebCore/css/CSSParser.h

@@namespace WebCore {
8484 void addFillValue(RefPtr<CSSValue>& lval, PassRefPtr<CSSValue> rval);
8585
8686 void addTransitionValue(RefPtr<CSSValue>& lval, PassRefPtr<CSSValue> rval);
87  PassRefPtr<CSSValue> parseTransitionDuration();
88  PassRefPtr<CSSValue> parseTransitionRepeatCount();
89  PassRefPtr<CSSValue> parseTransitionTimingFunction();
90  bool parseTimingFunctionValue(CSSParserValueList*& args, double& result);
 87
 88 PassRefPtr<CSSValue> parseDelay();
 89 PassRefPtr<CSSValue> parseDuration();
 90 PassRefPtr<CSSValue> parseTimingFunction();
9191 PassRefPtr<CSSValue> parseTransitionProperty();
 92
 93 bool parseTimingFunctionValue(CSSParserValueList*& args, double& result);
9294 bool parseTransitionProperty(int propId, RefPtr<CSSValue>&);
9395 bool parseTransitionShorthand(bool important);
9496

WebCore/css/CSSPropertyNames.in

@@word-spacing
142142word-wrap
143143z-index
144144zoom
145 -webkit-transition
146 -webkit-transition-duration
147 -webkit-transition-property
148 -webkit-transition-repeat-count
149 -webkit-transition-timing-function
150145-webkit-appearance
151146-webkit-background-clip
152147-webkit-background-composite

@@zoom
225220-webkit-transform-origin
226221-webkit-transform-origin-x
227222-webkit-transform-origin-y
 223-webkit-transition
 224-webkit-transition-delay
 225-webkit-transition-duration
 226-webkit-transition-property
 227-webkit-transition-timing-function
228228-webkit-user-drag
229229-webkit-user-modify
230230-webkit-user-select

WebCore/css/CSSStyleSelector.cpp

@@HANDLE_FILL_LAYER_VALUE(mask, Mask, prop, Prop, value)
184184
185185#define HANDLE_TRANSITION_INHERIT_AND_INITIAL(prop, Prop) \
186186if (isInherit) { \
187  Transition* currChild = m_style->accessTransitions(); \
188  Transition* prevChild = 0; \
189  const Transition* currParent = m_parentStyle->transitions(); \
 187 Animation* currChild = m_style->accessTransitions(); \
 188 Animation* prevChild = 0; \
 189 const Animation* currParent = m_parentStyle->transitions(); \
190190 while (currParent && currParent->is##Prop##Set()) { \
191191 if (!currChild) { \
192  /* Need to make a new layer.*/ \
193  currChild = new Transition(); \
 192 /* Need to make a new transition.*/ \
 193 currChild = new Animation(); \
194194 prevChild->setNext(currChild); \
195195 } \
196196 currChild->set##Prop(currParent->prop()); \

@@if (isInherit) { \
200200 } \
201201 \
202202 while (currChild) { \
203  /* Reset any remaining layers to not have the property set. */ \
 203 /* Reset any remaining transitions to not have the property set. */ \
204204 currChild->clear##Prop(); \
205205 currChild = currChild->next(); \
206206 } \
207 } else if (isInitial) { \
208  Transition* currChild = m_style->accessTransitions(); \
209  currChild->set##Prop(RenderStyle::initialTransition##Prop()); \
 207 return; \
 208} \
 209if (isInitial) { \
 210 Animation* currChild = m_style->accessTransitions(); \
 211 currChild->set##Prop(RenderStyle::initial##Prop()); \
210212 for (currChild = currChild->next(); currChild; currChild = currChild->next()) \
211213 currChild->clear##Prop(); \
 214 return; \
212215}
213216
214217#define HANDLE_TRANSITION_VALUE(prop, Prop, value) { \
215218HANDLE_TRANSITION_INHERIT_AND_INITIAL(prop, Prop) \
216 if (isInherit || isInitial) \
217  return; \
218 Transition* currChild = m_style->accessTransitions(); \
219 Transition* prevChild = 0; \
 219Animation* currChild = m_style->accessTransitions(); \
 220Animation* prevChild = 0; \
220221if (value->isValueList()) { \
221  /* Walk each value and put it into a layer, creating new layers as needed. */ \
 222 /* Walk each value and put it into a transition, creating new transitions as needed. */ \
222223 CSSValueList* valueList = static_cast<CSSValueList*>(value); \
223224 for (unsigned int i = 0; i < valueList->length(); i++) { \
224225 if (!currChild) { \
225  /* Need to make a new layer to hold this value */ \
226  currChild = new Transition(); \
227  prevChild->setNext(currChild); \
 226 /* Need to make a new transition to hold this value */ \
 227 currChild = new Animation(); \
 228 prevChild->setNext(currChild); \
228229 } \
229  mapTransition##Prop(currChild, valueList->itemWithoutBoundsCheck(i)); \
 230 map##Prop(currChild, valueList->item(i)); \
230231 prevChild = currChild; \
231232 currChild = currChild->next(); \
232233 } \
233234} else { \
234  mapTransition##Prop(currChild, value); \
 235 map##Prop(currChild, value); \
235236 currChild = currChild->next(); \
236237} \
237238while (currChild) { \
238  /* Reset all remaining layers to not have the property set. */ \
 239 /* Reset all remaining transitions to not have the property set. */ \
239240 currChild->clear##Prop(); \
240241 currChild = currChild->next(); \
241242} }

@@void CSSStyleSelector::applyProperty(int id, CSSValue *value)
47354736 else if (isInherit)
47364737 m_style->inheritTransitions(m_parentStyle->transitions());
47374738 return;
 4739 case CSSPropertyWebkitTransitionDelay:
 4740 HANDLE_TRANSITION_VALUE(delay, Delay, value)
 4741 return;
47384742 case CSSPropertyWebkitTransitionDuration:
47394743 HANDLE_TRANSITION_VALUE(duration, Duration, value)
47404744 return;
4741  case CSSPropertyWebkitTransitionRepeatCount:
4742  HANDLE_TRANSITION_VALUE(repeatCount, RepeatCount, value)
 4745 case CSSPropertyWebkitTransitionProperty:
 4746 HANDLE_TRANSITION_VALUE(property, Property, value)
47434747 return;
47444748 case CSSPropertyWebkitTransitionTimingFunction:
47454749 HANDLE_TRANSITION_VALUE(timingFunction, TimingFunction, value)
47464750 return;
4747  case CSSPropertyWebkitTransitionProperty:
4748  HANDLE_TRANSITION_VALUE(property, Property, value)
4749  return;
47504751 case CSSPropertyInvalid:
47514752 return;
47524753 case CSSPropertyFontStretch:

@@void CSSStyleSelector::mapFillYPosition(FillLayer* layer, CSSValue* value)
49874988 layer->setYPosition(l);
49884989}
49894990
4990 void CSSStyleSelector::mapTransitionDuration(Transition* transition, CSSValue* value)
 4991void CSSStyleSelector::mapDuration(Animation* transition, CSSValue* value)
49914992{
49924993 if (value->cssValueType() == CSSValue::CSS_INITIAL) {
4993  transition->setDuration(RenderStyle::initialTransitionDuration());
 4994 transition->setDuration(RenderStyle::initialDuration());
49944995 return;
49954996 }
49964997

@@void CSSStyleSelector::mapTransitionDuration(Transition* transition, CSSValue* v
49995000
50005001 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
50015002 if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_S)
5002  transition->setDuration(int(1000*primitiveValue->getFloatValue()));
 5003 transition->setDuration(primitiveValue->getFloatValue());
50035004 else if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_MS)
5004  transition->setDuration(int(primitiveValue->getFloatValue()));
 5005 transition->setDuration(primitiveValue->getFloatValue()/1000.0f);
50055006}
50065007
5007 void CSSStyleSelector::mapTransitionRepeatCount(Transition* transition, CSSValue* value)
 5008void CSSStyleSelector::mapDelay(Animation* transition, CSSValue* value)
50085009{
50095010 if (value->cssValueType() == CSSValue::CSS_INITIAL) {
5010  transition->setRepeatCount(RenderStyle::initialTransitionRepeatCount());
 5011 transition->setDelay(RenderStyle::initialDelay());
50115012 return;
50125013 }
50135014
5014  if (!value->isPrimitiveValue())
5015  return;
5016 
50175015 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
5018  if (primitiveValue->getIdent() == CSSValueInfinite)
5019  transition->setRepeatCount(-1);
5020  else
5021  transition->setRepeatCount(int(primitiveValue->getFloatValue()));
 5016 if (primitiveValue->getIdent() == CSSValueNow)
 5017 transition->setDelay(0);
 5018 else {
 5019 if (primitiveValue->primitiveType() == CSSPrimitiveValue::CSS_S)
 5020 transition->setDelay(primitiveValue->getFloatValue());
 5021 else
 5022 transition->setDelay(primitiveValue->getFloatValue()/1000.0f);
 5023 }
50225024}
50235025
5024 void CSSStyleSelector::mapTransitionTimingFunction(Transition* transition, CSSValue* value)
 5026void CSSStyleSelector::mapTimingFunction(Animation* transition, CSSValue* value)
50255027{
50265028 if (value->cssValueType() == CSSValue::CSS_INITIAL) {
5027  transition->setTimingFunction(RenderStyle::initialTransitionTimingFunction());
 5029 transition->setTimingFunction(RenderStyle::initialTimingFunction());
50285030 return;
50295031 }
5030 
 5032
50315033 if (value->isPrimitiveValue()) {
50325034 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
50335035 switch (primitiveValue->getIdent()) {

@@void CSSStyleSelector::mapTransitionTimingFunction(Transition* transition, CSSVa
50495051 }
50505052 return;
50515053 }
5052 
5053  if (value->isTransitionTimingFunctionValue()) {
 5054
 5055 if (value->isTimingFunctionValue()) {
50545056 CSSTimingFunctionValue* timingFunction = static_cast<CSSTimingFunctionValue*>(value);
50555057 transition->setTimingFunction(TimingFunction(CubicBezierTimingFunction, timingFunction->x1(), timingFunction->y1(), timingFunction->x2(), timingFunction->y2()));
50565058 }
50575059}
50585060
5059 void CSSStyleSelector::mapTransitionProperty(Transition* transition, CSSValue* value)
 5061void CSSStyleSelector::mapProperty(Animation* transition, CSSValue* value)
50605062{
50615063 if (value->cssValueType() == CSSValue::CSS_INITIAL) {
5062  transition->setProperty(RenderStyle::initialTransitionProperty());
 5064 transition->setProperty(RenderStyle::initialProperty());
50635065 return;
50645066 }
50655067

@@void CSSStyleSelector::mapTransitionProperty(Transition* transition, CSSValue* v
50675069 return;
50685070
50695071 CSSPrimitiveValue* primitiveValue = static_cast<CSSPrimitiveValue*>(value);
5070  transition->setProperty(primitiveValue->getIdent());
 5072 transition->setProperty(static_cast<CSSPropertyID>(primitiveValue->getIdent()));
50715073}
50725074
50735075void CSSStyleSelector::mapNinePieceImage(CSSValue* value, NinePieceImage& image)

WebCore/css/CSSStyleSelector.h

@@public:
204204 void mapFillXPosition(FillLayer*, CSSValue*);
205205 void mapFillYPosition(FillLayer*, CSSValue*);
206206
207  void mapTransitionDuration(Transition*, CSSValue*);
208  void mapTransitionRepeatCount(Transition*, CSSValue*);
209  void mapTransitionTimingFunction(Transition*, CSSValue*);
210  void mapTransitionProperty(Transition*, CSSValue*);
 207 void mapDelay(Animation*, CSSValue*);
 208 void mapDuration(Animation*, CSSValue*);
 209 void mapTimingFunction(Animation*, CSSValue*);
 210 void mapProperty(Animation*, CSSValue*);
211211
212212 void mapNinePieceImage(CSSValue*, NinePieceImage&);
213213

WebCore/css/CSSTimingFunctionValue.h

@@private:
5454 {
5555 }
5656
57  virtual bool isTransitionTimingFunctionValue() { return true; }
 57 virtual bool isTimingFunctionValue() { return true; }
5858
5959 double m_x1;
6060 double m_y1;

WebCore/css/CSSValue.h

@@public:
5252 virtual bool isImageValue() const { return false; }
5353 virtual bool isImplicitInitialValue() const { return false; }
5454 virtual bool isPrimitiveValue() const { return false; }
55  virtual bool isTransitionTimingFunctionValue() { return false; }
 55 virtual bool isTimingFunctionValue() { return false; }
5656 virtual bool isValueList() { return false; }
5757
5858#if ENABLE(SVG)

WebCore/css/CSSValueKeywords.in

@@visual
563563lines
564564
565565#
 566# CSS_PROP__WEBKIT_TRANSITION_DELAY
 567#
 568now
 569
 570#
566571# CSS_PROP__WEBKIT_TRANSITION_TIMING_FUNCTION
567572#
568573ease

WebCore/css/WebKitCSSTransformValue.cpp

3333namespace WebCore {
3434
3535WebKitCSSTransformValue::WebKitCSSTransformValue(TransformOperationType op)
36  : CSSValueList(false)
 36 : CSSValueList(true)
3737 , m_type(op)
3838{
3939}

WebCore/dom/Document.cpp

2424#include "config.h"
2525#include "Document.h"
2626
 27#include "AnimationController.h"
2728#include "AXObjectCache.h"
2829#include "CDATASection.h"
2930#include "CSSHelper.h"

@@void Document::updateRendering()
11661167{
11671168 if (hasChangedChild())
11681169 recalcStyle(NoChange);
 1170
 1171 // tell the animation controller that the style is available and it can start animations
 1172 if (m_frame)
 1173 m_frame->animation()->styleAvailable();
11691174}
11701175
11711176void Document::updateDocumentsRendering()

WebCore/dom/Document.h

@@public:
750750
751751 void updateFocusAppearanceSoon();
752752 void cancelFocusAppearanceUpdate();
753 
 753
754754 // FF method for accessing the selection added for compatability.
755755 DOMSelection* getSelection() const;
756756

@@private:
10461046#if USE(LOW_BANDWIDTH_DISPLAY)
10471047 bool m_inLowBandwidthDisplay;
10481048#endif
 1049
10491050};
10501051
10511052inline bool Document::hasElementWithId(AtomicStringImpl* id) const

WebCore/dom/Element.cpp

@@void Element::recalcStyle(StyleChange change)
785785 newStyle->setChildrenAffectedByDirectAdjacentRules();
786786 }
787787
788  if (ch != NoChange)
 788 if (ch != NoChange) {
789789 setRenderStyle(newStyle);
790  else if (changed() && (document()->usesSiblingRules() || document()->usesDescendantRules())) {
 790 } else if (changed() && (styleChangeType() != AnimationStyleChange) && (document()->usesSiblingRules() || document()->usesDescendantRules())) {
791791 // Although no change occurred, we use the new style so that the cousin style sharing code won't get
792792 // fooled into believing this style is the same. This is only necessary if the document actually uses
793793 // sibling/descendant rules, since otherwise it isn't possible for ancestor styles to affect sharing of

@@void Element::recalcStyle(StyleChange change)
796796 renderer()->setStyleInternal(newStyle);
797797 else
798798 setRenderStyle(newStyle);
799  }
 799 } else if (styleChangeType() == AnimationStyleChange)
 800 setRenderStyle(newStyle);
800801
801802 newStyle->deref(document()->renderArena());
802803
803804 if (change != Force) {
804  if ((document()->usesDescendantRules() || hasPositionalRules) && styleChangeType() == FullStyleChange)
 805 if ((document()->usesDescendantRules() || hasPositionalRules) && styleChangeType() >= FullStyleChange)
805806 change = Force;
806807 else
807808 change = ch;

WebCore/dom/EventNames.h

@@namespace WebCore { namespace EventNames {
119119 macro(progress) \
120120 macro(stalled) \
121121 \
 122 macro(webkitAnimationEnd) \
 123 macro(webkitAnimationStart) \
 124 macro(webkitAnimationIteration) \
 125 \
 126 macro(webkitTransitionEnd) \
 127 \
122128// end of DOM_EVENT_NAMES_FOR_EACH
123129
124130#ifndef DOM_EVENT_NAMES_HIDE_GLOBALS

WebCore/dom/Node.cpp

@@void Node::setChanged(StyleChangeType changeType)
416416 if ((changeType != NoStyleChange) && !attached()) // changed compared to what?
417417 return;
418418
419  if (!(changeType == InlineStyleChange && m_styleChange == FullStyleChange))
 419 if (!(changeType == InlineStyleChange && (m_styleChange == FullStyleChange || m_styleChange == AnimationStyleChange)))
420420 m_styleChange = changeType;
421421
422422 if (m_styleChange != NoStyleChange) {

WebCore/dom/Node.h

@@struct NodeListsNodeData;
6161
6262typedef int ExceptionCode;
6363
64 enum StyleChangeType { NoStyleChange, InlineStyleChange, FullStyleChange };
 64enum StyleChangeType { NoStyleChange, InlineStyleChange, FullStyleChange, AnimationStyleChange };
6565
6666const unsigned short DOCUMENT_POSITION_EQUIVALENT = 0x00;
6767const unsigned short DOCUMENT_POSITION_DISCONNECTED = 0x01;

WebCore/history/CachedPage.cpp

@@void CachedPage::restore(Page* page)
127127 m_document->accessSVGExtensions()->unpauseAnimations();
128128#endif
129129
130  mainFrame->animation()->resumeAnimations();
 130 mainFrame->animation()->resumeAnimations(m_document.get());
131131
132132 mainFrame->eventHandler()->setMousePressNode(mousePressNode());
133133

WebCore/page/AnimationController.cpp

3030#include "AnimationController.h"
3131
3232#include "CSSPropertyNames.h"
 33#include "CString.h"
3334#include "Document.h"
 35#include "EventNames.h"
3436#include "FloatConversion.h"
3537#include "Frame.h"
3638#include "RenderObject.h"

@@namespace WebCore {
4345
4446static const double cAnimationTimerDelay = 0.025;
4547
 48static void setChanged(Node* node)
 49{
 50 ASSERT(!node || (node->document() && !node->document()->inPageCache()));
 51 node->setChanged(AnimationStyleChange);
 52}
 53
4654// The epsilon value we pass to UnitBezier::solve given that the animation is going to run over |dur| seconds. The longer the
4755// animation, the more precision we need in the timing function result to avoid ugly discontinuities.
4856static inline double solveEpsilon(double duration) { return 1. / (200. * duration); }

@@static inline double solveCubicBezierFunction(double p1x, double p1y, double p2x
5563 return bezier.solve(t, solveEpsilon(duration));
5664}
5765
58 class CompositeImplicitAnimation;
 66class CompositeAnimation;
 67class AnimationBase;
5968
60 class ImplicitAnimation : public Noncopyable {
 69class AnimationTimerBase {
6170public:
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);
 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 }
6890
69  double progress() const;
 91 virtual void timerFired(Timer<AnimationTimerBase>*) = 0;
 92
 93private:
 94 Timer<AnimationTimerBase> m_timer;
 95
 96protected:
 97 AnimationBase* m_anim;
 98};
7099
71  int property() const { return m_property; }
 100class AnimationEventDispatcher : public AnimationTimerBase {
 101public:
 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 }
72125
73  bool finished() const { return m_finished; }
74  void setFinished(bool f) { m_finished = f; }
 126 virtual void timerFired(Timer<AnimationTimerBase>*);
75127
76  bool stale() const { return m_stale; }
77  void setStale() { m_stale = true; }
 128private:
 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};
78136
 137class AnimationTimerCallback : public AnimationTimerBase {
 138public:
 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
79154private:
80  // The two styles that we are blending.
81  RenderStyle* m_fromStyle;
82  RenderStyle* m_toStyle;
 155 AtomicString m_eventType;
 156 double m_elapsedTime;
 157};
83158
84  int m_property;
85  TimingFunction m_function;
86  double m_duration;
 159class ImplicitAnimation;
 160class AnimationControllerPrivate;
87161
88  int m_repeatCount;
 162// A CompositeAnimation represents a collection of animations that
 163// are running, such as a number of properties transitioning at once.
 164
 165class CompositeAnimation : public Noncopyable {
 166public:
 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);
 204protected:
 205 void updateTransitions(RenderObject* renderer, RenderStyle* currentStyle, RenderStyle* targetStyle);
 206
 207private:
 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
 216class AnimationBase : public Noncopyable {
 217public:
 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
 331protected:
 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
 353protected:
 354 AnimState m_animState;
89355 int m_iteration;
90356
91  bool m_finished;
 357 bool m_animating; // transition/animation requires continual timer firing
 358 bool m_waitedForResponse;
92359 double m_startTime;
93  bool m_paused;
94360 double m_pauseTime;
 361 RenderObject* m_object;
95362
96  bool m_stale;
 363 AnimationTimerCallback m_animationTimerCallback;
 364 AnimationEventDispatcher m_animationEventDispatcher;
 365 RefPtr<Animation> m_animation;
 366 CompositeAnimation* m_compAnim;
 367 bool m_waitingForEndEvent;
97368};
98369
99 class CompositeImplicitAnimation : public Noncopyable {
 370class ImplicitAnimation : public AnimationBase {
100371public:
101  ~CompositeImplicitAnimation() { deleteAllValues(m_animations); }
102 
103  RenderStyle* animate(RenderObject*, RenderStyle* currentStyle, RenderStyle* targetStyle);
104 
105  bool animating() const;
106 
107  void reset(RenderObject*);
 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
 395 int property() const { return m_property; }
 396
 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);
108415
 416 void blendPropertyValueInStyle(int prop, RenderStyle* currentStyle);
 417
 418protected:
 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
109426private:
110  HashMap<int, ImplicitAnimation*> m_animations;
 427 int m_property;
 428 bool m_overridden;
 429
 430 // The two styles that we are blending.
 431 RenderStyle* m_fromStyle;
 432 RenderStyle* m_toStyle;
111433};
112434
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())
120 , m_iteration(0)
121 , m_finished(false)
122 , m_startTime(currentTime())
123 , m_paused(false)
124 , m_pauseTime(m_startTime)
125 , m_stale(false)
 435void AnimationTimerCallback::timerFired(Timer<AnimationTimerBase>*)
126436{
 437 m_anim->animationTimerCallbackFired(m_eventType, m_elapsedTime);
127438}
128439
129 ImplicitAnimation::~ImplicitAnimation()
 440void AnimationEventDispatcher::timerFired(Timer<AnimationTimerBase>*)
130441{
131  ASSERT(!m_fromStyle && !m_toStyle);
 442 m_anim->animationEventDispatcherFired(m_element.get(), m_name, m_property, m_reset, m_eventType, m_elapsedTime);
132443}
133 
134 void ImplicitAnimation::reset(RenderObject* renderer, RenderStyle* from, RenderStyle* to)
 444
 445AnimationBase::AnimationBase(const Animation* transition, RenderObject* renderer, CompositeAnimation* compAnim)
 446: m_animState(STATE_NEW)
 447, m_iteration(0)
 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)
135458{
136  setFinished(false);
 459}
137460
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();
 461void 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);
150482
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;
164  }
 483 if (running())
 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);
165508 }
 509 return;
166510 }
167511
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);
 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());
 521 }
 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
 686void 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 }
171699}
172700
173 double ImplicitAnimation::progress() const
 701void AnimationBase::animationEventDispatcherFired(Element* element, const AtomicString& name, int property,
 702 bool reset, const AtomicString& eventType, double elapsedTime)
174703{
175  double elapsedTime = currentTime() - m_startTime;
 704 m_waitingForEndEvent = false;
176705
177  if (m_finished || !m_duration || elapsedTime >= m_duration)
178  return 1.0;
 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
 719void 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}
179724
180  if (m_function.type() == LinearTimingFunction)
181  return elapsedTime / m_duration;
 725double 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)
 737 return 1.0;
 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;
182751
183752 // 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
 761void 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 }
187791}
188792
189793static inline int blendFunc(int from, int to, double progress)

@@static inline IntSize blendFunc(const IntSize& from, const IntSize& to, double p
223827static inline ShadowData* blendFunc(const ShadowData* from, const ShadowData* to, double progress)
224828{
225829 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));
227832}
228833
229834static inline TransformOperations blendFunc(const TransformOperations& from, const TransformOperations& to, double progress)

@@static inline TransformOperations blendFunc(const TransformOperations& from, con
237842 TransformOperation* fromOp = i < fromSize ? from[i].get() : 0;
238843 TransformOperation* toOp = i < toSize ? to[i].get() : 0;
239844 TransformOperation* blendedOp = toOp ? toOp->blend(fromOp, progress) : fromOp->blend(0, progress, true);
240  result.append(blendedOp);
 845 if (blendedOp)
 846 result.append(blendedOp);
241847 }
242848 return result;
243849}

@@static inline EVisibility blendFunc(EVisibility from, EVisibility to, double pro
254860 return result > 0. ? VISIBLE : (to != VISIBLE ? to : from);
255861}
256862
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  }
 863class PropertyWrapperBase {
 864public:
 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
 874private:
 875 int m_prop;
 876};
 877
 878template <typename T>
 879class PropertyWrapperGetter : public PropertyWrapperBase {
 880public:
 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)();
409889 }
 890
 891protected:
 892 T (RenderStyle::*m_getter)() const;
 893};
410894
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;
 895template <typename T>
 896class PropertyWrapper : public PropertyWrapperGetter<T> {
 897public:
 898 PropertyWrapper(int prop, T (RenderStyle::*getter)() const, void (RenderStyle::*setter)(T))
 899 : PropertyWrapperGetter<T>(prop, getter)
 900 , m_setter(setter)
 901 { }
416902
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);
 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
 908protected:
 909 void (RenderStyle::*m_setter)(T);
 910};
421911
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);
 912class PropertyWrapperShadow : public PropertyWrapperGetter<ShadowData*> {
 913public:
 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)();
 923
 924 if (!shadowa && shadowb || shadowa && !shadowb)
 925 return false;
 926 if (shadowa && shadowb && (*shadowa != *shadowb))
 927 return false;
 928 return true;
426929 }
427930
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;
 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);
433936
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());
 937 if (!shadowa)
 938 shadowa = &defaultShadowData;
 939 if (!shadowb)
 940 shadowb = &defaultShadowData;
 941
 942 (dst->*m_setter)(blendFunc(shadowa, shadowb, prog), false);
 943 }
 944
 945private:
 946 void (RenderStyle::*m_setter)(ShadowData*, bool);
 947};
440948
 949class PropertyWrapperIntSize : public PropertyWrapperGetter<IntSize> {
 950public:
 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);
441962 }
442963
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;
 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));
448970 }
 971
 972private:
 973 void (RenderStyle::*m_setter)(const IntSize&);
 974};
449975
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 }
 976class PropertyWrapperMaybeInvalidColor : public PropertyWrapperBase {
 977public:
 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
 1007private:
 1008 const Color& (RenderStyle::*m_getter)() const;
 1009 void (RenderStyle::*m_setter)(const Color&);
 1010};
4711011
4721012class AnimationControllerPrivate {
4731013public:
4741014 AnimationControllerPrivate(Frame*);
4751015 ~AnimationControllerPrivate();
476 
477  CompositeImplicitAnimation* get(RenderObject*, RenderStyle*);
 1016
 1017 CompositeAnimation* accessCompositeAnimation(RenderObject*);
4781018 bool clear(RenderObject*);
4791019
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
4851044private:
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;
4881052 Frame* m_frame;
 1053 uint32_t m_numStyleAvailableWaiters;
 1054
 1055 static Vector<PropertyWrapperBase*>* gPropertyWrappers;
 1056 static int gPropertyWrapperMap[numCSSProperties];
4891057};
4901058
 1059Vector<PropertyWrapperBase*>* AnimationControllerPrivate::gPropertyWrappers = 0;
 1060int AnimationControllerPrivate::gPropertyWrapperMap[];
 1061
4911062AnimationControllerPrivate::AnimationControllerPrivate(Frame* frame)
492  : m_timer(this, &AnimationControllerPrivate::timerFired)
493  , m_frame(frame)
 1063: m_animationTimer(this, &AnimationControllerPrivate::animationTimerFired)
 1064, m_updateRenderingDispatcher(this, &AnimationControllerPrivate::updateRenderingDispatcherFired)
 1065, m_frame(frame)
 1066, m_numStyleAvailableWaiters(0)
4941067{
 1068 ensurePropertyMap();
4951069}
4961070
4971071AnimationControllerPrivate::~AnimationControllerPrivate()
4981072{
499  deleteAllValues(m_animations);
 1073 deleteAllValues(m_compositeAnimations);
 1074}
 1075
 1076// static
 1077void 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 }
5001151}
5011152
502 CompositeImplicitAnimation* AnimationControllerPrivate::get(RenderObject* renderer, RenderStyle* targetStyle)
 1153// static
 1154bool AnimationControllerPrivate::propertiesEqual(int prop, const RenderStyle* a, const RenderStyle* b)
5031155{
504  CompositeImplicitAnimation* animation = m_animations.get(renderer);
505  if (!animation && targetStyle->transitions()) {
506  animation = new CompositeImplicitAnimation();
507  m_animations.set(renderer, animation);
 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
 1175int 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
 1184bool 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
 1213CompositeAnimation* 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);
5081219 }
5091220 return animation;
5101221}
5111222
5121223bool AnimationControllerPrivate::clear(RenderObject* renderer)
5131224{
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);
5151228 if (!animation)
5161229 return false;
517  animation->reset(renderer);
 1230 animation->resetTransitions(renderer);
 1231 bool wasSuspended = animation->suspended();
5181232 delete animation;
519  return true;
 1233 return !wasSuspended;
5201234}
5211235
522 void AnimationControllerPrivate::updateTimer()
 1236void 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
 1248void AnimationControllerPrivate::updateAnimationTimer()
5231249{
5241250 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()) {
5281257 animating = true;
5291258 break;
5301259 }
5311260 }
5321261
5331262 if (animating) {
534  if (!m_timer.isActive())
535  m_timer.startRepeating(cAnimationTimerDelay);
536  } else if (m_timer.isActive())
537  m_timer.stop();
 1263 if (!m_animationTimer.isActive())
 1264 m_animationTimer.startRepeating(cAnimationTimerDelay);
 1265 } else if (m_animationTimer.isActive())
 1266 m_animationTimer.stop();
5381267}
5391268
540 void AnimationControllerPrivate::timerFired(Timer<AnimationControllerPrivate>* timer)
 1269void AnimationControllerPrivate::updateRenderingDispatcherFired(Timer<AnimationControllerPrivate>*)
 1270{
 1271 if (m_frame && m_frame->document()) {
 1272 m_frame->document()->updateRendering();
 1273 }
 1274}
 1275
 1276void AnimationControllerPrivate::startUpdateRenderingDispatcher()
 1277{
 1278 if (!m_updateRenderingDispatcher.isActive()) {
 1279 m_updateRenderingDispatcher.startOneShot(0);
 1280 }
 1281}
 1282
 1283void AnimationControllerPrivate::animationTimerFired(Timer<AnimationControllerPrivate>* timer)
5411284{
5421285 // When the timer fires, all we do is call setChanged on all DOM nodes with running animations and then do an immediate
5431286 // updateRendering. It will then call back to us with new information.
5441287 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()) {
5481294 animating = true;
549  it->first->element()->setChanged();
 1295 compAnim->setAnimating(false);
 1296 setChanged(renderer->element());
5501297 }
5511298 }
5521299
5531300 m_frame->document()->updateRendering();
5541301
555  updateTimer();
 1302 updateAnimationTimer();
5561303}
5571304
558 AnimationController::AnimationController(Frame* frame)
559 :m_data(new AnimationControllerPrivate(frame))
 1305bool 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
 1313void 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
 1327void 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
 1341void CompositeAnimation::updateTransitions(RenderObject* renderer, RenderStyle* currentStyle, RenderStyle* targetStyle)
 1342{
 1343 // If currentStyle is null, we don't do transitions
 1344 if (!currentStyle)
 1345 return;
 1346
 1347 // Check to see if we need to update the active transitions
 1348 for (const Animation* anim = targetStyle->transitions(); anim; anim = anim->next()) {
 1349 double duration = anim->duration();
 1350 double delay = anim->delay();
 1351
 1352 // If this is an empty transition, skip it
 1353 if (duration == 0 && delay <= 0)
 1354 continue;
 1355
 1356 int prop = anim->property();
 1357 bool all = prop == cAnimateAll;
 1358
 1359 // Handle both the 'all' and single property cases. For the single prop case, we make only one pass
 1360 // through the loop
 1361 for (int i = 0; ; ++i) {
 1362 if (all) {
 1363 if (i >= AnimationControllerPrivate::getNumProperties())
 1364 break;
 1365 // get the next prop
 1366 prop = AnimationControllerPrivate::getPropertyAtIndex(i);
 1367 }
 1368
 1369 // See if there is a current transition for this prop
 1370 ImplicitAnimation* implAnim = m_transitions.get(prop);
 1371 bool equal = true;
 1372
 1373 if (implAnim) {
 1374 // There is one, has our target changed?
 1375 if (!implAnim->isTargetPropertyEqual(prop, targetStyle)) {
 1376 // It has changed - toss it and start over
 1377 // Opacity is special since it can pop in and out of RenderLayers. We need to compute
 1378 // the blended opacity value between the previous from and to styles and put that in the currentStyle, which
 1379 // will become the new fromStyle. This is changing a const RenderStyle, but we know what we are doing, really :-)
 1380 if (prop == CSSPropertyOpacity) {
 1381 // get the blended value of opacity into the currentStyle (which will be the new fromStyle)
 1382 implAnim->blendPropertyValueInStyle(CSSPropertyOpacity, currentStyle);
 1383 }
 1384
 1385 implAnim->reset(renderer);
 1386 delete implAnim;
 1387 m_transitions.remove(prop);
 1388 equal = false;
 1389 }
 1390 }
 1391 else
 1392 // See if we need to start a new transition
 1393 equal = AnimationControllerPrivate::propertiesEqual(prop, currentStyle, targetStyle);
 1394
 1395 if (!equal) {
 1396 // AAdd the new transition
 1397 ImplicitAnimation* animation = new ImplicitAnimation(const_cast<Animation*>(anim), renderer, this);
 1398 m_transitions.set(prop, animation);
 1399 }
 1400
 1401 // We only need one pass for the single prop case
 1402 if (!all)
 1403 break;
 1404 }
 1405 }
 1406}
 1407
 1408RenderStyle* CompositeAnimation::animate(RenderObject* renderer, RenderStyle* currentStyle, RenderStyle* targetStyle)
 1409{
 1410 RenderStyle* resultStyle = 0;
 1411
 1412 // We don't do any transitions if we don't have a currentStyle (on startup)
 1413 updateTransitions(renderer, currentStyle, targetStyle);
 1414
 1415 if (currentStyle) {
 1416 // Now that we have transition objects ready, let them know about the new goal state. We want them
 1417 // to fill in a RenderStyle*& only if needed.
 1418 CSSPropertyTransitionsMap::const_iterator end = m_transitions.end();
 1419 for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it) {
 1420 ImplicitAnimation* anim = it->second;
 1421 if (anim) {
 1422 anim->animate(this, renderer, currentStyle, targetStyle, resultStyle);
 1423 }
 1424 }
 1425 }
 1426
 1427 cleanupFinishedAnimations(renderer);
 1428
 1429 return resultStyle ? resultStyle : targetStyle;
 1430}
 1431
 1432// "animating" means that something is running that requires the timer to keep firing
 1433// (e.g. a transition)
 1434void CompositeAnimation::setAnimating(bool inAnimating)
 1435{
 1436 CSSPropertyTransitionsMap::const_iterator end = m_transitions.end();
 1437 for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it) {
 1438 ImplicitAnimation* transition = it->second;
 1439 transition->setAnimating(inAnimating);
 1440 }
 1441}
 1442
 1443bool CompositeAnimation::animating()
 1444{
 1445 CSSPropertyTransitionsMap::const_iterator end = m_transitions.end();
 1446 for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it) {
 1447 ImplicitAnimation* transition = it->second;
 1448 if (transition && transition->animating() && transition->running())
 1449 return true;
 1450 }
 1451 return false;
 1452}
 1453
 1454void CompositeAnimation::resetTransitions(RenderObject* renderer)
 1455{
 1456 CSSPropertyTransitionsMap::const_iterator end = m_transitions.end();
 1457 for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it) {
 1458 ImplicitAnimation* transition = it->second;
 1459 transition->reset(renderer);
 1460 delete transition;
 1461 }
 1462 m_transitions.clear();
 1463}
 1464
 1465void CompositeAnimation::cleanupFinishedAnimations(RenderObject* renderer)
 1466{
 1467 if (suspended())
 1468 return;
 1469
 1470 // Make a list of transitions to be deleted
 1471 Vector<int> finishedTransitions;
 1472 CSSPropertyTransitionsMap::const_iterator end = m_transitions.end();
 1473
 1474 for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it) {
 1475 ImplicitAnimation* anim = it->second;
 1476 if (!anim)
 1477 continue;
 1478 if (anim->postactive() && !anim->waitingForEndEvent())
 1479 finishedTransitions.append(anim->property());
 1480 }
 1481
 1482 // Delete them
 1483 for (Vector<int>::iterator it = finishedTransitions.begin(); it != finishedTransitions.end(); ++it) {
 1484 ImplicitAnimation* anim = m_transitions.get(*it);
 1485 if (anim) {
 1486 anim->reset(renderer);
 1487 delete anim;
 1488 }
 1489 m_transitions.remove(*it);
 1490 }
 1491}
 1492
 1493void CompositeAnimation::setTransitionStartTime(int property, double t)
 1494{
 1495 // Set the start time for given property transition
 1496 CSSPropertyTransitionsMap::const_iterator end = m_transitions.end();
 1497 for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it) {
 1498 ImplicitAnimation* anim = it->second;
 1499 if (anim && anim->waitingForStartTime() &&
 1500 (anim->property() == property || anim->property() == cAnimateAll))
 1501 anim->updateStateMachine(AnimationBase::STATE_INPUT_START_TIME_SET, t);
 1502 }
 1503}
 1504
 1505void CompositeAnimation::suspendAnimations()
 1506{
 1507 if (m_suspended)
 1508 return;
 1509
 1510 m_suspended = true;
 1511
 1512 CSSPropertyTransitionsMap::const_iterator end = m_transitions.end();
 1513 for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it) {
 1514 ImplicitAnimation* anim = it->second;
 1515 if (anim && anim->hasStyle()) {
 1516 anim->updatePlayState(false);
 1517 }
 1518 }
 1519}
 1520
 1521void CompositeAnimation::resumeAnimations()
 1522{
 1523 if (!m_suspended)
 1524 return;
 1525
 1526 m_suspended = false;
 1527
 1528 CSSPropertyTransitionsMap::const_iterator end = m_transitions.end();
 1529 for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it) {
 1530 ImplicitAnimation* anim = it->second;
 1531 if (anim && anim->hasStyle()) {
 1532 anim->updatePlayState(true);
 1533 }
 1534 }
 1535}
 1536
 1537void CompositeAnimation::overrideImplicitAnimations(int property)
5601538{
 1539 CSSPropertyTransitionsMap::const_iterator end = m_transitions.end();
 1540 for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it) {
 1541 ImplicitAnimation* anim = it->second;
 1542 if (anim && (anim->property() == property || anim->property() == cAnimateAll))
 1543 anim->setOverridden(true);
 1544 }
 1545}
5611546
 1547void CompositeAnimation::resumeOverriddenImplicitAnimations(int property)
 1548{
 1549 CSSPropertyTransitionsMap::const_iterator end = m_transitions.end();
 1550 for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it) {
 1551 ImplicitAnimation* anim = it->second;
 1552 if (anim && (anim->property() == property || anim->property() == cAnimateAll))
 1553 anim->setOverridden(false);
 1554 }
 1555}
 1556
 1557void CompositeAnimation::styleAvailable()
 1558{
 1559 if (m_numStyleAvailableWaiters == 0)
 1560 return;
 1561
 1562 CSSPropertyTransitionsMap::const_iterator end = m_transitions.end();
 1563 for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it) {
 1564 ImplicitAnimation* anim = it->second;
 1565 if (anim && anim->waitingForStyleAvailable())
 1566 anim->updateStateMachine(AnimationBase::STATE_INPUT_STYLE_AVAILABLE, -1);
 1567 }
 1568}
 1569
 1570bool CompositeAnimation::isAnimatingProperty(int property) const
 1571{
 1572 CSSPropertyTransitionsMap::const_iterator end = m_transitions.end();
 1573 for (CSSPropertyTransitionsMap::const_iterator it = m_transitions.begin(); it != end; ++it) {
 1574 ImplicitAnimation* anim = it->second;
 1575 if (anim && anim->isAnimatingProperty(property))
 1576 return true;
 1577 }
 1578 return false;
 1579}
 1580
 1581void ImplicitAnimation::animate(CompositeAnimation* animation, RenderObject* renderer, const RenderStyle* currentStyle,
 1582 const RenderStyle* targetStyle, RenderStyle*& ioAnimatedStyle)
 1583{
 1584 if (paused())
 1585 return;
 1586
 1587 // If we get this far and the animation is done, it means we are cleaning up a just finished animation.
 1588 // If so, send back the targetStyle (it will get tossed later)
 1589 if (postactive()) {
 1590 if (!ioAnimatedStyle)
 1591 ioAnimatedStyle = const_cast<RenderStyle*>(targetStyle);
 1592 return;
 1593 }
 1594
 1595 // Reset to start the transition if we are new
 1596 if (isnew())
 1597 reset(renderer, currentStyle, targetStyle);
 1598
 1599 // Run a cycle of animation.
 1600 // We know we will need a new render style, so make one if needed
 1601 if (!ioAnimatedStyle)
 1602 ioAnimatedStyle = new (renderer->renderArena()) RenderStyle(*targetStyle);
 1603
 1604 double prog = progress(1, 0);
 1605 bool needsAnim = AnimationControllerPrivate::blendProperties(m_property, ioAnimatedStyle, m_fromStyle, m_toStyle, prog);
 1606 if (needsAnim)
 1607 setAnimating();
 1608}
 1609
 1610bool ImplicitAnimation::startAnimation(double beginTime)
 1611{
 1612 return false;
 1613}
 1614
 1615void ImplicitAnimation::endAnimation(bool reset)
 1616{
 1617}
 1618
 1619void ImplicitAnimation::onAnimationEnd(double inElapsedTime)
 1620{
 1621 // we're converting the animation into a transition here
 1622 if (!sendTransitionEvent(EventNames::webkitTransitionEndEvent, inElapsedTime)) {
 1623 // we didn't dispatch an event, which would call endAnimation(), so we'll just end
 1624 // it here.
 1625 endAnimation(true);
 1626 }
 1627}
 1628
 1629bool ImplicitAnimation::sendTransitionEvent(const AtomicString& inEventType, double inElapsedTime)
 1630{
 1631 return false; // didn't dispatch an event
 1632}
 1633
 1634void ImplicitAnimation::reset(RenderObject* renderer, const RenderStyle* from /* = 0 */, const RenderStyle* to /* = 0 */)
 1635{
 1636 ASSERT((!m_toStyle && !to) || m_toStyle != to);
 1637 ASSERT((!m_fromStyle && !from) || m_fromStyle != from);
 1638 if (m_fromStyle)
 1639 m_fromStyle->deref(renderer->renderArena());
 1640 if (m_toStyle)
 1641 m_toStyle->deref(renderer->renderArena());
 1642
 1643 m_fromStyle = const_cast<RenderStyle*>(from); // it is read-only, other than the ref
 1644 if (m_fromStyle)
 1645 m_fromStyle->ref();
 1646
 1647 m_toStyle = const_cast<RenderStyle*>(to); // it is read-only, other than the ref
 1648 if (m_toStyle)
 1649 m_toStyle->ref();
 1650
 1651 // restart the transition
 1652 if (from && to)
 1653 updateStateMachine(STATE_INPUT_RESTART_ANIMATION, -1);
 1654}
 1655
 1656void ImplicitAnimation::setOverridden(bool b)
 1657{
 1658 if (b != m_overridden) {
 1659 m_overridden = b;
 1660 updateStateMachine(m_overridden ? STATE_INPUT_PAUSE_OVERRIDE : STATE_INPUT_RESUME_OVERRIDE, -1);
 1661 }
 1662}
 1663
 1664bool ImplicitAnimation::affectsProperty(int property) const
 1665{
 1666 return m_property == property ||
 1667 (m_property == cAnimateAll && !AnimationControllerPrivate::propertiesEqual(property, m_fromStyle, m_toStyle));
 1668}
 1669
 1670bool ImplicitAnimation::isTargetPropertyEqual(int prop, RenderStyle* targetStyle)
 1671{
 1672 return AnimationControllerPrivate::propertiesEqual(prop, m_toStyle, targetStyle);
 1673}
 1674
 1675void ImplicitAnimation::blendPropertyValueInStyle(int prop, RenderStyle* currentStyle)
 1676{
 1677 double prog = progress(1, 0);
 1678 AnimationControllerPrivate::blendProperties(prop, currentStyle, m_fromStyle, m_toStyle, prog);
 1679}
 1680
 1681AnimationController::AnimationController(Frame* frame)
 1682: m_data(new AnimationControllerPrivate(frame))
 1683{
 1684
5621685}
5631686
5641687AnimationController::~AnimationController()

@@AnimationController::~AnimationController()
5661689 delete m_data;
5671690}
5681691
569 void AnimationController::cancelImplicitAnimations(RenderObject* renderer)
 1692void AnimationController::cancelAnimations(RenderObject* renderer)
5701693{
571  if (!m_data->hasImplicitAnimations())
 1694 if (!m_data->hasAnimations())
5721695 return;
573 
 1696
5741697 if (m_data->clear(renderer))
575  renderer->element()->setChanged();
 1698 setChanged(renderer->element());
5761699}
5771700
578 RenderStyle* AnimationController::updateImplicitAnimations(RenderObject* renderer, RenderStyle* newStyle)
579 {
 1701RenderStyle* AnimationController::updateAnimations(RenderObject* renderer, RenderStyle* newStyle)
 1702{
 1703 // don't do anything if we're in the cache
 1704 if (!renderer->document() || renderer->document()->inPageCache())
 1705 return newStyle;
 1706
 1707 RenderStyle* oldStyle = renderer->style();
 1708
 1709 if ((!oldStyle || !oldStyle->transitions()) && !newStyle->transitions())
 1710 return newStyle;
 1711
 1712 RenderStyle* blendedStyle = newStyle;
 1713
5801714 // Fetch our current set of implicit animations from a hashtable. We then compare them
5811715 // against the animations in the style and make sure we're in sync. If destination values
5821716 // have changed, we reset the animation. We then do a blend to get new values and we return
5831717 // a new style.
5841718 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 
 1719
 1720 CompositeAnimation* rendererAnimations = m_data->accessCompositeAnimation(renderer);
 1721 blendedStyle = rendererAnimations->animate(renderer, oldStyle, newStyle);
 1722
 1723 m_data->updateAnimationTimer();
 1724
5931725 if (blendedStyle != newStyle) {
594  // Do some of the work that CSSStyleSelector::adjustRenderStyle() does, to impose rules
595  // like opacity creating stacking context.
 1726 // If the animations/transitions change opacity or transform, we neeed to update
 1727 // the style to impose the stacking rules. Note that this is also
 1728 // done in CSSStyleSelector::adjustRenderStyle().
5961729 if (blendedStyle->hasAutoZIndex() && (blendedStyle->opacity() < 1.0f || blendedStyle->hasTransform()))
5971730 blendedStyle->setZIndex(0);
5981731 }
599 
6001732 return blendedStyle;
6011733}
6021734
603 void AnimationController::suspendAnimations()
 1735bool AnimationController::isAnimatingPropertyOnRenderer(RenderObject* obj, int property) const
 1736{
 1737 return m_data->isAnimatingPropertyOnRenderer(obj, property);
 1738}
 1739
 1740void AnimationController::suspendAnimations(Document* document)
6041741{
605  // FIXME: Walk the whole hashtable and call pause on each animation.
606  // Kill our timer.
 1742#ifdef DEBUG_STATE_MACHINE
 1743 fprintf(stderr, "AnimationController %p suspendAnimations for document %p\n", this, document);
 1744#endif
 1745 m_data->suspendAnimations(document);
6071746}
6081747
609 void AnimationController::resumeAnimations()
 1748void AnimationController::resumeAnimations(Document* document)
6101749{
611  // FIXME: Walk the whole hashtable and call resume on each animation.
612  // Start our timer.
 1750#ifdef DEBUG_STATE_MACHINE
 1751 fprintf(stderr, "AnimationController %p resumeAnimations for document %p\n", this, document);
 1752#endif
 1753 m_data->resumeAnimations(document);
6131754}
6141755
 1756void AnimationController::startUpdateRenderingDispatcher()
 1757{
 1758 m_data->startUpdateRenderingDispatcher();
 1759}
 1760
 1761void AnimationController::styleAvailable()
 1762{
 1763 m_data->styleAvailable();
 1764}
 1765
 1766void CompositeAnimation::setWaitingForStyleAvailable(bool waiting)
 1767{
 1768 if (waiting)
 1769 m_numStyleAvailableWaiters++;
 1770 else
 1771 m_numStyleAvailableWaiters--;
 1772 m_animationController->setWaitingForStyleAvailable(waiting);
 1773}
 1774
6151775}

WebCore/page/AnimationController.h

2929#ifndef AnimationController_h
3030#define AnimationController_h
3131
 32#include "CSSPropertyNames.h"
 33
3234namespace WebCore {
3335
3436class AnimationControllerPrivate;
 37class Document;
3538class Frame;
3639class RenderObject;
3740class RenderStyle;

@@public:
4245 AnimationController(Frame*);
4346 ~AnimationController();
4447
45  void cancelImplicitAnimations(RenderObject*);
46  RenderStyle* updateImplicitAnimations(RenderObject*, RenderStyle* newStyle);
 48 void cancelAnimations(RenderObject*);
 49 RenderStyle* updateAnimations(RenderObject*, RenderStyle* newStyle);
 50
 51 bool isAnimatingPropertyOnRenderer(RenderObject* obj, int property) const;
 52
 53 void suspendAnimations(Document* document);
 54 void resumeAnimations(Document* document);
 55 void updateAnimationTimer();
4756
48  void suspendAnimations();
49  void resumeAnimations();
 57 void startUpdateRenderingDispatcher();
 58
 59 void styleAvailable();
5060
5161private:
5262 AnimationControllerPrivate* m_data;
 63
5364};
5465
5566}

WebCore/page/Frame.cpp

@@void Frame::clearTimers(FrameView *view, Document *document)
14801480 if (view->frame()) {
14811481 if (document && document->renderer() && document->renderer()->hasLayer())
14821482 document->renderer()->layer()->suspendMarquees();
1483  view->frame()->animation()->suspendAnimations();
 1483 view->frame()->animation()->suspendAnimations(document);
14841484 view->frame()->eventHandler()->stopAutoscrollTimer();
14851485 }
14861486 }

WebCore/rendering/RenderObject.cpp

@@void RenderObject::handleDynamicFloatPositionChange()
21562156void RenderObject::setAnimatableStyle(RenderStyle* style)
21572157{
21582158 if (!isText() && m_style && style)
2159  style = animation()->updateImplicitAnimations(this, style);
 2159 style = animation()->updateAnimations(this, style);
21602160
21612161 setStyle(style);
21622162}

@@void RenderObject::destroy()
25352535 if (AXObjectCache::accessibilityEnabled())
25362536 document()->axObjectCache()->remove(this);
25372537
2538  animation()->cancelImplicitAnimations(this);
 2538 animation()->cancelAnimations(this);
25392539
25402540 // By default no ref-counting. RenderWidget::destroy() doesn't call
25412541 // this function because it needs to do ref-counting. If anything

WebCore/rendering/RenderWidget.cpp

@@void RenderWidget::destroy()
7272 // So the code below includes copied and pasted contents of
7373 // both RenderBox::destroy() and RenderObject::destroy().
7474 // Fix originally made for <rdar://problem/4228818>.
75  animation()->cancelImplicitAnimations(this);
 75 animation()->cancelAnimations(this);
7676
7777 if (RenderView* v = view())
7878 v->removeWidget(this);

WebCore/rendering/style/RenderStyle.cpp

@@TransformOperation* MatrixTransformOperation::blend(const TransformOperation* fr
664664 fromF + (m_f - fromF) * progress);
665665}
666666
667 Transition::Transition()
668  : m_duration(RenderStyle::initialTransitionDuration())
669  , m_repeatCount(RenderStyle::initialTransitionRepeatCount())
670  , m_timingFunction(RenderStyle::initialTransitionTimingFunction())
671  , m_property(RenderStyle::initialTransitionProperty())
 667Animation::Animation()
 668 : m_duration(RenderStyle::initialDuration())
 669 , m_timingFunction(RenderStyle::initialTimingFunction())
 670 , m_delay(RenderStyle::initialDelay())
 671 , m_property(RenderStyle::initialProperty())
672672 , m_durationSet(false)
673  , m_repeatCountSet(false)
674673 , m_timingFunctionSet(false)
 674 , m_delaySet(false)
675675 , m_propertySet(false)
676676 , m_next(0)
677677{
678678}
679679
680 Transition::Transition(const Transition& o)
681  : m_duration(o.m_duration)
682  , m_repeatCount(o.m_repeatCount)
 680Animation::Animation(const Animation& o)
 681 : RefCounted<Animation>()
 682 , m_duration(o.m_duration)
683683 , m_timingFunction(o.m_timingFunction)
 684 , m_delay(o.m_delay)
684685 , m_property(o.m_property)
685686 , m_durationSet(o.m_durationSet)
686  , m_repeatCountSet(o.m_repeatCountSet)
687687 , m_timingFunctionSet(o.m_timingFunctionSet)
 688 , m_delaySet(o.m_delaySet)
688689 , m_propertySet(o.m_propertySet)
689  , m_next(o.m_next ? new Transition(*o.m_next) : 0)
 690 , m_next(o.m_next ? new Animation(*(o.m_next.get())) : 0)
690691{
691692}
692693
693 Transition::~Transition()
694 {
695  delete m_next;
696 }
697 
698 Transition& Transition::operator=(const Transition& o)
 694Animation& Animation::operator=(const Animation& o)
699695{
700696 if (m_next != o.m_next) {
701  delete m_next;
702  m_next = o.m_next ? new Transition(*o.m_next) : 0;
 697 m_next = o.m_next ? new Animation(*(o.m_next.get())) : 0;
703698 }
704699
 700 m_delay = o.m_delay;
705701 m_duration = o.m_duration;
706  m_repeatCount = o.m_repeatCount;
707702 m_timingFunction = o.m_timingFunction;
708703 m_property = o.m_property;
709704
 705 m_delaySet = o.m_delaySet;
710706 m_durationSet = o.m_durationSet;
711  m_repeatCountSet = o.m_repeatCountSet;
712707 m_timingFunctionSet = o.m_timingFunctionSet;
713708 m_propertySet = o.m_propertySet;
714709
715710 return *this;
716711}
717712
718 bool Transition::operator==(const Transition& o) const
 713bool Animation::animationsMatch(const Animation* o) const
719714{
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  }
 715 if (!o)
 716 return false;
739717
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  }
 718 bool result = m_duration == o->m_duration &&
 719 m_timingFunction == o->m_timingFunction &&
 720 m_delay == o->m_delay &&
 721 m_property == o->m_property &&
 722 m_durationSet == o->m_durationSet &&
 723 m_timingFunctionSet == o->m_timingFunctionSet &&
 724 m_delaySet == o->m_delaySet &&
 725 m_propertySet == o->m_propertySet;
750726
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  }
 727 return result;
 728}
761729
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  }
 730#define FILL_UNSET_PROPERTY(test, prop) \
 731for (curr = this; curr && curr->test(); curr = curr->next()) { } \
 732if (curr && curr != this) { \
 733/* We need to fill in the remaining values with the pattern specified. */ \
 734for (Animation* pattern = this; curr; curr = curr->next()) { \
 735curr->prop = pattern->prop; \
 736pattern = pattern->next(); \
 737if (pattern == curr || !pattern) \
 738pattern = this; \
 739} \
 740}
 741
 742void Animation::fillUnsetProperties()
 743{
 744 Animation* curr;
 745 FILL_UNSET_PROPERTY(isDurationSet, m_duration);
 746 FILL_UNSET_PROPERTY(isTimingFunctionSet, m_timingFunction);
 747 FILL_UNSET_PROPERTY(isDelaySet, m_delay);
 748 FILL_UNSET_PROPERTY(isPropertySet, m_property);
772749}
773750
774751StyleRareNonInheritedData::StyleRareNonInheritedData()

@@StyleRareNonInheritedData::StyleRareNonInheritedData(const StyleRareNonInherited
811788 , m_borderFit(o.m_borderFit)
812789 , m_boxShadow(o.m_boxShadow ? new ShadowData(*o.m_boxShadow) : 0)
813790 , m_boxReflect(o.m_boxReflect)
814  , m_transition(o.m_transition ? new Transition(*o.m_transition) : 0)
 791 , m_transition(o.m_transition ? new Animation(*o.m_transition) : 0)
815792 , m_mask(o.m_mask)
816793 , m_maskBoxImage(o.m_maskBoxImage)
817794#if ENABLE(XBL)

@@StyleRareNonInheritedData::~StyleRareNonInheritedData()
825802 delete m_content;
826803 delete m_counterDirectives;
827804 delete m_boxShadow;
828  delete m_transition;
829805#if ENABLE(XBL)
830806 delete bindingURI;
831807#endif

@@RenderStyle::Diff RenderStyle::diff(const RenderStyle* other) const
14941470 // Cursors are not checked, since they will be set appropriately in response to mouse events,
14951471 // so they don't need to cause any repaint or layout.
14961472
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 off
 1473 // 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
14981474 // the resulting transition properly.
14991475 return Equal;
15001476}

@@const Vector<StyleDashboardRegion>& RenderStyle::noneDashboardRegions()
18711847void RenderStyle::adjustTransitions()
18721848{
18731849 if (transitions()) {
1874  if (transitions()->isEmpty()) {
 1850 if (transitions()->isEmptyOrZeroDuration()) {
18751851 clearTransitions();
18761852 return;
18771853 }
18781854
1879  Transition* next;
1880  for (Transition* p = accessTransitions(); p; p = next) {
1881  next = p->m_next;
 1855 Animation* next;
 1856 for (Animation* p = accessTransitions(); p; p = next) {
 1857 next = p->next();
18821858 if (next && next->isEmpty()) {
1883  delete next;
1884  p->m_next = 0;
 1859 p->setNext(0); // removes the ref, so next gets deleted
 1860 next = 0;
18851861 break;
18861862 }
18871863 }
1888 
 1864
 1865 if (!transitions())
 1866 return;
 1867
18891868 // Repeat patterns into layers that don't have some properties set.
18901869 accessTransitions()->fillUnsetProperties();
 1870
 1871 // Make sure there are no duplicate properties. This is an O(n^2) algorithm
 1872 // but the lists tend to be very short, so it is probably ok
 1873 Animation* previ = 0;
 1874 for (Animation* pi = accessTransitions(); pi; ) {
 1875 Animation* nexti = pi->next();
 1876 for (Animation* pj = nexti; pj; ) {
 1877 if (pi->property() == pj->property()) {
 1878 // toss pi
 1879 pi = pi->next();
 1880 if (previ)
 1881 previ->setNext(pi);
 1882 else
 1883 rareNonInheritedData.access()->m_transition = pi;
 1884 nexti = pi->next();
 1885 pj = nexti;
 1886 }
 1887 else
 1888 pj = pj->next();
 1889 }
 1890 previ = pi;
 1891 pi = nexti;
 1892 }
18911893 }
18921894}
18931895
1894 Transition* RenderStyle::accessTransitions()
 1896Animation* RenderStyle::accessTransitions()
18951897{
1896  Transition* layer = rareNonInheritedData.access()->m_transition;
 1898 Animation* layer = rareNonInheritedData.access()->m_transition.get();
18971899 if (!layer)
1898  rareNonInheritedData.access()->m_transition = new Transition();
1899  return rareNonInheritedData->m_transition;
 1900 rareNonInheritedData.access()->m_transition = new Animation();
 1901 return rareNonInheritedData->m_transition.get();
19001902}
19011903
19021904}

WebCore/rendering/style/RenderStyle.h

@@private:
12571257 double m_y2;
12581258};
12591259
1260 struct Transition {
 1260class Animation : public RefCounted<Animation> {
12611261public:
1262  Transition();
1263  ~Transition();
 1262 Animation();
12641263
1265  Transition* next() const { return m_next; }
1266  Transition* next() { return m_next; }
 1264 const Animation* next() const { return m_next.get(); }
 1265 Animation* next() { return m_next.get(); }
12671266
 1267 bool isDelaySet() const { return m_delaySet; }
12681268 bool isDurationSet() const { return m_durationSet; }
1269  bool isRepeatCountSet() const { return m_repeatCountSet; }
12701269 bool isTimingFunctionSet() const { return m_timingFunctionSet; }
12711270 bool isPropertySet() const { return m_propertySet; }
1272 
1273  bool isEmpty() const { return !m_durationSet && !m_repeatCountSet && !m_timingFunctionSet && !m_propertySet; }
 1271
 1272 bool isEmpty() const
 1273 {
 1274 return (!m_durationSet && !m_delaySet && !m_timingFunctionSet && !m_propertySet);
 1275 }
 1276
 1277 bool isEmptyOrZeroDuration() const
 1278 {
 1279 return isEmpty() || (m_duration == 0 && m_delay <= 0);
 1280 }
 1281
 1282 void clearDelay() { m_delaySet = false; }
12741283 void clearDuration() { m_durationSet = false; }
1275  void clearRepeatCount() { m_repeatCountSet = false; }
12761284 void clearTimingFunction() { m_timingFunctionSet = false; }
 1285
12771286 void clearProperty() { m_propertySet = false; }
12781287
1279  int duration() const { return m_duration; }
1280  int repeatCount() const { return m_repeatCount; }
 1288 double delay() const { return m_delay; }
 1289 double duration() const { return m_duration; }
12811290 const TimingFunction& timingFunction() const { return m_timingFunction; }
12821291 int property() const { return m_property; }
1283 
1284  void setDuration(int d) { m_duration = d; m_durationSet = true; }
1285  void setRepeatCount(int c) { m_repeatCount = c; m_repeatCountSet = true; }
 1292
 1293 void setDelay(double c) { m_delay = c; m_delaySet = true; }
 1294 void setDuration(double d) { ASSERT(d >= 0); m_duration = d; m_durationSet = true; }
12861295 void setTimingFunction(const TimingFunction& f) { m_timingFunction = f; m_timingFunctionSet = true; }
12871296 void setProperty(int t) { m_property = t; m_propertySet = true; }
 1297 void setNext(Animation* n) { if (m_next.get() != n) { m_next = n; } }
12881298
1289  void setNext(Transition* n) { if (m_next != n) { delete m_next; m_next = n; } }
 1299 Animation& operator=(const Animation& o);
 1300 Animation(const Animation& o);
12901301
1291  Transition& operator=(const Transition& o);
1292  Transition(const Transition& o);
 1302 // return true if all members of this class match (excluding m_next)
 1303 bool animationsMatch(const Animation* t) const;
12931304
1294  bool operator==(const Transition& o) const;
1295  bool operator!=(const Transition& o) const {
1296  return !(*this == o);
1297  }
 1305 // return true every Animation in the chain (defined by m_next) match
 1306 bool operator==(const Animation& o) const { return animationsMatch(&o) && ((m_next && o.m_next) ? (*m_next == *o.m_next) : (m_next == o.m_next)); }
 1307 bool operator!=(const Animation& o) const { return !(*this == o); }
12981308
12991309 void fillUnsetProperties();
13001310
1301  int m_duration;
1302  int m_repeatCount;
 1311private:
 1312 double m_duration;
13031313 TimingFunction m_timingFunction;
 1314 double m_delay;
13041315 int m_property;
13051316
1306  bool m_durationSet;
1307  bool m_repeatCountSet;
1308  bool m_timingFunctionSet;
1309  bool m_propertySet;
1310 
1311  Transition* m_next;
 1317 bool m_durationSet : 1;
 1318 bool m_timingFunctionSet : 1;
 1319 bool m_delaySet : 1;
 1320 bool m_propertySet : 1;
 1321
 1322 RefPtr<Animation> m_next;
13121323};
13131324
13141325class StyleReflection : public RefCounted<StyleReflection> {

@@public:
13891400
13901401 RefPtr<StyleReflection> m_boxReflect;
13911402
1392  Transition* m_transition;
 1403 RefPtr<Animation> m_transition;
13931404
13941405 FillLayer m_mask;
13951406 NinePieceImage m_maskBoxImage;

@@public:
20302041 return background->m_outline._offset;
20312042 }
20322043 ShadowData* textShadow() const { return rareInheritedData->textShadow; }
2033  Color textStrokeColor() const { return rareInheritedData->textStrokeColor; }
 2044 const Color& textStrokeColor() const { return rareInheritedData->textStrokeColor; }
20342045 float textStrokeWidth() const { return rareInheritedData->textStrokeWidth; }
2035  Color textFillColor() const { return rareInheritedData->textFillColor; }
 2046 const Color& textFillColor() const { return rareInheritedData->textFillColor; }
20362047 float opacity() const { return rareNonInheritedData->opacity; }
20372048 EAppearance appearance() const { return static_cast<EAppearance>(rareNonInheritedData->m_appearance); }
20382049 EBoxAlignment boxAlign() const { return static_cast<EBoxAlignment>(rareNonInheritedData->flexibleBox->align); }

@@public:
20872098 // End CSS3 Getters
20882099
20892100 // Apple-specific property getter methods
2090  Transition* accessTransitions();
2091  const Transition* transitions() const { return rareNonInheritedData->m_transition; }
 2101 Animation* accessTransitions();
 2102 const Animation* transitions() const { return rareNonInheritedData->m_transition.get(); }
20922103 int lineClamp() const { return rareNonInheritedData->lineClamp; }
20932104 bool textSizeAdjust() const { return rareInheritedData->textSizeAdjust; }
20942105 ETextSecurity textSecurity() const { return static_cast<ETextSecurity>(rareInheritedData->textSecurity); }

@@public:
23522363 // End CSS3 Setters
23532364
23542365 // 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); }
 2366 void clearTransitions() { rareNonInheritedData.access()->m_transition = 0; }
 2367 void inheritTransitions(const Animation* parent) { clearTransitions(); if (parent) rareNonInheritedData.access()->m_transition = new Animation(*parent); }
23572368 void adjustTransitions();
23582369 void setLineClamp(int c) { SET_VAR(rareNonInheritedData, lineClamp, c); }
23592370 void setTextSizeAdjust(bool b) { SET_VAR(rareInheritedData, textSizeAdjust, b); }

@@public:
25112522 static Length initialTransformOriginY() { return Length(50.0, Percent); }
25122523
25132524 // Keep these at the end.
2514  static int initialTransitionDuration() { return 0; }
2515  static int initialTransitionRepeatCount() { return 1; }
2516  static TimingFunction initialTransitionTimingFunction() { return TimingFunction(); }
2517  static int initialTransitionProperty() { return cAnimateAll; }
 2525 static float initialDelay() { return 0; }
 2526 static double initialDuration() { return 0; }
 2527 static TimingFunction initialTimingFunction() { return TimingFunction(); }
 2528 static int initialProperty() { return cAnimateAll; }
25182529 static int initialLineClamp() { return -1; }
25192530 static bool initialTextSizeAdjust() { return true; }
25202531 static ETextSecurity initialTextSecurity() { return TSNONE; }