blob: 5a585efffcff62cc9456aa841eb26b2d4201db3a [file] [log] [blame]
senorblanco@chromium.orgfd0ec2c2014-03-25 17:35:10 +00001/*
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
18SkMatrixImageFilter::SkMatrixImageFilter(const SkMatrix& transform,
reed93a12152015-03-16 10:08:34 -070019 SkFilterQuality filterQuality,
senorblanco24e06d52015-03-18 12:11:33 -070020 SkImageFilter* input)
21 : INHERITED(1, &input),
senorblanco@chromium.orgfd0ec2c2014-03-25 17:35:10 +000022 fTransform(transform),
reed93a12152015-03-16 10:08:34 -070023 fFilterQuality(filterQuality) {
senorblanco@chromium.orgfd0ec2c2014-03-25 17:35:10 +000024}
25
26SkMatrixImageFilter* SkMatrixImageFilter::Create(const SkMatrix& transform,
reed93a12152015-03-16 10:08:34 -070027 SkFilterQuality filterQuality,
senorblanco24e06d52015-03-18 12:11:33 -070028 SkImageFilter* input) {
halcanary385fe4d2015-08-26 13:07:48 -070029 return new SkMatrixImageFilter(transform, filterQuality, input);
senorblanco@chromium.orgfd0ec2c2014-03-25 17:35:10 +000030}
31
reed9fa60da2014-08-21 07:59:51 -070032SkFlattenable* SkMatrixImageFilter::CreateProc(SkReadBuffer& buffer) {
33 SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
34 SkMatrix matrix;
35 buffer.readMatrix(&matrix);
reed93a12152015-03-16 10:08:34 -070036 SkFilterQuality quality = static_cast<SkFilterQuality>(buffer.readInt());
senorblanco24e06d52015-03-18 12:11:33 -070037 return Create(matrix, quality, common.getInput(0));
reed9fa60da2014-08-21 07:59:51 -070038}
senorblanco@chromium.orgfd0ec2c2014-03-25 17:35:10 +000039
40void SkMatrixImageFilter::flatten(SkWriteBuffer& buffer) const {
41 this->INHERITED::flatten(buffer);
42 buffer.writeMatrix(fTransform);
reed93a12152015-03-16 10:08:34 -070043 buffer.writeInt(fFilterQuality);
senorblanco@chromium.orgfd0ec2c2014-03-25 17:35:10 +000044}
45
46SkMatrixImageFilter::~SkMatrixImageFilter() {
47}
48
robertphillips48e78462016-02-17 13:57:16 -080049bool SkMatrixImageFilter::onFilterImageDeprecated(Proxy* proxy,
50 const SkBitmap& source,
51 const Context& ctx,
52 SkBitmap* result,
53 SkIPoint* offset) const {
senorblanco@chromium.orgfd0ec2c2014-03-25 17:35:10 +000054 SkBitmap src = source;
55 SkIPoint srcOffset = SkIPoint::Make(0, 0);
robertphillips48e78462016-02-17 13:57:16 -080056 if (!this->filterInputDeprecated(0, proxy, source, ctx, &src, &srcOffset)) {
senorblanco@chromium.orgfd0ec2c2014-03-25 17:35:10 +000057 return false;
58 }
59
60 SkRect dstRect;
61 SkIRect srcBounds, dstBounds;
62 src.getBounds(&srcBounds);
63 srcBounds.offset(srcOffset);
64 SkRect srcRect = SkRect::Make(srcBounds);
65 SkMatrix matrix;
66 if (!ctx.ctm().invert(&matrix)) {
67 return false;
68 }
69 matrix.postConcat(fTransform);
70 matrix.postConcat(ctx.ctm());
71 matrix.mapRect(&dstRect, srcRect);
72 dstRect.roundOut(&dstBounds);
73
74 SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(dstBounds.width(), dstBounds.height()));
halcanary96fcdcc2015-08-27 07:41:13 -070075 if (nullptr == device.get()) {
senorblanco@chromium.orgfd0ec2c2014-03-25 17:35:10 +000076 return false;
77 }
78
79 SkCanvas canvas(device.get());
80 canvas.translate(-SkIntToScalar(dstBounds.x()), -SkIntToScalar(dstBounds.y()));
81 canvas.concat(matrix);
reeddaa57bf2015-05-15 10:39:17 -070082 SkPaint paint;
83
84 paint.setXfermodeMode(SkXfermode::kSrc_Mode);
85 paint.setFilterQuality(fFilterQuality);
senorblanco@chromium.orgfd0ec2c2014-03-25 17:35:10 +000086 canvas.drawBitmap(src, srcRect.x(), srcRect.y(), &paint);
87
88 *result = device.get()->accessBitmap(false);
89 offset->fX = dstBounds.fLeft;
90 offset->fY = dstBounds.fTop;
91 return true;
92}
93
94void SkMatrixImageFilter::computeFastBounds(const SkRect& src, SkRect* dst) const {
95 SkRect bounds = src;
96 if (getInput(0)) {
97 getInput(0)->computeFastBounds(src, &bounds);
98 }
robertphillips8b7b9c22014-12-09 05:28:24 -080099 fTransform.mapRect(dst, bounds);
senorblanco@chromium.orgfd0ec2c2014-03-25 17:35:10 +0000100}
101
senorblancodb64af32015-12-09 10:11:43 -0800102void SkMatrixImageFilter::onFilterNodeBounds(const SkIRect& src, const SkMatrix& ctm,
103 SkIRect* dst, MapDirection direction) const {
senorblanco@chromium.orgfd0ec2c2014-03-25 17:35:10 +0000104 SkMatrix matrix;
105 if (!ctm.invert(&matrix)) {
senorblancodb64af32015-12-09 10:11:43 -0800106 *dst = src;
107 return;
senorblanco@chromium.orgfd0ec2c2014-03-25 17:35:10 +0000108 }
senorblancodb64af32015-12-09 10:11:43 -0800109 if (kForward_MapDirection == direction) {
110 matrix.postConcat(fTransform);
111 } else {
112 SkMatrix transformInverse;
113 if (!fTransform.invert(&transformInverse)) {
114 *dst = src;
115 return;
116 }
117 matrix.postConcat(transformInverse);
118 }
senorblanco@chromium.orgfd0ec2c2014-03-25 17:35:10 +0000119 matrix.postConcat(ctm);
120 SkRect floatBounds;
121 matrix.mapRect(&floatBounds, SkRect::Make(src));
reedb07a94f2014-11-19 05:03:18 -0800122 SkIRect bounds = floatBounds.roundOut();
senorblanco@chromium.orgfd0ec2c2014-03-25 17:35:10 +0000123 *dst = bounds;
senorblanco@chromium.orgfd0ec2c2014-03-25 17:35:10 +0000124}
robertphillipsf3f5bad2014-12-19 13:49:15 -0800125
126#ifndef SK_IGNORE_TO_STRING
127void SkMatrixImageFilter::toString(SkString* str) const {
128 str->appendf("SkMatrixImageFilter: (");
129
130 str->appendf("transform: (%f %f %f %f %f %f %f %f %f)",
131 fTransform[SkMatrix::kMScaleX],
132 fTransform[SkMatrix::kMSkewX],
133 fTransform[SkMatrix::kMTransX],
134 fTransform[SkMatrix::kMSkewY],
135 fTransform[SkMatrix::kMScaleY],
136 fTransform[SkMatrix::kMTransY],
137 fTransform[SkMatrix::kMPersp0],
138 fTransform[SkMatrix::kMPersp1],
139 fTransform[SkMatrix::kMPersp2]);
140
141 str->append("<dt>FilterLevel:</dt><dd>");
142 static const char* gFilterLevelStrings[] = { "None", "Low", "Medium", "High" };
reed93a12152015-03-16 10:08:34 -0700143 str->append(gFilterLevelStrings[fFilterQuality]);
robertphillipsf3f5bad2014-12-19 13:49:15 -0800144 str->append("</dd>");
145
146 str->appendf(")");
147}
148#endif