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" 908541d5340a9cadcca60b2f04b1f2dde73be2587robertphillips 10fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org#include "SkCanvas.h" 11fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org#include "SkReadBuffer.h" 1208541d5340a9cadcca60b2f04b1f2dde73be2587robertphillips#include "SkSpecialImage.h" 1308541d5340a9cadcca60b2f04b1f2dde73be2587robertphillips#include "SkSpecialSurface.h" 14fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org#include "SkWriteBuffer.h" 15fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org#include "SkRect.h" 16fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org 17fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.orgSkMatrixImageFilter::SkMatrixImageFilter(const SkMatrix& transform, 1893a1215fe0ab007ce941c721f1fd3e9dcb5d4754reed SkFilterQuality filterQuality, 19ae8c933ca89315c1256bcf23749b5ee5cbc0d53crobertphillips sk_sp<SkImageFilter> input) 20ae8c933ca89315c1256bcf23749b5ee5cbc0d53crobertphillips : INHERITED(&input, 1, nullptr) 2108541d5340a9cadcca60b2f04b1f2dde73be2587robertphillips , fTransform(transform) 2208541d5340a9cadcca60b2f04b1f2dde73be2587robertphillips , fFilterQuality(filterQuality) { 23fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org} 24fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org 25ae8c933ca89315c1256bcf23749b5ee5cbc0d53crobertphillipssk_sp<SkImageFilter> SkMatrixImageFilter::Make(const SkMatrix& transform, 26ae8c933ca89315c1256bcf23749b5ee5cbc0d53crobertphillips SkFilterQuality filterQuality, 27ae8c933ca89315c1256bcf23749b5ee5cbc0d53crobertphillips sk_sp<SkImageFilter> input) { 28ae8c933ca89315c1256bcf23749b5ee5cbc0d53crobertphillips return sk_sp<SkImageFilter>(new SkMatrixImageFilter(transform, 29ae8c933ca89315c1256bcf23749b5ee5cbc0d53crobertphillips filterQuality, 30ae8c933ca89315c1256bcf23749b5ee5cbc0d53crobertphillips std::move(input))); 31fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org} 32fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org 3360c9b58b3214b0154c931656e91e39b230e987d8reedsk_sp<SkFlattenable> SkMatrixImageFilter::CreateProc(SkReadBuffer& buffer) { 349fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed SK_IMAGEFILTER_UNFLATTEN_COMMON(common, 1); 359fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed SkMatrix matrix; 369fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed buffer.readMatrix(&matrix); 3793a1215fe0ab007ce941c721f1fd3e9dcb5d4754reed SkFilterQuality quality = static_cast<SkFilterQuality>(buffer.readInt()); 38ae8c933ca89315c1256bcf23749b5ee5cbc0d53crobertphillips return Make(matrix, quality, common.getInput(0)); 399fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed} 40fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org 41fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.orgvoid SkMatrixImageFilter::flatten(SkWriteBuffer& buffer) const { 42fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org this->INHERITED::flatten(buffer); 43fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org buffer.writeMatrix(fTransform); 4493a1215fe0ab007ce941c721f1fd3e9dcb5d4754reed buffer.writeInt(fFilterQuality); 45fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org} 46fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org 4708541d5340a9cadcca60b2f04b1f2dde73be2587robertphillipssk_sp<SkSpecialImage> SkMatrixImageFilter::onFilterImage(SkSpecialImage* source, 4808541d5340a9cadcca60b2f04b1f2dde73be2587robertphillips const Context& ctx, 4908541d5340a9cadcca60b2f04b1f2dde73be2587robertphillips SkIPoint* offset) const { 50fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org 5108541d5340a9cadcca60b2f04b1f2dde73be2587robertphillips SkIPoint inputOffset = SkIPoint::Make(0, 0); 5208541d5340a9cadcca60b2f04b1f2dde73be2587robertphillips sk_sp<SkSpecialImage> input(this->filterInput(0, source, ctx, &inputOffset)); 5308541d5340a9cadcca60b2f04b1f2dde73be2587robertphillips if (!input) { 5408541d5340a9cadcca60b2f04b1f2dde73be2587robertphillips return nullptr; 55fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org } 56fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org 57fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org SkMatrix matrix; 58fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org if (!ctx.ctm().invert(&matrix)) { 5908541d5340a9cadcca60b2f04b1f2dde73be2587robertphillips return nullptr; 60fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org } 61fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org matrix.postConcat(fTransform); 62fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org matrix.postConcat(ctx.ctm()); 6308541d5340a9cadcca60b2f04b1f2dde73be2587robertphillips 6408541d5340a9cadcca60b2f04b1f2dde73be2587robertphillips const SkIRect srcBounds = SkIRect::MakeXYWH(inputOffset.x(), inputOffset.y(), 6508541d5340a9cadcca60b2f04b1f2dde73be2587robertphillips input->width(), input->height()); 6608541d5340a9cadcca60b2f04b1f2dde73be2587robertphillips const SkRect srcRect = SkRect::Make(srcBounds); 6708541d5340a9cadcca60b2f04b1f2dde73be2587robertphillips 6808541d5340a9cadcca60b2f04b1f2dde73be2587robertphillips SkRect dstRect; 69fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org matrix.mapRect(&dstRect, srcRect); 7008541d5340a9cadcca60b2f04b1f2dde73be2587robertphillips SkIRect dstBounds; 71fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org dstRect.roundOut(&dstBounds); 72fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org 73eed6b0e1d865a1f93143c09961debba0aca592cabrianosman sk_sp<SkSpecialSurface> surf(input->makeSurface(ctx.outputProperties(), dstBounds.size())); 7408541d5340a9cadcca60b2f04b1f2dde73be2587robertphillips if (!surf) { 7508541d5340a9cadcca60b2f04b1f2dde73be2587robertphillips return nullptr; 76fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org } 77fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org 7808541d5340a9cadcca60b2f04b1f2dde73be2587robertphillips SkCanvas* canvas = surf->getCanvas(); 7908541d5340a9cadcca60b2f04b1f2dde73be2587robertphillips SkASSERT(canvas); 8008541d5340a9cadcca60b2f04b1f2dde73be2587robertphillips 8108541d5340a9cadcca60b2f04b1f2dde73be2587robertphillips canvas->clear(0x0); 82daa57bfd4204f5a7d304c580bcf5ad99d0121e1freed 8308541d5340a9cadcca60b2f04b1f2dde73be2587robertphillips canvas->translate(-SkIntToScalar(dstBounds.x()), -SkIntToScalar(dstBounds.y())); 8408541d5340a9cadcca60b2f04b1f2dde73be2587robertphillips canvas->concat(matrix); 8508541d5340a9cadcca60b2f04b1f2dde73be2587robertphillips 8608541d5340a9cadcca60b2f04b1f2dde73be2587robertphillips SkPaint paint; 878c30a8196dd5903d2d23b4d0a5dc888e802bf698reed paint.setAntiAlias(true); 88374772bd61951f01bf84fe17bf53d8867681c9aereed paint.setBlendMode(SkBlendMode::kSrc); 89daa57bfd4204f5a7d304c580bcf5ad99d0121e1freed paint.setFilterQuality(fFilterQuality); 90fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org 9108541d5340a9cadcca60b2f04b1f2dde73be2587robertphillips input->draw(canvas, srcRect.x(), srcRect.y(), &paint); 9208541d5340a9cadcca60b2f04b1f2dde73be2587robertphillips 93fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org offset->fX = dstBounds.fLeft; 94fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org offset->fY = dstBounds.fTop; 9508541d5340a9cadcca60b2f04b1f2dde73be2587robertphillips return surf->makeImageSnapshot(); 96fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org} 97fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org 98e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblancoSkRect SkMatrixImageFilter::computeFastBounds(const SkRect& src) const { 99e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco SkRect bounds = this->getInput(0) ? this->getInput(0)->computeFastBounds(src) : src; 100e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco SkRect dst; 101e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco fTransform.mapRect(&dst, bounds); 102e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco return dst; 103fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org} 104fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org 105e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblancoSkIRect SkMatrixImageFilter::onFilterNodeBounds(const SkIRect& src, const SkMatrix& ctm, 106e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco MapDirection direction) const { 107fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org SkMatrix matrix; 108fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org if (!ctm.invert(&matrix)) { 109e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco return src; 110db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco } 111db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco if (kForward_MapDirection == direction) { 112db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco matrix.postConcat(fTransform); 113db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco } else { 114db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco SkMatrix transformInverse; 115db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco if (!fTransform.invert(&transformInverse)) { 116e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco return src; 117db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco } 118db64af3b178a19ecb47d2b9a373113687d8921fdsenorblanco matrix.postConcat(transformInverse); 119fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org } 120fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org matrix.postConcat(ctm); 121fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org SkRect floatBounds; 122fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org matrix.mapRect(&floatBounds, SkRect::Make(src)); 123e5e79840ef38ab1d3f03abcf1b2df66fb9940018senorblanco return floatBounds.roundOut(); 124fd0ec2c76a27ce26a62da23eb75017839959e7cbsenorblanco@chromium.org} 125f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips 126f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips#ifndef SK_IGNORE_TO_STRING 127f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillipsvoid SkMatrixImageFilter::toString(SkString* str) const { 128f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips str->appendf("SkMatrixImageFilter: ("); 129f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips 130f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips str->appendf("transform: (%f %f %f %f %f %f %f %f %f)", 131f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips fTransform[SkMatrix::kMScaleX], 132f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips fTransform[SkMatrix::kMSkewX], 133f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips fTransform[SkMatrix::kMTransX], 134f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips fTransform[SkMatrix::kMSkewY], 135f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips fTransform[SkMatrix::kMScaleY], 136f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips fTransform[SkMatrix::kMTransY], 137f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips fTransform[SkMatrix::kMPersp0], 138f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips fTransform[SkMatrix::kMPersp1], 139f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips fTransform[SkMatrix::kMPersp2]); 140f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips 141f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips str->append("<dt>FilterLevel:</dt><dd>"); 142f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips static const char* gFilterLevelStrings[] = { "None", "Low", "Medium", "High" }; 14393a1215fe0ab007ce941c721f1fd3e9dcb5d4754reed str->append(gFilterLevelStrings[fFilterQuality]); 144f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips str->append("</dd>"); 145f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips 146f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips str->appendf(")"); 147f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips} 148f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips#endif 149