summaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
Diffstat (limited to 'ui')
-rw-r--r--ui/base/resource/resource_bundle.cc22
-rw-r--r--ui/gfx/canvas.cc107
-rw-r--r--ui/gfx/canvas.h56
-rw-r--r--ui/gfx/image/image.cc35
-rw-r--r--ui/gfx/image/image.h8
-rw-r--r--ui/gfx/image/image_mac.mm37
-rw-r--r--ui/gfx/image/image_mac_unittest.mm96
-rw-r--r--ui/gfx/image/image_skia.cc255
-rw-r--r--ui/gfx/image/image_skia.h155
-rw-r--r--ui/gfx/image/image_unittest.cc66
10 files changed, 515 insertions, 322 deletions
diff --git a/ui/base/resource/resource_bundle.cc b/ui/base/resource/resource_bundle.cc
index 58765b1..d6a69bd 100644
--- a/ui/base/resource/resource_bundle.cc
+++ b/ui/base/resource/resource_bundle.cc
@@ -24,6 +24,7 @@
#include "ui/base/ui_base_switches.h"
#include "ui/gfx/codec/jpeg_codec.h"
#include "ui/gfx/codec/png_codec.h"
+#include "ui/gfx/image/image_skia.h"
namespace ui {
@@ -226,25 +227,26 @@ gfx::Image& ResourceBundle::GetImageNamed(int resource_id) {
if (image.IsEmpty()) {
DCHECK(!delegate_ && !data_packs_.empty()) <<
"Missing call to SetResourcesDataDLL?";
- ScopedVector<const SkBitmap> bitmaps;
+ gfx::ImageSkia image_skia;
for (size_t i = 0; i < data_packs_.size(); ++i) {
- SkBitmap* bitmap = LoadBitmap(*data_packs_[i], resource_id);
- if (bitmap)
- bitmaps.push_back(bitmap);
+ scoped_ptr<SkBitmap> bitmap(LoadBitmap(*data_packs_[i], resource_id));
+ if (bitmap.get()) {
+#if defined(ENABLE_DIP)
+ image_skia.AddBitmapForScale(*bitmap, data_packs_[i]->GetScaleFactor());
+#else
+ image_skia.AddBitmapForScale(*bitmap, 1.0f);
+#endif
+ }
}
- if (bitmaps.empty()) {
+ if (image_skia.empty()) {
LOG(WARNING) << "Unable to load image with id " << resource_id;
NOTREACHED(); // Want to assert in debug mode.
// The load failed to retrieve the image; show a debugging red square.
return GetEmptyImage();
}
- std::vector<const SkBitmap*> tmp_bitmaps;
- bitmaps.release(&tmp_bitmaps);
-
- // Takes ownership of bitmaps.
- image = gfx::Image(tmp_bitmaps);
+ image = gfx::Image(image_skia);
}
// The load was successful, so cache the image.
diff --git a/ui/gfx/canvas.cc b/ui/gfx/canvas.cc
index 288d192..aeabc12 100644
--- a/ui/gfx/canvas.cc
+++ b/ui/gfx/canvas.cc
@@ -254,42 +254,42 @@ void Canvas::DrawFocusRect(const gfx::Rect& rect) {
DrawDashedRect(rect, SK_ColorGRAY);
}
-void Canvas::DrawBitmapInt(const SkBitmap& bitmap, int x, int y) {
- canvas_->drawBitmap(bitmap, SkIntToScalar(x), SkIntToScalar(y));
+void Canvas::DrawBitmapInt(const gfx::ImageSkia& image, int x, int y) {
+ SkPaint paint;
+ DrawBitmapInt(image, x, y, paint);
}
-void Canvas::DrawBitmapInt(const SkBitmap& bitmap,
+void Canvas::DrawBitmapInt(const gfx::ImageSkia& image,
int x, int y,
const SkPaint& paint) {
- canvas_->drawBitmap(bitmap, SkIntToScalar(x), SkIntToScalar(y), &paint);
+ float bitmap_scale;
+ const SkBitmap& bitmap = GetBitmapToPaint(image, &bitmap_scale);
+ if (bitmap.isNull())
+ return;
+
+ canvas_->save();
+ canvas_->scale(SkFloatToScalar(1.0f / bitmap_scale),
+ SkFloatToScalar(1.0f / bitmap_scale));
+ canvas_->drawBitmap(bitmap,
+ SkFloatToScalar(x * bitmap_scale),
+ SkFloatToScalar(y * bitmap_scale));
+ canvas_->restore();
}
-void Canvas::DrawBitmapInt(const SkBitmap& bitmap,
+void Canvas::DrawBitmapInt(const gfx::ImageSkia& image,
int src_x, int src_y, int src_w, int src_h,
int dest_x, int dest_y, int dest_w, int dest_h,
bool filter) {
SkPaint p;
- DrawBitmapInt(bitmap, src_x, src_y, src_w, src_h, dest_x, dest_y,
+ DrawBitmapInt(image, src_x, src_y, src_w, src_h, dest_x, dest_y,
dest_w, dest_h, filter, p);
}
-void Canvas::DrawBitmapInt(const SkBitmap& bitmap,
+void Canvas::DrawBitmapInt(const gfx::ImageSkia& image,
int src_x, int src_y, int src_w, int src_h,
int dest_x, int dest_y, int dest_w, int dest_h,
bool filter,
const SkPaint& paint) {
- DrawBitmapFloat(bitmap, static_cast<float>(src_x), static_cast<float>(src_y),
- static_cast<float>(src_w), static_cast<float>(src_h),
- static_cast<float>(dest_x), static_cast<float>(dest_y),
- static_cast<float>(dest_w), static_cast<float>(dest_h),
- filter, paint);
-}
-
-void Canvas::DrawBitmapFloat(const SkBitmap& bitmap,
- float src_x, float src_y, float src_w, float src_h,
- float dest_x, float dest_y, float dest_w, float dest_h,
- bool filter,
- const SkPaint& paint) {
DLOG_ASSERT(src_x + src_w < std::numeric_limits<int16_t>::max() &&
src_y + src_h < std::numeric_limits<int16_t>::max());
if (src_w <= 0 || src_h <= 0) {
@@ -300,12 +300,22 @@ void Canvas::DrawBitmapFloat(const SkBitmap& bitmap,
if (!IntersectsClipRectInt(dest_x, dest_y, dest_w, dest_h))
return;
- SkRect dest_rect = { SkFloatToScalar(dest_x),
- SkFloatToScalar(dest_y),
- SkFloatToScalar(dest_x + dest_w),
- SkFloatToScalar(dest_y + dest_h) };
+ float user_scale_x = static_cast<float>(dest_w) / src_w;
+ float user_scale_y = static_cast<float>(dest_h) / src_h;
- if (src_w == dest_w && src_h == dest_h) {
+ float bitmap_scale;
+ const SkBitmap& bitmap = GetBitmapToPaint(image, user_scale_x, user_scale_y,
+ &bitmap_scale);
+ if (bitmap.isNull())
+ return;
+
+ SkRect dest_rect = { SkIntToScalar(dest_x),
+ SkIntToScalar(dest_y),
+ SkIntToScalar(dest_x + dest_w),
+ SkIntToScalar(dest_y + dest_h) };
+
+ if (src_w == dest_w && src_h == dest_h &&
+ bitmap_scale == 1.0f && bitmap_scale == 1.0f) {
// Workaround for apparent bug in Skia that causes image to occasionally
// shift.
SkIRect src_rect = { src_x, src_y, src_x + src_w, src_y + src_h };
@@ -321,10 +331,13 @@ void Canvas::DrawBitmapFloat(const SkBitmap& bitmap,
SkShader::kRepeat_TileMode,
SkShader::kRepeat_TileMode);
SkMatrix shader_scale;
- shader_scale.setScale(SkFloatToScalar(dest_w / src_w),
- SkFloatToScalar(dest_h / src_h));
- shader_scale.preTranslate(SkFloatToScalar(-src_x), SkFloatToScalar(-src_y));
- shader_scale.postTranslate(SkFloatToScalar(dest_x), SkFloatToScalar(dest_y));
+ shader_scale.setScale(SkFloatToScalar(user_scale_x),
+ SkFloatToScalar(user_scale_y));
+ shader_scale.preTranslate(SkFloatToScalar(-src_x * bitmap_scale),
+ SkFloatToScalar(-src_y * bitmap_scale));
+ shader_scale.postTranslate(SkFloatToScalar(dest_x * bitmap_scale),
+ SkFloatToScalar(dest_y * bitmap_scale));
+ shader_scale.postScale(1.0f / bitmap_scale, 1.0f / bitmap_scale);
shader->setLocalMatrix(shader_scale);
// Set up our paint to use the shader & release our reference (now just owned
@@ -366,17 +379,22 @@ void Canvas::DrawStringInt(const string16& text,
std::vector<ShadowValue>());
}
-void Canvas::TileImageInt(const SkBitmap& bitmap,
+void Canvas::TileImageInt(const gfx::ImageSkia& image,
int x, int y, int w, int h) {
- TileImageInt(bitmap, 0, 0, x, y, w, h);
+ TileImageInt(image, 0, 0, x, y, w, h);
}
-void Canvas::TileImageInt(const SkBitmap& bitmap,
+void Canvas::TileImageInt(const gfx::ImageSkia& image,
int src_x, int src_y,
int dest_x, int dest_y, int w, int h) {
if (!IntersectsClipRectInt(dest_x, dest_y, w, h))
return;
+ float bitmap_scale;
+ const SkBitmap& bitmap = GetBitmapToPaint(image, &bitmap_scale);
+ if (bitmap.isNull())
+ return;
+
SkPaint paint;
SkShader* shader = SkShader::CreateBitmapShader(bitmap,
@@ -392,6 +410,8 @@ void Canvas::TileImageInt(const SkBitmap& bitmap,
canvas_->translate(SkIntToScalar(dest_x - src_x),
SkIntToScalar(dest_y - src_y));
ClipRect(gfx::Rect(src_x, src_y, w, h));
+ canvas_->scale(SkFloatToScalar(1.0f / bitmap_scale),
+ SkFloatToScalar(1.0f / bitmap_scale));
canvas_->drawPaint(paint);
canvas_->restore();
}
@@ -420,4 +440,29 @@ bool Canvas::IntersectsClipRect(const gfx::Rect& rect) {
rect.width(), rect.height());
}
+
+const SkBitmap& Canvas::GetBitmapToPaint(const gfx::ImageSkia& image,
+ float* bitmap_scale_factor) const {
+ return GetBitmapToPaint(image, 1.0f, 1.0f, bitmap_scale_factor);
+}
+
+const SkBitmap& Canvas::GetBitmapToPaint(const gfx::ImageSkia& image,
+ float user_additional_scale_x,
+ float user_additional_scale_y,
+ float* bitmap_scale_factor) const {
+ SkMatrix m = canvas_->getTotalMatrix();
+ float scale_x = SkScalarToFloat(SkScalarAbs(m.getScaleX())) *
+ user_additional_scale_x;
+ float scale_y = SkScalarToFloat(SkScalarAbs(m.getScaleY())) *
+ user_additional_scale_y;
+
+ const SkBitmap& bitmap = image.GetBitmapForScale(scale_x, scale_y,
+ bitmap_scale_factor);
+ if (!bitmap.isNull() &&
+ (scale_x < *bitmap_scale_factor || scale_y < *bitmap_scale_factor))
+ const_cast<SkBitmap&>(bitmap).buildMipMap();
+
+ return bitmap;
+}
+
} // namespace gfx
diff --git a/ui/gfx/canvas.h b/ui/gfx/canvas.h
index 7653f39..69f402b 100644
--- a/ui/gfx/canvas.h
+++ b/ui/gfx/canvas.h
@@ -12,6 +12,7 @@
#include "base/memory/scoped_ptr.h"
#include "base/string16.h"
#include "skia/ext/platform_canvas.h"
+#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/native_widget_types.h"
class SkBitmap;
@@ -240,47 +241,43 @@ class UI_EXPORT Canvas {
// Draws the given path using the given |paint| parameters.
void DrawPath(const SkPath& path, const SkPaint& paint);
- // Draws a bitmap with the origin at the specified location. The upper left
+ // Draws an image with the origin at the specified location. The upper left
// corner of the bitmap is rendered at the specified location.
- void DrawBitmapInt(const SkBitmap& bitmap, int x, int y);
+ // Parameters are specified relative to current canvas scale not in pixels.
+ // Thus, |x| is 2 pixels if canvas scale = 2 & |x| = 1.
+ void DrawBitmapInt(const gfx::ImageSkia&, int x, int y);
- // Draws a bitmap with the origin at the specified location, using the
+ // Draws an image with the origin at the specified location, using the
// specified paint. The upper left corner of the bitmap is rendered at the
// specified location.
- void DrawBitmapInt(const SkBitmap& bitmap,
+ // Parameters are specified relative to current canvas scale not in pixels.
+ // Thus, |x| is 2 pixels if canvas scale = 2 & |x| = 1.
+ void DrawBitmapInt(const gfx::ImageSkia& image,
int x, int y,
const SkPaint& paint);
- // Draws a portion of a bitmap in the specified location. The src parameters
+ // Draws a portion of an image in the specified location. The src parameters
// correspond to the region of the bitmap to draw in the region defined
// by the dest coordinates.
//
// If the width or height of the source differs from that of the destination,
- // the bitmap will be scaled. When scaling down, it is highly recommended
- // that you call buildMipMap(false) on your bitmap to ensure that it has
- // a mipmap, which will result in much higher-quality output. Set |filter|
- // to use filtering for bitmaps, otherwise the nearest-neighbor algorithm
- // is used for resampling.
+ // the image will be scaled. When scaling down, a mipmap will be generated.
+ // Set |filter| to use filtering for images, otherwise the nearest-neighbor
+ // algorithm is used for resampling.
//
// An optional custom SkPaint can be provided.
- void DrawBitmapInt(const SkBitmap& bitmap,
+ // Parameters are specified relative to current canvas scale not in pixels.
+ // Thus, |x| is 2 pixels if canvas scale = 2 & |x| = 1.
+ void DrawBitmapInt(const gfx::ImageSkia& image,
int src_x, int src_y, int src_w, int src_h,
int dest_x, int dest_y, int dest_w, int dest_h,
bool filter);
- void DrawBitmapInt(const SkBitmap& bitmap,
+ void DrawBitmapInt(const gfx::ImageSkia& image,
int src_x, int src_y, int src_w, int src_h,
int dest_x, int dest_y, int dest_w, int dest_h,
bool filter,
const SkPaint& paint);
- // TODO(pkotwicz): make this function private once gfx::ImageSkia stops
- // calling this method.
- void DrawBitmapFloat(const SkBitmap& bitmap,
- float src_x, float src_y, float src_w, float src_h,
- float dest_x, float dest_y, float dest_w, float dest_h,
- bool filter,
- const SkPaint& paint);
-
// Draws text with the specified color, font and location. The text is
// aligned to the left, vertically centered, clipped to the region. If the
// text is too big, it is truncated and '...' is added to the end.
@@ -315,9 +312,11 @@ class UI_EXPORT Canvas {
void DrawFocusRect(const gfx::Rect& rect);
// Tiles the image in the specified region.
- void TileImageInt(const SkBitmap& bitmap,
+ // Parameters are specified relative to current canvas scale not in pixels.
+ // Thus, |x| is 2 pixels if canvas scale = 2 & |x| = 1.
+ void TileImageInt(const gfx::ImageSkia& image,
int x, int y, int w, int h);
- void TileImageInt(const SkBitmap& bitmap,
+ void TileImageInt(const gfx::ImageSkia& image,
int src_x, int src_y,
int dest_x, int dest_y, int w, int h);
@@ -354,6 +353,19 @@ class UI_EXPORT Canvas {
bool IntersectsClipRectInt(int x, int y, int w, int h);
bool IntersectsClipRect(const gfx::Rect& rect);
+ // Returns the bitmap whose density best matches the current canvas scale.
+ // Returns a null bitmap if |image| contains no bitmaps.
+ // |bitmap_scale_factor| is set to the scale factor of the returned bitmap.
+ // Builds mip map for returned bitmap if necessary.
+ //
+ // An optional additional user defined scale can be provided.
+ const SkBitmap& GetBitmapToPaint(const gfx::ImageSkia& image,
+ float* bitmap_scale_factor) const;
+ const SkBitmap& GetBitmapToPaint(const gfx::ImageSkia& image,
+ float user_defined_scale_factor_x,
+ float user_defined_scale_factor_y,
+ float* bitmap_scale_factor) const;
+
#if defined(OS_WIN)
// Draws text with the specified color, font and location. The text is
// aligned to the left, vertically centered, clipped to the region. If the
diff --git a/ui/gfx/image/image.cc b/ui/gfx/image/image.cc
index e748dd9..dac2ccc 100644
--- a/ui/gfx/image/image.cc
+++ b/ui/gfx/image/image.cc
@@ -31,7 +31,8 @@ namespace internal {
#if defined(OS_MACOSX)
// This is a wrapper around gfx::NSImageToSkBitmap() because this cross-platform
// file cannot include the [square brackets] of ObjC.
-bool NSImageToSkBitmaps(NSImage* image, std::vector<const SkBitmap*>* bitmaps);
+ImageSkia NSImageToImageSkia(NSImage* image);
+NSImage* ImageSkiaToNSImage(const ImageSkia* image);
#endif
#if defined(TOOLKIT_GTK)
@@ -97,6 +98,7 @@ class ImageRep {
class ImageRepSkia : public ImageRep {
public:
+ // Takes ownership of |image|.
explicit ImageRepSkia(ImageSkia* image)
: ImageRep(Image::kImageRepSkia),
image_(image) {
@@ -224,6 +226,13 @@ Image::Image() {
// |storage_| is NULL for empty Images.
}
+Image::Image(const ImageSkia& image)
+ : storage_(new internal::ImageStorage(Image::kImageRepSkia)) {
+ internal::ImageRepSkia* rep = new internal::ImageRepSkia(
+ new ImageSkia(image));
+ AddRepresentation(rep);
+}
+
Image::Image(const SkBitmap* bitmap)
: storage_(new internal::ImageStorage(Image::kImageRepSkia)) {
internal::ImageRepSkia* rep = new internal::ImageRepSkia(
@@ -238,13 +247,6 @@ Image::Image(const SkBitmap& bitmap)
AddRepresentation(rep);
}
-Image::Image(const std::vector<const SkBitmap*>& bitmaps)
- : storage_(new internal::ImageStorage(Image::kImageRepSkia)) {
- internal::ImageRepSkia* rep = new internal::ImageRepSkia(
- new ImageSkia(bitmaps));
- AddRepresentation(rep);
-}
-
#if defined(TOOLKIT_GTK)
Image::Image(GdkPixbuf* pixbuf)
: storage_(new internal::ImageStorage(Image::kImageRepGdk)) {
@@ -274,7 +276,7 @@ Image::~Image() {
const SkBitmap* Image::ToSkBitmap() const {
internal::ImageRep* rep = GetRepresentation(Image::kImageRepSkia);
- return rep->AsImageRepSkia()->image()->bitmaps()[0];
+ return rep->AsImageRepSkia()->image()->bitmap();
}
const ImageSkia* Image::ToImageSkia() const {
@@ -301,6 +303,10 @@ NSImage* Image::ToNSImage() const {
}
#endif
+ImageSkia* Image::CopyImageSkia() const {
+ return new ImageSkia(*ToImageSkia());
+}
+
SkBitmap* Image::CopySkBitmap() const {
return new SkBitmap(*ToSkBitmap());
}
@@ -386,9 +392,8 @@ internal::ImageRep* Image::GetRepresentation(
#elif defined(OS_MACOSX)
if (storage_->default_representation_type() == Image::kImageRepCocoa) {
internal::ImageRepCocoa* nsimage_rep = default_rep->AsImageRepCocoa();
- std::vector<const SkBitmap*> bitmaps;
- CHECK(internal::NSImageToSkBitmaps(nsimage_rep->image(), &bitmaps));
- rep = new internal::ImageRepSkia(new ImageSkia(bitmaps));
+ ImageSkia image_skia = internal::NSImageToImageSkia(nsimage_rep->image());
+ rep = new internal::ImageRepSkia(new ImageSkia(image_skia));
}
#endif
CHECK(rep);
@@ -417,13 +422,13 @@ internal::ImageRep* Image::GetRepresentation(
#elif defined(TOOLKIT_GTK)
if (rep_type == Image::kImageRepGdk) {
GdkPixbuf* pixbuf = gfx::GdkPixbufFromSkBitmap(
- default_rep->AsImageRepSkia()->image()->bitmaps()[0]);
+ default_rep->AsImageRepSkia()->image()->bitmap());
native_rep = new internal::ImageRepGdk(pixbuf);
}
#elif defined(OS_MACOSX)
if (rep_type == Image::kImageRepCocoa) {
- NSImage* image = gfx::SkBitmapsToNSImage(
- default_rep->AsImageRepSkia()->image()->bitmaps());
+ NSImage* image = internal::ImageSkiaToNSImage(
+ default_rep->AsImageRepSkia()->image());
base::mac::NSObjectRetain(image);
native_rep = new internal::ImageRepCocoa(image);
}
diff --git a/ui/gfx/image/image.h b/ui/gfx/image/image.h
index 9c0e6eb..b5bb3bf 100644
--- a/ui/gfx/image/image.h
+++ b/ui/gfx/image/image.h
@@ -62,6 +62,9 @@ class UI_EXPORT Image {
// Creates an empty image with no representations.
Image();
+ // Creates a new image with the default representation.
+ explicit Image(const ImageSkia& image);
+
// Creates a new image with the default representation. The object will take
// ownership of the image.
explicit Image(const SkBitmap* bitmap);
@@ -70,10 +73,6 @@ class UI_EXPORT Image {
// representation.
explicit Image(const SkBitmap& bitmap);
- // To create an Image that supports multiple resolutions pass a vector
- // of bitmaps, one for each resolution.
- explicit Image(const std::vector<const SkBitmap*>& bitmaps);
-
#if defined(TOOLKIT_GTK)
// Does not increase |pixbuf|'s reference count; expects to take ownership.
explicit Image(GdkPixbuf* pixbuf);
@@ -112,6 +111,7 @@ class UI_EXPORT Image {
// backing pixels are shared amongst all copies (a fact of each of the
// converted representations, rather than a limitation imposed by Image) and
// so the result should be considered immutable.
+ ImageSkia* CopyImageSkia() const;
SkBitmap* CopySkBitmap() const;
#if defined(TOOLKIT_GTK)
GdkPixbuf* CopyGdkPixbuf() const;
diff --git a/ui/gfx/image/image_mac.mm b/ui/gfx/image/image_mac.mm
index 55b4aa4..eeed857 100644
--- a/ui/gfx/image/image_mac.mm
+++ b/ui/gfx/image/image_mac.mm
@@ -1,25 +1,46 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#import <AppKit/AppKit.h>
+#import <vector>
+#include "base/memory/scoped_nsobject.h"
#include "base/memory/scoped_ptr.h"
#include "skia/ext/skia_utils_mac.h"
#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/image/image_skia.h"
namespace gfx {
namespace internal {
-bool NSImageToSkBitmaps(NSImage* image, std::vector<const SkBitmap*>* bitmaps) {
+gfx::ImageSkia NSImageToImageSkia(NSImage* image) {
+ gfx::ImageSkia image_skia;
for (NSImageRep* imageRep in [image representations]) {
- scoped_ptr<SkBitmap> bitmap(new SkBitmap(
- gfx::NSImageRepToSkBitmap(imageRep, [imageRep size], false)));
- if (bitmap->isNull())
- return false;
- bitmaps->push_back(bitmap.release());
+ NSSize imageRepSize = [imageRep size];
+ SkBitmap bitmap(gfx::NSImageRepToSkBitmap(imageRep, imageRepSize, false));
+ if (!bitmap.isNull() && !bitmap.empty()) {
+ float scaleFactor = imageRepSize.width / [image size].width;
+ image_skia.AddBitmapForScale(bitmap, scaleFactor);
+ }
}
- return true;
+ return image_skia;
+}
+
+NSImage* ImageSkiaToNSImage(const gfx::ImageSkia* image_skia) {
+ if (image_skia->empty())
+ return nil;
+
+ scoped_nsobject<NSImage> image([[NSImage alloc] init]);
+
+ const std::vector<SkBitmap> bitmaps = image_skia->bitmaps();
+ for (std::vector<SkBitmap>::const_iterator it = bitmaps.begin();
+ it != bitmaps.end(); ++it) {
+ [image addRepresentation:gfx::SkBitmapToNSBitmapImageRep(*it)];
+ }
+
+ [image setSize:NSMakeSize(image_skia->width(), image_skia->height())];
+ return [image.release() autorelease];
}
} // namespace internal
diff --git a/ui/gfx/image/image_mac_unittest.mm b/ui/gfx/image/image_mac_unittest.mm
index f0ed004..1de9c64 100644
--- a/ui/gfx/image/image_mac_unittest.mm
+++ b/ui/gfx/image/image_mac_unittest.mm
@@ -6,6 +6,7 @@
#include "base/logging.h"
#include "base/memory/scoped_nsobject.h"
+#include "base/memory/scoped_ptr.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/image/image.h"
@@ -31,57 +32,61 @@ class ImageMacTest : public testing::Test {
namespace gt = gfx::test;
-TEST_F(ImageMacTest, MultiResolutionNSImageToSkBitmap) {
- const int width1 = 10;
- const int height1 = 12;
- const int width2 = 20;
- const int height2 = 24;
+TEST_F(ImageMacTest, MultiResolutionNSImageToImageSkia) {
+ const int width1x = 10;
+ const int height1x = 12;
+ const int width2x = 20;
+ const int height2x = 24;
NSImageRep* image_rep_1;
- CreateBitmapImageRep(width1, height1, &image_rep_1);
+ CreateBitmapImageRep(width1x, height1x, &image_rep_1);
NSImageRep* image_rep_2;
- CreateBitmapImageRep(width2, height2, &image_rep_2);
+ CreateBitmapImageRep(width2x, height2x, &image_rep_2);
scoped_nsobject<NSImage> ns_image(
- [[NSImage alloc] initWithSize:NSMakeSize(width1, height1)]);
+ [[NSImage alloc] initWithSize:NSMakeSize(width1x, height1x)]);
[ns_image addRepresentation:image_rep_1];
[ns_image addRepresentation:image_rep_2];
gfx::Image image(ns_image.release());
EXPECT_EQ(1u, image.RepresentationCount());
- const std::vector<const SkBitmap*>& bitmaps = image.ToImageSkia()->bitmaps();
- EXPECT_EQ(2u, bitmaps.size());
-
- const SkBitmap* bitmap1 = bitmaps[0];
- EXPECT_TRUE(bitmap1);
- const SkBitmap* bitmap2 = bitmaps[1];
- EXPECT_TRUE(bitmap2);
-
- if (bitmap1->width() == width1) {
- EXPECT_EQ(bitmap1->height(), height1);
- EXPECT_EQ(bitmap2->width(), width2);
- EXPECT_EQ(bitmap2->height(), height2);
- } else {
- EXPECT_EQ(bitmap1->width(), width2);
- EXPECT_EQ(bitmap1->height(), height2);
- EXPECT_EQ(bitmap2->width(), width1);
- EXPECT_EQ(bitmap2->height(), height1);
- }
+
+ const gfx::ImageSkia* image_skia = image.ToImageSkia();
+ EXPECT_EQ(2u, image_skia->bitmaps().size());
+
+ float scale_factor;
+ const SkBitmap& bitmap1x = image_skia->GetBitmapForScale(1.0f, 1.0f,
+ &scale_factor);
+ EXPECT_TRUE(!bitmap1x.isNull());
+ EXPECT_EQ(1.0f, scale_factor);
+ EXPECT_EQ(width1x, bitmap1x.width());
+ EXPECT_EQ(height1x, bitmap1x.height());
+
+ const SkBitmap& bitmap2x = image_skia->GetBitmapForScale(2.0f, 2.0f,
+ &scale_factor);
+ EXPECT_TRUE(!bitmap2x.isNull());
+ EXPECT_EQ(2.0f, scale_factor);
+ EXPECT_EQ(width2x, bitmap2x.width());
+ EXPECT_EQ(height2x, bitmap2x.height());
// ToImageSkia should create a second representation.
EXPECT_EQ(2u, image.RepresentationCount());
}
-TEST_F(ImageMacTest, MultiResolutionSkBitmapToNSImage) {
- const int width1 = 10;
- const int height1 = 12;
- const int width2 = 20;
- const int height2 = 24;
+TEST_F(ImageMacTest, MultiResolutionImageSkiaToNSImage) {
+ const int width1x = 10;
+ const int height1x= 12;
+ const int width2x = 20;
+ const int height2x = 24;
+
+ scoped_ptr<SkBitmap> bitmap1x(gt::CreateBitmap(width1x, height1x));
+ scoped_ptr<SkBitmap> bitmap2x(gt::CreateBitmap(width2x, height2x));
- std::vector<const SkBitmap*> bitmaps;
- bitmaps.push_back(gt::CreateBitmap(width1, height1));
- bitmaps.push_back(gt::CreateBitmap(width2, height2));
- gfx::Image image(bitmaps);
+ gfx::ImageSkia image_skia;
+ image_skia.AddBitmapForScale(*bitmap1x, 1.0f);
+ image_skia.AddBitmapForScale(*bitmap2x, 2.0f);
+
+ gfx::Image image(image_skia);
EXPECT_EQ(1u, image.RepresentationCount());
EXPECT_EQ(2u, image.ToImageSkia()->bitmaps().size());
@@ -89,19 +94,24 @@ TEST_F(ImageMacTest, MultiResolutionSkBitmapToNSImage) {
NSImage* ns_image = image;
EXPECT_TRUE(ns_image);
+ // Image size should be the same as the 1x bitmap.
+ EXPECT_EQ([ns_image size].width, width1x);
+ EXPECT_EQ([ns_image size].height, height1x);
+
EXPECT_EQ(2u, [[image representations] count]);
NSImageRep* image_rep_1 = [[image representations] objectAtIndex:0];
NSImageRep* image_rep_2 = [[image representations] objectAtIndex:1];
- if ([image_rep_1 size].width == width1) {
- EXPECT_EQ([image_rep_1 size].height, height1);
- EXPECT_EQ([image_rep_2 size].width, width2);
- EXPECT_EQ([image_rep_2 size].height, height2);
+ if ([image_rep_1 size].width == width1x) {
+ EXPECT_EQ([image_rep_1 size].width, width1x);
+ EXPECT_EQ([image_rep_1 size].height, height1x);
+ EXPECT_EQ([image_rep_2 size].width, width2x);
+ EXPECT_EQ([image_rep_2 size].height, height2x);
} else {
- EXPECT_EQ([image_rep_1 size].width, width2);
- EXPECT_EQ([image_rep_1 size].height, height2);
- EXPECT_EQ([image_rep_2 size].width, width1);
- EXPECT_EQ([image_rep_2 size].height, height1);
+ EXPECT_EQ([image_rep_1 size].width, width2x);
+ EXPECT_EQ([image_rep_1 size].height, height2x);
+ EXPECT_EQ([image_rep_2 size].width, width1x);
+ EXPECT_EQ([image_rep_2 size].height, height1x);
}
// Cast to NSImage* should create a second representation.
diff --git a/ui/gfx/image/image_skia.cc b/ui/gfx/image/image_skia.cc
index 3c2e94f..d7ad469c 100644
--- a/ui/gfx/image/image_skia.cc
+++ b/ui/gfx/image/image_skia.cc
@@ -8,139 +8,200 @@
#include <cmath>
#include "base/logging.h"
-#include "base/stl_util.h"
+#include "ui/gfx/size.h"
+#include "base/message_loop.h"
+#include "third_party/skia/include/core/SkPixelRef.h"
namespace gfx {
-ImageSkia::ImageSkia(const SkBitmap* bitmap)
- : size_(bitmap->width(), bitmap->height()),
- mip_map_build_pending_(false) {
- CHECK(bitmap);
- // TODO(pkotwicz): Add a CHECK to ensure that !bitmap->isNull()
- bitmaps_.push_back(bitmap);
-}
-
-ImageSkia::ImageSkia(const std::vector<const SkBitmap*>& bitmaps)
- : bitmaps_(bitmaps),
- mip_map_build_pending_(false) {
- CHECK(!bitmaps_.empty());
- // TODO(pkotwicz): Add a CHECK to ensure that !bitmap->isNull() for each
- // vector element.
- // Assume that the smallest bitmap represents 1x scale factor.
- for (size_t i = 0; i < bitmaps_.size(); ++i) {
- gfx::Size bitmap_size(bitmaps_[i]->width(), bitmaps_[i]->height());
- if (size_.IsEmpty() || bitmap_size.GetArea() < size_.GetArea())
- size_ = bitmap_size;
+namespace internal {
+
+// 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() {
}
-}
-ImageSkia::~ImageSkia() {
- STLDeleteElements(&bitmaps_);
-}
+ void AddBitmap(const SkBitmap& bitmap) {
+ bitmaps_.push_back(bitmap);
+ }
-void ImageSkia::BuildMipMap() {
- mip_map_build_pending_ = true;
-}
+ const std::vector<SkBitmap>& bitmaps() const { return bitmaps_; }
-void ImageSkia::DrawToCanvasInt(gfx::Canvas* canvas, int x, int y) {
- SkPaint p;
- DrawToCanvasInt(canvas, x, y, p);
-}
+ void set_size(const gfx::Size& size) { size_ = size; }
+ const gfx::Size& size() const { return size_; }
-void ImageSkia::DrawToCanvasInt(gfx::Canvas* canvas,
- int x, int y,
- const SkPaint& paint) {
+ private:
+ ~ImageSkiaStorage() {
+ }
- if (IsZeroSized())
- return;
+ // Bitmaps at different densities.
+ std::vector<SkBitmap> bitmaps_;
- SkMatrix m = canvas->sk_canvas()->getTotalMatrix();
- float scale_x = std::abs(SkScalarToFloat(m.getScaleX()));
- float scale_y = std::abs(SkScalarToFloat(m.getScaleY()));
+ // Size of the image in DIP.
+ gfx::Size size_;
- const SkBitmap* bitmap = GetBitmapForScale(scale_x, scale_y);
+ friend class base::RefCounted<ImageSkiaStorage>;
+};
- if (mip_map_build_pending_) {
- const_cast<SkBitmap*>(bitmap)->buildMipMap();
- mip_map_build_pending_ = false;
- }
+} // internal
- float bitmap_scale_x = static_cast<float>(bitmap->width()) / width();
- float bitmap_scale_y = static_cast<float>(bitmap->height()) / height();
+ImageSkia::ImageSkia() : storage_(NULL) {
+}
- canvas->Save();
- canvas->sk_canvas()->scale(1.0f / bitmap_scale_x,
- 1.0f / bitmap_scale_y);
- canvas->sk_canvas()->drawBitmap(*bitmap, SkFloatToScalar(x * bitmap_scale_x),
- SkFloatToScalar(y * bitmap_scale_y));
- canvas->Restore();
+ImageSkia::ImageSkia(const SkBitmap& bitmap) {
+ Init(bitmap);
}
-void ImageSkia::DrawToCanvasInt(gfx::Canvas* canvas,
- int src_x, int src_y, int src_w, int src_h,
- int dest_x, int dest_y, int dest_w, int dest_h,
- bool filter) {
- SkPaint p;
- DrawToCanvasInt(canvas, src_x, src_y, src_w, src_h, dest_x, dest_y,
- dest_w, dest_h, filter, p);
+ImageSkia::ImageSkia(const SkBitmap& bitmap, float dip_scale_factor) {
+ Init(bitmap, dip_scale_factor);
}
-void ImageSkia::DrawToCanvasInt(gfx::Canvas* canvas,
- int src_x, int src_y, int src_w, int src_h,
- int dest_x, int dest_y, int dest_w, int dest_h,
- bool filter,
- const SkPaint& paint) {
- if (IsZeroSized())
- return;
+ImageSkia::ImageSkia(const SkBitmap* bitmap) {
+ Init(*bitmap);
- SkMatrix m = canvas->sk_canvas()->getTotalMatrix();
- float scale_x = std::abs(SkScalarToFloat(m.getScaleX()));
- float scale_y = std::abs(SkScalarToFloat(m.getScaleY()));
+ if (MessageLoop::current()) {
+ // Use DeleteSoon such that |bitmap| is still valid if caller uses |bitmap|
+ // immediately after having called constructor.
+ MessageLoop::current()->DeleteSoon(FROM_HERE, bitmap);
+ } else {
+ // Hit in unittests.
+ delete bitmap;
+ }
+}
+
+ImageSkia::ImageSkia(const ImageSkia& other) : storage_(other.storage_) {
+}
+
+ImageSkia& ImageSkia::operator=(const ImageSkia& other) {
+ storage_ = other.storage_;
+ return *this;
+}
- const SkBitmap* bitmap = GetBitmapForScale(scale_x, scale_y);
+ImageSkia& ImageSkia::operator=(const SkBitmap& other) {
+ Init(other);
+ return *this;
+}
- if (mip_map_build_pending_) {
- const_cast<SkBitmap*>(bitmap)->buildMipMap();
- mip_map_build_pending_ = false;
+ImageSkia::operator SkBitmap&() const {
+ if (isNull()) {
+ // TODO(pkotwicz): This is temporary till conversion to gfx::ImageSkia is
+ // done.
+ // Static null bitmap such that we are not returning a temporary.
+ static SkBitmap* null_bitmap = new SkBitmap();
+ return *null_bitmap;
}
- float bitmap_scale_x = static_cast<float>(bitmap->width()) / width();
- float bitmap_scale_y = static_cast<float>(bitmap->height()) / height();
+ return const_cast<SkBitmap&>(storage_->bitmaps()[0]);
+}
- canvas->Save();
- canvas->sk_canvas()->scale(1.0f / bitmap_scale_x,
- 1.0f / bitmap_scale_y);
- canvas->DrawBitmapFloat(*bitmap,
- src_x * bitmap_scale_x, src_y * bitmap_scale_x,
- src_w * bitmap_scale_x, src_h * bitmap_scale_y,
- dest_x * bitmap_scale_x, dest_y * bitmap_scale_y,
- dest_w * bitmap_scale_x, dest_h * bitmap_scale_y,
- filter, paint);
+ImageSkia::~ImageSkia() {
+}
- canvas->Restore();
+void ImageSkia::AddBitmapForScale(const SkBitmap& bitmap,
+ float dip_scale_factor) {
+ DCHECK(!bitmap.isNull());
+
+ if (isNull()) {
+ Init(bitmap, dip_scale_factor);
+ } else {
+ // We currently assume that the bitmap size = 1x size * |dip_scale_factor|.
+ // TODO(pkotwicz): Do something better because of rounding errors when
+ // |dip_scale_factor| is not an int.
+ // TODO(pkotwicz): Remove DCHECK for dip_scale_factor == 1.0f once
+ // image_loading_tracker correctly handles multiple sized images.
+ DCHECK(dip_scale_factor == 1.0f ||
+ static_cast<int>(width() * dip_scale_factor) == bitmap.width());
+ DCHECK(dip_scale_factor == 1.0f ||
+ static_cast<int>(height() * dip_scale_factor) == bitmap.height());
+ storage_->AddBitmap(bitmap);
+ }
}
-const SkBitmap* ImageSkia::GetBitmapForScale(float x_scale_factor,
- float y_scale_factor) const {
+const SkBitmap& ImageSkia::GetBitmapForScale(float x_scale_factor,
+ float y_scale_factor,
+ float* bitmap_scale_factor) const {
+
+ // Static null bitmap such that we are not returning a temporary.
+ static SkBitmap* null_bitmap = new SkBitmap();
+
+ if (empty())
+ return *null_bitmap;
+
// Get the desired bitmap width and height given |x_scale_factor|,
- // |y_scale_factor| and |size_| at 1x density.
- float desired_width = size_.width() * x_scale_factor;
- float desired_height = size_.height() * y_scale_factor;
+ // |y_scale_factor| and size at 1x density.
+ float desired_width = width() * x_scale_factor;
+ float desired_height = height() * y_scale_factor;
+ const std::vector<SkBitmap>& bitmaps = storage_->bitmaps();
size_t closest_index = 0;
float smallest_diff = std::numeric_limits<float>::max();
- for (size_t i = 0; i < bitmaps_.size(); ++i) {
- if (bitmaps_[i]->isNull())
- continue;
-
- float diff = std::abs(bitmaps_[i]->width() - desired_width) +
- std::abs(bitmaps_[i]->height() - desired_height);
+ for (size_t i = 0; i < bitmaps.size(); ++i) {
+ float diff = std::abs(bitmaps[i].width() - desired_width) +
+ std::abs(bitmaps[i].height() - desired_height);
if (diff < smallest_diff) {
closest_index = i;
smallest_diff = diff;
}
}
- return bitmaps_[closest_index];
+ if (smallest_diff < std::numeric_limits<float>::max()) {
+ *bitmap_scale_factor = bitmaps[closest_index].width() / width();
+ return bitmaps[closest_index];
+ }
+
+ return *null_bitmap;
+}
+
+bool ImageSkia::empty() const {
+ return isNull() || storage_->size().IsEmpty();
+}
+
+int ImageSkia::width() const {
+ return isNull() ? 0 : storage_->size().width();
+}
+
+int ImageSkia::height() const {
+ return isNull() ? 0 : storage_->size().height();
+}
+
+bool ImageSkia::extractSubset(ImageSkia* dst, SkIRect& subset) const {
+ if (isNull())
+ return false;
+ SkBitmap dst_bitmap;
+ bool return_value = storage_->bitmaps()[0].extractSubset(&dst_bitmap,
+ subset);
+ *dst = ImageSkia(dst_bitmap);
+ return return_value;
+}
+
+const std::vector<SkBitmap> ImageSkia::bitmaps() const {
+ return storage_->bitmaps();
+}
+
+const SkBitmap* ImageSkia::bitmap() const {
+ if (isNull())
+ return NULL;
+
+ return &storage_->bitmaps()[0];
+}
+
+void ImageSkia::Init(const SkBitmap& bitmap) {
+ Init(bitmap, 1.0f);
+}
+
+void ImageSkia::Init(const SkBitmap& bitmap, float scale_factor) {
+ DCHECK_GT(scale_factor, 0.0f);
+ // TODO(pkotwicz): The image should be null whenever bitmap is null.
+ if (bitmap.empty()) {
+ storage_ = NULL;
+ return;
+ }
+ storage_ = new internal::ImageSkiaStorage();
+ storage_->set_size(gfx::Size(static_cast<int>(bitmap.width() / scale_factor),
+ static_cast<int>(bitmap.height() / scale_factor)));
+ storage_->AddBitmap(bitmap);
}
} // namespace gfx
diff --git a/ui/gfx/image/image_skia.h b/ui/gfx/image/image_skia.h
index bdfb53f..8b911cb 100644
--- a/ui/gfx/image/image_skia.h
+++ b/ui/gfx/image/image_skia.h
@@ -9,80 +9,119 @@
#include <vector>
#include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
#include "third_party/skia/include/core/SkBitmap.h"
-#include "ui/gfx/canvas.h"
-#include "ui/gfx/size.h"
+#include "ui/base/ui_export.h"
namespace gfx {
-// Container for the same image at different densities, similar to NSImage.
-// Smallest image is assumed to represent 1x density.
+namespace internal {
+class ImageSkiaStorage;
+} // namespace internal
-// ImageSkia should be used for caching and drawing images of different
-// densities. It should not be used as an SkBitmap wrapper.
+// Container for the same image at different densities, similar to NSImage.
+// Image height and width are in DIP (Device Indepent Pixel) coordinates.
+//
+// ImageSkia should be used whenever possible instead of SkBitmap.
+// Functions that mutate the image should operate on the SkBitmap returned
+// from ImageSkia::GetBitmapForScale, not on ImageSkia.
+//
+// ImageSkia is cheap to copy and intentionally supports copy semantics.
class UI_EXPORT ImageSkia {
public:
+ // Creates instance with no bitmaps.
+ ImageSkia();
+
+ // Adds ref to passed in bitmap.
+ // DIP width and height are set based on scale factor of 1x.
+ // TODO(pkotwicz): This is temporary till conversion to gfx::ImageSkia is
+ // done.
+ ImageSkia(const SkBitmap& bitmap);
+
+ // Adds ref to passed in bitmap.
+ // DIP width and height are set based on |dip_scale_factor|.
+ ImageSkia(const SkBitmap& bitmap, float dip_scale_factor);
+
+ // Takes ownership of passed in bitmap.
+ // Caller should not assume that |bitmap| will be valid after constructor
+ // is called.
+ // DIP width and height are set based on scale factor of 1x.
+ // TODO(pkotwicz): This is temporary till conversion to gfx::ImageSkia is
+ // done.
explicit ImageSkia(const SkBitmap* bitmap);
- explicit ImageSkia(const std::vector<const SkBitmap*>& bitmaps);
- ~ImageSkia();
- // Build mipmap at time of next call to |DrawToCanvasInt|.
- void BuildMipMap();
-
- // Draws the image with the origin at the specified location. The upper left
- // corner of the image is rendered at the specified location.
- void DrawToCanvasInt(Canvas* canvas, int x, int y);
-
- // Draws the image with the origin at the specified location, using the
- // specified paint. The upper left corner of the image is rendered at the
- // specified location.
- void DrawToCanvasInt(Canvas* canvas,
- int x, int y,
- const SkPaint& paint);
-
- // Draws a portion of the image in the specified location. The src parameters
- // correspond to the region of the image to draw in the region defined
- // by the dest coordinates.
- //
- // If the width or height of the source differs from that of the destination,
- // the image will be scaled. When scaling down, it is highly recommended
- // that you call BuildMipMap() on your image to ensure that it has
- // a mipmap, which will result in much higher-quality output. Set |filter| to
- // use filtering for bitmaps, otherwise the nearest-neighbor algorithm is used
- // for resampling.
- //
- // An optional custom SkPaint can be provided.
- void DrawToCanvasInt(Canvas* canvas,
- int src_x, int src_y, int src_w, int src_h,
- int dest_x, int dest_y, int dest_w, int dest_h,
- bool filter);
- void DrawToCanvasInt(Canvas* canvas,
- int src_x, int src_y, int src_w, int src_h,
- int dest_x, int dest_y, int dest_w, int dest_h,
- bool filter,
- const SkPaint& paint);
-
- // Returns true if |size_| is empty.
- bool IsZeroSized() const { return size_.IsEmpty(); }
+ // Copies a reference to |other|'s storage.
+ ImageSkia(const ImageSkia& other);
- // Width and height of image in DIP coordinate system.
- int width() const { return size_.width(); }
- int height() const { return size_.height(); }
+ // Copies a reference to |other|'s storage.
+ ImageSkia& operator=(const ImageSkia& other);
- // Returns a vector with the SkBitmaps contained in this object.
- const std::vector<const SkBitmap*>& bitmaps() const { return bitmaps_; }
+ // Converts from SkBitmap.
+ // Adds ref to passed in bitmap.
+ // DIP width and height are set based on scale factor of 1x.
+ // TODO(pkotwicz): This is temporary till conversion to gfx::ImageSkia is
+ // done.
+ ImageSkia& operator=(const SkBitmap& other);
+
+ // Converts to SkBitmap.
+ // TODO(pkotwicz): This is temporary till conversion to gfx::ImageSkia is
+ // done.
+ operator SkBitmap&() const;
+
+ ~ImageSkia();
+
+ // Adds |bitmap| for |dip_scale_factor| to bitmaps contained by this object.
+ // Adds ref to passed in bitmap.
+ // DIP width and height are set based on |dip_scale_factor|.
+ void AddBitmapForScale(const SkBitmap& bitmap, float dip_scale_factor);
- private:
// Returns the bitmap whose density best matches |x_scale_factor| and
// |y_scale_factor|.
- const SkBitmap* GetBitmapForScale(float x_scale_factor,
- float y_scale_factor) const;
+ // Returns a null bitmap if object contains no bitmaps.
+ // |bitmap_scale_factor| is set to the scale factor of the returned bitmap.
+ const SkBitmap& GetBitmapForScale(float x_scale_factor,
+ float y_scale_factor,
+ float* bitmap_scale_factor) const;
+
+ // Returns true if object is null or |size_| is empty.
+ bool empty() const;
+
+ // Returns true if this is a null object.
+ // TODO(pkotwicz): Merge this function into empty().
+ bool isNull() const { return storage_ == NULL; }
+
+ // Width and height of image in DIP coordinate system.
+ int width() const;
+ int height() const;
- std::vector<const SkBitmap*> bitmaps_;
- gfx::Size size_;
- bool mip_map_build_pending_;
+ // Wrapper function for SkBitmap::extractBitmap.
+ // Operates on bitmap at index 0 if available.
+ // TODO(pkotwicz): This is temporary till conversion to gfx::ImageSkia is
+ // done.
+ bool extractSubset(ImageSkia* dst, SkIRect& subset) const;
- DISALLOW_COPY_AND_ASSIGN(ImageSkia);
+ // Returns pointer to an SkBitmap contained by this object.
+ // TODO(pkotwicz): This is temporary till conversion to gfx::ImageSkia is
+ // done.
+ const SkBitmap* bitmap() const;
+
+ // Returns a vector with the SkBitmaps contained in this object.
+ const std::vector<SkBitmap> bitmaps() const;
+
+ private:
+ // Initialize ImageStorage with passed in parameters.
+ // If |bitmap.isNull()|, ImageStorage is set to NULL.
+ // Scale factor is set based on default scale factor of 1x.
+ // TODO(pkotwicz): This is temporary till conversion to gfx::ImageSkia is
+ // done.
+ void Init(const SkBitmap& bitmap);
+
+ // Initialize ImageStorage with passed in parameters.
+ // If |bitmap.isNull()|, ImageStorage is set to NULL.
+ void Init(const SkBitmap& bitmap, float scale_factor);
+
+ // A refptr so that ImageRepSkia can be copied cheaply.
+ scoped_refptr<internal::ImageSkiaStorage> storage_;
};
} // namespace gfx
diff --git a/ui/gfx/image/image_unittest.cc b/ui/gfx/image/image_unittest.cc
index 8793562..7b50be8 100644
--- a/ui/gfx/image/image_unittest.cc
+++ b/ui/gfx/image/image_unittest.cc
@@ -251,41 +251,39 @@ TEST_F(ImageTest, Assign) {
EXPECT_EQ(image1.ToSkBitmap(), image2.ToSkBitmap());
}
-TEST_F(ImageTest, MultiResolutionSkBitmap) {
- const int width1 = 10;
- const int height1 = 12;
- const int width2 = 20;
- const int height2 = 24;
-
- std::vector<const SkBitmap*> bitmaps;
- bitmaps.push_back(gt::CreateBitmap(width1, height1));
- bitmaps.push_back(gt::CreateBitmap(width2, height2));
- gfx::Image image(bitmaps);
-
- EXPECT_EQ(1u, image.RepresentationCount());
- const std::vector<const SkBitmap*>& image_bitmaps =
- image.ToImageSkia()->bitmaps();
- EXPECT_EQ(2u, image_bitmaps.size());
-
- const SkBitmap* bitmap1 = image_bitmaps[0];
- EXPECT_TRUE(bitmap1);
- const SkBitmap* bitmap2 = image_bitmaps[1];
- EXPECT_TRUE(bitmap2);
-
- if (bitmap1->width() == width1) {
- EXPECT_EQ(bitmap1->height(), height1);
- EXPECT_EQ(bitmap2->width(), width2);
- EXPECT_EQ(bitmap2->height(), height2);
- } else {
- EXPECT_EQ(bitmap1->width(), width2);
- EXPECT_EQ(bitmap1->height(), height2);
- EXPECT_EQ(bitmap2->width(), width1);
- EXPECT_EQ(bitmap2->height(), height1);
- }
-
- // Sanity check.
+TEST_F(ImageTest, MultiResolutionImage) {
+ const int width1x = 10;
+ const int height1x = 12;
+ const int width2x = 20;
+ const int height2x = 24;
+
+ scoped_ptr<SkBitmap> bitmap1(gt::CreateBitmap(width1x, height1x));
+ scoped_ptr<SkBitmap> bitmap2(gt::CreateBitmap(width2x, height2x));
+
+ gfx::ImageSkia image_skia;
+ image_skia.AddBitmapForScale(*bitmap1, 1.0f);
+ image_skia.AddBitmapForScale(*bitmap2, 2.0f);
+
+ EXPECT_EQ(2u, image_skia.bitmaps().size());
+
+ float scale_factor;
+ const SkBitmap& bitmap1x = image_skia.GetBitmapForScale(1.0f, 1.0f,
+ &scale_factor);
+ EXPECT_TRUE(!bitmap1x.isNull());
+ EXPECT_EQ(1.0f, scale_factor);
+ EXPECT_EQ(width1x, bitmap1x.width());
+ EXPECT_EQ(height1x, bitmap1x.height());
+
+ const SkBitmap& bitmap2x = image_skia.GetBitmapForScale(2.0f, 2.0f,
+ &scale_factor);
+ EXPECT_TRUE(!bitmap2x.isNull());
+ EXPECT_EQ(2.0f, scale_factor);
+ EXPECT_EQ(width2x, bitmap2x.width());
+ EXPECT_EQ(height2x, bitmap2x.height());
+
+ // Check that the image has a single representation.
+ gfx::Image image(image_skia);
EXPECT_EQ(1u, image.RepresentationCount());
- EXPECT_EQ(2u, image.ToImageSkia()->bitmaps().size());
}
// Integration tests with UI toolkit frameworks require linking against the