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