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 
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__anonb1ec22a60111::RRectBlurKey23     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 
39 struct RRectBlurRec : public SkResourceCache::Rec {
RRectBlurRec__anonb1ec22a60111::RRectBlurRec40     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     }
~RRectBlurRec__anonb1ec22a60111::RRectBlurRec47     ~RRectBlurRec() {
48         fValue.fData->detachFromCacheAndUnref();
49     }
50 
51     RRectBlurKey   fKey;
52     MaskValue      fValue;
53 
getKey__anonb1ec22a60111::RRectBlurRec54     const Key& getKey() const override { return fKey; }
bytesUsed__anonb1ec22a60111::RRectBlurRec55     size_t bytesUsed() const override { return sizeof(*this) + fValue.fData->size(); }
56 
Visitor__anonb1ec22a60111::RRectBlurRec57     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 
FindAndRef(SkScalar sigma,SkBlurStyle style,SkBlurQuality quality,const SkRRect & rrect,SkMask * mask,SkResourceCache * localCache)73 SkCachedData* 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 
Add(SkScalar sigma,SkBlurStyle style,SkBlurQuality quality,const SkRRect & rrect,const SkMask & mask,SkCachedData * data,SkResourceCache * localCache)86 void 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 
95 namespace {
96 static unsigned gRectsBlurKeyNamespaceLabel;
97 
98 struct RectsBlurKey : public SkResourceCache::Key {
99 public:
RectsBlurKey__anonb1ec22a60211::RectsBlurKey100     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 
130 struct RectsBlurRec : public SkResourceCache::Rec {
RectsBlurRec__anonb1ec22a60211::RectsBlurRec131     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     }
~RectsBlurRec__anonb1ec22a60211::RectsBlurRec138     ~RectsBlurRec() {
139         fValue.fData->detachFromCacheAndUnref();
140     }
141 
142     RectsBlurKey   fKey;
143     MaskValue      fValue;
144 
getKey__anonb1ec22a60211::RectsBlurRec145     const Key& getKey() const override { return fKey; }
bytesUsed__anonb1ec22a60211::RectsBlurRec146     size_t bytesUsed() const override { return sizeof(*this) + fValue.fData->size(); }
147 
Visitor__anonb1ec22a60211::RectsBlurRec148     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 
FindAndRef(SkScalar sigma,SkBlurStyle style,SkBlurQuality quality,const SkRect rects[],int count,SkMask * mask,SkResourceCache * localCache)164 SkCachedData* 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 
Add(SkScalar sigma,SkBlurStyle style,SkBlurQuality quality,const SkRect rects[],int count,const SkMask & mask,SkCachedData * data,SkResourceCache * localCache)178 void 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