1/* 2 * Copyright 2014 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#include "SkMaskCache.h" 9 10#define CHECK_LOCAL(localCache, localName, globalName, ...) \ 11 ((localCache) ? localCache->localName(__VA_ARGS__) : SkResourceCache::globalName(__VA_ARGS__)) 12 13struct MaskValue { 14 SkMask fMask; 15 SkCachedData* fData; 16}; 17 18namespace { 19static unsigned gRRectBlurKeyNamespaceLabel; 20 21struct RRectBlurKey : public SkResourceCache::Key { 22public: 23 RRectBlurKey(SkScalar sigma, const SkRRect& rrect, SkBlurStyle style, SkBlurQuality quality) 24 : fSigma(sigma) 25 , fStyle(style) 26 , fQuality(quality) 27 , fRRect(rrect) 28 { 29 this->init(&gRRectBlurKeyNamespaceLabel, 0, 30 sizeof(fSigma) + sizeof(fStyle) + sizeof(fQuality) + sizeof(fRRect)); 31 } 32 33 SkScalar fSigma; 34 int32_t fStyle; 35 int32_t fQuality; 36 SkRRect fRRect; 37}; 38 39struct RRectBlurRec : public SkResourceCache::Rec { 40 RRectBlurRec(RRectBlurKey key, const SkMask& mask, SkCachedData* data) 41 : fKey(key) 42 { 43 fValue.fMask = mask; 44 fValue.fData = data; 45 fValue.fData->attachToCacheAndRef(); 46 } 47 ~RRectBlurRec() { 48 fValue.fData->detachFromCacheAndUnref(); 49 } 50 51 RRectBlurKey fKey; 52 MaskValue fValue; 53 54 const Key& getKey() const override { return fKey; } 55 size_t bytesUsed() const override { return sizeof(*this) + fValue.fData->size(); } 56 57 static bool Visitor(const SkResourceCache::Rec& baseRec, void* contextData) { 58 const RRectBlurRec& rec = static_cast<const RRectBlurRec&>(baseRec); 59 MaskValue* result = (MaskValue*)contextData; 60 61 SkCachedData* tmpData = rec.fValue.fData; 62 tmpData->ref(); 63 if (NULL == tmpData->data()) { 64 tmpData->unref(); 65 return false; 66 } 67 *result = rec.fValue; 68 return true; 69 } 70}; 71} // namespace 72 73SkCachedData* SkMaskCache::FindAndRef(SkScalar sigma, SkBlurStyle style, SkBlurQuality quality, 74 const SkRRect& rrect, SkMask* mask, SkResourceCache* localCache) { 75 MaskValue result; 76 RRectBlurKey key(sigma, rrect, style, quality); 77 if (!CHECK_LOCAL(localCache, find, Find, key, RRectBlurRec::Visitor, &result)) { 78 return NULL; 79 } 80 81 *mask = result.fMask; 82 mask->fImage = (uint8_t*)(result.fData->data()); 83 return result.fData; 84} 85 86void SkMaskCache::Add(SkScalar sigma, SkBlurStyle style, SkBlurQuality quality, 87 const SkRRect& rrect, const SkMask& mask, SkCachedData* data, 88 SkResourceCache* localCache) { 89 RRectBlurKey key(sigma, rrect, style, quality); 90 return CHECK_LOCAL(localCache, add, Add, SkNEW_ARGS(RRectBlurRec, (key, mask, data))); 91} 92 93////////////////////////////////////////////////////////////////////////////////////////// 94 95namespace { 96static unsigned gRectsBlurKeyNamespaceLabel; 97 98struct RectsBlurKey : public SkResourceCache::Key { 99public: 100 RectsBlurKey(SkScalar sigma, SkBlurStyle style, SkBlurQuality quality, 101 const SkRect rects[], int count) 102 : fSigma(sigma) 103 , fStyle(style) 104 , fQuality(quality) 105 { 106 SkASSERT(1 == count || 2 == count); 107 SkIRect ir; 108 rects[0].roundOut(&ir); 109 fSizes[0] = SkSize::Make(0, 0); 110 fSizes[1] = SkSize::Make(0, 0); 111 fSizes[2] = SkSize::Make(0, 0); 112 fSizes[3] = SkSize::Make(rects[0].x() - ir.x(), rects[0].y() - ir.y()); 113 for (int i = 0; i < count; i++) { 114 fSizes[i] = SkSize::Make(rects[i].width(), rects[i].height()); 115 } 116 if (2 == count) { 117 fSizes[2] = SkSize::Make(rects[0].x() - rects[1].x(), rects[0].y() - rects[1].y()); 118 } 119 120 this->init(&gRectsBlurKeyNamespaceLabel, 0, 121 sizeof(fSigma) + sizeof(fStyle) + sizeof(fQuality) + sizeof(fSizes)); 122 } 123 124 SkScalar fSigma; 125 int32_t fStyle; 126 int32_t fQuality; 127 SkSize fSizes[4]; 128}; 129 130struct RectsBlurRec : public SkResourceCache::Rec { 131 RectsBlurRec(RectsBlurKey key, const SkMask& mask, SkCachedData* data) 132 : fKey(key) 133 { 134 fValue.fMask = mask; 135 fValue.fData = data; 136 fValue.fData->attachToCacheAndRef(); 137 } 138 ~RectsBlurRec() { 139 fValue.fData->detachFromCacheAndUnref(); 140 } 141 142 RectsBlurKey fKey; 143 MaskValue fValue; 144 145 const Key& getKey() const override { return fKey; } 146 size_t bytesUsed() const override { return sizeof(*this) + fValue.fData->size(); } 147 148 static bool Visitor(const SkResourceCache::Rec& baseRec, void* contextData) { 149 const RectsBlurRec& rec = static_cast<const RectsBlurRec&>(baseRec); 150 MaskValue* result = static_cast<MaskValue*>(contextData); 151 152 SkCachedData* tmpData = rec.fValue.fData; 153 tmpData->ref(); 154 if (NULL == tmpData->data()) { 155 tmpData->unref(); 156 return false; 157 } 158 *result = rec.fValue; 159 return true; 160 } 161}; 162} // namespace 163 164SkCachedData* SkMaskCache::FindAndRef(SkScalar sigma, SkBlurStyle style, SkBlurQuality quality, 165 const SkRect rects[], int count, SkMask* mask, 166 SkResourceCache* localCache) { 167 MaskValue result; 168 RectsBlurKey key(sigma, style, quality, rects, count); 169 if (!CHECK_LOCAL(localCache, find, Find, key, RectsBlurRec::Visitor, &result)) { 170 return NULL; 171 } 172 173 *mask = result.fMask; 174 mask->fImage = (uint8_t*)(result.fData->data()); 175 return result.fData; 176} 177 178void SkMaskCache::Add(SkScalar sigma, SkBlurStyle style, SkBlurQuality quality, 179 const SkRect rects[], int count, const SkMask& mask, SkCachedData* data, 180 SkResourceCache* localCache) { 181 RectsBlurKey key(sigma, style, quality, rects, count); 182 return CHECK_LOCAL(localCache, add, Add, SkNEW_ARGS(RectsBlurRec, (key, mask, data))); 183} 184