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