Home | History | Annotate | Download | only in effects
      1 /*
      2  * Copyright 2012 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 "SkOffsetImageFilter.h"
      9 #include "SkBitmap.h"
     10 #include "SkCanvas.h"
     11 #include "SkDevice.h"
     12 #include "SkFlattenableBuffers.h"
     13 #include "SkMatrix.h"
     14 #include "SkPaint.h"
     15 
     16 bool SkOffsetImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& source,
     17                                         const SkMatrix& matrix,
     18                                         SkBitmap* result,
     19                                         SkIPoint* loc) {
     20     SkImageFilter* input = getInput(0);
     21     SkBitmap src = source;
     22 #ifdef SK_DISABLE_OFFSETIMAGEFILTER_OPTIMIZATION
     23     if (false) {
     24 #else
     25     if (!cropRectIsSet()) {
     26 #endif
     27         if (input && !input->filterImage(proxy, source, matrix, &src, loc)) {
     28             return false;
     29         }
     30 
     31         SkVector vec;
     32         matrix.mapVectors(&vec, &fOffset, 1);
     33 
     34         loc->fX += SkScalarRoundToInt(vec.fX);
     35         loc->fY += SkScalarRoundToInt(vec.fY);
     36         *result = src;
     37     } else {
     38         SkIPoint srcOffset = SkIPoint::Make(0, 0);
     39         if (input && !input->filterImage(proxy, source, matrix, &src, &srcOffset)) {
     40             return false;
     41         }
     42 
     43         SkIRect bounds;
     44         src.getBounds(&bounds);
     45 
     46         if (!applyCropRect(&bounds, matrix)) {
     47             return false;
     48         }
     49 
     50         SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds.width(), bounds.height()));
     51         if (NULL == device.get()) {
     52             return false;
     53         }
     54         SkCanvas canvas(device);
     55         SkPaint paint;
     56         paint.setXfermodeMode(SkXfermode::kSrc_Mode);
     57         canvas.drawBitmap(src, fOffset.fX - bounds.left(), fOffset.fY - bounds.top(), &paint);
     58         *result = device->accessBitmap(false);
     59         loc->fX += bounds.left();
     60         loc->fY += bounds.top();
     61     }
     62     return true;
     63 }
     64 
     65 bool SkOffsetImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
     66                                          SkIRect* dst) {
     67     SkVector vec;
     68     ctm.mapVectors(&vec, &fOffset, 1);
     69 
     70     *dst = src;
     71     dst->offset(SkScalarRoundToInt(vec.fX), SkScalarRoundToInt(vec.fY));
     72     return true;
     73 }
     74 
     75 void SkOffsetImageFilter::flatten(SkFlattenableWriteBuffer& buffer) const {
     76     this->INHERITED::flatten(buffer);
     77     buffer.writePoint(fOffset);
     78 }
     79 
     80 SkOffsetImageFilter::SkOffsetImageFilter(SkScalar dx, SkScalar dy, SkImageFilter* input,
     81                                          const CropRect* cropRect) : INHERITED(input, cropRect) {
     82     fOffset.set(dx, dy);
     83 }
     84 
     85 SkOffsetImageFilter::SkOffsetImageFilter(SkFlattenableReadBuffer& buffer)
     86   : INHERITED(1, buffer) {
     87     buffer.readPoint(&fOffset);
     88     buffer.validate(SkScalarIsFinite(fOffset.fX) &&
     89                     SkScalarIsFinite(fOffset.fY));
     90 }
     91