summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoroshima@chromium.org <oshima@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-20 18:53:44 +0000
committeroshima@chromium.org <oshima@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-06-20 18:53:44 +0000
commit6bb1fd3019d3509b9f764a8608a37b6c3927ca72 (patch)
treec657dd4d67e50da82708fbf7f690d39cef4349c2
parent2c1c9c835f57f3a50b05aa818feab35c9b754540 (diff)
downloadchromium_src-6bb1fd3019d3509b9f764a8608a37b6c3927ca72.zip
chromium_src-6bb1fd3019d3509b9f764a8608a37b6c3927ca72.tar.gz
chromium_src-6bb1fd3019d3509b9f764a8608a37b6c3927ca72.tar.bz2
Use ImageSkiaSource to create ImageSkia from ImagePNGReps
gfx::ImageKia will fetch the ImageSkiaRep based on resource scale factor (supported one) and scale accordingly. BUG=381601 TEST=covered by test. R=ananta@chromium.org, pkotwicz@chromium.org, rsesek@chromium.org Committed: https://src.chromium.org/viewvc/chrome?view=rev&revision=278589 Review URL: https://codereview.chromium.org/340613004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@278783 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--ui/gfx/image/image.cc128
-rw-r--r--ui/gfx/image/image_unittest.cc16
-rw-r--r--ui/gfx/image/image_unittest_util.cc2
3 files changed, 111 insertions, 35 deletions
diff --git a/ui/gfx/image/image.cc b/ui/gfx/image/image.cc
index 5c81a55..4598807 100644
--- a/ui/gfx/image/image.cc
+++ b/ui/gfx/image/image.cc
@@ -5,6 +5,7 @@
#include "ui/gfx/image/image.h"
#include <algorithm>
+#include <set>
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
@@ -12,6 +13,7 @@
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/image/image_png_rep.h"
#include "ui/gfx/image/image_skia.h"
+#include "ui/gfx/image/image_skia_source.h"
#include "ui/gfx/size.h"
#if !defined(OS_IOS)
@@ -35,20 +37,20 @@ scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromUIImage(
UIImage* uiimage);
// Caller takes ownership of the returned UIImage.
UIImage* CreateUIImageFromPNG(
- const std::vector<gfx::ImagePNGRep>& image_png_reps);
+ const std::vector<ImagePNGRep>& image_png_reps);
gfx::Size UIImageSize(UIImage* image);
#elif defined(OS_MACOSX)
scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromNSImage(
NSImage* nsimage);
// Caller takes ownership of the returned NSImage.
-NSImage* NSImageFromPNG(const std::vector<gfx::ImagePNGRep>& image_png_reps,
+NSImage* NSImageFromPNG(const std::vector<ImagePNGRep>& image_png_reps,
CGColorSpaceRef color_space);
gfx::Size NSImageSize(NSImage* image);
#endif // defined(OS_MACOSX)
#if defined(OS_IOS)
ImageSkia* ImageSkiaFromPNG(
- const std::vector<gfx::ImagePNGRep>& image_png_reps);
+ const std::vector<ImagePNGRep>& image_png_reps);
scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromImageSkia(
const ImageSkia* skia);
#else
@@ -59,31 +61,91 @@ ImageSkia* GetErrorImageSkia() {
bitmap.setConfig(SkBitmap::kARGB_8888_Config, 16, 16);
bitmap.allocPixels();
bitmap.eraseARGB(0xff, 0xff, 0, 0);
- return new gfx::ImageSkia(gfx::ImageSkiaRep(bitmap, 1.0f));
+ return new ImageSkia(ImageSkiaRep(bitmap, 1.0f));
}
+class PNGImageSource : public ImageSkiaSource {
+ public:
+ PNGImageSource() {}
+ virtual ~PNGImageSource() {}
+
+ virtual ImageSkiaRep GetImageForScale(float scale) OVERRIDE {
+ if (image_skia_reps_.empty())
+ return ImageSkiaRep();
+
+ const ImageSkiaRep* rep = NULL;
+ // gfx::ImageSkia passes one of the resource scale factors. The source
+ // should return:
+ // 1) The ImageSkiaRep with the highest scale if all available
+ // scales are smaller than |scale|.
+ // 2) The ImageSkiaRep with the smallest one that is larger than |scale|.
+ for (ImageSkiaRepSet::const_iterator iter = image_skia_reps_.begin();
+ iter != image_skia_reps_.end(); ++iter) {
+ if ((*iter).scale() == scale)
+ return (*iter);
+ if (!rep || rep->scale() < (*iter).scale())
+ rep = &(*iter);
+ if (rep->scale() >= scale)
+ break;
+ }
+ return rep ? *rep : ImageSkiaRep();
+ }
+
+ const gfx::Size size() const {
+ return size_;
+ }
+
+ bool AddPNGData(const ImagePNGRep& png_rep) {
+ const gfx::ImageSkiaRep rep = ToImageSkiaRep(png_rep);
+ if (rep.is_null())
+ return false;
+ if (size_.IsEmpty())
+ size_ = gfx::Size(rep.GetWidth(), rep.GetHeight());
+ image_skia_reps_.insert(rep);
+ return true;
+ }
+
+ static ImageSkiaRep ToImageSkiaRep(const ImagePNGRep& png_rep) {
+ scoped_refptr<base::RefCountedMemory> raw_data = png_rep.raw_data;
+ CHECK(raw_data.get());
+ SkBitmap bitmap;
+ if (!PNGCodec::Decode(raw_data->front(), raw_data->size(),
+ &bitmap)) {
+ LOG(ERROR) << "Unable to decode PNG for " << png_rep.scale << ".";
+ return ImageSkiaRep();
+ }
+ return ImageSkiaRep(bitmap, png_rep.scale);
+ }
+
+ private:
+ struct Compare {
+ bool operator()(const ImageSkiaRep& rep1, const ImageSkiaRep& rep2) {
+ return rep1.scale() < rep2.scale();
+ }
+ };
+
+ typedef std::set<ImageSkiaRep, Compare> ImageSkiaRepSet;
+ ImageSkiaRepSet image_skia_reps_;
+ gfx::Size size_;
+
+ DISALLOW_COPY_AND_ASSIGN(PNGImageSource);
+};
+
ImageSkia* ImageSkiaFromPNG(
- const std::vector<gfx::ImagePNGRep>& image_png_reps) {
+ const std::vector<ImagePNGRep>& image_png_reps) {
if (image_png_reps.empty())
return GetErrorImageSkia();
+ scoped_ptr<PNGImageSource> image_source(new PNGImageSource);
- scoped_ptr<gfx::ImageSkia> image_skia(new ImageSkia());
for (size_t i = 0; i < image_png_reps.size(); ++i) {
- scoped_refptr<base::RefCountedMemory> raw_data =
- image_png_reps[i].raw_data;
- CHECK(raw_data.get());
- SkBitmap bitmap;
- if (!gfx::PNGCodec::Decode(raw_data->front(), raw_data->size(),
- &bitmap)) {
- LOG(ERROR) << "Unable to decode PNG for "
- << image_png_reps[i].scale
- << ".";
+ if (!image_source->AddPNGData(image_png_reps[i]))
return GetErrorImageSkia();
- }
- image_skia->AddRepresentation(gfx::ImageSkiaRep(
- bitmap, image_png_reps[i].scale));
}
- return image_skia.release();
+ const gfx::Size& size = image_source->size();
+ DCHECK(!size.IsEmpty());
+ if (size.IsEmpty())
+ return GetErrorImageSkia();
+ return new ImageSkia(image_source.release(), size);
}
scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromImageSkia(
@@ -92,7 +154,7 @@ scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromImageSkia(
scoped_refptr<base::RefCountedBytes> png_bytes(new base::RefCountedBytes());
if (image_skia_rep.scale() != 1.0f ||
- !gfx::PNGCodec::EncodeBGRASkBitmap(image_skia_rep.sk_bitmap(), false,
+ !PNGCodec::EncodeBGRASkBitmap(image_skia_rep.sk_bitmap(), false,
&png_bytes->data())) {
return NULL;
}
@@ -302,7 +364,7 @@ class ImageRepCocoa : public ImageRep {
// ImageReps. This way, the Image can be cheaply copied.
class ImageStorage : public base::RefCounted<ImageStorage> {
public:
- ImageStorage(gfx::Image::RepresentationType default_type)
+ ImageStorage(Image::RepresentationType default_type)
: default_representation_type_(default_type),
#if defined(OS_MACOSX) && !defined(OS_IOS)
default_representation_color_space_(
@@ -311,10 +373,10 @@ class ImageStorage : public base::RefCounted<ImageStorage> {
representations_deleter_(&representations_) {
}
- gfx::Image::RepresentationType default_representation_type() {
+ Image::RepresentationType default_representation_type() {
return default_representation_type_;
}
- gfx::Image::RepresentationMap& representations() { return representations_; }
+ Image::RepresentationMap& representations() { return representations_; }
#if defined(OS_MACOSX) && !defined(OS_IOS)
void set_default_representation_color_space(CGColorSpaceRef color_space) {
@@ -332,7 +394,7 @@ class ImageStorage : public base::RefCounted<ImageStorage> {
// The type of image that was passed to the constructor. This key will always
// exist in the |representations_| map.
- gfx::Image::RepresentationType default_representation_type_;
+ Image::RepresentationType default_representation_type_;
#if defined(OS_MACOSX) && !defined(OS_IOS)
// The default representation's colorspace. This is used for converting to
@@ -344,7 +406,7 @@ class ImageStorage : public base::RefCounted<ImageStorage> {
// All the representations of an Image. Size will always be at least one, with
// more for any converted representations.
- gfx::Image::RepresentationMap representations_;
+ Image::RepresentationMap representations_;
STLValueDeleter<Image::RepresentationMap> representations_deleter_;
@@ -413,14 +475,14 @@ Image::~Image() {
// static
Image Image::CreateFrom1xBitmap(const SkBitmap& bitmap) {
- return gfx::Image(ImageSkia::CreateFrom1xBitmap(bitmap));
+ return Image(ImageSkia::CreateFrom1xBitmap(bitmap));
}
// static
Image Image::CreateFrom1xPNGBytes(const unsigned char* input,
size_t input_size) {
if (input_size == 0u)
- return gfx::Image();
+ return Image();
scoped_refptr<base::RefCountedBytes> raw_data(new base::RefCountedBytes());
raw_data->data().assign(input, input + input_size);
@@ -431,11 +493,11 @@ Image Image::CreateFrom1xPNGBytes(const unsigned char* input,
Image Image::CreateFrom1xPNGBytes(
const scoped_refptr<base::RefCountedMemory>& input) {
if (!input.get() || input->size() == 0u)
- return gfx::Image();
+ return Image();
- std::vector<gfx::ImagePNGRep> image_reps;
+ std::vector<ImagePNGRep> image_reps;
image_reps.push_back(ImagePNGRep(input, 1.0f));
- return gfx::Image(image_reps);
+ return Image(image_reps);
}
const SkBitmap* Image::ToSkBitmap() const {
@@ -550,7 +612,7 @@ scoped_refptr<base::RefCountedMemory> Image::As1xPNGBytes() const {
internal::ImageRep* rep = GetRepresentation(kImageRepPNG, false);
if (rep) {
- const std::vector<gfx::ImagePNGRep>& image_png_reps =
+ const std::vector<ImagePNGRep>& image_png_reps =
rep->AsImageRepPNG()->image_reps();
for (size_t i = 0; i < image_png_reps.size(); ++i) {
if (image_png_reps[i].scale == 1.0f)
@@ -601,7 +663,7 @@ scoped_refptr<base::RefCountedMemory> Image::As1xPNGBytes() const {
// final type eg (converting from ImageRepSkia to ImageRepPNG to get an
// ImageRepCocoa).
std::vector<ImagePNGRep> image_png_reps;
- image_png_reps.push_back(gfx::ImagePNGRep(png_bytes, 1.0f));
+ image_png_reps.push_back(ImagePNGRep(png_bytes, 1.0f));
rep = new internal::ImageRepPNG(image_png_reps);
AddRepresentation(rep);
return png_bytes;
@@ -683,7 +745,7 @@ gfx::Size Image::Size() const {
return GetRepresentation(DefaultRepresentationType(), true)->Size();
}
-void Image::SwapRepresentations(gfx::Image* other) {
+void Image::SwapRepresentations(Image* other) {
storage_.swap(other->storage_);
}
diff --git a/ui/gfx/image/image_unittest.cc b/ui/gfx/image/image_unittest.cc
index a0fbe3e..ca9efa0 100644
--- a/ui/gfx/image/image_unittest.cc
+++ b/ui/gfx/image/image_unittest.cc
@@ -243,12 +243,24 @@ TEST_F(ImageTest, MultiResolutionPNGToImageSkia) {
scales.push_back(1.0f);
scales.push_back(2.0f);
gfx::ImageSkia image_skia = image.AsImageSkia();
- EXPECT_TRUE(gt::ImageSkiaStructureMatches(image_skia, kSize1x, kSize1x,
- scales));
EXPECT_TRUE(gt::IsEqual(bytes1x,
image_skia.GetRepresentation(1.0f).sk_bitmap()));
EXPECT_TRUE(gt::IsEqual(bytes2x,
image_skia.GetRepresentation(2.0f).sk_bitmap()));
+ EXPECT_TRUE(gt::ImageSkiaStructureMatches(image_skia, kSize1x, kSize1x,
+ scales));
+#if !defined(OS_IOS)
+ // IOS does not support arbitrary scale factors.
+ gfx::ImageSkiaRep rep_1_6x = image_skia.GetRepresentation(1.6f);
+ ASSERT_FALSE(rep_1_6x.is_null());
+ ASSERT_EQ(1.6f, rep_1_6x.scale());
+ EXPECT_EQ("40x40", rep_1_6x.pixel_size().ToString());
+
+ gfx::ImageSkiaRep rep_0_8x = image_skia.GetRepresentation(0.8f);
+ ASSERT_FALSE(rep_0_8x.is_null());
+ ASSERT_EQ(0.8f, rep_0_8x.scale());
+ EXPECT_EQ("20x20", rep_0_8x.pixel_size().ToString());
+#endif
}
TEST_F(ImageTest, MultiResolutionPNGToPlatform) {
diff --git a/ui/gfx/image/image_unittest_util.cc b/ui/gfx/image/image_unittest_util.cc
index b66ace5..e9a0032 100644
--- a/ui/gfx/image/image_unittest_util.cc
+++ b/ui/gfx/image/image_unittest_util.cc
@@ -80,6 +80,8 @@ gfx::Image CreateImage(int width, int height) {
}
bool IsEqual(const gfx::Image& img1, const gfx::Image& img2) {
+ img1.AsImageSkia().EnsureRepsForSupportedScales();
+ img2.AsImageSkia().EnsureRepsForSupportedScales();
std::vector<gfx::ImageSkiaRep> img1_reps = img1.AsImageSkia().image_reps();
gfx::ImageSkia image_skia2 = img2.AsImageSkia();
if (image_skia2.image_reps().size() != img1_reps.size())