SkMatrixImageFilter.cpp revision daa57bfd4204f5a7d304c580bcf5ad99d0121e1f
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 18SkMatrixImageFilter::SkMatrixImageFilter(const SkMatrix& transform, 19 SkFilterQuality filterQuality, 20 SkImageFilter* input) 21 : INHERITED(1, &input), 22 fTransform(transform), 23 fFilterQuality(filterQuality) { 24} 25 26SkMatrixImageFilter* SkMatrixImageFilter::Create(const SkMatrix& transform, 27 SkFilterQuality filterQuality, 28 SkImageFilter* input) { 29 return SkNEW_ARGS(SkMatrixImageFilter, (transform, filterQuality, input)); 30} 31 32SkFlattenable* 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 40void SkMatrixImageFilter::flatten(SkWriteBuffer& buffer) const { 41 this->INHERITED::flatten(buffer); 42 buffer.writeMatrix(fTransform); 43 buffer.writeInt(fFilterQuality); 44} 45 46SkMatrixImageFilter::~SkMatrixImageFilter() { 47} 48 49bool 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 (getInput(0) && !getInput(0)->filterImage(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 (NULL == 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 94void 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 dst->join(bounds); // Work around for skia:3194 101} 102 103bool SkMatrixImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm, 104 SkIRect* dst) const { 105 SkMatrix transformInverse; 106 if (!fTransform.invert(&transformInverse)) { 107 return false; 108 } 109 SkMatrix matrix; 110 if (!ctm.invert(&matrix)) { 111 return false; 112 } 113 matrix.postConcat(transformInverse); 114 matrix.postConcat(ctm); 115 SkRect floatBounds; 116 matrix.mapRect(&floatBounds, SkRect::Make(src)); 117 SkIRect bounds = floatBounds.roundOut(); 118 if (getInput(0) && !getInput(0)->filterBounds(bounds, ctm, &bounds)) { 119 return false; 120 } 121 122 *dst = bounds; 123 return true; 124} 125 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" }; 143 str->append(gFilterLevelStrings[fFilterQuality]); 144 str->append("</dd>"); 145 146 str->appendf(")"); 147} 148#endif 149