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

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

Issue 10820049: Load 2x resources on demand (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: CHECK -> DCHECK Created 8 years, 4 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> 7 #include <algorithm>
8 #include <cmath> 8 #include <cmath>
9 #include <limits> 9 #include <limits>
10 10
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/memory/scoped_ptr.h" 12 #include "base/memory/scoped_ptr.h"
13 #include "base/threading/non_thread_safe.h"
13 #include "ui/gfx/image/image_skia_operations.h" 14 #include "ui/gfx/image/image_skia_operations.h"
14 #include "ui/gfx/image/image_skia_source.h" 15 #include "ui/gfx/image/image_skia_source.h"
15 #include "ui/gfx/rect.h" 16 #include "ui/gfx/rect.h"
16 #include "ui/gfx/size.h" 17 #include "ui/gfx/size.h"
17 #include "ui/gfx/skia_util.h" 18 #include "ui/gfx/skia_util.h"
18 19
19 namespace gfx { 20 namespace gfx {
20 namespace { 21 namespace {
21 22
22 // static 23 // static
(...skipping 18 matching lines...) Expand all
41 42
42 private: 43 private:
43 ui::ScaleFactor scale_factor_; 44 ui::ScaleFactor scale_factor_;
44 }; 45 };
45 46
46 } // namespace 47 } // namespace
47 48
48 // A helper class such that ImageSkia can be cheaply copied. ImageSkia holds a 49 // A helper class such that ImageSkia can be cheaply copied. ImageSkia holds a
49 // refptr instance of ImageSkiaStorage, which in turn holds all of ImageSkia's 50 // refptr instance of ImageSkiaStorage, which in turn holds all of ImageSkia's
50 // information. 51 // information.
51 class ImageSkiaStorage : public base::RefCounted<ImageSkiaStorage> { 52 class ImageSkiaStorage : public base::RefCounted<ImageSkiaStorage>,
53 public base::NonThreadSafe {
52 public: 54 public:
53 ImageSkiaStorage(ImageSkiaSource* source, const gfx::Size& size) 55 ImageSkiaStorage(ImageSkiaSource* source, const gfx::Size& size)
54 : source_(source), 56 : source_(source),
55 size_(size) { 57 size_(size) {
58 // We only care if the storage is modified by the same thread.
59 // Don't blow up even if someone else created/deleted the ImageSkia.
60 DetachFromThread();
56 } 61 }
57 62
58 bool has_source() const { return source_.get() != NULL; } 63 bool has_source() const { return source_.get() != NULL; }
59 64
60 std::vector<gfx::ImageSkiaRep>& image_reps() { return image_reps_; } 65 std::vector<gfx::ImageSkiaRep>& image_reps() { return image_reps_; }
61 66
62 const gfx::Size& size() const { return size_; } 67 const gfx::Size& size() const { return size_; }
63 68
69 void DeleteSource() {
70 source_.reset();
71 }
72
64 // Returns the iterator of the image rep whose density best matches 73 // Returns the iterator of the image rep whose density best matches
65 // |scale_factor|. If the image for the |scale_factor| doesn't exist 74 // |scale_factor|. If the image for the |scale_factor| doesn't exist
66 // in the storage and |storage| is set, it fetches new image by calling 75 // in the storage and |storage| is set, it fetches new image by calling
67 // |ImageSkiaSource::GetImageForScale|. If the source returns the 76 // |ImageSkiaSource::GetImageForScale|. If the source returns the
68 // image with different scale factor (if the image doesn't exist in 77 // image with different scale factor (if the image doesn't exist in
69 // resource, for example), it will fallback to closest image rep. 78 // resource, for example), it will fallback to closest image rep.
70 std::vector<ImageSkiaRep>::iterator FindRepresentation( 79 std::vector<ImageSkiaRep>::iterator FindRepresentation(
71 ui::ScaleFactor scale_factor, bool fetch_new_image) const { 80 ui::ScaleFactor scale_factor, bool fetch_new_image) const {
72 ImageSkiaStorage* non_const = const_cast<ImageSkiaStorage*>(this); 81 ImageSkiaStorage* non_const = const_cast<ImageSkiaStorage*>(this);
73 82
(...skipping 15 matching lines...) Expand all
89 break; 98 break;
90 } 99 }
91 float diff = std::abs(it->GetScale() - scale); 100 float diff = std::abs(it->GetScale() - scale);
92 if (diff < smallest_diff && !it->is_null()) { 101 if (diff < smallest_diff && !it->is_null()) {
93 closest_iter = it; 102 closest_iter = it;
94 smallest_diff = diff; 103 smallest_diff = diff;
95 } 104 }
96 } 105 }
97 106
98 if (fetch_new_image && source_.get()) { 107 if (fetch_new_image && source_.get()) {
108 DCHECK(CalledOnValidThread()) <<
109 "An ImageSkia with an ImageSkiaSource is accessed "
110 "by more than one thread.";
111
99 ImageSkiaRep image = source_->GetImageForScale(scale_factor); 112 ImageSkiaRep image = source_->GetImageForScale(scale_factor);
100 113
101 // If the source returned the new image, store it. 114 // If the source returned the new image, store it.
102 if (!image.is_null() && 115 if (!image.is_null() &&
103 std::find_if(image_reps_.begin(), image_reps_.end(), 116 std::find_if(image_reps_.begin(), image_reps_.end(),
104 Matcher(image.scale_factor())) == image_reps_.end()) { 117 Matcher(image.scale_factor())) == image_reps_.end()) {
105 non_const->image_reps().push_back(image); 118 non_const->image_reps().push_back(image);
106 } 119 }
107 120
108 // If the result image's scale factor isn't same as the expected 121 // If the result image's scale factor isn't same as the expected
109 // scale factor, create null ImageSkiaRep with the |scale_factor| 122 // scale factor, create null ImageSkiaRep with the |scale_factor|
110 // so that the next lookup will fallback to the closest scale. 123 // so that the next lookup will fallback to the closest scale.
111 if (image.is_null() || image.scale_factor() != scale_factor) { 124 if (image.is_null() || image.scale_factor() != scale_factor) {
112 non_const->image_reps().push_back( 125 non_const->image_reps().push_back(
113 ImageSkiaRep(SkBitmap(), scale_factor)); 126 ImageSkiaRep(SkBitmap(), scale_factor));
114 } 127 }
115 128
116 // image_reps_ must have the exact much now, so find again. 129 // image_reps_ must have the exact much now, so find again.
117 return FindRepresentation(scale_factor, false); 130 return FindRepresentation(scale_factor, false);
118 } 131 }
119 return exact_iter != image_reps_.end() ? exact_iter : closest_iter; 132 return exact_iter != image_reps_.end() ? exact_iter : closest_iter;
120 } 133 }
121 134
122 private: 135 private:
123 ~ImageSkiaStorage() { 136 virtual ~ImageSkiaStorage() {
137 DetachFromThread();
124 } 138 }
125 139
126 // Vector of bitmaps and their associated scale factor. 140 // Vector of bitmaps and their associated scale factor.
127 std::vector<gfx::ImageSkiaRep> image_reps_; 141 std::vector<gfx::ImageSkiaRep> image_reps_;
128 142
129 scoped_ptr<ImageSkiaSource> source_; 143 scoped_ptr<ImageSkiaSource> source_;
130 144
131 // Size of the image in DIP. 145 // Size of the image in DIP.
132 const gfx::Size size_; 146 const gfx::Size size_;
133 147
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
168 ImageSkia::~ImageSkia() { 182 ImageSkia::~ImageSkia() {
169 } 183 }
170 184
171 bool ImageSkia::BackedBySameObjectAs(const gfx::ImageSkia& other) const { 185 bool ImageSkia::BackedBySameObjectAs(const gfx::ImageSkia& other) const {
172 return storage_.get() == other.storage_.get(); 186 return storage_.get() == other.storage_.get();
173 } 187 }
174 188
175 void ImageSkia::AddRepresentation(const ImageSkiaRep& image_rep) { 189 void ImageSkia::AddRepresentation(const ImageSkiaRep& image_rep) {
176 DCHECK(!image_rep.is_null()); 190 DCHECK(!image_rep.is_null());
177 191
192 // TODO(oshima): This method should be called |SetRepresentation|
193 // and replace the existing rep if there is already one with the
194 // same scale factor so that we can guarantee that a ImageSkia
195 // instance contians only one image rep per scale factor. This is
196 // not possible now as ImageLoadingTracker currently stores need
197 // this feature, but this needs to be fixed.
198
178 if (isNull()) 199 if (isNull())
179 Init(image_rep); 200 Init(image_rep);
180 else 201 else
181 storage_->image_reps().push_back(image_rep); 202 storage_->image_reps().push_back(image_rep);
182 } 203 }
183 204
184 void ImageSkia::RemoveRepresentation(ui::ScaleFactor scale_factor) { 205 void ImageSkia::RemoveRepresentation(ui::ScaleFactor scale_factor) {
185 if (isNull()) 206 if (isNull())
186 return; 207 return;
187 208
(...skipping 27 matching lines...) Expand all
215 } 236 }
216 237
217 #if defined(OS_MACOSX) 238 #if defined(OS_MACOSX)
218 239
219 std::vector<ImageSkiaRep> ImageSkia::GetRepresentations() const { 240 std::vector<ImageSkiaRep> ImageSkia::GetRepresentations() const {
220 if (isNull()) 241 if (isNull())
221 return std::vector<ImageSkiaRep>(); 242 return std::vector<ImageSkiaRep>();
222 243
223 if (!storage_->has_source()) 244 if (!storage_->has_source())
224 return image_reps(); 245 return image_reps();
225 246 EnsureRepsForSupportedScaleFactors();
226 // Attempt to generate image reps for as many scale factors supported by
227 // this platform as possible.
228 // Do not build return array here because the mapping from scale factor to
229 // image rep is one to many in some cases.
230 std::vector<ui::ScaleFactor> supported_scale_factors =
231 ui::GetSupportedScaleFactors();
232 for (size_t i = 0; i < supported_scale_factors.size(); ++i)
233 storage_->FindRepresentation(supported_scale_factors[i], true);
234 247
235 return image_reps(); 248 return image_reps();
236 } 249 }
237 250
238 #endif // OS_MACOSX 251 #endif // OS_MACOSX
239 252
240 int ImageSkia::width() const { 253 int ImageSkia::width() const {
241 return isNull() ? 0 : storage_->size().width(); 254 return isNull() ? 0 : storage_->size().width();
242 } 255 }
243 256
(...skipping 15 matching lines...) Expand all
259 ImageSkiaReps image_reps; 272 ImageSkiaReps image_reps;
260 for (ImageSkiaReps::iterator it = internal_image_reps.begin(); 273 for (ImageSkiaReps::iterator it = internal_image_reps.begin();
261 it != internal_image_reps.end(); ++it) { 274 it != internal_image_reps.end(); ++it) {
262 if (!it->is_null()) 275 if (!it->is_null())
263 image_reps.push_back(*it); 276 image_reps.push_back(*it);
264 } 277 }
265 278
266 return image_reps; 279 return image_reps;
267 } 280 }
268 281
282 void ImageSkia::DeleteSource() {
283 if (storage_)
284 storage_->DeleteSource();
285 }
286
287 void ImageSkia::EnsureRepsForSupportedScaleFactors() const {
288 if (storage_ && storage_->has_source()) {
289 std::vector<ui::ScaleFactor> supported_scale_factors =
290 ui::GetSupportedScaleFactors();
291 for (size_t i = 0; i < supported_scale_factors.size(); ++i)
292 storage_->FindRepresentation(supported_scale_factors[i], true);
293 }
294 }
295
269 void ImageSkia::Init(const ImageSkiaRep& image_rep) { 296 void ImageSkia::Init(const ImageSkiaRep& image_rep) {
270 // TODO(pkotwicz): The image should be null whenever image rep is null. 297 // TODO(pkotwicz): The image should be null whenever image rep is null.
271 if (image_rep.sk_bitmap().empty()) { 298 if (image_rep.sk_bitmap().empty()) {
272 storage_ = NULL; 299 storage_ = NULL;
273 return; 300 return;
274 } 301 }
275 storage_ = new internal::ImageSkiaStorage( 302 storage_ = new internal::ImageSkiaStorage(
276 NULL, gfx::Size(image_rep.GetWidth(), image_rep.GetHeight())); 303 NULL, gfx::Size(image_rep.GetWidth(), image_rep.GetHeight()));
277 storage_->image_reps().push_back(image_rep); 304 storage_->image_reps().push_back(image_rep);
278 } 305 }
279 306
280 SkBitmap& ImageSkia::GetBitmap() const { 307 SkBitmap& ImageSkia::GetBitmap() const {
281 if (isNull()) { 308 if (isNull()) {
282 // Callers expect a ImageSkiaRep even if it is |isNull()|. 309 // Callers expect a ImageSkiaRep even if it is |isNull()|.
283 // TODO(pkotwicz): Fix this. 310 // TODO(pkotwicz): Fix this.
284 return NullImageRep().mutable_sk_bitmap(); 311 return NullImageRep().mutable_sk_bitmap();
285 } 312 }
286 313
287 ImageSkiaReps::iterator it = 314 ImageSkiaReps::iterator it =
288 storage_->FindRepresentation(ui::SCALE_FACTOR_100P, true); 315 storage_->FindRepresentation(ui::SCALE_FACTOR_100P, true);
289 if (it != storage_->image_reps().end()) 316 if (it != storage_->image_reps().end())
290 return it->mutable_sk_bitmap(); 317 return it->mutable_sk_bitmap();
291 return NullImageRep().mutable_sk_bitmap(); 318 return NullImageRep().mutable_sk_bitmap();
292 } 319 }
293 320
294 } // namespace gfx 321 } // namespace gfx
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698