1533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org/* 2533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org * Copyright 2013 The Android Open Source Project 3533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org * 4533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org * Use of this source code is governed by a BSD-style license that can be 5533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org * found in the LICENSE file. 6533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org */ 7533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org 8533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org#include "SkPictureImageFilter.h" 9533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org#include "SkDevice.h" 10533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org#include "SkCanvas.h" 118b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkReadBuffer.h" 122d97bc139a7de5813468bd3dbfd0037351ae5606fmalita#include "SkSurfaceProps.h" 138b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.org#include "SkWriteBuffer.h" 14533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org#include "SkValidationUtils.h" 15533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org 1624e06d5244ae96e440410e1d76e039983b2efac9senorblancoSkPictureImageFilter::SkPictureImageFilter(const SkPicture* picture) 1724e06d5244ae96e440410e1d76e039983b2efac9senorblanco : INHERITED(0, 0, NULL) 18a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips , fPicture(SkSafeRef(picture)) 195234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad , fCropRect(picture ? picture->cullRect() : SkRect::MakeEmpty()) 20f3c78ccf5694d22d2e4a7061a80399a7e69b59dbjunov , fPictureResolution(kDeviceSpace_PictureResolution) 2193a1215fe0ab007ce941c721f1fd3e9dcb5d4754reed , fFilterQuality(kLow_SkFilterQuality) { 22533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org} 23533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org 245e5f948b6b363dbfc8c076d8ff0c6b8e9ea99958senorblancoSkPictureImageFilter::SkPictureImageFilter(const SkPicture* picture, const SkRect& cropRect, 2524e06d5244ae96e440410e1d76e039983b2efac9senorblanco PictureResolution pictureResolution, 2693a1215fe0ab007ce941c721f1fd3e9dcb5d4754reed SkFilterQuality filterQuality) 2724e06d5244ae96e440410e1d76e039983b2efac9senorblanco : INHERITED(0, 0, NULL) 28a8d7f0b13cd4c6d773fcf055fe17db75d260fa05robertphillips , fPicture(SkSafeRef(picture)) 295234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad , fCropRect(cropRect) 30f3c78ccf5694d22d2e4a7061a80399a7e69b59dbjunov , fPictureResolution(pictureResolution) 3193a1215fe0ab007ce941c721f1fd3e9dcb5d4754reed , fFilterQuality(filterQuality) { 32533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org} 33533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org 34533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.orgSkPictureImageFilter::~SkPictureImageFilter() { 35533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org SkSafeUnref(fPicture); 36533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org} 37533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org 389fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reedSkFlattenable* SkPictureImageFilter::CreateProc(SkReadBuffer& buffer) { 399fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed SkAutoTUnref<SkPicture> picture; 409fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed SkRect cropRect; 419fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed 42c4bd39c903cc5da16f50d711063b01723b59281crobertphillips#ifdef SK_DISALLOW_CROSSPROCESS_PICTUREIMAGEFILTERS 43c4bd39c903cc5da16f50d711063b01723b59281crobertphillips if (buffer.isCrossProcess()) { 44c4bd39c903cc5da16f50d711063b01723b59281crobertphillips buffer.validate(!buffer.readBool()); 45c4bd39c903cc5da16f50d711063b01723b59281crobertphillips } else 46c4bd39c903cc5da16f50d711063b01723b59281crobertphillips#endif 47c4bd39c903cc5da16f50d711063b01723b59281crobertphillips { 489fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed if (buffer.readBool()) { 499fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed picture.reset(SkPicture::CreateFromBuffer(buffer)); 509fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed } 519fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed } 529fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed buffer.readRect(&cropRect); 535234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad PictureResolution pictureResolution; 545234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad if (buffer.isVersionLT(SkReadBuffer::kPictureImageFilterResolution_Version)) { 555234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad pictureResolution = kDeviceSpace_PictureResolution; 565234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad } else { 575234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad pictureResolution = (PictureResolution)buffer.readInt(); 58f3c78ccf5694d22d2e4a7061a80399a7e69b59dbjunov } 59f3c78ccf5694d22d2e4a7061a80399a7e69b59dbjunov 60f3c78ccf5694d22d2e4a7061a80399a7e69b59dbjunov if (kLocalSpace_PictureResolution == pictureResolution) { 61f3c78ccf5694d22d2e4a7061a80399a7e69b59dbjunov //filterLevel is only serialized if pictureResolution is LocalSpace 6293a1215fe0ab007ce941c721f1fd3e9dcb5d4754reed SkFilterQuality filterQuality; 63f3c78ccf5694d22d2e4a7061a80399a7e69b59dbjunov if (buffer.isVersionLT(SkReadBuffer::kPictureImageFilterLevel_Version)) { 6493a1215fe0ab007ce941c721f1fd3e9dcb5d4754reed filterQuality = kLow_SkFilterQuality; 65f3c78ccf5694d22d2e4a7061a80399a7e69b59dbjunov } else { 6693a1215fe0ab007ce941c721f1fd3e9dcb5d4754reed filterQuality = (SkFilterQuality)buffer.readInt(); 67f3c78ccf5694d22d2e4a7061a80399a7e69b59dbjunov } 6893a1215fe0ab007ce941c721f1fd3e9dcb5d4754reed return CreateForLocalSpace(picture, cropRect, filterQuality); 695234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad } 709fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed return Create(picture, cropRect); 719fa60daad4d5f54c0dbe3dbcc7608a8f6d721187reed} 72533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org 738b0e8ac5f582de80356019406e2975079bf0829dcommit-bot@chromium.orgvoid SkPictureImageFilter::flatten(SkWriteBuffer& buffer) const { 74c4bd39c903cc5da16f50d711063b01723b59281crobertphillips#ifdef SK_DISALLOW_CROSSPROCESS_PICTUREIMAGEFILTERS 75c4bd39c903cc5da16f50d711063b01723b59281crobertphillips if (buffer.isCrossProcess()) { 76c4bd39c903cc5da16f50d711063b01723b59281crobertphillips buffer.writeBool(false); 77c4bd39c903cc5da16f50d711063b01723b59281crobertphillips } else 78c4bd39c903cc5da16f50d711063b01723b59281crobertphillips#endif 79c4bd39c903cc5da16f50d711063b01723b59281crobertphillips { 8097f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org bool hasPicture = (fPicture != NULL); 8197f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org buffer.writeBool(hasPicture); 8297f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org if (hasPicture) { 8397f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org fPicture->flatten(buffer); 8497f5fc651956287e78e35934cf62b9e1b45b4f6csenorblanco@chromium.org } 855e0995e4b36178e1e4465a9f50114ed39f038c27commit-bot@chromium.org } 86cac5fd597f6e2495f50aaa6bcbe3dadc56f0b977commit-bot@chromium.org buffer.writeRect(fCropRect); 875234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad buffer.writeInt(fPictureResolution); 88f3c78ccf5694d22d2e4a7061a80399a7e69b59dbjunov if (kLocalSpace_PictureResolution == fPictureResolution) { 8993a1215fe0ab007ce941c721f1fd3e9dcb5d4754reed buffer.writeInt(fFilterQuality); 90f3c78ccf5694d22d2e4a7061a80399a7e69b59dbjunov } 91533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org} 92533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org 934cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.orgbool SkPictureImageFilter::onFilterImage(Proxy* proxy, const SkBitmap&, const Context& ctx, 944cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org SkBitmap* result, SkIPoint* offset) const { 95533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org if (!fPicture) { 966776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org offset->fX = offset->fY = 0; 97533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org return true; 98533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org } 99533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org 100533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org SkRect floatBounds; 1014cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org ctx.ctm().mapRect(&floatBounds, fCropRect); 102b07a94f1cba3976596ae1a7f23d8c2043ba353f3reed SkIRect bounds = floatBounds.roundOut(); 1033d822c29d4272a6749e59801b202b1ed6d611be8senorblanco if (!bounds.intersect(ctx.clipBounds())) { 1043d822c29d4272a6749e59801b202b1ed6d611be8senorblanco return false; 1053d822c29d4272a6749e59801b202b1ed6d611be8senorblanco } 106533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org 107533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org if (bounds.isEmpty()) { 1086776b82d466fa93ccffd251fdf556fe058395444senorblanco@chromium.org offset->fX = offset->fY = 0; 109533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org return true; 110533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org } 111533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org 112533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds.width(), bounds.height())); 113533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org if (NULL == device.get()) { 114533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org return false; 115533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org } 116533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org 117f3c78ccf5694d22d2e4a7061a80399a7e69b59dbjunov if (kDeviceSpace_PictureResolution == fPictureResolution || 118f3c78ccf5694d22d2e4a7061a80399a7e69b59dbjunov 0 == (ctx.ctm().getType() & ~SkMatrix::kTranslate_Mask)) { 119f3c78ccf5694d22d2e4a7061a80399a7e69b59dbjunov drawPictureAtDeviceResolution(proxy, device.get(), bounds, ctx); 1205234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad } else { 121f3c78ccf5694d22d2e4a7061a80399a7e69b59dbjunov drawPictureAtLocalResolution(proxy, device.get(), bounds, ctx); 1225234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad } 1235234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad 1245234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad *result = device.get()->accessBitmap(false); 1255234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad offset->fX = bounds.fLeft; 1265234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad offset->fY = bounds.fTop; 1275234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad return true; 1285234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad} 1295234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad 1305234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosadvoid SkPictureImageFilter::drawPictureAtDeviceResolution(Proxy* proxy, SkBaseDevice* device, 1315234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad const SkIRect& deviceBounds, 1325234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad const Context& ctx) const { 1332d97bc139a7de5813468bd3dbfd0037351ae5606fmalita // Pass explicit surface props, as the simplified canvas constructor discards device properties. 1342d97bc139a7de5813468bd3dbfd0037351ae5606fmalita // FIXME: switch back to the public constructor (and unfriend) after 1352d97bc139a7de5813468bd3dbfd0037351ae5606fmalita // https://code.google.com/p/skia/issues/detail?id=3142 is fixed. 1365234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad SkCanvas canvas(device, proxy->surfaceProps(), SkCanvas::kDefault_InitFlags); 137533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org 1385234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad canvas.translate(-SkIntToScalar(deviceBounds.fLeft), -SkIntToScalar(deviceBounds.fTop)); 1394cb543d6057b692e1099e9f115155f0bf323a0c8senorblanco@chromium.org canvas.concat(ctx.ctm()); 1409b14f26d0f3a974f3dd626c8354e1db1cfcd322frobertphillips canvas.drawPicture(fPicture); 1415234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad} 142533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org 1435234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosadvoid SkPictureImageFilter::drawPictureAtLocalResolution(Proxy* proxy, SkBaseDevice* device, 1445234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad const SkIRect& deviceBounds, 1455234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad const Context& ctx) const { 1465234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad SkMatrix inverseCtm; 1475234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad if (!ctx.ctm().invert(&inverseCtm)) 1485234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad return; 1495234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad SkRect localBounds = SkRect::Make(ctx.clipBounds()); 1505234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad inverseCtm.mapRect(&localBounds); 1515234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad if (!localBounds.intersect(fCropRect)) 1525234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad return; 1535234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad SkIRect localIBounds = localBounds.roundOut(); 1545234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad SkAutoTUnref<SkBaseDevice> localDevice(proxy->createDevice(localIBounds.width(), localIBounds.height())); 1555234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad 1565234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad // Pass explicit surface props, as the simplified canvas constructor discards device properties. 1575234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad // FIXME: switch back to the public constructor (and unfriend) after 1585234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad // https://code.google.com/p/skia/issues/detail?id=3142 is fixed. 1595234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad SkCanvas localCanvas(localDevice, proxy->surfaceProps(), SkCanvas::kDefault_InitFlags); 1605234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad localCanvas.translate(-SkIntToScalar(localIBounds.fLeft), -SkIntToScalar(localIBounds.fTop)); 1615234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad localCanvas.drawPicture(fPicture); 1625234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad 1635234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad // Pass explicit surface props, as the simplified canvas constructor discards device properties. 1645234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad // FIXME: switch back to the public constructor (and unfriend) after 1655234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad // https://code.google.com/p/skia/issues/detail?id=3142 is fixed. 1665234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad SkCanvas canvas(device, proxy->surfaceProps(), SkCanvas::kDefault_InitFlags); 1675234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad 1685234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad canvas.translate(-SkIntToScalar(deviceBounds.fLeft), -SkIntToScalar(deviceBounds.fTop)); 1695234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad canvas.concat(ctx.ctm()); 1705234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad SkPaint paint; 17193a1215fe0ab007ce941c721f1fd3e9dcb5d4754reed paint.setFilterQuality(fFilterQuality); 172f3c78ccf5694d22d2e4a7061a80399a7e69b59dbjunov canvas.drawBitmap(localDevice.get()->accessBitmap(false), SkIntToScalar(localIBounds.fLeft), 173f3c78ccf5694d22d2e4a7061a80399a7e69b59dbjunov SkIntToScalar(localIBounds.fTop), &paint); 1745234075b1c6bcada4ad17ed5a83bfcb53df66b7fJustin Novosad //canvas.drawPicture(fPicture); 175533330065a28b51808e5bf564ae45e56f8d9956asenorblanco@chromium.org} 176f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips 177f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips#ifndef SK_IGNORE_TO_STRING 178f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillipsvoid SkPictureImageFilter::toString(SkString* str) const { 179f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips str->appendf("SkPictureImageFilter: ("); 180f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips str->appendf("crop: (%f,%f,%f,%f) ", 181f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips fCropRect.fLeft, fCropRect.fTop, fCropRect.fRight, fCropRect.fBottom); 182f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips if (fPicture) { 183f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips str->appendf("picture: (%f,%f,%f,%f)", 184f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips fPicture->cullRect().fLeft, fPicture->cullRect().fTop, 185f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips fPicture->cullRect().fRight, fPicture->cullRect().fBottom); 186f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips } 187f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips str->append(")"); 188f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips} 189f3f5bad7ded35265c0b5d042cc4174386b197a33robertphillips#endif 190