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