network_icon_image_source.cc 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. // Copyright 2018 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/public/cpp/network_icon_image_source.h"
  5. #include "third_party/skia/include/core/SkPath.h"
  6. #include "ui/gfx/canvas.h"
  7. #include "ui/gfx/geometry/insets.h"
  8. #include "ui/gfx/geometry/rect.h"
  9. #include "ui/gfx/geometry/rect_f.h"
  10. #include "ui/gfx/geometry/skia_conversions.h"
  11. #include "ui/gfx/paint_vector_icon.h"
  12. #include "ui/gfx/scoped_canvas.h"
  13. #include "ui/gfx/vector_icon_types.h"
  14. #include "ui/gfx/vector_icon_utils.h"
  15. namespace ash {
  16. namespace network_icon {
  17. namespace {
  18. constexpr int kIconStrokeWidth = 2;
  19. constexpr int kCellularIconOffset = 1;
  20. SkPath CreateArcPath(gfx::RectF oval, float start_angle, float sweep_angle) {
  21. SkPath path;
  22. path.setIsVolatile(true);
  23. path.setFillType(SkPathFillType::kWinding);
  24. path.moveTo(oval.CenterPoint().x(), oval.CenterPoint().y());
  25. path.arcTo(gfx::RectFToSkRect(oval), start_angle, sweep_angle, false);
  26. path.close();
  27. return path;
  28. }
  29. } // namespace
  30. //------------------------------------------------------------------------------
  31. // NetworkIconImageSource
  32. NetworkIconImageSource::NetworkIconImageSource(const gfx::Size& size,
  33. const gfx::ImageSkia& icon,
  34. const Badges& badges)
  35. : CanvasImageSource(size), icon_(icon), badges_(badges) {}
  36. NetworkIconImageSource::~NetworkIconImageSource() = default;
  37. void NetworkIconImageSource::Draw(gfx::Canvas* canvas) {
  38. const int width = size().width();
  39. const int height = size().height();
  40. // The base icon is centered in both dimensions.
  41. const int icon_x = (width - icon_.width()) / 2;
  42. const int icon_y = (height - icon_.height()) / 2;
  43. canvas->DrawImageInt(icon_, icon_x, icon_y);
  44. auto paint_badge = [&canvas](const Badge& badge, int x, int y,
  45. int badge_size = 0) {
  46. gfx::ScopedCanvas scoped(canvas);
  47. canvas->Translate(gfx::Vector2d(x, y));
  48. if (badge_size)
  49. gfx::PaintVectorIcon(canvas, *badge.icon, badge_size, badge.color);
  50. else
  51. gfx::PaintVectorIcon(canvas, *badge.icon, badge.color);
  52. };
  53. // The center badge is scaled and centered over the icon.
  54. if (badges_.center.icon)
  55. paint_badge(badges_.center, icon_x, icon_y, icon_.width());
  56. if (badges_.top_left.icon)
  57. paint_badge(badges_.top_left, 0, icon_y);
  58. if (badges_.bottom_left.icon) {
  59. paint_badge(
  60. badges_.bottom_left, 0,
  61. height - gfx::GetDefaultSizeOfVectorIcon(*badges_.bottom_left.icon));
  62. }
  63. if (badges_.bottom_right.icon) {
  64. const int badge_offset =
  65. gfx::GetDefaultSizeOfVectorIcon(*badges_.bottom_right.icon) - 1;
  66. paint_badge(badges_.bottom_right, width - badge_offset,
  67. height - badge_offset);
  68. }
  69. }
  70. bool NetworkIconImageSource::HasRepresentationAtAllScales() const {
  71. return true;
  72. }
  73. //------------------------------------------------------------------------------
  74. // SignalStrengthImageSource
  75. SignalStrengthImageSource::SignalStrengthImageSource(ImageType image_type,
  76. SkColor color,
  77. const gfx::Size& size,
  78. int signal_strength,
  79. int padding)
  80. : CanvasImageSource(size),
  81. image_type_(image_type),
  82. color_(color),
  83. signal_strength_(signal_strength),
  84. padding_(padding) {
  85. if (image_type_ == NONE)
  86. image_type_ = ARCS;
  87. DCHECK_GE(signal_strength, 0);
  88. DCHECK_LT(signal_strength, kNumNetworkImages);
  89. }
  90. SignalStrengthImageSource::~SignalStrengthImageSource() = default;
  91. // gfx::CanvasImageSource:
  92. void SignalStrengthImageSource::Draw(gfx::Canvas* canvas) {
  93. if (image_type_ == ARCS)
  94. DrawArcs(canvas);
  95. else
  96. DrawBars(canvas);
  97. }
  98. bool SignalStrengthImageSource::HasRepresentationAtAllScales() const {
  99. return true;
  100. }
  101. void SignalStrengthImageSource::DrawArcs(gfx::Canvas* canvas) {
  102. gfx::RectF oval_bounds((gfx::Rect(size())));
  103. oval_bounds.Inset(padding_);
  104. // Double the width and height. The new midpoint should be the former
  105. // bottom center.
  106. oval_bounds.Inset(gfx::InsetsF::TLBR(0, -oval_bounds.width() / 2,
  107. -oval_bounds.height(),
  108. -oval_bounds.width() / 2));
  109. constexpr SkScalar kAngleAboveHorizontal = 51.f;
  110. constexpr SkScalar kStartAngle = 180.f + kAngleAboveHorizontal;
  111. constexpr SkScalar kSweepAngle = 180.f - 2 * kAngleAboveHorizontal;
  112. cc::PaintFlags flags;
  113. flags.setAntiAlias(true);
  114. flags.setStyle(cc::PaintFlags::kStroke_Style);
  115. flags.setStrokeWidth(kIconStrokeWidth);
  116. flags.setColor(color_);
  117. // Background (outline)
  118. canvas->sk_canvas()->drawPath(
  119. CreateArcPath(oval_bounds, kStartAngle, kSweepAngle), flags);
  120. // Foreground (signal strength).
  121. if (signal_strength_ != 0) {
  122. flags.setStyle(cc::PaintFlags::kFill_Style);
  123. // Percent of the height of the background wedge that we draw the
  124. // foreground wedge, indexed by signal strength.
  125. static constexpr float kWedgeHeightPercentages[] = {0.f, 0.375f, 0.5833f,
  126. 0.75f, 1.f};
  127. const float wedge_percent = kWedgeHeightPercentages[signal_strength_];
  128. oval_bounds.Inset(
  129. gfx::InsetsF((oval_bounds.height() / 2) * (1.f - wedge_percent)));
  130. canvas->sk_canvas()->drawPath(
  131. CreateArcPath(oval_bounds, kStartAngle, kSweepAngle), flags);
  132. }
  133. }
  134. void SignalStrengthImageSource::DrawBars(gfx::Canvas* canvas) {
  135. // Undo the canvas's device scaling and round values to the nearest whole
  136. // number so we can draw on exact pixel boundaries.
  137. const float dsf = canvas->UndoDeviceScaleFactor();
  138. auto scale = [dsf](SkScalar dimension) {
  139. return std::round(dimension * dsf);
  140. };
  141. // Length of short side of an isosceles right triangle, in dip.
  142. const SkScalar kFullTriangleSide =
  143. SkIntToScalar(size().width()) - padding_ * 2;
  144. auto make_triangle = [scale, kFullTriangleSide, this](SkScalar side) {
  145. SkPath triangle;
  146. triangle.moveTo(scale(padding_ + kCellularIconOffset),
  147. scale(padding_ + kFullTriangleSide + kCellularIconOffset));
  148. triangle.rLineTo(scale(side), 0);
  149. triangle.rLineTo(0, -scale(side));
  150. triangle.close();
  151. return triangle;
  152. };
  153. cc::PaintFlags flags;
  154. flags.setAntiAlias(true);
  155. flags.setColor(color_);
  156. // Background.
  157. flags.setStyle(cc::PaintFlags::kStroke_Style);
  158. flags.setStrokeWidth(kIconStrokeWidth);
  159. canvas->DrawPath(make_triangle(kFullTriangleSide), flags);
  160. // Foreground (signal strength).
  161. if (signal_strength_ != 0) {
  162. flags.setStyle(cc::PaintFlags::kFill_Style);
  163. // As a percentage of the bg triangle, the length of one of the short
  164. // sides of the fg triangle, indexed by signal strength.
  165. static constexpr float kTriangleSidePercents[] = {0.f, 0.375f, 0.5833f,
  166. 0.75f, 1.f};
  167. canvas->DrawPath(make_triangle(kTriangleSidePercents[signal_strength_] *
  168. kFullTriangleSide),
  169. flags);
  170. }
  171. }
  172. //------------------------------------------------------------------------------
  173. gfx::ImageSkia GetImageForWifiNetwork(SkColor color, gfx::Size size) {
  174. return gfx::CanvasImageSource::MakeImageSkia<SignalStrengthImageSource>(
  175. ARCS, color, size, kNumNetworkImages - 1);
  176. }
  177. } // namespace network_icon
  178. } // namespace ash