blob: 7680c62cfc948738b9f8e9dea124ef07666f50d7 [file] [log] [blame]
senorblanco@chromium.org9daf96a2012-11-06 20:29:39 +00001/*
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"
commit-bot@chromium.org1a4fb702013-09-26 16:09:28 +000010#include "SkCanvas.h"
11#include "SkDevice.h"
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000012#include "SkReadBuffer.h"
13#include "SkWriteBuffer.h"
commit-bot@chromium.org1a4fb702013-09-26 16:09:28 +000014#include "SkMatrix.h"
15#include "SkPaint.h"
senorblanco@chromium.org9daf96a2012-11-06 20:29:39 +000016
17bool SkOffsetImageFilter::onFilterImage(Proxy* proxy, const SkBitmap& source,
senorblanco@chromium.org4cb543d2014-03-14 15:44:01 +000018 const Context& ctx,
senorblanco@chromium.org9daf96a2012-11-06 20:29:39 +000019 SkBitmap* result,
commit-bot@chromium.orgae761f72014-02-05 22:32:02 +000020 SkIPoint* offset) const {
commit-bot@chromium.org1a4fb702013-09-26 16:09:28 +000021 SkImageFilter* input = getInput(0);
senorblanco@chromium.org68400762013-05-24 15:04:07 +000022 SkBitmap src = source;
senorblanco@chromium.org6776b822014-01-03 21:48:22 +000023 SkIPoint srcOffset = SkIPoint::Make(0, 0);
commit-bot@chromium.orgf2f8f3a2013-11-01 11:55:06 +000024#ifdef SK_DISABLE_OFFSETIMAGEFILTER_OPTIMIZATION
25 if (false) {
26#else
senorblanco@chromium.orgb295fb62013-10-10 13:51:19 +000027 if (!cropRectIsSet()) {
commit-bot@chromium.orgf2f8f3a2013-11-01 11:55:06 +000028#endif
senorblanco@chromium.org4cb543d2014-03-14 15:44:01 +000029 if (input && !input->filterImage(proxy, source, ctx, &src, &srcOffset)) {
commit-bot@chromium.org1a4fb702013-09-26 16:09:28 +000030 return false;
31 }
32
33 SkVector vec;
senorblanco@chromium.org4cb543d2014-03-14 15:44:01 +000034 ctx.ctm().mapVectors(&vec, &fOffset, 1);
commit-bot@chromium.org1a4fb702013-09-26 16:09:28 +000035
senorblanco@chromium.org6776b822014-01-03 21:48:22 +000036 offset->fX = srcOffset.fX + SkScalarRoundToInt(vec.fX);
37 offset->fY = srcOffset.fY + SkScalarRoundToInt(vec.fY);
commit-bot@chromium.org1a4fb702013-09-26 16:09:28 +000038 *result = src;
39 } else {
senorblanco@chromium.org4cb543d2014-03-14 15:44:01 +000040 if (input && !input->filterImage(proxy, source, ctx, &src, &srcOffset)) {
commit-bot@chromium.org1a4fb702013-09-26 16:09:28 +000041 return false;
42 }
43
44 SkIRect bounds;
senorblanco@chromium.org11825292014-03-14 17:44:41 +000045 if (!this->applyCropRect(ctx, src, srcOffset, &bounds)) {
commit-bot@chromium.org1a4fb702013-09-26 16:09:28 +000046 return false;
47 }
48
49 SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds.width(), bounds.height()));
commit-bot@chromium.orgcd3b15c2013-12-04 17:06:49 +000050 if (NULL == device.get()) {
51 return false;
52 }
commit-bot@chromium.org1a4fb702013-09-26 16:09:28 +000053 SkCanvas canvas(device);
54 SkPaint paint;
55 paint.setXfermodeMode(SkXfermode::kSrc_Mode);
senorblanco@chromium.org6776b822014-01-03 21:48:22 +000056 canvas.translate(SkIntToScalar(srcOffset.fX - bounds.fLeft),
57 SkIntToScalar(srcOffset.fY - bounds.fTop));
senorblanco@chromium.orge09244d2014-03-04 19:05:25 +000058 SkVector vec;
senorblanco@chromium.org4cb543d2014-03-14 15:44:01 +000059 ctx.ctm().mapVectors(&vec, &fOffset, 1);
senorblanco@chromium.orge09244d2014-03-04 19:05:25 +000060 canvas.drawBitmap(src, vec.x(), vec.y(), &paint);
commit-bot@chromium.org1a4fb702013-09-26 16:09:28 +000061 *result = device->accessBitmap(false);
senorblanco@chromium.org6776b822014-01-03 21:48:22 +000062 offset->fX = bounds.fLeft;
63 offset->fY = bounds.fTop;
senorblanco@chromium.org68400762013-05-24 15:04:07 +000064 }
senorblanco@chromium.org9daf96a2012-11-06 20:29:39 +000065 return true;
66}
67
senorblanco@chromium.org336d1d72014-01-27 21:03:17 +000068void SkOffsetImageFilter::computeFastBounds(const SkRect& src, SkRect* dst) const {
69 if (getInput(0)) {
70 getInput(0)->computeFastBounds(src, dst);
71 } else {
72 *dst = src;
73 }
senorblanco@chromium.orgc4b12f12014-02-05 17:51:22 +000074 SkRect copy = *dst;
senorblanco@chromium.org336d1d72014-01-27 21:03:17 +000075 dst->offset(fOffset.fX, fOffset.fY);
senorblanco@chromium.orgc4b12f12014-02-05 17:51:22 +000076 dst->join(copy);
senorblanco@chromium.org336d1d72014-01-27 21:03:17 +000077}
78
senorblanco@chromium.org9daf96a2012-11-06 20:29:39 +000079bool SkOffsetImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
senorblanco@chromium.orgc4b12f12014-02-05 17:51:22 +000080 SkIRect* dst) const {
senorblanco@chromium.org9daf96a2012-11-06 20:29:39 +000081 SkVector vec;
82 ctm.mapVectors(&vec, &fOffset, 1);
83
senorblanco@chromium.org06342a22014-03-11 18:29:42 +000084 SkIRect bounds = src;
85 bounds.offset(-SkScalarCeilToInt(vec.fX), -SkScalarCeilToInt(vec.fY));
86 bounds.join(src);
senorblanco@chromium.org29ac34e2014-05-28 19:29:25 +000087 if (getInput(0)) {
88 return getInput(0)->filterBounds(bounds, ctm, dst);
89 }
senorblanco@chromium.org06342a22014-03-11 18:29:42 +000090 *dst = bounds;
senorblanco@chromium.org9daf96a2012-11-06 20:29:39 +000091 return true;
92}
93
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000094void SkOffsetImageFilter::flatten(SkWriteBuffer& buffer) const {
senorblanco@chromium.org9daf96a2012-11-06 20:29:39 +000095 this->INHERITED::flatten(buffer);
96 buffer.writePoint(fOffset);
97}
98
commit-bot@chromium.org1a4fb702013-09-26 16:09:28 +000099SkOffsetImageFilter::SkOffsetImageFilter(SkScalar dx, SkScalar dy, SkImageFilter* input,
senorblanco@chromium.orgb295fb62013-10-10 13:51:19 +0000100 const CropRect* cropRect) : INHERITED(input, cropRect) {
senorblanco@chromium.org9daf96a2012-11-06 20:29:39 +0000101 fOffset.set(dx, dy);
102}
103
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +0000104SkOffsetImageFilter::SkOffsetImageFilter(SkReadBuffer& buffer)
commit-bot@chromium.orgce33d602013-11-25 21:46:31 +0000105 : INHERITED(1, buffer) {
senorblanco@chromium.org9daf96a2012-11-06 20:29:39 +0000106 buffer.readPoint(&fOffset);
commit-bot@chromium.orgc0b7e102013-10-23 17:06:21 +0000107 buffer.validate(SkScalarIsFinite(fOffset.fX) &&
108 SkScalarIsFinite(fOffset.fY));
senorblanco@chromium.org9daf96a2012-11-06 20:29:39 +0000109}