blob: 14c14bb1762f4785e04819d91a10ca1053dd2c0a [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
senorblanco24e06d52015-03-18 12:11:33 -070016SkPictureImageFilter::SkPictureImageFilter(const SkPicture* picture)
halcanary96fcdcc2015-08-27 07:41:13 -070017 : INHERITED(0, 0, nullptr)
robertphillipsa8d7f0b2014-08-29 08:03:56 -070018 , fPicture(SkSafeRef(picture))
Justin Novosad52340752014-12-02 14:50:56 -050019 , fCropRect(picture ? picture->cullRect() : SkRect::MakeEmpty())
junovf3c78cc2014-12-09 13:07:22 -080020 , fPictureResolution(kDeviceSpace_PictureResolution)
reed93a12152015-03-16 10:08:34 -070021 , fFilterQuality(kLow_SkFilterQuality) {
senorblanco@chromium.org53333002013-12-12 23:28:52 +000022}
23
senorblanco5e5f9482014-08-26 12:27:12 -070024SkPictureImageFilter::SkPictureImageFilter(const SkPicture* picture, const SkRect& cropRect,
senorblanco24e06d52015-03-18 12:11:33 -070025 PictureResolution pictureResolution,
reed93a12152015-03-16 10:08:34 -070026 SkFilterQuality filterQuality)
halcanary96fcdcc2015-08-27 07:41:13 -070027 : INHERITED(0, 0, nullptr)
robertphillipsa8d7f0b2014-08-29 08:03:56 -070028 , fPicture(SkSafeRef(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
34SkPictureImageFilter::~SkPictureImageFilter() {
35 SkSafeUnref(fPicture);
36}
37
reed9fa60da2014-08-21 07:59:51 -070038SkFlattenable* SkPictureImageFilter::CreateProc(SkReadBuffer& buffer) {
reedca2622b2016-03-18 07:25:55 -070039 sk_sp<SkPicture> picture;
reed9fa60da2014-08-21 07:59:51 -070040 SkRect cropRect;
41
hendrikw446ee672015-06-16 09:28:37 -070042 if (buffer.isCrossProcess() && SkPicture::PictureIOSecurityPrecautionsEnabled()) {
robertphillipsc4bd39c2015-01-06 09:17:02 -080043 buffer.validate(!buffer.readBool());
hendrikw446ee672015-06-16 09:28:37 -070044 } else {
reed9fa60da2014-08-21 07:59:51 -070045 if (buffer.readBool()) {
reedca2622b2016-03-18 07:25:55 -070046 picture = SkPicture::MakeFromBuffer(buffer);
reed9fa60da2014-08-21 07:59:51 -070047 }
reed9fa60da2014-08-21 07:59:51 -070048 }
49 buffer.readRect(&cropRect);
Justin Novosad52340752014-12-02 14:50:56 -050050 PictureResolution pictureResolution;
51 if (buffer.isVersionLT(SkReadBuffer::kPictureImageFilterResolution_Version)) {
52 pictureResolution = kDeviceSpace_PictureResolution;
53 } else {
54 pictureResolution = (PictureResolution)buffer.readInt();
junovf3c78cc2014-12-09 13:07:22 -080055 }
reed9fa60da2014-08-21 07:59:51 -070056
junovf3c78cc2014-12-09 13:07:22 -080057 if (kLocalSpace_PictureResolution == pictureResolution) {
58 //filterLevel is only serialized if pictureResolution is LocalSpace
reed93a12152015-03-16 10:08:34 -070059 SkFilterQuality filterQuality;
junovf3c78cc2014-12-09 13:07:22 -080060 if (buffer.isVersionLT(SkReadBuffer::kPictureImageFilterLevel_Version)) {
reed93a12152015-03-16 10:08:34 -070061 filterQuality = kLow_SkFilterQuality;
junovf3c78cc2014-12-09 13:07:22 -080062 } else {
reed93a12152015-03-16 10:08:34 -070063 filterQuality = (SkFilterQuality)buffer.readInt();
junovf3c78cc2014-12-09 13:07:22 -080064 }
reedca2622b2016-03-18 07:25:55 -070065 return CreateForLocalSpace(picture.get(), cropRect, filterQuality);
Justin Novosad52340752014-12-02 14:50:56 -050066 }
reedca2622b2016-03-18 07:25:55 -070067 return Create(picture.get(), cropRect);
reed9fa60da2014-08-21 07:59:51 -070068}
senorblanco@chromium.org53333002013-12-12 23:28:52 +000069
commit-bot@chromium.org8b0e8ac2014-01-30 18:58:24 +000070void SkPictureImageFilter::flatten(SkWriteBuffer& buffer) const {
hendrikw446ee672015-06-16 09:28:37 -070071 if (buffer.isCrossProcess() && SkPicture::PictureIOSecurityPrecautionsEnabled()) {
robertphillipsc4bd39c2015-01-06 09:17:02 -080072 buffer.writeBool(false);
hendrikw446ee672015-06-16 09:28:37 -070073 } else {
halcanary96fcdcc2015-08-27 07:41:13 -070074 bool hasPicture = (fPicture != nullptr);
senorblanco@chromium.org97f5fc62014-05-30 20:50:56 +000075 buffer.writeBool(hasPicture);
76 if (hasPicture) {
77 fPicture->flatten(buffer);
78 }
commit-bot@chromium.org5e0995e2014-02-07 12:20:04 +000079 }
commit-bot@chromium.orgcac5fd52014-03-10 10:51:58 +000080 buffer.writeRect(fCropRect);
Justin Novosad52340752014-12-02 14:50:56 -050081 buffer.writeInt(fPictureResolution);
junovf3c78cc2014-12-09 13:07:22 -080082 if (kLocalSpace_PictureResolution == fPictureResolution) {
reed93a12152015-03-16 10:08:34 -070083 buffer.writeInt(fFilterQuality);
junovf3c78cc2014-12-09 13:07:22 -080084 }
senorblanco@chromium.org53333002013-12-12 23:28:52 +000085}
86
robertphillips48e78462016-02-17 13:57:16 -080087bool SkPictureImageFilter::onFilterImageDeprecated(Proxy* proxy, const SkBitmap&,
88 const Context& ctx,
89 SkBitmap* result, SkIPoint* offset) const {
senorblanco@chromium.org53333002013-12-12 23:28:52 +000090 if (!fPicture) {
senorblanco@chromium.org6776b822014-01-03 21:48:22 +000091 offset->fX = offset->fY = 0;
senorblanco@chromium.org53333002013-12-12 23:28:52 +000092 return true;
93 }
94
95 SkRect floatBounds;
senorblanco@chromium.org4cb543d2014-03-14 15:44:01 +000096 ctx.ctm().mapRect(&floatBounds, fCropRect);
reedb07a94f2014-11-19 05:03:18 -080097 SkIRect bounds = floatBounds.roundOut();
senorblanco3d822c22014-07-30 14:49:31 -070098 if (!bounds.intersect(ctx.clipBounds())) {
99 return false;
100 }
senorblanco@chromium.org53333002013-12-12 23:28:52 +0000101
102 if (bounds.isEmpty()) {
senorblanco@chromium.org6776b822014-01-03 21:48:22 +0000103 offset->fX = offset->fY = 0;
senorblanco@chromium.org53333002013-12-12 23:28:52 +0000104 return true;
105 }
106
107 SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds.width(), bounds.height()));
halcanary96fcdcc2015-08-27 07:41:13 -0700108 if (nullptr == device.get()) {
senorblanco@chromium.org53333002013-12-12 23:28:52 +0000109 return false;
110 }
111
junovf3c78cc2014-12-09 13:07:22 -0800112 if (kDeviceSpace_PictureResolution == fPictureResolution ||
113 0 == (ctx.ctm().getType() & ~SkMatrix::kTranslate_Mask)) {
robertphillipsefbffed2015-06-22 12:06:08 -0700114 this->drawPictureAtDeviceResolution(device.get(), bounds, ctx);
Justin Novosad52340752014-12-02 14:50:56 -0500115 } else {
robertphillipsefbffed2015-06-22 12:06:08 -0700116 this->drawPictureAtLocalResolution(proxy, device.get(), bounds, ctx);
Justin Novosad52340752014-12-02 14:50:56 -0500117 }
senorblanco@chromium.org53333002013-12-12 23:28:52 +0000118
119 *result = device.get()->accessBitmap(false);
senorblanco@chromium.org6776b822014-01-03 21:48:22 +0000120 offset->fX = bounds.fLeft;
121 offset->fY = bounds.fTop;
senorblanco@chromium.org53333002013-12-12 23:28:52 +0000122 return true;
123}
Justin Novosad52340752014-12-02 14:50:56 -0500124
robertphillipsefbffed2015-06-22 12:06:08 -0700125void SkPictureImageFilter::drawPictureAtDeviceResolution(SkBaseDevice* device,
Justin Novosad52340752014-12-02 14:50:56 -0500126 const SkIRect& deviceBounds,
127 const Context& ctx) const {
robertphillipsefbffed2015-06-22 12:06:08 -0700128 SkCanvas canvas(device);
Justin Novosad52340752014-12-02 14:50:56 -0500129
130 canvas.translate(-SkIntToScalar(deviceBounds.fLeft), -SkIntToScalar(deviceBounds.fTop));
131 canvas.concat(ctx.ctm());
132 canvas.drawPicture(fPicture);
133}
134
135void SkPictureImageFilter::drawPictureAtLocalResolution(Proxy* proxy, SkBaseDevice* device,
136 const SkIRect& deviceBounds,
137 const Context& ctx) const {
138 SkMatrix inverseCtm;
robertphillipsefbffed2015-06-22 12:06:08 -0700139 if (!ctx.ctm().invert(&inverseCtm)) {
Justin Novosad52340752014-12-02 14:50:56 -0500140 return;
robertphillipsefbffed2015-06-22 12:06:08 -0700141 }
142
Justin Novosad52340752014-12-02 14:50:56 -0500143 SkRect localBounds = SkRect::Make(ctx.clipBounds());
144 inverseCtm.mapRect(&localBounds);
robertphillipsefbffed2015-06-22 12:06:08 -0700145 if (!localBounds.intersect(fCropRect)) {
Justin Novosad52340752014-12-02 14:50:56 -0500146 return;
robertphillipsefbffed2015-06-22 12:06:08 -0700147 }
Justin Novosad52340752014-12-02 14:50:56 -0500148 SkIRect localIBounds = localBounds.roundOut();
149 SkAutoTUnref<SkBaseDevice> localDevice(proxy->createDevice(localIBounds.width(), localIBounds.height()));
150
robertphillipsefbffed2015-06-22 12:06:08 -0700151 SkCanvas localCanvas(localDevice);
Justin Novosad52340752014-12-02 14:50:56 -0500152 localCanvas.translate(-SkIntToScalar(localIBounds.fLeft), -SkIntToScalar(localIBounds.fTop));
153 localCanvas.drawPicture(fPicture);
154
robertphillipsefbffed2015-06-22 12:06:08 -0700155 SkCanvas canvas(device);
Justin Novosad52340752014-12-02 14:50:56 -0500156
157 canvas.translate(-SkIntToScalar(deviceBounds.fLeft), -SkIntToScalar(deviceBounds.fTop));
158 canvas.concat(ctx.ctm());
159 SkPaint paint;
reed93a12152015-03-16 10:08:34 -0700160 paint.setFilterQuality(fFilterQuality);
junovf3c78cc2014-12-09 13:07:22 -0800161 canvas.drawBitmap(localDevice.get()->accessBitmap(false), SkIntToScalar(localIBounds.fLeft),
162 SkIntToScalar(localIBounds.fTop), &paint);
Justin Novosad52340752014-12-02 14:50:56 -0500163}
robertphillipsf3f5bad2014-12-19 13:49:15 -0800164
165#ifndef SK_IGNORE_TO_STRING
166void SkPictureImageFilter::toString(SkString* str) const {
167 str->appendf("SkPictureImageFilter: (");
168 str->appendf("crop: (%f,%f,%f,%f) ",
169 fCropRect.fLeft, fCropRect.fTop, fCropRect.fRight, fCropRect.fBottom);
170 if (fPicture) {
171 str->appendf("picture: (%f,%f,%f,%f)",
172 fPicture->cullRect().fLeft, fPicture->cullRect().fTop,
173 fPicture->cullRect().fRight, fPicture->cullRect().fBottom);
174 }
175 str->append(")");
176}
177#endif