blob: 2dff41a8d7c4612c1d251c22569972af764a8e8d [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"
9#include "SkDevice.h"
10#include "SkCanvas.h"
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000011#include "SkReadBuffer.h"
fmalita2d97bc12014-11-20 10:44:58 -080012#include "SkSurfaceProps.h"
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000013#include "SkWriteBuffer.h"
senorblanco@chromium.org53333002013-12-12 23:28:52 +000014#include "SkValidationUtils.h"
15
robertphillips5ff17b12016-03-28 13:13:42 -070016SkPictureImageFilter::SkPictureImageFilter(sk_sp<SkPicture> picture)
robertphillips372177e2016-03-30 07:32:28 -070017 : INHERITED(nullptr, 0, nullptr)
robertphillips5ff17b12016-03-28 13:13:42 -070018 , fPicture(std::move(picture))
19 , fCropRect(fPicture ? fPicture->cullRect() : SkRect::MakeEmpty())
halcanary9d524f22016-03-29 09:03:52 -070020 , fPictureResolution(kDeviceSpace_PictureResolution)
reed93a12152015-03-16 10:08:34 -070021 , fFilterQuality(kLow_SkFilterQuality) {
senorblanco@chromium.org53333002013-12-12 23:28:52 +000022}
23
robertphillips5ff17b12016-03-28 13:13:42 -070024SkPictureImageFilter::SkPictureImageFilter(sk_sp<SkPicture> picture, const SkRect& cropRect,
senorblanco24e06d52015-03-18 12:11:33 -070025 PictureResolution pictureResolution,
reed93a12152015-03-16 10:08:34 -070026 SkFilterQuality filterQuality)
robertphillips372177e2016-03-30 07:32:28 -070027 : INHERITED(nullptr, 0, nullptr)
robertphillips5ff17b12016-03-28 13:13:42 -070028 , fPicture(std::move(picture))
Justin Novosad52340752014-12-02 14:50:56 -050029 , fCropRect(cropRect)
junovf3c78cc2014-12-09 13:07:22 -080030 , fPictureResolution(pictureResolution)
reed93a12152015-03-16 10:08:34 -070031 , fFilterQuality(filterQuality) {
senorblanco@chromium.org53333002013-12-12 23:28:52 +000032}
33
reed60c9b582016-04-03 09:11:13 -070034sk_sp<SkFlattenable> SkPictureImageFilter::CreateProc(SkReadBuffer& buffer) {
reedca2622b2016-03-18 07:25:55 -070035 sk_sp<SkPicture> picture;
reed9fa60da2014-08-21 07:59:51 -070036 SkRect cropRect;
37
hendrikw446ee672015-06-16 09:28:37 -070038 if (buffer.isCrossProcess() && SkPicture::PictureIOSecurityPrecautionsEnabled()) {
robertphillipsc4bd39c2015-01-06 09:17:02 -080039 buffer.validate(!buffer.readBool());
hendrikw446ee672015-06-16 09:28:37 -070040 } else {
reed9fa60da2014-08-21 07:59:51 -070041 if (buffer.readBool()) {
reedca2622b2016-03-18 07:25:55 -070042 picture = SkPicture::MakeFromBuffer(buffer);
reed9fa60da2014-08-21 07:59:51 -070043 }
reed9fa60da2014-08-21 07:59:51 -070044 }
45 buffer.readRect(&cropRect);
Justin Novosad52340752014-12-02 14:50:56 -050046 PictureResolution pictureResolution;
47 if (buffer.isVersionLT(SkReadBuffer::kPictureImageFilterResolution_Version)) {
48 pictureResolution = kDeviceSpace_PictureResolution;
49 } else {
50 pictureResolution = (PictureResolution)buffer.readInt();
halcanary9d524f22016-03-29 09:03:52 -070051 }
reed9fa60da2014-08-21 07:59:51 -070052
junovf3c78cc2014-12-09 13:07:22 -080053 if (kLocalSpace_PictureResolution == pictureResolution) {
54 //filterLevel is only serialized if pictureResolution is LocalSpace
reed93a12152015-03-16 10:08:34 -070055 SkFilterQuality filterQuality;
junovf3c78cc2014-12-09 13:07:22 -080056 if (buffer.isVersionLT(SkReadBuffer::kPictureImageFilterLevel_Version)) {
reed93a12152015-03-16 10:08:34 -070057 filterQuality = kLow_SkFilterQuality;
junovf3c78cc2014-12-09 13:07:22 -080058 } else {
reed93a12152015-03-16 10:08:34 -070059 filterQuality = (SkFilterQuality)buffer.readInt();
junovf3c78cc2014-12-09 13:07:22 -080060 }
reed60c9b582016-04-03 09:11:13 -070061 return MakeForLocalSpace(picture, cropRect, filterQuality);
Justin Novosad52340752014-12-02 14:50:56 -050062 }
reed60c9b582016-04-03 09:11:13 -070063 return Make(picture, cropRect);
reed9fa60da2014-08-21 07:59:51 -070064}
senorblanco@chromium.org53333002013-12-12 23:28:52 +000065
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000066void SkPictureImageFilter::flatten(SkWriteBuffer& buffer) const {
hendrikw446ee672015-06-16 09:28:37 -070067 if (buffer.isCrossProcess() && SkPicture::PictureIOSecurityPrecautionsEnabled()) {
robertphillipsc4bd39c2015-01-06 09:17:02 -080068 buffer.writeBool(false);
hendrikw446ee672015-06-16 09:28:37 -070069 } else {
halcanary96fcdcc2015-08-27 07:41:13 -070070 bool hasPicture = (fPicture != nullptr);
senorblanco@chromium.org97f5fc62014-05-30 20:50:56 +000071 buffer.writeBool(hasPicture);
72 if (hasPicture) {
73 fPicture->flatten(buffer);
74 }
commit-bot@chromium.org5e0995e2014-02-07 12:20:04 +000075 }
commit-bot@chromium.orgcac5fd52014-03-10 10:51:58 +000076 buffer.writeRect(fCropRect);
Justin Novosad52340752014-12-02 14:50:56 -050077 buffer.writeInt(fPictureResolution);
junovf3c78cc2014-12-09 13:07:22 -080078 if (kLocalSpace_PictureResolution == fPictureResolution) {
reed93a12152015-03-16 10:08:34 -070079 buffer.writeInt(fFilterQuality);
junovf3c78cc2014-12-09 13:07:22 -080080 }
senorblanco@chromium.org53333002013-12-12 23:28:52 +000081}
82
robertphillips48e78462016-02-17 13:57:16 -080083bool SkPictureImageFilter::onFilterImageDeprecated(Proxy* proxy, const SkBitmap&,
84 const Context& ctx,
85 SkBitmap* result, SkIPoint* offset) const {
senorblanco@chromium.org53333002013-12-12 23:28:52 +000086 if (!fPicture) {
senorblanco@chromium.org6776b822014-01-03 21:48:22 +000087 offset->fX = offset->fY = 0;
senorblanco@chromium.org53333002013-12-12 23:28:52 +000088 return true;
89 }
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())) {
95 return false;
96 }
senorblanco@chromium.org53333002013-12-12 23:28:52 +000097
98 if (bounds.isEmpty()) {
senorblanco@chromium.org6776b822014-01-03 21:48:22 +000099 offset->fX = offset->fY = 0;
senorblanco@chromium.org53333002013-12-12 23:28:52 +0000100 return true;
101 }
102
103 SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds.width(), bounds.height()));
halcanary96fcdcc2015-08-27 07:41:13 -0700104 if (nullptr == device.get()) {
senorblanco@chromium.org53333002013-12-12 23:28:52 +0000105 return false;
106 }
107
halcanary9d524f22016-03-29 09:03:52 -0700108 if (kDeviceSpace_PictureResolution == fPictureResolution ||
junovf3c78cc2014-12-09 13:07:22 -0800109 0 == (ctx.ctm().getType() & ~SkMatrix::kTranslate_Mask)) {
halcanary9d524f22016-03-29 09:03:52 -0700110 this->drawPictureAtDeviceResolution(device.get(), bounds, ctx);
Justin Novosad52340752014-12-02 14:50:56 -0500111 } else {
robertphillipsefbffed2015-06-22 12:06:08 -0700112 this->drawPictureAtLocalResolution(proxy, device.get(), bounds, ctx);
Justin Novosad52340752014-12-02 14:50:56 -0500113 }
senorblanco@chromium.org53333002013-12-12 23:28:52 +0000114
115 *result = device.get()->accessBitmap(false);
senorblanco@chromium.org6776b822014-01-03 21:48:22 +0000116 offset->fX = bounds.fLeft;
117 offset->fY = bounds.fTop;
senorblanco@chromium.org53333002013-12-12 23:28:52 +0000118 return true;
119}
Justin Novosad52340752014-12-02 14:50:56 -0500120
robertphillipsefbffed2015-06-22 12:06:08 -0700121void SkPictureImageFilter::drawPictureAtDeviceResolution(SkBaseDevice* device,
Justin Novosad52340752014-12-02 14:50:56 -0500122 const SkIRect& deviceBounds,
123 const Context& ctx) const {
robertphillipsefbffed2015-06-22 12:06:08 -0700124 SkCanvas canvas(device);
Justin Novosad52340752014-12-02 14:50:56 -0500125
126 canvas.translate(-SkIntToScalar(deviceBounds.fLeft), -SkIntToScalar(deviceBounds.fTop));
127 canvas.concat(ctx.ctm());
128 canvas.drawPicture(fPicture);
129}
130
131void SkPictureImageFilter::drawPictureAtLocalResolution(Proxy* proxy, SkBaseDevice* device,
132 const SkIRect& deviceBounds,
133 const Context& ctx) const {
134 SkMatrix inverseCtm;
robertphillipsefbffed2015-06-22 12:06:08 -0700135 if (!ctx.ctm().invert(&inverseCtm)) {
Justin Novosad52340752014-12-02 14:50:56 -0500136 return;
robertphillipsefbffed2015-06-22 12:06:08 -0700137 }
138
Justin Novosad52340752014-12-02 14:50:56 -0500139 SkRect localBounds = SkRect::Make(ctx.clipBounds());
140 inverseCtm.mapRect(&localBounds);
robertphillipsefbffed2015-06-22 12:06:08 -0700141 if (!localBounds.intersect(fCropRect)) {
Justin Novosad52340752014-12-02 14:50:56 -0500142 return;
robertphillipsefbffed2015-06-22 12:06:08 -0700143 }
Justin Novosad52340752014-12-02 14:50:56 -0500144 SkIRect localIBounds = localBounds.roundOut();
145 SkAutoTUnref<SkBaseDevice> localDevice(proxy->createDevice(localIBounds.width(), localIBounds.height()));
146
robertphillipsefbffed2015-06-22 12:06:08 -0700147 SkCanvas localCanvas(localDevice);
Justin Novosad52340752014-12-02 14:50:56 -0500148 localCanvas.translate(-SkIntToScalar(localIBounds.fLeft), -SkIntToScalar(localIBounds.fTop));
149 localCanvas.drawPicture(fPicture);
150
robertphillipsefbffed2015-06-22 12:06:08 -0700151 SkCanvas canvas(device);
Justin Novosad52340752014-12-02 14:50:56 -0500152
153 canvas.translate(-SkIntToScalar(deviceBounds.fLeft), -SkIntToScalar(deviceBounds.fTop));
154 canvas.concat(ctx.ctm());
155 SkPaint paint;
reed93a12152015-03-16 10:08:34 -0700156 paint.setFilterQuality(fFilterQuality);
junovf3c78cc2014-12-09 13:07:22 -0800157 canvas.drawBitmap(localDevice.get()->accessBitmap(false), SkIntToScalar(localIBounds.fLeft),
158 SkIntToScalar(localIBounds.fTop), &paint);
Justin Novosad52340752014-12-02 14:50:56 -0500159}
robertphillipsf3f5bad2014-12-19 13:49:15 -0800160
161#ifndef SK_IGNORE_TO_STRING
162void SkPictureImageFilter::toString(SkString* str) const {
163 str->appendf("SkPictureImageFilter: (");
halcanary9d524f22016-03-29 09:03:52 -0700164 str->appendf("crop: (%f,%f,%f,%f) ",
robertphillipsf3f5bad2014-12-19 13:49:15 -0800165 fCropRect.fLeft, fCropRect.fTop, fCropRect.fRight, fCropRect.fBottom);
166 if (fPicture) {
167 str->appendf("picture: (%f,%f,%f,%f)",
168 fPicture->cullRect().fLeft, fPicture->cullRect().fTop,
169 fPicture->cullRect().fRight, fPicture->cullRect().fBottom);
170 }
171 str->append(")");
172}
173#endif