Home | History | Annotate | Download | only in effects
      1 /*
      2  * Copyright 2014 The Android Open Source Project
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "SkMatrixImageFilter.h"
      9 #include "SkBitmap.h"
     10 #include "SkCanvas.h"
     11 #include "SkDevice.h"
     12 #include "SkColorPriv.h"
     13 #include "SkReadBuffer.h"
     14 #include "SkWriteBuffer.h"
     15 #include "SkMatrix.h"
     16 #include "SkRect.h"
     17 
     18 SkMatrixImageFilter::SkMatrixImageFilter(const SkMatrix& transform,
     19                                          SkPaint::FilterLevel filterLevel,
     20                                          SkImageFilter* input,
     21                                          uint32_t uniqueID)
     22   : INHERITED(1, &input, NULL, uniqueID),
     23     fTransform(transform),
     24     fFilterLevel(filterLevel) {
     25 }
     26 
     27 SkMatrixImageFilter* SkMatrixImageFilter::Create(const SkMatrix& transform,
     28                                                  SkPaint::FilterLevel filterLevel,
     29                                                  SkImageFilter* input,
     30                                                  uint32_t uniqueID) {
     31     return SkNEW_ARGS(SkMatrixImageFilter, (transform, filterLevel, input, uniqueID));
     32 }
     33 
     34 #ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
     35 SkMatrixImageFilter::SkMatrixImageFilter(SkReadBuffer& buffer)
     36   : INHERITED(1, buffer) {
     37     buffer.readMatrix(&fTransform);
     38     fFilterLevel = static_cast<SkPaint::FilterLevel>(buffer.readInt());
     39 }
     40 #endif
     41 
     42 SkFlattenable* SkMatrixImageFilter::CreateProc(SkReadBuffer& buffer) {
     43     SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
     44     SkMatrix matrix;
     45     buffer.readMatrix(&matrix);
     46     SkPaint::FilterLevel level = static_cast<SkPaint::FilterLevel>(buffer.readInt());
     47     return Create(matrix, level, common.getInput(0), common.uniqueID());
     48 }
     49 
     50 void SkMatrixImageFilter::flatten(SkWriteBuffer& buffer) const {
     51     this->INHERITED::flatten(buffer);
     52     buffer.writeMatrix(fTransform);
     53     buffer.writeInt(fFilterLevel);
     54 }
     55 
     56 SkMatrixImageFilter::~SkMatrixImageFilter() {
     57 }
     58 
     59 bool SkMatrixImageFilter::onFilterImage(Proxy* proxy,
     60                                         const SkBitmap& source,
     61                                         const Context& ctx,
     62                                         SkBitmap* result,
     63                                         SkIPoint* offset) const {
     64     SkBitmap src = source;
     65     SkIPoint srcOffset = SkIPoint::Make(0, 0);
     66     if (getInput(0) && !getInput(0)->filterImage(proxy, source, ctx, &src, &srcOffset)) {
     67         return false;
     68     }
     69 
     70     SkRect dstRect;
     71     SkIRect srcBounds, dstBounds;
     72     src.getBounds(&srcBounds);
     73     srcBounds.offset(srcOffset);
     74     SkRect srcRect = SkRect::Make(srcBounds);
     75     SkMatrix matrix;
     76     if (!ctx.ctm().invert(&matrix)) {
     77         return false;
     78     }
     79     matrix.postConcat(fTransform);
     80     matrix.postConcat(ctx.ctm());
     81     matrix.mapRect(&dstRect, srcRect);
     82     dstRect.roundOut(&dstBounds);
     83 
     84     SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(dstBounds.width(), dstBounds.height()));
     85     if (NULL == device.get()) {
     86         return false;
     87     }
     88 
     89     SkCanvas canvas(device.get());
     90     canvas.translate(-SkIntToScalar(dstBounds.x()), -SkIntToScalar(dstBounds.y()));
     91     canvas.concat(matrix);
     92     SkPaint paint;
     93 
     94     paint.setXfermodeMode(SkXfermode::kSrc_Mode);
     95     paint.setFilterLevel(fFilterLevel);
     96     canvas.drawBitmap(src, srcRect.x(), srcRect.y(), &paint);
     97 
     98     *result = device.get()->accessBitmap(false);
     99     offset->fX = dstBounds.fLeft;
    100     offset->fY = dstBounds.fTop;
    101     return true;
    102 }
    103 
    104 void SkMatrixImageFilter::computeFastBounds(const SkRect& src, SkRect* dst) const {
    105     SkRect bounds = src;
    106     if (getInput(0)) {
    107         getInput(0)->computeFastBounds(src, &bounds);
    108     }
    109     SkMatrix matrix;
    110     matrix.setTranslate(-bounds.x(), -bounds.y());
    111     matrix.postConcat(fTransform);
    112     matrix.postTranslate(bounds.x(), bounds.y());
    113     matrix.mapRect(dst, bounds);
    114 }
    115 
    116 bool SkMatrixImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
    117                                          SkIRect* dst) const {
    118     SkMatrix transformInverse;
    119     if (!fTransform.invert(&transformInverse)) {
    120         return false;
    121     }
    122     SkMatrix matrix;
    123     if (!ctm.invert(&matrix)) {
    124         return false;
    125     }
    126     matrix.postConcat(transformInverse);
    127     matrix.postConcat(ctm);
    128     SkRect floatBounds;
    129     matrix.mapRect(&floatBounds, SkRect::Make(src));
    130     SkIRect bounds;
    131     floatBounds.roundOut(&bounds);
    132     if (getInput(0) && !getInput(0)->filterBounds(bounds, ctm, &bounds)) {
    133         return false;
    134     }
    135 
    136     *dst = bounds;
    137     return true;
    138 }
    139