1#include "SkTestImageFilters.h"
2#include "SkCanvas.h"
3#include "SkDevice.h"
4
5class OwnDeviceCanvas : public SkCanvas {
6public:
7    OwnDeviceCanvas(SkDevice* device) : SkCanvas(device) {
8        SkSafeUnref(device);
9    }
10};
11
12bool SkOffsetImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src,
13                                        const SkMatrix& matrix,
14                                        SkBitmap* result,
15                                        SkIPoint* loc) {
16    SkVector vec;
17    matrix.mapVectors(&vec, &fOffset, 1);
18
19    loc->fX += SkScalarRoundToInt(vec.fX);
20    loc->fY += SkScalarRoundToInt(vec.fY);
21    *result = src;
22    return true;
23}
24
25bool SkOffsetImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
26                                         SkIRect* dst) {
27    SkVector vec;
28    ctm.mapVectors(&vec, &fOffset, 1);
29
30    *dst = src;
31    dst->offset(SkScalarRoundToInt(vec.fX), SkScalarRoundToInt(vec.fY));
32    return true;
33}
34
35void SkOffsetImageFilter::flatten(SkFlattenableWriteBuffer& buffer) {
36    this->INHERITED::flatten(buffer);
37    buffer.writeScalar(fOffset.x());
38    buffer.writeScalar(fOffset.y());
39}
40
41SkOffsetImageFilter::SkOffsetImageFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
42    fOffset.fX = buffer.readScalar();
43    fOffset.fY = buffer.readScalar();
44}
45
46SkFlattenable::Factory SkOffsetImageFilter::getFactory() {
47    return CreateProc;
48}
49
50///////////////////////////////////////////////////////////////////////////////
51
52SkComposeImageFilter::~SkComposeImageFilter() {
53    SkSafeUnref(fInner);
54    SkSafeUnref(fOuter);
55}
56
57bool SkComposeImageFilter::onFilterImage(Proxy* proxy,
58                                         const SkBitmap& src,
59                                         const SkMatrix& ctm,
60                                         SkBitmap* result,
61                                         SkIPoint* loc) {
62    if (!fOuter && !fInner) {
63        return false;
64    }
65
66    if (!fOuter || !fInner) {
67        return (fOuter ? fOuter : fInner)->filterImage(proxy, src, ctm, result, loc);
68    }
69
70    SkBitmap tmp;
71    return fInner->filterImage(proxy, src, ctm, &tmp, loc) &&
72           fOuter->filterImage(proxy, tmp, ctm, result, loc);
73}
74
75bool SkComposeImageFilter::onFilterBounds(const SkIRect& src,
76                                          const SkMatrix& ctm,
77                                          SkIRect* dst) {
78    if (!fOuter && !fInner) {
79        return false;
80    }
81
82    if (!fOuter || !fInner) {
83        return (fOuter ? fOuter : fInner)->filterBounds(src, ctm, dst);
84    }
85
86    SkIRect tmp;
87    return fInner->filterBounds(src, ctm, &tmp) &&
88           fOuter->filterBounds(tmp, ctm, dst);
89}
90
91void SkComposeImageFilter::flatten(SkFlattenableWriteBuffer& buffer) {
92    this->INHERITED::flatten(buffer);
93
94    buffer.writeFlattenable(fOuter);
95    buffer.writeFlattenable(fInner);
96}
97
98SkComposeImageFilter::SkComposeImageFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
99    fOuter = (SkImageFilter*)buffer.readFlattenable();
100    fInner = (SkImageFilter*)buffer.readFlattenable();
101}
102
103SkFlattenable::Factory SkComposeImageFilter::getFactory() {
104    return CreateProc;
105}
106
107///////////////////////////////////////////////////////////////////////////////
108
109template <typename T> T* SkSafeRefReturn(T* obj) {
110    SkSafeRef(obj);
111    return obj;
112}
113
114void SkMergeImageFilter::initAlloc(int count, bool hasModes) {
115    if (count < 1) {
116        fFilters = NULL;
117        fModes = NULL;
118        fCount = 0;
119    } else {
120        int modeCount = hasModes ? count : 0;
121        size_t size = sizeof(SkImageFilter*) * count + sizeof(uint8_t) * modeCount;
122        if (size <= sizeof(fStorage)) {
123            fFilters = SkTCast<SkImageFilter**>(fStorage);
124        } else {
125            fFilters = SkTCast<SkImageFilter**>(sk_malloc_throw(size));
126        }
127        fModes = hasModes ? SkTCast<uint8_t*>(fFilters + count) : NULL;
128        fCount = count;
129    }
130}
131
132void SkMergeImageFilter::init(SkImageFilter* const filters[], int count,
133                              const SkXfermode::Mode modes[]) {
134    this->initAlloc(count, !!modes);
135    for (int i = 0; i < count; ++i) {
136        fFilters[i] = SkSafeRefReturn(filters[i]);
137        if (modes) {
138            fModes[i] = SkToU8(modes[i]);
139        }
140    }
141}
142
143SkMergeImageFilter::SkMergeImageFilter(SkImageFilter* first, SkImageFilter* second,
144                                       SkXfermode::Mode mode) {
145    SkImageFilter* filters[] = { first, second };
146    SkXfermode::Mode modes[] = { mode, mode };
147    this->init(filters, 2, SkXfermode::kSrcOver_Mode == mode ? NULL : modes);
148}
149
150SkMergeImageFilter::SkMergeImageFilter(SkImageFilter* const filters[], int count,
151                                       const SkXfermode::Mode modes[]) {
152    this->init(filters, count, modes);
153}
154
155SkMergeImageFilter::~SkMergeImageFilter() {
156    for (int i = 0; i < fCount; ++i) {
157        SkSafeUnref(fFilters[i]);
158    }
159
160    if (fFilters != SkTCast<SkImageFilter**>(fStorage)) {
161        sk_free(fFilters);
162        // fModes is allocated in the same block as fFilters, so no need to
163        // separately free it.
164    }
165}
166
167bool SkMergeImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
168                                        SkIRect* dst) {
169    if (fCount < 1) {
170        return false;
171    }
172
173    SkIRect totalBounds;
174
175    for (int i = 0; i < fCount; ++i) {
176        SkImageFilter* filter = fFilters[i];
177        SkIRect r;
178        if (filter) {
179            if (!filter->filterBounds(src, ctm, &r)) {
180                return false;
181            }
182        } else {
183            r = src;
184        }
185        if (0 == i) {
186            totalBounds = r;
187        } else {
188            totalBounds.join(r);
189        }
190    }
191
192    // don't modify dst until now, so we don't accidentally change it in the
193    // loop, but then return false on the next filter.
194    *dst = totalBounds;
195    return true;
196}
197
198bool SkMergeImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src,
199                                       const SkMatrix& ctm,
200                                       SkBitmap* result, SkIPoint* loc) {
201    if (fCount < 1) {
202        return false;
203    }
204
205    const SkIRect srcBounds = SkIRect::MakeXYWH(loc->x(), loc->y(),
206                                                src.width(), src.height());
207    SkIRect bounds;
208    if (!this->filterBounds(srcBounds, ctm, &bounds)) {
209        return false;
210    }
211
212    const int x0 = bounds.left();
213    const int y0 = bounds.top();
214
215    SkDevice* dst = proxy->createDevice(bounds.width(), bounds.height());
216    if (NULL == dst) {
217        return false;
218    }
219    OwnDeviceCanvas canvas(dst);
220    SkPaint paint;
221
222    for (int i = 0; i < fCount; ++i) {
223        SkBitmap tmp;
224        const SkBitmap* srcPtr;
225        SkIPoint pos = *loc;
226        SkImageFilter* filter = fFilters[i];
227        if (filter) {
228            if (!filter->filterImage(proxy, src, ctm, &tmp, &pos)) {
229                return false;
230            }
231            srcPtr = &tmp;
232        } else {
233            srcPtr = &src;
234        }
235
236        if (fModes) {
237            paint.setXfermodeMode((SkXfermode::Mode)fModes[i]);
238        } else {
239            paint.setXfermode(NULL);
240        }
241        canvas.drawSprite(*srcPtr, pos.x() - x0, pos.y() - y0, &paint);
242    }
243
244    loc->set(bounds.left(), bounds.top());
245    *result = dst->accessBitmap(false);
246    return true;
247}
248
249void SkMergeImageFilter::flatten(SkFlattenableWriteBuffer& buffer) {
250    this->INHERITED::flatten(buffer);
251
252    int storedCount = fCount;
253    if (fModes) {
254        // negative count signals we have modes
255        storedCount = -storedCount;
256    }
257    buffer.write32(storedCount);
258
259    if (fCount) {
260        for (int i = 0; i < fCount; ++i) {
261            buffer.writeFlattenable(fFilters[i]);
262        }
263        if (fModes) {
264            buffer.write(fModes, fCount * sizeof(fModes[0]));
265        }
266    }
267}
268
269SkMergeImageFilter::SkMergeImageFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
270    int storedCount = buffer.readS32();
271    this->initAlloc(SkAbs32(storedCount), storedCount < 0);
272
273    for (int i = 0; i < fCount; ++i) {
274        fFilters[i] = (SkImageFilter*)buffer.readFlattenable();
275    }
276
277    if (fModes) {
278        SkASSERT(storedCount < 0);
279        buffer.read(fModes, fCount * sizeof(fModes[0]));
280    } else {
281        SkASSERT(storedCount >= 0);
282    }
283}
284
285SkFlattenable::Factory SkMergeImageFilter::getFactory() {
286    return CreateProc;
287}
288
289///////////////////////////////////////////////////////////////////////////////
290
291#include "SkColorFilter.h"
292
293SkColorFilterImageFilter::~SkColorFilterImageFilter() {
294    SkSafeUnref(fColorFilter);
295}
296
297bool SkColorFilterImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src,
298                                             const SkMatrix& matrix,
299                                             SkBitmap* result,
300                                             SkIPoint* loc) {
301    SkColorFilter* cf = fColorFilter;
302    if (NULL == cf) {
303        *result = src;
304        return true;
305    }
306
307    SkDevice* dev = proxy->createDevice(src.width(), src.height());
308    if (NULL == dev) {
309        return false;
310    }
311    OwnDeviceCanvas canvas(dev);
312    SkPaint paint;
313
314    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
315    paint.setColorFilter(fColorFilter);
316    canvas.drawSprite(src, 0, 0, &paint);
317
318    *result = dev->accessBitmap(false);
319    return true;
320}
321
322void SkColorFilterImageFilter::flatten(SkFlattenableWriteBuffer& buffer) {
323    this->INHERITED::flatten(buffer);
324
325    buffer.writeFlattenable(fColorFilter);
326}
327
328SkColorFilterImageFilter::SkColorFilterImageFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
329    fColorFilter = (SkColorFilter*)buffer.readFlattenable();
330}
331
332SkFlattenable::Factory SkColorFilterImageFilter::getFactory() {
333    return CreateProc;
334}
335
336///////////////////////////////////////////////////////////////////////////////
337
338bool SkDownSampleImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& src,
339                                            const SkMatrix& matrix,
340                                            SkBitmap* result, SkIPoint*) {
341    SkScalar scale = fScale;
342    if (scale > SK_Scalar1 || scale <= 0) {
343        return false;
344    }
345
346    int dstW = SkScalarRoundToInt(src.width() * scale);
347    int dstH = SkScalarRoundToInt(src.height() * scale);
348    if (dstW < 1) {
349        dstW = 1;
350    }
351    if (dstH < 1) {
352        dstH = 1;
353    }
354
355    SkBitmap tmp;
356
357    // downsample
358    {
359        SkDevice* dev = proxy->createDevice(dstW, dstH);
360        if (NULL == dev) {
361            return false;
362        }
363        OwnDeviceCanvas canvas(dev);
364        SkPaint paint;
365
366        paint.setFilterBitmap(true);
367        canvas.scale(scale, scale);
368        canvas.drawBitmap(src, 0, 0, &paint);
369        tmp = dev->accessBitmap(false);
370    }
371
372    // upscale
373    {
374        SkDevice* dev = proxy->createDevice(src.width(), src.height());
375        if (NULL == dev) {
376            return false;
377        }
378        OwnDeviceCanvas canvas(dev);
379
380        SkRect r = SkRect::MakeWH(SkIntToScalar(src.width()),
381                                  SkIntToScalar(src.height()));
382        canvas.drawBitmapRect(tmp, NULL, r, NULL);
383        *result = dev->accessBitmap(false);
384    }
385    return true;
386}
387
388void SkDownSampleImageFilter::flatten(SkFlattenableWriteBuffer& buffer) {
389    this->INHERITED::flatten(buffer);
390
391    buffer.writeScalar(fScale);
392}
393
394SkDownSampleImageFilter::SkDownSampleImageFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
395    fScale = buffer.readScalar();
396}
397
398SkFlattenable::Factory SkDownSampleImageFilter::getFactory() {
399    return CreateProc;
400}
401
402