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, 205e5f948b6b363dbfc8c076d8ff0c6b8e9ea99958senorblanco SkImageFilter* input, 215e5f948b6b363dbfc8c076d8ff0c6b8e9ea99958senorblanco uint32_t uniqueID) 225e5f948b6b363dbfc8c076d8ff0c6b8e9ea99958senorblanco : INHERITED(1, &input, NULL, uniqueID), 23fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org fTransform(transform), 24fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org fFilterLevel(filterLevel) { 25fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org} 26fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org 27fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.orgSkMatrixImageFilter* SkMatrixImageFilter::Create(const SkMatrix& transform, 28fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org SkPaint::FilterLevel filterLevel, 295e5f948b6b363dbfc8c076d8ff0c6b8e9ea99958senorblanco SkImageFilter* input, 305e5f948b6b363dbfc8c076d8ff0c6b8e9ea99958senorblanco uint32_t uniqueID) { 315e5f948b6b363dbfc8c076d8ff0c6b8e9ea99958senorblanco return SkNEW_ARGS(SkMatrixImageFilter, (transform, filterLevel, input, uniqueID)); 32fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org} 33fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org 349fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING 35fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.orgSkMatrixImageFilter::SkMatrixImageFilter(SkReadBuffer& buffer) 36fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org : INHERITED(1, buffer) { 37fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org buffer.readMatrix(&fTransform); 38fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org fFilterLevel = static_cast<SkPaint::FilterLevel>(buffer.readInt()); 39fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org} 409fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed#endif 419fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed 429fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedSkFlattenable* SkMatrixImageFilter::CreateProc(SkReadBuffer& buffer) { 439fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1); 449fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed SkMatrix matrix; 459fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed buffer.readMatrix(&matrix); 469fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed SkPaint::FilterLevel level = static_cast<SkPaint::FilterLevel>(buffer.readInt()); 475e5f948b6b363dbfc8c076d8ff0c6b8e9ea99958senorblanco return Create(matrix, level, common.getInput(0), common.uniqueID()); 489fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed} 49fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org 50fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.orgvoid SkMatrixImageFilter::flatten(SkWriteBuffer& buffer) const { 51fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org this->INHERITED::flatten(buffer); 52fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org buffer.writeMatrix(fTransform); 53fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org buffer.writeInt(fFilterLevel); 54fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org} 55fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org 56fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.orgSkMatrixImageFilter::~SkMatrixImageFilter() { 57fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org} 58fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org 59fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.orgbool SkMatrixImageFilter::onFilterImage(Proxy* proxy, 60fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org const SkBitmap& source, 61fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org const Context& ctx, 62fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org SkBitmap* result, 63fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org SkIPoint* offset) const { 64fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org SkBitmap src = source; 65fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org SkIPoint srcOffset = SkIPoint::Make(0, 0); 66fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org if (getInput(0) && !getInput(0)->filterImage(proxy, source, ctx, &src, &srcOffset)) { 67fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org return false; 68fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org } 69fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org 70fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org SkRect dstRect; 71fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org SkIRect srcBounds, dstBounds; 72fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org src.getBounds(&srcBounds); 73fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org srcBounds.offset(srcOffset); 74fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org SkRect srcRect = SkRect::Make(srcBounds); 75fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org SkMatrix matrix; 76fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org if (!ctx.ctm().invert(&matrix)) { 77fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org return false; 78fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org } 79fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org matrix.postConcat(fTransform); 80fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org matrix.postConcat(ctx.ctm()); 81fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org matrix.mapRect(&dstRect, srcRect); 82fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org dstRect.roundOut(&dstBounds); 83fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org 84fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(dstBounds.width(), dstBounds.height())); 85fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org if (NULL == device.get()) { 86fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org return false; 87fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org } 88fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org 89fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org SkCanvas canvas(device.get()); 90fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org canvas.translate(-SkIntToScalar(dstBounds.x()), -SkIntToScalar(dstBounds.y())); 91fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org canvas.concat(matrix); 92fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org SkPaint paint; 93fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org 94fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org paint.setXfermodeMode(SkXfermode::kSrc_Mode); 95fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org paint.setFilterLevel(fFilterLevel); 96fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org canvas.drawBitmap(src, srcRect.x(), srcRect.y(), &paint); 97fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org 98fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org *result = device.get()->accessBitmap(false); 99fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org offset->fX = dstBounds.fLeft; 100fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org offset->fY = dstBounds.fTop; 101fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org return true; 102fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org} 103fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org 104fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.orgvoid SkMatrixImageFilter::computeFastBounds(const SkRect& src, SkRect* dst) const { 105fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org SkRect bounds = src; 106fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org if (getInput(0)) { 107fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org getInput(0)->computeFastBounds(src, &bounds); 108fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org } 109fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org SkMatrix matrix; 110fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org matrix.setTranslate(-bounds.x(), -bounds.y()); 111fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org matrix.postConcat(fTransform); 112fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org matrix.postTranslate(bounds.x(), bounds.y()); 113fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org matrix.mapRect(dst, bounds); 114fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org} 115fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org 116fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.orgbool SkMatrixImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm, 117fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org SkIRect* dst) const { 118fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org SkMatrix transformInverse; 119fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org if (!fTransform.invert(&transformInverse)) { 120fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org return false; 121fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org } 122fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org SkMatrix matrix; 123fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org if (!ctm.invert(&matrix)) { 124fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org return false; 125fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org } 126fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org matrix.postConcat(transformInverse); 127fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org matrix.postConcat(ctm); 128fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org SkRect floatBounds; 129fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org matrix.mapRect(&floatBounds, SkRect::Make(src)); 130fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org SkIRect bounds; 131fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org floatBounds.roundOut(&bounds); 132fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org if (getInput(0) && !getInput(0)->filterBounds(bounds, ctm, &bounds)) { 133fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org return false; 134fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org } 135fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org 136fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org *dst = bounds; 137fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org return true; 138fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org} 139