/*
* Copyright 2011 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "SkFlattenable.h"
#include "SkPtrRecorder.h"
#include "SkReadBuffer.h"
#include <algorithm>
SkNamedFactorySet::SkNamedFactorySet() : fNextAddedFactory(0) {}
uint32_t SkNamedFactorySet::find(SkFlattenable::Factory factory) {
uint32_t index = fFactorySet.find(factory);
if (index > 0) {
return index;
}
const char* name = SkFlattenable::FactoryToName(factory);
if (nullptr == name) {
return 0;
}
*fNames.append() = name;
return fFactorySet.add(factory);
}
const char* SkNamedFactorySet::getNextAddedFactoryName() {
if (fNextAddedFactory < fNames.count()) {
return fNames[fNextAddedFactory++];
}
return nullptr;
}
///////////////////////////////////////////////////////////////////////////////
SkRefCntSet::~SkRefCntSet() {
// call this now, while our decPtr() is sill in scope
this->reset();
}
void SkRefCntSet::incPtr(void* ptr) {
((SkRefCnt*)ptr)->ref();
}
void SkRefCntSet::decPtr(void* ptr) {
((SkRefCnt*)ptr)->unref();
}
///////////////////////////////////////////////////////////////////////////////
namespace {
struct Entry {
const char* fName;
SkFlattenable::Factory fFactory;
};
struct EntryComparator {
bool operator()(const Entry& a, const Entry& b) const {
return strcmp(a.fName, b.fName) < 0;
}
bool operator()(const Entry& a, const char* b) const {
return strcmp(a.fName, b) < 0;
}
bool operator()(const char* a, const Entry& b) const {
return strcmp(a, b.fName) < 0;
}
};
int gCount = 0;
Entry gEntries[128];
} // namespace
void SkFlattenable::Finalize() {
std::sort(gEntries, gEntries + gCount, EntryComparator());
}
void SkFlattenable::Register(const char name[], Factory factory) {
SkASSERT(name);
SkASSERT(factory);
SkASSERT(gCount < (int)SK_ARRAY_COUNT(gEntries));
gEntries[gCount].fName = name;
gEntries[gCount].fFactory = factory;
gCount += 1;
}
SkFlattenable::Factory SkFlattenable::NameToFactory(const char name[]) {
RegisterFlattenablesIfNeeded();
SkASSERT(std::is_sorted(gEntries, gEntries + gCount, EntryComparator()));
auto pair = std::equal_range(gEntries, gEntries + gCount, name, EntryComparator());
if (pair.first == pair.second) {
return nullptr;
}
return pair.first->fFactory;
}
const char* SkFlattenable::FactoryToName(Factory fact) {
RegisterFlattenablesIfNeeded();
const Entry* entries = gEntries;
for (int i = gCount - 1; i >= 0; --i) {
if (entries[i].fFactory == fact) {
return entries[i].fName;
}
}
return nullptr;
}
///////////////////////////////////////////////////////////////////////////////////////////////////
sk_sp<SkData> SkFlattenable::serialize(const SkSerialProcs* procs) const {
SkBinaryWriteBuffer writer;
if (procs) {
writer.setSerialProcs(*procs);
}
writer.writeFlattenable(this);
size_t size = writer.bytesWritten();
auto data = SkData::MakeUninitialized(size);
writer.writeToMemory(data->writable_data());
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);
if (procs) {
buffer.setDeserialProcs(*procs);
}
return sk_sp<SkFlattenable>(buffer.readFlattenable(type));
}