| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright (C) 2013 Google Inc. All rights reserved. | |
| 3 * | |
| 4 * Redistribution and use in source and binary forms, with or without | |
| 5 * modification, are permitted provided that the following conditions are | |
| 6 * met: | |
| 7 * | |
| 8 * * Redistributions of source code must retain the above copyright | |
| 9 * notice, this list of conditions and the following disclaimer. | |
| 10 * * Redistributions in binary form must reproduce the above | |
| 11 * copyright notice, this list of conditions and the following disclaimer | |
| 12 * in the documentation and/or other materials provided with the | |
| 13 * distribution. | |
| 14 * * Neither the name of Google Inc. nor the names of its | |
| 15 * contributors may be used to endorse or promote products derived from | |
| 16 * this software without specific prior written permission. | |
| 17 * | |
| 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
| 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
| 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
| 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
| 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 29 */ | |
| 30 | |
| 31 #include "sky/engine/config.h" | |
| 32 #include "sky/engine/core/animation/CompositorAnimations.h" | |
| 33 | |
| 34 #include "sky/engine/core/animation/AnimationTranslationUtil.h" | |
| 35 #include "sky/engine/core/animation/CompositorAnimationsImpl.h" | |
| 36 #include "sky/engine/core/animation/animatable/AnimatableDouble.h" | |
| 37 #include "sky/engine/core/animation/animatable/AnimatableFilterOperations.h" | |
| 38 #include "sky/engine/core/animation/animatable/AnimatableTransform.h" | |
| 39 #include "sky/engine/core/animation/animatable/AnimatableValue.h" | |
| 40 #include "sky/engine/core/rendering/RenderBoxModelObject.h" | |
| 41 #include "sky/engine/core/rendering/RenderLayer.h" | |
| 42 #include "sky/engine/core/rendering/RenderObject.h" | |
| 43 #include "sky/engine/platform/geometry/FloatBox.h" | |
| 44 #include "sky/engine/public/platform/Platform.h" | |
| 45 #include "sky/engine/public/platform/WebCompositorAnimation.h" | |
| 46 #include "sky/engine/public/platform/WebCompositorSupport.h" | |
| 47 #include "sky/engine/public/platform/WebFilterAnimationCurve.h" | |
| 48 #include "sky/engine/public/platform/WebFilterKeyframe.h" | |
| 49 #include "sky/engine/public/platform/WebFloatAnimationCurve.h" | |
| 50 #include "sky/engine/public/platform/WebFloatKeyframe.h" | |
| 51 #include "sky/engine/public/platform/WebTransformAnimationCurve.h" | |
| 52 #include "sky/engine/public/platform/WebTransformKeyframe.h" | |
| 53 | |
| 54 #include <algorithm> | |
| 55 #include <cmath> | |
| 56 | |
| 57 namespace blink { | |
| 58 | |
| 59 namespace { | |
| 60 | |
| 61 void getKeyframeValuesForProperty(const KeyframeEffectModelBase* effect, CSSProp
ertyID id, double scale, bool reverse, PropertySpecificKeyframeVector& values) | |
| 62 { | |
| 63 ASSERT(values.isEmpty()); | |
| 64 const PropertySpecificKeyframeVector& group = effect->getPropertySpecificKey
frames(id); | |
| 65 | |
| 66 if (reverse) { | |
| 67 for (size_t i = group.size(); i--;) { | |
| 68 double offset = (1 - group[i]->offset()) * scale; | |
| 69 values.append(group[i]->cloneWithOffset(offset)); | |
| 70 } | |
| 71 } else { | |
| 72 for (size_t i = 0; i < group.size(); ++i) { | |
| 73 double offset = group[i]->offset() * scale; | |
| 74 values.append(group[i]->cloneWithOffset(offset)); | |
| 75 } | |
| 76 } | |
| 77 } | |
| 78 | |
| 79 } | |
| 80 | |
| 81 // ----------------------------------------------------------------------- | |
| 82 // TimingFunctionReverser methods | |
| 83 // ----------------------------------------------------------------------- | |
| 84 | |
| 85 PassRefPtr<TimingFunction> CompositorAnimationsTimingFunctionReverser::reverse(c
onst LinearTimingFunction& timefunc) | |
| 86 { | |
| 87 return const_cast<LinearTimingFunction*>(&timefunc); | |
| 88 } | |
| 89 | |
| 90 PassRefPtr<TimingFunction> CompositorAnimationsTimingFunctionReverser::reverse(c
onst CubicBezierTimingFunction& timefunc) | |
| 91 { | |
| 92 switch (timefunc.subType()) { | |
| 93 case CubicBezierTimingFunction::EaseIn: | |
| 94 return CubicBezierTimingFunction::preset(CubicBezierTimingFunction::Ease
Out); | |
| 95 case CubicBezierTimingFunction::EaseOut: | |
| 96 return CubicBezierTimingFunction::preset(CubicBezierTimingFunction::Ease
In); | |
| 97 case CubicBezierTimingFunction::EaseInOut: | |
| 98 return const_cast<CubicBezierTimingFunction*>(&timefunc); | |
| 99 case CubicBezierTimingFunction::Ease: // Ease is not symmetrical | |
| 100 case CubicBezierTimingFunction::Custom: | |
| 101 return CubicBezierTimingFunction::create(1 - timefunc.x2(), 1 - timefunc
.y2(), 1 - timefunc.x1(), 1 - timefunc.y1()); | |
| 102 default: | |
| 103 ASSERT_NOT_REACHED(); | |
| 104 return PassRefPtr<TimingFunction>(); | |
| 105 } | |
| 106 } | |
| 107 | |
| 108 PassRefPtr<TimingFunction> CompositorAnimationsTimingFunctionReverser::reverse(c
onst TimingFunction& timefunc) | |
| 109 { | |
| 110 switch (timefunc.type()) { | |
| 111 case TimingFunction::LinearFunction: { | |
| 112 const LinearTimingFunction& linear = toLinearTimingFunction(timefunc); | |
| 113 return reverse(linear); | |
| 114 } | |
| 115 case TimingFunction::CubicBezierFunction: { | |
| 116 const CubicBezierTimingFunction& cubic = toCubicBezierTimingFunction(tim
efunc); | |
| 117 return reverse(cubic); | |
| 118 } | |
| 119 | |
| 120 // Steps function can not be reversed. | |
| 121 case TimingFunction::StepsFunction: | |
| 122 default: | |
| 123 ASSERT_NOT_REACHED(); | |
| 124 return PassRefPtr<TimingFunction>(); | |
| 125 } | |
| 126 } | |
| 127 | |
| 128 bool CompositorAnimations::getAnimatedBoundingBox(FloatBox& box, const Animation
Effect& effect, double minValue, double maxValue) const | |
| 129 { | |
| 130 const KeyframeEffectModelBase& keyframeEffect = toKeyframeEffectModelBase(ef
fect); | |
| 131 | |
| 132 PropertySet properties = keyframeEffect.properties(); | |
| 133 | |
| 134 if (properties.isEmpty()) | |
| 135 return true; | |
| 136 | |
| 137 minValue = std::min(minValue, 0.0); | |
| 138 maxValue = std::max(maxValue, 1.0); | |
| 139 | |
| 140 for (PropertySet::const_iterator it = properties.begin(); it != properties.e
nd(); ++it) { | |
| 141 // TODO: Add the ability to get expanded bounds for filters as well. | |
| 142 if (*it != CSSPropertyTransform && *it != CSSPropertyWebkitTransform) | |
| 143 continue; | |
| 144 | |
| 145 const PropertySpecificKeyframeVector& frames = keyframeEffect.getPropert
ySpecificKeyframes(*it); | |
| 146 if (frames.isEmpty() || frames.size() < 2) | |
| 147 continue; | |
| 148 | |
| 149 FloatBox originalBox(box); | |
| 150 | |
| 151 for (size_t j = 0; j < frames.size() - 1; ++j) { | |
| 152 const AnimatableTransform* startTransform = toAnimatableTransform(fr
ames[j]->getAnimatableValue().get()); | |
| 153 const AnimatableTransform* endTransform = toAnimatableTransform(fram
es[j+1]->getAnimatableValue().get()); | |
| 154 // TODO: Add support for inflating modes other than Replace. | |
| 155 if (frames[j]->composite() != AnimationEffect::CompositeReplace) | |
| 156 return false; | |
| 157 | |
| 158 const TimingFunction& timing = frames[j]->easing(); | |
| 159 double min = 0; | |
| 160 double max = 1; | |
| 161 if (j == 0) { | |
| 162 float frameLength = frames[j+1]->offset(); | |
| 163 if (frameLength > 0) { | |
| 164 min = minValue / frameLength; | |
| 165 } | |
| 166 } | |
| 167 | |
| 168 if (j == frames.size() - 2) { | |
| 169 float frameLength = frames[j+1]->offset() - frames[j]->offset(); | |
| 170 if (frameLength > 0) { | |
| 171 max = 1 + (maxValue - 1) / frameLength; | |
| 172 } | |
| 173 } | |
| 174 | |
| 175 FloatBox bounds; | |
| 176 timing.range(&min, &max); | |
| 177 if (!endTransform->transformOperations().blendedBoundsForBox(origina
lBox, startTransform->transformOperations(), min, max, &bounds)) | |
| 178 return false; | |
| 179 box.expandTo(bounds); | |
| 180 } | |
| 181 } | |
| 182 return true; | |
| 183 } | |
| 184 | |
| 185 // ----------------------------------------------------------------------- | |
| 186 // CompositorAnimations public API | |
| 187 // ----------------------------------------------------------------------- | |
| 188 | |
| 189 bool CompositorAnimations::isCandidateForAnimationOnCompositor(const Timing& tim
ing, const AnimationEffect& effect) | |
| 190 { | |
| 191 const KeyframeEffectModelBase& keyframeEffect = toKeyframeEffectModelBase(ef
fect); | |
| 192 | |
| 193 PropertySet properties = keyframeEffect.properties(); | |
| 194 | |
| 195 if (properties.isEmpty()) | |
| 196 return false; | |
| 197 | |
| 198 for (PropertySet::const_iterator it = properties.begin(); it != properties.e
nd(); ++it) { | |
| 199 const PropertySpecificKeyframeVector& frames = keyframeEffect.getPropert
ySpecificKeyframes(*it); | |
| 200 ASSERT(frames.size() >= 2); | |
| 201 for (size_t i = 0; i < frames.size(); ++i) { | |
| 202 const Keyframe::PropertySpecificKeyframe *frame = frames[i].get(); | |
| 203 // FIXME: Determine candidacy based on the CSSValue instead of a sna
pshot AnimatableValue. | |
| 204 if (frame->composite() != AnimationEffect::CompositeReplace || !fram
e->getAnimatableValue()) | |
| 205 return false; | |
| 206 | |
| 207 switch (*it) { | |
| 208 case CSSPropertyOpacity: | |
| 209 break; | |
| 210 case CSSPropertyTransform: | |
| 211 if (toAnimatableTransform(frame->getAnimatableValue().get())->tr
ansformOperations().dependsOnBoxSize()) | |
| 212 return false; | |
| 213 break; | |
| 214 case CSSPropertyWebkitFilter: { | |
| 215 const FilterOperations& operations = toAnimatableFilterOperation
s(frame->getAnimatableValue().get())->operations(); | |
| 216 if (operations.hasFilterThatMovesPixels()) | |
| 217 return false; | |
| 218 break; | |
| 219 } | |
| 220 default: | |
| 221 return false; | |
| 222 } | |
| 223 | |
| 224 // FIXME: Remove this check when crbug.com/229405 is resolved | |
| 225 if (i < frames.size() - 1 && frame->easing().type() == TimingFunctio
n::StepsFunction) | |
| 226 return false; | |
| 227 } | |
| 228 } | |
| 229 | |
| 230 CompositorAnimationsImpl::CompositorTiming out; | |
| 231 if (!CompositorAnimationsImpl::convertTimingForCompositor(timing, 0, out)) | |
| 232 return false; | |
| 233 | |
| 234 if (timing.timingFunction->type() != TimingFunction::LinearFunction) { | |
| 235 // Checks the of size of KeyframeVector instead of PropertySpecificKeyfr
ameVector. | |
| 236 const KeyframeVector& keyframes = keyframeEffect.getFrames(); | |
| 237 if (keyframes.size() == 2 && keyframes[0]->easing().type() == TimingFunc
tion::LinearFunction && timing.timingFunction->type() != TimingFunction::StepsFu
nction) | |
| 238 return true; | |
| 239 | |
| 240 // FIXME: Support non-linear timing functions in the compositor for | |
| 241 // more than two keyframes and step timing functions in the compositor. | |
| 242 return false; | |
| 243 } | |
| 244 | |
| 245 return true; | |
| 246 } | |
| 247 | |
| 248 bool CompositorAnimations::canStartAnimationOnCompositor(const Element& element) | |
| 249 { | |
| 250 return false; | |
| 251 } | |
| 252 | |
| 253 bool CompositorAnimations::startAnimationOnCompositor(const Element& element, do
uble startTime, double timeOffset, const Timing& timing, const AnimationEffect&
effect, Vector<int>& startedAnimationIds) | |
| 254 { | |
| 255 // FIXME(sky): Remove CompositorAnimations entirely. | |
| 256 ASSERT_NOT_REACHED(); | |
| 257 return true; | |
| 258 } | |
| 259 | |
| 260 void CompositorAnimations::cancelAnimationOnCompositor(const Element& element, i
nt id) | |
| 261 { | |
| 262 // FIXME(sky): Remove CompositorAnimations entirely. | |
| 263 ASSERT_NOT_REACHED(); | |
| 264 } | |
| 265 | |
| 266 void CompositorAnimations::pauseAnimationForTestingOnCompositor(const Element& e
lement, int id, double pauseTime) | |
| 267 { | |
| 268 // FIXME(sky): Remove CompositorAnimations entirely. | |
| 269 ASSERT_NOT_REACHED(); | |
| 270 } | |
| 271 | |
| 272 // ----------------------------------------------------------------------- | |
| 273 // CompositorAnimationsImpl | |
| 274 // ----------------------------------------------------------------------- | |
| 275 | |
| 276 bool CompositorAnimationsImpl::convertTimingForCompositor(const Timing& timing,
double timeOffset, CompositorTiming& out) | |
| 277 { | |
| 278 timing.assertValid(); | |
| 279 | |
| 280 // All fill modes are supported (the calling code handles them). | |
| 281 | |
| 282 // FIXME: Support non-zero iteration start. | |
| 283 if (timing.iterationStart) | |
| 284 return false; | |
| 285 | |
| 286 if (timing.iterationCount <= 0) | |
| 287 return false; | |
| 288 | |
| 289 if (std::isnan(timing.iterationDuration) || !timing.iterationDuration) | |
| 290 return false; | |
| 291 | |
| 292 // FIXME: Support other playback rates | |
| 293 if (timing.playbackRate != 1) | |
| 294 return false; | |
| 295 | |
| 296 // All directions are supported. | |
| 297 | |
| 298 // Now attempt an actual conversion | |
| 299 out.scaledDuration = timing.iterationDuration; | |
| 300 ASSERT(out.scaledDuration > 0); | |
| 301 | |
| 302 double scaledStartDelay = timing.startDelay; | |
| 303 if (scaledStartDelay > 0 && scaledStartDelay > out.scaledDuration * timing.i
terationCount) | |
| 304 return false; | |
| 305 | |
| 306 out.reverse = (timing.direction == Timing::PlaybackDirectionReverse | |
| 307 || timing.direction == Timing::PlaybackDirectionAlternateReverse); | |
| 308 out.alternate = (timing.direction == Timing::PlaybackDirectionAlternate | |
| 309 || timing.direction == Timing::PlaybackDirectionAlternateReverse); | |
| 310 | |
| 311 if (!std::isfinite(timing.iterationCount)) { | |
| 312 out.adjustedIterationCount = -1; | |
| 313 } else { | |
| 314 out.adjustedIterationCount = timing.iterationCount; | |
| 315 ASSERT(out.adjustedIterationCount > 0); | |
| 316 } | |
| 317 | |
| 318 // Compositor's time offset is positive for seeking into the animation. | |
| 319 out.scaledTimeOffset = -scaledStartDelay + timeOffset; | |
| 320 return true; | |
| 321 } | |
| 322 | |
| 323 namespace { | |
| 324 | |
| 325 template<typename PlatformAnimationCurveType, typename PlatformAnimationKeyframe
Type> | |
| 326 void addKeyframeWithTimingFunction(PlatformAnimationCurveType& curve, const Plat
formAnimationKeyframeType& keyframe, const TimingFunction* timingFunction) | |
| 327 { | |
| 328 if (!timingFunction) { | |
| 329 curve.add(keyframe); | |
| 330 return; | |
| 331 } | |
| 332 | |
| 333 switch (timingFunction->type()) { | |
| 334 case TimingFunction::LinearFunction: | |
| 335 curve.add(keyframe, WebCompositorAnimationCurve::TimingFunctionTypeLinea
r); | |
| 336 return; | |
| 337 | |
| 338 case TimingFunction::CubicBezierFunction: { | |
| 339 const CubicBezierTimingFunction* cubic = toCubicBezierTimingFunction(tim
ingFunction); | |
| 340 | |
| 341 if (cubic->subType() == CubicBezierTimingFunction::Custom) { | |
| 342 curve.add(keyframe, cubic->x1(), cubic->y1(), cubic->x2(), cubic->y2
()); | |
| 343 } else { | |
| 344 | |
| 345 WebCompositorAnimationCurve::TimingFunctionType easeType; | |
| 346 switch (cubic->subType()) { | |
| 347 case CubicBezierTimingFunction::Ease: | |
| 348 easeType = WebCompositorAnimationCurve::TimingFunctionTypeEase; | |
| 349 break; | |
| 350 case CubicBezierTimingFunction::EaseIn: | |
| 351 easeType = WebCompositorAnimationCurve::TimingFunctionTypeEaseIn
; | |
| 352 break; | |
| 353 case CubicBezierTimingFunction::EaseOut: | |
| 354 easeType = WebCompositorAnimationCurve::TimingFunctionTypeEaseOu
t; | |
| 355 break; | |
| 356 case CubicBezierTimingFunction::EaseInOut: | |
| 357 easeType = WebCompositorAnimationCurve::TimingFunctionTypeEaseIn
Out; | |
| 358 break; | |
| 359 | |
| 360 // Custom Bezier are handled seperately. | |
| 361 case CubicBezierTimingFunction::Custom: | |
| 362 default: | |
| 363 ASSERT_NOT_REACHED(); | |
| 364 return; | |
| 365 } | |
| 366 | |
| 367 curve.add(keyframe, easeType); | |
| 368 } | |
| 369 return; | |
| 370 } | |
| 371 | |
| 372 case TimingFunction::StepsFunction: | |
| 373 default: | |
| 374 ASSERT_NOT_REACHED(); | |
| 375 return; | |
| 376 } | |
| 377 } | |
| 378 | |
| 379 } // namespace anoymous | |
| 380 | |
| 381 void CompositorAnimationsImpl::addKeyframesToCurve(WebCompositorAnimationCurve&
curve, const PropertySpecificKeyframeVector& keyframes, const Timing& timing, bo
ol reverse) | |
| 382 { | |
| 383 for (size_t i = 0; i < keyframes.size(); i++) { | |
| 384 RefPtr<TimingFunction> reversedTimingFunction; | |
| 385 const TimingFunction* keyframeTimingFunction = 0; | |
| 386 if (i < keyframes.size() - 1) { // Ignore timing function of last frame. | |
| 387 if (keyframes.size() == 2 && keyframes[0]->easing().type() == Timing
Function::LinearFunction) { | |
| 388 if (reverse) { | |
| 389 reversedTimingFunction = CompositorAnimationsTimingFunctionR
everser::reverse(*timing.timingFunction.get()); | |
| 390 keyframeTimingFunction = reversedTimingFunction.get(); | |
| 391 } else { | |
| 392 keyframeTimingFunction = timing.timingFunction.get(); | |
| 393 } | |
| 394 } else { | |
| 395 if (reverse) { | |
| 396 reversedTimingFunction = CompositorAnimationsTimingFunctionR
everser::reverse(keyframes[i + 1]->easing()); | |
| 397 keyframeTimingFunction = reversedTimingFunction.get(); | |
| 398 } else { | |
| 399 keyframeTimingFunction = &keyframes[i]->easing(); | |
| 400 } | |
| 401 } | |
| 402 } | |
| 403 | |
| 404 // FIXME: This relies on StringKeyframes being eagerly evaluated, which
will | |
| 405 // not happen eventually. Instead we should extract the CSSValue here | |
| 406 // and convert using another set of toAnimatableXXXOperations functions. | |
| 407 const AnimatableValue* value = keyframes[i]->getAnimatableValue().get(); | |
| 408 | |
| 409 switch (curve.type()) { | |
| 410 case WebCompositorAnimationCurve::AnimationCurveTypeFilter: { | |
| 411 OwnPtr<WebFilterOperations> ops = adoptPtr(Platform::current()->comp
ositorSupport()->createFilterOperations()); | |
| 412 toWebFilterOperations(toAnimatableFilterOperations(value)->operation
s(), ops.get()); | |
| 413 | |
| 414 WebFilterKeyframe filterKeyframe(keyframes[i]->offset(), ops.release
()); | |
| 415 WebFilterAnimationCurve* filterCurve = static_cast<WebFilterAnimatio
nCurve*>(&curve); | |
| 416 addKeyframeWithTimingFunction(*filterCurve, filterKeyframe, keyframe
TimingFunction); | |
| 417 break; | |
| 418 } | |
| 419 case WebCompositorAnimationCurve::AnimationCurveTypeFloat: { | |
| 420 WebFloatKeyframe floatKeyframe(keyframes[i]->offset(), toAnimatableD
ouble(value)->toDouble()); | |
| 421 WebFloatAnimationCurve* floatCurve = static_cast<WebFloatAnimationCu
rve*>(&curve); | |
| 422 addKeyframeWithTimingFunction(*floatCurve, floatKeyframe, keyframeTi
mingFunction); | |
| 423 break; | |
| 424 } | |
| 425 case WebCompositorAnimationCurve::AnimationCurveTypeTransform: { | |
| 426 OwnPtr<WebTransformOperations> ops = adoptPtr(Platform::current()->c
ompositorSupport()->createTransformOperations()); | |
| 427 toWebTransformOperations(toAnimatableTransform(value)->transformOper
ations(), ops.get()); | |
| 428 | |
| 429 WebTransformKeyframe transformKeyframe(keyframes[i]->offset(), ops.r
elease()); | |
| 430 WebTransformAnimationCurve* transformCurve = static_cast<WebTransfor
mAnimationCurve*>(&curve); | |
| 431 addKeyframeWithTimingFunction(*transformCurve, transformKeyframe, ke
yframeTimingFunction); | |
| 432 break; | |
| 433 } | |
| 434 default: | |
| 435 ASSERT_NOT_REACHED(); | |
| 436 } | |
| 437 } | |
| 438 } | |
| 439 | |
| 440 void CompositorAnimationsImpl::getAnimationOnCompositor(const Timing& timing, do
uble startTime, double timeOffset, const KeyframeEffectModelBase& effect, Vector
<OwnPtr<WebCompositorAnimation> >& animations) | |
| 441 { | |
| 442 ASSERT(animations.isEmpty()); | |
| 443 CompositorTiming compositorTiming; | |
| 444 bool timingValid = convertTimingForCompositor(timing, timeOffset, compositor
Timing); | |
| 445 ASSERT_UNUSED(timingValid, timingValid); | |
| 446 | |
| 447 PropertySet properties = effect.properties(); | |
| 448 ASSERT(!properties.isEmpty()); | |
| 449 for (PropertySet::iterator it = properties.begin(); it != properties.end();
++it) { | |
| 450 | |
| 451 PropertySpecificKeyframeVector values; | |
| 452 getKeyframeValuesForProperty(&effect, *it, compositorTiming.scaledDurati
on, compositorTiming.reverse, values); | |
| 453 | |
| 454 WebCompositorAnimation::TargetProperty targetProperty; | |
| 455 OwnPtr<WebCompositorAnimationCurve> curve; | |
| 456 switch (*it) { | |
| 457 case CSSPropertyOpacity: { | |
| 458 targetProperty = WebCompositorAnimation::TargetPropertyOpacity; | |
| 459 | |
| 460 WebFloatAnimationCurve* floatCurve = Platform::current()->compositor
Support()->createFloatAnimationCurve(); | |
| 461 addKeyframesToCurve(*floatCurve, values, timing, compositorTiming.re
verse); | |
| 462 curve = adoptPtr(floatCurve); | |
| 463 break; | |
| 464 } | |
| 465 case CSSPropertyWebkitFilter: { | |
| 466 targetProperty = WebCompositorAnimation::TargetPropertyFilter; | |
| 467 WebFilterAnimationCurve* filterCurve = Platform::current()->composit
orSupport()->createFilterAnimationCurve(); | |
| 468 addKeyframesToCurve(*filterCurve, values, timing, compositorTiming.r
everse); | |
| 469 curve = adoptPtr(filterCurve); | |
| 470 break; | |
| 471 } | |
| 472 case CSSPropertyTransform: { | |
| 473 targetProperty = WebCompositorAnimation::TargetPropertyTransform; | |
| 474 WebTransformAnimationCurve* transformCurve = Platform::current()->co
mpositorSupport()->createTransformAnimationCurve(); | |
| 475 addKeyframesToCurve(*transformCurve, values, timing, compositorTimin
g.reverse); | |
| 476 curve = adoptPtr(transformCurve); | |
| 477 break; | |
| 478 } | |
| 479 default: | |
| 480 ASSERT_NOT_REACHED(); | |
| 481 continue; | |
| 482 } | |
| 483 ASSERT(curve.get()); | |
| 484 | |
| 485 OwnPtr<WebCompositorAnimation> animation = adoptPtr(Platform::current()-
>compositorSupport()->createAnimation(*curve, targetProperty)); | |
| 486 | |
| 487 if (!std::isnan(startTime)) | |
| 488 animation->setStartTime(startTime); | |
| 489 | |
| 490 animation->setIterations(compositorTiming.adjustedIterationCount); | |
| 491 animation->setTimeOffset(compositorTiming.scaledTimeOffset); | |
| 492 animation->setAlternatesDirection(compositorTiming.alternate); | |
| 493 | |
| 494 animations.append(animation.release()); | |
| 495 } | |
| 496 ASSERT(!animations.isEmpty()); | |
| 497 } | |
| 498 | |
| 499 } // namespace blink | |
| OLD | NEW |