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 "SkFlattenable.h"
9 #include "SkPtrRecorder.h"
10 #include "SkReadBuffer.h"
11
12 #include <algorithm>
13
SkNamedFactorySet()14 SkNamedFactorySet::SkNamedFactorySet() : fNextAddedFactory(0) {}
15
find(SkFlattenable::Factory factory)16 uint32_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
getNextAddedFactoryName()29 const char* SkNamedFactorySet::getNextAddedFactoryName() {
30 if (fNextAddedFactory < fNames.count()) {
31 return fNames[fNextAddedFactory++];
32 }
33 return nullptr;
34 }
35
36 ///////////////////////////////////////////////////////////////////////////////
37
~SkRefCntSet()38 SkRefCntSet::~SkRefCntSet() {
39 // call this now, while our decPtr() is sill in scope
40 this->reset();
41 }
42
incPtr(void * ptr)43 void SkRefCntSet::incPtr(void* ptr) {
44 ((SkRefCnt*)ptr)->ref();
45 }
46
decPtr(void * ptr)47 void SkRefCntSet::decPtr(void* ptr) {
48 ((SkRefCnt*)ptr)->unref();
49 }
50
51 ///////////////////////////////////////////////////////////////////////////////
52
53 namespace {
54
55 struct Entry {
56 const char* fName;
57 SkFlattenable::Factory fFactory;
58 SkFlattenable::Type fType;
59 };
60
61 struct EntryComparator {
operator ()__anone3f7f7050111::EntryComparator62 bool operator()(const Entry& a, const Entry& b) const {
63 return strcmp(a.fName, b.fName) < 0;
64 }
operator ()__anone3f7f7050111::EntryComparator65 bool operator()(const Entry& a, const char* b) const {
66 return strcmp(a.fName, b) < 0;
67 }
operator ()__anone3f7f7050111::EntryComparator68 bool operator()(const char* a, const Entry& b) const {
69 return strcmp(a, b.fName) < 0;
70 }
71 };
72
73 int gCount = 0;
74 Entry gEntries[128];
75
76 } // namespace
77
Finalize()78 void SkFlattenable::Finalize() {
79 std::sort(gEntries, gEntries + gCount, EntryComparator());
80 }
81
Register(const char name[],Factory factory,SkFlattenable::Type type)82 void SkFlattenable::Register(const char name[], Factory factory, SkFlattenable::Type type) {
83 SkASSERT(name);
84 SkASSERT(factory);
85 SkASSERT(gCount < (int)SK_ARRAY_COUNT(gEntries));
86
87 gEntries[gCount].fName = name;
88 gEntries[gCount].fFactory = factory;
89 gEntries[gCount].fType = type;
90 gCount += 1;
91 }
92
93 #ifdef SK_DEBUG
report_no_entries(const char * functionName)94 static void report_no_entries(const char* functionName) {
95 if (!gCount) {
96 SkDebugf("%s has no registered name/factory/type entries."
97 " Call SkFlattenable::InitializeFlattenablesIfNeeded() before using gEntries",
98 functionName);
99 }
100 }
101 #endif
102
NameToFactory(const char name[])103 SkFlattenable::Factory SkFlattenable::NameToFactory(const char name[]) {
104 InitializeFlattenablesIfNeeded();
105 SkASSERT(std::is_sorted(gEntries, gEntries + gCount, EntryComparator()));
106 #ifdef SK_DEBUG
107 report_no_entries(__FUNCTION__);
108 #endif
109 auto pair = std::equal_range(gEntries, gEntries + gCount, name, EntryComparator());
110 if (pair.first == pair.second)
111 return nullptr;
112 return pair.first->fFactory;
113 }
114
NameToType(const char name[],SkFlattenable::Type * type)115 bool SkFlattenable::NameToType(const char name[], SkFlattenable::Type* type) {
116 SkASSERT(type);
117 InitializeFlattenablesIfNeeded();
118 SkASSERT(std::is_sorted(gEntries, gEntries + gCount, EntryComparator()));
119 #ifdef SK_DEBUG
120 report_no_entries(__FUNCTION__);
121 #endif
122 auto pair = std::equal_range(gEntries, gEntries + gCount, name, EntryComparator());
123 if (pair.first == pair.second)
124 return false;
125 *type = pair.first->fType;
126 return true;
127 }
128
FactoryToName(Factory fact)129 const char* SkFlattenable::FactoryToName(Factory fact) {
130 InitializeFlattenablesIfNeeded();
131 #ifdef SK_DEBUG
132 report_no_entries(__FUNCTION__);
133 #endif
134 const Entry* entries = gEntries;
135 for (int i = gCount - 1; i >= 0; --i) {
136 if (entries[i].fFactory == fact) {
137 return entries[i].fName;
138 }
139 }
140 return nullptr;
141 }
142
143 ///////////////////////////////////////////////////////////////////////////////////////////////////
144
serialize(const SkSerialProcs * procs) const145 sk_sp<SkData> SkFlattenable::serialize(const SkSerialProcs* procs) const {
146 SkBinaryWriteBuffer writer;
147 if (procs) {
148 writer.setSerialProcs(*procs);
149 }
150 writer.writeFlattenable(this);
151 size_t size = writer.bytesWritten();
152 auto data = SkData::MakeUninitialized(size);
153 writer.writeToMemory(data->writable_data());
154 return data;
155 }
156
Deserialize(SkFlattenable::Type type,const void * data,size_t size,const SkDeserialProcs * procs)157 sk_sp<SkFlattenable> SkFlattenable::Deserialize(SkFlattenable::Type type, const void* data,
158 size_t size, const SkDeserialProcs* procs) {
159 SkReadBuffer buffer(data, size);
160 if (procs) {
161 buffer.setDeserialProcs(*procs);
162 }
163 return sk_sp<SkFlattenable>(buffer.readFlattenable(type));
164 }
165