Home | History | Annotate | Download | only in core
      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