Home | History | Annotate | Download | only in effects
      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