blob: 623be2b822137ddd95bf43cf2824a056e71587f2 [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"
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000011#include "SkReadBuffer.h"
robertphillipsfef28602016-04-11 11:08:52 -070012#include "SkSpecialImage.h"
13#include "SkSpecialSurface.h"
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000014#include "SkWriteBuffer.h"
senorblanco@chromium.org53333002013-12-12 23:28:52 +000015#include "SkValidationUtils.h"
16
robertphillips5ff17b12016-03-28 13:13:42 -070017SkPictureImageFilter::SkPictureImageFilter(sk_sp<SkPicture> picture)
robertphillips372177e2016-03-30 07:32:28 -070018 : INHERITED(nullptr, 0, nullptr)
robertphillips5ff17b12016-03-28 13:13:42 -070019 , fPicture(std::move(picture))
20 , fCropRect(fPicture ? fPicture->cullRect() : SkRect::MakeEmpty())
halcanary9d524f22016-03-29 09:03:52 -070021 , fPictureResolution(kDeviceSpace_PictureResolution)
reed93a12152015-03-16 10:08:34 -070022 , fFilterQuality(kLow_SkFilterQuality) {
senorblanco@chromium.org53333002013-12-12 23:28:52 +000023}
24
robertphillips5ff17b12016-03-28 13:13:42 -070025SkPictureImageFilter::SkPictureImageFilter(sk_sp<SkPicture> picture, const SkRect& cropRect,
senorblanco24e06d52015-03-18 12:11:33 -070026 PictureResolution pictureResolution,
reed93a12152015-03-16 10:08:34 -070027 SkFilterQuality filterQuality)
robertphillips372177e2016-03-30 07:32:28 -070028 : INHERITED(nullptr, 0, nullptr)
robertphillips5ff17b12016-03-28 13:13:42 -070029 , fPicture(std::move(picture))
Justin Novosad52340752014-12-02 14:50:56 -050030 , fCropRect(cropRect)
junovf3c78cc2014-12-09 13:07:22 -080031 , fPictureResolution(pictureResolution)
reed93a12152015-03-16 10:08:34 -070032 , fFilterQuality(filterQuality) {
senorblanco@chromium.org53333002013-12-12 23:28:52 +000033}
34
reed60c9b582016-04-03 09:11:13 -070035sk_sp<SkFlattenable> SkPictureImageFilter::CreateProc(SkReadBuffer& buffer) {
reedca2622b2016-03-18 07:25:55 -070036 sk_sp<SkPicture> picture;
reed9fa60da2014-08-21 07:59:51 -070037 SkRect cropRect;
38
hendrikw446ee672015-06-16 09:28:37 -070039 if (buffer.isCrossProcess() && SkPicture::PictureIOSecurityPrecautionsEnabled()) {
robertphillipsc4bd39c2015-01-06 09:17:02 -080040 buffer.validate(!buffer.readBool());
hendrikw446ee672015-06-16 09:28:37 -070041 } else {
reed9fa60da2014-08-21 07:59:51 -070042 if (buffer.readBool()) {
reedca2622b2016-03-18 07:25:55 -070043 picture = SkPicture::MakeFromBuffer(buffer);
reed9fa60da2014-08-21 07:59:51 -070044 }
reed9fa60da2014-08-21 07:59:51 -070045 }
46 buffer.readRect(&cropRect);
Justin Novosad52340752014-12-02 14:50:56 -050047 PictureResolution pictureResolution;
48 if (buffer.isVersionLT(SkReadBuffer::kPictureImageFilterResolution_Version)) {
49 pictureResolution = kDeviceSpace_PictureResolution;
50 } else {
51 pictureResolution = (PictureResolution)buffer.readInt();
halcanary9d524f22016-03-29 09:03:52 -070052 }
reed9fa60da2014-08-21 07:59:51 -070053
junovf3c78cc2014-12-09 13:07:22 -080054 if (kLocalSpace_PictureResolution == pictureResolution) {
55 //filterLevel is only serialized if pictureResolution is LocalSpace
reed93a12152015-03-16 10:08:34 -070056 SkFilterQuality filterQuality;
junovf3c78cc2014-12-09 13:07:22 -080057 if (buffer.isVersionLT(SkReadBuffer::kPictureImageFilterLevel_Version)) {
reed93a12152015-03-16 10:08:34 -070058 filterQuality = kLow_SkFilterQuality;
junovf3c78cc2014-12-09 13:07:22 -080059 } else {
reed93a12152015-03-16 10:08:34 -070060 filterQuality = (SkFilterQuality)buffer.readInt();
junovf3c78cc2014-12-09 13:07:22 -080061 }
reed60c9b582016-04-03 09:11:13 -070062 return MakeForLocalSpace(picture, cropRect, filterQuality);
Justin Novosad52340752014-12-02 14:50:56 -050063 }
reed60c9b582016-04-03 09:11:13 -070064 return Make(picture, cropRect);
reed9fa60da2014-08-21 07:59:51 -070065}
senorblanco@chromium.org53333002013-12-12 23:28:52 +000066
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000067void SkPictureImageFilter::flatten(SkWriteBuffer& buffer) const {
hendrikw446ee672015-06-16 09:28:37 -070068 if (buffer.isCrossProcess() && SkPicture::PictureIOSecurityPrecautionsEnabled()) {
robertphillipsc4bd39c2015-01-06 09:17:02 -080069 buffer.writeBool(false);
hendrikw446ee672015-06-16 09:28:37 -070070 } else {
halcanary96fcdcc2015-08-27 07:41:13 -070071 bool hasPicture = (fPicture != nullptr);
senorblanco@chromium.org97f5fc62014-05-30 20:50:56 +000072 buffer.writeBool(hasPicture);
73 if (hasPicture) {
74 fPicture->flatten(buffer);
75 }
commit-bot@chromium.org5e0995e2014-02-07 12:20:04 +000076 }
commit-bot@chromium.orgcac5fd52014-03-10 10:51:58 +000077 buffer.writeRect(fCropRect);
Justin Novosad52340752014-12-02 14:50:56 -050078 buffer.writeInt(fPictureResolution);
junovf3c78cc2014-12-09 13:07:22 -080079 if (kLocalSpace_PictureResolution == fPictureResolution) {
reed93a12152015-03-16 10:08:34 -070080 buffer.writeInt(fFilterQuality);
junovf3c78cc2014-12-09 13:07:22 -080081 }
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
100 SkImageInfo info = SkImageInfo::MakeN32(bounds.width(), bounds.height(), kPremul_SkAlphaType);
101 sk_sp<SkSpecialSurface> surf(source->makeSurface(info));
102 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);
senorblanco@chromium.org53333002013-12-12 23:28:52 +0000108
robertphillipsfef28602016-04-11 11:08:52 -0700109 canvas->clear(0x0);
110
111 if (kDeviceSpace_PictureResolution == fPictureResolution ||
junovf3c78cc2014-12-09 13:07:22 -0800112 0 == (ctx.ctm().getType() & ~SkMatrix::kTranslate_Mask)) {
robertphillipsfef28602016-04-11 11:08:52 -0700113 this->drawPictureAtDeviceResolution(canvas, bounds, ctx);
Justin Novosad52340752014-12-02 14:50:56 -0500114 } else {
robertphillipsfef28602016-04-11 11:08:52 -0700115 this->drawPictureAtLocalResolution(source, canvas, bounds, ctx);
Justin Novosad52340752014-12-02 14:50:56 -0500116 }
senorblanco@chromium.org53333002013-12-12 23:28:52 +0000117
senorblanco@chromium.org6776b822014-01-03 21:48:22 +0000118 offset->fX = bounds.fLeft;
119 offset->fY = bounds.fTop;
robertphillipsfef28602016-04-11 11:08:52 -0700120 return surf->makeImageSnapshot();
senorblanco@chromium.org53333002013-12-12 23:28:52 +0000121}
Justin Novosad52340752014-12-02 14:50:56 -0500122
robertphillipsfef28602016-04-11 11:08:52 -0700123void SkPictureImageFilter::drawPictureAtDeviceResolution(SkCanvas* canvas,
Justin Novosad52340752014-12-02 14:50:56 -0500124 const SkIRect& deviceBounds,
125 const Context& ctx) const {
robertphillipsfef28602016-04-11 11:08:52 -0700126 canvas->translate(-SkIntToScalar(deviceBounds.fLeft), -SkIntToScalar(deviceBounds.fTop));
127 canvas->concat(ctx.ctm());
128 canvas->drawPicture(fPicture);
Justin Novosad52340752014-12-02 14:50:56 -0500129}
130
robertphillipsfef28602016-04-11 11:08:52 -0700131void SkPictureImageFilter::drawPictureAtLocalResolution(SkSpecialImage* source,
132 SkCanvas* canvas,
Justin Novosad52340752014-12-02 14:50:56 -0500133 const SkIRect& deviceBounds,
134 const Context& ctx) const {
135 SkMatrix inverseCtm;
robertphillipsefbffed2015-06-22 12:06:08 -0700136 if (!ctx.ctm().invert(&inverseCtm)) {
Justin Novosad52340752014-12-02 14:50:56 -0500137 return;
robertphillipsefbffed2015-06-22 12:06:08 -0700138 }
139
Justin Novosad52340752014-12-02 14:50:56 -0500140 SkRect localBounds = SkRect::Make(ctx.clipBounds());
141 inverseCtm.mapRect(&localBounds);
robertphillipsefbffed2015-06-22 12:06:08 -0700142 if (!localBounds.intersect(fCropRect)) {
Justin Novosad52340752014-12-02 14:50:56 -0500143 return;
robertphillipsefbffed2015-06-22 12:06:08 -0700144 }
Justin Novosad52340752014-12-02 14:50:56 -0500145 SkIRect localIBounds = localBounds.roundOut();
Justin Novosad52340752014-12-02 14:50:56 -0500146
robertphillipsfef28602016-04-11 11:08:52 -0700147 sk_sp<SkSpecialImage> localImg;
148 {
149 const SkImageInfo info = SkImageInfo::MakeN32(localIBounds.width(), localIBounds.height(),
150 kPremul_SkAlphaType);
Justin Novosad52340752014-12-02 14:50:56 -0500151
robertphillipsfef28602016-04-11 11:08:52 -0700152 sk_sp<SkSpecialSurface> localSurface(source->makeSurface(info));
153 if (!localSurface) {
154 return;
155 }
Justin Novosad52340752014-12-02 14:50:56 -0500156
robertphillipsfef28602016-04-11 11:08:52 -0700157 SkCanvas* localCanvas = localSurface->getCanvas();
158 SkASSERT(localCanvas);
159
160 localCanvas->translate(-SkIntToScalar(localIBounds.fLeft),
161 -SkIntToScalar(localIBounds.fTop));
162 localCanvas->drawPicture(fPicture);
163
164 localImg = localSurface->makeImageSnapshot();
165 SkASSERT(localImg);
166 }
167
168 {
169 canvas->translate(-SkIntToScalar(deviceBounds.fLeft), -SkIntToScalar(deviceBounds.fTop));
170 canvas->concat(ctx.ctm());
171 SkPaint paint;
172 paint.setFilterQuality(fFilterQuality);
173
174 localImg->draw(canvas,
175 SkIntToScalar(localIBounds.fLeft),
176 SkIntToScalar(localIBounds.fTop),
177 &paint);
178 }
Justin Novosad52340752014-12-02 14:50:56 -0500179}
robertphillipsf3f5bad2014-12-19 13:49:15 -0800180
181#ifndef SK_IGNORE_TO_STRING
182void SkPictureImageFilter::toString(SkString* str) const {
183 str->appendf("SkPictureImageFilter: (");
halcanary9d524f22016-03-29 09:03:52 -0700184 str->appendf("crop: (%f,%f,%f,%f) ",
robertphillipsf3f5bad2014-12-19 13:49:15 -0800185 fCropRect.fLeft, fCropRect.fTop, fCropRect.fRight, fCropRect.fBottom);
186 if (fPicture) {
187 str->appendf("picture: (%f,%f,%f,%f)",
188 fPicture->cullRect().fLeft, fPicture->cullRect().fTop,
189 fPicture->cullRect().fRight, fPicture->cullRect().fBottom);
190 }
191 str->append(")");
192}
193#endif