| 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 |