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 
13 struct MaskValue {
14     SkMask          fMask;
15     SkCachedData*   fData;
16 };
17 
18 namespace {
19 static unsigned gRRectBlurKeyNamespaceLabel;
20 
21 struct RRectBlurKey : public SkResourceCache::Key {
22 public:
RRectBlurKey__anon8031870e0111::RRectBlurKey23     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 
37 struct RRectBlurRec : public SkResourceCache::Rec {
RRectBlurRec__anon8031870e0111::RRectBlurRec38     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     }
~RRectBlurRec__anon8031870e0111::RRectBlurRec45     ~RRectBlurRec() override {
46         fValue.fData->detachFromCacheAndUnref();
47     }
48 
49     RRectBlurKey   fKey;
50     MaskValue      fValue;
51 
getKey__anon8031870e0111::RRectBlurRec52     const Key& getKey() const override { return fKey; }
bytesUsed__anon8031870e0111::RRectBlurRec53     size_t bytesUsed() const override { return sizeof(*this) + fValue.fData->size(); }
getCategory__anon8031870e0111::RRectBlurRec54     const char* getCategory() const override { return "rrect-blur"; }
diagnostic_only_getDiscardable__anon8031870e0111::RRectBlurRec55     SkDiscardableMemory* diagnostic_only_getDiscardable() const override {
56         return fValue.fData->diagnostic_only_getDiscardable();
57     }
58 
Visitor__anon8031870e0111::RRectBlurRec59     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 
FindAndRef(SkScalar sigma,SkBlurStyle style,const SkRRect & rrect,SkMask * mask,SkResourceCache * localCache)75 SkCachedData* 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 
Add(SkScalar sigma,SkBlurStyle style,const SkRRect & rrect,const SkMask & mask,SkCachedData * data,SkResourceCache * localCache)88 void 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 
97 namespace {
98 static unsigned gRectsBlurKeyNamespaceLabel;
99 
100 struct RectsBlurKey : public SkResourceCache::Key {
101 public:
RectsBlurKey__anon8031870e0211::RectsBlurKey102     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 
128 struct RectsBlurRec : public SkResourceCache::Rec {
RectsBlurRec__anon8031870e0211::RectsBlurRec129     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     }
~RectsBlurRec__anon8031870e0211::RectsBlurRec136     ~RectsBlurRec() override {
137         fValue.fData->detachFromCacheAndUnref();
138     }
139 
140     RectsBlurKey   fKey;
141     MaskValue      fValue;
142 
getKey__anon8031870e0211::RectsBlurRec143     const Key& getKey() const override { return fKey; }
bytesUsed__anon8031870e0211::RectsBlurRec144     size_t bytesUsed() const override { return sizeof(*this) + fValue.fData->size(); }
getCategory__anon8031870e0211::RectsBlurRec145     const char* getCategory() const override { return "rects-blur"; }
diagnostic_only_getDiscardable__anon8031870e0211::RectsBlurRec146     SkDiscardableMemory* diagnostic_only_getDiscardable() const override {
147         return fValue.fData->diagnostic_only_getDiscardable();
148     }
149 
Visitor__anon8031870e0211::RectsBlurRec150     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 
FindAndRef(SkScalar sigma,SkBlurStyle style,const SkRect rects[],int count,SkMask * mask,SkResourceCache * localCache)166 SkCachedData* 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 
Add(SkScalar sigma,SkBlurStyle style,const SkRect rects[],int count,const SkMask & mask,SkCachedData * data,SkResourceCache * localCache)180 void 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