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
11///////////////////////////////////////////////////////////////////////////////
12
13void SkFlattenable::flatten(SkFlattenableWriteBuffer&) const
14{
15    /*  we don't write anything at the moment, but this allows our subclasses
16        to not know that, since we want them to always call INHERITED::flatten()
17        in their code.
18    */
19}
20
21///////////////////////////////////////////////////////////////////////////////
22
23SkNamedFactorySet::SkNamedFactorySet() : fNextAddedFactory(0) {}
24
25uint32_t SkNamedFactorySet::find(SkFlattenable::Factory factory) {
26    uint32_t index = fFactorySet.find(factory);
27    if (index > 0) {
28        return index;
29    }
30    const char* name = SkFlattenable::FactoryToName(factory);
31    if (NULL == name) {
32        return 0;
33    }
34    *fNames.append() = name;
35    return fFactorySet.add(factory);
36}
37
38const char* SkNamedFactorySet::getNextAddedFactoryName() {
39    if (fNextAddedFactory < fNames.count()) {
40        return fNames[fNextAddedFactory++];
41    }
42    return NULL;
43}
44
45///////////////////////////////////////////////////////////////////////////////
46
47SkRefCntSet::~SkRefCntSet() {
48    // call this now, while our decPtr() is sill in scope
49    this->reset();
50}
51
52void SkRefCntSet::incPtr(void* ptr) {
53    ((SkRefCnt*)ptr)->ref();
54}
55
56void SkRefCntSet::decPtr(void* ptr) {
57    ((SkRefCnt*)ptr)->unref();
58}
59
60///////////////////////////////////////////////////////////////////////////////
61///////////////////////////////////////////////////////////////////////////////
62///////////////////////////////////////////////////////////////////////////////
63
64#define MAX_ENTRY_COUNT  1024
65
66struct Entry {
67    const char*             fName;
68    SkFlattenable::Factory  fFactory;
69    SkFlattenable::Type     fType;
70};
71
72static int gCount;
73static Entry gEntries[MAX_ENTRY_COUNT];
74
75void SkFlattenable::Register(const char name[], Factory factory, SkFlattenable::Type type) {
76    SkASSERT(name);
77    SkASSERT(factory);
78
79    static bool gOnce = false;
80    if (!gOnce) {
81        gCount = 0;
82        gOnce = true;
83    }
84
85    SkASSERT(gCount < MAX_ENTRY_COUNT);
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
94static 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
103SkFlattenable::Factory SkFlattenable::NameToFactory(const char name[]) {
104    InitializeFlattenablesIfNeeded();
105#ifdef SK_DEBUG
106    report_no_entries(__FUNCTION__);
107#endif
108    const Entry* entries = gEntries;
109    for (int i = gCount - 1; i >= 0; --i) {
110        if (strcmp(entries[i].fName, name) == 0) {
111            return entries[i].fFactory;
112        }
113    }
114    return NULL;
115}
116
117bool SkFlattenable::NameToType(const char name[], SkFlattenable::Type* type) {
118    SkASSERT(NULL != type);
119    InitializeFlattenablesIfNeeded();
120#ifdef SK_DEBUG
121    report_no_entries(__FUNCTION__);
122#endif
123    const Entry* entries = gEntries;
124    for (int i = gCount - 1; i >= 0; --i) {
125        if (strcmp(entries[i].fName, name) == 0) {
126            *type = entries[i].fType;
127            return true;
128        }
129    }
130    return false;
131}
132
133const char* SkFlattenable::FactoryToName(Factory fact) {
134    InitializeFlattenablesIfNeeded();
135#ifdef SK_DEBUG
136    report_no_entries(__FUNCTION__);
137#endif
138    const Entry* entries = gEntries;
139    for (int i = gCount - 1; i >= 0; --i) {
140        if (entries[i].fFactory == fact) {
141            return entries[i].fName;
142        }
143    }
144    return NULL;
145}
146