123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216 |
- // Copyright 2018 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "ash/public/cpp/network_icon_image_source.h"
- #include "third_party/skia/include/core/SkPath.h"
- #include "ui/gfx/canvas.h"
- #include "ui/gfx/geometry/insets.h"
- #include "ui/gfx/geometry/rect.h"
- #include "ui/gfx/geometry/rect_f.h"
- #include "ui/gfx/geometry/skia_conversions.h"
- #include "ui/gfx/paint_vector_icon.h"
- #include "ui/gfx/scoped_canvas.h"
- #include "ui/gfx/vector_icon_types.h"
- #include "ui/gfx/vector_icon_utils.h"
- namespace ash {
- namespace network_icon {
- namespace {
- constexpr int kIconStrokeWidth = 2;
- constexpr int kCellularIconOffset = 1;
- SkPath CreateArcPath(gfx::RectF oval, float start_angle, float sweep_angle) {
- SkPath path;
- path.setIsVolatile(true);
- path.setFillType(SkPathFillType::kWinding);
- path.moveTo(oval.CenterPoint().x(), oval.CenterPoint().y());
- path.arcTo(gfx::RectFToSkRect(oval), start_angle, sweep_angle, false);
- path.close();
- return path;
- }
- } // namespace
- //------------------------------------------------------------------------------
- // NetworkIconImageSource
- NetworkIconImageSource::NetworkIconImageSource(const gfx::Size& size,
- const gfx::ImageSkia& icon,
- const Badges& badges)
- : CanvasImageSource(size), icon_(icon), badges_(badges) {}
- NetworkIconImageSource::~NetworkIconImageSource() = default;
- void NetworkIconImageSource::Draw(gfx::Canvas* canvas) {
- const int width = size().width();
- const int height = size().height();
- // The base icon is centered in both dimensions.
- const int icon_x = (width - icon_.width()) / 2;
- const int icon_y = (height - icon_.height()) / 2;
- canvas->DrawImageInt(icon_, icon_x, icon_y);
- auto paint_badge = [&canvas](const Badge& badge, int x, int y,
- int badge_size = 0) {
- gfx::ScopedCanvas scoped(canvas);
- canvas->Translate(gfx::Vector2d(x, y));
- if (badge_size)
- gfx::PaintVectorIcon(canvas, *badge.icon, badge_size, badge.color);
- else
- gfx::PaintVectorIcon(canvas, *badge.icon, badge.color);
- };
- // The center badge is scaled and centered over the icon.
- if (badges_.center.icon)
- paint_badge(badges_.center, icon_x, icon_y, icon_.width());
- if (badges_.top_left.icon)
- paint_badge(badges_.top_left, 0, icon_y);
- if (badges_.bottom_left.icon) {
- paint_badge(
- badges_.bottom_left, 0,
- height - gfx::GetDefaultSizeOfVectorIcon(*badges_.bottom_left.icon));
- }
- if (badges_.bottom_right.icon) {
- const int badge_offset =
- gfx::GetDefaultSizeOfVectorIcon(*badges_.bottom_right.icon) - 1;
- paint_badge(badges_.bottom_right, width - badge_offset,
- height - badge_offset);
- }
- }
- bool NetworkIconImageSource::HasRepresentationAtAllScales() const {
- return true;
- }
- //------------------------------------------------------------------------------
- // SignalStrengthImageSource
- SignalStrengthImageSource::SignalStrengthImageSource(ImageType image_type,
- SkColor color,
- const gfx::Size& size,
- int signal_strength,
- int padding)
- : CanvasImageSource(size),
- image_type_(image_type),
- color_(color),
- signal_strength_(signal_strength),
- padding_(padding) {
- if (image_type_ == NONE)
- image_type_ = ARCS;
- DCHECK_GE(signal_strength, 0);
- DCHECK_LT(signal_strength, kNumNetworkImages);
- }
- SignalStrengthImageSource::~SignalStrengthImageSource() = default;
- // gfx::CanvasImageSource:
- void SignalStrengthImageSource::Draw(gfx::Canvas* canvas) {
- if (image_type_ == ARCS)
- DrawArcs(canvas);
- else
- DrawBars(canvas);
- }
- bool SignalStrengthImageSource::HasRepresentationAtAllScales() const {
- return true;
- }
- void SignalStrengthImageSource::DrawArcs(gfx::Canvas* canvas) {
- gfx::RectF oval_bounds((gfx::Rect(size())));
- oval_bounds.Inset(padding_);
- // Double the width and height. The new midpoint should be the former
- // bottom center.
- oval_bounds.Inset(gfx::InsetsF::TLBR(0, -oval_bounds.width() / 2,
- -oval_bounds.height(),
- -oval_bounds.width() / 2));
- constexpr SkScalar kAngleAboveHorizontal = 51.f;
- constexpr SkScalar kStartAngle = 180.f + kAngleAboveHorizontal;
- constexpr SkScalar kSweepAngle = 180.f - 2 * kAngleAboveHorizontal;
- cc::PaintFlags flags;
- flags.setAntiAlias(true);
- flags.setStyle(cc::PaintFlags::kStroke_Style);
- flags.setStrokeWidth(kIconStrokeWidth);
- flags.setColor(color_);
- // Background (outline)
- canvas->sk_canvas()->drawPath(
- CreateArcPath(oval_bounds, kStartAngle, kSweepAngle), flags);
- // Foreground (signal strength).
- if (signal_strength_ != 0) {
- flags.setStyle(cc::PaintFlags::kFill_Style);
- // Percent of the height of the background wedge that we draw the
- // foreground wedge, indexed by signal strength.
- static constexpr float kWedgeHeightPercentages[] = {0.f, 0.375f, 0.5833f,
- 0.75f, 1.f};
- const float wedge_percent = kWedgeHeightPercentages[signal_strength_];
- oval_bounds.Inset(
- gfx::InsetsF((oval_bounds.height() / 2) * (1.f - wedge_percent)));
- canvas->sk_canvas()->drawPath(
- CreateArcPath(oval_bounds, kStartAngle, kSweepAngle), flags);
- }
- }
- void SignalStrengthImageSource::DrawBars(gfx::Canvas* canvas) {
- // Undo the canvas's device scaling and round values to the nearest whole
- // number so we can draw on exact pixel boundaries.
- const float dsf = canvas->UndoDeviceScaleFactor();
- auto scale = [dsf](SkScalar dimension) {
- return std::round(dimension * dsf);
- };
- // Length of short side of an isosceles right triangle, in dip.
- const SkScalar kFullTriangleSide =
- SkIntToScalar(size().width()) - padding_ * 2;
- auto make_triangle = [scale, kFullTriangleSide, this](SkScalar side) {
- SkPath triangle;
- triangle.moveTo(scale(padding_ + kCellularIconOffset),
- scale(padding_ + kFullTriangleSide + kCellularIconOffset));
- triangle.rLineTo(scale(side), 0);
- triangle.rLineTo(0, -scale(side));
- triangle.close();
- return triangle;
- };
- cc::PaintFlags flags;
- flags.setAntiAlias(true);
- flags.setColor(color_);
- // Background.
- flags.setStyle(cc::PaintFlags::kStroke_Style);
- flags.setStrokeWidth(kIconStrokeWidth);
- canvas->DrawPath(make_triangle(kFullTriangleSide), flags);
- // Foreground (signal strength).
- if (signal_strength_ != 0) {
- flags.setStyle(cc::PaintFlags::kFill_Style);
- // As a percentage of the bg triangle, the length of one of the short
- // sides of the fg triangle, indexed by signal strength.
- static constexpr float kTriangleSidePercents[] = {0.f, 0.375f, 0.5833f,
- 0.75f, 1.f};
- canvas->DrawPath(make_triangle(kTriangleSidePercents[signal_strength_] *
- kFullTriangleSide),
- flags);
- }
- }
- //------------------------------------------------------------------------------
- gfx::ImageSkia GetImageForWifiNetwork(SkColor color, gfx::Size size) {
- return gfx::CanvasImageSource::MakeImageSkia<SignalStrengthImageSource>(
- ARCS, color, size, kNumNetworkImages - 1);
- }
- } // namespace network_icon
- } // namespace ash
|