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

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: cleanup 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
« no previous file with comments | « ui/gfx/image/image_skia.h ('k') | ui/gfx/image/image_skia_source.h » ('j') | 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 <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 // TODO(oshima): Make this DCHECK for M23. crbug.com/144367.
oshima 2012/08/23 14:21:09 Looks like NonThreadSafe is no-op in release build
109 CHECK(CalledOnValidThread()) <<
110 "More than one thread is tring to access ImageSkia which has "
111 "ImageSkiaSource. This is thread unsafe operation and not allowed";
112
99 ImageSkiaRep image = source_->GetImageForScale(scale_factor); 113 ImageSkiaRep image = source_->GetImageForScale(scale_factor);
100 114
101 // If the source returned the new image, store it. 115 // If the source returned the new image, store it.
102 if (!image.is_null() && 116 if (!image.is_null() &&
103 std::find_if(image_reps_.begin(), image_reps_.end(), 117 std::find_if(image_reps_.begin(), image_reps_.end(),
104 Matcher(image.scale_factor())) == image_reps_.end()) { 118 Matcher(image.scale_factor())) == image_reps_.end()) {
105 non_const->image_reps().push_back(image); 119 non_const->image_reps().push_back(image);
106 } 120 }
107 121
108 // If the result image's scale factor isn't same as the expected 122 // If the result image's scale factor isn't same as the expected
109 // scale factor, create null ImageSkiaRep with the |scale_factor| 123 // scale factor, create null ImageSkiaRep with the |scale_factor|
110 // so that the next lookup will fallback to the closest scale. 124 // so that the next lookup will fallback to the closest scale.
111 if (image.is_null() || image.scale_factor() != scale_factor) { 125 if (image.is_null() || image.scale_factor() != scale_factor) {
112 non_const->image_reps().push_back( 126 non_const->image_reps().push_back(
113 ImageSkiaRep(SkBitmap(), scale_factor)); 127 ImageSkiaRep(SkBitmap(), scale_factor));
114 } 128 }
115 129
116 // image_reps_ must have the exact much now, so find again. 130 // image_reps_ must have the exact much now, so find again.
117 return FindRepresentation(scale_factor, false); 131 return FindRepresentation(scale_factor, false);
118 } 132 }
119 return exact_iter != image_reps_.end() ? exact_iter : closest_iter; 133 return exact_iter != image_reps_.end() ? exact_iter : closest_iter;
120 } 134 }
121 135
122 private: 136 private:
123 ~ImageSkiaStorage() { 137 virtual ~ImageSkiaStorage() {
138 DetachFromThread();
124 } 139 }
125 140
126 // Vector of bitmaps and their associated scale factor. 141 // Vector of bitmaps and their associated scale factor.
127 std::vector<gfx::ImageSkiaRep> image_reps_; 142 std::vector<gfx::ImageSkiaRep> image_reps_;
128 143
129 scoped_ptr<ImageSkiaSource> source_; 144 scoped_ptr<ImageSkiaSource> source_;
130 145
131 // Size of the image in DIP. 146 // Size of the image in DIP.
132 const gfx::Size size_; 147 const gfx::Size size_;
133 148
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
168 ImageSkia::~ImageSkia() { 183 ImageSkia::~ImageSkia() {
169 } 184 }
170 185
171 bool ImageSkia::BackedBySameObjectAs(const gfx::ImageSkia& other) const { 186 bool ImageSkia::BackedBySameObjectAs(const gfx::ImageSkia& other) const {
172 return storage_.get() == other.storage_.get(); 187 return storage_.get() == other.storage_.get();
173 } 188 }
174 189
175 void ImageSkia::AddRepresentation(const ImageSkiaRep& image_rep) { 190 void ImageSkia::AddRepresentation(const ImageSkiaRep& image_rep) {
176 DCHECK(!image_rep.is_null()); 191 DCHECK(!image_rep.is_null());
177 192
193 // TODO(oshima): This method should be called |SetRepresentation|
194 // and replace the existing rep if there is already one with the
195 // same scale factor so that we can guarantee that a ImageSkia
196 // instance contians only one image rep per scale factor. This is
197 // not possible now as ImageLoadingTracker currently stores need
198 // this feature, but this needs to be fixed.
199
178 if (isNull()) 200 if (isNull())
179 Init(image_rep); 201 Init(image_rep);
180 else 202 else
181 storage_->image_reps().push_back(image_rep); 203 storage_->image_reps().push_back(image_rep);
182 } 204 }
183 205
184 void ImageSkia::RemoveRepresentation(ui::ScaleFactor scale_factor) { 206 void ImageSkia::RemoveRepresentation(ui::ScaleFactor scale_factor) {
185 if (isNull()) 207 if (isNull())
186 return; 208 return;
187 209
(...skipping 27 matching lines...) Expand all
215 } 237 }
216 238
217 #if defined(OS_MACOSX) 239 #if defined(OS_MACOSX)
218 240
219 std::vector<ImageSkiaRep> ImageSkia::GetRepresentations() const { 241 std::vector<ImageSkiaRep> ImageSkia::GetRepresentations() const {
220 if (isNull()) 242 if (isNull())
221 return std::vector<ImageSkiaRep>(); 243 return std::vector<ImageSkiaRep>();
222 244
223 if (!storage_->has_source()) 245 if (!storage_->has_source())
224 return image_reps(); 246 return image_reps();
225 247 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 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
« no previous file with comments | « ui/gfx/image/image_skia.h ('k') | ui/gfx/image/image_skia_source.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698