TEST_F(AnimationInterpolationEffectTest, SingleInterpolation) { RefPtrWillBeRawPtr<InterpolationEffect> interpolationEffect = InterpolationEffect::create(); interpolationEffect->addInterpolation(SampleInterpolation::create(InterpolableNumber::create(0), InterpolableNumber::create(10)), RefPtr<TimingFunction>(), 0, 1, -1, 2); OwnPtrWillBeRawPtr<WillBeHeapVector<RefPtrWillBeMember<Interpolation>>> activeInterpolations = nullptr; interpolationEffect->getActiveInterpolations(-2, duration, activeInterpolations); EXPECT_EQ(0ul, activeInterpolations->size()); interpolationEffect->getActiveInterpolations(-0.5, duration, activeInterpolations); EXPECT_EQ(1ul, activeInterpolations->size()); EXPECT_EQ(-5, getInterpolableNumber(activeInterpolations->at(0))); interpolationEffect->getActiveInterpolations(0.5, duration, activeInterpolations); EXPECT_EQ(1ul, activeInterpolations->size()); EXPECT_FLOAT_EQ(5, getInterpolableNumber(activeInterpolations->at(0))); interpolationEffect->getActiveInterpolations(1.5, duration, activeInterpolations); EXPECT_EQ(1ul, activeInterpolations->size()); EXPECT_FLOAT_EQ(15, getInterpolableNumber(activeInterpolations->at(0))); interpolationEffect->getActiveInterpolations(3, duration, activeInterpolations); EXPECT_EQ(0ul, activeInterpolations->size()); }
StyleRuleKeyframes* BisonCSSParser::createKeyframesRule(const String& name, PassOwnPtrWillBeRawPtr<WillBeHeapVector<RefPtrWillBeMember<StyleRuleKeyframe>>> popKeyframes, bool isPrefixed) { OwnPtrWillBeRawPtr<WillBeHeapVector<RefPtrWillBeMember<StyleRuleKeyframe>>> keyframes = popKeyframes; m_allowImportRules = m_allowNamespaceDeclarations = false; RefPtrWillBeRawPtr<StyleRuleKeyframes> rule = StyleRuleKeyframes::create(); for (size_t i = 0; i < keyframes->size(); ++i) rule->parserAppendKeyframe(keyframes->at(i)); rule->setName(name); rule->setVendorPrefixed(isPrefixed); StyleRuleKeyframes* rulePtr = rule.get(); m_parsedRules.append(rule.release()); return rulePtr; }
Element* TreeScope::adjustedFocusedElement() const { Document& document = rootNode().document(); Element* element = document.focusedElement(); if (!element && document.page()) element = focusedFrameOwnerElement(document.page()->focusController().focusedFrame(), document.frame()); if (!element) return 0; OwnPtrWillBeRawPtr<EventPath> eventPath = adoptPtrWillBeNoop(new EventPath(*element)); for (size_t i = 0; i < eventPath->size(); ++i) { if (eventPath->at(i).node() == rootNode()) { // eventPath->at(i).target() is one of the followings: // - InsertionPoint // - shadow host // - Document::focusedElement() // So, it's safe to do toElement(). return toElement(eventPath->at(i).target()->toNode()); } } return 0; }
TEST_F(AnimationInterpolationEffectTest, MultipleInterpolations) { RefPtrWillBeRawPtr<InterpolationEffect> interpolationEffect = InterpolationEffect::create(); interpolationEffect->addInterpolation(SampleInterpolation::create(InterpolableNumber::create(10), InterpolableNumber::create(15)), RefPtr<TimingFunction>(), 1, 2, 1, 3); interpolationEffect->addInterpolation(SampleInterpolation::create(InterpolableNumber::create(0), InterpolableNumber::create(1)), LinearTimingFunction::shared(), 0, 1, 0, 1); interpolationEffect->addInterpolation(SampleInterpolation::create(InterpolableNumber::create(1), InterpolableNumber::create(6)), CubicBezierTimingFunction::preset(CubicBezierTimingFunction::Ease), 0.5, 1.5, 0.5, 1.5); OwnPtrWillBeRawPtr<WillBeHeapVector<RefPtrWillBeMember<Interpolation>>> activeInterpolations = nullptr; interpolationEffect->getActiveInterpolations(-0.5, duration, activeInterpolations); EXPECT_EQ(0ul, activeInterpolations->size()); interpolationEffect->getActiveInterpolations(0, duration, activeInterpolations); EXPECT_EQ(1ul, activeInterpolations->size()); EXPECT_FLOAT_EQ(0, getInterpolableNumber(activeInterpolations->at(0))); interpolationEffect->getActiveInterpolations(0.5, duration, activeInterpolations); EXPECT_EQ(2ul, activeInterpolations->size()); EXPECT_FLOAT_EQ(0.5f, getInterpolableNumber(activeInterpolations->at(0))); EXPECT_FLOAT_EQ(1, getInterpolableNumber(activeInterpolations->at(1))); interpolationEffect->getActiveInterpolations(1, duration, activeInterpolations); EXPECT_EQ(2ul, activeInterpolations->size()); EXPECT_FLOAT_EQ(10, getInterpolableNumber(activeInterpolations->at(0))); EXPECT_FLOAT_EQ(5.0282884f, getInterpolableNumber(activeInterpolations->at(1))); interpolationEffect->getActiveInterpolations(1, duration * 1000, activeInterpolations); EXPECT_EQ(2ul, activeInterpolations->size()); EXPECT_FLOAT_EQ(10, getInterpolableNumber(activeInterpolations->at(0))); EXPECT_FLOAT_EQ(5.0120168f, getInterpolableNumber(activeInterpolations->at(1))); interpolationEffect->getActiveInterpolations(1.5, duration, activeInterpolations); EXPECT_EQ(1ul, activeInterpolations->size()); EXPECT_FLOAT_EQ(12.5f, getInterpolableNumber(activeInterpolations->at(0))); interpolationEffect->getActiveInterpolations(2, duration, activeInterpolations); EXPECT_EQ(1ul, activeInterpolations->size()); EXPECT_FLOAT_EQ(15, getInterpolableNumber(activeInterpolations->at(0))); }
void CSSAnimations::maybeApplyPendingUpdate(Element* element) { if (!m_pendingUpdate) { m_previousActiveInterpolationsForAnimations.clear(); return; } OwnPtrWillBeRawPtr<CSSAnimationUpdate> update = m_pendingUpdate.release(); m_previousActiveInterpolationsForAnimations.swap(update->activeInterpolationsForAnimations()); // FIXME: cancelling, pausing, unpausing animations all query compositingState, which is not necessarily up to date here // since we call this from recalc style. // https://code.google.com/p/chromium/issues/detail?id=339847 DisableCompositingQueryAsserts disabler; for (const AtomicString& animationName : update->cancelledAnimationNames()) { RefPtrWillBeRawPtr<AnimationPlayer> player = m_animations.take(animationName); player->cancel(); player->update(TimingUpdateOnDemand); } for (const AtomicString& animationName : update->animationsWithPauseToggled()) { AnimationPlayer* player = m_animations.get(animationName); if (player->paused()) player->unpause(); else player->pause(); if (player->outdated()) player->update(TimingUpdateOnDemand); } for (const auto& entry : update->newAnimations()) { const InertAnimation* inertAnimation = entry.animation.get(); OwnPtrWillBeRawPtr<AnimationEventDelegate> eventDelegate = adoptPtrWillBeNoop(new AnimationEventDelegate(element, entry.name)); RefPtrWillBeRawPtr<Animation> animation = Animation::create(element, inertAnimation->effect(), inertAnimation->specifiedTiming(), Animation::DefaultPriority, eventDelegate.release()); animation->setName(inertAnimation->name()); RefPtrWillBeRawPtr<AnimationPlayer> player = element->document().timeline().createAnimationPlayer(animation.get()); if (inertAnimation->paused()) player->pause(); player->update(TimingUpdateOnDemand); m_animations.set(entry.name, player.get()); } // Transitions that are run on the compositor only update main-thread state // lazily. However, we need the new state to know what the from state shoud // be when transitions are retargeted. Instead of triggering complete style // recalculation, we find these cases by searching for new transitions that // have matching cancelled animation property IDs on the compositor. WillBeHeapHashMap<CSSPropertyID, std::pair<RefPtrWillBeMember<Animation>, double>> retargetedCompositorTransitions; for (CSSPropertyID id : update->cancelledTransitions()) { ASSERT(m_transitions.contains(id)); RefPtrWillBeRawPtr<AnimationPlayer> player = m_transitions.take(id).player; Animation* animation = toAnimation(player->source()); if (animation->hasActiveAnimationsOnCompositor(id) && update->newTransitions().find(id) != update->newTransitions().end()) retargetedCompositorTransitions.add(id, std::pair<RefPtrWillBeMember<Animation>, double>(animation, player->startTimeInternal())); player->cancel(); player->update(TimingUpdateOnDemand); } for (const auto& entry : update->newTransitions()) { const CSSAnimationUpdate::NewTransition& newTransition = entry.value; RunningTransition runningTransition; runningTransition.from = newTransition.from; runningTransition.to = newTransition.to; CSSPropertyID id = newTransition.id; InertAnimation* inertAnimation = newTransition.animation.get(); OwnPtrWillBeRawPtr<TransitionEventDelegate> eventDelegate = adoptPtrWillBeNoop(new TransitionEventDelegate(element, newTransition.eventId)); RefPtrWillBeRawPtr<AnimationEffect> effect = inertAnimation->effect(); if (retargetedCompositorTransitions.contains(id)) { const std::pair<RefPtrWillBeMember<Animation>, double>& oldTransition = retargetedCompositorTransitions.get(id); RefPtrWillBeRawPtr<Animation> oldAnimation = oldTransition.first; double oldStartTime = oldTransition.second; double inheritedTime = isNull(oldStartTime) ? 0 : element->document().timeline().currentTimeInternal() - oldStartTime; AnimatableValueKeyframeEffectModel* oldEffect = toAnimatableValueKeyframeEffectModel(inertAnimation->effect()); const KeyframeVector& frames = oldEffect->getFrames(); AnimatableValueKeyframeVector newFrames; newFrames.append(toAnimatableValueKeyframe(frames[0]->clone().get())); newFrames.append(toAnimatableValueKeyframe(frames[1]->clone().get())); newFrames[0]->clearPropertyValue(id); RefPtrWillBeRawPtr<InertAnimation> inertAnimationForSampling = InertAnimation::create(oldAnimation->effect(), oldAnimation->specifiedTiming(), false); OwnPtrWillBeRawPtr<WillBeHeapVector<RefPtrWillBeMember<Interpolation>>> sample = inertAnimationForSampling->sample(inheritedTime); ASSERT(sample->size() == 1); newFrames[0]->setPropertyValue(id, toLegacyStyleInterpolation(sample->at(0).get())->currentValue()); effect = AnimatableValueKeyframeEffectModel::create(newFrames); } RefPtrWillBeRawPtr<Animation> transition = Animation::create(element, effect, inertAnimation->specifiedTiming(), Animation::TransitionPriority, eventDelegate.release()); transition->setName(inertAnimation->name()); RefPtrWillBeRawPtr<AnimationPlayer> player = element->document().timeline().createAnimationPlayer(transition.get()); player->update(TimingUpdateOnDemand); runningTransition.player = player; m_transitions.set(id, runningTransition); ASSERT(id != CSSPropertyInvalid); blink::Platform::current()->histogramSparse("WebCore.Animation.CSSProperties", UseCounter::mapCSSPropertyIdToCSSSampleIdForHistogram(id)); } }