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