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