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

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

Issue 10694045: Loading/Creating images for mutiple scale factors on the fly (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: size fix Created 8 years, 5 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
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 <algorithm>
8 #include <cmath>
7 #include <limits> 9 #include <limits>
8 #include <cmath>
9 10
10 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "ui/gfx/image/image_skia_source.h"
11 #include "ui/gfx/size.h" 14 #include "ui/gfx/size.h"
12 #include "ui/gfx/skia_util.h" 15 #include "ui/gfx/skia_util.h"
13 16
14 namespace gfx { 17 namespace gfx {
18 namespace {
19
20 // static
21 gfx::ImageSkiaRep& NullImageRep() {
22 CR_DEFINE_STATIC_LOCAL(ImageSkiaRep, null_image_rep, ());
23 return null_image_rep;
24 }
25
26 } // namespace
15 27
16 namespace internal { 28 namespace internal {
29 namespace {
30
31 class Matcher {
32 public:
33 explicit Matcher(ui::ScaleFactor scale_factor) : scale_factor_(scale_factor) {
34 }
35
36 bool operator()(const ImageSkiaRep& rep) const {
37 return rep.scale_factor() == scale_factor_;
38 }
39
40 private:
41 ui::ScaleFactor scale_factor_;
42 };
43
44 } // namespace
17 45
18 // A helper class such that ImageSkia can be cheaply copied. ImageSkia holds a 46 // 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 47 // refptr instance of ImageSkiaStorage, which in turn holds all of ImageSkia's
20 // information. 48 // information.
21 class ImageSkiaStorage : public base::RefCounted<ImageSkiaStorage> { 49 class ImageSkiaStorage : public base::RefCounted<ImageSkiaStorage> {
22 public: 50 public:
23 ImageSkiaStorage() { 51 ImageSkiaStorage(ImageSkiaSource* source, const gfx::Size& size)
52 : source_(source),
53 size_(size) {
24 } 54 }
25 55
26 std::vector<gfx::ImageSkiaRep>& image_reps() { return image_reps_; } 56 std::vector<gfx::ImageSkiaRep>& image_reps() { return image_reps_; }
27 57
28 void set_size(const gfx::Size& size) { size_ = size; }
29 const gfx::Size& size() const { return size_; } 58 const gfx::Size& size() const { return size_; }
30 59
60 // Returns the iterator of the image rep whose density best matches
61 // |scale_factor|. If the image for the |scale_factor| doesn't exist
62 // in the storage and |storage| is set, it fetches new image by calling
63 // |ImageSkiaSource::GetImageForScale|. If the source returns the
64 // image with different scale factor (if the image doesn't exist in
65 // resource, for example), it will fallback to closest image rep.
66 std::vector<ImageSkiaRep>::iterator FindRepresentation(
67 ui::ScaleFactor scale_factor, bool fetch_new_image) const {
68 ImageSkiaStorage* non_const = const_cast<ImageSkiaStorage*>(this);
69
70 float scale = ui::GetScaleFactorScale(scale_factor);
71 ImageSkia::ImageSkiaReps::iterator closest_iter =
72 non_const->image_reps().end();
73 ImageSkia::ImageSkiaReps::iterator exact_iter =
74 non_const->image_reps().end();
75 float smallest_diff = std::numeric_limits<float>::max();
76 for (ImageSkia::ImageSkiaReps::iterator it =
77 non_const->image_reps().begin();
78 it < image_reps_.end(); ++it) {
79 if (it->GetScale() == scale) {
80 // found exact match
81 fetch_new_image = false;
82 if (it->is_null())
83 continue;
84 exact_iter = it;
85 break;
86 }
87 float diff = std::abs(it->GetScale() - scale);
88 if (diff < smallest_diff && !it->is_null()) {
89 closest_iter = it;
90 smallest_diff = diff;
91 }
92 }
93
94 if (fetch_new_image && source_.get()) {
95 ImageSkiaRep image = source_->GetImageForScale(scale_factor);
96
97 // If the source returned the new image, store it.
98 if (!image.is_null() &&
99 std::find_if(image_reps_.begin(), image_reps_.end(),
100 Matcher(image.scale_factor())) == image_reps_.end()) {
101 non_const->image_reps().push_back(image);
102 }
103
104 // If the result image's scale factor isn't same as the expected
105 // scale factor, create null ImageSkiaRep with the |scale_factor|
106 // so that the next lookup will fallback to the closest scale.
107 if (image.is_null() || image.scale_factor() != scale_factor) {
108 non_const->image_reps().push_back(
109 ImageSkiaRep(SkBitmap(), scale_factor));
110 }
111
112 // image_reps_ must have the exact much now, so find again.
113 return FindRepresentation(scale_factor, false);
114 }
115 return exact_iter != image_reps_.end() ? exact_iter : closest_iter;
116 }
117
31 private: 118 private:
32 ~ImageSkiaStorage() { 119 ~ImageSkiaStorage() {
33 } 120 }
34 121
35 // Vector of bitmaps and their associated scale factor. 122 // Vector of bitmaps and their associated scale factor.
36 std::vector<gfx::ImageSkiaRep> image_reps_; 123 std::vector<gfx::ImageSkiaRep> image_reps_;
37 124
125 scoped_ptr<ImageSkiaSource> source_;
126
38 // Size of the image in DIP. 127 // Size of the image in DIP.
39 gfx::Size size_; 128 const gfx::Size size_;
40 129
41 friend class base::RefCounted<ImageSkiaStorage>; 130 friend class base::RefCounted<ImageSkiaStorage>;
42 }; 131 };
43 132
44 } // internal 133 } // internal
45 134
46 ImageSkia::ImageSkia() : storage_(NULL) { 135 ImageSkia::ImageSkia() : storage_(NULL) {
47 } 136 }
48 137
138 ImageSkia::ImageSkia(ImageSkiaSource* source, const gfx::Size& size)
139 : storage_(new internal::ImageSkiaStorage(source, size)) {
140 DCHECK(source);
141 }
142
49 ImageSkia::ImageSkia(const SkBitmap& bitmap) { 143 ImageSkia::ImageSkia(const SkBitmap& bitmap) {
50 Init(ImageSkiaRep(bitmap)); 144 Init(ImageSkiaRep(bitmap));
51 } 145 }
52 146
53 ImageSkia::ImageSkia(const ImageSkiaRep& image_rep) { 147 ImageSkia::ImageSkia(const ImageSkiaRep& image_rep) {
54 Init(image_rep); 148 Init(image_rep);
55 } 149 }
56 150
57 ImageSkia::ImageSkia(const ImageSkia& other) : storage_(other.storage_) { 151 ImageSkia::ImageSkia(const ImageSkia& other) : storage_(other.storage_) {
58 } 152 }
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
96 Init(image_rep); 190 Init(image_rep);
97 else 191 else
98 storage_->image_reps().push_back(image_rep); 192 storage_->image_reps().push_back(image_rep);
99 } 193 }
100 194
101 void ImageSkia::RemoveRepresentation(ui::ScaleFactor scale_factor) { 195 void ImageSkia::RemoveRepresentation(ui::ScaleFactor scale_factor) {
102 if (isNull()) 196 if (isNull())
103 return; 197 return;
104 198
105 ImageSkiaReps& image_reps = storage_->image_reps(); 199 ImageSkiaReps& image_reps = storage_->image_reps();
106 ImageSkiaReps::iterator it = FindRepresentation(scale_factor); 200 ImageSkiaReps::iterator it =
201 storage_->FindRepresentation(scale_factor, false);
107 if (it != image_reps.end() && it->scale_factor() == scale_factor) 202 if (it != image_reps.end() && it->scale_factor() == scale_factor)
108 image_reps.erase(it); 203 image_reps.erase(it);
109 } 204 }
110 205
111 bool ImageSkia::HasRepresentation(ui::ScaleFactor scale_factor) { 206 bool ImageSkia::HasRepresentation(ui::ScaleFactor scale_factor) {
112 if (isNull()) 207 if (isNull())
113 return false; 208 return false;
114 209
115 ImageSkiaReps::iterator it = FindRepresentation(scale_factor); 210 ImageSkiaReps::iterator it =
211 storage_->FindRepresentation(scale_factor, false);
116 return (it != storage_->image_reps().end() && 212 return (it != storage_->image_reps().end() &&
117 it->scale_factor() == scale_factor); 213 it->scale_factor() == scale_factor);
118 } 214 }
119 215
120 const ImageSkiaRep& ImageSkia::GetRepresentation( 216 const ImageSkiaRep& ImageSkia::GetRepresentation(
121 ui::ScaleFactor scale_factor) const { 217 ui::ScaleFactor scale_factor) const {
122 if (isNull()) 218 if (isNull())
123 return NullImageRep(); 219 return NullImageRep();
124 220
125 ImageSkiaReps::iterator it = FindRepresentation(scale_factor); 221 ImageSkiaReps::iterator it = storage_->FindRepresentation(scale_factor, true);
126 if (it == storage_->image_reps().end()) 222 if (it == storage_->image_reps().end())
127 return NullImageRep(); 223 return NullImageRep();
128 224
129 return *it; 225 return *it;
130 } 226 }
131 227
132 bool ImageSkia::empty() const { 228 bool ImageSkia::empty() const {
133 return isNull() || storage_->size().IsEmpty(); 229 return isNull() || storage_->size().IsEmpty();
134 } 230 }
135 231
136 int ImageSkia::width() const { 232 int ImageSkia::width() const {
137 return isNull() ? 0 : storage_->size().width(); 233 return isNull() ? 0 : storage_->size().width();
138 } 234 }
139 235
236 gfx::Size ImageSkia::size() const {
237 return gfx::Size(width(), height());
238 }
239
140 int ImageSkia::height() const { 240 int ImageSkia::height() const {
141 return isNull() ? 0 : storage_->size().height(); 241 return isNull() ? 0 : storage_->size().height();
142 } 242 }
143 243
144 bool ImageSkia::extractSubset(ImageSkia* dst, const SkIRect& subset) const { 244 bool ImageSkia::extractSubset(ImageSkia* dst, const SkIRect& subset) const {
145 if (isNull()) 245 if (isNull())
146 return false; 246 return false;
147 ImageSkia image; 247 ImageSkia image;
148 ImageSkiaReps& image_reps = storage_->image_reps(); 248 ImageSkiaReps& image_reps = storage_->image_reps();
149 for (ImageSkiaReps::iterator it = image_reps.begin(); 249 for (ImageSkiaReps::iterator it = image_reps.begin();
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
184 284
185 return &storage_->image_reps()[0].sk_bitmap(); 285 return &storage_->image_reps()[0].sk_bitmap();
186 } 286 }
187 287
188 void ImageSkia::Init(const ImageSkiaRep& image_rep) { 288 void ImageSkia::Init(const ImageSkiaRep& image_rep) {
189 // TODO(pkotwicz): The image should be null whenever image rep is null. 289 // TODO(pkotwicz): The image should be null whenever image rep is null.
190 if (image_rep.sk_bitmap().empty()) { 290 if (image_rep.sk_bitmap().empty()) {
191 storage_ = NULL; 291 storage_ = NULL;
192 return; 292 return;
193 } 293 }
194 storage_ = new internal::ImageSkiaStorage(); 294 storage_ = new internal::ImageSkiaStorage(
195 storage_->set_size(gfx::Size(image_rep.GetWidth(), image_rep.GetHeight())); 295 NULL, gfx::Size(image_rep.GetWidth(), image_rep.GetHeight()));
196 storage_->image_reps().push_back(image_rep); 296 storage_->image_reps().push_back(image_rep);
197 } 297 }
198 298
199 // static
200 ImageSkiaRep& ImageSkia::NullImageRep() {
201 CR_DEFINE_STATIC_LOCAL(ImageSkiaRep, null_image_rep, ());
202 return null_image_rep;
203 }
204
205 std::vector<ImageSkiaRep>::iterator ImageSkia::FindRepresentation(
206 ui::ScaleFactor scale_factor) const {
207 DCHECK(!isNull());
208
209 float scale = ui::GetScaleFactorScale(scale_factor);
210 ImageSkiaReps& image_reps = storage_->image_reps();
211 ImageSkiaReps::iterator closest_iter = image_reps.end();
212 float smallest_diff = std::numeric_limits<float>::max();
213 for (ImageSkiaReps::iterator it = image_reps.begin();
214 it < image_reps.end();
215 ++it) {
216 float diff = std::abs(it->GetScale() - scale);
217 if (diff < smallest_diff) {
218 closest_iter = it;
219 smallest_diff = diff;
220 }
221 }
222
223 return closest_iter;
224 }
225
226 } // namespace gfx 299 } // namespace gfx
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698