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 }