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" 11e22a6a29e2e5664ee907f1abccf615a900cbcfadMatt Sarett#include "SkColorSpaceXformCanvas.h" 12e22a6a29e2e5664ee907f1abccf615a900cbcfadMatt Sarett#include "SkColorSpaceXformer.h" 1348723156c597ec4d7be8e0648548ff27ef6c4e02Mike Reed#include "SkImageSource.h" 148b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkReadBuffer.h" 15fef28606d2c51be627be3a656581882e31945c03robertphillips#include "SkSpecialImage.h" 16fef28606d2c51be627be3a656581882e31945c03robertphillips#include "SkSpecialSurface.h" 178b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkWriteBuffer.h" 18533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org#include "SkValidationUtils.h" 19533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org 20225db4441e0cb887d52c906e8bb39df506304b3erobertphillipssk_sp<SkImageFilter> SkPictureImageFilter::Make(sk_sp<SkPicture> picture) { 21225db4441e0cb887d52c906e8bb39df506304b3erobertphillips return sk_sp<SkImageFilter>(new SkPictureImageFilter(std::move(picture))); 22225db4441e0cb887d52c906e8bb39df506304b3erobertphillips} 23225db4441e0cb887d52c906e8bb39df506304b3erobertphillips 24225db4441e0cb887d52c906e8bb39df506304b3erobertphillipssk_sp<SkImageFilter> SkPictureImageFilter::Make(sk_sp<SkPicture> picture, 25225db4441e0cb887d52c906e8bb39df506304b3erobertphillips const SkRect& cropRect) { 2648723156c597ec4d7be8e0648548ff27ef6c4e02Mike Reed return sk_sp<SkImageFilter>(new SkPictureImageFilter(std::move(picture), cropRect, nullptr)); 27225db4441e0cb887d52c906e8bb39df506304b3erobertphillips} 28225db4441e0cb887d52c906e8bb39df506304b3erobertphillips 295ff17b13524eea03e4b672ee3b3a49b649dd09fbrobertphillipsSkPictureImageFilter::SkPictureImageFilter(sk_sp<SkPicture> picture) 30372177ee115d46dfb5bfb881a408e6c37ae83678robertphillips : INHERITED(nullptr, 0, nullptr) 315ff17b13524eea03e4b672ee3b3a49b649dd09fbrobertphillips , fPicture(std::move(picture)) 3248723156c597ec4d7be8e0648548ff27ef6c4e02Mike Reed , fCropRect(fPicture ? fPicture->cullRect() : SkRect::MakeEmpty()) { 33533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org} 34533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org 355ff17b13524eea03e4b672ee3b3a49b649dd09fbrobertphillipsSkPictureImageFilter::SkPictureImageFilter(sk_sp<SkPicture> picture, const SkRect& cropRect, 36e22a6a29e2e5664ee907f1abccf615a900cbcfadMatt Sarett sk_sp<SkColorSpace> colorSpace) 37372177ee115d46dfb5bfb881a408e6c37ae83678robertphillips : INHERITED(nullptr, 0, nullptr) 385ff17b13524eea03e4b672ee3b3a49b649dd09fbrobertphillips , fPicture(std::move(picture)) 395234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad , fCropRect(cropRect) 40e22a6a29e2e5664ee907f1abccf615a900cbcfadMatt Sarett , fColorSpace(std::move(colorSpace)) { 41533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org} 42533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org 4348723156c597ec4d7be8e0648548ff27ef6c4e02Mike Reedenum PictureResolution { 4448723156c597ec4d7be8e0648548ff27ef6c4e02Mike Reed kDeviceSpace_PictureResolution, 4548723156c597ec4d7be8e0648548ff27ef6c4e02Mike Reed kLocalSpace_PictureResolution 4648723156c597ec4d7be8e0648548ff27ef6c4e02Mike Reed}; 4748723156c597ec4d7be8e0648548ff27ef6c4e02Mike Reedstatic sk_sp<SkImageFilter> make_localspace_filter(sk_sp<SkPicture> pic, const SkRect& cropRect, 4848723156c597ec4d7be8e0648548ff27ef6c4e02Mike Reed SkFilterQuality fq) { 4948723156c597ec4d7be8e0648548ff27ef6c4e02Mike Reed SkISize dim = { SkScalarRoundToInt(cropRect.width()), SkScalarRoundToInt(cropRect.height()) }; 5048723156c597ec4d7be8e0648548ff27ef6c4e02Mike Reed auto img = SkImage::MakeFromPicture(std::move(pic), dim, nullptr, nullptr, 5148723156c597ec4d7be8e0648548ff27ef6c4e02Mike Reed SkImage::BitDepth::kU8, SkColorSpace::MakeSRGB()); 5248723156c597ec4d7be8e0648548ff27ef6c4e02Mike Reed return SkImageSource::Make(img, cropRect, cropRect, fq); 5348723156c597ec4d7be8e0648548ff27ef6c4e02Mike Reed} 5448723156c597ec4d7be8e0648548ff27ef6c4e02Mike Reed 5560c9b58b3214b0154c931656e91e39b230e987d8reedsk_sp<SkFlattenable> SkPictureImageFilter::CreateProc(SkReadBuffer& buffer) { 56ca2622ba051829fed5f30facd74c5b41cd4b931creed sk_sp<SkPicture> picture; 579fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed SkRect cropRect; 589fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed 595a0f3455320f5591c196844ff8a89b71a7d9aa56Mike Reed if (buffer.readBool()) { 605a0f3455320f5591c196844ff8a89b71a7d9aa56Mike Reed picture = SkPicture::MakeFromBuffer(buffer); 619fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed } 629fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed buffer.readRect(&cropRect); 63f3c78ccf5694d22d2e4a7061a80399a7e69b59dbjunov 6477e487dfc005be66346ebf3e33d3ec394de4cc36Mike Reed if (buffer.isVersionLT(SkReadBuffer::kRemovePictureImageFilterLocalSpace)) { 6548723156c597ec4d7be8e0648548ff27ef6c4e02Mike Reed PictureResolution pictureResolution = buffer.checkRange<PictureResolution>( 6648723156c597ec4d7be8e0648548ff27ef6c4e02Mike Reed kDeviceSpace_PictureResolution, kLocalSpace_PictureResolution); 6777e487dfc005be66346ebf3e33d3ec394de4cc36Mike Reed if (kLocalSpace_PictureResolution == pictureResolution) { 6848723156c597ec4d7be8e0648548ff27ef6c4e02Mike Reed return make_localspace_filter(std::move(picture), cropRect, 6948723156c597ec4d7be8e0648548ff27ef6c4e02Mike Reed buffer.checkFilterQuality()); 7077e487dfc005be66346ebf3e33d3ec394de4cc36Mike Reed } 715234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad } 7248723156c597ec4d7be8e0648548ff27ef6c4e02Mike Reed return sk_sp<SkImageFilter>(new SkPictureImageFilter(picture, cropRect, nullptr)); 739fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed} 74533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org 758b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkPictureImageFilter::flatten(SkWriteBuffer& buffer) const { 765a0f3455320f5591c196844ff8a89b71a7d9aa56Mike Reed bool hasPicture = (fPicture != nullptr); 775a0f3455320f5591c196844ff8a89b71a7d9aa56Mike Reed buffer.writeBool(hasPicture); 785a0f3455320f5591c196844ff8a89b71a7d9aa56Mike Reed if (hasPicture) { 795a0f3455320f5591c196844ff8a89b71a7d9aa56Mike Reed fPicture->flatten(buffer); 805e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org } 81cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org buffer.writeRect(fCropRect); 82533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org} 83533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org 84fef28606d2c51be627be3a656581882e31945c03robertphillipssk_sp<SkSpecialImage> SkPictureImageFilter::onFilterImage(SkSpecialImage* source, 85fef28606d2c51be627be3a656581882e31945c03robertphillips const Context& ctx, 86fef28606d2c51be627be3a656581882e31945c03robertphillips SkIPoint* offset) const { 87533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org if (!fPicture) { 88fef28606d2c51be627be3a656581882e31945c03robertphillips return nullptr; 89533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org } 90533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org 91533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org SkRect floatBounds; 924cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org ctx.ctm().mapRect(&floatBounds, fCropRect); 93b07a94f1cba3976596ae1a7f23d8c2043ba353f3reed SkIRect bounds = floatBounds.roundOut(); 943d822c29d4272a6749e59801b202b1ed6d611be8senorblanco if (!bounds.intersect(ctx.clipBounds())) { 95fef28606d2c51be627be3a656581882e31945c03robertphillips return nullptr; 963d822c29d4272a6749e59801b202b1ed6d611be8senorblanco } 97533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org 98fef28606d2c51be627be3a656581882e31945c03robertphillips SkASSERT(!bounds.isEmpty()); 99533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org 100eed6b0e1d865a1f93143c09961debba0aca592cabrianosman sk_sp<SkSpecialSurface> surf(source->makeSurface(ctx.outputProperties(), bounds.size())); 101fef28606d2c51be627be3a656581882e31945c03robertphillips if (!surf) { 102fef28606d2c51be627be3a656581882e31945c03robertphillips return nullptr; 103533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org } 104533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org 105fef28606d2c51be627be3a656581882e31945c03robertphillips SkCanvas* canvas = surf->getCanvas(); 106fef28606d2c51be627be3a656581882e31945c03robertphillips SkASSERT(canvas); 107fef28606d2c51be627be3a656581882e31945c03robertphillips canvas->clear(0x0); 108fef28606d2c51be627be3a656581882e31945c03robertphillips 10948723156c597ec4d7be8e0648548ff27ef6c4e02Mike Reed std::unique_ptr<SkCanvas> xformCanvas; 11048723156c597ec4d7be8e0648548ff27ef6c4e02Mike Reed if (fColorSpace) { 11148723156c597ec4d7be8e0648548ff27ef6c4e02Mike Reed // Only non-null in the case where onMakeColorSpace() was called. This instructs 11248723156c597ec4d7be8e0648548ff27ef6c4e02Mike Reed // us to do the color space xform on playback. 11348723156c597ec4d7be8e0648548ff27ef6c4e02Mike Reed xformCanvas = SkCreateColorSpaceXformCanvas(canvas, fColorSpace); 11448723156c597ec4d7be8e0648548ff27ef6c4e02Mike Reed canvas = xformCanvas.get(); 1155234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad } 11648723156c597ec4d7be8e0648548ff27ef6c4e02Mike Reed canvas->translate(-SkIntToScalar(bounds.fLeft), -SkIntToScalar(bounds.fTop)); 11748723156c597ec4d7be8e0648548ff27ef6c4e02Mike Reed canvas->concat(ctx.ctm()); 11848723156c597ec4d7be8e0648548ff27ef6c4e02Mike Reed canvas->drawPicture(fPicture); 1195234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad 1205234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad offset->fX = bounds.fLeft; 1215234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad offset->fY = bounds.fTop; 122fef28606d2c51be627be3a656581882e31945c03robertphillips return surf->makeImageSnapshot(); 1235234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad} 1245234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad 125e22a6a29e2e5664ee907f1abccf615a900cbcfadMatt Sarettsk_sp<SkImageFilter> SkPictureImageFilter::onMakeColorSpace(SkColorSpaceXformer* xformer) const { 126a252c661d686393207b133cccbc6211620bf7772Florin Malita sk_sp<SkColorSpace> dstCS = xformer->dst(); 127604f0d54a8b22e6d1ec7581fcb68191aa0ff03fcFlorin Malita if (SkColorSpace::Equals(dstCS.get(), fColorSpace.get())) { 128a252c661d686393207b133cccbc6211620bf7772Florin Malita return this->refMe(); 129a252c661d686393207b133cccbc6211620bf7772Florin Malita } 130a252c661d686393207b133cccbc6211620bf7772Florin Malita 13148723156c597ec4d7be8e0648548ff27ef6c4e02Mike Reed return sk_sp<SkImageFilter>(new SkPictureImageFilter(fPicture, fCropRect, std::move(dstCS))); 132533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org} 133f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips 134f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips#ifndef SK_IGNORE_TO_STRING 135f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillipsvoid SkPictureImageFilter::toString(SkString* str) const { 136f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips str->appendf("SkPictureImageFilter: ("); 1379d524f22bfde5dc3dc8f48e1be39bdebd3bb0304halcanary str->appendf("crop: (%f,%f,%f,%f) ", 138f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips fCropRect.fLeft, fCropRect.fTop, fCropRect.fRight, fCropRect.fBottom); 139f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips if (fPicture) { 140f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips str->appendf("picture: (%f,%f,%f,%f)", 141f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips fPicture->cullRect().fLeft, fPicture->cullRect().fTop, 142f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips fPicture->cullRect().fRight, fPicture->cullRect().fBottom); 143f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips } 144f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips str->append(")"); 145f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips} 146f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips#endif 147