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 14 SkNamedFactorySet::SkNamedFactorySet() : fNextAddedFactory(0) {} 15 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 29 const char* SkNamedFactorySet::getNextAddedFactoryName() { 30 if (fNextAddedFactory < fNames.count()) { 31 return fNames[fNextAddedFactory++]; 32 } 33 return nullptr; 34 } 35 36 /////////////////////////////////////////////////////////////////////////////// 37 38 SkRefCntSet::~SkRefCntSet() { 39 // call this now, while our decPtr() is sill in scope 40 this->reset(); 41 } 42 43 void SkRefCntSet::incPtr(void* ptr) { 44 ((SkRefCnt*)ptr)->ref(); 45 } 46 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 { 62 bool operator()(const Entry& a, const Entry& b) const { 63 return strcmp(a.fName, b.fName) < 0; 64 } 65 bool operator()(const Entry& a, const char* b) const { 66 return strcmp(a.fName, b) < 0; 67 } 68 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 78 void SkFlattenable::Finalize() { 79 std::sort(gEntries, gEntries + gCount, EntryComparator()); 80 } 81 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 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 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 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 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 145 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 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