1 :
2 : /*
3 : * Copyright 2010 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 :
9 :
10 : #include "SkBitmapCache.h"
11 :
12 : struct SkBitmapCache::Entry {
13 : Entry* fPrev;
14 : Entry* fNext;
15 :
16 : void* fBuffer;
17 : size_t fSize;
18 : SkBitmap fBitmap;
19 :
20 0 : Entry(const void* buffer, size_t size, const SkBitmap& bm)
21 : : fPrev(NULL),
22 : fNext(NULL),
23 0 : fBitmap(bm) {
24 0 : fBuffer = sk_malloc_throw(size);
25 0 : fSize = size;
26 0 : memcpy(fBuffer, buffer, size);
27 0 : }
28 :
29 0 : ~Entry() { sk_free(fBuffer); }
30 :
31 0 : bool equals(const void* buffer, size_t size) const {
32 0 : return (fSize == size) && !memcmp(fBuffer, buffer, size);
33 : }
34 : };
35 :
36 0 : SkBitmapCache::SkBitmapCache(int max) : fMaxEntries(max) {
37 0 : fEntryCount = 0;
38 0 : fHead = fTail = NULL;
39 :
40 0 : this->validate();
41 0 : }
42 :
43 0 : SkBitmapCache::~SkBitmapCache() {
44 0 : this->validate();
45 :
46 0 : Entry* entry = fHead;
47 0 : while (entry) {
48 0 : Entry* next = entry->fNext;
49 0 : delete entry;
50 0 : entry = next;
51 : }
52 0 : }
53 :
54 0 : SkBitmapCache::Entry* SkBitmapCache::detach(Entry* entry) const {
55 0 : if (entry->fPrev) {
56 0 : SkASSERT(fHead != entry);
57 0 : entry->fPrev->fNext = entry->fNext;
58 : } else {
59 0 : SkASSERT(fHead == entry);
60 0 : fHead = entry->fNext;
61 : }
62 0 : if (entry->fNext) {
63 0 : SkASSERT(fTail != entry);
64 0 : entry->fNext->fPrev = entry->fPrev;
65 : } else {
66 0 : SkASSERT(fTail == entry);
67 0 : fTail = entry->fPrev;
68 : }
69 0 : return entry;
70 : }
71 :
72 0 : void SkBitmapCache::attachToHead(Entry* entry) const {
73 0 : entry->fPrev = NULL;
74 0 : entry->fNext = fHead;
75 0 : if (fHead) {
76 0 : fHead->fPrev = entry;
77 : } else {
78 0 : fTail = entry;
79 : }
80 0 : fHead = entry;
81 0 : }
82 :
83 0 : bool SkBitmapCache::find(const void* buffer, size_t size, SkBitmap* bm) const {
84 0 : AutoValidate av(this);
85 :
86 0 : Entry* entry = fHead;
87 0 : while (entry) {
88 0 : if (entry->equals(buffer, size)) {
89 0 : if (bm) {
90 0 : *bm = entry->fBitmap;
91 : }
92 : // move to the head of our list, so we purge it last
93 0 : this->detach(entry);
94 0 : this->attachToHead(entry);
95 0 : return true;
96 : }
97 0 : entry = entry->fNext;
98 : }
99 0 : return false;
100 : }
101 :
102 0 : void SkBitmapCache::add(const void* buffer, size_t len, const SkBitmap& bm) {
103 0 : AutoValidate av(this);
104 :
105 0 : if (fEntryCount == fMaxEntries) {
106 0 : SkASSERT(fTail);
107 0 : delete this->detach(fTail);
108 0 : fEntryCount -= 1;
109 : }
110 :
111 0 : Entry* entry = new Entry(buffer, len, bm);
112 0 : this->attachToHead(entry);
113 0 : fEntryCount += 1;
114 0 : }
115 :
116 : ///////////////////////////////////////////////////////////////////////////////
117 :
118 : #ifdef SK_DEBUG
119 :
120 0 : void SkBitmapCache::validate() const {
121 0 : SkASSERT(fEntryCount >= 0 && fEntryCount <= fMaxEntries);
122 :
123 0 : if (fEntryCount > 0) {
124 0 : SkASSERT(NULL == fHead->fPrev);
125 0 : SkASSERT(NULL == fTail->fNext);
126 :
127 0 : if (fEntryCount == 1) {
128 0 : SkASSERT(fHead == fTail);
129 : } else {
130 0 : SkASSERT(fHead != fTail);
131 : }
132 :
133 0 : Entry* entry = fHead;
134 0 : int count = 0;
135 0 : while (entry) {
136 0 : count += 1;
137 0 : entry = entry->fNext;
138 : }
139 0 : SkASSERT(count == fEntryCount);
140 :
141 0 : entry = fTail;
142 0 : while (entry) {
143 0 : count -= 1;
144 0 : entry = entry->fPrev;
145 : }
146 0 : SkASSERT(0 == count);
147 : } else {
148 0 : SkASSERT(NULL == fHead);
149 0 : SkASSERT(NULL == fTail);
150 : }
151 0 : }
152 :
153 : #endif
154 :
|