blob: b9c298dbacac92a2fb0d6fdc67d3a3981effdf75 [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"
Cary Clarkefd99cc2018-06-11 16:25:43 -040015#include "SkPicturePriv.h"
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000016#include "SkReadBuffer.h"
robertphillipsfef28602016-04-11 11:08:52 -070017#include "SkSpecialImage.h"
18#include "SkSpecialSurface.h"
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000019#include "SkWriteBuffer.h"
senorblanco@chromium.org53333002013-12-12 23:28:52 +000020#include "SkValidationUtils.h"
21
robertphillips225db442016-04-17 14:27:05 -070022sk_sp<SkImageFilter> SkPictureImageFilter::Make(sk_sp<SkPicture> picture) {
23 return sk_sp<SkImageFilter>(new SkPictureImageFilter(std::move(picture)));
24}
25
26sk_sp<SkImageFilter> SkPictureImageFilter::Make(sk_sp<SkPicture> picture,
27 const SkRect& cropRect) {
Mike Reed48723152017-11-10 14:35:54 -050028 return sk_sp<SkImageFilter>(new SkPictureImageFilter(std::move(picture), cropRect, nullptr));
robertphillips225db442016-04-17 14:27:05 -070029}
30
robertphillips5ff17b12016-03-28 13:13:42 -070031SkPictureImageFilter::SkPictureImageFilter(sk_sp<SkPicture> picture)
robertphillips372177e2016-03-30 07:32:28 -070032 : INHERITED(nullptr, 0, nullptr)
robertphillips5ff17b12016-03-28 13:13:42 -070033 , fPicture(std::move(picture))
Mike Reed48723152017-11-10 14:35:54 -050034 , fCropRect(fPicture ? fPicture->cullRect() : SkRect::MakeEmpty()) {
senorblanco@chromium.org53333002013-12-12 23:28:52 +000035}
36
robertphillips5ff17b12016-03-28 13:13:42 -070037SkPictureImageFilter::SkPictureImageFilter(sk_sp<SkPicture> picture, const SkRect& cropRect,
Matt Sarette22a6a22017-04-12 16:26:21 -040038 sk_sp<SkColorSpace> colorSpace)
robertphillips372177e2016-03-30 07:32:28 -070039 : INHERITED(nullptr, 0, nullptr)
robertphillips5ff17b12016-03-28 13:13:42 -070040 , fPicture(std::move(picture))
Justin Novosad52340752014-12-02 14:50:56 -050041 , fCropRect(cropRect)
Matt Sarette22a6a22017-04-12 16:26:21 -040042 , fColorSpace(std::move(colorSpace)) {
senorblanco@chromium.org53333002013-12-12 23:28:52 +000043}
44
Mike Reed48723152017-11-10 14:35:54 -050045enum PictureResolution {
46 kDeviceSpace_PictureResolution,
47 kLocalSpace_PictureResolution
48};
49static sk_sp<SkImageFilter> make_localspace_filter(sk_sp<SkPicture> pic, const SkRect& cropRect,
50 SkFilterQuality fq) {
51 SkISize dim = { SkScalarRoundToInt(cropRect.width()), SkScalarRoundToInt(cropRect.height()) };
52 auto img = SkImage::MakeFromPicture(std::move(pic), dim, nullptr, nullptr,
53 SkImage::BitDepth::kU8, SkColorSpace::MakeSRGB());
54 return SkImageSource::Make(img, cropRect, cropRect, fq);
55}
56
reed60c9b582016-04-03 09:11:13 -070057sk_sp<SkFlattenable> SkPictureImageFilter::CreateProc(SkReadBuffer& buffer) {
reedca2622b2016-03-18 07:25:55 -070058 sk_sp<SkPicture> picture;
reed9fa60da2014-08-21 07:59:51 -070059 SkRect cropRect;
60
Mike Reed5a0f3452018-01-19 08:25:11 -050061 if (buffer.readBool()) {
Cary Clarkefd99cc2018-06-11 16:25:43 -040062 picture = SkPicturePriv::MakeFromBuffer(buffer);
reed9fa60da2014-08-21 07:59:51 -070063 }
64 buffer.readRect(&cropRect);
65
Mike Reed77e487d2017-11-09 21:50:20 +000066 if (buffer.isVersionLT(SkReadBuffer::kRemovePictureImageFilterLocalSpace)) {
Mike Reed48723152017-11-10 14:35:54 -050067 PictureResolution pictureResolution = buffer.checkRange<PictureResolution>(
68 kDeviceSpace_PictureResolution, kLocalSpace_PictureResolution);
Mike Reed77e487d2017-11-09 21:50:20 +000069 if (kLocalSpace_PictureResolution == pictureResolution) {
Mike Reed48723152017-11-10 14:35:54 -050070 return make_localspace_filter(std::move(picture), cropRect,
71 buffer.checkFilterQuality());
Mike Reed77e487d2017-11-09 21:50:20 +000072 }
Justin Novosad52340752014-12-02 14:50:56 -050073 }
Mike Reed48723152017-11-10 14:35:54 -050074 return sk_sp<SkImageFilter>(new SkPictureImageFilter(picture, cropRect, nullptr));
reed9fa60da2014-08-21 07:59:51 -070075}
senorblanco@chromium.org53333002013-12-12 23:28:52 +000076
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000077void SkPictureImageFilter::flatten(SkWriteBuffer& buffer) const {
Mike Reed5a0f3452018-01-19 08:25:11 -050078 bool hasPicture = (fPicture != nullptr);
79 buffer.writeBool(hasPicture);
80 if (hasPicture) {
Cary Clarkefd99cc2018-06-11 16:25:43 -040081 SkPicturePriv::Flatten(fPicture, buffer);
commit-bot@chromium.org5e0995e2014-02-07 12:20:04 +000082 }
commit-bot@chromium.orgcac5fd52014-03-10 10:51:58 +000083 buffer.writeRect(fCropRect);
senorblanco@chromium.org53333002013-12-12 23:28:52 +000084}
85
robertphillipsfef28602016-04-11 11:08:52 -070086sk_sp<SkSpecialImage> SkPictureImageFilter::onFilterImage(SkSpecialImage* source,
87 const Context& ctx,
88 SkIPoint* offset) const {
senorblanco@chromium.org53333002013-12-12 23:28:52 +000089 if (!fPicture) {
robertphillipsfef28602016-04-11 11:08:52 -070090 return nullptr;
senorblanco@chromium.org53333002013-12-12 23:28:52 +000091 }
92
93 SkRect floatBounds;
senorblanco@chromium.org4cb543d2014-03-14 15:44:01 +000094 ctx.ctm().mapRect(&floatBounds, fCropRect);
reedb07a94f2014-11-19 05:03:18 -080095 SkIRect bounds = floatBounds.roundOut();
senorblanco3d822c22014-07-30 14:49:31 -070096 if (!bounds.intersect(ctx.clipBounds())) {
robertphillipsfef28602016-04-11 11:08:52 -070097 return nullptr;
senorblanco3d822c22014-07-30 14:49:31 -070098 }
senorblanco@chromium.org53333002013-12-12 23:28:52 +000099
robertphillipsfef28602016-04-11 11:08:52 -0700100 SkASSERT(!bounds.isEmpty());
101
brianosmaneed6b0e2016-09-23 13:04:05 -0700102 sk_sp<SkSpecialSurface> surf(source->makeSurface(ctx.outputProperties(), bounds.size()));
robertphillipsfef28602016-04-11 11:08:52 -0700103 if (!surf) {
104 return nullptr;
senorblanco@chromium.org53333002013-12-12 23:28:52 +0000105 }
106
robertphillipsfef28602016-04-11 11:08:52 -0700107 SkCanvas* canvas = surf->getCanvas();
108 SkASSERT(canvas);
robertphillipsfef28602016-04-11 11:08:52 -0700109 canvas->clear(0x0);
110
Mike Reed48723152017-11-10 14:35:54 -0500111 std::unique_ptr<SkCanvas> xformCanvas;
112 if (fColorSpace) {
113 // Only non-null in the case where onMakeColorSpace() was called. This instructs
114 // us to do the color space xform on playback.
115 xformCanvas = SkCreateColorSpaceXformCanvas(canvas, fColorSpace);
116 canvas = xformCanvas.get();
Justin Novosad52340752014-12-02 14:50:56 -0500117 }
Mike Reed48723152017-11-10 14:35:54 -0500118 canvas->translate(-SkIntToScalar(bounds.fLeft), -SkIntToScalar(bounds.fTop));
119 canvas->concat(ctx.ctm());
120 canvas->drawPicture(fPicture);
senorblanco@chromium.org53333002013-12-12 23:28:52 +0000121
senorblanco@chromium.org6776b822014-01-03 21:48:22 +0000122 offset->fX = bounds.fLeft;
123 offset->fY = bounds.fTop;
robertphillipsfef28602016-04-11 11:08:52 -0700124 return surf->makeImageSnapshot();
senorblanco@chromium.org53333002013-12-12 23:28:52 +0000125}
Justin Novosad52340752014-12-02 14:50:56 -0500126
Matt Sarette22a6a22017-04-12 16:26:21 -0400127sk_sp<SkImageFilter> SkPictureImageFilter::onMakeColorSpace(SkColorSpaceXformer* xformer) const {
Florin Malitaa252c662017-07-10 12:27:52 -0400128 sk_sp<SkColorSpace> dstCS = xformer->dst();
Florin Malita604f0d52017-07-13 14:29:12 -0400129 if (SkColorSpace::Equals(dstCS.get(), fColorSpace.get())) {
Florin Malitaa252c662017-07-10 12:27:52 -0400130 return this->refMe();
131 }
132
Mike Reed48723152017-11-10 14:35:54 -0500133 return sk_sp<SkImageFilter>(new SkPictureImageFilter(fPicture, fCropRect, std::move(dstCS)));
Justin Novosad52340752014-12-02 14:50:56 -0500134}