blob: 709a0901b6b895919ff124856756058d527ab2d5 [file] [log] [blame]
senorblanco@chromium.org53333002013-12-12 23:28:52 +00001/*
2 * Copyright 2013 The Android Open Source Project
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#include "SkPictureImageFilter.h"
robertphillipsfef28602016-04-11 11:08:52 -07009
senorblanco@chromium.org53333002013-12-12 23:28:52 +000010#include "SkCanvas.h"
Matt Sarette22a6a22017-04-12 16:26:21 -040011#include "SkColorSpaceXformCanvas.h"
12#include "SkColorSpaceXformer.h"
Mike Reed48723152017-11-10 14:35:54 -050013#include "SkImageSource.h"
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000014#include "SkReadBuffer.h"
robertphillipsfef28602016-04-11 11:08:52 -070015#include "SkSpecialImage.h"
16#include "SkSpecialSurface.h"
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000017#include "SkWriteBuffer.h"
senorblanco@chromium.org53333002013-12-12 23:28:52 +000018#include "SkValidationUtils.h"
19
robertphillips225db442016-04-17 14:27:05 -070020sk_sp<SkImageFilter> SkPictureImageFilter::Make(sk_sp<SkPicture> picture) {
21 return sk_sp<SkImageFilter>(new SkPictureImageFilter(std::move(picture)));
22}
23
24sk_sp<SkImageFilter> SkPictureImageFilter::Make(sk_sp<SkPicture> picture,
25 const SkRect& cropRect) {
Mike Reed48723152017-11-10 14:35:54 -050026 return sk_sp<SkImageFilter>(new SkPictureImageFilter(std::move(picture), cropRect, nullptr));
robertphillips225db442016-04-17 14:27:05 -070027}
28
robertphillips5ff17b12016-03-28 13:13:42 -070029SkPictureImageFilter::SkPictureImageFilter(sk_sp<SkPicture> picture)
robertphillips372177e2016-03-30 07:32:28 -070030 : INHERITED(nullptr, 0, nullptr)
robertphillips5ff17b12016-03-28 13:13:42 -070031 , fPicture(std::move(picture))
Mike Reed48723152017-11-10 14:35:54 -050032 , fCropRect(fPicture ? fPicture->cullRect() : SkRect::MakeEmpty()) {
senorblanco@chromium.org53333002013-12-12 23:28:52 +000033}
34
robertphillips5ff17b12016-03-28 13:13:42 -070035SkPictureImageFilter::SkPictureImageFilter(sk_sp<SkPicture> picture, const SkRect& cropRect,
Matt Sarette22a6a22017-04-12 16:26:21 -040036 sk_sp<SkColorSpace> colorSpace)
robertphillips372177e2016-03-30 07:32:28 -070037 : INHERITED(nullptr, 0, nullptr)
robertphillips5ff17b12016-03-28 13:13:42 -070038 , fPicture(std::move(picture))
Justin Novosad52340752014-12-02 14:50:56 -050039 , fCropRect(cropRect)
Matt Sarette22a6a22017-04-12 16:26:21 -040040 , fColorSpace(std::move(colorSpace)) {
senorblanco@chromium.org53333002013-12-12 23:28:52 +000041}
42
Mike Reed48723152017-11-10 14:35:54 -050043enum PictureResolution {
44 kDeviceSpace_PictureResolution,
45 kLocalSpace_PictureResolution
46};
47static sk_sp<SkImageFilter> make_localspace_filter(sk_sp<SkPicture> pic, const SkRect& cropRect,
48 SkFilterQuality fq) {
49 SkISize dim = { SkScalarRoundToInt(cropRect.width()), SkScalarRoundToInt(cropRect.height()) };
50 auto img = SkImage::MakeFromPicture(std::move(pic), dim, nullptr, nullptr,
51 SkImage::BitDepth::kU8, SkColorSpace::MakeSRGB());
52 return SkImageSource::Make(img, cropRect, cropRect, fq);
53}
54
reed60c9b582016-04-03 09:11:13 -070055sk_sp<SkFlattenable> SkPictureImageFilter::CreateProc(SkReadBuffer& buffer) {
reedca2622b2016-03-18 07:25:55 -070056 sk_sp<SkPicture> picture;
reed9fa60da2014-08-21 07:59:51 -070057 SkRect cropRect;
58
hendrikw446ee672015-06-16 09:28:37 -070059 if (buffer.isCrossProcess() && SkPicture::PictureIOSecurityPrecautionsEnabled()) {
robertphillipsc4bd39c2015-01-06 09:17:02 -080060 buffer.validate(!buffer.readBool());
hendrikw446ee672015-06-16 09:28:37 -070061 } else {
reed9fa60da2014-08-21 07:59:51 -070062 if (buffer.readBool()) {
reedca2622b2016-03-18 07:25:55 -070063 picture = SkPicture::MakeFromBuffer(buffer);
reed9fa60da2014-08-21 07:59:51 -070064 }
reed9fa60da2014-08-21 07:59:51 -070065 }
66 buffer.readRect(&cropRect);
67
Mike Reed77e487d2017-11-09 21:50:20 +000068 if (buffer.isVersionLT(SkReadBuffer::kRemovePictureImageFilterLocalSpace)) {
Mike Reed48723152017-11-10 14:35:54 -050069 PictureResolution pictureResolution = buffer.checkRange<PictureResolution>(
70 kDeviceSpace_PictureResolution, kLocalSpace_PictureResolution);
Mike Reed77e487d2017-11-09 21:50:20 +000071 if (kLocalSpace_PictureResolution == pictureResolution) {
Mike Reed48723152017-11-10 14:35:54 -050072 return make_localspace_filter(std::move(picture), cropRect,
73 buffer.checkFilterQuality());
Mike Reed77e487d2017-11-09 21:50:20 +000074 }
Justin Novosad52340752014-12-02 14:50:56 -050075 }
Mike Reed48723152017-11-10 14:35:54 -050076 return sk_sp<SkImageFilter>(new SkPictureImageFilter(picture, cropRect, nullptr));
reed9fa60da2014-08-21 07:59:51 -070077}
senorblanco@chromium.org53333002013-12-12 23:28:52 +000078
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000079void SkPictureImageFilter::flatten(SkWriteBuffer& buffer) const {
hendrikw446ee672015-06-16 09:28:37 -070080 if (buffer.isCrossProcess() && SkPicture::PictureIOSecurityPrecautionsEnabled()) {
robertphillipsc4bd39c2015-01-06 09:17:02 -080081 buffer.writeBool(false);
hendrikw446ee672015-06-16 09:28:37 -070082 } else {
halcanary96fcdcc2015-08-27 07:41:13 -070083 bool hasPicture = (fPicture != nullptr);
senorblanco@chromium.org97f5fc62014-05-30 20:50:56 +000084 buffer.writeBool(hasPicture);
85 if (hasPicture) {
86 fPicture->flatten(buffer);
87 }
commit-bot@chromium.org5e0995e2014-02-07 12:20:04 +000088 }
commit-bot@chromium.orgcac5fd52014-03-10 10:51:58 +000089 buffer.writeRect(fCropRect);
senorblanco@chromium.org53333002013-12-12 23:28:52 +000090}
91
robertphillipsfef28602016-04-11 11:08:52 -070092sk_sp<SkSpecialImage> SkPictureImageFilter::onFilterImage(SkSpecialImage* source,
93 const Context& ctx,
94 SkIPoint* offset) const {
senorblanco@chromium.org53333002013-12-12 23:28:52 +000095 if (!fPicture) {
robertphillipsfef28602016-04-11 11:08:52 -070096 return nullptr;
senorblanco@chromium.org53333002013-12-12 23:28:52 +000097 }
98
99 SkRect floatBounds;
senorblanco@chromium.org4cb543d2014-03-14 15:44:01 +0000100 ctx.ctm().mapRect(&floatBounds, fCropRect);
reedb07a94f2014-11-19 05:03:18 -0800101 SkIRect bounds = floatBounds.roundOut();
senorblanco3d822c22014-07-30 14:49:31 -0700102 if (!bounds.intersect(ctx.clipBounds())) {
robertphillipsfef28602016-04-11 11:08:52 -0700103 return nullptr;
senorblanco3d822c22014-07-30 14:49:31 -0700104 }
senorblanco@chromium.org53333002013-12-12 23:28:52 +0000105
robertphillipsfef28602016-04-11 11:08:52 -0700106 SkASSERT(!bounds.isEmpty());
107
brianosmaneed6b0e2016-09-23 13:04:05 -0700108 sk_sp<SkSpecialSurface> surf(source->makeSurface(ctx.outputProperties(), bounds.size()));
robertphillipsfef28602016-04-11 11:08:52 -0700109 if (!surf) {
110 return nullptr;
senorblanco@chromium.org53333002013-12-12 23:28:52 +0000111 }
112
robertphillipsfef28602016-04-11 11:08:52 -0700113 SkCanvas* canvas = surf->getCanvas();
114 SkASSERT(canvas);
robertphillipsfef28602016-04-11 11:08:52 -0700115 canvas->clear(0x0);
116
Mike Reed48723152017-11-10 14:35:54 -0500117 std::unique_ptr<SkCanvas> xformCanvas;
118 if (fColorSpace) {
119 // Only non-null in the case where onMakeColorSpace() was called. This instructs
120 // us to do the color space xform on playback.
121 xformCanvas = SkCreateColorSpaceXformCanvas(canvas, fColorSpace);
122 canvas = xformCanvas.get();
Justin Novosad52340752014-12-02 14:50:56 -0500123 }
Mike Reed48723152017-11-10 14:35:54 -0500124 canvas->translate(-SkIntToScalar(bounds.fLeft), -SkIntToScalar(bounds.fTop));
125 canvas->concat(ctx.ctm());
126 canvas->drawPicture(fPicture);
senorblanco@chromium.org53333002013-12-12 23:28:52 +0000127
senorblanco@chromium.org6776b822014-01-03 21:48:22 +0000128 offset->fX = bounds.fLeft;
129 offset->fY = bounds.fTop;
robertphillipsfef28602016-04-11 11:08:52 -0700130 return surf->makeImageSnapshot();
senorblanco@chromium.org53333002013-12-12 23:28:52 +0000131}
Justin Novosad52340752014-12-02 14:50:56 -0500132
Matt Sarette22a6a22017-04-12 16:26:21 -0400133sk_sp<SkImageFilter> SkPictureImageFilter::onMakeColorSpace(SkColorSpaceXformer* xformer) const {
Florin Malitaa252c662017-07-10 12:27:52 -0400134 sk_sp<SkColorSpace> dstCS = xformer->dst();
Florin Malita604f0d52017-07-13 14:29:12 -0400135 if (SkColorSpace::Equals(dstCS.get(), fColorSpace.get())) {
Florin Malitaa252c662017-07-10 12:27:52 -0400136 return this->refMe();
137 }
138
Mike Reed48723152017-11-10 14:35:54 -0500139 return sk_sp<SkImageFilter>(new SkPictureImageFilter(fPicture, fCropRect, std::move(dstCS)));
Justin Novosad52340752014-12-02 14:50:56 -0500140}
robertphillipsf3f5bad2014-12-19 13:49:15 -0800141
142#ifndef SK_IGNORE_TO_STRING
143void SkPictureImageFilter::toString(SkString* str) const {
144 str->appendf("SkPictureImageFilter: (");
halcanary9d524f22016-03-29 09:03:52 -0700145 str->appendf("crop: (%f,%f,%f,%f) ",
robertphillipsf3f5bad2014-12-19 13:49:15 -0800146 fCropRect.fLeft, fCropRect.fTop, fCropRect.fRight, fCropRect.fBottom);
147 if (fPicture) {
148 str->appendf("picture: (%f,%f,%f,%f)",
149 fPicture->cullRect().fLeft, fPicture->cullRect().fTop,
150 fPicture->cullRect().fRight, fPicture->cullRect().fBottom);
151 }
152 str->append(")");
153}
154#endif