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
onFilterImageDeprecated(Proxy * proxy,const SkBitmap & source,const Context & ctx,SkBitmap * result,SkIPoint * offset) const17 bool SkOffsetImageFilter::onFilterImageDeprecated(Proxy* proxy, const SkBitmap& source,
18 const Context& ctx,
19 SkBitmap* result,
20 SkIPoint* offset) const {
21 SkBitmap src = source;
22 SkIPoint srcOffset = SkIPoint::Make(0, 0);
23 if (!cropRectIsSet()) {
24 if (!this->filterInputDeprecated(0, proxy, source, ctx, &src, &srcOffset)) {
25 return false;
26 }
27
28 SkVector vec;
29 ctx.ctm().mapVectors(&vec, &fOffset, 1);
30
31 offset->fX = srcOffset.fX + SkScalarRoundToInt(vec.fX);
32 offset->fY = srcOffset.fY + SkScalarRoundToInt(vec.fY);
33 *result = src;
34 } else {
35 if (!this->filterInputDeprecated(0, proxy, source, ctx, &src, &srcOffset)) {
36 return false;
37 }
38
39 SkIRect bounds;
40 SkIRect srcBounds = src.bounds();
41 srcBounds.offset(srcOffset);
42 if (!this->applyCropRect(ctx, srcBounds, &bounds)) {
43 return false;
44 }
45
46 SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds.width(), bounds.height()));
47 if (nullptr == device.get()) {
48 return false;
49 }
50 SkCanvas canvas(device);
51 SkPaint paint;
52 paint.setXfermodeMode(SkXfermode::kSrc_Mode);
53 canvas.translate(SkIntToScalar(srcOffset.fX - bounds.fLeft),
54 SkIntToScalar(srcOffset.fY - bounds.fTop));
55 SkVector vec;
56 ctx.ctm().mapVectors(&vec, &fOffset, 1);
57 canvas.drawBitmap(src, vec.x(), vec.y(), &paint);
58 *result = device->accessBitmap(false);
59 offset->fX = bounds.fLeft;
60 offset->fY = bounds.fTop;
61 }
62 return true;
63 }
64
computeFastBounds(const SkRect & src,SkRect * dst) const65 void SkOffsetImageFilter::computeFastBounds(const SkRect& src, SkRect* dst) const {
66 if (getInput(0)) {
67 getInput(0)->computeFastBounds(src, dst);
68 } else {
69 *dst = src;
70 }
71 dst->offset(fOffset.fX, fOffset.fY);
72 }
73
onFilterNodeBounds(const SkIRect & src,const SkMatrix & ctm,SkIRect * dst,MapDirection direction) const74 void SkOffsetImageFilter::onFilterNodeBounds(const SkIRect& src, const SkMatrix& ctm,
75 SkIRect* dst, MapDirection direction) const {
76 SkVector vec;
77 ctm.mapVectors(&vec, &fOffset, 1);
78 if (kReverse_MapDirection == direction) {
79 vec.negate();
80 }
81
82 *dst = src;
83 dst->offset(SkScalarCeilToInt(vec.fX), SkScalarCeilToInt(vec.fY));
84 }
85
CreateProc(SkReadBuffer & buffer)86 SkFlattenable* SkOffsetImageFilter::CreateProc(SkReadBuffer& buffer) {
87 SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
88 SkPoint offset;
89 buffer.readPoint(&offset);
90 return Create(offset.x(), offset.y(), common.getInput(0), &common.cropRect());
91 }
92
flatten(SkWriteBuffer & buffer) const93 void SkOffsetImageFilter::flatten(SkWriteBuffer& buffer) const {
94 this->INHERITED::flatten(buffer);
95 buffer.writePoint(fOffset);
96 }
97
SkOffsetImageFilter(SkScalar dx,SkScalar dy,SkImageFilter * input,const CropRect * cropRect)98 SkOffsetImageFilter::SkOffsetImageFilter(SkScalar dx, SkScalar dy, SkImageFilter* input,
99 const CropRect* cropRect)
100 : INHERITED(1, &input, cropRect) {
101 fOffset.set(dx, dy);
102 }
103
104 #ifndef SK_IGNORE_TO_STRING
toString(SkString * str) const105 void SkOffsetImageFilter::toString(SkString* str) const {
106 str->appendf("SkOffsetImageFilter: (");
107 str->appendf("offset: (%f, %f) ", fOffset.fX, fOffset.fY);
108 str->append("input: (");
109 if (this->getInput(0)) {
110 this->getInput(0)->toString(str);
111 }
112 str->append("))");
113 }
114 #endif
115