/*
 * Copyright 2013 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkPictureImageFilter.h"
#include "SkDevice.h"
#include "SkCanvas.h"
#include "SkReadBuffer.h"
#include "SkWriteBuffer.h"
#include "SkValidationUtils.h"

SkPictureImageFilter::SkPictureImageFilter(const SkPicture* picture, uint32_t uniqueID)
  : INHERITED(0, 0, NULL, uniqueID),
    fPicture(picture),
    fCropRect(SkRect::MakeWH(picture ? SkIntToScalar(picture->width()) : 0,
                             picture ? SkIntToScalar(picture->height()) : 0)) {
    SkSafeRef(fPicture);
}

SkPictureImageFilter::SkPictureImageFilter(const SkPicture* picture, const SkRect& cropRect,
                                           uint32_t uniqueID)
  : INHERITED(0, 0, NULL, uniqueID),
    fPicture(picture),
    fCropRect(cropRect) {
    SkSafeRef(fPicture);
}

SkPictureImageFilter::~SkPictureImageFilter() {
    SkSafeUnref(fPicture);
}

#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
SkPictureImageFilter::SkPictureImageFilter(SkReadBuffer& buffer)
  : INHERITED(0, buffer),
    fPicture(NULL) {
    if (!buffer.isCrossProcess()) {
        if (buffer.readBool()) {
            fPicture = SkPicture::CreateFromBuffer(buffer);
        }
    } else {
        buffer.validate(!buffer.readBool());
    }
    buffer.readRect(&fCropRect);
}
#endif

SkFlattenable* SkPictureImageFilter::CreateProc(SkReadBuffer& buffer) {
    SkAutoTUnref<SkPicture> picture;
    SkRect cropRect;

    if (!buffer.isCrossProcess()) {
        if (buffer.readBool()) {
            picture.reset(SkPicture::CreateFromBuffer(buffer));
        }
    } else {
        buffer.validate(!buffer.readBool());
    }
    buffer.readRect(&cropRect);

    return Create(picture, cropRect);
}

void SkPictureImageFilter::flatten(SkWriteBuffer& buffer) const {
    if (!buffer.isCrossProcess()) {
        bool hasPicture = (fPicture != NULL);
        buffer.writeBool(hasPicture);
        if (hasPicture) {
            fPicture->flatten(buffer);
        }
    } else {
        buffer.writeBool(false);
    }
    buffer.writeRect(fCropRect);
}

bool SkPictureImageFilter::onFilterImage(Proxy* proxy, const SkBitmap&, const Context& ctx,
                                         SkBitmap* result, SkIPoint* offset) const {
    if (!fPicture) {
        offset->fX = offset->fY = 0;
        return true;
    }

    SkRect floatBounds;
    SkIRect bounds;
    ctx.ctm().mapRect(&floatBounds, fCropRect);
    floatBounds.roundOut(&bounds);
    if (!bounds.intersect(ctx.clipBounds())) {
        return false;
    }

    if (bounds.isEmpty()) {
        offset->fX = offset->fY = 0;
        return true;
    }

    SkAutoTUnref<SkBaseDevice> device(proxy->createDevice(bounds.width(), bounds.height()));
    if (NULL == device.get()) {
        return false;
    }

    SkCanvas canvas(device.get());
    SkPaint paint;

    canvas.translate(-SkIntToScalar(bounds.fLeft), -SkIntToScalar(bounds.fTop));
    canvas.concat(ctx.ctm());
    canvas.drawPicture(fPicture);

    *result = device.get()->accessBitmap(false);
    offset->fX = bounds.fLeft;
    offset->fY = bounds.fTop;
    return true;
}

bool SkPictureImageFilter::onFilterBounds(const SkIRect& src, const SkMatrix& ctm,
                                          SkIRect* dst) const {
    *dst = src;
    return true;
}

