File: progress_ring_pulse_animation.cc

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (107 lines) | stat: -rw-r--r-- 4,233 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
// Copyright 2021 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "ash/system/progress_indicator/progress_ring_pulse_animation.h"

#include <array>

#include "base/dcheck_is_on.h"
#include "base/notreached.h"
#include "ui/compositor/scoped_animation_duration_scale_mode.h"
#include "ui/gfx/animation/tween.h"

namespace ash {
namespace {

// Animation -------------------------------------------------------------------

constexpr float kAnimationDurationInMs = 2331.f;

// Models a single key frame in the animation.
struct AnimationKeyFrame {
  float fraction = 0.f;
  float opacity = 0.f;
};

// The collection of all key frames in the animation.
constexpr std::array<AnimationKeyFrame, 10> kAnimationKeyFrames = {{
    {.fraction = 0.f, .opacity = 1.f},                              // Start.
    {.fraction = 333.f / kAnimationDurationInMs, .opacity = 0.f},   // Fade out.
    {.fraction = 433.f / kAnimationDurationInMs, .opacity = 0.f},   // Hold.
    {.fraction = 766.f / kAnimationDurationInMs, .opacity = 1.f},   // Fade in.
    {.fraction = 999.f / kAnimationDurationInMs, .opacity = 1.f},   // Hold.
    {.fraction = 1332.f / kAnimationDurationInMs, .opacity = 0.f},  // Fade out.
    {.fraction = 1432.f / kAnimationDurationInMs, .opacity = 0.f},  // Hold.
    {.fraction = 1765.f / kAnimationDurationInMs, .opacity = 1.f},  // Fade in.
    {.fraction = 1998.f / kAnimationDurationInMs, .opacity = 1.f},  // Hold.
    {.fraction = 1.f, .opacity = 0.f}                               // Fade out.
}};

}  // namespace

// ProgressRingPulseAnimation --------------------------------------------------

ProgressRingPulseAnimation::ProgressRingPulseAnimation()
    : ProgressRingAnimation(Type::kPulse,
                            base::Milliseconds(kAnimationDurationInMs),
                            /*is_cyclic=*/false) {
#if DCHECK_IS_ON()
  constexpr size_t kAnimationKeyFramesCount = std::size(kAnimationKeyFrames);
  DCHECK_GE(kAnimationKeyFramesCount, 2u);
  for (size_t i = 0u; i < kAnimationKeyFramesCount; ++i) {
    if (i == 0u) {
      // The first animation key frame should be at `0.f`.
      DCHECK_EQ(kAnimationKeyFrames[i].fraction, 0.f);
    } else if (i == kAnimationKeyFramesCount - 1u) {
      // The last animation key frame should be at `1.f`.
      DCHECK_EQ(kAnimationKeyFrames[i].fraction, 1.f);
    } else {
      // Animation key frames should appear in sorted order.
      DCHECK_GT(kAnimationKeyFrames[i].fraction, 0.f);
      DCHECK_LT(kAnimationKeyFrames[i].fraction, 1.f);
      DCHECK_GT(kAnimationKeyFrames[i].fraction,
                kAnimationKeyFrames[i - 1u].fraction);
    }
  }
#endif  // DCHECK_IS_ON()
}

ProgressRingPulseAnimation::~ProgressRingPulseAnimation() = default;

void ProgressRingPulseAnimation::UpdateAnimatableProperties(
    double fraction,
    float* start_position,
    float* end_position,
    float* outer_ring_opacity) {
  *end_position = 1.f;

  // Loop over all animation key frames until the correct key frames for the
  // current animation `fraction` are found.
  for (size_t i = 1u; i < std::size(kAnimationKeyFrames); ++i) {
    if (fraction > kAnimationKeyFrames[i].fraction)
      continue;

    const AnimationKeyFrame& previous_key_frame = kAnimationKeyFrames[i - 1u];
    const AnimationKeyFrame& target_key_frame = kAnimationKeyFrames[i];

    // Update `fraction` so that it is still within the range [0, 1], but with
    // respect to the `previous_key_frame` and `target_key_frame`, instead of
    // with respect to the entire animation.
    fraction = (fraction - previous_key_frame.fraction) /
               (target_key_frame.fraction - previous_key_frame.fraction);

    // Interpolate `outer_ring_opacity` between the `previous_key_frame` and
    // `target_key_frame`.
    *outer_ring_opacity = gfx::Tween::FloatValueBetween(
        fraction, /*start_opacity=*/previous_key_frame.opacity,
        /*target_opacity=*/target_key_frame.opacity);
    return;
  }

  // This LOC should never be reached as the correct key frames for the current
  // animation `fraction` should have been found in the loop above.
  NOTREACHED();
}

}  // namespace ash