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

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: . 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 base::NonThreadSafe::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 // A public method to call base::NonThreadSafeImpl::DetachFromThread
70 // which is protected. See base/threading/non_thread_safe_impl.h
71 // for more details.
72 void DetachFromThread() {
73 base::NonThreadSafe::DetachFromThread();
74 }
75
76 void DeleteSource() {
77 source_.reset();
78 }
79
64 // Returns the iterator of the image rep whose density best matches 80 // Returns the iterator of the image rep whose density best matches
65 // |scale_factor|. If the image for the |scale_factor| doesn't exist 81 // |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 82 // in the storage and |storage| is set, it fetches new image by calling
67 // |ImageSkiaSource::GetImageForScale|. If the source returns the 83 // |ImageSkiaSource::GetImageForScale|. If the source returns the
68 // image with different scale factor (if the image doesn't exist in 84 // image with different scale factor (if the image doesn't exist in
69 // resource, for example), it will fallback to closest image rep. 85 // resource, for example), it will fallback to closest image rep.
70 std::vector<ImageSkiaRep>::iterator FindRepresentation( 86 std::vector<ImageSkiaRep>::iterator FindRepresentation(
71 ui::ScaleFactor scale_factor, bool fetch_new_image) const { 87 ui::ScaleFactor scale_factor, bool fetch_new_image) const {
72 ImageSkiaStorage* non_const = const_cast<ImageSkiaStorage*>(this); 88 ImageSkiaStorage* non_const = const_cast<ImageSkiaStorage*>(this);
73 89
(...skipping 15 matching lines...) Expand all
89 break; 105 break;
90 } 106 }
91 float diff = std::abs(it->GetScale() - scale); 107 float diff = std::abs(it->GetScale() - scale);
92 if (diff < smallest_diff && !it->is_null()) { 108 if (diff < smallest_diff && !it->is_null()) {
93 closest_iter = it; 109 closest_iter = it;
94 smallest_diff = diff; 110 smallest_diff = diff;
95 } 111 }
96 } 112 }
97 113
98 if (fetch_new_image && source_.get()) { 114 if (fetch_new_image && source_.get()) {
115 DCHECK(CalledOnValidThread()) <<
116 "More than one thread is tring to access ImageSkia which has "
117 "ImageSkiaSource. This is thread unsafe operation and not allowed";
118
99 ImageSkiaRep image = source_->GetImageForScale(scale_factor); 119 ImageSkiaRep image = source_->GetImageForScale(scale_factor);
100 120
101 // If the source returned the new image, store it. 121 // If the source returned the new image, store it.
102 if (!image.is_null() && 122 if (!image.is_null() &&
103 std::find_if(image_reps_.begin(), image_reps_.end(), 123 std::find_if(image_reps_.begin(), image_reps_.end(),
104 Matcher(image.scale_factor())) == image_reps_.end()) { 124 Matcher(image.scale_factor())) == image_reps_.end()) {
105 non_const->image_reps().push_back(image); 125 non_const->image_reps().push_back(image);
106 } 126 }
107 127
108 // If the result image's scale factor isn't same as the expected 128 // If the result image's scale factor isn't same as the expected
109 // scale factor, create null ImageSkiaRep with the |scale_factor| 129 // scale factor, create null ImageSkiaRep with the |scale_factor|
110 // so that the next lookup will fallback to the closest scale. 130 // so that the next lookup will fallback to the closest scale.
111 if (image.is_null() || image.scale_factor() != scale_factor) { 131 if (image.is_null() || image.scale_factor() != scale_factor) {
112 non_const->image_reps().push_back( 132 non_const->image_reps().push_back(
113 ImageSkiaRep(SkBitmap(), scale_factor)); 133 ImageSkiaRep(SkBitmap(), scale_factor));
114 } 134 }
115 135
116 // image_reps_ must have the exact much now, so find again. 136 // image_reps_ must have the exact much now, so find again.
117 return FindRepresentation(scale_factor, false); 137 return FindRepresentation(scale_factor, false);
118 } 138 }
119 return exact_iter != image_reps_.end() ? exact_iter : closest_iter; 139 return exact_iter != image_reps_.end() ? exact_iter : closest_iter;
120 } 140 }
121 141
122 private: 142 private:
123 ~ImageSkiaStorage() { 143 virtual ~ImageSkiaStorage() {
144 DetachFromThread();
124 } 145 }
125 146
126 // Vector of bitmaps and their associated scale factor. 147 // Vector of bitmaps and their associated scale factor.
127 std::vector<gfx::ImageSkiaRep> image_reps_; 148 std::vector<gfx::ImageSkiaRep> image_reps_;
128 149
129 scoped_ptr<ImageSkiaSource> source_; 150 scoped_ptr<ImageSkiaSource> source_;
130 151
131 // Size of the image in DIP. 152 // Size of the image in DIP.
132 const gfx::Size size_; 153 const gfx::Size size_;
133 154
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
226 // Attempt to generate image reps for as many scale factors supported by 247 EnsureRepsForSupportedScaleFactors();
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 248
235 return image_reps(); 249 return image_reps();
236 } 250 }
237 251
238 #endif // OS_MACOSX 252 #endif // OS_MACOSX
239 253
240 int ImageSkia::width() const { 254 int ImageSkia::width() const {
241 return isNull() ? 0 : storage_->size().width(); 255 return isNull() ? 0 : storage_->size().width();
242 } 256 }
243 257
(...skipping 15 matching lines...) Expand all
259 ImageSkiaReps image_reps; 273 ImageSkiaReps image_reps;
260 for (ImageSkiaReps::iterator it = internal_image_reps.begin(); 274 for (ImageSkiaReps::iterator it = internal_image_reps.begin();
261 it != internal_image_reps.end(); ++it) { 275 it != internal_image_reps.end(); ++it) {
262 if (!it->is_null()) 276 if (!it->is_null())
263 image_reps.push_back(*it); 277 image_reps.push_back(*it);
264 } 278 }
265 279
266 return image_reps; 280 return image_reps;
267 } 281 }
268 282
283 void ImageSkia::DeleteSource() {
284 if (storage_)
285 storage_->DeleteSource();
286 }
287
288 void ImageSkia::EnsureRepsForSupportedScaleFactors() const {
289 if (storage_ && storage_->has_source()) {
290 std::vector<ui::ScaleFactor> supported_scale_factors =
291 ui::GetSupportedScaleFactors();
292 for (size_t i = 0; i < supported_scale_factors.size(); ++i)
293 storage_->FindRepresentation(supported_scale_factors[i], true);
294 }
295 }
296
269 void ImageSkia::Init(const ImageSkiaRep& image_rep) { 297 void ImageSkia::Init(const ImageSkiaRep& image_rep) {
270 // TODO(pkotwicz): The image should be null whenever image rep is null. 298 // TODO(pkotwicz): The image should be null whenever image rep is null.
271 if (image_rep.sk_bitmap().empty()) { 299 if (image_rep.sk_bitmap().empty()) {
272 storage_ = NULL; 300 storage_ = NULL;
273 return; 301 return;
274 } 302 }
275 storage_ = new internal::ImageSkiaStorage( 303 storage_ = new internal::ImageSkiaStorage(
276 NULL, gfx::Size(image_rep.GetWidth(), image_rep.GetHeight())); 304 NULL, gfx::Size(image_rep.GetWidth(), image_rep.GetHeight()));
277 storage_->image_reps().push_back(image_rep); 305 storage_->image_reps().push_back(image_rep);
278 } 306 }
279 307
280 SkBitmap& ImageSkia::GetBitmap() const { 308 SkBitmap& ImageSkia::GetBitmap() const {
281 if (isNull()) { 309 if (isNull()) {
282 // Callers expect a ImageSkiaRep even if it is |isNull()|. 310 // Callers expect a ImageSkiaRep even if it is |isNull()|.
283 // TODO(pkotwicz): Fix this. 311 // TODO(pkotwicz): Fix this.
284 return NullImageRep().mutable_sk_bitmap(); 312 return NullImageRep().mutable_sk_bitmap();
285 } 313 }
286 314
287 ImageSkiaReps::iterator it = 315 ImageSkiaReps::iterator it =
288 storage_->FindRepresentation(ui::SCALE_FACTOR_100P, true); 316 storage_->FindRepresentation(ui::SCALE_FACTOR_100P, true);
289 if (it != storage_->image_reps().end()) 317 if (it != storage_->image_reps().end())
290 return it->mutable_sk_bitmap(); 318 return it->mutable_sk_bitmap();
291 return NullImageRep().mutable_sk_bitmap(); 319 return NullImageRep().mutable_sk_bitmap();
292 } 320 }
293 321
294 } // namespace gfx 322 } // namespace gfx
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698