1 /* 2 * Copyright (C) 2007, 2008, 2009 Apple Inc. All rights reserved. 3 * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 15 * its contributors may be used to endorse or promote products derived 16 * from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 */ 29 30 #include "config.h" 31 #include "core/frame/animation/CSSPropertyAnimation.h" 32 33 #include <algorithm> 34 #include "StylePropertyShorthand.h" 35 #include "core/animation/css/CSSAnimations.h" 36 #include "core/css/CSSCrossfadeValue.h" 37 #include "core/css/CSSImageValue.h" 38 #include "core/css/CSSPrimitiveValue.h" 39 #include "core/fetch/ImageResource.h" 40 #include "core/frame/animation/AnimationBase.h" 41 #include "core/rendering/ClipPathOperation.h" 42 #include "core/rendering/RenderBox.h" 43 #include "core/rendering/style/RenderStyle.h" 44 #include "core/rendering/style/ShadowList.h" 45 #include "core/rendering/style/StyleFetchedImage.h" 46 #include "core/rendering/style/StyleGeneratedImage.h" 47 #include "platform/FloatConversion.h" 48 #include "wtf/Noncopyable.h" 49 50 namespace WebCore { 51 52 template <typename T> 53 static inline T blendFunc(const AnimationBase*, T from, T to, double progress) 54 { 55 return blend(from, to, progress); 56 } 57 58 static inline float blendFunc(const AnimationBase*, float from, float to, double progress) 59 { 60 return narrowPrecisionToFloat(from + (to - from) * progress); 61 } 62 63 static inline Color blendFunc(const AnimationBase*, const Color& from, const Color& to, double progress) 64 { 65 return blend(from, to, progress); 66 } 67 68 static inline Length blendFunc(const AnimationBase*, const Length& from, const Length& to, double progress) 69 { 70 return to.blend(from, progress, ValueRangeAll); 71 } 72 73 static inline BorderImageLength blendFunc(const AnimationBase* anim, const BorderImageLength& from, const BorderImageLength& to, double progress) 74 { 75 if (from.isNumber() && to.isNumber()) 76 return BorderImageLength(blendFunc(anim, from.number(), to.number(), progress)); 77 78 if (from.isLength() && to.isLength()) 79 return BorderImageLength(blendFunc(anim, from.length(), to.length(), progress)); 80 81 // FIXME: Converting numbers to lengths using the computed border 82 // width would make it possible to interpolate between numbers and 83 // lengths. 84 // https://code.google.com/p/chromium/issues/detail?id=316164 85 return to; 86 } 87 88 static inline BorderImageLengthBox blendFunc(const AnimationBase* anim, const BorderImageLengthBox& from, 89 const BorderImageLengthBox& to, double progress) 90 { 91 return BorderImageLengthBox(blendFunc(anim, from.top(), to.top(), progress), 92 blendFunc(anim, from.right(), to.right(), progress), 93 blendFunc(anim, from.bottom(), to.bottom(), progress), 94 blendFunc(anim, from.left(), to.left(), progress)); 95 } 96 97 static inline LengthSize blendFunc(const AnimationBase* anim, const LengthSize& from, const LengthSize& to, double progress) 98 { 99 return LengthSize(blendFunc(anim, from.width(), to.width(), progress), 100 blendFunc(anim, from.height(), to.height(), progress)); 101 } 102 103 static inline LengthPoint blendFunc(const AnimationBase* anim, const LengthPoint& from, const LengthPoint& to, double progress) 104 { 105 return LengthPoint(blendFunc(anim, from.x(), to.x(), progress), blendFunc(anim, from.y(), to.y(), progress)); 106 } 107 108 static inline TransformOperations blendFunc(const AnimationBase* anim, const TransformOperations& from, const TransformOperations& to, double progress) 109 { 110 if (anim->isTransformFunctionListValid()) 111 return to.blendByMatchingOperations(from, progress); 112 return to.blendByUsingMatrixInterpolation(from, progress); 113 } 114 115 static inline PassRefPtr<ClipPathOperation> blendFunc(const AnimationBase*, ClipPathOperation* from, ClipPathOperation* to, double progress) 116 { 117 // Other clip-path operations than BasicShapes can not be animated. 118 if (!from || !to || from->type() != ClipPathOperation::SHAPE || to->type() != ClipPathOperation::SHAPE) 119 return to; 120 121 const BasicShape* fromShape = toShapeClipPathOperation(from)->basicShape(); 122 const BasicShape* toShape = toShapeClipPathOperation(to)->basicShape(); 123 124 if (!fromShape->canBlend(toShape)) 125 return to; 126 127 return ShapeClipPathOperation::create(toShape->blend(fromShape, progress)); 128 } 129 130 static inline PassRefPtr<ShapeValue> blendFunc(const AnimationBase*, ShapeValue* from, ShapeValue* to, double progress) 131 { 132 // FIXME Bug 102723: Shape-inside should be able to animate a value of 'outside-shape' when shape-outside is set to a BasicShape 133 if (!from || !to || from->type() != ShapeValue::Shape || to->type() != ShapeValue::Shape) 134 return to; 135 136 const BasicShape* fromShape = from->shape(); 137 const BasicShape* toShape = to->shape(); 138 139 if (!fromShape->canBlend(toShape)) 140 return to; 141 142 return ShapeValue::createShapeValue(toShape->blend(fromShape, progress)); 143 } 144 145 static inline FilterOperations blendFunc(const AnimationBase* anim, const FilterOperations& from, const FilterOperations& to, double progress) 146 { 147 FilterOperations result; 148 149 // If we have a filter function list, use that to do a per-function animation. 150 if (anim->filterFunctionListsMatch()) { 151 size_t fromSize = from.operations().size(); 152 size_t toSize = to.operations().size(); 153 size_t size = max(fromSize, toSize); 154 for (size_t i = 0; i < size; i++) { 155 const FilterOperation* fromOp = (i < fromSize) ? from.operations()[i].get() : 0; 156 const FilterOperation* toOp = (i < toSize) ? to.operations()[i].get() : 0; 157 RefPtr<FilterOperation> blendedOp = FilterOperation::blend(fromOp, toOp, progress); 158 if (blendedOp) 159 result.operations().append(blendedOp); 160 else 161 ASSERT_NOT_REACHED(); 162 } 163 } else { 164 // If the filter function lists don't match, we could try to cross-fade, but don't yet have a way to represent that in CSS. 165 // For now we'll just fail to animate. 166 result = to; 167 } 168 169 return result; 170 } 171 172 static inline EVisibility blendFunc(const AnimationBase* anim, EVisibility from, EVisibility to, double progress) 173 { 174 // Any non-zero result means we consider the object to be visible. Only at 0 do we consider the object to be 175 // invisible. The invisible value we use (HIDDEN vs. COLLAPSE) depends on the specified from/to values. 176 double fromVal = from == VISIBLE ? 1. : 0.; 177 double toVal = to == VISIBLE ? 1. : 0.; 178 if (fromVal == toVal) 179 return to; 180 double result = blendFunc(anim, fromVal, toVal, progress); 181 return result > 0. ? VISIBLE : (to != VISIBLE ? to : from); 182 } 183 184 static inline LengthBox blendFunc(const AnimationBase* anim, const LengthBox& from, const LengthBox& to, double progress) 185 { 186 // Length types have to match to animate 187 if (from.top().type() != to.top().type() 188 || from.right().type() != to.right().type() 189 || from.bottom().type() != to.bottom().type() 190 || from.left().type() != to.left().type()) 191 return to; 192 193 LengthBox result(blendFunc(anim, from.top(), to.top(), progress), 194 blendFunc(anim, from.right(), to.right(), progress), 195 blendFunc(anim, from.bottom(), to.bottom(), progress), 196 blendFunc(anim, from.left(), to.left(), progress)); 197 return result; 198 } 199 200 static inline SVGLength blendFunc(const AnimationBase*, const SVGLength& from, const SVGLength& to, double progress) 201 { 202 return to.blend(from, narrowPrecisionToFloat(progress)); 203 } 204 205 static inline Vector<SVGLength> blendFunc(const AnimationBase*, const Vector<SVGLength>& from, const Vector<SVGLength>& to, double progress) 206 { 207 size_t fromLength = from.size(); 208 size_t toLength = to.size(); 209 if (!fromLength) 210 return !progress ? from : to; 211 if (!toLength) 212 return progress == 1 ? from : to; 213 214 size_t resultLength = fromLength; 215 if (fromLength != toLength) { 216 if (!(fromLength % toLength)) 217 resultLength = fromLength; 218 else if (!(toLength % fromLength)) 219 resultLength = toLength; 220 else 221 resultLength = fromLength * toLength; 222 } 223 Vector<SVGLength> result(resultLength); 224 for (size_t i = 0; i < resultLength; ++i) 225 result[i] = to[i % toLength].blend(from[i % fromLength], narrowPrecisionToFloat(progress)); 226 return result; 227 } 228 229 static inline PassRefPtr<StyleImage> crossfadeBlend(const AnimationBase*, StyleFetchedImage* fromStyleImage, StyleFetchedImage* toStyleImage, double progress) 230 { 231 // If progress is at one of the extremes, we want getComputedStyle to show the image, 232 // not a completed cross-fade, so we hand back one of the existing images. 233 if (!progress) 234 return fromStyleImage; 235 if (progress == 1) 236 return toStyleImage; 237 238 ImageResource* fromImageResource = static_cast<ImageResource*>(fromStyleImage->data()); 239 ImageResource* toImageResource = static_cast<ImageResource*>(toStyleImage->data()); 240 241 RefPtr<CSSImageValue> fromImageValue = CSSImageValue::create(fromImageResource->url(), fromStyleImage); 242 RefPtr<CSSImageValue> toImageValue = CSSImageValue::create(toImageResource->url(), toStyleImage); 243 RefPtr<CSSCrossfadeValue> crossfadeValue = CSSCrossfadeValue::create(fromImageValue, toImageValue); 244 245 crossfadeValue->setPercentage(CSSPrimitiveValue::create(progress, CSSPrimitiveValue::CSS_NUMBER)); 246 247 return StyleGeneratedImage::create(crossfadeValue.get()); 248 } 249 250 static inline PassRefPtr<StyleImage> blendFunc(const AnimationBase* anim, StyleImage* from, StyleImage* to, double progress) 251 { 252 if (!from || !to) 253 return to; 254 255 if (from->isImageResource() && to->isImageResource()) 256 return crossfadeBlend(anim, toStyleFetchedImage(from), toStyleFetchedImage(to), progress); 257 258 // FIXME: Support transitioning generated images as well. (gradients, etc.) 259 260 return to; 261 } 262 263 class AnimationPropertyWrapperBase { 264 WTF_MAKE_NONCOPYABLE(AnimationPropertyWrapperBase); 265 WTF_MAKE_FAST_ALLOCATED; 266 public: 267 AnimationPropertyWrapperBase(CSSPropertyID prop) 268 : m_prop(prop) 269 { 270 } 271 272 virtual ~AnimationPropertyWrapperBase() { } 273 274 virtual bool isShorthandWrapper() const { return false; } 275 virtual bool equals(const RenderStyle* a, const RenderStyle* b) const = 0; 276 virtual void blend(const AnimationBase*, RenderStyle*, const RenderStyle*, const RenderStyle*, double) const = 0; 277 278 CSSPropertyID property() const { return m_prop; } 279 280 virtual bool animationIsAccelerated() const { return false; } 281 282 private: 283 CSSPropertyID m_prop; 284 }; 285 286 static int gPropertyWrapperMap[numCSSProperties]; 287 static const int cInvalidPropertyWrapperIndex = -1; 288 static Vector<AnimationPropertyWrapperBase*>* gPropertyWrappers = 0; 289 290 static void addPropertyWrapper(CSSPropertyID propertyID, AnimationPropertyWrapperBase* wrapper) 291 { 292 int propIndex = propertyID - firstCSSProperty; 293 294 ASSERT(gPropertyWrapperMap[propIndex] == cInvalidPropertyWrapperIndex); 295 296 unsigned wrapperIndex = gPropertyWrappers->size(); 297 gPropertyWrappers->append(wrapper); 298 gPropertyWrapperMap[propIndex] = wrapperIndex; 299 } 300 301 static AnimationPropertyWrapperBase* wrapperForProperty(CSSPropertyID propertyID) 302 { 303 int propIndex = propertyID - firstCSSProperty; 304 if (propIndex >= 0 && propIndex < numCSSProperties) { 305 int wrapperIndex = gPropertyWrapperMap[propIndex]; 306 if (wrapperIndex >= 0) 307 return (*gPropertyWrappers)[wrapperIndex]; 308 } 309 return 0; 310 } 311 312 template <typename T> 313 class PropertyWrapperGetter : public AnimationPropertyWrapperBase { 314 public: 315 PropertyWrapperGetter(CSSPropertyID prop, T (RenderStyle::*getter)() const) 316 : AnimationPropertyWrapperBase(prop) 317 , m_getter(getter) 318 { 319 } 320 321 virtual bool equals(const RenderStyle* a, const RenderStyle* b) const 322 { 323 // If the style pointers are the same, don't bother doing the test. 324 // If either is null, return false. If both are null, return true. 325 if ((!a && !b) || a == b) 326 return true; 327 if (!a || !b) 328 return false; 329 return (a->*m_getter)() == (b->*m_getter)(); 330 } 331 332 protected: 333 T (RenderStyle::*m_getter)() const; 334 }; 335 336 template <typename T> 337 class PropertyWrapper : public PropertyWrapperGetter<T> { 338 public: 339 PropertyWrapper(CSSPropertyID prop, T (RenderStyle::*getter)() const, void (RenderStyle::*setter)(T)) 340 : PropertyWrapperGetter<T>(prop, getter) 341 , m_setter(setter) 342 { 343 } 344 345 virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const 346 { 347 (dst->*m_setter)(blendFunc(anim, (a->*PropertyWrapperGetter<T>::m_getter)(), (b->*PropertyWrapperGetter<T>::m_getter)(), progress)); 348 } 349 350 protected: 351 void (RenderStyle::*m_setter)(T); 352 }; 353 354 class NonNegativeLengthWrapper : public PropertyWrapper<Length> { 355 public: 356 NonNegativeLengthWrapper(CSSPropertyID prop, Length (RenderStyle::*getter)() const, void (RenderStyle::*setter)(Length)) 357 : PropertyWrapper<Length>(prop, getter, setter) 358 { 359 } 360 361 virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const 362 { 363 Length from = (a->*PropertyWrapperGetter<Length>::m_getter)(); 364 Length to = (b->*PropertyWrapperGetter<Length>::m_getter)(); 365 (dst->*PropertyWrapper<Length>::m_setter)(to.blend(from, progress, ValueRangeNonNegative)); 366 } 367 }; 368 369 template <typename T> 370 class RefCountedPropertyWrapper : public PropertyWrapperGetter<T*> { 371 public: 372 RefCountedPropertyWrapper(CSSPropertyID prop, T* (RenderStyle::*getter)() const, void (RenderStyle::*setter)(PassRefPtr<T>)) 373 : PropertyWrapperGetter<T*>(prop, getter) 374 , m_setter(setter) 375 { 376 } 377 378 virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const 379 { 380 (dst->*m_setter)(blendFunc(anim, (a->*PropertyWrapperGetter<T*>::m_getter)(), (b->*PropertyWrapperGetter<T*>::m_getter)(), progress)); 381 } 382 383 protected: 384 void (RenderStyle::*m_setter)(PassRefPtr<T>); 385 }; 386 387 388 class PropertyWrapperClipPath : public RefCountedPropertyWrapper<ClipPathOperation> { 389 public: 390 PropertyWrapperClipPath(CSSPropertyID prop, ClipPathOperation* (RenderStyle::*getter)() const, void (RenderStyle::*setter)(PassRefPtr<ClipPathOperation>)) 391 : RefCountedPropertyWrapper<ClipPathOperation>(prop, getter, setter) 392 { 393 } 394 }; 395 396 class PropertyWrapperShape : public RefCountedPropertyWrapper<ShapeValue> { 397 public: 398 PropertyWrapperShape(CSSPropertyID prop, ShapeValue* (RenderStyle::*getter)() const, void (RenderStyle::*setter)(PassRefPtr<ShapeValue>)) 399 : RefCountedPropertyWrapper<ShapeValue>(prop, getter, setter) 400 { 401 } 402 }; 403 404 class StyleImagePropertyWrapper : public RefCountedPropertyWrapper<StyleImage> { 405 public: 406 StyleImagePropertyWrapper(CSSPropertyID prop, StyleImage* (RenderStyle::*getter)() const, void (RenderStyle::*setter)(PassRefPtr<StyleImage>)) 407 : RefCountedPropertyWrapper<StyleImage>(prop, getter, setter) 408 { 409 } 410 411 virtual bool equals(const RenderStyle* a, const RenderStyle* b) const 412 { 413 // If the style pointers are the same, don't bother doing the test. 414 // If either is null, return false. If both are null, return true. 415 if (a == b) 416 return true; 417 if (!a || !b) 418 return false; 419 420 StyleImage* imageA = (a->*m_getter)(); 421 StyleImage* imageB = (b->*m_getter)(); 422 return StyleImage::imagesEquivalent(imageA, imageB); 423 } 424 }; 425 426 class PropertyWrapperColor : public PropertyWrapperGetter<Color> { 427 public: 428 PropertyWrapperColor(CSSPropertyID prop, Color (RenderStyle::*getter)() const, void (RenderStyle::*setter)(const Color&)) 429 : PropertyWrapperGetter<Color>(prop, getter) 430 , m_setter(setter) 431 { 432 } 433 434 virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const 435 { 436 (dst->*m_setter)(blendFunc(anim, (a->*PropertyWrapperGetter<Color>::m_getter)(), (b->*PropertyWrapperGetter<Color>::m_getter)(), progress)); 437 } 438 439 protected: 440 void (RenderStyle::*m_setter)(const Color&); 441 }; 442 443 class PropertyWrapperAcceleratedOpacity : public PropertyWrapper<float> { 444 public: 445 PropertyWrapperAcceleratedOpacity() 446 : PropertyWrapper<float>(CSSPropertyOpacity, &RenderStyle::opacity, &RenderStyle::setOpacity) 447 { 448 } 449 450 virtual bool animationIsAccelerated() const { return true; } 451 452 virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const 453 { 454 float fromOpacity = a->opacity(); 455 456 // This makes sure we put the object being animated into a RenderLayer during the animation 457 dst->setOpacity(blendFunc(anim, (fromOpacity == 1) ? 0.999999f : fromOpacity, b->opacity(), progress)); 458 } 459 }; 460 461 class PropertyWrapperAcceleratedTransform : public PropertyWrapper<const TransformOperations&> { 462 public: 463 PropertyWrapperAcceleratedTransform() 464 : PropertyWrapper<const TransformOperations&>(CSSPropertyWebkitTransform, &RenderStyle::transform, &RenderStyle::setTransform) 465 { 466 } 467 468 virtual bool animationIsAccelerated() const { return true; } 469 470 virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const 471 { 472 dst->setTransform(blendFunc(anim, a->transform(), b->transform(), progress)); 473 } 474 }; 475 476 class PropertyWrapperAcceleratedFilter : public PropertyWrapper<const FilterOperations&> { 477 public: 478 PropertyWrapperAcceleratedFilter() 479 : PropertyWrapper<const FilterOperations&>(CSSPropertyWebkitFilter, &RenderStyle::filter, &RenderStyle::setFilter) 480 { 481 } 482 483 virtual bool animationIsAccelerated() const { return true; } 484 485 virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const 486 { 487 dst->setFilter(blendFunc(anim, a->filter(), b->filter(), progress)); 488 } 489 }; 490 491 class PropertyWrapperShadow : public AnimationPropertyWrapperBase { 492 public: 493 PropertyWrapperShadow(CSSPropertyID prop, ShadowList* (RenderStyle::*getter)() const, void (RenderStyle::*setter)(PassRefPtr<ShadowList>)) 494 : AnimationPropertyWrapperBase(prop) 495 , m_getter(getter) 496 , m_setter(setter) 497 { 498 } 499 500 virtual bool equals(const RenderStyle* a, const RenderStyle* b) const 501 { 502 const ShadowList* shadowA = (a->*m_getter)(); 503 const ShadowList* shadowB = (b->*m_getter)(); 504 if (shadowA == shadowB) 505 return true; 506 if (shadowA && shadowB) 507 return *shadowA == *shadowB; 508 return false; 509 } 510 511 virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const 512 { 513 (dst->*m_setter)(ShadowList::blend((a->*m_getter)(), (b->*m_getter)(), progress)); 514 } 515 516 ShadowList* (RenderStyle::*m_getter)() const; 517 void (RenderStyle::*m_setter)(PassRefPtr<ShadowList>); 518 }; 519 520 class PropertyWrapperMaybeInvalidColor : public AnimationPropertyWrapperBase { 521 public: 522 PropertyWrapperMaybeInvalidColor(CSSPropertyID prop, Color (RenderStyle::*getter)() const, void (RenderStyle::*setter)(const Color&)) 523 : AnimationPropertyWrapperBase(prop) 524 , m_getter(getter) 525 , m_setter(setter) 526 { 527 } 528 529 virtual bool equals(const RenderStyle* a, const RenderStyle* b) const 530 { 531 Color fromColor = (a->*m_getter)(); 532 Color toColor = (b->*m_getter)(); 533 534 if (!fromColor.isValid() && !toColor.isValid()) 535 return true; 536 537 if (!fromColor.isValid()) 538 fromColor = a->color(); 539 if (!toColor.isValid()) 540 toColor = b->color(); 541 542 return fromColor == toColor; 543 } 544 545 virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const 546 { 547 Color fromColor = (a->*m_getter)(); 548 Color toColor = (b->*m_getter)(); 549 550 if (!fromColor.isValid() && !toColor.isValid()) 551 return; 552 553 if (!fromColor.isValid()) 554 fromColor = a->color(); 555 if (!toColor.isValid()) 556 toColor = b->color(); 557 (dst->*m_setter)(blendFunc(anim, fromColor, toColor, progress)); 558 } 559 560 private: 561 Color (RenderStyle::*m_getter)() const; 562 void (RenderStyle::*m_setter)(const Color&); 563 }; 564 565 566 enum MaybeInvalidColorTag { MaybeInvalidColor }; 567 class PropertyWrapperVisitedAffectedColor : public AnimationPropertyWrapperBase { 568 public: 569 PropertyWrapperVisitedAffectedColor(CSSPropertyID prop, Color (RenderStyle::*getter)() const, void (RenderStyle::*setter)(const Color&), 570 Color (RenderStyle::*visitedGetter)() const, void (RenderStyle::*visitedSetter)(const Color&)) 571 : AnimationPropertyWrapperBase(prop) 572 , m_wrapper(adoptPtr(new PropertyWrapperColor(prop, getter, setter))) 573 , m_visitedWrapper(adoptPtr(new PropertyWrapperColor(prop, visitedGetter, visitedSetter))) 574 { 575 } 576 PropertyWrapperVisitedAffectedColor(CSSPropertyID prop, MaybeInvalidColorTag, Color (RenderStyle::*getter)() const, void (RenderStyle::*setter)(const Color&), 577 Color (RenderStyle::*visitedGetter)() const, void (RenderStyle::*visitedSetter)(const Color&)) 578 : AnimationPropertyWrapperBase(prop) 579 , m_wrapper(adoptPtr(new PropertyWrapperMaybeInvalidColor(prop, getter, setter))) 580 , m_visitedWrapper(adoptPtr(new PropertyWrapperMaybeInvalidColor(prop, visitedGetter, visitedSetter))) 581 { 582 } 583 virtual bool equals(const RenderStyle* a, const RenderStyle* b) const 584 { 585 return m_wrapper->equals(a, b) && m_visitedWrapper->equals(a, b); 586 } 587 virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const 588 { 589 m_wrapper->blend(anim, dst, a, b, progress); 590 m_visitedWrapper->blend(anim, dst, a, b, progress); 591 } 592 593 private: 594 OwnPtr<AnimationPropertyWrapperBase> m_wrapper; 595 OwnPtr<AnimationPropertyWrapperBase> m_visitedWrapper; 596 }; 597 598 // Wrapper base class for an animatable property in a FillLayer 599 class FillLayerAnimationPropertyWrapperBase { 600 public: 601 FillLayerAnimationPropertyWrapperBase() 602 { 603 } 604 605 virtual ~FillLayerAnimationPropertyWrapperBase() { } 606 607 virtual bool equals(const FillLayer*, const FillLayer*) const = 0; 608 virtual void blend(const AnimationBase*, FillLayer*, const FillLayer*, const FillLayer*, double) const = 0; 609 }; 610 611 template <typename T> 612 class FillLayerPropertyWrapperGetter : public FillLayerAnimationPropertyWrapperBase { 613 WTF_MAKE_NONCOPYABLE(FillLayerPropertyWrapperGetter); 614 public: 615 FillLayerPropertyWrapperGetter(T (FillLayer::*getter)() const) 616 : m_getter(getter) 617 { 618 } 619 620 virtual bool equals(const FillLayer* a, const FillLayer* b) const 621 { 622 // If the style pointers are the same, don't bother doing the test. 623 // If either is null, return false. If both are null, return true. 624 if ((!a && !b) || a == b) 625 return true; 626 if (!a || !b) 627 return false; 628 return (a->*m_getter)() == (b->*m_getter)(); 629 } 630 631 protected: 632 T (FillLayer::*m_getter)() const; 633 }; 634 635 template <typename T> 636 class FillLayerPropertyWrapper : public FillLayerPropertyWrapperGetter<T> { 637 public: 638 FillLayerPropertyWrapper(T (FillLayer::*getter)() const, void (FillLayer::*setter)(T)) 639 : FillLayerPropertyWrapperGetter<T>(getter) 640 , m_setter(setter) 641 { 642 } 643 644 virtual void blend(const AnimationBase* anim, FillLayer* dst, const FillLayer* a, const FillLayer* b, double progress) const 645 { 646 (dst->*m_setter)(blendFunc(anim, (a->*FillLayerPropertyWrapperGetter<T>::m_getter)(), (b->*FillLayerPropertyWrapperGetter<T>::m_getter)(), progress)); 647 } 648 649 protected: 650 void (FillLayer::*m_setter)(T); 651 }; 652 653 template <typename T> 654 class FillLayerRefCountedPropertyWrapper : public FillLayerPropertyWrapperGetter<T*> { 655 public: 656 FillLayerRefCountedPropertyWrapper(T* (FillLayer::*getter)() const, void (FillLayer::*setter)(PassRefPtr<T>)) 657 : FillLayerPropertyWrapperGetter<T*>(getter) 658 , m_setter(setter) 659 { 660 } 661 662 virtual void blend(const AnimationBase* anim, FillLayer* dst, const FillLayer* a, const FillLayer* b, double progress) const 663 { 664 (dst->*m_setter)(blendFunc(anim, (a->*FillLayerPropertyWrapperGetter<T*>::m_getter)(), (b->*FillLayerPropertyWrapperGetter<T*>::m_getter)(), progress)); 665 } 666 667 protected: 668 void (FillLayer::*m_setter)(PassRefPtr<T>); 669 }; 670 671 class FillLayerStyleImagePropertyWrapper : public FillLayerRefCountedPropertyWrapper<StyleImage> { 672 public: 673 FillLayerStyleImagePropertyWrapper(StyleImage* (FillLayer::*getter)() const, void (FillLayer::*setter)(PassRefPtr<StyleImage>)) 674 : FillLayerRefCountedPropertyWrapper<StyleImage>(getter, setter) 675 { 676 } 677 678 virtual bool equals(const FillLayer* a, const FillLayer* b) const 679 { 680 // If the style pointers are the same, don't bother doing the test. 681 // If either is null, return false. If both are null, return true. 682 if (a == b) 683 return true; 684 if (!a || !b) 685 return false; 686 687 StyleImage* imageA = (a->*m_getter)(); 688 StyleImage* imageB = (b->*m_getter)(); 689 return StyleImage::imagesEquivalent(imageA, imageB); 690 } 691 }; 692 693 694 class FillLayersPropertyWrapper : public AnimationPropertyWrapperBase { 695 public: 696 typedef const FillLayer* (RenderStyle::*LayersGetter)() const; 697 typedef FillLayer* (RenderStyle::*LayersAccessor)(); 698 699 FillLayersPropertyWrapper(CSSPropertyID prop, LayersGetter getter, LayersAccessor accessor) 700 : AnimationPropertyWrapperBase(prop) 701 , m_layersGetter(getter) 702 , m_layersAccessor(accessor) 703 { 704 switch (prop) { 705 case CSSPropertyBackgroundPositionX: 706 case CSSPropertyWebkitMaskPositionX: 707 m_fillLayerPropertyWrapper = new FillLayerPropertyWrapper<Length>(&FillLayer::xPosition, &FillLayer::setXPosition); 708 break; 709 case CSSPropertyBackgroundPositionY: 710 case CSSPropertyWebkitMaskPositionY: 711 m_fillLayerPropertyWrapper = new FillLayerPropertyWrapper<Length>(&FillLayer::yPosition, &FillLayer::setYPosition); 712 break; 713 case CSSPropertyBackgroundSize: 714 case CSSPropertyWebkitBackgroundSize: 715 case CSSPropertyWebkitMaskSize: 716 m_fillLayerPropertyWrapper = new FillLayerPropertyWrapper<LengthSize>(&FillLayer::sizeLength, &FillLayer::setSizeLength); 717 break; 718 case CSSPropertyBackgroundImage: 719 m_fillLayerPropertyWrapper = new FillLayerStyleImagePropertyWrapper(&FillLayer::image, &FillLayer::setImage); 720 break; 721 default: 722 break; 723 } 724 } 725 726 virtual bool equals(const RenderStyle* a, const RenderStyle* b) const 727 { 728 const FillLayer* fromLayer = (a->*m_layersGetter)(); 729 const FillLayer* toLayer = (b->*m_layersGetter)(); 730 731 while (fromLayer && toLayer) { 732 if (!m_fillLayerPropertyWrapper->equals(fromLayer, toLayer)) 733 return false; 734 735 fromLayer = fromLayer->next(); 736 toLayer = toLayer->next(); 737 } 738 739 return true; 740 } 741 742 virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const 743 { 744 const FillLayer* aLayer = (a->*m_layersGetter)(); 745 const FillLayer* bLayer = (b->*m_layersGetter)(); 746 FillLayer* dstLayer = (dst->*m_layersAccessor)(); 747 748 while (aLayer && bLayer && dstLayer) { 749 m_fillLayerPropertyWrapper->blend(anim, dstLayer, aLayer, bLayer, progress); 750 aLayer = aLayer->next(); 751 bLayer = bLayer->next(); 752 dstLayer = dstLayer->next(); 753 } 754 } 755 756 private: 757 FillLayerAnimationPropertyWrapperBase* m_fillLayerPropertyWrapper; 758 759 LayersGetter m_layersGetter; 760 LayersAccessor m_layersAccessor; 761 }; 762 763 class ShorthandPropertyWrapper : public AnimationPropertyWrapperBase { 764 public: 765 ShorthandPropertyWrapper(CSSPropertyID property, const StylePropertyShorthand& shorthand) 766 : AnimationPropertyWrapperBase(property) 767 { 768 for (unsigned i = 0; i < shorthand.length(); ++i) { 769 AnimationPropertyWrapperBase* wrapper = wrapperForProperty(shorthand.properties()[i]); 770 if (wrapper) 771 m_propertyWrappers.append(wrapper); 772 } 773 } 774 775 virtual bool isShorthandWrapper() const { return true; } 776 777 virtual bool equals(const RenderStyle* a, const RenderStyle* b) const 778 { 779 Vector<AnimationPropertyWrapperBase*>::const_iterator end = m_propertyWrappers.end(); 780 for (Vector<AnimationPropertyWrapperBase*>::const_iterator it = m_propertyWrappers.begin(); it != end; ++it) { 781 if (!(*it)->equals(a, b)) 782 return false; 783 } 784 return true; 785 } 786 787 virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const 788 { 789 Vector<AnimationPropertyWrapperBase*>::const_iterator end = m_propertyWrappers.end(); 790 for (Vector<AnimationPropertyWrapperBase*>::const_iterator it = m_propertyWrappers.begin(); it != end; ++it) 791 (*it)->blend(anim, dst, a, b, progress); 792 } 793 794 const Vector<AnimationPropertyWrapperBase*> propertyWrappers() const { return m_propertyWrappers; } 795 796 private: 797 Vector<AnimationPropertyWrapperBase*> m_propertyWrappers; 798 }; 799 800 class PropertyWrapperFlex : public AnimationPropertyWrapperBase { 801 public: 802 PropertyWrapperFlex() 803 : AnimationPropertyWrapperBase(CSSPropertyFlex) 804 { 805 } 806 807 virtual bool equals(const RenderStyle* a, const RenderStyle* b) const 808 { 809 // If the style pointers are the same, don't bother doing the test. 810 // If either is null, return false. If both are null, return true. 811 if ((!a && !b) || a == b) 812 return true; 813 if (!a || !b) 814 return false; 815 816 return a->flexBasis() == b->flexBasis() && a->flexGrow() == b->flexGrow() && a->flexShrink() == b->flexShrink(); 817 } 818 819 virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const 820 { 821 dst->setFlexBasis(blendFunc(anim, a->flexBasis(), b->flexBasis(), progress)); 822 dst->setFlexGrow(blendFunc(anim, a->flexGrow(), b->flexGrow(), progress)); 823 dst->setFlexShrink(blendFunc(anim, a->flexShrink(), b->flexShrink(), progress)); 824 } 825 }; 826 827 class PropertyWrapperSVGPaint : public AnimationPropertyWrapperBase { 828 public: 829 PropertyWrapperSVGPaint(CSSPropertyID prop, const SVGPaint::SVGPaintType& (RenderStyle::*paintTypeGetter)() const, Color (RenderStyle::*getter)() const, void (RenderStyle::*setter)(const Color&)) 830 : AnimationPropertyWrapperBase(prop) 831 , m_paintTypeGetter(paintTypeGetter) 832 , m_getter(getter) 833 , m_setter(setter) 834 { 835 } 836 837 virtual bool equals(const RenderStyle* a, const RenderStyle* b) const 838 { 839 if ((a->*m_paintTypeGetter)() != (b->*m_paintTypeGetter)()) 840 return false; 841 842 // We only support animations between SVGPaints that are pure Color values. 843 // For everything else we must return true for this method, otherwise 844 // we will try to animate between values forever. 845 if ((a->*m_paintTypeGetter)() == SVGPaint::SVG_PAINTTYPE_RGBCOLOR) { 846 Color fromColor = (a->*m_getter)(); 847 Color toColor = (b->*m_getter)(); 848 849 if (!fromColor.isValid() && !toColor.isValid()) 850 return true; 851 852 if (!fromColor.isValid()) 853 fromColor = Color(); 854 if (!toColor.isValid()) 855 toColor = Color(); 856 857 return fromColor == toColor; 858 } 859 return true; 860 } 861 862 virtual void blend(const AnimationBase* anim, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) const 863 { 864 if ((a->*m_paintTypeGetter)() != SVGPaint::SVG_PAINTTYPE_RGBCOLOR 865 || (b->*m_paintTypeGetter)() != SVGPaint::SVG_PAINTTYPE_RGBCOLOR) 866 return; 867 868 Color fromColor = (a->*m_getter)(); 869 Color toColor = (b->*m_getter)(); 870 871 if (!fromColor.isValid() && !toColor.isValid()) 872 return; 873 874 if (!fromColor.isValid()) 875 fromColor = Color(); 876 if (!toColor.isValid()) 877 toColor = Color(); 878 (dst->*m_setter)(blendFunc(anim, fromColor, toColor, progress)); 879 } 880 881 private: 882 const SVGPaint::SVGPaintType& (RenderStyle::*m_paintTypeGetter)() const; 883 Color (RenderStyle::*m_getter)() const; 884 void (RenderStyle::*m_setter)(const Color&); 885 }; 886 887 static void addShorthandProperties() 888 { 889 static const CSSPropertyID animatableShorthandProperties[] = { 890 CSSPropertyBackground, // for background-color, background-position, background-image 891 CSSPropertyBackgroundPosition, 892 CSSPropertyFont, // for font-size, font-weight 893 CSSPropertyWebkitMask, // for mask-position 894 CSSPropertyWebkitMaskPosition, 895 CSSPropertyBorderTop, CSSPropertyBorderRight, CSSPropertyBorderBottom, CSSPropertyBorderLeft, 896 CSSPropertyBorderColor, 897 CSSPropertyBorderRadius, 898 CSSPropertyBorderWidth, 899 CSSPropertyBorder, 900 CSSPropertyBorderImage, 901 CSSPropertyBorderSpacing, 902 CSSPropertyListStyle, // for list-style-image 903 CSSPropertyMargin, 904 CSSPropertyOutline, 905 CSSPropertyPadding, 906 CSSPropertyWebkitTextStroke, 907 CSSPropertyWebkitColumnRule, 908 CSSPropertyWebkitBorderRadius, 909 CSSPropertyWebkitTransformOrigin 910 }; 911 912 for (size_t i = 0; i < WTF_ARRAY_LENGTH(animatableShorthandProperties); ++i) { 913 CSSPropertyID propertyID = animatableShorthandProperties[i]; 914 StylePropertyShorthand shorthand = shorthandForProperty(propertyID); 915 if (shorthand.length() > 0) 916 addPropertyWrapper(propertyID, new ShorthandPropertyWrapper(propertyID, shorthand)); 917 } 918 } 919 920 void CSSPropertyAnimation::ensurePropertyMap() 921 { 922 // FIXME: This data is never destroyed. Maybe we should ref count it and toss it when the last AnimationController is destroyed? 923 if (gPropertyWrappers) 924 return; 925 926 gPropertyWrappers = new Vector<AnimationPropertyWrapperBase*>(); 927 928 // build the list of property wrappers to do the comparisons and blends 929 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyLeft, &RenderStyle::left, &RenderStyle::setLeft)); 930 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyRight, &RenderStyle::right, &RenderStyle::setRight)); 931 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyTop, &RenderStyle::top, &RenderStyle::setTop)); 932 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyBottom, &RenderStyle::bottom, &RenderStyle::setBottom)); 933 934 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyWidth, &RenderStyle::width, &RenderStyle::setWidth)); 935 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMinWidth, &RenderStyle::minWidth, &RenderStyle::setMinWidth)); 936 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMaxWidth, &RenderStyle::maxWidth, &RenderStyle::setMaxWidth)); 937 938 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyHeight, &RenderStyle::height, &RenderStyle::setHeight)); 939 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMinHeight, &RenderStyle::minHeight, &RenderStyle::setMinHeight)); 940 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMaxHeight, &RenderStyle::maxHeight, &RenderStyle::setMaxHeight)); 941 942 if (!RuntimeEnabledFeatures::webAnimationsCSSEnabled()) 943 gPropertyWrappers->append(new PropertyWrapperFlex()); 944 945 gPropertyWrappers->append(new PropertyWrapper<unsigned>(CSSPropertyBorderLeftWidth, &RenderStyle::borderLeftWidth, &RenderStyle::setBorderLeftWidth)); 946 gPropertyWrappers->append(new PropertyWrapper<unsigned>(CSSPropertyBorderRightWidth, &RenderStyle::borderRightWidth, &RenderStyle::setBorderRightWidth)); 947 gPropertyWrappers->append(new PropertyWrapper<unsigned>(CSSPropertyBorderTopWidth, &RenderStyle::borderTopWidth, &RenderStyle::setBorderTopWidth)); 948 gPropertyWrappers->append(new PropertyWrapper<unsigned>(CSSPropertyBorderBottomWidth, &RenderStyle::borderBottomWidth, &RenderStyle::setBorderBottomWidth)); 949 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMarginLeft, &RenderStyle::marginLeft, &RenderStyle::setMarginLeft)); 950 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMarginRight, &RenderStyle::marginRight, &RenderStyle::setMarginRight)); 951 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMarginTop, &RenderStyle::marginTop, &RenderStyle::setMarginTop)); 952 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyMarginBottom, &RenderStyle::marginBottom, &RenderStyle::setMarginBottom)); 953 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyPaddingLeft, &RenderStyle::paddingLeft, &RenderStyle::setPaddingLeft)); 954 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyPaddingRight, &RenderStyle::paddingRight, &RenderStyle::setPaddingRight)); 955 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyPaddingTop, &RenderStyle::paddingTop, &RenderStyle::setPaddingTop)); 956 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyPaddingBottom, &RenderStyle::paddingBottom, &RenderStyle::setPaddingBottom)); 957 gPropertyWrappers->append(new PropertyWrapperVisitedAffectedColor(CSSPropertyColor, &RenderStyle::color, &RenderStyle::setColor, &RenderStyle::visitedLinkColor, &RenderStyle::setVisitedLinkColor)); 958 959 gPropertyWrappers->append(new PropertyWrapperVisitedAffectedColor(CSSPropertyBackgroundColor, &RenderStyle::backgroundColor, &RenderStyle::setBackgroundColor, &RenderStyle::visitedLinkBackgroundColor, &RenderStyle::setVisitedLinkBackgroundColor)); 960 961 gPropertyWrappers->append(new FillLayersPropertyWrapper(CSSPropertyBackgroundImage, &RenderStyle::backgroundLayers, &RenderStyle::accessBackgroundLayers)); 962 gPropertyWrappers->append(new StyleImagePropertyWrapper(CSSPropertyListStyleImage, &RenderStyle::listStyleImage, &RenderStyle::setListStyleImage)); 963 gPropertyWrappers->append(new StyleImagePropertyWrapper(CSSPropertyWebkitMaskImage, &RenderStyle::maskImage, &RenderStyle::setMaskImage)); 964 965 gPropertyWrappers->append(new StyleImagePropertyWrapper(CSSPropertyBorderImageSource, &RenderStyle::borderImageSource, &RenderStyle::setBorderImageSource)); 966 gPropertyWrappers->append(new PropertyWrapper<LengthBox>(CSSPropertyBorderImageSlice, &RenderStyle::borderImageSlices, &RenderStyle::setBorderImageSlices)); 967 gPropertyWrappers->append(new PropertyWrapper<const BorderImageLengthBox&>(CSSPropertyBorderImageWidth, &RenderStyle::borderImageWidth, &RenderStyle::setBorderImageWidth)); 968 gPropertyWrappers->append(new PropertyWrapper<const BorderImageLengthBox&>(CSSPropertyBorderImageOutset, &RenderStyle::borderImageOutset, &RenderStyle::setBorderImageOutset)); 969 970 gPropertyWrappers->append(new StyleImagePropertyWrapper(CSSPropertyWebkitMaskBoxImageSource, &RenderStyle::maskBoxImageSource, &RenderStyle::setMaskBoxImageSource)); 971 gPropertyWrappers->append(new PropertyWrapper<LengthBox>(CSSPropertyWebkitMaskBoxImageSlice, &RenderStyle::maskBoxImageSlices, &RenderStyle::setMaskBoxImageSlices)); 972 gPropertyWrappers->append(new PropertyWrapper<const BorderImageLengthBox&>(CSSPropertyWebkitMaskBoxImageWidth, &RenderStyle::maskBoxImageWidth, &RenderStyle::setMaskBoxImageWidth)); 973 gPropertyWrappers->append(new PropertyWrapper<const BorderImageLengthBox&>(CSSPropertyWebkitMaskBoxImageOutset, &RenderStyle::maskBoxImageOutset, &RenderStyle::setMaskBoxImageOutset)); 974 975 gPropertyWrappers->append(new FillLayersPropertyWrapper(CSSPropertyBackgroundPositionX, &RenderStyle::backgroundLayers, &RenderStyle::accessBackgroundLayers)); 976 gPropertyWrappers->append(new FillLayersPropertyWrapper(CSSPropertyBackgroundPositionY, &RenderStyle::backgroundLayers, &RenderStyle::accessBackgroundLayers)); 977 gPropertyWrappers->append(new FillLayersPropertyWrapper(CSSPropertyBackgroundSize, &RenderStyle::backgroundLayers, &RenderStyle::accessBackgroundLayers)); 978 gPropertyWrappers->append(new FillLayersPropertyWrapper(CSSPropertyWebkitBackgroundSize, &RenderStyle::backgroundLayers, &RenderStyle::accessBackgroundLayers)); 979 980 gPropertyWrappers->append(new FillLayersPropertyWrapper(CSSPropertyWebkitMaskPositionX, &RenderStyle::maskLayers, &RenderStyle::accessMaskLayers)); 981 gPropertyWrappers->append(new FillLayersPropertyWrapper(CSSPropertyWebkitMaskPositionY, &RenderStyle::maskLayers, &RenderStyle::accessMaskLayers)); 982 gPropertyWrappers->append(new FillLayersPropertyWrapper(CSSPropertyWebkitMaskSize, &RenderStyle::maskLayers, &RenderStyle::accessMaskLayers)); 983 984 gPropertyWrappers->append(new PropertyWrapper<LengthPoint>(CSSPropertyObjectPosition, &RenderStyle::objectPosition, &RenderStyle::setObjectPosition)); 985 986 gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyFontSize, 987 // Must pass a specified size to setFontSize if Text Autosizing is enabled, but a computed size 988 // if text zoom is enabled (if neither is enabled it's irrelevant as they're probably the same). 989 // FIXME: Should we introduce an option to pass the computed font size here, allowing consumers to 990 // enable text zoom rather than Text Autosizing? See http://crbug.com/227545. 991 &RenderStyle::specifiedFontSize, 992 &RenderStyle::setFontSize)); 993 gPropertyWrappers->append(new PropertyWrapper<unsigned short>(CSSPropertyWebkitColumnRuleWidth, &RenderStyle::columnRuleWidth, &RenderStyle::setColumnRuleWidth)); 994 gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyWebkitColumnGap, &RenderStyle::columnGap, &RenderStyle::setColumnGap)); 995 gPropertyWrappers->append(new PropertyWrapper<unsigned short>(CSSPropertyWebkitColumnCount, &RenderStyle::columnCount, &RenderStyle::setColumnCount)); 996 gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyWebkitColumnWidth, &RenderStyle::columnWidth, &RenderStyle::setColumnWidth)); 997 gPropertyWrappers->append(new PropertyWrapper<short>(CSSPropertyWebkitBorderHorizontalSpacing, &RenderStyle::horizontalBorderSpacing, &RenderStyle::setHorizontalBorderSpacing)); 998 gPropertyWrappers->append(new PropertyWrapper<short>(CSSPropertyWebkitBorderVerticalSpacing, &RenderStyle::verticalBorderSpacing, &RenderStyle::setVerticalBorderSpacing)); 999 gPropertyWrappers->append(new PropertyWrapper<int>(CSSPropertyZIndex, &RenderStyle::zIndex, &RenderStyle::setZIndex)); 1000 gPropertyWrappers->append(new PropertyWrapper<short>(CSSPropertyOrphans, &RenderStyle::orphans, &RenderStyle::setOrphans)); 1001 gPropertyWrappers->append(new PropertyWrapper<short>(CSSPropertyWidows, &RenderStyle::widows, &RenderStyle::setWidows)); 1002 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyLineHeight, &RenderStyle::specifiedLineHeight, &RenderStyle::setLineHeight)); 1003 gPropertyWrappers->append(new PropertyWrapper<int>(CSSPropertyOutlineOffset, &RenderStyle::outlineOffset, &RenderStyle::setOutlineOffset)); 1004 gPropertyWrappers->append(new PropertyWrapper<unsigned short>(CSSPropertyOutlineWidth, &RenderStyle::outlineWidth, &RenderStyle::setOutlineWidth)); 1005 gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyLetterSpacing, &RenderStyle::letterSpacing, &RenderStyle::setLetterSpacing)); 1006 gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyWordSpacing, &RenderStyle::wordSpacing, &RenderStyle::setWordSpacing)); 1007 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyTextIndent, &RenderStyle::textIndent, &RenderStyle::setTextIndent)); 1008 1009 gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyWebkitPerspective, &RenderStyle::perspective, &RenderStyle::setPerspective)); 1010 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyWebkitPerspectiveOriginX, &RenderStyle::perspectiveOriginX, &RenderStyle::setPerspectiveOriginX)); 1011 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyWebkitPerspectiveOriginY, &RenderStyle::perspectiveOriginY, &RenderStyle::setPerspectiveOriginY)); 1012 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyWebkitTransformOriginX, &RenderStyle::transformOriginX, &RenderStyle::setTransformOriginX)); 1013 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyWebkitTransformOriginY, &RenderStyle::transformOriginY, &RenderStyle::setTransformOriginY)); 1014 gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyWebkitTransformOriginZ, &RenderStyle::transformOriginZ, &RenderStyle::setTransformOriginZ)); 1015 gPropertyWrappers->append(new PropertyWrapper<LengthSize>(CSSPropertyBorderTopLeftRadius, &RenderStyle::borderTopLeftRadius, &RenderStyle::setBorderTopLeftRadius)); 1016 gPropertyWrappers->append(new PropertyWrapper<LengthSize>(CSSPropertyBorderTopRightRadius, &RenderStyle::borderTopRightRadius, &RenderStyle::setBorderTopRightRadius)); 1017 gPropertyWrappers->append(new PropertyWrapper<LengthSize>(CSSPropertyBorderBottomLeftRadius, &RenderStyle::borderBottomLeftRadius, &RenderStyle::setBorderBottomLeftRadius)); 1018 gPropertyWrappers->append(new PropertyWrapper<LengthSize>(CSSPropertyBorderBottomRightRadius, &RenderStyle::borderBottomRightRadius, &RenderStyle::setBorderBottomRightRadius)); 1019 gPropertyWrappers->append(new PropertyWrapper<EVisibility>(CSSPropertyVisibility, &RenderStyle::visibility, &RenderStyle::setVisibility)); 1020 gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyZoom, &RenderStyle::zoom, &RenderStyle::setZoomWithoutReturnValue)); 1021 1022 gPropertyWrappers->append(new PropertyWrapper<LengthBox>(CSSPropertyClip, &RenderStyle::clip, &RenderStyle::setClip)); 1023 1024 gPropertyWrappers->append(new PropertyWrapperAcceleratedOpacity()); 1025 gPropertyWrappers->append(new PropertyWrapperAcceleratedTransform()); 1026 gPropertyWrappers->append(new PropertyWrapperAcceleratedFilter()); 1027 1028 gPropertyWrappers->append(new PropertyWrapperClipPath(CSSPropertyWebkitClipPath, &RenderStyle::clipPath, &RenderStyle::setClipPath)); 1029 1030 gPropertyWrappers->append(new PropertyWrapperShape(CSSPropertyShapeInside, &RenderStyle::shapeInside, &RenderStyle::setShapeInside)); 1031 gPropertyWrappers->append(new PropertyWrapperShape(CSSPropertyShapeOutside, &RenderStyle::shapeOutside, &RenderStyle::setShapeOutside)); 1032 gPropertyWrappers->append(new NonNegativeLengthWrapper(CSSPropertyShapeMargin, &RenderStyle::shapeMargin, &RenderStyle::setShapeMargin)); 1033 gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyShapeImageThreshold, &RenderStyle::shapeImageThreshold, &RenderStyle::setShapeImageThreshold)); 1034 1035 gPropertyWrappers->append(new PropertyWrapperVisitedAffectedColor(CSSPropertyWebkitColumnRuleColor, MaybeInvalidColor, &RenderStyle::columnRuleColor, &RenderStyle::setColumnRuleColor, &RenderStyle::visitedLinkColumnRuleColor, &RenderStyle::setVisitedLinkColumnRuleColor)); 1036 gPropertyWrappers->append(new PropertyWrapperVisitedAffectedColor(CSSPropertyWebkitTextStrokeColor, MaybeInvalidColor, &RenderStyle::textStrokeColor, &RenderStyle::setTextStrokeColor, &RenderStyle::visitedLinkTextStrokeColor, &RenderStyle::setVisitedLinkTextStrokeColor)); 1037 gPropertyWrappers->append(new PropertyWrapperVisitedAffectedColor(CSSPropertyBorderLeftColor, MaybeInvalidColor, &RenderStyle::borderLeftColor, &RenderStyle::setBorderLeftColor, &RenderStyle::visitedLinkBorderLeftColor, &RenderStyle::setVisitedLinkBorderLeftColor)); 1038 gPropertyWrappers->append(new PropertyWrapperVisitedAffectedColor(CSSPropertyBorderRightColor, MaybeInvalidColor, &RenderStyle::borderRightColor, &RenderStyle::setBorderRightColor, &RenderStyle::visitedLinkBorderRightColor, &RenderStyle::setVisitedLinkBorderRightColor)); 1039 gPropertyWrappers->append(new PropertyWrapperVisitedAffectedColor(CSSPropertyBorderTopColor, MaybeInvalidColor, &RenderStyle::borderTopColor, &RenderStyle::setBorderTopColor, &RenderStyle::visitedLinkBorderTopColor, &RenderStyle::setVisitedLinkBorderTopColor)); 1040 gPropertyWrappers->append(new PropertyWrapperVisitedAffectedColor(CSSPropertyBorderBottomColor, MaybeInvalidColor, &RenderStyle::borderBottomColor, &RenderStyle::setBorderBottomColor, &RenderStyle::visitedLinkBorderBottomColor, &RenderStyle::setVisitedLinkBorderBottomColor)); 1041 gPropertyWrappers->append(new PropertyWrapperVisitedAffectedColor(CSSPropertyOutlineColor, MaybeInvalidColor, &RenderStyle::outlineColor, &RenderStyle::setOutlineColor, &RenderStyle::visitedLinkOutlineColor, &RenderStyle::setVisitedLinkOutlineColor)); 1042 1043 gPropertyWrappers->append(new PropertyWrapperShadow(CSSPropertyBoxShadow, &RenderStyle::boxShadow, &RenderStyle::setBoxShadow)); 1044 gPropertyWrappers->append(new PropertyWrapperShadow(CSSPropertyWebkitBoxShadow, &RenderStyle::boxShadow, &RenderStyle::setBoxShadow)); 1045 gPropertyWrappers->append(new PropertyWrapperShadow(CSSPropertyTextShadow, &RenderStyle::textShadow, &RenderStyle::setTextShadow)); 1046 1047 gPropertyWrappers->append(new PropertyWrapperSVGPaint(CSSPropertyFill, &RenderStyle::fillPaintType, &RenderStyle::fillPaintColor, &RenderStyle::setFillPaintColor)); 1048 gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyFillOpacity, &RenderStyle::fillOpacity, &RenderStyle::setFillOpacity)); 1049 1050 gPropertyWrappers->append(new PropertyWrapperSVGPaint(CSSPropertyStroke, &RenderStyle::strokePaintType, &RenderStyle::strokePaintColor, &RenderStyle::setStrokePaintColor)); 1051 gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyStrokeOpacity, &RenderStyle::strokeOpacity, &RenderStyle::setStrokeOpacity)); 1052 gPropertyWrappers->append(new PropertyWrapper<SVGLength>(CSSPropertyStrokeWidth, &RenderStyle::strokeWidth, &RenderStyle::setStrokeWidth)); 1053 gPropertyWrappers->append(new PropertyWrapper< Vector<SVGLength> >(CSSPropertyStrokeDasharray, &RenderStyle::strokeDashArray, &RenderStyle::setStrokeDashArray)); 1054 gPropertyWrappers->append(new PropertyWrapper<SVGLength>(CSSPropertyStrokeDashoffset, &RenderStyle::strokeDashOffset, &RenderStyle::setStrokeDashOffset)); 1055 gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyStrokeMiterlimit, &RenderStyle::strokeMiterLimit, &RenderStyle::setStrokeMiterLimit)); 1056 1057 gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyFloodOpacity, &RenderStyle::floodOpacity, &RenderStyle::setFloodOpacity)); 1058 gPropertyWrappers->append(new PropertyWrapperMaybeInvalidColor(CSSPropertyFloodColor, &RenderStyle::floodColor, &RenderStyle::setFloodColor)); 1059 1060 gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyStopOpacity, &RenderStyle::stopOpacity, &RenderStyle::setStopOpacity)); 1061 gPropertyWrappers->append(new PropertyWrapperMaybeInvalidColor(CSSPropertyStopColor, &RenderStyle::stopColor, &RenderStyle::setStopColor)); 1062 1063 gPropertyWrappers->append(new PropertyWrapperMaybeInvalidColor(CSSPropertyLightingColor, &RenderStyle::lightingColor, &RenderStyle::setLightingColor)); 1064 1065 gPropertyWrappers->append(new PropertyWrapper<SVGLength>(CSSPropertyBaselineShift, &RenderStyle::baselineShiftValue, &RenderStyle::setBaselineShiftValue)); 1066 gPropertyWrappers->append(new PropertyWrapper<SVGLength>(CSSPropertyKerning, &RenderStyle::kerning, &RenderStyle::setKerning)); 1067 1068 if (RuntimeEnabledFeatures::webAnimationsCSSEnabled()) { 1069 gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyFlexGrow, &RenderStyle::flexGrow, &RenderStyle::setFlexGrow)); 1070 gPropertyWrappers->append(new PropertyWrapper<float>(CSSPropertyFlexShrink, &RenderStyle::flexShrink, &RenderStyle::setFlexShrink)); 1071 gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyFlexBasis, &RenderStyle::flexBasis, &RenderStyle::setFlexBasis)); 1072 } 1073 1074 // TODO: 1075 // 1076 // CSSPropertyVerticalAlign 1077 // 1078 // Compound properties that have components that should be animatable: 1079 // 1080 // CSSPropertyWebkitColumns 1081 // CSSPropertyWebkitBoxReflect 1082 1083 // Make sure unused slots have a value 1084 for (unsigned int i = 0; i < static_cast<unsigned int>(numCSSProperties); ++i) 1085 gPropertyWrapperMap[i] = cInvalidPropertyWrapperIndex; 1086 1087 // First we put the non-shorthand property wrappers into the map, so the shorthand-building 1088 // code can find them. 1089 size_t n = gPropertyWrappers->size(); 1090 for (unsigned int i = 0; i < n; ++i) { 1091 CSSPropertyID property = (*gPropertyWrappers)[i]->property(); 1092 ASSERT_WITH_MESSAGE(RuntimeEnabledFeatures::webAnimationsCSSEnabled() || CSSAnimations::isAnimatableProperty(property), "%s is not whitelisted for animation", getPropertyNameString(property).utf8().data()); 1093 ASSERT(property - firstCSSProperty < numCSSProperties); 1094 gPropertyWrapperMap[property - firstCSSProperty] = i; 1095 } 1096 1097 // Now add the shorthand wrappers. 1098 addShorthandProperties(); 1099 } 1100 1101 // Returns true if we need to start animation timers 1102 bool CSSPropertyAnimation::blendProperties(const AnimationBase* anim, CSSPropertyID prop, RenderStyle* dst, const RenderStyle* a, const RenderStyle* b, double progress) 1103 { 1104 ASSERT(prop != CSSPropertyInvalid); 1105 1106 ensurePropertyMap(); 1107 1108 AnimationPropertyWrapperBase* wrapper = wrapperForProperty(prop); 1109 if (wrapper) { 1110 wrapper->blend(anim, dst, a, b, progress); 1111 return !wrapper->animationIsAccelerated() || !anim->isAccelerated(); 1112 } 1113 1114 return false; 1115 } 1116 1117 bool CSSPropertyAnimation::animationOfPropertyIsAccelerated(CSSPropertyID prop) 1118 { 1119 ensurePropertyMap(); 1120 AnimationPropertyWrapperBase* wrapper = wrapperForProperty(prop); 1121 return wrapper ? wrapper->animationIsAccelerated() : false; 1122 } 1123 1124 bool CSSPropertyAnimation::propertiesEqual(CSSPropertyID prop, const RenderStyle* a, const RenderStyle* b) 1125 { 1126 ensurePropertyMap(); 1127 1128 AnimationPropertyWrapperBase* wrapper = wrapperForProperty(prop); 1129 if (wrapper) 1130 return wrapper->equals(a, b); 1131 return true; 1132 } 1133 1134 CSSPropertyID CSSPropertyAnimation::getPropertyAtIndex(int i, bool& isShorthand) 1135 { 1136 ensurePropertyMap(); 1137 1138 if (i < 0 || i >= getNumProperties()) 1139 return CSSPropertyInvalid; 1140 1141 AnimationPropertyWrapperBase* wrapper = (*gPropertyWrappers)[i]; 1142 isShorthand = wrapper->isShorthandWrapper(); 1143 return wrapper->property(); 1144 } 1145 1146 int CSSPropertyAnimation::getNumProperties() 1147 { 1148 ensurePropertyMap(); 1149 1150 return gPropertyWrappers->size(); 1151 } 1152 1153 } 1154