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