aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Khushal <khushalsagar@chromium.org>2018-04-03 17:51:40 -0700
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-04-04 01:25:11 +0000
commit42f8bc40fd3702c801c9f5b9d438fabcc77fb58b (patch)
tree99f0fcd1ae3747d6553b9a77282442aa2693d78b
parent46117c83d22886286196f7965f5fdffeb7e43457 (diff)
Add API for SkTextBlob serialization into caller's memory.
R=reed@google.com Change-Id: Iaeb67504aabf0dc036e81fa23c1a3c949b72b2b9 Reviewed-on: https://skia-review.googlesource.com/114262 Commit-Queue: Khusal Sagar <khushalsagar@chromium.org> Reviewed-by: Mike Klein <mtklein@google.com> Reviewed-by: Mike Reed <reed@google.com>
-rw-r--r--include/core/SkFlattenable.h2
-rw-r--r--include/core/SkTextBlob.h6
-rw-r--r--src/core/SkFlattenable.cpp10
-rw-r--r--src/core/SkTextBlob.cpp7
-rw-r--r--tests/SerializationTest.cpp44
5 files changed, 69 insertions, 0 deletions
diff --git a/include/core/SkFlattenable.h b/include/core/SkFlattenable.h
index 05b8fba9a7..ed343c82ae 100644
--- a/include/core/SkFlattenable.h
+++ b/include/core/SkFlattenable.h
@@ -135,6 +135,8 @@ public:
// public ways to serialize / deserialize
//
sk_sp<SkData> serialize(const SkSerialProcs* = nullptr) const;
+ size_t serialize(void* memory, size_t memory_size,
+ const SkSerialProcs* = nullptr) const;
static sk_sp<SkFlattenable> Deserialize(Type, const void* data, size_t length,
const SkDeserialProcs* procs = nullptr);
diff --git a/include/core/SkTextBlob.h b/include/core/SkTextBlob.h
index 89c6697cc9..59151d3002 100644
--- a/include/core/SkTextBlob.h
+++ b/include/core/SkTextBlob.h
@@ -67,6 +67,12 @@ public:
sk_sp<SkData> serialize(SkTypefaceCatalogerProc, void* ctx) const;
/**
+ * Similar to serialize above, but writes directly into |memory|. Returns bytes written or 0u
+ * if serialization failed due to insufficient size.
+ */
+ size_t serialize(const SkSerialProcs& procs, void* memory, size_t memory_size) const;
+
+ /**
* Re-create a text blob previously serialized. Since the serialized form records the uniqueIDs
* of its typefaces, deserialization requires that the caller provide the corresponding
* SkTypefaces for those IDs.
diff --git a/src/core/SkFlattenable.cpp b/src/core/SkFlattenable.cpp
index 0c673181a7..c8766f88be 100644
--- a/src/core/SkFlattenable.cpp
+++ b/src/core/SkFlattenable.cpp
@@ -154,6 +154,16 @@ sk_sp<SkData> SkFlattenable::serialize(const SkSerialProcs* procs) const {
return data;
}
+size_t SkFlattenable::serialize(void* memory, size_t memory_size,
+ const SkSerialProcs* procs) const {
+ SkBinaryWriteBuffer writer(memory, memory_size);
+ if (procs) {
+ writer.setSerialProcs(*procs);
+ }
+ writer.writeFlattenable(this);
+ return writer.usingInitialStorage() ? writer.bytesWritten() : 0u;
+}
+
sk_sp<SkFlattenable> SkFlattenable::Deserialize(SkFlattenable::Type type, const void* data,
size_t size, const SkDeserialProcs* procs) {
SkReadBuffer buffer(data, size);
diff --git a/src/core/SkTextBlob.cpp b/src/core/SkTextBlob.cpp
index 182cf72ec2..eac2430f5f 100644
--- a/src/core/SkTextBlob.cpp
+++ b/src/core/SkTextBlob.cpp
@@ -912,6 +912,13 @@ sk_sp<SkData> SkTextBlob::serialize(SkTypefaceCatalogerProc proc, void* ctx) con
return this->serialize(procs);
}
+size_t SkTextBlob::serialize(const SkSerialProcs& procs, void* memory, size_t memory_size) const {
+ SkBinaryWriteBuffer buffer(memory, memory_size);
+ buffer.setSerialProcs(procs);
+ this->flatten(buffer);
+ return buffer.usingInitialStorage() ? buffer.bytesWritten() : 0u;
+}
+
namespace {
struct ResolverState {
SkTypefaceResolverProc fProc;
diff --git a/tests/SerializationTest.cpp b/tests/SerializationTest.cpp
index da797398c1..c6d529b0cb 100644
--- a/tests/SerializationTest.cpp
+++ b/tests/SerializationTest.cpp
@@ -8,6 +8,7 @@
#include "Resources.h"
#include "SkAnnotationKeys.h"
#include "SkCanvas.h"
+#include "SkDashPathEffect.h"
#include "SkFixed.h"
#include "SkFontDescriptor.h"
#include "SkImage.h"
@@ -21,6 +22,7 @@
#include "SkShaderBase.h"
#include "SkTableColorFilter.h"
#include "SkTemplates.h"
+#include "SkTextBlob.h"
#include "SkTypeface.h"
#include "SkWriteBuffer.h"
#include "SkXfermodeImageFilter.h"
@@ -666,3 +668,45 @@ DEF_TEST(WriteBuffer_storage, reporter) {
REPORTER_ASSERT(reporter, !writer.usingInitialStorage()); // this is the change
REPORTER_ASSERT(reporter, writer.bytesWritten() == kSize);
}
+
+DEF_TEST(WriteBuffer_external_memory_textblob, reporter) {
+ SkPaint font;
+ font.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+ font.setTypeface(SkTypeface::MakeDefault());
+
+ SkTextBlobBuilder builder;
+ int glyph_count = 5;
+ const auto& run = builder.allocRun(font, glyph_count, 1.2f, 2.3f);
+ // allocRun() allocates only the glyph buffer.
+ std::fill(run.glyphs, run.glyphs + glyph_count, 0);
+ auto blob = builder.make();
+ SkSerialProcs procs;
+ SkAutoTMalloc<uint8_t> storage;
+ size_t blob_size = 0u;
+ size_t storage_size = 0u;
+
+ blob_size = SkAlign4(blob->serialize(procs)->size());
+ REPORTER_ASSERT(reporter, blob_size > 4u);
+ storage_size = blob_size - 4;
+ storage.realloc(storage_size);
+ REPORTER_ASSERT(reporter, blob->serialize(procs, storage.get(), storage_size) == 0u);
+ storage_size = blob_size;
+ storage.realloc(storage_size);
+ REPORTER_ASSERT(reporter, blob->serialize(procs, storage.get(), storage_size) != 0u);
+}
+
+DEF_TEST(WriteBuffer_external_memory_flattenable, reporter) {
+ SkScalar intervals[] = {1.f, 1.f};
+ auto path_effect = SkDashPathEffect::Make(intervals, 2, 0);
+ size_t path_size = SkAlign4(path_effect->serialize()->size());
+ REPORTER_ASSERT(reporter, path_size > 4u);
+ SkAutoTMalloc<uint8_t> storage;
+
+ size_t storage_size = path_size - 4;
+ storage.realloc(storage_size);
+ REPORTER_ASSERT(reporter, path_effect->serialize(storage.get(), storage_size) == 0u);
+
+ storage_size = path_size;
+ storage.realloc(storage_size);
+ REPORTER_ASSERT(reporter, path_effect->serialize(storage.get(), storage_size) != 0u);
+}