| /* | |
| * 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 "include/core/SkFlattenable.h" | |
| #include "include/core/SkData.h" | |
| #include "include/core/SkRefCnt.h" | |
| #include "include/core/SkSerialProcs.h" | |
| #include "include/core/SkTypes.h" | |
| #include "include/private/base/SkTDArray.h" | |
| #include "src/core/SkPtrRecorder.h" | |
| #include "src/core/SkReadBuffer.h" | |
| #include "src/core/SkWriteBuffer.h" | |
| #include <algorithm> | |
| #include <cstdint> | |
| #include <cstring> | |
| #include <iterator> | |
| #include <utility> | |
| 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.size()) { | |
| 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)std::size(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 { | |
| SkSerialProcs p; | |
| if (procs) { | |
| p = *procs; | |
| } | |
| SkBinaryWriteBuffer writer(p); | |
| 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 { | |
| SkSerialProcs p; | |
| if (procs) { | |
| p = *procs; | |
| } | |
| SkBinaryWriteBuffer writer(memory, memory_size, p); | |
| 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)); | |
| } |