Remove SK_SUPPORT_SRC_BOUNDS_BLOAT_FOR_IMAGEFILTERS (now unused).
[platform/upstream/libSkiaSharp.git] / src / core / SkMatrixImageFilter.cpp
1 /*
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
18 SkMatrixImageFilter::SkMatrixImageFilter(const SkMatrix& transform,
19                                          SkFilterQuality filterQuality,
20                                          SkImageFilter* input)
21   : INHERITED(1, &input),
22     fTransform(transform),
23     fFilterQuality(filterQuality) {
24 }
25
26 SkMatrixImageFilter* SkMatrixImageFilter::Create(const SkMatrix& transform,
27                                                  SkFilterQuality filterQuality,
28                                                  SkImageFilter* input) {
29     return new SkMatrixImageFilter(transform, filterQuality, input);
30 }
31
32 SkFlattenable* SkMatrixImageFilter::CreateProc(SkReadBuffer& buffer) {
33     SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
34     SkMatrix matrix;
35     buffer.readMatrix(&matrix);
36     SkFilterQuality quality = static_cast<SkFilterQuality>(buffer.readInt());
37     return Create(matrix, quality, common.getInput(0));
38 }
39
40 void SkMatrixImageFilter::flatten(SkWriteBuffer& buffer) const {
41     this->INHERITED::flatten(buffer);
42     buffer.writeMatrix(fTransform);
43     buffer.writeInt(fFilterQuality);
44 }
45
46 SkMatrixImageFilter::~SkMatrixImageFilter() {
47 }
48
49 bool SkMatrixImageFilter::onFilterImage(Proxy* proxy,
50                                         const SkBitmap& source,
51                                         const Context& ctx,
52                                         SkBitmap* result,
53                                         SkIPoint* offset) const {
54     SkBitmap src = source;
55     SkIPoint srcOffset = SkIPoint::Make(0, 0);
56     if (!this->filterInput(0, proxy, source, ctx, &src, &srcOffset)) {
57         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()));
75     if (nullptr == device.get()) {
76         return false;
77     }
78
79     SkCanvas canvas(device.get());
80     canvas.translate(-SkIntToScalar(dstBounds.x()), -SkIntToScalar(dstBounds.y()));
81     canvas.concat(matrix);
82     SkPaint paint;
83
84     paint.setXfermodeMode(SkXfermode::kSrc_Mode);
85     paint.setFilterQuality(fFilterQuality);
86     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
94 void SkMatrixImageFilter::computeFastBounds(const SkRect& src, SkRect* dst) const {
95     SkRect bounds = src;
96     if (getInput(0)) {
97         getInput(0)->computeFastBounds(src, &bounds);
98     }
99     fTransform.mapRect(dst, bounds);
100 }
101
102 void SkMatrixImageFilter::onFilterNodeBounds(const SkIRect& src, const SkMatrix& ctm,
103                                              SkIRect* dst, MapDirection direction) const {
104     SkMatrix matrix;
105     if (!ctm.invert(&matrix)) {
106         *dst = src;
107         return;
108     }
109     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     }
119     matrix.postConcat(ctm);
120     SkRect floatBounds;
121     matrix.mapRect(&floatBounds, SkRect::Make(src));
122     SkIRect bounds = floatBounds.roundOut();
123     *dst = bounds;
124 }
125
126 #ifndef SK_IGNORE_TO_STRING
127 void 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" };
143     str->append(gFilterLevelStrings[fFilterQuality]);
144     str->append("</dd>");
145
146     str->appendf(")");
147 }
148 #endif