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