Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(217)

Side by Side Diff: ui/gfx/image/image_skia.cc

Issue 10245003: Makes ImageSkia more like SkBitmap (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« ui/gfx/image/image_skia.h ('K') | « ui/gfx/image/image_skia.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "ui/gfx/image/image_skia.h" 5 #include "ui/gfx/image/image_skia.h"
6 6
7 #include <limits> 7 #include <limits>
8 #include <cmath> 8 #include <cmath>
9 9
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "ui/gfx/size.h"
11 #include "base/stl_util.h" 12 #include "base/stl_util.h"
12 13
13 namespace gfx { 14 namespace gfx {
14 15
16 namespace internal {
17
18 // A helper class such that ImageSkia can be cheaply copied. ImageSkia holds a
19 // refptr instance of ImageSkiaStorage, which in turn holds all of ImageSkia's
20 // information.
21 class ImageSkiaStorage : public base::RefCounted<ImageSkiaStorage> {
22 public:
23 ImageSkiaStorage() : build_mip_map_(false) {
24 }
25
26 void add_bitmap(const SkBitmap* bitmap) { bitmaps_.push_back(bitmap); }
27 void set_bitmaps(const std::vector<const SkBitmap*>& bitmaps) {
28 bitmaps_ = bitmaps;
29 }
30 const std::vector<const SkBitmap*>& bitmaps() const { return bitmaps_; }
31
32 void set_size(gfx::Size size) { size_ = size; }
33 gfx::Size size() const { return size_; }
34
35 void set_build_mip_map() { build_mip_map_ = true; }
36 bool build_mip_map() const { return build_mip_map_; }
37
38 private:
39 ~ImageSkiaStorage() {
40 STLDeleteElements(&bitmaps_);
41 }
42
43 std::vector<const SkBitmap*> bitmaps_;
sky 2012/04/27 23:33:58 Why does this need to be pointers? It would be a l
pkotwicz 2012/04/30 20:27:07 I think this needs to be pointers as long as we ha
sky 2012/04/30 21:03:32 Is the long term plan to get rid of ToSkBitmap? If
44 gfx::Size size_;
sky 2012/04/27 23:33:58 Document what this is.
45 bool build_mip_map_;
sky 2012/04/27 23:33:58 Shouldn't the mip-map be per-image?
46
47 friend class base::RefCounted<ImageSkiaStorage>;
48 };
49
50 } // internal
51
52 ImageSkia::ImageSkia() : storage_(NULL) {
53 }
54
55 ImageSkia::ImageSkia(const SkBitmap& bitmap)
56 : storage_(new internal::ImageSkiaStorage()) {
57 storage_->set_size(gfx::Size(bitmap.width(), bitmap.height()));
58 // TODO(pkotwicz): Add a CHECK to ensure that !bitmap.isNull()
59 storage_->add_bitmap(new SkBitmap(bitmap));
60 }
61
62 ImageSkia::ImageSkia(const SkBitmap& bitmap, float scale_factor)
63 : storage_(new internal::ImageSkiaStorage()) {
64 storage_->set_size(gfx::Size(
65 static_cast<int>(bitmap.width() / scale_factor),
66 static_cast<int>(bitmap.height() / scale_factor)));
67 // TODO(pkotwicz): Add a CHECK to ensure that !bitmap.isNull()
68 storage_->add_bitmap(new SkBitmap(bitmap));
69 }
70
15 ImageSkia::ImageSkia(const SkBitmap* bitmap) 71 ImageSkia::ImageSkia(const SkBitmap* bitmap)
16 : size_(bitmap->width(), bitmap->height()), 72 : storage_(new internal::ImageSkiaStorage()) {
17 mip_map_build_pending_(false) { 73 storage_->set_size(gfx::Size(bitmap->width(), bitmap->height()));
18 CHECK(bitmap); 74 // TODO(pkotwicz): Add a CHECK to ensure that !bitmap.isNull()
19 // TODO(pkotwicz): Add a CHECK to ensure that !bitmap->isNull() 75 storage_->add_bitmap(bitmap);
20 bitmaps_.push_back(bitmap);
21 } 76 }
22 77
23 ImageSkia::ImageSkia(const std::vector<const SkBitmap*>& bitmaps) 78 ImageSkia::ImageSkia(const std::vector<const SkBitmap*>& bitmaps)
24 : bitmaps_(bitmaps), 79 : storage_(new internal::ImageSkiaStorage()) {
25 mip_map_build_pending_(false) { 80 storage_->set_bitmaps(bitmaps);
26 CHECK(!bitmaps_.empty());
27 // TODO(pkotwicz): Add a CHECK to ensure that !bitmap->isNull() for each 81 // TODO(pkotwicz): Add a CHECK to ensure that !bitmap->isNull() for each
28 // vector element. 82 // vector element.
29 // Assume that the smallest bitmap represents 1x scale factor. 83 // Assume that the smallest bitmap represents 1x scale factor.
30 for (size_t i = 0; i < bitmaps_.size(); ++i) { 84 gfx::Size smallest_bitmap_size;
31 gfx::Size bitmap_size(bitmaps_[i]->width(), bitmaps_[i]->height()); 85 for (size_t i = 0; i < bitmaps.size(); ++i) {
32 if (size_.IsEmpty() || bitmap_size.GetArea() < size_.GetArea()) 86 gfx::Size bitmap_size(bitmaps[i]->width(), bitmaps[i]->height());
33 size_ = bitmap_size; 87 if (smallest_bitmap_size.IsEmpty() ||
88 bitmap_size.GetArea() < smallest_bitmap_size.GetArea())
89 smallest_bitmap_size = bitmap_size;
34 } 90 }
91 storage_->set_size(smallest_bitmap_size);
92 }
93
94 ImageSkia::ImageSkia(const ImageSkia& other) : storage_(other.storage_) {
95 }
96
97 ImageSkia& ImageSkia::operator=(const ImageSkia& other) {
98 storage_ = other.storage_;
99 return *this;
100 }
101
102 ImageSkia& ImageSkia::operator=(const SkBitmap& other) {
103 storage_ = new internal::ImageSkiaStorage();
104 storage_->set_size(gfx::Size(other.width(), other.height()));
105 // TODO(pkotwicz): Add a CHECK to ensure that !other.isNull()
106 storage_->add_bitmap(new SkBitmap(other));
107 return *this;
108 }
109
110 ImageSkia::operator SkBitmap() const {
111 return isNull() ? SkBitmap() : *bitmaps()[0];
35 } 112 }
36 113
37 ImageSkia::~ImageSkia() { 114 ImageSkia::~ImageSkia() {
38 STLDeleteElements(&bitmaps_);
39 }
40
41 void ImageSkia::BuildMipMap() {
42 mip_map_build_pending_ = true;
43 }
44
45 void ImageSkia::DrawToCanvasInt(gfx::Canvas* canvas, int x, int y) {
46 SkPaint p;
47 DrawToCanvasInt(canvas, x, y, p);
48 }
49
50 void ImageSkia::DrawToCanvasInt(gfx::Canvas* canvas,
51 int x, int y,
52 const SkPaint& paint) {
53
54 if (IsZeroSized())
55 return;
56
57 SkMatrix m = canvas->sk_canvas()->getTotalMatrix();
58 float scale_x = std::abs(SkScalarToFloat(m.getScaleX()));
59 float scale_y = std::abs(SkScalarToFloat(m.getScaleY()));
60
61 const SkBitmap* bitmap = GetBitmapForScale(scale_x, scale_y);
62
63 if (mip_map_build_pending_) {
64 const_cast<SkBitmap*>(bitmap)->buildMipMap();
65 mip_map_build_pending_ = false;
66 }
67
68 float bitmap_scale_x = static_cast<float>(bitmap->width()) / width();
69 float bitmap_scale_y = static_cast<float>(bitmap->height()) / height();
70
71 canvas->Save();
72 canvas->sk_canvas()->scale(1.0f / bitmap_scale_x,
73 1.0f / bitmap_scale_y);
74 canvas->sk_canvas()->drawBitmap(*bitmap, SkFloatToScalar(x * bitmap_scale_x),
75 SkFloatToScalar(y * bitmap_scale_y));
76 canvas->Restore();
77 }
78
79 void ImageSkia::DrawToCanvasInt(gfx::Canvas* canvas,
80 int src_x, int src_y, int src_w, int src_h,
81 int dest_x, int dest_y, int dest_w, int dest_h,
82 bool filter) {
83 SkPaint p;
84 DrawToCanvasInt(canvas, src_x, src_y, src_w, src_h, dest_x, dest_y,
85 dest_w, dest_h, filter, p);
86 }
87
88 void ImageSkia::DrawToCanvasInt(gfx::Canvas* canvas,
89 int src_x, int src_y, int src_w, int src_h,
90 int dest_x, int dest_y, int dest_w, int dest_h,
91 bool filter,
92 const SkPaint& paint) {
93 if (IsZeroSized())
94 return;
95
96 SkMatrix m = canvas->sk_canvas()->getTotalMatrix();
97 float scale_x = std::abs(SkScalarToFloat(m.getScaleX()));
98 float scale_y = std::abs(SkScalarToFloat(m.getScaleY()));
99
100 const SkBitmap* bitmap = GetBitmapForScale(scale_x, scale_y);
101
102 if (mip_map_build_pending_) {
103 const_cast<SkBitmap*>(bitmap)->buildMipMap();
104 mip_map_build_pending_ = false;
105 }
106
107 float bitmap_scale_x = static_cast<float>(bitmap->width()) / width();
108 float bitmap_scale_y = static_cast<float>(bitmap->height()) / height();
109
110 canvas->Save();
111 canvas->sk_canvas()->scale(1.0f / bitmap_scale_x,
112 1.0f / bitmap_scale_y);
113 canvas->DrawBitmapFloat(*bitmap,
114 src_x * bitmap_scale_x, src_y * bitmap_scale_x,
115 src_w * bitmap_scale_x, src_h * bitmap_scale_y,
116 dest_x * bitmap_scale_x, dest_y * bitmap_scale_y,
117 dest_w * bitmap_scale_x, dest_h * bitmap_scale_y,
118 filter, paint);
119
120 canvas->Restore();
121 } 115 }
122 116
123 const SkBitmap* ImageSkia::GetBitmapForScale(float x_scale_factor, 117 const SkBitmap* ImageSkia::GetBitmapForScale(float x_scale_factor,
124 float y_scale_factor) const { 118 float y_scale_factor) const {
119 if (isNull())
120 return NULL;
121
125 // Get the desired bitmap width and height given |x_scale_factor|, 122 // Get the desired bitmap width and height given |x_scale_factor|,
126 // |y_scale_factor| and |size_| at 1x density. 123 // |y_scale_factor| and size at 1x density.
127 float desired_width = size_.width() * x_scale_factor; 124 float desired_width = width() * x_scale_factor;
128 float desired_height = size_.height() * y_scale_factor; 125 float desired_height = height() * y_scale_factor;
129 126
130 size_t closest_index = 0; 127 const std::vector<const SkBitmap*>& bitmaps = storage_->bitmaps();
128 size_t closest_index = -1;
131 float smallest_diff = std::numeric_limits<float>::max(); 129 float smallest_diff = std::numeric_limits<float>::max();
132 for (size_t i = 0; i < bitmaps_.size(); ++i) { 130 for (size_t i = 0; i < bitmaps.size(); ++i) {
133 if (bitmaps_[i]->isNull()) 131 if (bitmaps[i]->isNull())
sky 2012/04/27 23:33:58 Is there a reason to allow null/empty images into
pkotwicz 2012/04/30 20:27:07 Changed semantics such that if bitmap->isNull(), t
134 continue; 132 continue;
135 133
136 float diff = std::abs(bitmaps_[i]->width() - desired_width) + 134 float diff = std::abs(bitmaps[i]->width() - desired_width) +
137 std::abs(bitmaps_[i]->height() - desired_height); 135 std::abs(bitmaps[i]->height() - desired_height);
138 if (diff < smallest_diff) { 136 if (diff < smallest_diff) {
139 closest_index = i; 137 closest_index = i;
140 smallest_diff = diff; 138 smallest_diff = diff;
141 } 139 }
142 } 140 }
143 return bitmaps_[closest_index]; 141 return closest_index < 0 ? NULL : bitmaps[closest_index];
142 }
143
144 bool ImageSkia::empty() const {
145 return isNull() || storage_->size().IsEmpty();
146 }
147
148 int ImageSkia::width() const {
149 return isNull() ? 0 : storage_->size().width();
150 }
151
152 int ImageSkia::height() const {
153 return isNull() ? 0 : storage_->size().height();
154 }
155
156 bool ImageSkia::extractSubset(ImageSkia* dst, SkIRect& subset) const {
157 if (isNull())
158 return false;
159 SkBitmap dst_bitmap;
160 bool return_value = bitmaps()[0]->extractSubset(&dst_bitmap, subset);
161 *dst = ImageSkia(dst_bitmap);
162 return return_value;
163 }
164
165 void ImageSkia::BuildMipMap() {
166 if (isNull())
167 return;
168
169 storage_->set_build_mip_map();
170 // |build_mip_map_| does not need to be turned off as SkBitmap will not
171 // regenerate a mipmap if one exists.
172 }
173
174 bool ImageSkia::ShouldBuildMipMap() const {
175 return storage_->build_mip_map();
176 }
177
178 const std::vector<const SkBitmap*>& ImageSkia::bitmaps() const {
179 return storage_->bitmaps();
144 } 180 }
145 181
146 } // namespace gfx 182 } // namespace gfx
OLDNEW
« ui/gfx/image/image_skia.h ('K') | « ui/gfx/image/image_skia.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698