gradient_layer_delegate.cc 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. // Copyright 2021 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/controls/gradient_layer_delegate.h"
  5. #include "base/time/time.h"
  6. #include "ui/compositor/paint_recorder.h"
  7. #include "ui/gfx/animation/linear_animation.h"
  8. #include "ui/gfx/canvas.h"
  9. #include "ui/gfx/skia_paint_util.h"
  10. #include "ui/views/paint_info.h"
  11. namespace ash {
  12. GradientLayerDelegate::GradientLayerDelegate(bool animate_in)
  13. : layer_(ui::LAYER_TEXTURED) {
  14. layer_.set_delegate(this);
  15. layer_.SetFillsBoundsOpaquely(false);
  16. if (animate_in) {
  17. animation_ = std::make_unique<gfx::LinearAnimation>(
  18. base::Milliseconds(50), gfx::LinearAnimation::kDefaultFrameRate,
  19. /*delegate=*/this);
  20. animation_->Start();
  21. // The animation is usually 2 or 3 frames. Instead of starting the animation
  22. // at 0.0, which results in a fully transparent frame in the beginning, use
  23. // an initial value so the first frame is partially opaque.
  24. animation_->SetCurrentValue(0.333);
  25. }
  26. }
  27. GradientLayerDelegate::~GradientLayerDelegate() {
  28. layer_.set_delegate(nullptr);
  29. }
  30. void GradientLayerDelegate::OnPaintLayer(const ui::PaintContext& context) {
  31. const gfx::Size size = layer()->size();
  32. views::PaintInfo paint_info =
  33. views::PaintInfo::CreateRootPaintInfo(context, size);
  34. const auto& paint_recording_size = paint_info.paint_recording_size();
  35. // Pass the scale factor when constructing PaintRecorder so the MaskLayer
  36. // size is not incorrectly rounded (see https://crbug.com/921274).
  37. ui::PaintRecorder recorder(
  38. context, paint_info.paint_recording_size(),
  39. static_cast<float>(paint_recording_size.width()) / size.width(),
  40. static_cast<float>(paint_recording_size.height()) / size.height(),
  41. nullptr);
  42. recorder.canvas()->DrawColor(SK_ColorBLACK, SkBlendMode::kSrc);
  43. if (!start_fade_zone_.zone_rect.IsEmpty())
  44. DrawFadeZone(start_fade_zone_, recorder.canvas());
  45. if (!end_fade_zone_.zone_rect.IsEmpty())
  46. DrawFadeZone(end_fade_zone_, recorder.canvas());
  47. }
  48. void GradientLayerDelegate::AnimationProgressed(
  49. const gfx::Animation* animation) {
  50. DCHECK_EQ(animation, animation_.get());
  51. // Schedule repaint of the affected areas.
  52. if (!start_fade_zone_.zone_rect.IsEmpty())
  53. layer_.SchedulePaint(start_fade_zone_.zone_rect);
  54. if (!end_fade_zone_.zone_rect.IsEmpty())
  55. layer_.SchedulePaint(end_fade_zone_.zone_rect);
  56. }
  57. void GradientLayerDelegate::DrawFadeZone(const FadeZone& fade_zone,
  58. gfx::Canvas* canvas) {
  59. gfx::Point start_point;
  60. gfx::Point end_point;
  61. if (fade_zone.is_horizontal) {
  62. start_point = gfx::Point(fade_zone.zone_rect.x(), 0);
  63. end_point = gfx::Point(fade_zone.zone_rect.right(), 0);
  64. } else {
  65. start_point = gfx::Point(0, fade_zone.zone_rect.y());
  66. end_point = gfx::Point(0, fade_zone.zone_rect.bottom());
  67. }
  68. cc::PaintFlags flags;
  69. flags.setBlendMode(SkBlendMode::kSrc);
  70. flags.setAntiAlias(false);
  71. SkColor target_color;
  72. if (animation_) {
  73. // Animation runs 0.0 to 1.0, so alpha runs 255 (opaque) to 0 (transparent).
  74. uint8_t alpha = (1.0 - animation_->GetCurrentValue()) * 255;
  75. target_color = SkColorSetA(SK_ColorTRANSPARENT, alpha);
  76. } else {
  77. target_color = SK_ColorTRANSPARENT;
  78. }
  79. flags.setShader(gfx::CreateGradientShader(
  80. start_point, end_point, fade_zone.fade_in ? target_color : SK_ColorBLACK,
  81. fade_zone.fade_in ? SK_ColorBLACK : target_color));
  82. canvas->DrawRect(fade_zone.zone_rect, flags);
  83. }
  84. } // namespace ash