157c3a863fce929a96463ab24318006f8b2afcc7areed@google.com
2ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com/*
3ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Copyright 2010 Google Inc.
4ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com *
5ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * Use of this source code is governed by a BSD-style license that can be
6ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com * found in the LICENSE file.
7dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com */
8dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com
9ec3ed6a5ebf6f2c406d7bcf94b6bc34fcaeb976eepoger@google.com
10a6cac4ce3896669e1b5935def0a84b4456ec9777reed#include "SkGradientBitmapCache.h"
11dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com
12a6cac4ce3896669e1b5935def0a84b4456ec9777reedstruct SkGradientBitmapCache::Entry {
13dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    Entry*      fPrev;
14dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    Entry*      fNext;
15dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com
16dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    void*       fBuffer;
17dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    size_t      fSize;
18dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    SkBitmap    fBitmap;
19dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com
203c898186c9082c535e589807752a0a9dc5d28aa0vandebo@chromium.org    Entry(const void* buffer, size_t size, const SkBitmap& bm)
212880df2609eba09b555ca37be04b6ad89290c765Tom Hudson            : fPrev(nullptr),
222880df2609eba09b555ca37be04b6ad89290c765Tom Hudson              fNext(nullptr),
233c898186c9082c535e589807752a0a9dc5d28aa0vandebo@chromium.org              fBitmap(bm) {
24dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        fBuffer = sk_malloc_throw(size);
25dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        fSize = size;
26dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        memcpy(fBuffer, buffer, size);
27dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    }
28dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com
29dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    ~Entry() { sk_free(fBuffer); }
30dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com
31dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    bool equals(const void* buffer, size_t size) const {
32dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        return (fSize == size) && !memcmp(fBuffer, buffer, size);
33dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    }
34dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com};
35dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com
36a6cac4ce3896669e1b5935def0a84b4456ec9777reedSkGradientBitmapCache::SkGradientBitmapCache(int max) : fMaxEntries(max) {
37dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    fEntryCount = 0;
382880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    fHead = fTail = nullptr;
39dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com
40dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    this->validate();
41dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com}
42dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com
43a6cac4ce3896669e1b5935def0a84b4456ec9777reedSkGradientBitmapCache::~SkGradientBitmapCache() {
44dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    this->validate();
45dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com
46dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    Entry* entry = fHead;
47dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    while (entry) {
48dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        Entry* next = entry->fNext;
49dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        delete entry;
50dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        entry = next;
51dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    }
52dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com}
53dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com
54a6cac4ce3896669e1b5935def0a84b4456ec9777reedSkGradientBitmapCache::Entry* SkGradientBitmapCache::detach(Entry* entry) const {
55dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    if (entry->fPrev) {
56dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        SkASSERT(fHead != entry);
57dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        entry->fPrev->fNext = entry->fNext;
58dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    } else {
59dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        SkASSERT(fHead == entry);
60dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        fHead = entry->fNext;
61dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    }
62dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    if (entry->fNext) {
63dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        SkASSERT(fTail != entry);
64dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        entry->fNext->fPrev = entry->fPrev;
65dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    } else {
66dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        SkASSERT(fTail == entry);
67dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        fTail = entry->fPrev;
68dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    }
69dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    return entry;
70dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com}
71dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com
72a6cac4ce3896669e1b5935def0a84b4456ec9777reedvoid SkGradientBitmapCache::attachToHead(Entry* entry) const {
732880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    entry->fPrev = nullptr;
74dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    entry->fNext = fHead;
75dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    if (fHead) {
76dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        fHead->fPrev = entry;
77dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    } else {
78dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        fTail = entry;
79dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    }
80dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    fHead = entry;
81dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com}
82dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com
83a6cac4ce3896669e1b5935def0a84b4456ec9777reedbool SkGradientBitmapCache::find(const void* buffer, size_t size, SkBitmap* bm) const {
84dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    AutoValidate av(this);
85dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com
86dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    Entry* entry = fHead;
87dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    while (entry) {
88dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        if (entry->equals(buffer, size)) {
89dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com            if (bm) {
90dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com                *bm = entry->fBitmap;
91dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com            }
92dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com            // move to the head of our list, so we purge it last
93dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com            this->detach(entry);
94dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com            this->attachToHead(entry);
95dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com            return true;
96dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        }
97dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        entry = entry->fNext;
98dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    }
99dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    return false;
100dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com}
101dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com
102a6cac4ce3896669e1b5935def0a84b4456ec9777reedvoid SkGradientBitmapCache::add(const void* buffer, size_t len, const SkBitmap& bm) {
103dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    AutoValidate av(this);
104e49d57117507903a7d912218b4e1ebd2f15bbbd7reed@google.com
105dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    if (fEntryCount == fMaxEntries) {
106e49d57117507903a7d912218b4e1ebd2f15bbbd7reed@google.com        SkASSERT(fTail);
107e49d57117507903a7d912218b4e1ebd2f15bbbd7reed@google.com        delete this->detach(fTail);
108e49d57117507903a7d912218b4e1ebd2f15bbbd7reed@google.com        fEntryCount -= 1;
109dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    }
110dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com
1112880df2609eba09b555ca37be04b6ad89290c765Tom Hudson    Entry* entry = new Entry(buffer, len, bm);
112dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    this->attachToHead(entry);
113dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    fEntryCount += 1;
114dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com}
115dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com
116dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com///////////////////////////////////////////////////////////////////////////////
117dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com
118dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com#ifdef SK_DEBUG
119dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com
120a6cac4ce3896669e1b5935def0a84b4456ec9777reedvoid SkGradientBitmapCache::validate() const {
121dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    SkASSERT(fEntryCount >= 0 && fEntryCount <= fMaxEntries);
122e49d57117507903a7d912218b4e1ebd2f15bbbd7reed@google.com
123dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    if (fEntryCount > 0) {
1242880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        SkASSERT(nullptr == fHead->fPrev);
1252880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        SkASSERT(nullptr == fTail->fNext);
126dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com
127dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        if (fEntryCount == 1) {
128dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com            SkASSERT(fHead == fTail);
129dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        } else {
130dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com            SkASSERT(fHead != fTail);
131dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        }
132dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com
133dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        Entry* entry = fHead;
134dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        int count = 0;
135dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        while (entry) {
136dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com            count += 1;
137dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com            entry = entry->fNext;
138dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        }
139dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        SkASSERT(count == fEntryCount);
140e49d57117507903a7d912218b4e1ebd2f15bbbd7reed@google.com
141dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        entry = fTail;
142dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        while (entry) {
143dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com            count -= 1;
144dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com            entry = entry->fPrev;
145dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        }
146dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com        SkASSERT(0 == count);
147dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com    } else {
1482880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        SkASSERT(nullptr == fHead);
1492880df2609eba09b555ca37be04b6ad89290c765Tom Hudson        SkASSERT(nullptr == fTail);
150e49d57117507903a7d912218b4e1ebd2f15bbbd7reed@google.com    }
151dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com}
152dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com
153dc731fd4830380a01664b99f7a23df4bfca71facreed@google.com#endif
154