Commit 1986f3a9 authored by Dana Fried's avatar Dana Fried Committed by Commit Bot

Improve handling of Skia images by gfx::Image

Removed unnecessary indirection and allocation via std::unique_ptr for
storage of value types in cached image data (both gfx::Size and
gfx::ImageSkia are value types).

Added unit tests checking assumptions and ensuring that we will not
break said assumptions about how image data is cached/image data
duplication is prevented in the future.

Change-Id: I59a70aa1ccb2e00fbc1a69ad92e48374643b6d20
Reviewed-on: https://chromium-review.googlesource.com/c/1471514Reviewed-by: default avatarRobert Sesek <rsesek@chromium.org>
Commit-Queue: Dana Fried <dfried@chromium.org>
Cr-Commit-Position: refs/heads/master@{#632315}
parent 791b30c6
...@@ -109,10 +109,8 @@ class ImageRepPNG : public ImageRep { ...@@ -109,10 +109,8 @@ class ImageRepPNG : public ImageRep {
ImageRepPNG() : ImageRep(Image::kImageRepPNG) { ImageRepPNG() : ImageRep(Image::kImageRepPNG) {
} }
ImageRepPNG(const std::vector<ImagePNGRep>& image_png_reps) explicit ImageRepPNG(const std::vector<ImagePNGRep>& image_png_reps)
: ImageRep(Image::kImageRepPNG), : ImageRep(Image::kImageRepPNG), image_png_reps_(image_png_reps) {}
image_png_reps_(image_png_reps) {
}
~ImageRepPNG() override {} ~ImageRepPNG() override {}
...@@ -125,11 +123,11 @@ class ImageRepPNG : public ImageRep { ...@@ -125,11 +123,11 @@ class ImageRepPNG : public ImageRep {
if (!size_cache_) { if (!size_cache_) {
for (auto it = image_reps().begin(); it != image_reps().end(); ++it) { for (auto it = image_reps().begin(); it != image_reps().end(); ++it) {
if (it->scale == 1.0f) { if (it->scale == 1.0f) {
size_cache_.reset(new gfx::Size(it->Size())); size_cache_ = it->Size();
return *size_cache_; return *size_cache_;
} }
} }
size_cache_.reset(new gfx::Size); size_cache_ = gfx::Size();
} }
return *size_cache_; return *size_cache_;
...@@ -141,7 +139,7 @@ class ImageRepPNG : public ImageRep { ...@@ -141,7 +139,7 @@ class ImageRepPNG : public ImageRep {
std::vector<ImagePNGRep> image_png_reps_; std::vector<ImagePNGRep> image_png_reps_;
// Cached to avoid having to parse the raw data multiple times. // Cached to avoid having to parse the raw data multiple times.
mutable std::unique_ptr<gfx::Size> size_cache_; mutable base::Optional<gfx::Size> size_cache_;
DISALLOW_COPY_AND_ASSIGN(ImageRepPNG); DISALLOW_COPY_AND_ASSIGN(ImageRepPNG);
}; };
...@@ -150,23 +148,21 @@ class ImageRepSkia : public ImageRep { ...@@ -150,23 +148,21 @@ class ImageRepSkia : public ImageRep {
public: public:
// Takes ownership of |image|. // Takes ownership of |image|.
explicit ImageRepSkia(ImageSkia* image) explicit ImageRepSkia(ImageSkia* image)
: ImageRep(Image::kImageRepSkia), : ImageRep(Image::kImageRepSkia), image_(*image) {}
image_(image) {
}
~ImageRepSkia() override {} ~ImageRepSkia() override {}
int Width() const override { return image_->width(); } int Width() const override { return image_.width(); }
int Height() const override { return image_->height(); } int Height() const override { return image_.height(); }
gfx::Size Size() const override { return image_->size(); } gfx::Size Size() const override { return image_.size(); }
const ImageSkia* image() const { return image_.get(); } const ImageSkia* image() const { return &image_; }
ImageSkia* image() { return image_.get(); } ImageSkia* image() { return &image_; }
private: private:
std::unique_ptr<ImageSkia> image_; ImageSkia image_;
DISALLOW_COPY_AND_ASSIGN(ImageRepSkia); DISALLOW_COPY_AND_ASSIGN(ImageRepSkia);
}; };
...@@ -238,7 +234,7 @@ class ImageRepCocoa : public ImageRep { ...@@ -238,7 +234,7 @@ class ImageRepCocoa : public ImageRep {
// themselves not threadsafe. // themselves not threadsafe.
class ImageStorage : public base::RefCounted<ImageStorage> { class ImageStorage : public base::RefCounted<ImageStorage> {
public: public:
ImageStorage(Image::RepresentationType default_type) explicit ImageStorage(Image::RepresentationType default_type)
: default_representation_type_(default_type) : default_representation_type_(default_type)
#if defined(OS_MACOSX) && !defined(OS_IOS) #if defined(OS_MACOSX) && !defined(OS_IOS)
, ,
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
#include <stddef.h> #include <stddef.h>
#include <utility>
#include "build/build_config.h" #include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkCanvas.h" #include "third_party/skia/include/core/SkCanvas.h"
...@@ -575,6 +577,72 @@ TEST_F(ImageTest, MoveAssign) { ...@@ -575,6 +577,72 @@ TEST_F(ImageTest, MoveAssign) {
EXPECT_EQ(1U, image2.RepresentationCount()); EXPECT_EQ(1U, image2.RepresentationCount());
} }
TEST_F(ImageTest, Copy_PreservesRepresentation) {
const gfx::Size kSize1x(25, 25);
const gfx::Size kSize2x(50, 50);
std::vector<gfx::ImagePNGRep> image_png_reps;
image_png_reps.push_back(
gfx::ImagePNGRep(gt::CreatePNGBytes(kSize1x.width()), 1.0f));
image_png_reps.push_back(
gfx::ImagePNGRep(gt::CreatePNGBytes(kSize2x.width()), 2.0f));
gfx::Image image(image_png_reps);
gfx::ImageSkia image_skia = image.AsImageSkia();
EXPECT_EQ(kSize1x, image_skia.size());
SkISize size = image_skia.GetRepresentation(2.0f).GetBitmap().dimensions();
EXPECT_EQ(kSize2x, gfx::Size(size.fWidth, size.fHeight));
gfx::Image image2(image);
gfx::ImageSkia image_skia2 = image2.AsImageSkia();
EXPECT_EQ(kSize1x, image_skia2.size());
size = image_skia2.GetRepresentation(2.0f).GetBitmap().dimensions();
EXPECT_EQ(kSize2x, gfx::Size(size.fWidth, size.fHeight));
EXPECT_TRUE(image_skia.BackedBySameObjectAs(image_skia2));
}
TEST_F(ImageTest, Copy_PreventsDuplication) {
const gfx::Size kSize1x(25, 25);
const gfx::Size kSize2x(50, 50);
std::vector<gfx::ImagePNGRep> image_png_reps;
image_png_reps.push_back(
gfx::ImagePNGRep(gt::CreatePNGBytes(kSize1x.width()), 1.0f));
image_png_reps.push_back(
gfx::ImagePNGRep(gt::CreatePNGBytes(kSize2x.width()), 2.0f));
gfx::Image image(image_png_reps);
gfx::Image image2(image);
gfx::ImageSkia image_skia = image.AsImageSkia();
EXPECT_EQ(kSize1x, image_skia.size());
SkISize size = image_skia.GetRepresentation(2.0f).GetBitmap().dimensions();
EXPECT_EQ(kSize2x, gfx::Size(size.fWidth, size.fHeight));
gfx::ImageSkia image_skia2 = image2.AsImageSkia();
EXPECT_EQ(kSize1x, image_skia2.size());
size = image_skia2.GetRepresentation(2.0f).GetBitmap().dimensions();
EXPECT_EQ(kSize2x, gfx::Size(size.fWidth, size.fHeight));
EXPECT_TRUE(image_skia.BackedBySameObjectAs(image_skia2));
}
TEST_F(ImageTest, Copy_PreservesBackingStore) {
const gfx::Size kSize1x(25, 25);
gfx::Image image(gt::CreateImageSkia(kSize1x.width(), kSize1x.height()));
gfx::Image image2 = gfx::Image::CreateFrom1xBitmap(image.AsBitmap());
gfx::ImageSkia image_skia = image.AsImageSkia();
gfx::ImageSkia image_skia2 = image2.AsImageSkia();
// Because we haven't copied the image representation (scale info, etc.) the
// new Skia image isn't backed by the same object, but it should still contain
// the same bitmap data.
EXPECT_FALSE(image_skia2.BackedBySameObjectAs(image_skia));
EXPECT_EQ(image_skia.bitmap()->getPixels(),
image_skia2.bitmap()->getPixels());
}
TEST_F(ImageTest, MultiResolutionImageSkia) { TEST_F(ImageTest, MultiResolutionImageSkia) {
const int kWidth1x = 10; const int kWidth1x = 10;
const int kHeight1x = 12; const int kHeight1x = 12;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment