blob: 304b91cf3c9958b2b8ff17027260525436936298 [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
Mike Reed5a0f3452018-01-19 08:25:11 -050059 if (buffer.readBool()) {
60 picture = SkPicture::MakeFromBuffer(buffer);
reed9fa60da2014-08-21 07:59:51 -070061 }
62 buffer.readRect(&cropRect);
63
Mike Reed77e487d2017-11-09 21:50:20 +000064 if (buffer.isVersionLT(SkReadBuffer::kRemovePictureImageFilterLocalSpace)) {
Mike Reed48723152017-11-10 14:35:54 -050065 PictureResolution pictureResolution = buffer.checkRange<PictureResolution>(
66 kDeviceSpace_PictureResolution, kLocalSpace_PictureResolution);
Mike Reed77e487d2017-11-09 21:50:20 +000067 if (kLocalSpace_PictureResolution == pictureResolution) {
Mike Reed48723152017-11-10 14:35:54 -050068 return make_localspace_filter(std::move(picture), cropRect,
69 buffer.checkFilterQuality());
Mike Reed77e487d2017-11-09 21:50:20 +000070 }
Justin Novosad52340752014-12-02 14:50:56 -050071 }
Mike Reed48723152017-11-10 14:35:54 -050072 return sk_sp<SkImageFilter>(new SkPictureImageFilter(picture, cropRect, nullptr));
reed9fa60da2014-08-21 07:59:51 -070073}
senorblanco@chromium.org53333002013-12-12 23:28:52 +000074
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000075void SkPictureImageFilter::flatten(SkWriteBuffer& buffer) const {
Mike Reed5a0f3452018-01-19 08:25:11 -050076 bool hasPicture = (fPicture != nullptr);
77 buffer.writeBool(hasPicture);
78 if (hasPicture) {
79 fPicture->flatten(buffer);
commit-bot@chromium.org5e0995e2014-02-07 12:20:04 +000080 }
commit-bot@chromium.orgcac5fd52014-03-10 10:51:58 +000081 buffer.writeRect(fCropRect);
senorblanco@chromium.org53333002013-12-12 23:28:52 +000082}
83
robertphillipsfef28602016-04-11 11:08:52 -070084sk_sp<SkSpecialImage> SkPictureImageFilter::onFilterImage(SkSpecialImage* source,
85 const Context& ctx,
86 SkIPoint* offset) const {
senorblanco@chromium.org53333002013-12-12 23:28:52 +000087 if (!fPicture) {
robertphillipsfef28602016-04-11 11:08:52 -070088 return nullptr;
senorblanco@chromium.org53333002013-12-12 23:28:52 +000089 }
90
91 SkRect floatBounds;
senorblanco@chromium.org4cb543d2014-03-14 15:44:01 +000092 ctx.ctm().mapRect(&floatBounds, fCropRect);
reedb07a94f2014-11-19 05:03:18 -080093 SkIRect bounds = floatBounds.roundOut();
senorblanco3d822c22014-07-30 14:49:31 -070094 if (!bounds.intersect(ctx.clipBounds())) {
robertphillipsfef28602016-04-11 11:08:52 -070095 return nullptr;
senorblanco3d822c22014-07-30 14:49:31 -070096 }
senorblanco@chromium.org53333002013-12-12 23:28:52 +000097
robertphillipsfef28602016-04-11 11:08:52 -070098 SkASSERT(!bounds.isEmpty());
99
brianosmaneed6b0e2016-09-23 13:04:05 -0700100 sk_sp<SkSpecialSurface> surf(source->makeSurface(ctx.outputProperties(), bounds.size()));
robertphillipsfef28602016-04-11 11:08:52 -0700101 if (!surf) {
102 return nullptr;
senorblanco@chromium.org53333002013-12-12 23:28:52 +0000103 }
104
robertphillipsfef28602016-04-11 11:08:52 -0700105 SkCanvas* canvas = surf->getCanvas();
106 SkASSERT(canvas);
robertphillipsfef28602016-04-11 11:08:52 -0700107 canvas->clear(0x0);
108
Mike Reed48723152017-11-10 14:35:54 -0500109 std::unique_ptr<SkCanvas> xformCanvas;
110 if (fColorSpace) {
111 // Only non-null in the case where onMakeColorSpace() was called. This instructs
112 // us to do the color space xform on playback.
113 xformCanvas = SkCreateColorSpaceXformCanvas(canvas, fColorSpace);
114 canvas = xformCanvas.get();
Justin Novosad52340752014-12-02 14:50:56 -0500115 }
Mike Reed48723152017-11-10 14:35:54 -0500116 canvas->translate(-SkIntToScalar(bounds.fLeft), -SkIntToScalar(bounds.fTop));
117 canvas->concat(ctx.ctm());
118 canvas->drawPicture(fPicture);
senorblanco@chromium.org53333002013-12-12 23:28:52 +0000119
senorblanco@chromium.org6776b822014-01-03 21:48:22 +0000120 offset->fX = bounds.fLeft;
121 offset->fY = bounds.fTop;
robertphillipsfef28602016-04-11 11:08:52 -0700122 return surf->makeImageSnapshot();
senorblanco@chromium.org53333002013-12-12 23:28:52 +0000123}
Justin Novosad52340752014-12-02 14:50:56 -0500124
Matt Sarette22a6a22017-04-12 16:26:21 -0400125sk_sp<SkImageFilter> SkPictureImageFilter::onMakeColorSpace(SkColorSpaceXformer* xformer) const {
Florin Malitaa252c662017-07-10 12:27:52 -0400126 sk_sp<SkColorSpace> dstCS = xformer->dst();
Florin Malita604f0d52017-07-13 14:29:12 -0400127 if (SkColorSpace::Equals(dstCS.get(), fColorSpace.get())) {
Florin Malitaa252c662017-07-10 12:27:52 -0400128 return this->refMe();
129 }
130
Mike Reed48723152017-11-10 14:35:54 -0500131 return sk_sp<SkImageFilter>(new SkPictureImageFilter(fPicture, fCropRect, std::move(dstCS)));
Justin Novosad52340752014-12-02 14:50:56 -0500132}
robertphillipsf3f5bad2014-12-19 13:49:15 -0800133
134#ifndef SK_IGNORE_TO_STRING
135void SkPictureImageFilter::toString(SkString* str) const {
136 str->appendf("SkPictureImageFilter: (");
halcanary9d524f22016-03-29 09:03:52 -0700137 str->appendf("crop: (%f,%f,%f,%f) ",
robertphillipsf3f5bad2014-12-19 13:49:15 -0800138 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}
146#endif