1 /* 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" 11 #include "SkReadBuffer.h" 12 #include "SkWriteBuffer.h" 13 #include "SkValidationUtils.h" 14 15 SkPictureImageFilter::SkPictureImageFilter(const SkPicture* picture, uint32_t uniqueID) 16 : INHERITED(0, 0, NULL, uniqueID) 17 , fPicture(SkSafeRef(picture)) 18 , fCropRect(picture ? picture->cullRect() : SkRect::MakeEmpty()) { 19 } 20 21 SkPictureImageFilter::SkPictureImageFilter(const SkPicture* picture, const SkRect& cropRect, 22 uint32_t uniqueID) 23 : INHERITED(0, 0, NULL, uniqueID) 24 , fPicture(SkSafeRef(picture)) 25 , fCropRect(cropRect) { 26 } 27 28 SkPictureImageFilter::~SkPictureImageFilter() { 29 SkSafeUnref(fPicture); 30 } 31 32 #ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING 33 SkPictureImageFilter::SkPictureImageFilter(SkReadBuffer& buffer) 34 : INHERITED(0, buffer), 35 fPicture(NULL) { 36 if (!buffer.isCrossProcess()) { 37 if (buffer.readBool()) { 38 fPicture = SkPicture::CreateFromBuffer(buffer); 39 } 40 } else { 41 buffer.validate(!buffer.readBool()); 42 } 43 buffer.readRect(&fCropRect); 44 } 45 #endif 46 47 SkFlattenable* SkPictureImageFilter::CreateProc(SkReadBuffer& buffer) { 48 SkAutoTUnref<SkPicture> picture; 49 SkRect cropRect; 50 51 if (!buffer.isCrossProcess()) { 52 if (buffer.readBool()) { 53 picture.reset(SkPicture::CreateFromBuffer(buffer)); 54 } 55 } else { 56 buffer.validate(!buffer.readBool()); 57 } 58 buffer.readRect(&cropRect); 59 60 return Create(picture, cropRect); 61 } 62 63 void SkPictureImageFilter::flatten(SkWriteBuffer& buffer) const { 64 if (!buffer.isCrossProcess()) { 65 bool hasPicture = (fPicture != NULL); 66 buffer.writeBool(hasPicture); 67 if (hasPicture) { 68 fPicture->flatten(buffer); 69 } 70 } else { 71 buffer.writeBool(false); 72 } 73 buffer.writeRect(fCropRect); 74 } 75 76 bool SkPictureImageFilter::onFilterImage(Proxy* proxy, const SkBitmap&, const Context& ctx, 77 SkBitmap* result, SkIPoint* offset) const { 78 if (!fPicture) { 79 offset->fX = offset->fY = 0; 80 return true; 81 } 82 83 SkRect floatBounds; 84 SkIRect bounds; 85 ctx.ctm().mapRect(&floatBounds, fCropRect); 86 floatBounds.roundOut(&bounds); 87 if (!bounds.intersect(ctx.clipBounds())) { 88 return false; 89 } 90 91 if (bounds.isEmpty()) { 92 offset->fX = offset->fY = 0; 93 return true; 94 } 95 96 SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds.width(), bounds.height())); 97 if (NULL == device.get()) { 98 return false; 99 } 100 101 SkCanvas canvas(device.get()); 102 SkPaint paint; 103 104 canvas.translate(-SkIntToScalar(bounds.fLeft), -SkIntToScalar(bounds.fTop)); 105 canvas.concat(ctx.ctm()); 106 canvas.drawPicture(fPicture); 107 108 *result = device.get()->accessBitmap(false); 109 offset->fX = bounds.fLeft; 110 offset->fY = bounds.fTop; 111 return true; 112 } 113 114 bool SkPictureImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm, 115 SkIRect* dst) const { 116 *dst = src; 117 return true; 118 } 119 120