diff options
author | pkotwicz@chromium.org <pkotwicz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-06-20 00:21:45 +0000 |
---|---|---|
committer | pkotwicz@chromium.org <pkotwicz@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-06-20 00:21:45 +0000 |
commit | dad4661819c280d4468548864442face8082b0b2 (patch) | |
tree | 627e91e922b678d227f1fe40ec131be295db59f7 /ui/views | |
parent | 5951c851f2b1024645553a5657330c4005a5e3e3 (diff) | |
download | chromium_src-dad4661819c280d4468548864442face8082b0b2.zip chromium_src-dad4661819c280d4468548864442face8082b0b2.tar.gz chromium_src-dad4661819c280d4468548864442face8082b0b2.tar.bz2 |
Make ImageButton and NetworkMenuIcon work in high DPI
Test=Manual
Bug=None
Testing steps
1) Run chromium using --force-device-scale-factor=2 --highlight-missing-2x-resources --load-2x-resources
2) Ensure that the hot image is not pixelated
Review URL: https://chromiumcodereview.appspot.com/10546160
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@143092 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/views')
-rw-r--r-- | ui/views/controls/button/image_button.cc | 68 | ||||
-rw-r--r-- | ui/views/controls/button/image_button.h | 25 | ||||
-rw-r--r-- | ui/views/controls/button/image_button_unittest.cc | 22 |
3 files changed, 89 insertions, 26 deletions
diff --git a/ui/views/controls/button/image_button.cc b/ui/views/controls/button/image_button.cc index a9d15fc..383cafd 100644 --- a/ui/views/controls/button/image_button.cc +++ b/ui/views/controls/button/image_button.cc @@ -7,7 +7,9 @@ #include "base/utf_string_conversions.h" #include "ui/base/animation/throb_animation.h" #include "ui/gfx/canvas.h" +#include "ui/gfx/screen.h" #include "ui/gfx/skbitmap_operations.h" +#include "ui/views/widget/widget.h" namespace views { @@ -39,13 +41,10 @@ void ImageButton::SetImage(ButtonState state, const gfx::ImageSkia* image) { void ImageButton::SetBackground(SkColor color, const gfx::ImageSkia* image, const gfx::ImageSkia* mask) { - if (!image || !mask) { - background_image_ = gfx::ImageSkia(); - return; - } - - background_image_ = - SkBitmapOperations::CreateButtonBackground(color, *image, *mask); + background_image_.src_color_ = color; + background_image_.src_image_ = image ? *image : gfx::ImageSkia(); + background_image_.src_mask_ = mask ? *mask : gfx::ImageSkia(); + background_image_.result_ = gfx::ImageSkia(); } void ImageButton::SetOverlayImage(const gfx::ImageSkia* image) { @@ -76,7 +75,8 @@ void ImageButton::OnPaint(gfx::Canvas* canvas) { // Call the base class first to paint any background/borders. View::OnPaint(canvas); - gfx::ImageSkia img = GetImageToPaint(); + float current_device_scale = GetCurrentDeviceScale(); + gfx::ImageSkia img = GetImageToPaint(current_device_scale); if (!img.isNull()) { int x = 0, y = 0; @@ -91,8 +91,10 @@ void ImageButton::OnPaint(gfx::Canvas* canvas) { else if (v_alignment_ == ALIGN_BOTTOM) y = height() - img.height(); - if (!background_image_.empty()) - canvas->DrawImageInt(background_image_, x, y); + if (!background_image_.result_.HasBitmapForScale(current_device_scale)) + UpdateButtonBackground(current_device_scale); + if (!background_image_.result_.empty()) + canvas->DrawImageInt(background_image_.result_, x, y); canvas->DrawImageInt(img, x, y); @@ -105,12 +107,26 @@ void ImageButton::OnPaint(gfx::Canvas* canvas) { //////////////////////////////////////////////////////////////////////////////// // ImageButton, protected: -gfx::ImageSkia ImageButton::GetImageToPaint() { +float ImageButton::GetCurrentDeviceScale() { + gfx::Display display = gfx::Screen::GetDisplayNearestWindow( + GetWidget() ? GetWidget()->GetNativeView() : NULL); + return display.device_scale_factor(); +} + +gfx::ImageSkia ImageButton::GetImageToPaint(float scale) { gfx::ImageSkia img; if (!images_[BS_HOT].isNull() && hover_animation_->is_animating()) { - img = SkBitmapOperations::CreateBlendedBitmap(images_[BS_NORMAL], - images_[BS_HOT], hover_animation_->GetCurrentValue()); + float normal_bitmap_scale; + float hot_bitmap_scale; + SkBitmap normal_bitmap = images_[BS_NORMAL].GetBitmapForScale( + scale, &normal_bitmap_scale); + SkBitmap hot_bitmap = images_[BS_HOT].GetBitmapForScale(scale, + &hot_bitmap_scale); + DCHECK_EQ(normal_bitmap_scale, hot_bitmap_scale); + SkBitmap blended_bitmap = SkBitmapOperations::CreateBlendedBitmap( + normal_bitmap, hot_bitmap, hover_animation_->GetCurrentValue()); + img = gfx::ImageSkia(blended_bitmap, normal_bitmap_scale); } else { img = images_[state_]; } @@ -118,6 +134,23 @@ gfx::ImageSkia ImageButton::GetImageToPaint() { return !img.isNull() ? img : images_[BS_NORMAL]; } +void ImageButton::UpdateButtonBackground(float scale) { + float bitmap_scale; + float mask_scale; + SkBitmap bitmap = background_image_.src_image_.GetBitmapForScale( + scale, &bitmap_scale); + SkBitmap mask_bitmap = background_image_.src_mask_.GetBitmapForScale( + scale, &mask_scale); + if (bitmap.isNull() || mask_bitmap.isNull() || + background_image_.result_.HasBitmapForScale(bitmap_scale)) { + return; + } + DCHECK_EQ(bitmap_scale, mask_scale); + SkBitmap result = SkBitmapOperations::CreateButtonBackground( + background_image_.src_color_, bitmap, mask_bitmap); + background_image_.result_.AddBitmapForScale(result, bitmap_scale); +} + //////////////////////////////////////////////////////////////////////////////// // ToggleImageButton, public: @@ -184,4 +217,13 @@ bool ToggleImageButton::GetTooltipText(const gfx::Point& p, return true; } +/////////////////////////////////////////////////////////////////////////////// +// struct BackgroundImageGenerationInfo +ImageButton::BackgroundImageGenerationInfo::BackgroundImageGenerationInfo() + : src_color_(0) { +} + +ImageButton::BackgroundImageGenerationInfo::~BackgroundImageGenerationInfo() { +} + } // namespace views diff --git a/ui/views/controls/button/image_button.h b/ui/views/controls/button/image_button.h index b267e3c..49f44b8 100644 --- a/ui/views/controls/button/image_button.h +++ b/ui/views/controls/button/image_button.h @@ -7,6 +7,7 @@ #pragma once #include "base/gtest_prod_util.h" +#include "base/memory/scoped_ptr.h" #include "ui/gfx/image/image_skia.h" #include "ui/views/controls/button/custom_button.h" @@ -62,15 +63,33 @@ class VIEWS_EXPORT ImageButton : public CustomButton { } protected: + // Returns the current device scale of the view. + // TODO(pkotwicz): Remove this once scale factor can be queried from canvas. + float GetCurrentDeviceScale(); + // Returns the image to paint. This is invoked from paint and returns a value // from images. - virtual gfx::ImageSkia GetImageToPaint(); + // |scale| is the scale at which the view is painted and the scale + // which should be used when mutating ImageSkias. + virtual gfx::ImageSkia GetImageToPaint(float scale); + + // Updates button background for |scale|. + void UpdateButtonBackground(float scale); // The images used to render the different states of this button. gfx::ImageSkia images_[BS_COUNT]; - // The background image. - gfx::ImageSkia background_image_; + // Information necessary to generate background image. + struct BackgroundImageGenerationInfo { + BackgroundImageGenerationInfo(); + ~BackgroundImageGenerationInfo(); + + SkColor src_color_; + gfx::ImageSkia src_image_; + gfx::ImageSkia src_mask_; + gfx::ImageSkia result_; + }; + BackgroundImageGenerationInfo background_image_; // Image to draw on top of normal / hot / pushed image. Usually empty. gfx::ImageSkia overlay_image_; diff --git a/ui/views/controls/button/image_button_unittest.cc b/ui/views/controls/button/image_button_unittest.cc index 4e6c5b2..8f5ea5f 100644 --- a/ui/views/controls/button/image_button_unittest.cc +++ b/ui/views/controls/button/image_button_unittest.cc @@ -24,8 +24,10 @@ typedef ViewsTestBase ImageButtonTest; TEST_F(ImageButtonTest, Basics) { ImageButton button(NULL); + float kRequestedScale = 1.0f; + // Our image to paint starts empty. - EXPECT_TRUE(button.GetImageToPaint().empty()); + EXPECT_TRUE(button.GetImageToPaint(kRequestedScale).empty()); // Without a theme, buttons are 16x14 by default. EXPECT_EQ("16x14", button.GetPreferredSize().ToString()); @@ -39,9 +41,9 @@ TEST_F(ImageButtonTest, Basics) { button.SetImage(CustomButton::BS_NORMAL, &normal_image); // Image uses normal image for painting. - EXPECT_FALSE(button.GetImageToPaint().empty()); - EXPECT_EQ(10, button.GetImageToPaint().width()); - EXPECT_EQ(20, button.GetImageToPaint().height()); + EXPECT_FALSE(button.GetImageToPaint(kRequestedScale).empty()); + EXPECT_EQ(10, button.GetImageToPaint(kRequestedScale).width()); + EXPECT_EQ(20, button.GetImageToPaint(kRequestedScale).height()); // Preferred size is the normal button size. EXPECT_EQ("10x20", button.GetPreferredSize().ToString()); @@ -55,9 +57,9 @@ TEST_F(ImageButtonTest, Basics) { EXPECT_EQ("10x20", button.GetPreferredSize().ToString()); // We're still painting the normal image. - EXPECT_FALSE(button.GetImageToPaint().empty()); - EXPECT_EQ(10, button.GetImageToPaint().width()); - EXPECT_EQ(20, button.GetImageToPaint().height()); + EXPECT_FALSE(button.GetImageToPaint(kRequestedScale).empty()); + EXPECT_EQ(10, button.GetImageToPaint(kRequestedScale).width()); + EXPECT_EQ(20, button.GetImageToPaint(kRequestedScale).height()); // Set an overlay image. gfx::ImageSkia overlay_image = CreateTestImage(12, 22); @@ -70,9 +72,9 @@ TEST_F(ImageButtonTest, Basics) { EXPECT_EQ("10x20", button.GetPreferredSize().ToString()); // We're still painting the normal image. - EXPECT_FALSE(button.GetImageToPaint().empty()); - EXPECT_EQ(10, button.GetImageToPaint().width()); - EXPECT_EQ(20, button.GetImageToPaint().height()); + EXPECT_FALSE(button.GetImageToPaint(kRequestedScale).empty()); + EXPECT_EQ(10, button.GetImageToPaint(kRequestedScale).width()); + EXPECT_EQ(20, button.GetImageToPaint(kRequestedScale).height()); // Reset the overlay image. button.SetOverlayImage(NULL); |