2 * Copyright 2014 The Android Open Source Project
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #include "SkMatrixImageFilter.h"
12 #include "SkColorPriv.h"
13 #include "SkReadBuffer.h"
14 #include "SkWriteBuffer.h"
18 SkMatrixImageFilter::SkMatrixImageFilter(const SkMatrix& transform,
19 SkFilterQuality filterQuality,
21 : INHERITED(1, &input),
22 fTransform(transform),
23 fFilterQuality(filterQuality) {
26 SkMatrixImageFilter* SkMatrixImageFilter::Create(const SkMatrix& transform,
27 SkFilterQuality filterQuality,
28 SkImageFilter* input) {
29 return new SkMatrixImageFilter(transform, filterQuality, input);
32 SkFlattenable* SkMatrixImageFilter::CreateProc(SkReadBuffer& buffer) {
33 SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1);
35 buffer.readMatrix(&matrix);
36 SkFilterQuality quality = static_cast<SkFilterQuality>(buffer.readInt());
37 return Create(matrix, quality, common.getInput(0));
40 void SkMatrixImageFilter::flatten(SkWriteBuffer& buffer) const {
41 this->INHERITED::flatten(buffer);
42 buffer.writeMatrix(fTransform);
43 buffer.writeInt(fFilterQuality);
46 SkMatrixImageFilter::~SkMatrixImageFilter() {
49 bool SkMatrixImageFilter::onFilterImage(Proxy* proxy,
50 const SkBitmap& source,
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)) {
61 SkIRect srcBounds, dstBounds;
62 src.getBounds(&srcBounds);
63 srcBounds.offset(srcOffset);
64 SkRect srcRect = SkRect::Make(srcBounds);
66 if (!ctx.ctm().invert(&matrix)) {
69 matrix.postConcat(fTransform);
70 matrix.postConcat(ctx.ctm());
71 matrix.mapRect(&dstRect, srcRect);
72 dstRect.roundOut(&dstBounds);
74 SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(dstBounds.width(), dstBounds.height()));
75 if (nullptr == device.get()) {
79 SkCanvas canvas(device.get());
80 canvas.translate(-SkIntToScalar(dstBounds.x()), -SkIntToScalar(dstBounds.y()));
81 canvas.concat(matrix);
84 paint.setXfermodeMode(SkXfermode::kSrc_Mode);
85 paint.setFilterQuality(fFilterQuality);
86 canvas.drawBitmap(src, srcRect.x(), srcRect.y(), &paint);
88 *result = device.get()->accessBitmap(false);
89 offset->fX = dstBounds.fLeft;
90 offset->fY = dstBounds.fTop;
94 void SkMatrixImageFilter::computeFastBounds(const SkRect& src, SkRect* dst) const {
97 getInput(0)->computeFastBounds(src, &bounds);
99 fTransform.mapRect(dst, bounds);
102 void SkMatrixImageFilter::onFilterNodeBounds(const SkIRect& src, const SkMatrix& ctm,
103 SkIRect* dst, MapDirection direction) const {
105 if (!ctm.invert(&matrix)) {
109 if (kForward_MapDirection == direction) {
110 matrix.postConcat(fTransform);
112 SkMatrix transformInverse;
113 if (!fTransform.invert(&transformInverse)) {
117 matrix.postConcat(transformInverse);
119 matrix.postConcat(ctm);
121 matrix.mapRect(&floatBounds, SkRect::Make(src));
122 SkIRect bounds = floatBounds.roundOut();
126 #ifndef SK_IGNORE_TO_STRING
127 void SkMatrixImageFilter::toString(SkString* str) const {
128 str->appendf("SkMatrixImageFilter: (");
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]);
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>");