1/*
2 * Copyright 2011 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "include/core/SkFlattenable.h"
9#include "src/core/SkPtrRecorder.h"
10#include "src/core/SkReadBuffer.h"
11
12#include <algorithm>
13
14SkNamedFactorySet::SkNamedFactorySet() : fNextAddedFactory(0) {}
15
16uint32_t SkNamedFactorySet::find(SkFlattenable::Factory factory) {
17 uint32_t index = fFactorySet.find(factory);
18 if (index > 0) {
19 return index;
20 }
21 const char* name = SkFlattenable::FactoryToName(factory);
22 if (nullptr == name) {
23 return 0;
24 }
25 *fNames.append() = name;
26 return fFactorySet.add(factory);
27}
28
29const char* SkNamedFactorySet::getNextAddedFactoryName() {
30 if (fNextAddedFactory < fNames.count()) {
31 return fNames[fNextAddedFactory++];
32 }
33 return nullptr;
34}
35
36///////////////////////////////////////////////////////////////////////////////
37
38SkRefCntSet::~SkRefCntSet() {
39 // call this now, while our decPtr() is sill in scope
40 this->reset();
41}
42
43void SkRefCntSet::incPtr(void* ptr) {
44 ((SkRefCnt*)ptr)->ref();
45}
46
47void SkRefCntSet::decPtr(void* ptr) {
48 ((SkRefCnt*)ptr)->unref();
49}
50
51///////////////////////////////////////////////////////////////////////////////
52
53namespace {
54
55struct Entry {
56 const char* fName;
57 SkFlattenable::Factory fFactory;
58};
59
60struct EntryComparator {
61 bool operator()(const Entry& a, const Entry& b) const {
62 return strcmp(a.fName, b.fName) < 0;
63 }
64 bool operator()(const Entry& a, const char* b) const {
65 return strcmp(a.fName, b) < 0;
66 }
67 bool operator()(const char* a, const Entry& b) const {
68 return strcmp(a, b.fName) < 0;
69 }
70};
71
72int gCount = 0;
73Entry gEntries[128];
74
75} // namespace
76
77void SkFlattenable::Finalize() {
78 std::sort(gEntries, gEntries + gCount, EntryComparator());
79}
80
81void SkFlattenable::Register(const char name[], Factory factory) {
82 SkASSERT(name);
83 SkASSERT(factory);
84 SkASSERT(gCount < (int)SK_ARRAY_COUNT(gEntries));
85
86 gEntries[gCount].fName = name;
87 gEntries[gCount].fFactory = factory;
88 gCount += 1;
89}
90
91SkFlattenable::Factory SkFlattenable::NameToFactory(const char name[]) {
92 RegisterFlattenablesIfNeeded();
93
94 SkASSERT(std::is_sorted(gEntries, gEntries + gCount, EntryComparator()));
95 auto pair = std::equal_range(gEntries, gEntries + gCount, name, EntryComparator());
96 if (pair.first == pair.second) {
97 return nullptr;
98 }
99 return pair.first->fFactory;
100}
101
102const char* SkFlattenable::FactoryToName(Factory fact) {
103 RegisterFlattenablesIfNeeded();
104
105 const Entry* entries = gEntries;
106 for (int i = gCount - 1; i >= 0; --i) {
107 if (entries[i].fFactory == fact) {
108 return entries[i].fName;
109 }
110 }
111 return nullptr;
112}
113
114///////////////////////////////////////////////////////////////////////////////////////////////////
115
116sk_sp<SkData> SkFlattenable::serialize(const SkSerialProcs* procs) const {
117 SkBinaryWriteBuffer writer;
118 if (procs) {
119 writer.setSerialProcs(*procs);
120 }
121 writer.writeFlattenable(this);
122 size_t size = writer.bytesWritten();
123 auto data = SkData::MakeUninitialized(size);
124 writer.writeToMemory(data->writable_data());
125 return data;
126}
127
128size_t SkFlattenable::serialize(void* memory, size_t memory_size,
129 const SkSerialProcs* procs) const {
130 SkBinaryWriteBuffer writer(memory, memory_size);
131 if (procs) {
132 writer.setSerialProcs(*procs);
133 }
134 writer.writeFlattenable(this);
135 return writer.usingInitialStorage() ? writer.bytesWritten() : 0u;
136}
137
138sk_sp<SkFlattenable> SkFlattenable::Deserialize(SkFlattenable::Type type, const void* data,
139 size_t size, const SkDeserialProcs* procs) {
140 SkReadBuffer buffer(data, size);
141 if (procs) {
142 buffer.setDeserialProcs(*procs);
143 }
144 return sk_sp<SkFlattenable>(buffer.readFlattenable(type));
145}
146