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

Unified 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, 6 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 side-by-side diff with in-line comments
Download patch
Index: ui/gfx/image/image_skia.cc
diff --git a/ui/gfx/image/image_skia.cc b/ui/gfx/image/image_skia.cc
index e5fb8e3c617ce18b81fb4c00aea2918c07cd49d2..3d8acf135fb0b991938abca1660b94229af48897 100644
--- a/ui/gfx/image/image_skia.cc
+++ b/ui/gfx/image/image_skia.cc
@@ -4,30 +4,117 @@
#include "ui/gfx/image/image_skia.h"
-#include <limits>
+#include <algorithm>
#include <cmath>
+#include <limits>
#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "ui/gfx/image/image_skia_source.h"
#include "ui/gfx/size.h"
#include "ui/gfx/skia_util.h"
namespace gfx {
+namespace {
+
+// static
+gfx::ImageSkiaRep& NullImageRep() {
+ CR_DEFINE_STATIC_LOCAL(ImageSkiaRep, null_image_rep, ());
+ return null_image_rep;
+}
+
+} // namespace
namespace internal {
+namespace {
+
+class Matcher {
+ public:
+ explicit Matcher(ui::ScaleFactor scale_factor) : scale_factor_(scale_factor) {
+ }
+
+ bool operator()(const ImageSkiaRep& rep) const {
+ return rep.scale_factor() == scale_factor_;
+ }
+
+ private:
+ ui::ScaleFactor scale_factor_;
+};
+
+} // namespace
// A helper class such that ImageSkia can be cheaply copied. ImageSkia holds a
// refptr instance of ImageSkiaStorage, which in turn holds all of ImageSkia's
// information.
class ImageSkiaStorage : public base::RefCounted<ImageSkiaStorage> {
public:
- ImageSkiaStorage() {
+ ImageSkiaStorage(ImageSkiaSource* source, const gfx::Size& size)
+ : source_(source),
+ size_(size) {
}
std::vector<gfx::ImageSkiaRep>& image_reps() { return image_reps_; }
- void set_size(const gfx::Size& size) { size_ = size; }
const gfx::Size& size() const { return size_; }
+ // Returns the iterator of the image rep whose density best matches
+ // |scale_factor|. If the image for the |scale_factor| doesn't exist
+ // in the storage and |storage| is set, it fetches new image by calling
+ // |ImageSkiaSource::GetImageForScale|. If the source returns the
+ // image with different scale factor (if the image doesn't exist in
+ // resource, for example), it will fallback to closest image rep.
+ std::vector<ImageSkiaRep>::iterator FindRepresentation(
+ ui::ScaleFactor scale_factor, bool fetch_new_image) const {
+ ImageSkiaStorage* non_const = const_cast<ImageSkiaStorage*>(this);
+
+ float scale = ui::GetScaleFactorScale(scale_factor);
+ ImageSkia::ImageSkiaReps::iterator closest_iter =
+ non_const->image_reps().end();
+ ImageSkia::ImageSkiaReps::iterator exact_iter =
+ non_const->image_reps().end();
+ float smallest_diff = std::numeric_limits<float>::max();
+ for (ImageSkia::ImageSkiaReps::iterator it =
+ non_const->image_reps().begin();
+ it < image_reps_.end(); ++it) {
+ if (it->GetScale() == scale) {
+ // found exact match
+ fetch_new_image = false;
+ if (it->is_null())
+ continue;
+ exact_iter = it;
+ break;
+ }
+ float diff = std::abs(it->GetScale() - scale);
+ if (diff < smallest_diff && !it->is_null()) {
+ closest_iter = it;
+ smallest_diff = diff;
+ }
+ }
+
+ if (fetch_new_image && source_.get()) {
+ ImageSkiaRep image = source_->GetImageForScale(scale_factor);
+
+ // If the source returned the new image, store it.
+ if (!image.is_null() &&
+ std::find_if(image_reps_.begin(), image_reps_.end(),
+ Matcher(image.scale_factor())) == image_reps_.end()) {
+ non_const->image_reps().push_back(image);
+ }
+
+ // If the result image's scale factor isn't same as the expected
+ // scale factor, create null ImageSkiaRep with the |scale_factor|
+ // so that the next lookup will fallback to the closest scale.
+ if (image.is_null() || image.scale_factor() != scale_factor) {
+ non_const->image_reps().push_back(
+ ImageSkiaRep(SkBitmap(), scale_factor));
+ }
+
+ // image_reps_ must have the exact much now, so find again.
+ return FindRepresentation(scale_factor, false);
+ }
+ return exact_iter != image_reps_.end() ? exact_iter : closest_iter;
+ }
+
private:
~ImageSkiaStorage() {
}
@@ -35,8 +122,10 @@ class ImageSkiaStorage : public base::RefCounted<ImageSkiaStorage> {
// Vector of bitmaps and their associated scale factor.
std::vector<gfx::ImageSkiaRep> image_reps_;
+ scoped_ptr<ImageSkiaSource> source_;
+
// Size of the image in DIP.
- gfx::Size size_;
+ const gfx::Size size_;
friend class base::RefCounted<ImageSkiaStorage>;
};
@@ -46,6 +135,11 @@ class ImageSkiaStorage : public base::RefCounted<ImageSkiaStorage> {
ImageSkia::ImageSkia() : storage_(NULL) {
}
+ImageSkia::ImageSkia(ImageSkiaSource* source, const gfx::Size& size)
+ : storage_(new internal::ImageSkiaStorage(source, size)) {
+ DCHECK(source);
+}
+
ImageSkia::ImageSkia(const SkBitmap& bitmap) {
Init(ImageSkiaRep(bitmap));
}
@@ -103,7 +197,8 @@ void ImageSkia::RemoveRepresentation(ui::ScaleFactor scale_factor) {
return;
ImageSkiaReps& image_reps = storage_->image_reps();
- ImageSkiaReps::iterator it = FindRepresentation(scale_factor);
+ ImageSkiaReps::iterator it =
+ storage_->FindRepresentation(scale_factor, false);
if (it != image_reps.end() && it->scale_factor() == scale_factor)
image_reps.erase(it);
}
@@ -112,7 +207,8 @@ bool ImageSkia::HasRepresentation(ui::ScaleFactor scale_factor) {
if (isNull())
return false;
- ImageSkiaReps::iterator it = FindRepresentation(scale_factor);
+ ImageSkiaReps::iterator it =
+ storage_->FindRepresentation(scale_factor, false);
return (it != storage_->image_reps().end() &&
it->scale_factor() == scale_factor);
}
@@ -122,7 +218,7 @@ const ImageSkiaRep& ImageSkia::GetRepresentation(
if (isNull())
return NullImageRep();
- ImageSkiaReps::iterator it = FindRepresentation(scale_factor);
+ ImageSkiaReps::iterator it = storage_->FindRepresentation(scale_factor, true);
if (it == storage_->image_reps().end())
return NullImageRep();
@@ -137,6 +233,10 @@ int ImageSkia::width() const {
return isNull() ? 0 : storage_->size().width();
}
+gfx::Size ImageSkia::size() const {
+ return gfx::Size(width(), height());
+}
+
int ImageSkia::height() const {
return isNull() ? 0 : storage_->size().height();
}
@@ -191,36 +291,9 @@ void ImageSkia::Init(const ImageSkiaRep& image_rep) {
storage_ = NULL;
return;
}
- storage_ = new internal::ImageSkiaStorage();
- storage_->set_size(gfx::Size(image_rep.GetWidth(), image_rep.GetHeight()));
+ storage_ = new internal::ImageSkiaStorage(
+ NULL, gfx::Size(image_rep.GetWidth(), image_rep.GetHeight()));
storage_->image_reps().push_back(image_rep);
}
-// static
-ImageSkiaRep& ImageSkia::NullImageRep() {
- CR_DEFINE_STATIC_LOCAL(ImageSkiaRep, null_image_rep, ());
- return null_image_rep;
-}
-
-std::vector<ImageSkiaRep>::iterator ImageSkia::FindRepresentation(
- ui::ScaleFactor scale_factor) const {
- DCHECK(!isNull());
-
- float scale = ui::GetScaleFactorScale(scale_factor);
- ImageSkiaReps& image_reps = storage_->image_reps();
- ImageSkiaReps::iterator closest_iter = image_reps.end();
- float smallest_diff = std::numeric_limits<float>::max();
- for (ImageSkiaReps::iterator it = image_reps.begin();
- it < image_reps.end();
- ++it) {
- float diff = std::abs(it->GetScale() - scale);
- if (diff < smallest_diff) {
- closest_iter = it;
- smallest_diff = diff;
- }
- }
-
- return closest_iter;
-}
-
} // namespace gfx

Powered by Google App Engine
This is Rietveld 408576698