summaryrefslogtreecommitdiffstats
path: root/ui/gfx/image/image_skia.cc
diff options
context:
space:
mode:
Diffstat (limited to 'ui/gfx/image/image_skia.cc')
-rw-r--r--ui/gfx/image/image_skia.cc255
1 files changed, 97 insertions, 158 deletions
diff --git a/ui/gfx/image/image_skia.cc b/ui/gfx/image/image_skia.cc
index d7ad469c..3c2e94f 100644
--- a/ui/gfx/image/image_skia.cc
+++ b/ui/gfx/image/image_skia.cc
@@ -8,200 +8,139 @@
#include <cmath>
#include "base/logging.h"
-#include "ui/gfx/size.h"
-#include "base/message_loop.h"
-#include "third_party/skia/include/core/SkPixelRef.h"
+#include "base/stl_util.h"
namespace gfx {
-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() {
- }
-
- void AddBitmap(const SkBitmap& bitmap) {
- bitmaps_.push_back(bitmap);
- }
-
- const std::vector<SkBitmap>& bitmaps() const { return bitmaps_; }
-
- void set_size(const gfx::Size& size) { size_ = size; }
- const gfx::Size& size() const { return size_; }
-
- private:
- ~ImageSkiaStorage() {
+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;
}
+}
- // Bitmaps at different densities.
- std::vector<SkBitmap> bitmaps_;
-
- // Size of the image in DIP.
- gfx::Size size_;
-
- friend class base::RefCounted<ImageSkiaStorage>;
-};
-
-} // internal
-
-ImageSkia::ImageSkia() : storage_(NULL) {
+ImageSkia::~ImageSkia() {
+ STLDeleteElements(&bitmaps_);
}
-ImageSkia::ImageSkia(const SkBitmap& bitmap) {
- Init(bitmap);
+void ImageSkia::BuildMipMap() {
+ mip_map_build_pending_ = true;
}
-ImageSkia::ImageSkia(const SkBitmap& bitmap, float dip_scale_factor) {
- Init(bitmap, dip_scale_factor);
+void ImageSkia::DrawToCanvasInt(gfx::Canvas* canvas, int x, int y) {
+ SkPaint p;
+ DrawToCanvasInt(canvas, x, y, p);
}
-ImageSkia::ImageSkia(const SkBitmap* bitmap) {
- Init(*bitmap);
+void ImageSkia::DrawToCanvasInt(gfx::Canvas* canvas,
+ int x, int y,
+ const SkPaint& paint) {
+
+ if (IsZeroSized())
+ return;
+
+ SkMatrix m = canvas->sk_canvas()->getTotalMatrix();
+ float scale_x = std::abs(SkScalarToFloat(m.getScaleX()));
+ float scale_y = std::abs(SkScalarToFloat(m.getScaleY()));
+
+ const SkBitmap* bitmap = GetBitmapForScale(scale_x, scale_y);
- 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;
+ if (mip_map_build_pending_) {
+ const_cast<SkBitmap*>(bitmap)->buildMipMap();
+ mip_map_build_pending_ = false;
}
-}
-ImageSkia::ImageSkia(const ImageSkia& other) : storage_(other.storage_) {
-}
+ float bitmap_scale_x = static_cast<float>(bitmap->width()) / width();
+ float bitmap_scale_y = static_cast<float>(bitmap->height()) / height();
-ImageSkia& ImageSkia::operator=(const ImageSkia& other) {
- storage_ = other.storage_;
- return *this;
+ 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::operator=(const SkBitmap& other) {
- Init(other);
- return *this;
+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::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;
- }
+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;
- return const_cast<SkBitmap&>(storage_->bitmaps()[0]);
-}
+ SkMatrix m = canvas->sk_canvas()->getTotalMatrix();
+ float scale_x = std::abs(SkScalarToFloat(m.getScaleX()));
+ float scale_y = std::abs(SkScalarToFloat(m.getScaleY()));
-ImageSkia::~ImageSkia() {
-}
+ const SkBitmap* bitmap = GetBitmapForScale(scale_x, scale_y);
-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);
+ if (mip_map_build_pending_) {
+ const_cast<SkBitmap*>(bitmap)->buildMipMap();
+ mip_map_build_pending_ = false;
}
-}
-const SkBitmap& ImageSkia::GetBitmapForScale(float x_scale_factor,
- float y_scale_factor,
- float* bitmap_scale_factor) const {
+ float bitmap_scale_x = static_cast<float>(bitmap->width()) / width();
+ float bitmap_scale_y = static_cast<float>(bitmap->height()) / height();
- // Static null bitmap such that we are not returning a temporary.
- static SkBitmap* null_bitmap = new SkBitmap();
+ 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);
- if (empty())
- return *null_bitmap;
+ canvas->Restore();
+}
+const SkBitmap* ImageSkia::GetBitmapForScale(float x_scale_factor,
+ float y_scale_factor) const {
// Get the desired bitmap width and height given |x_scale_factor|,
- // |y_scale_factor| and size at 1x density.
- float desired_width = width() * x_scale_factor;
- float desired_height = height() * y_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;
- 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) {
- 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) {
+ if (bitmaps_[i]->isNull())
+ continue;
+
+ 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;
}
}
- 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);
+ return bitmaps_[closest_index];
}
} // namespace gfx