BookmarkManager: Fix 'new folder text field size changes on clicking it' issue.
[chromium-blink-merge.git] / components / wallpaper / wallpaper_resizer.cc
blob7de7a26fdc3eb32168f7d72a766350fa6af0fc21
1 // Copyright (c) 2013 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.
5 #include "components/wallpaper/wallpaper_resizer.h"
7 #include "base/bind.h"
8 #include "base/location.h"
9 #include "base/logging.h"
10 #include "base/threading/sequenced_worker_pool.h"
11 #include "base/threading/worker_pool.h"
12 #include "components/wallpaper/wallpaper_resizer_observer.h"
13 #include "third_party/skia/include/core/SkImage.h"
14 #include "ui/gfx/image/image_skia_rep.h"
15 #include "ui/gfx/skia_util.h"
17 using base::SequencedWorkerPool;
19 namespace wallpaper {
20 namespace {
22 // For our scaling ratios we need to round positive numbers.
23 int RoundPositive(double x) {
24 return static_cast<int>(floor(x + 0.5));
27 // Resizes |orig_bitmap| to |target_size| using |layout| and stores the
28 // resulting bitmap at |resized_bitmap_out|.
29 void Resize(SkBitmap orig_bitmap,
30 const gfx::Size& target_size,
31 WallpaperLayout layout,
32 SkBitmap* resized_bitmap_out,
33 SequencedWorkerPool* worker_pool) {
34 DCHECK(worker_pool->RunsTasksOnCurrentThread());
35 SkBitmap new_bitmap = orig_bitmap;
37 const int orig_width = orig_bitmap.width();
38 const int orig_height = orig_bitmap.height();
39 const int new_width = target_size.width();
40 const int new_height = target_size.height();
42 if (orig_width > new_width || orig_height > new_height) {
43 gfx::Rect wallpaper_rect(0, 0, orig_width, orig_height);
44 gfx::Size cropped_size = gfx::Size(std::min(new_width, orig_width),
45 std::min(new_height, orig_height));
46 switch (layout) {
47 case WALLPAPER_LAYOUT_CENTER:
48 wallpaper_rect.ClampToCenteredSize(cropped_size);
49 orig_bitmap.extractSubset(&new_bitmap,
50 gfx::RectToSkIRect(wallpaper_rect));
51 break;
52 case WALLPAPER_LAYOUT_TILE:
53 wallpaper_rect.set_size(cropped_size);
54 orig_bitmap.extractSubset(&new_bitmap,
55 gfx::RectToSkIRect(wallpaper_rect));
56 break;
57 case WALLPAPER_LAYOUT_STRETCH:
58 new_bitmap = skia::ImageOperations::Resize(
59 orig_bitmap, skia::ImageOperations::RESIZE_LANCZOS3, new_width,
60 new_height);
61 break;
62 case WALLPAPER_LAYOUT_CENTER_CROPPED:
63 if (orig_width > new_width && orig_height > new_height) {
64 // The dimension with the smallest ratio must be cropped, the other
65 // one is preserved. Both are set in gfx::Size cropped_size.
66 double horizontal_ratio =
67 static_cast<double>(new_width) / static_cast<double>(orig_width);
68 double vertical_ratio = static_cast<double>(new_height) /
69 static_cast<double>(orig_height);
71 if (vertical_ratio > horizontal_ratio) {
72 cropped_size = gfx::Size(
73 RoundPositive(static_cast<double>(new_width) / vertical_ratio),
74 orig_height);
75 } else {
76 cropped_size = gfx::Size(
77 orig_width, RoundPositive(static_cast<double>(new_height) /
78 horizontal_ratio));
80 wallpaper_rect.ClampToCenteredSize(cropped_size);
81 SkBitmap sub_image;
82 orig_bitmap.extractSubset(&sub_image,
83 gfx::RectToSkIRect(wallpaper_rect));
84 new_bitmap = skia::ImageOperations::Resize(
85 sub_image, skia::ImageOperations::RESIZE_LANCZOS3, new_width,
86 new_height);
88 break;
89 case NUM_WALLPAPER_LAYOUT:
90 NOTREACHED();
91 break;
95 *resized_bitmap_out = new_bitmap;
96 resized_bitmap_out->setImmutable();
99 } // namespace
101 // static
102 uint32_t WallpaperResizer::GetImageId(const gfx::ImageSkia& image) {
103 const gfx::ImageSkiaRep& image_rep = image.GetRepresentation(1.0f);
104 return image_rep.is_null() ? 0 : image_rep.sk_bitmap().getGenerationID();
107 WallpaperResizer::WallpaperResizer(const gfx::ImageSkia& image,
108 const gfx::Size& target_size,
109 WallpaperLayout layout,
110 base::SequencedWorkerPool* worker_pool_ptr)
111 : image_(image),
112 original_image_id_(GetImageId(image_)),
113 target_size_(target_size),
114 layout_(layout),
115 worker_pool_(worker_pool_ptr),
116 weak_ptr_factory_(this) {
117 image_.MakeThreadSafe();
120 WallpaperResizer::~WallpaperResizer() {
123 void WallpaperResizer::StartResize() {
124 SkBitmap* resized_bitmap = new SkBitmap;
125 scoped_refptr<SequencedWorkerPool> worker_pool_refptr(worker_pool_);
126 if (!worker_pool_->PostTaskAndReply(
127 FROM_HERE, base::Bind(&Resize, *image_.bitmap(), target_size_,
128 layout_, resized_bitmap, worker_pool_refptr),
129 base::Bind(&WallpaperResizer::OnResizeFinished,
130 weak_ptr_factory_.GetWeakPtr(),
131 base::Owned(resized_bitmap)))) {
132 LOG(WARNING) << "PostSequencedWorkerTask failed. "
133 << "Wallpaper may not be resized.";
137 void WallpaperResizer::AddObserver(WallpaperResizerObserver* observer) {
138 observers_.AddObserver(observer);
141 void WallpaperResizer::RemoveObserver(WallpaperResizerObserver* observer) {
142 observers_.RemoveObserver(observer);
145 void WallpaperResizer::OnResizeFinished(SkBitmap* resized_bitmap) {
146 image_ = gfx::ImageSkia::CreateFrom1xBitmap(*resized_bitmap);
147 FOR_EACH_OBSERVER(WallpaperResizerObserver, observers_, OnWallpaperResized());
150 } // namespace wallpaper