• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include "SkTestImageFilters.h"
2 #include "SkCanvas.h"
3 #include "SkDevice.h"
4 
5 class OwnDeviceCanvas : public SkCanvas {
6 public:
OwnDeviceCanvas(SkDevice * device)7     OwnDeviceCanvas(SkDevice* device) : SkCanvas(device) {
8         SkSafeUnref(device);
9     }
10 };
11 
onFilterImage(Proxy * proxy,const SkBitmap & src,const SkMatrix & matrix,SkBitmap * result,SkIPoint * loc)12 bool 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 
onFilterBounds(const SkIRect & src,const SkMatrix & ctm,SkIRect * dst)25 bool 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 
flatten(SkFlattenableWriteBuffer & buffer)35 void SkOffsetImageFilter::flatten(SkFlattenableWriteBuffer& buffer) {
36     this->INHERITED::flatten(buffer);
37     buffer.writeScalar(fOffset.x());
38     buffer.writeScalar(fOffset.y());
39 }
40 
SkOffsetImageFilter(SkFlattenableReadBuffer & buffer)41 SkOffsetImageFilter::SkOffsetImageFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
42     fOffset.fX = buffer.readScalar();
43     fOffset.fY = buffer.readScalar();
44 }
45 
getFactory()46 SkFlattenable::Factory SkOffsetImageFilter::getFactory() {
47     return CreateProc;
48 }
49 
50 ///////////////////////////////////////////////////////////////////////////////
51 
~SkComposeImageFilter()52 SkComposeImageFilter::~SkComposeImageFilter() {
53     SkSafeUnref(fInner);
54     SkSafeUnref(fOuter);
55 }
56 
onFilterImage(Proxy * proxy,const SkBitmap & src,const SkMatrix & ctm,SkBitmap * result,SkIPoint * loc)57 bool 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 
onFilterBounds(const SkIRect & src,const SkMatrix & ctm,SkIRect * dst)75 bool 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 
flatten(SkFlattenableWriteBuffer & buffer)91 void SkComposeImageFilter::flatten(SkFlattenableWriteBuffer& buffer) {
92     this->INHERITED::flatten(buffer);
93 
94     buffer.writeFlattenable(fOuter);
95     buffer.writeFlattenable(fInner);
96 }
97 
SkComposeImageFilter(SkFlattenableReadBuffer & buffer)98 SkComposeImageFilter::SkComposeImageFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
99     fOuter = (SkImageFilter*)buffer.readFlattenable();
100     fInner = (SkImageFilter*)buffer.readFlattenable();
101 }
102 
getFactory()103 SkFlattenable::Factory SkComposeImageFilter::getFactory() {
104     return CreateProc;
105 }
106 
107 ///////////////////////////////////////////////////////////////////////////////
108 
SkSafeRefReturn(T * obj)109 template <typename T> T* SkSafeRefReturn(T* obj) {
110     SkSafeRef(obj);
111     return obj;
112 }
113 
initAlloc(int count,bool hasModes)114 void 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 
init(SkImageFilter * const filters[],int count,const SkXfermode::Mode modes[])132 void 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 
SkMergeImageFilter(SkImageFilter * first,SkImageFilter * second,SkXfermode::Mode mode)143 SkMergeImageFilter::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 
SkMergeImageFilter(SkImageFilter * const filters[],int count,const SkXfermode::Mode modes[])150 SkMergeImageFilter::SkMergeImageFilter(SkImageFilter* const filters[], int count,
151                                        const SkXfermode::Mode modes[]) {
152     this->init(filters, count, modes);
153 }
154 
~SkMergeImageFilter()155 SkMergeImageFilter::~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 
onFilterBounds(const SkIRect & src,const SkMatrix & ctm,SkIRect * dst)167 bool 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 
onFilterImage(Proxy * proxy,const SkBitmap & src,const SkMatrix & ctm,SkBitmap * result,SkIPoint * loc)198 bool 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 
flatten(SkFlattenableWriteBuffer & buffer)249 void 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 
SkMergeImageFilter(SkFlattenableReadBuffer & buffer)269 SkMergeImageFilter::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 
getFactory()285 SkFlattenable::Factory SkMergeImageFilter::getFactory() {
286     return CreateProc;
287 }
288 
289 ///////////////////////////////////////////////////////////////////////////////
290 
291 #include "SkColorFilter.h"
292 
~SkColorFilterImageFilter()293 SkColorFilterImageFilter::~SkColorFilterImageFilter() {
294     SkSafeUnref(fColorFilter);
295 }
296 
onFilterImage(Proxy * proxy,const SkBitmap & src,const SkMatrix & matrix,SkBitmap * result,SkIPoint * loc)297 bool 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 
flatten(SkFlattenableWriteBuffer & buffer)322 void SkColorFilterImageFilter::flatten(SkFlattenableWriteBuffer& buffer) {
323     this->INHERITED::flatten(buffer);
324 
325     buffer.writeFlattenable(fColorFilter);
326 }
327 
SkColorFilterImageFilter(SkFlattenableReadBuffer & buffer)328 SkColorFilterImageFilter::SkColorFilterImageFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
329     fColorFilter = (SkColorFilter*)buffer.readFlattenable();
330 }
331 
getFactory()332 SkFlattenable::Factory SkColorFilterImageFilter::getFactory() {
333     return CreateProc;
334 }
335 
336 ///////////////////////////////////////////////////////////////////////////////
337 
onFilterImage(Proxy * proxy,const SkBitmap & src,const SkMatrix & matrix,SkBitmap * result,SkIPoint *)338 bool 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 
flatten(SkFlattenableWriteBuffer & buffer)388 void SkDownSampleImageFilter::flatten(SkFlattenableWriteBuffer& buffer) {
389     this->INHERITED::flatten(buffer);
390 
391     buffer.writeScalar(fScale);
392 }
393 
SkDownSampleImageFilter(SkFlattenableReadBuffer & buffer)394 SkDownSampleImageFilter::SkDownSampleImageFilter(SkFlattenableReadBuffer& buffer) : INHERITED(buffer) {
395     fScale = buffer.readScalar();
396 }
397 
getFactory()398 SkFlattenable::Factory SkDownSampleImageFilter::getFactory() {
399     return CreateProc;
400 }
401 
402