OLD | NEW |
1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "ui/gfx/paint_throbber.h" | 5 #include "ui/gfx/paint_throbber.h" |
6 | 6 |
7 #include "base/time/time.h" | 7 #include "base/time/time.h" |
8 #include "third_party/skia/include/core/SkPath.h" | 8 #include "third_party/skia/include/core/SkPath.h" |
9 #include "ui/gfx/animation/tween.h" | 9 #include "ui/gfx/animation/tween.h" |
10 #include "ui/gfx/canvas.h" | 10 #include "ui/gfx/canvas.h" |
11 #include "ui/gfx/color_utils.h" | 11 #include "ui/gfx/color_utils.h" |
12 #include "ui/gfx/geometry/rect.h" | 12 #include "ui/gfx/geometry/rect.h" |
13 #include "ui/gfx/skia_util.h" | 13 #include "ui/gfx/skia_util.h" |
14 | 14 |
15 namespace gfx { | 15 namespace gfx { |
16 | 16 |
17 namespace { | 17 namespace { |
18 | 18 |
19 // The maximum size of the "spinning" state arc, in degrees. | 19 // The maximum size of the "spinning" state arc, in degrees. |
20 const int64_t kMaxArcSize = 270; | 20 const int64_t kMaxArcSize = 270; |
21 | 21 |
22 // The amount of time it takes to grow the "spinning" arc from 0 to 270 degrees. | 22 // The amount of time it takes to grow the "spinning" arc from 0 to 270 degrees. |
23 const int64_t kArcTimeMs = 666; | 23 const int64_t kArcTimeMs = 666; |
24 | 24 |
25 // The amount of time it takes for the "spinning" throbber to make a full | 25 // The amount of time it takes for the "spinning" throbber to make a full |
26 // rotation. | 26 // rotation. |
27 const int64_t kRotationTimeMs = 1568; | 27 const int64_t kRotationTimeMs = 1568; |
28 | 28 |
29 void PaintArc(Canvas* canvas, | |
30 const Rect& bounds, | |
31 SkColor color, | |
32 SkScalar start_angle, | |
33 SkScalar sweep) { | |
34 // Stroke width depends on size. | |
35 // . For size < 28: 3 - (28 - size) / 16 | |
36 // . For 28 <= size: (8 + size) / 12 | |
37 SkScalar stroke_width = bounds.width() < 28 | |
38 ? 3.0 - SkIntToScalar(28 - bounds.width()) / 16.0 | |
39 : SkIntToScalar(bounds.width() + 8) / 12.0; | |
40 Rect oval = bounds; | |
41 // Inset by half the stroke width to make sure the whole arc is inside | |
42 // the visible rect. | |
43 int inset = SkScalarCeilToInt(stroke_width / 2.0); | |
44 oval.Inset(inset, inset); | |
45 | |
46 SkPath path; | |
47 path.arcTo(RectToSkRect(oval), start_angle, sweep, true); | |
48 | |
49 SkPaint paint; | |
50 paint.setColor(color); | |
51 paint.setStrokeCap(SkPaint::kRound_Cap); | |
52 paint.setStrokeWidth(stroke_width); | |
53 paint.setStyle(SkPaint::kStroke_Style); | |
54 paint.setAntiAlias(true); | |
55 canvas->DrawPath(path, paint); | |
56 } | |
57 | |
58 void CalculateWaitingAngles(const base::TimeDelta& elapsed_time, | 29 void CalculateWaitingAngles(const base::TimeDelta& elapsed_time, |
59 int64_t* start_angle, | 30 int64_t* start_angle, |
60 int64_t* sweep) { | 31 int64_t* sweep) { |
61 // Calculate start and end points. The angles are counter-clockwise because | 32 // Calculate start and end points. The angles are counter-clockwise because |
62 // the throbber spins counter-clockwise. The finish angle starts at 12 o'clock | 33 // the throbber spins counter-clockwise. The finish angle starts at 12 o'clock |
63 // (90 degrees) and rotates steadily. The start angle trails 180 degrees | 34 // (90 degrees) and rotates steadily. The start angle trails 180 degrees |
64 // behind, except for the first half revolution, when it stays at 12 o'clock. | 35 // behind, except for the first half revolution, when it stays at 12 o'clock. |
65 base::TimeDelta revolution_time = base::TimeDelta::FromMilliseconds(1320); | 36 base::TimeDelta revolution_time = base::TimeDelta::FromMilliseconds(1320); |
66 int64_t twelve_oclock = 90; | 37 int64_t twelve_oclock = 90; |
67 int64_t finish_angle_cc = | 38 int64_t finish_angle_cc = |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
103 start_angle -= (min_sweep_length - sweep); | 74 start_angle -= (min_sweep_length - sweep); |
104 sweep = min_sweep_length; | 75 sweep = min_sweep_length; |
105 } else if (sweep <= 0.0 && sweep > -min_sweep_length) { | 76 } else if (sweep <= 0.0 && sweep > -min_sweep_length) { |
106 start_angle += (-min_sweep_length - sweep); | 77 start_angle += (-min_sweep_length - sweep); |
107 sweep = -min_sweep_length; | 78 sweep = -min_sweep_length; |
108 } | 79 } |
109 | 80 |
110 // To keep the sweep smooth, we have an additional rotation after each | 81 // To keep the sweep smooth, we have an additional rotation after each |
111 // |arc_time| period has elapsed. See SVG's 'rot' animation. | 82 // |arc_time| period has elapsed. See SVG's 'rot' animation. |
112 int64_t rot_keyframe = (elapsed_time / (arc_time * 2)) % 4; | 83 int64_t rot_keyframe = (elapsed_time / (arc_time * 2)) % 4; |
113 PaintArc(canvas, bounds, color, start_angle + rot_keyframe * kMaxArcSize, | 84 PaintThrobberArc(canvas, bounds, color, |
114 sweep); | 85 start_angle + rot_keyframe * kMaxArcSize, sweep); |
115 } | 86 } |
116 | 87 |
117 } // namespace | 88 } // namespace |
118 | 89 |
| 90 void PaintThrobberArc(Canvas* canvas, |
| 91 const Rect& bounds, |
| 92 SkColor color, |
| 93 SkScalar start_angle, |
| 94 SkScalar sweep) { |
| 95 // Stroke width depends on size. |
| 96 // . For size < 28: 3 - (28 - size) / 16 |
| 97 // . For 28 <= size: (8 + size) / 12 |
| 98 SkScalar stroke_width = bounds.width() < 28 |
| 99 ? 3.0 - SkIntToScalar(28 - bounds.width()) / 16.0 |
| 100 : SkIntToScalar(bounds.width() + 8) / 12.0; |
| 101 Rect oval = bounds; |
| 102 // Inset by half the stroke width to make sure the whole arc is inside |
| 103 // the visible rect. |
| 104 int inset = SkScalarCeilToInt(stroke_width / 2.0); |
| 105 oval.Inset(inset, inset); |
| 106 |
| 107 SkPath path; |
| 108 path.arcTo(RectToSkRect(oval), start_angle, sweep, true); |
| 109 |
| 110 SkPaint paint; |
| 111 paint.setColor(color); |
| 112 paint.setStrokeCap(SkPaint::kRound_Cap); |
| 113 paint.setStrokeWidth(stroke_width); |
| 114 paint.setStyle(SkPaint::kStroke_Style); |
| 115 paint.setAntiAlias(true); |
| 116 canvas->DrawPath(path, paint); |
| 117 } |
| 118 |
119 void PaintThrobberSpinning(Canvas* canvas, | 119 void PaintThrobberSpinning(Canvas* canvas, |
120 const Rect& bounds, | 120 const Rect& bounds, |
121 SkColor color, | 121 SkColor color, |
122 const base::TimeDelta& elapsed_time) { | 122 const base::TimeDelta& elapsed_time) { |
123 base::TimeDelta rotation_time = | 123 base::TimeDelta rotation_time = |
124 base::TimeDelta::FromMilliseconds(kRotationTimeMs); | 124 base::TimeDelta::FromMilliseconds(kRotationTimeMs); |
125 int64_t start_angle = 270 + 360 * elapsed_time / rotation_time; | 125 int64_t start_angle = 270 + 360 * elapsed_time / rotation_time; |
126 PaintThrobberSpinningWithStartAngle(canvas, bounds, color, elapsed_time, | 126 PaintThrobberSpinningWithStartAngle(canvas, bounds, color, elapsed_time, |
127 start_angle); | 127 start_angle); |
128 } | 128 } |
129 | 129 |
130 void PaintThrobberWaiting(Canvas* canvas, | 130 void PaintThrobberWaiting(Canvas* canvas, |
131 const Rect& bounds, SkColor color, const base::TimeDelta& elapsed_time) { | 131 const Rect& bounds, SkColor color, const base::TimeDelta& elapsed_time) { |
132 int64_t start_angle = 0, sweep = 0; | 132 int64_t start_angle = 0, sweep = 0; |
133 CalculateWaitingAngles(elapsed_time, &start_angle, &sweep); | 133 CalculateWaitingAngles(elapsed_time, &start_angle, &sweep); |
134 PaintArc(canvas, bounds, color, start_angle, sweep); | 134 PaintThrobberArc(canvas, bounds, color, start_angle, sweep); |
135 } | 135 } |
136 | 136 |
137 void PaintThrobberSpinningAfterWaiting(Canvas* canvas, | 137 void PaintThrobberSpinningAfterWaiting(Canvas* canvas, |
138 const Rect& bounds, | 138 const Rect& bounds, |
139 SkColor color, | 139 SkColor color, |
140 const base::TimeDelta& elapsed_time, | 140 const base::TimeDelta& elapsed_time, |
141 ThrobberWaitingState* waiting_state) { | 141 ThrobberWaitingState* waiting_state) { |
142 int64_t waiting_start_angle = 0, waiting_sweep = 0; | 142 int64_t waiting_start_angle = 0, waiting_sweep = 0; |
143 CalculateWaitingAngles(waiting_state->elapsed_time, &waiting_start_angle, | 143 CalculateWaitingAngles(waiting_state->elapsed_time, &waiting_start_angle, |
144 &waiting_sweep); | 144 &waiting_sweep); |
(...skipping 30 matching lines...) Expand all Loading... |
175 waiting_start_angle + | 175 waiting_start_angle + |
176 360 * elapsed_time / base::TimeDelta::FromMilliseconds(kRotationTimeMs); | 176 360 * elapsed_time / base::TimeDelta::FromMilliseconds(kRotationTimeMs); |
177 base::TimeDelta effective_elapsed_time = | 177 base::TimeDelta effective_elapsed_time = |
178 elapsed_time + waiting_state->arc_time_offset; | 178 elapsed_time + waiting_state->arc_time_offset; |
179 | 179 |
180 PaintThrobberSpinningWithStartAngle(canvas, bounds, blend_color, | 180 PaintThrobberSpinningWithStartAngle(canvas, bounds, blend_color, |
181 effective_elapsed_time, start_angle); | 181 effective_elapsed_time, start_angle); |
182 } | 182 } |
183 | 183 |
184 } // namespace gfx | 184 } // namespace gfx |
OLD | NEW |