blob: 66fea1fe3f631ed0a8fdd743d2eddf2a20c668c2 [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"
Cary Clark4dc5a452018-05-21 11:56:57 -040013#include "SkFlattenablePriv.h"
Mike Reed48723152017-11-10 14:35:54 -050014#include "SkImageSource.h"
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000015#include "SkReadBuffer.h"
robertphillipsfef28602016-04-11 11:08:52 -070016#include "SkSpecialImage.h"
17#include "SkSpecialSurface.h"
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000018#include "SkWriteBuffer.h"
senorblanco@chromium.org53333002013-12-12 23:28:52 +000019#include "SkValidationUtils.h"
20
robertphillips225db442016-04-17 14:27:05 -070021sk_sp<SkImageFilter> SkPictureImageFilter::Make(sk_sp<SkPicture> picture) {
22 return sk_sp<SkImageFilter>(new SkPictureImageFilter(std::move(picture)));
23}
24
25sk_sp<SkImageFilter> SkPictureImageFilter::Make(sk_sp<SkPicture> picture,
26 const SkRect& cropRect) {
Mike Reed48723152017-11-10 14:35:54 -050027 return sk_sp<SkImageFilter>(new SkPictureImageFilter(std::move(picture), cropRect, nullptr));
robertphillips225db442016-04-17 14:27:05 -070028}
29
robertphillips5ff17b12016-03-28 13:13:42 -070030SkPictureImageFilter::SkPictureImageFilter(sk_sp<SkPicture> picture)
robertphillips372177e2016-03-30 07:32:28 -070031 : INHERITED(nullptr, 0, nullptr)
robertphillips5ff17b12016-03-28 13:13:42 -070032 , fPicture(std::move(picture))
Mike Reed48723152017-11-10 14:35:54 -050033 , fCropRect(fPicture ? fPicture->cullRect() : SkRect::MakeEmpty()) {
senorblanco@chromium.org53333002013-12-12 23:28:52 +000034}
35
robertphillips5ff17b12016-03-28 13:13:42 -070036SkPictureImageFilter::SkPictureImageFilter(sk_sp<SkPicture> picture, const SkRect& cropRect,
Matt Sarette22a6a22017-04-12 16:26:21 -040037 sk_sp<SkColorSpace> colorSpace)
robertphillips372177e2016-03-30 07:32:28 -070038 : INHERITED(nullptr, 0, nullptr)
robertphillips5ff17b12016-03-28 13:13:42 -070039 , fPicture(std::move(picture))
Justin Novosad52340752014-12-02 14:50:56 -050040 , fCropRect(cropRect)
Matt Sarette22a6a22017-04-12 16:26:21 -040041 , fColorSpace(std::move(colorSpace)) {
senorblanco@chromium.org53333002013-12-12 23:28:52 +000042}
43
Mike Reed48723152017-11-10 14:35:54 -050044enum PictureResolution {
45 kDeviceSpace_PictureResolution,
46 kLocalSpace_PictureResolution
47};
48static sk_sp<SkImageFilter> make_localspace_filter(sk_sp<SkPicture> pic, const SkRect& cropRect,
49 SkFilterQuality fq) {
50 SkISize dim = { SkScalarRoundToInt(cropRect.width()), SkScalarRoundToInt(cropRect.height()) };
51 auto img = SkImage::MakeFromPicture(std::move(pic), dim, nullptr, nullptr,
52 SkImage::BitDepth::kU8, SkColorSpace::MakeSRGB());
53 return SkImageSource::Make(img, cropRect, cropRect, fq);
54}
55
reed60c9b582016-04-03 09:11:13 -070056sk_sp<SkFlattenable> SkPictureImageFilter::CreateProc(SkReadBuffer& buffer) {
reedca2622b2016-03-18 07:25:55 -070057 sk_sp<SkPicture> picture;
reed9fa60da2014-08-21 07:59:51 -070058 SkRect cropRect;
59
Mike Reed5a0f3452018-01-19 08:25:11 -050060 if (buffer.readBool()) {
61 picture = SkPicture::MakeFromBuffer(buffer);
reed9fa60da2014-08-21 07:59:51 -070062 }
63 buffer.readRect(&cropRect);
64
Mike Reed77e487d2017-11-09 21:50:20 +000065 if (buffer.isVersionLT(SkReadBuffer::kRemovePictureImageFilterLocalSpace)) {
Mike Reed48723152017-11-10 14:35:54 -050066 PictureResolution pictureResolution = buffer.checkRange<PictureResolution>(
67 kDeviceSpace_PictureResolution, kLocalSpace_PictureResolution);
Mike Reed77e487d2017-11-09 21:50:20 +000068 if (kLocalSpace_PictureResolution == pictureResolution) {
Mike Reed48723152017-11-10 14:35:54 -050069 return make_localspace_filter(std::move(picture), cropRect,
70 buffer.checkFilterQuality());
Mike Reed77e487d2017-11-09 21:50:20 +000071 }
Justin Novosad52340752014-12-02 14:50:56 -050072 }
Mike Reed48723152017-11-10 14:35:54 -050073 return sk_sp<SkImageFilter>(new SkPictureImageFilter(picture, cropRect, nullptr));
reed9fa60da2014-08-21 07:59:51 -070074}
senorblanco@chromium.org53333002013-12-12 23:28:52 +000075
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000076void SkPictureImageFilter::flatten(SkWriteBuffer& buffer) const {
Mike Reed5a0f3452018-01-19 08:25:11 -050077 bool hasPicture = (fPicture != nullptr);
78 buffer.writeBool(hasPicture);
79 if (hasPicture) {
Mike Klein88d90712018-01-27 17:30:04 +000080 fPicture->flatten(buffer);
commit-bot@chromium.org5e0995e2014-02-07 12:20:04 +000081 }
commit-bot@chromium.orgcac5fd52014-03-10 10:51:58 +000082 buffer.writeRect(fCropRect);
senorblanco@chromium.org53333002013-12-12 23:28:52 +000083}
84
robertphillipsfef28602016-04-11 11:08:52 -070085sk_sp<SkSpecialImage> SkPictureImageFilter::onFilterImage(SkSpecialImage* source,
86 const Context& ctx,
87 SkIPoint* offset) const {
senorblanco@chromium.org53333002013-12-12 23:28:52 +000088 if (!fPicture) {
robertphillipsfef28602016-04-11 11:08:52 -070089 return nullptr;
senorblanco@chromium.org53333002013-12-12 23:28:52 +000090 }
91
92 SkRect floatBounds;
senorblanco@chromium.org4cb543d2014-03-14 15:44:01 +000093 ctx.ctm().mapRect(&floatBounds, fCropRect);
reedb07a94f2014-11-19 05:03:18 -080094 SkIRect bounds = floatBounds.roundOut();
senorblanco3d822c22014-07-30 14:49:31 -070095 if (!bounds.intersect(ctx.clipBounds())) {
robertphillipsfef28602016-04-11 11:08:52 -070096 return nullptr;
senorblanco3d822c22014-07-30 14:49:31 -070097 }
senorblanco@chromium.org53333002013-12-12 23:28:52 +000098
robertphillipsfef28602016-04-11 11:08:52 -070099 SkASSERT(!bounds.isEmpty());
100
brianosmaneed6b0e2016-09-23 13:04:05 -0700101 sk_sp<SkSpecialSurface> surf(source->makeSurface(ctx.outputProperties(), bounds.size()));
robertphillipsfef28602016-04-11 11:08:52 -0700102 if (!surf) {
103 return nullptr;
senorblanco@chromium.org53333002013-12-12 23:28:52 +0000104 }
105
robertphillipsfef28602016-04-11 11:08:52 -0700106 SkCanvas* canvas = surf->getCanvas();
107 SkASSERT(canvas);
robertphillipsfef28602016-04-11 11:08:52 -0700108 canvas->clear(0x0);
109
Mike Reed48723152017-11-10 14:35:54 -0500110 std::unique_ptr<SkCanvas> xformCanvas;
111 if (fColorSpace) {
112 // Only non-null in the case where onMakeColorSpace() was called. This instructs
113 // us to do the color space xform on playback.
114 xformCanvas = SkCreateColorSpaceXformCanvas(canvas, fColorSpace);
115 canvas = xformCanvas.get();
Justin Novosad52340752014-12-02 14:50:56 -0500116 }
Mike Reed48723152017-11-10 14:35:54 -0500117 canvas->translate(-SkIntToScalar(bounds.fLeft), -SkIntToScalar(bounds.fTop));
118 canvas->concat(ctx.ctm());
119 canvas->drawPicture(fPicture);
senorblanco@chromium.org53333002013-12-12 23:28:52 +0000120
senorblanco@chromium.org6776b822014-01-03 21:48:22 +0000121 offset->fX = bounds.fLeft;
122 offset->fY = bounds.fTop;
robertphillipsfef28602016-04-11 11:08:52 -0700123 return surf->makeImageSnapshot();
senorblanco@chromium.org53333002013-12-12 23:28:52 +0000124}
Justin Novosad52340752014-12-02 14:50:56 -0500125
Matt Sarette22a6a22017-04-12 16:26:21 -0400126sk_sp<SkImageFilter> SkPictureImageFilter::onMakeColorSpace(SkColorSpaceXformer* xformer) const {
Florin Malitaa252c662017-07-10 12:27:52 -0400127 sk_sp<SkColorSpace> dstCS = xformer->dst();
Florin Malita604f0d52017-07-13 14:29:12 -0400128 if (SkColorSpace::Equals(dstCS.get(), fColorSpace.get())) {
Florin Malitaa252c662017-07-10 12:27:52 -0400129 return this->refMe();
130 }
131
Mike Reed48723152017-11-10 14:35:54 -0500132 return sk_sp<SkImageFilter>(new SkPictureImageFilter(fPicture, fCropRect, std::move(dstCS)));
Justin Novosad52340752014-12-02 14:50:56 -0500133}
Cary Clark32a49102018-05-20 23:15:43 +0000134
135void SkPictureImageFilter::toString(SkString* str) const {
136 str->appendf("SkPictureImageFilter: (");
137 str->appendf("crop: (%f,%f,%f,%f) ",
138 fCropRect.fLeft, fCropRect.fTop, fCropRect.fRight, fCropRect.fBottom);
139 if (fPicture) {
140 str->appendf("picture: (%f,%f,%f,%f)",
141 fPicture->cullRect().fLeft, fPicture->cullRect().fTop,
142 fPicture->cullRect().fRight, fPicture->cullRect().fBottom);
143 }
144 str->append(")");
145}