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 "SkReadBuffer.h"
     13 #include "SkWriteBuffer.h"
     14 #include "SkMatrix.h"
     15 #include "SkPaint.h"
     16 
     17 bool SkOffsetImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& source,
     18                                         const Context& ctx,
     19                                         SkBitmap* result,
     20                                         SkIPoint* offset) const {
     21     SkImageFilter* input = getInput(0);
     22     SkBitmap src = source;
     23     SkIPoint srcOffset = SkIPoint::Make(0, 0);
     24 #ifdef SK_DISABLE_OFFSETIMAGEFILTER_OPTIMIZATION
     25     if (false) {
     26 #else
     27     if (!cropRectIsSet()) {
     28 #endif
     29         if (input && !input->filterImage(proxy, source, ctx, &src, &srcOffset)) {
     30             return false;
     31         }
     32 
     33         SkVector vec;
     34         ctx.ctm().mapVectors(&vec, &fOffset, 1);
     35 
     36         offset->fX = srcOffset.fX + SkScalarRoundToInt(vec.fX);
     37         offset->fY = srcOffset.fY + SkScalarRoundToInt(vec.fY);
     38         *result = src;
     39     } else {
     40         if (input && !input->filterImage(proxy, source, ctx, &src, &srcOffset)) {
     41             return false;
     42         }
     43 
     44         SkIRect bounds;
     45         if (!this->applyCropRect(ctx, src, srcOffset, &bounds)) {
     46             return false;
     47         }
     48 
     49         SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds.width(), bounds.height()));
     50         if (NULL == device.get()) {
     51             return false;
     52         }
     53         SkCanvas canvas(device);
     54         SkPaint paint;
     55         paint.setXfermodeMode(SkXfermode::kSrc_Mode);
     56         canvas.translate(SkIntToScalar(srcOffset.fX - bounds.fLeft),
     57                          SkIntToScalar(srcOffset.fY - bounds.fTop));
     58         SkVector vec;
     59         ctx.ctm().mapVectors(&vec, &fOffset, 1);
     60         canvas.drawBitmap(src, vec.x(), vec.y(), &paint);
     61         *result = device->accessBitmap(false);
     62         offset->fX = bounds.fLeft;
     63         offset->fY = bounds.fTop;
     64     }
     65     return true;
     66 }
     67 
     68 void SkOffsetImageFilter::computeFastBounds(const SkRect& src, SkRect* dst) const {
     69     if (getInput(0)) {
     70         getInput(0)->computeFastBounds(src, dst);
     71     } else {
     72         *dst = src;
     73     }
     74     SkRect copy = *dst;
     75     dst->offset(fOffset.fX, fOffset.fY);
     76     dst->join(copy);
     77 }
     78 
     79 bool SkOffsetImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
     80                                          SkIRect* dst) const {
     81     SkVector vec;
     82     ctm.mapVectors(&vec, &fOffset, 1);
     83 
     84     SkIRect bounds = src;
     85     bounds.offset(-SkScalarCeilToInt(vec.fX), -SkScalarCeilToInt(vec.fY));
     86     bounds.join(src);
     87     if (getInput(0)) {
     88         return getInput(0)->filterBounds(bounds, ctm, dst);
     89     }
     90     *dst = bounds;
     91     return true;
     92 }
     93 
     94 void SkOffsetImageFilter::flatten(SkWriteBuffer& buffer) const {
     95     this->INHERITED::flatten(buffer);
     96     buffer.writePoint(fOffset);
     97 }
     98 
     99 SkOffsetImageFilter::SkOffsetImageFilter(SkScalar dx, SkScalar dy, SkImageFilter* input,
    100                                          const CropRect* cropRect) : INHERITED(input, cropRect) {
    101     fOffset.set(dx, dy);
    102 }
    103 
    104 SkOffsetImageFilter::SkOffsetImageFilter(SkReadBuffer& buffer)
    105   : INHERITED(1, buffer) {
    106     buffer.readPoint(&fOffset);
    107     buffer.validate(SkScalarIsFinite(fOffset.fX) &&
    108                     SkScalarIsFinite(fOffset.fY));
    109 }
    110