diff options
author | vollick@chromium.org <vollick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-03 21:38:08 +0000 |
---|---|---|
committer | vollick@chromium.org <vollick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-11-03 21:38:08 +0000 |
commit | f5cd9e5d3c402226c8ff260eb63562df269f27ac (patch) | |
tree | 81f71523b4497cd576a469e8dd5383a7cefeee27 /ui | |
parent | 6cd8a30576416c6e28debe4c811a22aa670e88db (diff) | |
download | chromium_src-f5cd9e5d3c402226c8ff260eb63562df269f27ac.zip chromium_src-f5cd9e5d3c402226c8ff260eb63562df269f27ac.tar.gz chromium_src-f5cd9e5d3c402226c8ff260eb63562df269f27ac.tar.bz2 |
Setting a layer property immediately should cancel any current animations.
This CL depends on http://codereview.chromium.org/8395046/
The fix boils down to two changes to the layer animator:
1. When calling Set*** we must start a zero duration animation and not short circuit. The animator needs to be able to update its state, and the preemption strategy needs to be applied.
2. Always be aware that progressing or aborting animation may affect the list of running animation and take appropriate precautions.
I have added a unit test to make sure the fix for 102413 doesn't regress and updated the existing unit tests for the new behavior (specifically, we now get notified that a sequence has ended whenever we call Set*** because of 1. above).
BUG=102413
TEST=compositor_unittests
Review URL: http://codereview.chromium.org/8387051
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@108546 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui')
-rw-r--r-- | ui/aura/screen_rotation.cc | 4 | ||||
-rw-r--r-- | ui/base/animation/tween.cc | 5 | ||||
-rw-r--r-- | ui/gfx/compositor/layer_animation_element.cc | 10 | ||||
-rw-r--r-- | ui/gfx/compositor/layer_animation_element.h | 4 | ||||
-rw-r--r-- | ui/gfx/compositor/layer_animation_element_unittest.cc | 6 | ||||
-rw-r--r-- | ui/gfx/compositor/layer_animation_observer.h | 3 | ||||
-rw-r--r-- | ui/gfx/compositor/layer_animation_sequence.cc | 4 | ||||
-rw-r--r-- | ui/gfx/compositor/layer_animation_sequence_unittest.cc | 2 | ||||
-rw-r--r-- | ui/gfx/compositor/layer_animator.cc | 180 | ||||
-rw-r--r-- | ui/gfx/compositor/layer_animator.h | 7 | ||||
-rw-r--r-- | ui/gfx/compositor/layer_animator_unittest.cc | 31 | ||||
-rw-r--r-- | ui/gfx/compositor/layer_unittest.cc | 2 |
12 files changed, 156 insertions, 102 deletions
diff --git a/ui/aura/screen_rotation.cc b/ui/aura/screen_rotation.cc index d9e1fc8..6b46817 100644 --- a/ui/aura/screen_rotation.cc +++ b/ui/aura/screen_rotation.cc @@ -114,9 +114,7 @@ void ScreenRotation::OnAbort() { const ui::LayerAnimationElement::AnimatableProperties& ScreenRotation::GetProperties() { static LayerAnimationElement::AnimatableProperties properties; - if (properties.size() == 0) { + if (properties.empty()) properties.insert(LayerAnimationElement::TRANSFORM); - properties.insert(LayerAnimationElement::BOUNDS); - } return properties; } diff --git a/ui/base/animation/tween.cc b/ui/base/animation/tween.cc index a16bb18..3d57aef 100644 --- a/ui/base/animation/tween.cc +++ b/ui/base/animation/tween.cc @@ -91,6 +91,11 @@ gfx::Rect Tween::ValueBetween(double value, Transform Tween::ValueBetween(double value, const Transform& start_transform, const Transform& end_transform) { + if (value >= 1.0) + return end_transform; + if (value <= 0.0) + return start_transform; + Transform to_return; gfx::Point start_translation, end_translation; float start_rotation, end_rotation; diff --git a/ui/gfx/compositor/layer_animation_element.cc b/ui/gfx/compositor/layer_animation_element.cc index abff5f6..8aca397 100644 --- a/ui/gfx/compositor/layer_animation_element.cc +++ b/ui/gfx/compositor/layer_animation_element.cc @@ -150,7 +150,15 @@ class OpacityTransition : public LayerAnimationElement { // LayerAnimationElement::TargetValue ------------------------------------------ -LayerAnimationElement::TargetValue::TargetValue() : opacity(0.0f) { +LayerAnimationElement::TargetValue::TargetValue() + : opacity(0.0f) { +} + +LayerAnimationElement::TargetValue::TargetValue( + const LayerAnimationDelegate* delegate) + : bounds(delegate ? delegate->GetBoundsForAnimation() : gfx::Rect()), + transform(delegate ? delegate->GetTransformForAnimation() : Transform()), + opacity(delegate ? delegate->GetOpacityForAnimation() : 0.0f) { } // LayerAnimationElement ------------------------------------------------------- diff --git a/ui/gfx/compositor/layer_animation_element.h b/ui/gfx/compositor/layer_animation_element.h index d38bc42..c059f16 100644 --- a/ui/gfx/compositor/layer_animation_element.h +++ b/ui/gfx/compositor/layer_animation_element.h @@ -30,8 +30,10 @@ class COMPOSITOR_EXPORT LayerAnimationElement { }; struct TargetValue { - public: TargetValue(); + // Initializes the target value to match the delegate. NULL may be supplied. + explicit TargetValue(const LayerAnimationDelegate* delegate); + gfx::Rect bounds; Transform transform; float opacity; diff --git a/ui/gfx/compositor/layer_animation_element_unittest.cc b/ui/gfx/compositor/layer_animation_element_unittest.cc index 27940d4..4637e92 100644 --- a/ui/gfx/compositor/layer_animation_element_unittest.cc +++ b/ui/gfx/compositor/layer_animation_element_unittest.cc @@ -44,7 +44,7 @@ TEST(LayerAnimationElementTest, TransformElement) { delegate.GetTransformForAnimation()); } - LayerAnimationElement::TargetValue target_value; + LayerAnimationElement::TargetValue target_value(&delegate); element->GetTargetValue(&target_value); CheckApproximatelyEqual(target_transform, target_value.transform); @@ -74,7 +74,7 @@ TEST(LayerAnimationElementTest, BoundsElement) { CheckApproximatelyEqual(target, delegate.GetBoundsForAnimation()); } - LayerAnimationElement::TargetValue target_value; + LayerAnimationElement::TargetValue target_value(&delegate); element->GetTargetValue(&target_value); CheckApproximatelyEqual(target, target_value.bounds); @@ -102,7 +102,7 @@ TEST(LayerAnimationElementTest, OpacityElement) { EXPECT_FLOAT_EQ(target, delegate.GetOpacityForAnimation()); } - LayerAnimationElement::TargetValue target_value; + LayerAnimationElement::TargetValue target_value(&delegate); element->GetTargetValue(&target_value); EXPECT_FLOAT_EQ(target, target_value.opacity); diff --git a/ui/gfx/compositor/layer_animation_observer.h b/ui/gfx/compositor/layer_animation_observer.h index 1fe031e..e737345 100644 --- a/ui/gfx/compositor/layer_animation_observer.h +++ b/ui/gfx/compositor/layer_animation_observer.h @@ -19,7 +19,8 @@ class COMPOSITOR_EXPORT LayerAnimationObserver { virtual void OnLayerAnimationEnded( const LayerAnimationSequence* sequence) = 0; - // Called if |sequence| is aborted for any reason. + // Called if |sequence| is aborted for any reason. Should never do anything + // that may cause another animation to be started. virtual void OnLayerAnimationAborted( const LayerAnimationSequence* sequence) = 0; diff --git a/ui/gfx/compositor/layer_animation_sequence.cc b/ui/gfx/compositor/layer_animation_sequence.cc index f2e362b..1b408bc 100644 --- a/ui/gfx/compositor/layer_animation_sequence.cc +++ b/ui/gfx/compositor/layer_animation_sequence.cc @@ -30,10 +30,10 @@ LayerAnimationSequence::~LayerAnimationSequence() { void LayerAnimationSequence::Progress(base::TimeDelta elapsed, LayerAnimationDelegate* delegate) { - if (elements_.size() == 0 || duration_ == base::TimeDelta()) + if (elements_.empty()) return; - if (is_cyclic_) { + if (is_cyclic_ && duration_ > base::TimeDelta()) { // If delta = elapsed - last_start_ is huge, we can skip ahead by complete // loops to save time. base::TimeDelta delta = elapsed - last_start_; diff --git a/ui/gfx/compositor/layer_animation_sequence_unittest.cc b/ui/gfx/compositor/layer_animation_sequence_unittest.cc index ff44b58..11c1e8b 100644 --- a/ui/gfx/compositor/layer_animation_sequence_unittest.cc +++ b/ui/gfx/compositor/layer_animation_sequence_unittest.cc @@ -165,7 +165,7 @@ TEST(LayerAnimationSequenceTest, SetTarget) { sequence.AddElement( LayerAnimationElement::CreateOpacityElement(target_opacity, delta)); - LayerAnimationElement::TargetValue target_value; + LayerAnimationElement::TargetValue target_value(&delegate); target_value.opacity = start_opacity; sequence.GetTargetValue(&target_value); EXPECT_FLOAT_EQ(target_opacity, target_value.opacity); diff --git a/ui/gfx/compositor/layer_animator.cc b/ui/gfx/compositor/layer_animator.cc index 14a4bf98..1ec2b78 100644 --- a/ui/gfx/compositor/layer_animator.cc +++ b/ui/gfx/compositor/layer_animator.cc @@ -53,46 +53,37 @@ LayerAnimator* LayerAnimator::CreateImplicitAnimator() { } void LayerAnimator::SetTransform(const Transform& transform) { - if (transition_duration_ == base::TimeDelta()) - delegate_->SetTransformFromAnimation(transform); - else - StartAnimation(new LayerAnimationSequence( - LayerAnimationElement::CreateTransformElement( - transform, transition_duration_))); + StartAnimation(new LayerAnimationSequence( + LayerAnimationElement::CreateTransformElement( + transform, transition_duration_))); } Transform LayerAnimator::GetTargetTransform() const { - LayerAnimationElement::TargetValue target; + LayerAnimationElement::TargetValue target(delegate()); GetTargetValue(&target); return target.transform; } void LayerAnimator::SetBounds(const gfx::Rect& bounds) { - if (transition_duration_ == base::TimeDelta()) - delegate_->SetBoundsFromAnimation(bounds); - else - StartAnimation(new LayerAnimationSequence( - LayerAnimationElement::CreateBoundsElement( - bounds, transition_duration_))); + StartAnimation(new LayerAnimationSequence( + LayerAnimationElement::CreateBoundsElement( + bounds, transition_duration_))); } gfx::Rect LayerAnimator::GetTargetBounds() const { - LayerAnimationElement::TargetValue target; + LayerAnimationElement::TargetValue target(delegate()); GetTargetValue(&target); return target.bounds; } void LayerAnimator::SetOpacity(float opacity) { - if (transition_duration_ == base::TimeDelta()) - delegate_->SetOpacityFromAnimation(opacity); - else - StartAnimation(new LayerAnimationSequence( - LayerAnimationElement::CreateOpacityElement( - opacity, transition_duration_))); + StartAnimation(new LayerAnimationSequence( + LayerAnimationElement::CreateOpacityElement( + opacity, transition_duration_))); } float LayerAnimator::GetTargetOpacity() const { - LayerAnimationElement::TargetValue target; + LayerAnimationElement::TargetValue target(delegate()); GetTargetValue(&target); return target.opacity; } @@ -232,24 +223,23 @@ void LayerAnimator::ScopedSettings::SetTransitionDuration( void LayerAnimator::Step(base::TimeTicks now) { last_step_time_ = now; - std::vector<LayerAnimationSequence*> to_finish; - for (RunningAnimations::iterator iter = running_animations_.begin(); - iter != running_animations_.end(); ++iter) { - base::TimeDelta delta = now - (*iter).start_time; - if (delta >= (*iter).sequence->duration() && - !(*iter).sequence->is_cyclic()) { - to_finish.push_back((*iter).sequence); + // We need to make a copy of the running animations because progressing them + // and finishing them may indirectly affect the collection of running + // animations. + RunningAnimations running_animations_copy = running_animations_; + for (size_t i = 0; i < running_animations_copy.size(); ++i) { + base::TimeDelta delta = now - running_animations_copy[i].start_time; + if (delta >= running_animations_copy[i].sequence->duration() && + !running_animations_copy[i].sequence->is_cyclic()) { + FinishAnimation(running_animations_copy[i].sequence); } else { - (*iter).sequence->Progress(delta, delegate()); + running_animations_copy[i].sequence->Progress(delta, delegate()); } } - for (std::vector<LayerAnimationSequence*>::iterator iter = to_finish.begin(); - iter != to_finish.end(); ++iter) { - FinishAnimation(*iter); - } } void LayerAnimator::SetStartTime(base::TimeTicks start_time) { + // Do nothing. } base::TimeDelta LayerAnimator::GetTimerInterval() const { @@ -275,8 +265,11 @@ void LayerAnimator::UpdateAnimationState() { is_started_ = should_start; } -void LayerAnimator::RemoveAnimation(LayerAnimationSequence* sequence) { - // First remove from running animations +LayerAnimationSequence* LayerAnimator::RemoveAnimation( + LayerAnimationSequence* sequence) { + linked_ptr<LayerAnimationSequence> to_return; + + // First remove from running animations for (RunningAnimations::iterator iter = running_animations_.begin(); iter != running_animations_.end(); ++iter) { if ((*iter).sequence == sequence) { @@ -289,32 +282,32 @@ void LayerAnimator::RemoveAnimation(LayerAnimationSequence* sequence) { for (AnimationQueue::iterator queue_iter = animation_queue_.begin(); queue_iter != animation_queue_.end(); ++queue_iter) { if ((*queue_iter) == sequence) { + to_return = *queue_iter; animation_queue_.erase(queue_iter); break; } } + + return to_return.release(); } void LayerAnimator::FinishAnimation(LayerAnimationSequence* sequence) { + scoped_ptr<LayerAnimationSequence> removed(RemoveAnimation(sequence)); sequence->Progress(sequence->duration(), delegate()); - RemoveAnimation(sequence); ProcessQueue(); UpdateAnimationState(); } void LayerAnimator::FinishAnyAnimationWithZeroDuration() { - // Special case: if we've started a 0 duration animation, just finish it now - // and get rid of it. Note at each iteration of the loop, we either increment - // i or remove an element from running_animations_, so - // running_animations_.size() - i is always decreasing and we are always - // progressing towards the termination of the loop. - for (size_t i = 0; i < running_animations_.size();) { - if (running_animations_[i].sequence->duration() == base::TimeDelta()) { - running_animations_[i].sequence->Progress( - running_animations_[i].sequence->duration(), delegate()); - RemoveAnimation(running_animations_[i].sequence); - } else { - ++i; + // We need to make a copy because Progress may indirectly cause new animations + // to start running. + RunningAnimations running_animations_copy = running_animations_; + for (size_t i = 0; i < running_animations_copy.size(); ++i) { + if (running_animations_copy[i].sequence->duration() == base::TimeDelta()) { + running_animations_copy[i].sequence->Progress( + running_animations_copy[i].sequence->duration(), delegate()); + scoped_ptr<LayerAnimationSequence> removed( + RemoveAnimation(running_animations_copy[i].sequence)); } } ProcessQueue(); @@ -322,10 +315,17 @@ void LayerAnimator::FinishAnyAnimationWithZeroDuration() { } void LayerAnimator::ClearAnimations() { - for (RunningAnimations::iterator iter = running_animations_.begin(); - iter != running_animations_.end(); ++iter) { - (*iter).sequence->Abort(); + // Abort should never affect the set of running animations, but just in case + // clients are badly behaved, we will use a copy of the running animations. + RunningAnimations running_animations_copy = running_animations_; + for (size_t i = 0; i < running_animations_copy.size(); ++i) { + scoped_ptr<LayerAnimationSequence> removed( + RemoveAnimation(running_animations_copy[i].sequence)); + if (removed.get()) + removed->Abort(); } + // This *should* have cleared the list of running animations. + DCHECK(running_animations_.empty()); running_animations_.clear(); animation_queue_.clear(); UpdateAnimationState(); @@ -358,41 +358,40 @@ void LayerAnimator::AddToQueueIfNotPresent(LayerAnimationSequence* animation) { } void LayerAnimator::RemoveAllAnimationsWithACommonProperty( - LayerAnimationSequence* sequence, - bool abort) { + LayerAnimationSequence* sequence, bool abort) { // For all the running animations, if they animate the same property, - // progress them to the end and remove them. Note: at each iteration i is - // incremented or an element is removed from the queue, so - // animation_queue_.size() - i is always decreasing and we are always making - // progress towards the loop terminating. - for (size_t i = 0; i < running_animations_.size();) { - if (running_animations_[i].sequence->HasCommonProperty( + // progress them to the end and remove them. Note, Aborting or Progressing + // animations may affect the collection of running animations, so we need to + // operate on a copy. + RunningAnimations running_animations_copy = running_animations_; + for (size_t i = 0; i < running_animations_copy.size(); ++i) { + if (running_animations_copy[i].sequence->HasCommonProperty( sequence->properties())) { - // Finish the animation. - if (abort){ - running_animations_[i].sequence->Abort(); - } else { - running_animations_[i].sequence->Progress( - running_animations_[i].sequence->duration(), delegate()); - } - RemoveAnimation(running_animations_[i].sequence); - } else { - ++i; + scoped_ptr<LayerAnimationSequence> removed( + RemoveAnimation(running_animations_copy[i].sequence)); + if (abort) + running_animations_copy[i].sequence->Abort(); + else + running_animations_copy[i].sequence->Progress( + running_animations_copy[i].sequence->duration(), delegate()); } } - // Same for the queued animations. See comment above about loop termination. - for (size_t i = 0; i < animation_queue_.size();) { - if (animation_queue_[i]->HasCommonProperty(sequence->properties())) { - // Finish the animation. + // Same for the queued animations that haven't been started. Again, we'll + // need to operate on a copy. + std::vector<LayerAnimationSequence*> sequences; + for (AnimationQueue::iterator queue_iter = animation_queue_.begin(); + queue_iter != animation_queue_.end(); ++queue_iter) + sequences.push_back((*queue_iter).get()); + + for (size_t i = 0; i < sequences.size(); ++i) { + if (sequences[i]->HasCommonProperty(sequence->properties())) { + scoped_ptr<LayerAnimationSequence> removed( + RemoveAnimation(sequences[i])); if (abort) - animation_queue_[i]->Abort(); + sequences[i]->Abort(); else - animation_queue_[i]->Progress(animation_queue_[i]->duration(), - delegate()); - RemoveAnimation(animation_queue_[i].get()); - } else { - ++i; + sequences[i]->Progress(sequences[i]->duration(), delegate()); } } } @@ -400,8 +399,8 @@ void LayerAnimator::RemoveAllAnimationsWithACommonProperty( void LayerAnimator::ImmediatelySetNewTarget(LayerAnimationSequence* sequence) { const bool abort = false; RemoveAllAnimationsWithACommonProperty(sequence, abort); + scoped_ptr<LayerAnimationSequence> removed(RemoveAnimation(sequence)); sequence->Progress(sequence->duration(), delegate()); - RemoveAnimation(sequence); } void LayerAnimator::ImmediatelyAnimateToNewTarget( @@ -435,7 +434,8 @@ void LayerAnimator::ReplaceQueuedAnimations(LayerAnimationSequence* sequence) { } } if (!is_running) - RemoveAnimation(animation_queue_[i].get()); + scoped_ptr<LayerAnimationSequence>( + RemoveAnimation(animation_queue_[i].get())); else ++i; } @@ -456,11 +456,17 @@ void LayerAnimator::ProcessQueue() { } // Try to find an animation that doesn't conflict with an animated - // property or a property that will be animated before it. + // property or a property that will be animated before it. Note: starting + // the animation may indirectly cause more animations to be started, so we + // need to operate on a copy. + std::vector<LayerAnimationSequence*> sequences; for (AnimationQueue::iterator queue_iter = animation_queue_.begin(); - queue_iter != animation_queue_.end(); ++queue_iter) { - if (!(*queue_iter)->HasCommonProperty(animated)) { - StartSequenceImmediately((*queue_iter).get()); + queue_iter != animation_queue_.end(); ++queue_iter) + sequences.push_back((*queue_iter).get()); + + for (size_t i = 0; i < sequences.size(); ++i) { + if (!sequences[i]->HasCommonProperty(animated)) { + StartSequenceImmediately(sequences[i]); started_sequence = true; break; } @@ -473,8 +479,8 @@ void LayerAnimator::ProcessQueue() { // the first element because it animates the transform, too. We cannot // start the second element, either, because the first element animates // bounds too, and needs to go first. - animated.insert((*queue_iter)->properties().begin(), - (*queue_iter)->properties().end()); + animated.insert(sequences[i]->properties().begin(), + sequences[i]->properties().end()); } // If we started a sequence, try again. We may be able to start several. diff --git a/ui/gfx/compositor/layer_animator.h b/ui/gfx/compositor/layer_animator.h index c7286b5..4b7de40 100644 --- a/ui/gfx/compositor/layer_animator.h +++ b/ui/gfx/compositor/layer_animator.h @@ -10,6 +10,7 @@ #include <set> #include <vector> +#include "base/compiler_specific.h" #include "base/memory/linked_ptr.h" #include "base/memory/scoped_ptr.h" #include "base/observer_list.h" @@ -140,6 +141,7 @@ class COMPOSITOR_EXPORT LayerAnimator : public AnimationContainerElement { protected: LayerAnimationDelegate* delegate() { return delegate_; } + const LayerAnimationDelegate* delegate() const { return delegate_; } private: friend class ScopedSettings; @@ -167,7 +169,10 @@ class COMPOSITOR_EXPORT LayerAnimator : public AnimationContainerElement { void UpdateAnimationState(); // Removes the sequences from both the running animations and the queue. - void RemoveAnimation(LayerAnimationSequence* sequence); + // Returns a pointer to the removed animation, if any. NOTE: the caller is + // responsible for deleting the returned pointer. + LayerAnimationSequence* RemoveAnimation( + LayerAnimationSequence* sequence) WARN_UNUSED_RESULT; // Progresses to the end of the sequence before removing it. void FinishAnimation(LayerAnimationSequence* sequence); diff --git a/ui/gfx/compositor/layer_animator_unittest.cc b/ui/gfx/compositor/layer_animator_unittest.cc index 7d957cf..762a3b2 100644 --- a/ui/gfx/compositor/layer_animator_unittest.cc +++ b/ui/gfx/compositor/layer_animator_unittest.cc @@ -692,12 +692,12 @@ TEST(LayerAnimatorTest, AddObserverImplicit) { animator->SetDelegate(&delegate); animator->AddObserver(&observer); - // Should not end a sequence with the default animator. + // Should end a sequence with the default animator. EXPECT_TRUE(!observer.last_ended_sequence()); animator->SetOpacity(1.0f); base::TimeTicks start_time = base::TimeTicks::Now(); element->Step(start_time + base::TimeDelta::FromMilliseconds(1000)); - EXPECT_TRUE(!observer.last_ended_sequence()); + EXPECT_TRUE(observer.last_ended_sequence()); TestLayerAnimationObserver scoped_observer; { @@ -722,6 +722,33 @@ TEST(LayerAnimatorTest, AddObserverImplicit) { EXPECT_TRUE(!scoped_observer.last_ended_sequence()); } +// Check that setting a property during an animation with a default animator +// cancels the original animation. +TEST(LayerAnimatorTest, SettingPropertyDuringAnAnimation) { + scoped_ptr<LayerAnimator> animator(LayerAnimator::CreateDefaultAnimator()); + animator->set_disable_timer_for_test(true); + TestLayerAnimationDelegate delegate; + animator->SetDelegate(&delegate); + + double start_opacity(0.0); + double target_opacity(1.0); + + base::TimeDelta delta = base::TimeDelta::FromSeconds(1); + + delegate.SetOpacityFromAnimation(start_opacity); + + scoped_ptr<LayerAnimationSequence> sequence( + new LayerAnimationSequence( + LayerAnimationElement::CreateOpacityElement(target_opacity, delta))); + + animator->StartAnimation(sequence.release()); + + animator->SetOpacity(0.5); + + EXPECT_FALSE(animator->is_animating()); + EXPECT_EQ(0.5, animator->GetTargetOpacity()); +} + } // namespace } // namespace ui diff --git a/ui/gfx/compositor/layer_unittest.cc b/ui/gfx/compositor/layer_unittest.cc index 2308cd0..8d269c4 100644 --- a/ui/gfx/compositor/layer_unittest.cc +++ b/ui/gfx/compositor/layer_unittest.cc @@ -597,6 +597,8 @@ TEST_F(LayerWithNullDelegateTest, HoleWithNinetyDegreeTransforms) { EXPECT_TRUE(!parent->hole_rect().IsEmpty()); for (int i = -4; i <= 4; ++i) { + SCOPED_TRACE(::testing::Message() << "Iteration " << i); + ui::Transform t; // Need to rotate in local coordinates. t.SetTranslate(-25, -25); |