1533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org/* 2533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org * Copyright 2013 The Android Open Source Project 3533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org * 4533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org * Use of this source code is governed by a BSD-style license that can be 5533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org * found in the LICENSE file. 6533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org */ 7533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org 8533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org#include "SkPictureImageFilter.h" 9fef28606d2c51be627be3a656581882e31945c03robertphillips 10533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org#include "SkCanvas.h" 118b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkReadBuffer.h" 12fef28606d2c51be627be3a656581882e31945c03robertphillips#include "SkSpecialImage.h" 13fef28606d2c51be627be3a656581882e31945c03robertphillips#include "SkSpecialSurface.h" 148b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkWriteBuffer.h" 15533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org#include "SkValidationUtils.h" 16533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org 17225db4441e0cb887d52c906e8bb39df506304b3erobertphillipssk_sp<SkImageFilter> SkPictureImageFilter::Make(sk_sp<SkPicture> picture) { 18225db4441e0cb887d52c906e8bb39df506304b3erobertphillips return sk_sp<SkImageFilter>(new SkPictureImageFilter(std::move(picture))); 19225db4441e0cb887d52c906e8bb39df506304b3erobertphillips} 20225db4441e0cb887d52c906e8bb39df506304b3erobertphillips 21225db4441e0cb887d52c906e8bb39df506304b3erobertphillipssk_sp<SkImageFilter> SkPictureImageFilter::Make(sk_sp<SkPicture> picture, 22225db4441e0cb887d52c906e8bb39df506304b3erobertphillips const SkRect& cropRect) { 23225db4441e0cb887d52c906e8bb39df506304b3erobertphillips return sk_sp<SkImageFilter>(new SkPictureImageFilter(std::move(picture), 24225db4441e0cb887d52c906e8bb39df506304b3erobertphillips cropRect, 25225db4441e0cb887d52c906e8bb39df506304b3erobertphillips kDeviceSpace_PictureResolution, 26225db4441e0cb887d52c906e8bb39df506304b3erobertphillips kLow_SkFilterQuality)); 27225db4441e0cb887d52c906e8bb39df506304b3erobertphillips} 28225db4441e0cb887d52c906e8bb39df506304b3erobertphillips 29225db4441e0cb887d52c906e8bb39df506304b3erobertphillipssk_sp<SkImageFilter> SkPictureImageFilter::MakeForLocalSpace(sk_sp<SkPicture> picture, 30225db4441e0cb887d52c906e8bb39df506304b3erobertphillips const SkRect& cropRect, 31225db4441e0cb887d52c906e8bb39df506304b3erobertphillips SkFilterQuality filterQuality) { 32225db4441e0cb887d52c906e8bb39df506304b3erobertphillips return sk_sp<SkImageFilter>(new SkPictureImageFilter(std::move(picture), 33225db4441e0cb887d52c906e8bb39df506304b3erobertphillips cropRect, 34225db4441e0cb887d52c906e8bb39df506304b3erobertphillips kLocalSpace_PictureResolution, 35225db4441e0cb887d52c906e8bb39df506304b3erobertphillips filterQuality)); 36225db4441e0cb887d52c906e8bb39df506304b3erobertphillips} 37225db4441e0cb887d52c906e8bb39df506304b3erobertphillips 385ff17b13524eea03e4b672ee3b3a49b649dd09fbrobertphillipsSkPictureImageFilter::SkPictureImageFilter(sk_sp<SkPicture> picture) 39372177ee115d46dfb5bfb881a408e6c37ae83678robertphillips : INHERITED(nullptr, 0, nullptr) 405ff17b13524eea03e4b672ee3b3a49b649dd09fbrobertphillips , fPicture(std::move(picture)) 415ff17b13524eea03e4b672ee3b3a49b649dd09fbrobertphillips , fCropRect(fPicture ? fPicture->cullRect() : SkRect::MakeEmpty()) 429d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary , fPictureResolution(kDeviceSpace_PictureResolution) 4393a1215fe0ab007ce941c721f1fd3e9dcb5d4754reed , fFilterQuality(kLow_SkFilterQuality) { 44533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org} 45533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org 465ff17b13524eea03e4b672ee3b3a49b649dd09fbrobertphillipsSkPictureImageFilter::SkPictureImageFilter(sk_sp<SkPicture> picture, const SkRect& cropRect, 4724e06d5244ae96e440410e1d76e039983b2efac9senorblanco PictureResolution pictureResolution, 4893a1215fe0ab007ce941c721f1fd3e9dcb5d4754reed SkFilterQuality filterQuality) 49372177ee115d46dfb5bfb881a408e6c37ae83678robertphillips : INHERITED(nullptr, 0, nullptr) 505ff17b13524eea03e4b672ee3b3a49b649dd09fbrobertphillips , fPicture(std::move(picture)) 515234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad , fCropRect(cropRect) 52f3c78ccf5694d22d2e4a7061a80399a7e69b59dbjunov , fPictureResolution(pictureResolution) 5393a1215fe0ab007ce941c721f1fd3e9dcb5d4754reed , fFilterQuality(filterQuality) { 54533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org} 55533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org 5660c9b58b3214b0154c931656e91e39b230e987d8reedsk_sp<SkFlattenable> SkPictureImageFilter::CreateProc(SkReadBuffer& buffer) { 57ca2622ba051829fed5f30facd74c5b41cd4b931creed sk_sp<SkPicture> picture; 589fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed SkRect cropRect; 599fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed 60446ee67fda73b11281b8e28a68edec811347c0c5hendrikw if (buffer.isCrossProcess() && SkPicture::PictureIOSecurityPrecautionsEnabled()) { 61c4bd39c903cc5da16f50d711063b01723b59281crobertphillips buffer.validate(!buffer.readBool()); 62446ee67fda73b11281b8e28a68edec811347c0c5hendrikw } else { 639fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed if (buffer.readBool()) { 64ca2622ba051829fed5f30facd74c5b41cd4b931creed picture = SkPicture::MakeFromBuffer(buffer); 659fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed } 669fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed } 679fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed buffer.readRect(&cropRect); 685234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad PictureResolution pictureResolution; 695234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad if (buffer.isVersionLT(SkReadBuffer::kPictureImageFilterResolution_Version)) { 705234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad pictureResolution = kDeviceSpace_PictureResolution; 715234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad } else { 725234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad pictureResolution = (PictureResolution)buffer.readInt(); 739d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary } 74f3c78ccf5694d22d2e4a7061a80399a7e69b59dbjunov 75f3c78ccf5694d22d2e4a7061a80399a7e69b59dbjunov if (kLocalSpace_PictureResolution == pictureResolution) { 76f3c78ccf5694d22d2e4a7061a80399a7e69b59dbjunov //filterLevel is only serialized if pictureResolution is LocalSpace 7793a1215fe0ab007ce941c721f1fd3e9dcb5d4754reed SkFilterQuality filterQuality; 78f3c78ccf5694d22d2e4a7061a80399a7e69b59dbjunov if (buffer.isVersionLT(SkReadBuffer::kPictureImageFilterLevel_Version)) { 7993a1215fe0ab007ce941c721f1fd3e9dcb5d4754reed filterQuality = kLow_SkFilterQuality; 80f3c78ccf5694d22d2e4a7061a80399a7e69b59dbjunov } else { 8193a1215fe0ab007ce941c721f1fd3e9dcb5d4754reed filterQuality = (SkFilterQuality)buffer.readInt(); 82f3c78ccf5694d22d2e4a7061a80399a7e69b59dbjunov } 8360c9b58b3214b0154c931656e91e39b230e987d8reed return MakeForLocalSpace(picture, cropRect, filterQuality); 845234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad } 8560c9b58b3214b0154c931656e91e39b230e987d8reed return Make(picture, cropRect); 869fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed} 87533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org 888b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkPictureImageFilter::flatten(SkWriteBuffer& buffer) const { 89446ee67fda73b11281b8e28a68edec811347c0c5hendrikw if (buffer.isCrossProcess() && SkPicture::PictureIOSecurityPrecautionsEnabled()) { 90c4bd39c903cc5da16f50d711063b01723b59281crobertphillips buffer.writeBool(false); 91446ee67fda73b11281b8e28a68edec811347c0c5hendrikw } else { 9296fcdcc219d2a0d3579719b84b28bede76efba64halcanary bool hasPicture = (fPicture != nullptr); 9397f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org buffer.writeBool(hasPicture); 9497f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org if (hasPicture) { 9597f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org fPicture->flatten(buffer); 9697f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org } 975e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org } 98cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org buffer.writeRect(fCropRect); 995234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad buffer.writeInt(fPictureResolution); 100f3c78ccf5694d22d2e4a7061a80399a7e69b59dbjunov if (kLocalSpace_PictureResolution == fPictureResolution) { 10193a1215fe0ab007ce941c721f1fd3e9dcb5d4754reed buffer.writeInt(fFilterQuality); 102f3c78ccf5694d22d2e4a7061a80399a7e69b59dbjunov } 103533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org} 104533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org 105fef28606d2c51be627be3a656581882e31945c03robertphillipssk_sp<SkSpecialImage> SkPictureImageFilter::onFilterImage(SkSpecialImage* source, 106fef28606d2c51be627be3a656581882e31945c03robertphillips const Context& ctx, 107fef28606d2c51be627be3a656581882e31945c03robertphillips SkIPoint* offset) const { 108533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org if (!fPicture) { 109fef28606d2c51be627be3a656581882e31945c03robertphillips return nullptr; 110533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org } 111533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org 112533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org SkRect floatBounds; 1134cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org ctx.ctm().mapRect(&floatBounds, fCropRect); 114b07a94f1cba3976596ae1a7f23d8c2043ba353f3reed SkIRect bounds = floatBounds.roundOut(); 1153d822c29d4272a6749e59801b202b1ed6d611be8senorblanco if (!bounds.intersect(ctx.clipBounds())) { 116fef28606d2c51be627be3a656581882e31945c03robertphillips return nullptr; 1173d822c29d4272a6749e59801b202b1ed6d611be8senorblanco } 118533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org 119fef28606d2c51be627be3a656581882e31945c03robertphillips SkASSERT(!bounds.isEmpty()); 120533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org 121eed6b0e1d865a1f93143c09961debba0aca592cabrianosman sk_sp<SkSpecialSurface> surf(source->makeSurface(ctx.outputProperties(), bounds.size())); 122fef28606d2c51be627be3a656581882e31945c03robertphillips if (!surf) { 123fef28606d2c51be627be3a656581882e31945c03robertphillips return nullptr; 124533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org } 125533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org 126fef28606d2c51be627be3a656581882e31945c03robertphillips SkCanvas* canvas = surf->getCanvas(); 127fef28606d2c51be627be3a656581882e31945c03robertphillips SkASSERT(canvas); 128fef28606d2c51be627be3a656581882e31945c03robertphillips 129fef28606d2c51be627be3a656581882e31945c03robertphillips canvas->clear(0x0); 130fef28606d2c51be627be3a656581882e31945c03robertphillips 1310b7e5a13bd371126b5d5794f3f9d2930c35ce05frobertphillips if (kDeviceSpace_PictureResolution == fPictureResolution || 132f3c78ccf5694d22d2e4a7061a80399a7e69b59dbjunov 0 == (ctx.ctm().getType() & ~SkMatrix::kTranslate_Mask)) { 1330b7e5a13bd371126b5d5794f3f9d2930c35ce05frobertphillips this->drawPictureAtDeviceResolution(canvas, bounds, ctx); 1345234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad } else { 135fef28606d2c51be627be3a656581882e31945c03robertphillips this->drawPictureAtLocalResolution(source, canvas, bounds, ctx); 1365234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad } 1375234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad 1385234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad offset->fX = bounds.fLeft; 1395234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad offset->fY = bounds.fTop; 140fef28606d2c51be627be3a656581882e31945c03robertphillips return surf->makeImageSnapshot(); 1415234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad} 1425234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad 143fef28606d2c51be627be3a656581882e31945c03robertphillipsvoid SkPictureImageFilter::drawPictureAtDeviceResolution(SkCanvas* canvas, 1445234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad const SkIRect& deviceBounds, 1455234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad const Context& ctx) const { 146fef28606d2c51be627be3a656581882e31945c03robertphillips canvas->translate(-SkIntToScalar(deviceBounds.fLeft), -SkIntToScalar(deviceBounds.fTop)); 147fef28606d2c51be627be3a656581882e31945c03robertphillips canvas->concat(ctx.ctm()); 148fef28606d2c51be627be3a656581882e31945c03robertphillips canvas->drawPicture(fPicture); 1495234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad} 150533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org 151fef28606d2c51be627be3a656581882e31945c03robertphillipsvoid SkPictureImageFilter::drawPictureAtLocalResolution(SkSpecialImage* source, 152fef28606d2c51be627be3a656581882e31945c03robertphillips SkCanvas* canvas, 1535234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad const SkIRect& deviceBounds, 1545234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad const Context& ctx) const { 1555234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad SkMatrix inverseCtm; 156efbffedd68636e94d4379e84a2585bce80f6fb8frobertphillips if (!ctx.ctm().invert(&inverseCtm)) { 1575234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad return; 158efbffedd68636e94d4379e84a2585bce80f6fb8frobertphillips } 159efbffedd68636e94d4379e84a2585bce80f6fb8frobertphillips 1605234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad SkRect localBounds = SkRect::Make(ctx.clipBounds()); 1615234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad inverseCtm.mapRect(&localBounds); 162efbffedd68636e94d4379e84a2585bce80f6fb8frobertphillips if (!localBounds.intersect(fCropRect)) { 1635234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad return; 164efbffedd68636e94d4379e84a2585bce80f6fb8frobertphillips } 1655234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad SkIRect localIBounds = localBounds.roundOut(); 1665234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad 167fef28606d2c51be627be3a656581882e31945c03robertphillips sk_sp<SkSpecialImage> localImg; 168fef28606d2c51be627be3a656581882e31945c03robertphillips { 169eed6b0e1d865a1f93143c09961debba0aca592cabrianosman sk_sp<SkSpecialSurface> localSurface(source->makeSurface(ctx.outputProperties(), 170eed6b0e1d865a1f93143c09961debba0aca592cabrianosman localIBounds.size())); 171fef28606d2c51be627be3a656581882e31945c03robertphillips if (!localSurface) { 172fef28606d2c51be627be3a656581882e31945c03robertphillips return; 173fef28606d2c51be627be3a656581882e31945c03robertphillips } 174fef28606d2c51be627be3a656581882e31945c03robertphillips 175fef28606d2c51be627be3a656581882e31945c03robertphillips SkCanvas* localCanvas = localSurface->getCanvas(); 176fef28606d2c51be627be3a656581882e31945c03robertphillips SkASSERT(localCanvas); 177a31312cddd51c896b34c5c3382bcf6c50632d70bericrk 178a31312cddd51c896b34c5c3382bcf6c50632d70bericrk localCanvas->clear(0x0); 179fef28606d2c51be627be3a656581882e31945c03robertphillips 180fef28606d2c51be627be3a656581882e31945c03robertphillips localCanvas->translate(-SkIntToScalar(localIBounds.fLeft), 181fef28606d2c51be627be3a656581882e31945c03robertphillips -SkIntToScalar(localIBounds.fTop)); 182fef28606d2c51be627be3a656581882e31945c03robertphillips localCanvas->drawPicture(fPicture); 1835234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad 184fef28606d2c51be627be3a656581882e31945c03robertphillips localImg = localSurface->makeImageSnapshot(); 185fef28606d2c51be627be3a656581882e31945c03robertphillips SkASSERT(localImg); 186fef28606d2c51be627be3a656581882e31945c03robertphillips } 187fef28606d2c51be627be3a656581882e31945c03robertphillips 188fef28606d2c51be627be3a656581882e31945c03robertphillips { 189fef28606d2c51be627be3a656581882e31945c03robertphillips canvas->translate(-SkIntToScalar(deviceBounds.fLeft), -SkIntToScalar(deviceBounds.fTop)); 190fef28606d2c51be627be3a656581882e31945c03robertphillips canvas->concat(ctx.ctm()); 191fef28606d2c51be627be3a656581882e31945c03robertphillips SkPaint paint; 192fef28606d2c51be627be3a656581882e31945c03robertphillips paint.setFilterQuality(fFilterQuality); 1935234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad 194fef28606d2c51be627be3a656581882e31945c03robertphillips localImg->draw(canvas, 195fef28606d2c51be627be3a656581882e31945c03robertphillips SkIntToScalar(localIBounds.fLeft), 196fef28606d2c51be627be3a656581882e31945c03robertphillips SkIntToScalar(localIBounds.fTop), 197fef28606d2c51be627be3a656581882e31945c03robertphillips &paint); 198fef28606d2c51be627be3a656581882e31945c03robertphillips } 199533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org} 200f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips 201f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips#ifndef SK_IGNORE_TO_STRING 202f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillipsvoid SkPictureImageFilter::toString(SkString* str) const { 203f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips str->appendf("SkPictureImageFilter: ("); 2049d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary str->appendf("crop: (%f,%f,%f,%f) ", 205f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips fCropRect.fLeft, fCropRect.fTop, fCropRect.fRight, fCropRect.fBottom); 206f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips if (fPicture) { 207f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips str->appendf("picture: (%f,%f,%f,%f)", 208f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips fPicture->cullRect().fLeft, fPicture->cullRect().fTop, 209f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips fPicture->cullRect().fRight, fPicture->cullRect().fBottom); 210f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips } 211f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips str->append(")"); 212f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips} 213f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips#endif 214