SkFlattenable.cpp revision c0b7e10c6a68f59e1653e6c18e6bc954b3c3f0cf
1
2/*
3 * Copyright 2011 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8#include "SkFlattenable.h"
9#include "SkPtrRecorder.h"
10
11SK_DEFINE_INST_COUNT(SkFlattenable)
12
13///////////////////////////////////////////////////////////////////////////////
14
15void SkFlattenable::flatten(SkFlattenableWriteBuffer&) const
16{
17    /*  we don't write anything at the moment, but this allows our subclasses
18        to not know that, since we want them to always call INHERITED::flatten()
19        in their code.
20    */
21}
22
23///////////////////////////////////////////////////////////////////////////////
24
25SkNamedFactorySet::SkNamedFactorySet() : fNextAddedFactory(0) {}
26
27uint32_t SkNamedFactorySet::find(SkFlattenable::Factory factory) {
28    uint32_t index = fFactorySet.find(factory);
29    if (index > 0) {
30        return index;
31    }
32    const char* name = SkFlattenable::FactoryToName(factory);
33    if (NULL == name) {
34        return 0;
35    }
36    *fNames.append() = name;
37    return fFactorySet.add(factory);
38}
39
40const char* SkNamedFactorySet::getNextAddedFactoryName() {
41    if (fNextAddedFactory < fNames.count()) {
42        return fNames[fNextAddedFactory++];
43    }
44    return NULL;
45}
46
47///////////////////////////////////////////////////////////////////////////////
48
49SkRefCntSet::~SkRefCntSet() {
50    // call this now, while our decPtr() is sill in scope
51    this->reset();
52}
53
54void SkRefCntSet::incPtr(void* ptr) {
55    ((SkRefCnt*)ptr)->ref();
56}
57
58void SkRefCntSet::decPtr(void* ptr) {
59    ((SkRefCnt*)ptr)->unref();
60}
61
62///////////////////////////////////////////////////////////////////////////////
63///////////////////////////////////////////////////////////////////////////////
64///////////////////////////////////////////////////////////////////////////////
65
66#define MAX_ENTRY_COUNT  1024
67
68struct Entry {
69    const char*             fName;
70    SkFlattenable::Factory  fFactory;
71    SkFlattenable::Type     fType;
72};
73
74static int gCount;
75static Entry gEntries[MAX_ENTRY_COUNT];
76
77void SkFlattenable::Register(const char name[], Factory factory, SkFlattenable::Type type) {
78    SkASSERT(name);
79    SkASSERT(factory);
80
81    static bool gOnce = false;
82    if (!gOnce) {
83        gCount = 0;
84        gOnce = true;
85    }
86
87    SkASSERT(gCount < MAX_ENTRY_COUNT);
88
89    gEntries[gCount].fName = name;
90    gEntries[gCount].fFactory = factory;
91    gEntries[gCount].fType = type;
92    gCount += 1;
93}
94
95#ifdef SK_DEBUG
96static void report_no_entries(const char* functionName) {
97    if (!gCount) {
98        SkDebugf("%s has no registered name/factory/type entries."
99                 " Call SkFlattenable::InitializeFlattenablesIfNeeded() before using gEntries",
100                 functionName);
101    }
102}
103#endif
104
105SkFlattenable::Factory SkFlattenable::NameToFactory(const char name[]) {
106    InitializeFlattenablesIfNeeded();
107#ifdef SK_DEBUG
108    report_no_entries(__FUNCTION__);
109#endif
110    const Entry* entries = gEntries;
111    for (int i = gCount - 1; i >= 0; --i) {
112        if (strcmp(entries[i].fName, name) == 0) {
113            return entries[i].fFactory;
114        }
115    }
116    return NULL;
117}
118
119bool SkFlattenable::NameToType(const char name[], SkFlattenable::Type* type) {
120    SkASSERT(NULL != type);
121    InitializeFlattenablesIfNeeded();
122#ifdef SK_DEBUG
123    report_no_entries(__FUNCTION__);
124#endif
125    const Entry* entries = gEntries;
126    for (int i = gCount - 1; i >= 0; --i) {
127        if (strcmp(entries[i].fName, name) == 0) {
128            *type = entries[i].fType;
129            return true;
130        }
131    }
132    return false;
133}
134
135const char* SkFlattenable::FactoryToName(Factory fact) {
136    InitializeFlattenablesIfNeeded();
137#ifdef SK_DEBUG
138    report_no_entries(__FUNCTION__);
139#endif
140    const Entry* entries = gEntries;
141    for (int i = gCount - 1; i >= 0; --i) {
142        if (entries[i].fFactory == fact) {
143            return entries[i].fName;
144        }
145    }
146    return NULL;
147}
148