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