OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
89 return Animation::hasLowerPriority(&animationToAdd, &animation); | 89 return Animation::hasLowerPriority(&animationToAdd, &animation); |
90 default: | 90 default: |
91 ASSERT_NOT_REACHED(); | 91 ASSERT_NOT_REACHED(); |
92 return true; | 92 return true; |
93 } | 93 } |
94 } | 94 } |
95 | 95 |
96 bool hasIncompatibleAnimations(const Element& targetElement, const Animation& an
imationToAdd, const EffectModel& effectToAdd) | 96 bool hasIncompatibleAnimations(const Element& targetElement, const Animation& an
imationToAdd, const EffectModel& effectToAdd) |
97 { | 97 { |
98 const bool affectsOpacity = effectToAdd.affects(PropertyHandle(CSSPropertyOp
acity)); | 98 const bool affectsOpacity = effectToAdd.affects(PropertyHandle(CSSPropertyOp
acity)); |
99 const bool affectsTransform = effectToAdd.affects(PropertyHandle(CSSProperty
Transform)); | 99 const bool affectsTransform = effectToAdd.affects(PropertyHandle(CSSProperty
Transform)) |
| 100 || effectToAdd.affects(PropertyHandle(CSSPropertyTranslate)) |
| 101 || effectToAdd.affects(PropertyHandle(CSSPropertyRotate)) |
| 102 || effectToAdd.affects(PropertyHandle(CSSPropertyScale)); |
100 const bool affectsFilter = effectToAdd.affects(PropertyHandle(CSSPropertyWeb
kitFilter)); | 103 const bool affectsFilter = effectToAdd.affects(PropertyHandle(CSSPropertyWeb
kitFilter)); |
101 | 104 |
102 if (!targetElement.hasAnimations()) | 105 if (!targetElement.hasAnimations()) |
103 return false; | 106 return false; |
104 | 107 |
105 ElementAnimations* elementAnimations = targetElement.elementAnimations(); | 108 ElementAnimations* elementAnimations = targetElement.elementAnimations(); |
106 ASSERT(elementAnimations); | 109 ASSERT(elementAnimations); |
107 | 110 |
108 for (const auto& entry : elementAnimations->animations()) { | 111 for (const auto& entry : elementAnimations->animations()) { |
109 const Animation* attachedAnimation = entry.key; | 112 const Animation* attachedAnimation = entry.key; |
110 if (!considerAnimationAsIncompatible(*attachedAnimation, animationToAdd)
) | 113 if (!considerAnimationAsIncompatible(*attachedAnimation, animationToAdd)
) |
111 continue; | 114 continue; |
112 | 115 |
113 if ((affectsOpacity && attachedAnimation->affects(targetElement, CSSProp
ertyOpacity)) | 116 if ((affectsOpacity && attachedAnimation->affects(targetElement, CSSProp
ertyOpacity)) |
| 117 || (affectsTransform && attachedAnimation->affects(targetElement, CS
SPropertyTranslate)) |
| 118 || (affectsTransform && attachedAnimation->affects(targetElement, CS
SPropertyScale)) |
| 119 || (affectsTransform && attachedAnimation->affects(targetElement, CS
SPropertyRotate)) |
114 || (affectsTransform && attachedAnimation->affects(targetElement, CS
SPropertyTransform)) | 120 || (affectsTransform && attachedAnimation->affects(targetElement, CS
SPropertyTransform)) |
115 || (affectsFilter && attachedAnimation->affects(targetElement, CSSPr
opertyWebkitFilter))) | 121 || (affectsFilter && attachedAnimation->affects(targetElement, CSSPr
opertyWebkitFilter))) |
116 return true; | 122 return true; |
117 } | 123 } |
118 | 124 |
119 return false; | 125 return false; |
120 } | 126 } |
121 | 127 |
122 } | 128 } |
123 | 129 |
124 CSSPropertyID CompositorAnimations::CompositableProperties[3] = { | 130 CSSPropertyID CompositorAnimations::CompositableProperties[6] = { |
125 CSSPropertyOpacity, CSSPropertyTransform, CSSPropertyWebkitFilter | 131 CSSPropertyOpacity, |
| 132 CSSPropertyTransform, |
| 133 CSSPropertyWebkitFilter, |
| 134 CSSPropertyTranslate, |
| 135 CSSPropertyRotate, |
| 136 CSSPropertyScale |
126 }; | 137 }; |
127 | 138 |
128 bool CompositorAnimations::getAnimatedBoundingBox(FloatBox& box, const EffectMod
el& effect, double minValue, double maxValue) const | 139 bool CompositorAnimations::getAnimatedBoundingBox(FloatBox& box, const EffectMod
el& effect, double minValue, double maxValue) const |
129 { | 140 { |
130 const KeyframeEffectModelBase& keyframeEffect = toKeyframeEffectModelBase(ef
fect); | 141 const KeyframeEffectModelBase& keyframeEffect = toKeyframeEffectModelBase(ef
fect); |
131 | 142 |
132 PropertyHandleSet properties = keyframeEffect.properties(); | 143 PropertyHandleSet properties = keyframeEffect.properties(); |
133 | 144 |
134 if (properties.isEmpty()) | 145 if (properties.isEmpty()) |
135 return true; | 146 return true; |
136 | 147 |
137 minValue = std::min(minValue, 0.0); | 148 minValue = std::min(minValue, 0.0); |
138 maxValue = std::max(maxValue, 1.0); | 149 maxValue = std::max(maxValue, 1.0); |
139 | 150 |
140 for (const auto& property : properties) { | 151 for (const auto& property : properties) { |
141 if (!property.isCSSProperty()) | 152 if (!property.isCSSProperty()) |
142 continue; | 153 continue; |
143 | 154 |
144 // TODO: Add the ability to get expanded bounds for filters as well. | 155 // TODO: Add the ability to get expanded bounds for filters as well. |
145 if (property.cssProperty() != CSSPropertyTransform) | 156 if (property.cssProperty() != CSSPropertyTransform |
| 157 || property.cssProperty() != CSSPropertyTranslate |
| 158 || property.cssProperty() != CSSPropertyRotate |
| 159 || property.cssProperty() != CSSPropertyScale) |
146 continue; | 160 continue; |
147 | 161 |
148 const PropertySpecificKeyframeVector& frames = keyframeEffect.getPropert
ySpecificKeyframes(property); | 162 const PropertySpecificKeyframeVector& frames = keyframeEffect.getPropert
ySpecificKeyframes(property); |
149 if (frames.isEmpty() || frames.size() < 2) | 163 if (frames.isEmpty() || frames.size() < 2) |
150 continue; | 164 continue; |
151 | 165 |
152 FloatBox originalBox(box); | 166 FloatBox originalBox(box); |
153 | 167 |
154 for (size_t j = 0; j < frames.size() - 1; ++j) { | 168 for (size_t j = 0; j < frames.size() - 1; ++j) { |
155 const AnimatableTransform* startTransform = toAnimatableTransform(fr
ames[j]->getAnimatableValue().get()); | 169 const AnimatableTransform* startTransform = toAnimatableTransform(fr
ames[j]->getAnimatableValue().get()); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
193 // ----------------------------------------------------------------------- | 207 // ----------------------------------------------------------------------- |
194 | 208 |
195 bool CompositorAnimations::isCandidateForAnimationOnCompositor(const Timing& tim
ing, const Element& targetElement, const Animation* animationToAdd, const Effect
Model& effect, double animationPlaybackRate) | 209 bool CompositorAnimations::isCandidateForAnimationOnCompositor(const Timing& tim
ing, const Element& targetElement, const Animation* animationToAdd, const Effect
Model& effect, double animationPlaybackRate) |
196 { | 210 { |
197 const KeyframeEffectModelBase& keyframeEffect = toKeyframeEffectModelBase(ef
fect); | 211 const KeyframeEffectModelBase& keyframeEffect = toKeyframeEffectModelBase(ef
fect); |
198 | 212 |
199 PropertyHandleSet properties = keyframeEffect.properties(); | 213 PropertyHandleSet properties = keyframeEffect.properties(); |
200 if (properties.isEmpty()) | 214 if (properties.isEmpty()) |
201 return false; | 215 return false; |
202 | 216 |
| 217 unsigned transformOperationCount = 0; |
203 for (const auto& property : properties) { | 218 for (const auto& property : properties) { |
204 if (!property.isCSSProperty()) | 219 if (!property.isCSSProperty()) |
205 return false; | 220 return false; |
206 | 221 |
| 222 if (property.cssProperty() == CSSPropertyTransform |
| 223 || property.cssProperty() == CSSPropertyTranslate |
| 224 || property.cssProperty() == CSSPropertyScale |
| 225 || property.cssProperty() == CSSPropertyRotate) |
| 226 transformOperationCount++; |
| 227 |
207 const PropertySpecificKeyframeVector& keyframes = keyframeEffect.getProp
ertySpecificKeyframes(property); | 228 const PropertySpecificKeyframeVector& keyframes = keyframeEffect.getProp
ertySpecificKeyframes(property); |
208 ASSERT(keyframes.size() >= 2); | 229 ASSERT(keyframes.size() >= 2); |
209 for (const auto& keyframe : keyframes) { | 230 for (const auto& keyframe : keyframes) { |
210 // FIXME: Determine candidacy based on the CSSValue instead of a sna
pshot AnimatableValue. | 231 // FIXME: Determine candidacy based on the CSSValue instead of a sna
pshot AnimatableValue. |
211 bool isNeutralKeyframe = keyframe->isCSSPropertySpecificKeyframe() &
& !toCSSPropertySpecificKeyframe(keyframe.get())->value() && keyframe->composite
() == EffectModel::CompositeAdd; | 232 bool isNeutralKeyframe = keyframe->isCSSPropertySpecificKeyframe() &
& !toCSSPropertySpecificKeyframe(keyframe.get())->value() && keyframe->composite
() == EffectModel::CompositeAdd; |
212 if ((keyframe->composite() != EffectModel::CompositeReplace && !isNe
utralKeyframe) || !keyframe->getAnimatableValue()) | 233 if ((keyframe->composite() != EffectModel::CompositeReplace && !isNe
utralKeyframe) || !keyframe->getAnimatableValue()) |
213 return false; | 234 return false; |
214 | 235 |
215 switch (property.cssProperty()) { | 236 switch (property.cssProperty()) { |
216 case CSSPropertyOpacity: | 237 case CSSPropertyOpacity: |
217 break; | 238 break; |
| 239 /* Intentional fallthrough */ |
| 240 case CSSPropertyTranslate: |
| 241 case CSSPropertyRotate: |
| 242 case CSSPropertyScale: |
218 case CSSPropertyTransform: | 243 case CSSPropertyTransform: |
219 if (toAnimatableTransform(keyframe->getAnimatableValue().get())-
>transformOperations().dependsOnBoxSize()) | 244 if (toAnimatableTransform(keyframe->getAnimatableValue().get())-
>transformOperations().dependsOnBoxSize()) |
220 return false; | 245 return false; |
221 break; | 246 break; |
222 case CSSPropertyWebkitFilter: { | 247 case CSSPropertyWebkitFilter: { |
223 const FilterOperations& operations = toAnimatableFilterOperation
s(keyframe->getAnimatableValue().get())->operations(); | 248 const FilterOperations& operations = toAnimatableFilterOperation
s(keyframe->getAnimatableValue().get())->operations(); |
224 if (operations.hasFilterThatMovesPixels()) | 249 if (operations.hasFilterThatMovesPixels()) |
225 return false; | 250 return false; |
226 break; | 251 break; |
227 } | 252 } |
228 default: | 253 default: |
229 // any other types are not allowed to run on compositor. | 254 // any other types are not allowed to run on compositor. |
230 return false; | 255 return false; |
231 } | 256 } |
232 } | 257 } |
233 } | 258 } |
| 259 if (transformOperationCount > 1) |
| 260 return false; |
234 | 261 |
235 if (animationToAdd && hasIncompatibleAnimations(targetElement, *animationToA
dd, effect)) | 262 if (animationToAdd && hasIncompatibleAnimations(targetElement, *animationToA
dd, effect)) |
236 return false; | 263 return false; |
237 | 264 |
238 CompositorAnimationsImpl::CompositorTiming out; | 265 CompositorAnimationsImpl::CompositorTiming out; |
239 if (!CompositorAnimationsImpl::convertTimingForCompositor(timing, 0, out, an
imationPlaybackRate)) | 266 if (!CompositorAnimationsImpl::convertTimingForCompositor(timing, 0, out, an
imationPlaybackRate)) |
240 return false; | 267 return false; |
241 | 268 |
242 return true; | 269 return true; |
243 } | 270 } |
244 | 271 |
245 void CompositorAnimations::cancelIncompatibleAnimationsOnCompositor(const Elemen
t& targetElement, const Animation& animationToAdd, const EffectModel& effectToAd
d) | 272 void CompositorAnimations::cancelIncompatibleAnimationsOnCompositor(const Elemen
t& targetElement, const Animation& animationToAdd, const EffectModel& effectToAd
d) |
246 { | 273 { |
| 274 |
247 const bool affectsOpacity = effectToAdd.affects(PropertyHandle(CSSPropertyOp
acity)); | 275 const bool affectsOpacity = effectToAdd.affects(PropertyHandle(CSSPropertyOp
acity)); |
248 const bool affectsTransform = effectToAdd.affects(PropertyHandle(CSSProperty
Transform)); | 276 const bool affectsTransform = effectToAdd.affects(PropertyHandle(CSSProperty
Transform)) |
| 277 || effectToAdd.affects(PropertyHandle(CSSPropertyTranslate)) |
| 278 || effectToAdd.affects(PropertyHandle(CSSPropertyRotate)) |
| 279 || effectToAdd.affects(PropertyHandle(CSSPropertyScale)); |
249 const bool affectsFilter = effectToAdd.affects(PropertyHandle(CSSPropertyWeb
kitFilter)); | 280 const bool affectsFilter = effectToAdd.affects(PropertyHandle(CSSPropertyWeb
kitFilter)); |
250 | 281 |
251 if (!targetElement.hasAnimations()) | 282 if (!targetElement.hasAnimations()) |
252 return; | 283 return; |
253 | 284 |
254 ElementAnimations* elementAnimations = targetElement.elementAnimations(); | 285 ElementAnimations* elementAnimations = targetElement.elementAnimations(); |
255 ASSERT(elementAnimations); | 286 ASSERT(elementAnimations); |
256 | 287 |
257 for (const auto& entry : elementAnimations->animations()) { | 288 for (const auto& entry : elementAnimations->animations()) { |
258 Animation* attachedAnimation = entry.key; | 289 Animation* attachedAnimation = entry.key; |
259 if (!considerAnimationAsIncompatible(*attachedAnimation, animationToAdd)
) | 290 if (!considerAnimationAsIncompatible(*attachedAnimation, animationToAdd)
) |
260 continue; | 291 continue; |
261 | 292 |
262 if ((affectsOpacity && attachedAnimation->affects(targetElement, CSSProp
ertyOpacity)) | 293 if ((affectsOpacity && attachedAnimation->affects(targetElement, CSSProp
ertyOpacity)) |
| 294 || (affectsTransform && attachedAnimation->affects(targetElement, CS
SPropertyTranslate)) |
| 295 || (affectsTransform && attachedAnimation->affects(targetElement, CS
SPropertyScale)) |
| 296 || (affectsTransform && attachedAnimation->affects(targetElement, CS
SPropertyRotate)) |
263 || (affectsTransform && attachedAnimation->affects(targetElement, CS
SPropertyTransform)) | 297 || (affectsTransform && attachedAnimation->affects(targetElement, CS
SPropertyTransform)) |
264 || (affectsFilter && attachedAnimation->affects(targetElement, CSSPr
opertyWebkitFilter))) | 298 || (affectsFilter && attachedAnimation->affects(targetElement, CSSPr
opertyWebkitFilter))) |
265 attachedAnimation->cancelAnimationOnCompositor(); | 299 attachedAnimation->cancelAnimationOnCompositor(); |
266 } | 300 } |
267 } | 301 } |
268 | 302 |
269 bool CompositorAnimations::canStartAnimationOnCompositor(const Element& element) | 303 bool CompositorAnimations::canStartAnimationOnCompositor(const Element& element) |
270 { | 304 { |
271 return element.layoutObject() && element.layoutObject()->compositingState()
== PaintsIntoOwnBacking; | 305 return element.layoutObject() && element.layoutObject()->compositingState()
== PaintsIntoOwnBacking; |
272 } | 306 } |
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
623 break; | 657 break; |
624 } | 658 } |
625 case CSSPropertyWebkitFilter: { | 659 case CSSPropertyWebkitFilter: { |
626 targetProperty = WebCompositorAnimation::TargetPropertyFilter; | 660 targetProperty = WebCompositorAnimation::TargetPropertyFilter; |
627 WebFilterAnimationCurve* filterCurve = Platform::current()->composit
orSupport()->createFilterAnimationCurve(); | 661 WebFilterAnimationCurve* filterCurve = Platform::current()->composit
orSupport()->createFilterAnimationCurve(); |
628 addKeyframesToCurve(*filterCurve, values, timing); | 662 addKeyframesToCurve(*filterCurve, values, timing); |
629 setTimingFunctionOnCurve(*filterCurve, timing.timingFunction.get()); | 663 setTimingFunctionOnCurve(*filterCurve, timing.timingFunction.get()); |
630 curve = adoptPtr(filterCurve); | 664 curve = adoptPtr(filterCurve); |
631 break; | 665 break; |
632 } | 666 } |
| 667 /* Intentional fallthrough */ |
| 668 case CSSPropertyTranslate: |
| 669 case CSSPropertyRotate: |
| 670 case CSSPropertyScale: |
633 case CSSPropertyTransform: { | 671 case CSSPropertyTransform: { |
634 targetProperty = WebCompositorAnimation::TargetPropertyTransform; | 672 targetProperty = WebCompositorAnimation::TargetPropertyTransform; |
635 WebTransformAnimationCurve* transformCurve = Platform::current()->co
mpositorSupport()->createTransformAnimationCurve(); | 673 WebTransformAnimationCurve* transformCurve = Platform::current()->co
mpositorSupport()->createTransformAnimationCurve(); |
636 addKeyframesToCurve(*transformCurve, values, timing); | 674 addKeyframesToCurve(*transformCurve, values, timing); |
637 setTimingFunctionOnCurve(*transformCurve, timing.timingFunction.get(
)); | 675 setTimingFunctionOnCurve(*transformCurve, timing.timingFunction.get(
)); |
638 curve = adoptPtr(transformCurve); | 676 curve = adoptPtr(transformCurve); |
639 break; | 677 break; |
640 } | 678 } |
641 default: | 679 default: |
642 ASSERT_NOT_REACHED(); | 680 ASSERT_NOT_REACHED(); |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
686 break; | 724 break; |
687 default: | 725 default: |
688 ASSERT_NOT_REACHED(); | 726 ASSERT_NOT_REACHED(); |
689 } | 727 } |
690 animations.append(animation.release()); | 728 animations.append(animation.release()); |
691 } | 729 } |
692 ASSERT(!animations.isEmpty()); | 730 ASSERT(!animations.isEmpty()); |
693 } | 731 } |
694 | 732 |
695 } // namespace blink | 733 } // namespace blink |
OLD | NEW |