1fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org/* 2fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org * Copyright 2014 The Android Open Source Project 3fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org * 4fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org * Use of this source code is governed by a BSD-style license that can be 5fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org * found in the LICENSE file. 6fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org */ 7fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org 8fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org#include "SkMatrixImageFilter.h" 9fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org#include "SkBitmap.h" 10fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org#include "SkCanvas.h" 11fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org#include "SkDevice.h" 12fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org#include "SkColorPriv.h" 13fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org#include "SkReadBuffer.h" 14fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org#include "SkWriteBuffer.h" 15fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org#include "SkMatrix.h" 16fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org#include "SkRect.h" 17fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org 18fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.orgSkMatrixImageFilter::SkMatrixImageFilter(const SkMatrix& transform, 19fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org SkPaint::FilterLevel filterLevel, 20fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org SkImageFilter* input) 21fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org : INHERITED(input), 22fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org fTransform(transform), 23fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org fFilterLevel(filterLevel) { 24fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org} 25fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org 26fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.orgSkMatrixImageFilter* SkMatrixImageFilter::Create(const SkMatrix& transform, 27fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org SkPaint::FilterLevel filterLevel, 28fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org SkImageFilter* input) { 29fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org return SkNEW_ARGS(SkMatrixImageFilter, (transform, filterLevel, input)); 30fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org} 31fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org 32fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.orgSkMatrixImageFilter::SkMatrixImageFilter(SkReadBuffer& buffer) 33fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org : INHERITED(1, buffer) { 34fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org buffer.readMatrix(&fTransform); 35fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org fFilterLevel = static_cast<SkPaint::FilterLevel>(buffer.readInt()); 36fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org} 37fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org 38fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.orgvoid SkMatrixImageFilter::flatten(SkWriteBuffer& buffer) const { 39fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org this->INHERITED::flatten(buffer); 40fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org buffer.writeMatrix(fTransform); 41fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org buffer.writeInt(fFilterLevel); 42fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org} 43fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org 44fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.orgSkMatrixImageFilter::~SkMatrixImageFilter() { 45fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org} 46fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org 47fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.orgbool SkMatrixImageFilter::onFilterImage(Proxy* proxy, 48fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org const SkBitmap& source, 49fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org const Context& ctx, 50fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org SkBitmap* result, 51fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org SkIPoint* offset) const { 52fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org SkBitmap src = source; 53fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org SkIPoint srcOffset = SkIPoint::Make(0, 0); 54fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org if (getInput(0) && !getInput(0)->filterImage(proxy, source, ctx, &src, &srcOffset)) { 55fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org return false; 56fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org } 57fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org 58fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org SkRect dstRect; 59fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org SkIRect srcBounds, dstBounds; 60fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org src.getBounds(&srcBounds); 61fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org srcBounds.offset(srcOffset); 62fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org SkRect srcRect = SkRect::Make(srcBounds); 63fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org SkMatrix matrix; 64fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org if (!ctx.ctm().invert(&matrix)) { 65fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org return false; 66fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org } 67fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org matrix.postConcat(fTransform); 68fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org matrix.postConcat(ctx.ctm()); 69fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org matrix.mapRect(&dstRect, srcRect); 70fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org dstRect.roundOut(&dstBounds); 71fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org 72fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(dstBounds.width(), dstBounds.height())); 73fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org if (NULL == device.get()) { 74fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org return false; 75fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org } 76fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org 77fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org SkCanvas canvas(device.get()); 78fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org canvas.translate(-SkIntToScalar(dstBounds.x()), -SkIntToScalar(dstBounds.y())); 79fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org canvas.concat(matrix); 80fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org SkPaint paint; 81fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org 82fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org paint.setXfermodeMode(SkXfermode::kSrc_Mode); 83fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org paint.setFilterLevel(fFilterLevel); 84fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org canvas.drawBitmap(src, srcRect.x(), srcRect.y(), &paint); 85fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org 86fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org *result = device.get()->accessBitmap(false); 87fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org offset->fX = dstBounds.fLeft; 88fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org offset->fY = dstBounds.fTop; 89fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org return true; 90fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org} 91fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org 92fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.orgvoid SkMatrixImageFilter::computeFastBounds(const SkRect& src, SkRect* dst) const { 93fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org SkRect bounds = src; 94fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org if (getInput(0)) { 95fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org getInput(0)->computeFastBounds(src, &bounds); 96fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org } 97fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org SkMatrix matrix; 98fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org matrix.setTranslate(-bounds.x(), -bounds.y()); 99fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org matrix.postConcat(fTransform); 100fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org matrix.postTranslate(bounds.x(), bounds.y()); 101fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org matrix.mapRect(dst, bounds); 102fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org} 103fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org 104fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.orgbool SkMatrixImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm, 105fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org SkIRect* dst) const { 106fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org SkMatrix transformInverse; 107fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org if (!fTransform.invert(&transformInverse)) { 108fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org return false; 109fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org } 110fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org SkMatrix matrix; 111fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org if (!ctm.invert(&matrix)) { 112fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org return false; 113fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org } 114fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org matrix.postConcat(transformInverse); 115fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org matrix.postConcat(ctm); 116fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org SkRect floatBounds; 117fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org matrix.mapRect(&floatBounds, SkRect::Make(src)); 118fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org SkIRect bounds; 119fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org floatBounds.roundOut(&bounds); 120fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org if (getInput(0) && !getInput(0)->filterBounds(bounds, ctm, &bounds)) { 121fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org return false; 122fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org } 123fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org 124fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org *dst = bounds; 125fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org return true; 126fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org} 127