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