Revert of Fix missing GN dependencies. (patchset #4 id:60001 of https://codereview...
[chromium-blink-merge.git] / ui / gfx / paint_throbber.cc
blobdfa9677f29b7a3db8434ecdb24c5d5c8853d84d3
1 // Copyright (c) 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ui/gfx/paint_throbber.h"
7 #include "base/time/time.h"
8 #include "ui/gfx/animation/tween.h"
9 #include "ui/gfx/canvas.h"
10 #include "ui/gfx/geometry/rect.h"
11 #include "ui/gfx/skia_util.h"
13 namespace gfx {
15 namespace {
17 void PaintArc(Canvas* canvas,
18 const Rect& bounds,
19 SkColor color,
20 SkScalar start_angle,
21 SkScalar sweep) {
22 // Stroke width depends on size.
23 // . For size < 28: 3 - (28 - size) / 16
24 // . For 28 <= size: (8 + size) / 12
25 SkScalar stroke_width = bounds.width() < 28
26 ? 3.0 - SkIntToScalar(28 - bounds.width()) / 16.0
27 : SkIntToScalar(bounds.width() + 8) / 12.0;
28 Rect oval = bounds;
29 // Inset by half the stroke width to make sure the whole arc is inside
30 // the visible rect.
31 int inset = SkScalarCeilToInt(stroke_width / 2.0);
32 oval.Inset(inset, inset);
34 SkPath path;
35 path.arcTo(RectToSkRect(oval), start_angle, sweep, true);
37 SkPaint paint;
38 paint.setColor(color);
39 paint.setStrokeCap(SkPaint::kRound_Cap);
40 paint.setStrokeWidth(stroke_width);
41 paint.setStyle(SkPaint::kStroke_Style);
42 paint.setAntiAlias(true);
43 canvas->DrawPath(path, paint);
46 } // namespace
48 void PaintThrobberSpinning(Canvas* canvas,
49 const Rect& bounds, SkColor color, const base::TimeDelta& elapsed_time) {
50 // This is a Skia port of the MD spinner SVG. The |start_angle| rotation
51 // here corresponds to the 'rotate' animation.
52 base::TimeDelta rotation_time = base::TimeDelta::FromMilliseconds(1568);
53 int64_t start_angle = 270 + 360 * elapsed_time / rotation_time;
55 // The sweep angle ranges from -|arc_size| to |arc_size| over 1333ms. CSS
56 // animation timing functions apply in between key frames, so we have to
57 // break up the |arc_time| into two keyframes (-arc_size to 0, then 0 to
58 // arc_size).
59 int64_t arc_size = 270;
60 base::TimeDelta arc_time = base::TimeDelta::FromMilliseconds(666);
61 double arc_size_progress = static_cast<double>(elapsed_time.InMicroseconds() %
62 arc_time.InMicroseconds()) /
63 arc_time.InMicroseconds();
64 // This tween is equivalent to cubic-bezier(0.4, 0.0, 0.2, 1).
65 double sweep =
66 arc_size * Tween::CalculateValue(Tween::FAST_OUT_SLOW_IN,
67 arc_size_progress);
68 int64_t sweep_keyframe = (elapsed_time / arc_time) % 2;
69 if (sweep_keyframe == 0)
70 sweep -= arc_size;
72 // This part makes sure the sweep is at least 5 degrees long. Roughly
73 // equivalent to the "magic constants" in SVG's fillunfill animation.
74 const double min_sweep_length = 5.0;
75 if (sweep >= 0.0 && sweep < min_sweep_length) {
76 start_angle -= (min_sweep_length - sweep);
77 sweep = min_sweep_length;
78 } else if (sweep <= 0.0 && sweep > -min_sweep_length) {
79 start_angle += (-min_sweep_length - sweep);
80 sweep = -min_sweep_length;
83 // To keep the sweep smooth, we have an additional rotation after each
84 // |arc_time| period has elapsed. See SVG's 'rot' animation.
85 int64_t rot_keyframe = (elapsed_time / (arc_time * 2)) % 4;
86 PaintArc(canvas, bounds, color,
87 start_angle + rot_keyframe * arc_size, sweep);
90 void PaintThrobberSpinningForFrame(Canvas* canvas,
91 const Rect& bounds, SkColor color, uint32_t frame) {
92 const uint32_t frame_duration_ms = 30;
93 PaintThrobberSpinning(canvas, bounds, color,
94 base::TimeDelta::FromMilliseconds(frame * frame_duration_ms));
97 void PaintThrobberWaiting(Canvas* canvas,
98 const Rect& bounds, SkColor color, const base::TimeDelta& elapsed_time) {
99 // Calculate start and end points. The angles are counter-clockwise because
100 // the throbber spins counter-clockwise. The finish angle starts at 12 o'clock
101 // (90 degrees) and rotates steadily. The start angle trails 180 degrees
102 // behind, except for the first half revolution, when it stays at 12 o'clock.
103 base::TimeDelta revolution_time = base::TimeDelta::FromMilliseconds(1320);
104 int64_t twelve_oclock = 90;
105 int64_t finish_angle = twelve_oclock + 360 * elapsed_time / revolution_time;
106 int64_t start_angle = std::max(finish_angle - 180, twelve_oclock);
108 // Negate the angles to convert to the clockwise numbers Skia expects.
109 PaintArc(canvas, bounds, color, -start_angle, -(finish_angle - start_angle));
112 void PaintThrobberWaitingForFrame(Canvas* canvas,
113 const Rect& bounds, SkColor color, uint32_t frame) {
114 const uint32_t frame_duration_ms = 30;
115 PaintThrobberWaiting(canvas, bounds, color,
116 base::TimeDelta::FromMilliseconds(frame * frame_duration_ms));
119 } // namespace gfx