highlighter_result_view.cc 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. // Copyright 2017 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.
  4. #include "ash/highlighter/highlighter_result_view.h"
  5. #include <memory>
  6. #include "ash/highlighter/highlighter_gesture_util.h"
  7. #include "ash/highlighter/highlighter_view.h"
  8. #include "ash/public/cpp/shell_window_ids.h"
  9. #include "ash/shell.h"
  10. #include "base/bind.h"
  11. #include "base/timer/timer.h"
  12. #include "ui/compositor/layer.h"
  13. #include "ui/compositor/paint_recorder.h"
  14. #include "ui/compositor/scoped_layer_animation_settings.h"
  15. #include "ui/gfx/geometry/rect_conversions.h"
  16. #include "ui/views/widget/widget.h"
  17. namespace ash {
  18. namespace {
  19. // Variables for rendering the highlight result. Sizes in DIP.
  20. constexpr float kCornerCircleRadius = 6;
  21. constexpr float kStrokeFillWidth = 2;
  22. constexpr float kStrokeOutlineWidth = 1;
  23. constexpr float kOutsetForAntialiasing = 1;
  24. constexpr float kResultLayerMargin =
  25. kOutsetForAntialiasing + kCornerCircleRadius;
  26. constexpr int kInnerFillOpacity = 0x0D;
  27. const SkColor kInnerFillColor = SkColorSetRGB(0x00, 0x00, 0x00);
  28. constexpr int kStrokeFillOpacity = 0xFF;
  29. const SkColor kStrokeFillColor = SkColorSetRGB(0xFF, 0xFF, 0xFF);
  30. constexpr int kStrokeOutlineOpacity = 0x14;
  31. const SkColor kStrokeOutlineColor = SkColorSetRGB(0x00, 0x00, 0x00);
  32. constexpr int kCornerCircleOpacity = 0xFF;
  33. const SkColor kCornerCircleColorLT = SkColorSetRGB(0x42, 0x85, 0xF4);
  34. const SkColor kCornerCircleColorRT = SkColorSetRGB(0xEA, 0x43, 0x35);
  35. const SkColor kCornerCircleColorLB = SkColorSetRGB(0x34, 0xA8, 0x53);
  36. const SkColor kCornerCircleColorRB = SkColorSetRGB(0xFB, 0xBC, 0x05);
  37. constexpr int kResultFadeinDelayMs = 200;
  38. constexpr int kResultFadeinDurationMs = 400;
  39. constexpr int kResultFadeoutDelayMs = 500;
  40. constexpr int kResultFadeoutDurationMs = 200;
  41. constexpr int kResultInPlaceFadeinDelayMs = 100;
  42. constexpr int kResultInPlaceFadeinDurationMs = 500;
  43. constexpr float kInitialScale = 1.2;
  44. class ResultLayer : public ui::Layer, public ui::LayerDelegate {
  45. public:
  46. ResultLayer(const gfx::Rect& bounds);
  47. ResultLayer(const ResultLayer&) = delete;
  48. ResultLayer& operator=(const ResultLayer&) = delete;
  49. private:
  50. // ui::LayerDelegate:
  51. void OnDeviceScaleFactorChanged(float old_device_scale_factor,
  52. float new_device_scale_factor) override {}
  53. void OnPaintLayer(const ui::PaintContext& context) override;
  54. void DrawVerticalBar(gfx::Canvas& canvas,
  55. float x,
  56. float y,
  57. float height,
  58. cc::PaintFlags& flags);
  59. void DrawHorizontalBar(gfx::Canvas& canvas,
  60. float x,
  61. float y,
  62. float width,
  63. cc::PaintFlags& flags);
  64. };
  65. ResultLayer::ResultLayer(const gfx::Rect& box) {
  66. SetName("HighlighterResultView:ResultLayer");
  67. gfx::Rect bounds = box;
  68. bounds.Inset(-kResultLayerMargin);
  69. SetBounds(bounds);
  70. SetFillsBoundsOpaquely(false);
  71. SetMasksToBounds(false);
  72. set_delegate(this);
  73. }
  74. void ResultLayer::OnPaintLayer(const ui::PaintContext& context) {
  75. ui::PaintRecorder recorder(context, size());
  76. gfx::Canvas& canvas = *recorder.canvas();
  77. cc::PaintFlags flags;
  78. flags.setStyle(cc::PaintFlags::kFill_Style);
  79. flags.setAntiAlias(true);
  80. const float left = kResultLayerMargin;
  81. const float right = size().width() - kResultLayerMargin;
  82. const float width = right - left;
  83. const float top = kResultLayerMargin;
  84. const float bottom = size().height() - kResultLayerMargin;
  85. const float height = bottom - top;
  86. flags.setColor(SkColorSetA(kInnerFillColor, kInnerFillOpacity));
  87. canvas.DrawRect(gfx::RectF(left, top, width, height), flags);
  88. DrawVerticalBar(canvas, left, top, height, flags);
  89. DrawVerticalBar(canvas, right, top, height, flags);
  90. DrawHorizontalBar(canvas, left, top, width, flags);
  91. DrawHorizontalBar(canvas, left, bottom, width, flags);
  92. flags.setColor(SkColorSetA(kCornerCircleColorLT, kCornerCircleOpacity));
  93. canvas.DrawCircle(gfx::PointF(left, top), kCornerCircleRadius, flags);
  94. flags.setColor(SkColorSetA(kCornerCircleColorRT, kCornerCircleOpacity));
  95. canvas.DrawCircle(gfx::PointF(right, top), kCornerCircleRadius, flags);
  96. flags.setColor(SkColorSetA(kCornerCircleColorLB, kCornerCircleOpacity));
  97. canvas.DrawCircle(gfx::PointF(right, bottom), kCornerCircleRadius, flags);
  98. flags.setColor(SkColorSetA(kCornerCircleColorRB, kCornerCircleOpacity));
  99. canvas.DrawCircle(gfx::PointF(left, bottom), kCornerCircleRadius, flags);
  100. }
  101. void ResultLayer::DrawVerticalBar(gfx::Canvas& canvas,
  102. float x,
  103. float y,
  104. float height,
  105. cc::PaintFlags& flags) {
  106. const float x_fill = x - kStrokeFillWidth / 2;
  107. const float x_outline_left = x_fill - kStrokeOutlineWidth;
  108. const float x_outline_right = x_fill + kStrokeFillWidth;
  109. flags.setColor(SkColorSetA(kStrokeFillColor, kStrokeFillOpacity));
  110. canvas.DrawRect(gfx::RectF(x_fill, y, kStrokeFillWidth, height), flags);
  111. flags.setColor(SkColorSetA(kStrokeOutlineColor, kStrokeOutlineOpacity));
  112. canvas.DrawRect(gfx::RectF(x_outline_left, y, kStrokeOutlineWidth, height),
  113. flags);
  114. canvas.DrawRect(gfx::RectF(x_outline_right, y, kStrokeOutlineWidth, height),
  115. flags);
  116. }
  117. void ResultLayer::DrawHorizontalBar(gfx::Canvas& canvas,
  118. float x,
  119. float y,
  120. float width,
  121. cc::PaintFlags& flags) {
  122. const float y_fill = y - kStrokeFillWidth / 2;
  123. const float y_outline_left = y_fill - kStrokeOutlineWidth;
  124. const float y_outline_right = y_fill + kStrokeFillWidth;
  125. flags.setColor(SkColorSetA(kStrokeFillColor, kStrokeFillOpacity));
  126. canvas.DrawRect(gfx::RectF(x, y_fill, width, kStrokeFillWidth), flags);
  127. flags.setColor(SkColorSetA(kStrokeOutlineColor, kStrokeOutlineOpacity));
  128. canvas.DrawRect(gfx::RectF(x, y_outline_left, width, kStrokeOutlineWidth),
  129. flags);
  130. canvas.DrawRect(gfx::RectF(x, y_outline_right, width, kStrokeOutlineWidth),
  131. flags);
  132. }
  133. } // namespace
  134. HighlighterResultView::HighlighterResultView() = default;
  135. HighlighterResultView::~HighlighterResultView() = default;
  136. // static
  137. views::UniqueWidgetPtr HighlighterResultView::Create(
  138. aura::Window* root_window) {
  139. views::Widget::InitParams params;
  140. params.type = views::Widget::InitParams::TYPE_WINDOW_FRAMELESS;
  141. params.name = "HighlighterResult";
  142. params.accept_events = false;
  143. params.activatable = views::Widget::InitParams::Activatable::kNo;
  144. params.opacity = views::Widget::InitParams::WindowOpacity::kTranslucent;
  145. params.parent =
  146. Shell::GetContainer(root_window, kShellWindowId_OverlayContainer);
  147. params.layer_type = ui::LAYER_SOLID_COLOR;
  148. auto widget = views::UniqueWidgetPtr(
  149. std::make_unique<views::Widget>(std::move(params)));
  150. widget->SetContentsView(std::make_unique<HighlighterResultView>());
  151. widget->SetFullscreen(true);
  152. widget->Show();
  153. return widget;
  154. }
  155. void HighlighterResultView::Animate(const gfx::RectF& bounds,
  156. HighlighterGestureType gesture_type,
  157. base::OnceClosure done) {
  158. ui::Layer* layer = GetWidget()->GetLayer();
  159. base::TimeDelta delay;
  160. base::TimeDelta duration;
  161. if (gesture_type == HighlighterGestureType::kHorizontalStroke) {
  162. // The original stroke is fading out in place.
  163. // Fade in a solid transparent rectangle.
  164. result_layer_ = std::make_unique<ui::Layer>(ui::LAYER_SOLID_COLOR);
  165. result_layer_->SetName("HighlighterResultView:SOLID_LAYER");
  166. result_layer_->SetBounds(gfx::ToEnclosingRect(bounds));
  167. result_layer_->SetFillsBoundsOpaquely(false);
  168. result_layer_->SetMasksToBounds(false);
  169. result_layer_->SetColor(fast_ink::FastInkPoints::kDefaultColor);
  170. layer->Add(result_layer_.get());
  171. delay = base::Milliseconds(kResultInPlaceFadeinDelayMs);
  172. duration = base::Milliseconds(kResultInPlaceFadeinDurationMs);
  173. } else {
  174. DCHECK(gesture_type == HighlighterGestureType::kClosedShape);
  175. // The original stroke is fading out and inflating.
  176. // Fade in the deflating lens overlay.
  177. result_layer_ = std::make_unique<ResultLayer>(gfx::ToEnclosingRect(bounds));
  178. layer->Add(result_layer_.get());
  179. gfx::Transform transform;
  180. const gfx::PointF pivot = bounds.CenterPoint();
  181. transform.Translate(pivot.x() * (1 - kInitialScale),
  182. pivot.y() * (1 - kInitialScale));
  183. transform.Scale(kInitialScale, kInitialScale);
  184. layer->SetTransform(transform);
  185. delay = base::Milliseconds(kResultFadeinDelayMs);
  186. duration = base::Milliseconds(kResultFadeinDurationMs);
  187. }
  188. layer->SetOpacity(0);
  189. animation_timer_ = std::make_unique<base::OneShotTimer>();
  190. animation_timer_->Start(
  191. FROM_HERE, delay,
  192. base::BindOnce(&HighlighterResultView::FadeIn, base::Unretained(this),
  193. duration, std::move(done)));
  194. }
  195. void HighlighterResultView::FadeIn(const base::TimeDelta& duration,
  196. base::OnceClosure done) {
  197. ui::Layer* layer = GetWidget()->GetLayer();
  198. {
  199. ui::ScopedLayerAnimationSettings settings(layer->GetAnimator());
  200. settings.SetTransitionDuration(duration);
  201. settings.SetTweenType(gfx::Tween::LINEAR_OUT_SLOW_IN);
  202. layer->SetOpacity(1);
  203. gfx::Transform transform;
  204. transform.Scale(1, 1);
  205. transform.Translate(0, 0);
  206. layer->SetTransform(transform);
  207. }
  208. animation_timer_ = std::make_unique<base::OneShotTimer>();
  209. animation_timer_->Start(
  210. FROM_HERE, duration + base::Milliseconds(kResultFadeoutDelayMs),
  211. base::BindOnce(&HighlighterResultView::FadeOut, base::Unretained(this),
  212. std::move(done)));
  213. }
  214. void HighlighterResultView::FadeOut(base::OnceClosure done) {
  215. ui::Layer* layer = GetWidget()->GetLayer();
  216. base::TimeDelta duration = base::Milliseconds(kResultFadeoutDurationMs);
  217. ui::ScopedLayerAnimationSettings settings(layer->GetAnimator());
  218. settings.SetTransitionDuration(duration);
  219. settings.SetTweenType(gfx::Tween::LINEAR_OUT_SLOW_IN);
  220. layer->SetOpacity(0);
  221. animation_timer_ = std::make_unique<base::OneShotTimer>();
  222. animation_timer_->Start(FROM_HERE, duration, std::move(done));
  223. }
  224. } // namespace ash