diff options
author | reed <reed@google.com> | 2015-08-28 06:43:25 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-08-28 13:43:50 +0000 |
commit | 47c0625da08aa28d4fc8c0743ac7bab5739346d0 (patch) | |
tree | 7b5161683cc3f413e3d20fb73e67c057c4f6cb4e | |
parent | 25b4f71939bcb300e586eefc4bcf5c0fe5cb81a7 (diff) | |
download | chromium_src-47c0625da08aa28d4fc8c0743ac7bab5739346d0.zip chromium_src-47c0625da08aa28d4fc8c0743ac7bab5739346d0.tar.gz chromium_src-47c0625da08aa28d4fc8c0743ac7bab5739346d0.tar.bz2 |
clone pixel_ref_utils into discardable_image_utils, since blink now creates images instead of bitmaps. When this is in place, we can remove pixel_ref_utils.
BUG=
Review URL: https://codereview.chromium.org/1306293004
Cr-Commit-Position: refs/heads/master@{#346134}
-rw-r--r-- | skia/ext/discardable_image_utils.cc | 134 | ||||
-rw-r--r-- | skia/ext/discardable_image_utils.h | 33 | ||||
-rw-r--r-- | skia/ext/discardable_image_utils_unittest.cc | 185 | ||||
-rw-r--r-- | skia/skia_chrome.gypi | 1 | ||||
-rw-r--r-- | skia/skia_tests.gyp | 1 |
5 files changed, 354 insertions, 0 deletions
diff --git a/skia/ext/discardable_image_utils.cc b/skia/ext/discardable_image_utils.cc new file mode 100644 index 0000000..f447ff9 --- /dev/null +++ b/skia/ext/discardable_image_utils.cc @@ -0,0 +1,134 @@ +// Copyright 2015 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. + +#include "skia/ext/discardable_image_utils.h" + +#include <algorithm> + +#include "third_party/skia/include/core/SkCanvas.h" +#include "third_party/skia/include/core/SkImage.h" +#include "third_party/skia/include/utils/SkNWayCanvas.h" + +namespace skia { + +namespace { + +class DiscardableImageSet { + public: + DiscardableImageSet(std::vector<DiscardableImageUtils::PositionImage>* images) + : images_(images) {} + + void Add(const SkImage* image, + const SkRect& rect, + const SkMatrix& matrix, + SkFilterQuality filter_quality) { + // We should only be saving discardable pixel refs. + SkASSERT(image->isLazyGenerated()); + + DiscardableImageUtils::PositionImage position_image; + position_image.image = image; + position_image.image_rect = rect; + position_image.matrix = matrix; + position_image.filter_quality = filter_quality; + images_->push_back(position_image); + } + + private: + std::vector<DiscardableImageUtils::PositionImage>* images_; +}; + +SkRect MapRect(const SkMatrix& matrix, const SkRect& src) { + SkRect dst; + matrix.mapRect(&dst, src); + return dst; +} + +class GatherDiscardableImageCanvas : public SkNWayCanvas { + public: + GatherDiscardableImageCanvas(int width, + int height, + DiscardableImageSet* image_set) + : SkNWayCanvas(width, height), + image_set_(image_set), + canvas_bounds_(SkRect::MakeIWH(width, height)) {} + + protected: + // we need to "undo" the behavio of SkNWayCanvas, which will try to forward + // it. + void onDrawPicture(const SkPicture* picture, + const SkMatrix* matrix, + const SkPaint* paint) override { + SkCanvas::onDrawPicture(picture, matrix, paint); + } + + void onDrawImage(const SkImage* image, + SkScalar x, + SkScalar y, + const SkPaint* paint) override { + const SkMatrix& ctm = this->getTotalMatrix(); + AddImage(image, MapRect(ctm, SkRect::MakeXYWH(x, y, image->width(), + image->height())), + ctm, paint); + } + + void onDrawImageRect(const SkImage* image, + const SkRect* src, + const SkRect& dst, + const SkPaint* paint, + SrcRectConstraint) override { + const SkMatrix& ctm = this->getTotalMatrix(); + SkRect src_storage; + if (!src) { + src_storage = SkRect::MakeIWH(image->width(), image->height()); + src = &src_storage; + } + SkMatrix matrix; + matrix.setRectToRect(*src, dst, SkMatrix::kFill_ScaleToFit); + matrix.postConcat(ctm); + AddImage(image, MapRect(ctm, dst), matrix, paint); + } + + void onDrawImageNine(const SkImage* image, + const SkIRect& center, + const SkRect& dst, + const SkPaint* paint) override { + AddImage(image, dst, this->getTotalMatrix(), paint); + } + + private: + DiscardableImageSet* image_set_; + const SkRect canvas_bounds_; + + void AddImage(const SkImage* image, + const SkRect& rect, + const SkMatrix& matrix, + const SkPaint* paint) { + if (rect.intersects(canvas_bounds_) && image->isLazyGenerated()) { + SkFilterQuality filter_quality = kNone_SkFilterQuality; + if (paint) { + filter_quality = paint->getFilterQuality(); + } + image_set_->Add(image, rect, matrix, filter_quality); + } + } +}; + +} // namespace + +void DiscardableImageUtils::GatherDiscardableImages( + SkPicture* picture, + std::vector<PositionImage>* images) { + images->clear(); + DiscardableImageSet image_set(images); + + SkIRect picture_ibounds = picture->cullRect().roundOut(); + // Use right/bottom as the size so that we don't need a translate and, as a + // result, the information is returned relative to the picture's origin. + GatherDiscardableImageCanvas canvas(picture_ibounds.right(), + picture_ibounds.bottom(), &image_set); + + canvas.drawPicture(picture); +} + +} // namespace skia diff --git a/skia/ext/discardable_image_utils.h b/skia/ext/discardable_image_utils.h new file mode 100644 index 0000000..b2d7c93 --- /dev/null +++ b/skia/ext/discardable_image_utils.h @@ -0,0 +1,33 @@ +// Copyright 2015 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. + +#ifndef SKIA_EXT_PIXEL_REF_UTILS_H_ +#define SKIA_EXT_PIXEL_REF_UTILS_H_ + +#include <vector> + +#include "SkPicture.h" +#include "SkRect.h" + +namespace skia { + +class SK_API DiscardableImageUtils { + public: + struct PositionImage { + const SkImage* image; + SkRect image_rect; + SkMatrix matrix; + SkFilterQuality filter_quality; + }; + + static void GatherDiscardableImages(SkPicture* picture, + std::vector<PositionImage>* images); +}; + +using PositionImage = DiscardableImageUtils::PositionImage; +using DiscardableImageList = std::vector<PositionImage>; + +} // namespace skia + +#endif diff --git a/skia/ext/discardable_image_utils_unittest.cc b/skia/ext/discardable_image_utils_unittest.cc new file mode 100644 index 0000000..0357b61 --- /dev/null +++ b/skia/ext/discardable_image_utils_unittest.cc @@ -0,0 +1,185 @@ +// Copyright 2014 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. + +#include "base/compiler_specific.h" +#include "base/memory/scoped_ptr.h" +#include "cc/test/geometry_test_utils.h" +#include "skia/ext/discardable_image_utils.h" +#include "skia/ext/refptr.h" +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/skia/include/core/SkCanvas.h" +#include "third_party/skia/include/core/SkImage.h" +#include "third_party/skia/include/core/SkImageGenerator.h" +#include "third_party/skia/include/core/SkPictureRecorder.h" +#include "third_party/skia/src/core/SkOrderedReadBuffer.h" +#include "ui/gfx/geometry/rect.h" +#include "ui/gfx/skia_util.h" + +namespace skia { + +namespace { + +class TestImageGenerator : public SkImageGenerator { + public: + TestImageGenerator(const SkImageInfo& info) : SkImageGenerator(info) {} +}; + +skia::RefPtr<SkImage> CreateDiscardableImage(const gfx::Size& size) { + const SkImageInfo info = + SkImageInfo::MakeN32Premul(size.width(), size.height()); + return skia::AdoptRef( + SkImage::NewFromGenerator(new TestImageGenerator(info))); +} + +SkCanvas* StartRecording(SkPictureRecorder* recorder, gfx::Rect layer_rect) { + SkCanvas* canvas = + recorder->beginRecording(layer_rect.width(), layer_rect.height()); + + canvas->save(); + canvas->translate(-layer_rect.x(), -layer_rect.y()); + canvas->clipRect(SkRect::MakeXYWH(layer_rect.x(), layer_rect.y(), + layer_rect.width(), layer_rect.height())); + + return canvas; +} + +SkPicture* StopRecording(SkPictureRecorder* recorder, SkCanvas* canvas) { + canvas->restore(); + return recorder->endRecordingAsPicture(); +} + +void VerifyScales(SkScalar x_scale, + SkScalar y_scale, + const SkMatrix& matrix, + int source_line) { + SkSize scales; + bool success = matrix.decomposeScale(&scales); + EXPECT_TRUE(success) << "line: " << source_line; + EXPECT_FLOAT_EQ(x_scale, scales.width()) << "line: " << source_line; + EXPECT_FLOAT_EQ(y_scale, scales.height()) << "line: " << source_line; +} + +} // namespace + +TEST(DiscardableImageUtilsTest, DrawImage) { + gfx::Rect layer_rect(0, 0, 256, 256); + + SkPictureRecorder recorder; + SkCanvas* canvas = StartRecording(&recorder, layer_rect); + + skia::RefPtr<SkImage> first = CreateDiscardableImage(gfx::Size(50, 50)); + skia::RefPtr<SkImage> second = CreateDiscardableImage(gfx::Size(50, 50)); + skia::RefPtr<SkImage> third = CreateDiscardableImage(gfx::Size(50, 50)); + skia::RefPtr<SkImage> fourth = CreateDiscardableImage(gfx::Size(50, 1)); + skia::RefPtr<SkImage> fifth = CreateDiscardableImage(gfx::Size(10, 10)); + skia::RefPtr<SkImage> sixth = CreateDiscardableImage(gfx::Size(10, 10)); + + canvas->save(); + + // At (0, 0). + canvas->drawImage(first.get(), 0, 0); + canvas->translate(25, 0); + // At (25, 0). + canvas->drawImage(second.get(), 0, 0); + canvas->translate(0, 50); + // At (50, 50). + canvas->drawImage(third.get(), 25, 0); + + canvas->restore(); + canvas->save(); + + canvas->translate(1, 0); + canvas->rotate(90); + // At (1, 0), rotated 90 degrees + canvas->drawImage(fourth.get(), 0, 0); + + canvas->restore(); + canvas->save(); + + canvas->scale(5.f, 6.f); + // At (0, 0), scaled by 5 and 6 + canvas->drawImage(fifth.get(), 0, 0); + + canvas->restore(); + + canvas->rotate(27); + canvas->scale(3.3f, 0.4f); + + canvas->drawImage(sixth.get(), 0, 0); + + canvas->restore(); + + skia::RefPtr<SkPicture> picture = + skia::AdoptRef(StopRecording(&recorder, canvas)); + + std::vector<skia::DiscardableImageUtils::PositionImage> images; + skia::DiscardableImageUtils::GatherDiscardableImages(picture.get(), &images); + + EXPECT_EQ(6u, images.size()); + EXPECT_FLOAT_RECT_EQ(SkRect::MakeXYWH(0, 0, 50, 50), images[0].image_rect); + VerifyScales(1.f, 1.f, images[0].matrix, __LINE__); + EXPECT_EQ(kNone_SkFilterQuality, images[0].filter_quality); + EXPECT_FLOAT_RECT_EQ(gfx::RectF(25, 0, 50, 50), images[1].image_rect); + VerifyScales(1.f, 1.f, images[1].matrix, __LINE__); + EXPECT_EQ(kNone_SkFilterQuality, images[1].filter_quality); + EXPECT_FLOAT_RECT_EQ(gfx::RectF(50, 50, 50, 50), images[2].image_rect); + VerifyScales(1.f, 1.f, images[2].matrix, __LINE__); + EXPECT_EQ(kNone_SkFilterQuality, images[2].filter_quality); + EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 1, 50), images[3].image_rect); + VerifyScales(1.f, 1.f, images[3].matrix, __LINE__); + EXPECT_EQ(kNone_SkFilterQuality, images[3].filter_quality); + EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 50, 60), images[4].image_rect); + VerifyScales(5.f, 6.f, images[4].matrix, __LINE__); + EXPECT_EQ(kNone_SkFilterQuality, images[4].filter_quality); + EXPECT_FLOAT_RECT_EQ(gfx::RectF(-1.8159621f, 0, 31.219175f, 18.545712f), + images[5].image_rect); + VerifyScales(3.3f, 0.4f, images[5].matrix, __LINE__); + EXPECT_EQ(kNone_SkFilterQuality, images[5].filter_quality); +} + +TEST(DiscardableImageUtilsTest, DrawImageRect) { + gfx::Rect layer_rect(0, 0, 256, 256); + + SkPictureRecorder recorder; + SkCanvas* canvas = StartRecording(&recorder, layer_rect); + + skia::RefPtr<SkImage> first = CreateDiscardableImage(gfx::Size(50, 50)); + skia::RefPtr<SkImage> second = CreateDiscardableImage(gfx::Size(50, 50)); + skia::RefPtr<SkImage> third = CreateDiscardableImage(gfx::Size(50, 50)); + + canvas->save(); + + SkPaint paint; + + // (0, 0, 100, 100). + canvas->drawImageRect(first.get(), SkRect::MakeWH(100, 100), &paint); + canvas->translate(25, 0); + // (75, 50, 10, 10). + canvas->drawImageRect(second.get(), SkRect::MakeXYWH(50, 50, 10, 10), &paint); + canvas->translate(5, 50); + // (0, 30, 100, 100). + canvas->drawImageRect(third.get(), SkRect::MakeXYWH(-30, -20, 100, 100), + &paint); + + canvas->restore(); + + skia::RefPtr<SkPicture> picture = + skia::AdoptRef(StopRecording(&recorder, canvas)); + + std::vector<skia::DiscardableImageUtils::PositionImage> images; + skia::DiscardableImageUtils::GatherDiscardableImages(picture.get(), &images); + + EXPECT_EQ(3u, images.size()); + EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 0, 100, 100), images[0].image_rect); + VerifyScales(2.f, 2.f, images[0].matrix, __LINE__); + EXPECT_EQ(kNone_SkFilterQuality, images[0].filter_quality); + EXPECT_FLOAT_RECT_EQ(gfx::RectF(75, 50, 10, 10), images[1].image_rect); + VerifyScales(0.2f, 0.2f, images[1].matrix, __LINE__); + EXPECT_EQ(kNone_SkFilterQuality, images[1].filter_quality); + EXPECT_FLOAT_RECT_EQ(gfx::RectF(0, 30, 100, 100), images[2].image_rect); + VerifyScales(2.f, 2.f, images[2].matrix, __LINE__); + EXPECT_EQ(kNone_SkFilterQuality, images[2].filter_quality); +} + +} // namespace skia diff --git a/skia/skia_chrome.gypi b/skia/skia_chrome.gypi index 724cb86..9efc631 100644 --- a/skia/skia_chrome.gypi +++ b/skia/skia_chrome.gypi @@ -45,6 +45,7 @@ 'ext/platform_device_linux.cc', 'ext/platform_device_mac.cc', 'ext/platform_device_win.cc', + 'ext/discardable_image_utils.cc', 'ext/recursive_gaussian_convolution.cc', 'ext/SkDiscardableMemory_chrome.cc', 'ext/SkMemory_new_handler.cpp', diff --git a/skia/skia_tests.gyp b/skia/skia_tests.gyp index f120d7c..32afbdb 100644 --- a/skia/skia_tests.gyp +++ b/skia/skia_tests.gyp @@ -22,6 +22,7 @@ 'ext/analysis_canvas_unittest.cc', 'ext/bitmap_platform_device_mac_unittest.cc', 'ext/convolver_unittest.cc', + 'ext/discardable_image_utils_unittest.cc', 'ext/image_operations_unittest.cc', 'ext/pixel_ref_utils_unittest.cc', 'ext/platform_canvas_unittest.cc', |