blob: 7882fd153963c52afa962692305cbf69d1f65a45 [file] [log] [blame]
// Copyright 2019 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/wallpaper/wallpaper_base_view.h"
#include "ash/public/cpp/wallpaper_types.h"
#include "ash/session/session_controller_impl.h"
#include "ash/shell.h"
#include "ash/style/ash_color_provider.h"
#include "ash/wallpaper/wallpaper_controller_impl.h"
#include "base/numerics/safe_conversions.h"
#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/gfx/canvas.h"
namespace ash {
namespace {
// Gets the shield color based on the state. This is used for the login, lock,
// overview and tablet mode.
SkColor GetWallpaperShieldColor() {
return AshColorProvider::Get()->GetShieldLayerColor(
Shell::Get()->session_controller()->IsUserSessionBlocked()
? AshColorProvider::ShieldLayerType::kShield80
: AshColorProvider::ShieldLayerType::kShield40);
}
} // namespace
void WallpaperBaseView::OnPaint(gfx::Canvas* canvas) {
// Scale the image while maintaining the aspect ratio, cropping as necessary
// to fill the wallpaper. Ideally the image should be larger than the largest
// display supported, if not we will scale and center it if the layout is
// WALLPAPER_LAYOUT_CENTER_CROPPED.
auto* controller = Shell::Get()->wallpaper_controller();
gfx::ImageSkia wallpaper = controller->GetWallpaper();
WallpaperLayout layout = controller->GetWallpaperLayout();
// Wallpapers with png format could be partially transparent. Fill the canvas
// with black to make it opaque before painting the wallpaper.
canvas->FillRect(GetLocalBounds(), SK_ColorBLACK);
if (wallpaper.isNull())
return;
cc::PaintFlags flags;
switch (layout) {
case WALLPAPER_LAYOUT_CENTER_CROPPED: {
// The dimension with the smallest ratio must be cropped, the other one
// is preserved. Both are set in gfx::Size cropped_size.
double horizontal_ratio =
static_cast<double>(width()) / static_cast<double>(wallpaper.width());
double vertical_ratio = static_cast<double>(height()) /
static_cast<double>(wallpaper.height());
gfx::Size cropped_size;
if (vertical_ratio > horizontal_ratio) {
cropped_size = gfx::Size(
base::ClampFloor(static_cast<double>(width()) / vertical_ratio),
wallpaper.height());
} else {
cropped_size = gfx::Size(
wallpaper.width(),
base::ClampFloor(static_cast<double>(height()) / horizontal_ratio));
}
gfx::Rect wallpaper_cropped_rect(wallpaper.size());
wallpaper_cropped_rect.ClampToCenteredSize(cropped_size);
DrawWallpaper(wallpaper, wallpaper_cropped_rect, gfx::Rect(size()), flags,
canvas);
break;
}
case WALLPAPER_LAYOUT_TILE: {
canvas->TileImageInt(wallpaper, 0, 0, 0, 0, width(), height(), 1.0f,
SkTileMode::kRepeat, SkTileMode::kRepeat, &flags);
break;
}
case WALLPAPER_LAYOUT_STRETCH: {
// This is generally not recommended as it may show artifacts.
DrawWallpaper(wallpaper, gfx::Rect(wallpaper.size()), gfx::Rect(size()),
flags, canvas);
break;
}
case WALLPAPER_LAYOUT_CENTER: {
const float image_scale = canvas->image_scale();
// Simply centered and not scaled (but may be clipped).
gfx::Rect wallpaper_rect = gfx::ScaleToRoundedRect(
gfx::Rect(wallpaper.size()),
centered_layout_image_scale_.x() / image_scale,
centered_layout_image_scale_.y() / image_scale);
wallpaper_rect.set_x((width() - wallpaper_rect.width()) / 2);
wallpaper_rect.set_y((height() - wallpaper_rect.height()) / 2);
DrawWallpaper(wallpaper, gfx::Rect(wallpaper.size()), wallpaper_rect,
flags, canvas);
break;
}
default: {
NOTREACHED();
break;
}
}
if (controller->ShouldApplyShield())
canvas->FillRect(GetLocalBounds(), GetWallpaperShieldColor());
}
void WallpaperBaseView::DrawWallpaper(const gfx::ImageSkia& wallpaper,
const gfx::Rect& src,
const gfx::Rect& dst,
const cc::PaintFlags& flags,
gfx::Canvas* canvas) {
canvas->DrawImageInt(wallpaper, src.x(), src.y(), src.width(), src.height(),
dst.x(), dst.y(), dst.width(), dst.height(),
/*filter=*/true, flags);
}
BEGIN_METADATA(WallpaperBaseView, views::View)
END_METADATA
} // namespace ash