summaryrefslogtreecommitdiffstats
path: root/cc
diff options
context:
space:
mode:
authorvmpstr@chromium.org <vmpstr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-20 01:14:59 +0000
committervmpstr@chromium.org <vmpstr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-04-20 01:14:59 +0000
commitf95cc396f40937df6c0ae299ef0a94bf33945ecb (patch)
tree8b03ec6c06c79f8585bda2ddbe2bf197f2749b7d /cc
parent8b6bee0aa93f3947f297644ea7947cf91b9681f6 (diff)
downloadchromium_src-f95cc396f40937df6c0ae299ef0a94bf33945ecb.zip
chromium_src-f95cc396f40937df6c0ae299ef0a94bf33945ecb.tar.gz
chromium_src-f95cc396f40937df6c0ae299ef0a94bf33945ecb.tar.bz2
cc: Add base64 encoding to picture
This adds ability to serialize cc::Picture to base64 string and to initialize the picture back from that serialization. Review URL: https://chromiumcodereview.appspot.com/13884018 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@195361 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'cc')
-rw-r--r--cc/cc_tests.gyp1
-rw-r--r--cc/resources/picture.cc86
-rw-r--r--cc/resources/picture.h6
-rw-r--r--cc/resources/picture_unittest.cc124
4 files changed, 216 insertions, 1 deletions
diff --git a/cc/cc_tests.gyp b/cc/cc_tests.gyp
index 144cfb5..7271c61 100644
--- a/cc/cc_tests.gyp
+++ b/cc/cc_tests.gyp
@@ -51,6 +51,7 @@
'resources/picture_layer_tiling_set_unittest.cc',
'resources/picture_layer_tiling_unittest.cc',
'resources/picture_pile_impl_unittest.cc',
+ 'resources/picture_unittest.cc',
'resources/prioritized_resource_unittest.cc',
'trees/quad_culler_unittest.cc',
'base/region_unittest.cc',
diff --git a/cc/resources/picture.cc b/cc/resources/picture.cc
index 2b6eca8..b54e08f 100644
--- a/cc/resources/picture.cc
+++ b/cc/resources/picture.cc
@@ -2,15 +2,18 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "cc/resources/picture.h"
+
+#include "base/base64.h"
#include "base/debug/trace_event.h"
#include "cc/debug/rendering_stats.h"
#include "cc/layers/content_layer_client.h"
-#include "cc/resources/picture.h"
#include "skia/ext/analysis_canvas.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkData.h"
#include "third_party/skia/include/core/SkDrawFilter.h"
#include "third_party/skia/include/core/SkPaint.h"
+#include "third_party/skia/include/core/SkStream.h"
#include "third_party/skia/include/utils/SkPictureUtils.h"
#include "ui/gfx/rect_conversions.h"
#include "ui/gfx/skia_util.h"
@@ -18,6 +21,11 @@
namespace {
// URI label for a lazily decoded SkPixelRef.
const char kLabelLazyDecoded[] = "lazy";
+// Version ID; to be used in serialization.
+const int kPictureVersion = 1;
+// Minimum size of a decoded stream that we need.
+// 4 bytes for version, 4 * 4 for each of the 2 rects.
+const unsigned int kMinPictureSizeBytes = 36;
class DisableLCDTextFilter : public SkDrawFilter {
public:
@@ -38,10 +46,59 @@ scoped_refptr<Picture> Picture::Create(gfx::Rect layer_rect) {
return make_scoped_refptr(new Picture(layer_rect));
}
+scoped_refptr<Picture> Picture::CreateFromBase64String(
+ const std::string& encoded_string) {
+ bool success;
+ scoped_refptr<Picture> picture =
+ make_scoped_refptr(new Picture(encoded_string, &success));
+ if (!success)
+ picture = NULL;
+ return picture;
+}
+
Picture::Picture(gfx::Rect layer_rect)
: layer_rect_(layer_rect) {
}
+Picture::Picture(const std::string& encoded_string, bool* success) {
+ // Decode the picture from base64.
+ std::string decoded;
+ base::Base64Decode(encoded_string, &decoded);
+ SkMemoryStream stream(decoded.data(), decoded.size());
+
+ if (decoded.size() < kMinPictureSizeBytes) {
+ *success = false;
+ return;
+ }
+
+ int version = stream.readS32();
+ if (version != kPictureVersion) {
+ *success = false;
+ return;
+ }
+
+ // First, read the layer and opaque rects.
+ int layer_rect_x = stream.readS32();
+ int layer_rect_y = stream.readS32();
+ int layer_rect_width = stream.readS32();
+ int layer_rect_height = stream.readS32();
+ layer_rect_ = gfx::Rect(layer_rect_x,
+ layer_rect_y,
+ layer_rect_width,
+ layer_rect_height);
+ int opaque_rect_x = stream.readS32();
+ int opaque_rect_y = stream.readS32();
+ int opaque_rect_width = stream.readS32();
+ int opaque_rect_height = stream.readS32();
+ opaque_rect_ = gfx::Rect(opaque_rect_x,
+ opaque_rect_y,
+ opaque_rect_width,
+ opaque_rect_height);
+
+ // Read the picture. This creates an empty picture on failure.
+ picture_ = skia::AdoptRef(new SkPicture(&stream, success, NULL));
+}
+
Picture::Picture(const skia::RefPtr<SkPicture>& picture,
gfx::Rect layer_rect,
gfx::Rect opaque_rect) :
@@ -178,4 +235,31 @@ void Picture::GatherPixelRefs(const gfx::Rect& layer_rect,
pixel_refs->unref();
}
+void Picture::AsBase64String(std::string* output) const {
+ SkDynamicMemoryWStream stream;
+
+ // First save the version, layer_rect_ and opaque_rect.
+ stream.write32(kPictureVersion);
+
+ stream.write32(layer_rect_.x());
+ stream.write32(layer_rect_.y());
+ stream.write32(layer_rect_.width());
+ stream.write32(layer_rect_.height());
+
+ stream.write32(opaque_rect_.x());
+ stream.write32(opaque_rect_.y());
+ stream.write32(opaque_rect_.width());
+ stream.write32(opaque_rect_.height());
+
+ // Serialize the picture.
+ picture_->serialize(&stream);
+
+ // Encode the picture as base64.
+ size_t serialized_size = stream.bytesWritten();
+ scoped_ptr<char[]> serialized_picture(new char[serialized_size]);
+ stream.copyTo(serialized_picture.get());
+ base::Base64Encode(std::string(serialized_picture.get(), serialized_size),
+ output);
+}
+
} // namespace cc
diff --git a/cc/resources/picture.h b/cc/resources/picture.h
index 8598fbf..a29d5af 100644
--- a/cc/resources/picture.h
+++ b/cc/resources/picture.h
@@ -6,6 +6,7 @@
#define CC_RESOURCES_PICTURE_H_
#include <list>
+#include <string>
#include <vector>
#include "base/basictypes.h"
@@ -30,6 +31,8 @@ class CC_EXPORT Picture
: public base::RefCountedThreadSafe<Picture> {
public:
static scoped_refptr<Picture> Create(gfx::Rect layer_rect);
+ static scoped_refptr<Picture> CreateFromBase64String(
+ const std::string& encoded_string);
const gfx::Rect& LayerRect() const { return layer_rect_; }
const gfx::Rect& OpaqueRect() const { return opaque_rect_; }
@@ -59,8 +62,11 @@ class CC_EXPORT Picture
const gfx::Rect& layer_rect,
std::list<skia::LazyPixelRef*>& pixel_ref_list);
+ void AsBase64String(std::string* output) const;
+
private:
explicit Picture(gfx::Rect layer_rect);
+ Picture(const std::string& encoded_string, bool* success);
// This constructor assumes SkPicture is already ref'd and transfers
// ownership to this picture.
Picture(const skia::RefPtr<SkPicture>&,
diff --git a/cc/resources/picture_unittest.cc b/cc/resources/picture_unittest.cc
new file mode 100644
index 0000000..f20c547
--- /dev/null
+++ b/cc/resources/picture_unittest.cc
@@ -0,0 +1,124 @@
+// Copyright 2013 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 "cc/resources/picture.h"
+
+#include "base/memory/ref_counted.h"
+#include "cc/test/fake_content_layer_client.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkDevice.h"
+#include "third_party/skia/include/core/SkGraphics.h"
+#include "third_party/skia/include/core/SkTileGridPicture.h"
+#include "ui/gfx/rect.h"
+#include "ui/gfx/skia_util.h"
+
+namespace cc {
+namespace {
+
+void DrawPicture(unsigned char* buffer,
+ gfx::Rect layer_rect,
+ scoped_refptr<Picture> picture) {
+ SkBitmap bitmap;
+ bitmap.setConfig(SkBitmap::kARGB_8888_Config,
+ layer_rect.width(),
+ layer_rect.height());
+ bitmap.setPixels(buffer);
+ SkDevice device(bitmap);
+ SkCanvas canvas(&device);
+ canvas.clipRect(gfx::RectToSkRect(layer_rect));
+ picture->Raster(&canvas, layer_rect, 1.0f, false);
+}
+
+TEST(PictureTest, AsBase64String) {
+ SkGraphics::Init();
+
+ gfx::Rect layer_rect(100, 100);
+
+ SkTileGridPicture::TileGridInfo tile_grid_info;
+ tile_grid_info.fTileInterval = SkISize::Make(100, 100);
+ tile_grid_info.fMargin.setEmpty();
+ tile_grid_info.fOffset.setZero();
+
+ FakeContentLayerClient content_layer_client;
+
+ SkPaint red_paint;
+ red_paint.setColor(SkColorSetARGB(255, 255, 0, 0));
+ SkPaint green_paint;
+ green_paint.setColor(SkColorSetARGB(255, 0, 255, 0));
+
+ // Invalid picture (not base64).
+ scoped_refptr<Picture> invalid_picture =
+ Picture::CreateFromBase64String("abc!@#$%");
+ EXPECT_TRUE(!invalid_picture);
+
+ // Invalid picture (empty string).
+ scoped_refptr<Picture> second_invalid_picture =
+ Picture::CreateFromBase64String("");
+ EXPECT_TRUE(!second_invalid_picture);
+
+ // Invalid picture (random base64 string).
+ scoped_refptr<Picture> third_invalid_picture =
+ Picture::CreateFromBase64String("ABCDABCDABCDABCDABCDABCDABCDABCDABCD"
+ "ABCDABCDABCDABCDABCDABCDABCDABCDABCD"
+ "ABCDABCDABCDABCDABCDABCDABCDABCDABCD"
+ "ABCDABCDABCDABCDABCDABCDABCDABCDABCD"
+ "ABCDABCDABCDABCDABCDABCDABCDABCDABCD"
+ "ABCDABCDABCDABCDABCDABCDABCDABCDABCD"
+ "ABCDABCDABCDABCDABCDABCDABCDABCDABCD");
+ EXPECT_TRUE(!third_invalid_picture);
+
+ // Single full-size rect picture.
+ content_layer_client.add_draw_rect(layer_rect, red_paint);
+ scoped_refptr<Picture> one_rect_picture = Picture::Create(layer_rect);
+ one_rect_picture->Record(&content_layer_client, NULL, tile_grid_info);
+ std::string serialized_one_rect;
+ one_rect_picture->AsBase64String(&serialized_one_rect);
+
+ // Reconstruct the picture.
+ scoped_refptr<Picture> one_rect_picture_check =
+ Picture::CreateFromBase64String(serialized_one_rect);
+ EXPECT_TRUE(!!one_rect_picture_check);
+
+ // Check for equivalence.
+ unsigned char one_rect_buffer[4 * 100 * 100] = {0};
+ DrawPicture(one_rect_buffer, layer_rect, one_rect_picture);
+ unsigned char one_rect_buffer_check[4 * 100 * 100] = {0};
+ DrawPicture(one_rect_buffer_check, layer_rect, one_rect_picture_check);
+
+ EXPECT_EQ(one_rect_picture->LayerRect(),
+ one_rect_picture_check->LayerRect());
+ EXPECT_EQ(one_rect_picture->OpaqueRect(),
+ one_rect_picture_check->OpaqueRect());
+ EXPECT_TRUE(
+ memcmp(one_rect_buffer, one_rect_buffer_check, 4 * 100 * 100) == 0);
+
+ // Two rect picture.
+ content_layer_client.add_draw_rect(gfx::Rect(25, 25, 50, 50), green_paint);
+ scoped_refptr<Picture> two_rect_picture = Picture::Create(layer_rect);
+ two_rect_picture->Record(&content_layer_client, NULL, tile_grid_info);
+ std::string serialized_two_rect;
+ two_rect_picture->AsBase64String(&serialized_two_rect);
+
+ // Reconstruct the picture.
+ scoped_refptr<Picture> two_rect_picture_check =
+ Picture::CreateFromBase64String(serialized_two_rect);
+ EXPECT_TRUE(!!two_rect_picture_check);
+
+ // Check for equivalence.
+ unsigned char two_rect_buffer[4 * 100 * 100] = {0};
+ DrawPicture(two_rect_buffer, layer_rect, two_rect_picture);
+ unsigned char two_rect_buffer_check[4 * 100 * 100] = {0};
+ DrawPicture(two_rect_buffer_check, layer_rect, two_rect_picture_check);
+
+ EXPECT_EQ(two_rect_picture->LayerRect(),
+ two_rect_picture_check->LayerRect());
+ EXPECT_EQ(two_rect_picture->OpaqueRect(),
+ two_rect_picture_check->OpaqueRect());
+ EXPECT_TRUE(
+ memcmp(two_rect_buffer, two_rect_buffer_check, 4 * 100 * 100) == 0);
+}
+
+} // namespace
+} // namespace cc