Commit 741b4b0a authored by Khushal's avatar Khushal Committed by Commit Bot

cc: Allow serialization failure for paths.

We currently assume that a path will always serialize to a non-zero size,
and so we should always get a valid path at deserialization. But SkPath
may return a zero size indicating that the given path can not be
serialized. Account for that and just bail out serializing this path.

R=enne@chromium.org

Bug: 924042
Change-Id: I467003ea90efd5915b24b032d079bde2c3c5cacd
Reviewed-on: https://chromium-review.googlesource.com/c/1481084
Commit-Queue: Khushal <khushalsagar@chromium.org>
Reviewed-by: default avatarenne <enne@chromium.org>
Cr-Commit-Position: refs/heads/master@{#634901}
parent 2ba4b0c6
......@@ -37,6 +37,13 @@ namespace cc {
using PaintCacheId = uint32_t;
using PaintCacheIds = std::vector<PaintCacheId>;
enum class PaintCacheDataType : uint32_t { kTextBlob, kPath, kLast = kPath };
enum class PaintCacheEntryState : uint32_t {
kEmpty,
kCached,
kInlined,
kLast = kInlined
};
constexpr size_t PaintCacheDataTypeCount =
static_cast<uint32_t>(PaintCacheDataType::kLast) + 1u;
......
......@@ -215,33 +215,45 @@ void PaintOpReader::Read(SkPath* path) {
if (!valid_)
return;
size_t path_bytes = 0u;
ReadSize(&path_bytes);
if (path_bytes > remaining_bytes_)
SetInvalid();
if (!valid_)
uint32_t entry_state_int = 0u;
ReadSimple(&entry_state_int);
if (entry_state_int > static_cast<uint32_t>(PaintCacheEntryState::kLast)) {
valid_ = false;
return;
}
if (path_bytes != 0u) {
auto* scratch = CopyScratchSpace(path_bytes);
size_t bytes_read = path->readFromMemory(scratch, path_bytes);
if (bytes_read == 0u) {
SetInvalid();
auto entry_state = static_cast<PaintCacheEntryState>(entry_state_int);
switch (entry_state) {
case PaintCacheEntryState::kEmpty:
return;
case PaintCacheEntryState::kCached: {
auto* cached_path = options_.paint_cache->GetPath(path_id);
if (!cached_path)
SetInvalid();
else
*path = *cached_path;
return;
}
case PaintCacheEntryState::kInlined: {
size_t path_bytes = 0u;
ReadSize(&path_bytes);
if (path_bytes > remaining_bytes_ || path_bytes == 0u)
SetInvalid();
if (!valid_)
return;
options_.paint_cache->PutPath(path_id, *path);
memory_ += path_bytes;
remaining_bytes_ -= path_bytes;
return;
}
auto* cached_path = options_.paint_cache->GetPath(path_id);
if (!cached_path) {
SetInvalid();
return;
auto* scratch = CopyScratchSpace(path_bytes);
size_t bytes_read = path->readFromMemory(scratch, path_bytes);
if (bytes_read == 0u) {
SetInvalid();
return;
}
options_.paint_cache->PutPath(path_id, *path);
memory_ += path_bytes;
remaining_bytes_ -= path_bytes;
return;
}
}
*path = *cached_path;
}
void PaintOpReader::Read(PaintFlags* flags) {
......
......@@ -173,18 +173,27 @@ void PaintOpWriter::Write(const SkPath& path) {
auto id = path.getGenerationID();
Write(id);
if (options_.paint_cache->Get(PaintCacheDataType::kPath, id)) {
Write(static_cast<uint32_t>(PaintCacheEntryState::kCached));
return;
}
// The SkPath may fail to serialize if the bytes required would overflow.
uint64_t bytes_required = path.writeToMemory(nullptr);
if (bytes_required == 0u) {
Write(static_cast<uint32_t>(PaintCacheEntryState::kEmpty));
return;
}
Write(static_cast<uint32_t>(PaintCacheEntryState::kInlined));
uint64_t* bytes_to_skip = WriteSize(0u);
if (!valid_)
return;
if (options_.paint_cache->Get(PaintCacheDataType::kPath, id))
return;
uint64_t bytes_required = path.writeToMemory(nullptr);
if (bytes_required > remaining_bytes_) {
valid_ = false;
return;
}
size_t bytes_written = path.writeToMemory(memory_);
DCHECK_EQ(bytes_written, bytes_required);
options_.paint_cache->Put(PaintCacheDataType::kPath, id, bytes_written);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment