/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "Picture.h"
#include "SkStream.h"

#include <memory>
#include <hwui/Canvas.h>

namespace android {

Picture::Picture(const Picture* src) {
    if (NULL != src) {
        mWidth = src->width();
        mHeight = src->height();
        if (NULL != src->mPicture.get()) {
            mPicture = src->mPicture;
        } else if (NULL != src->mRecorder.get()) {
            mPicture = src->makePartialCopy();
        }
    } else {
        mWidth = 0;
        mHeight = 0;
    }
}

Picture::Picture(sk_sp<SkPicture>&& src) {
    mPicture = std::move(src);
    mWidth = 0;
    mHeight = 0;
}

Canvas* Picture::beginRecording(int width, int height) {
    mPicture.reset(NULL);
    mRecorder.reset(new SkPictureRecorder);
    mWidth = width;
    mHeight = height;
    SkCanvas* canvas = mRecorder->beginRecording(SkIntToScalar(width), SkIntToScalar(height));
    return Canvas::create_canvas(canvas);
}

void Picture::endRecording() {
    if (NULL != mRecorder.get()) {
        mPicture = mRecorder->finishRecordingAsPicture();
        mRecorder.reset(NULL);
    }
}

int Picture::width() const {
    return mWidth;
}

int Picture::height() const {
    return mHeight;
}

Picture* Picture::CreateFromStream(SkStream* stream) {
    Picture* newPict = new Picture;

    sk_sp<SkPicture> skPicture = SkPicture::MakeFromStream(stream);
    if (NULL != skPicture) {
        newPict->mPicture = skPicture;

        const SkIRect cullRect = skPicture->cullRect().roundOut();
        newPict->mWidth = cullRect.width();
        newPict->mHeight = cullRect.height();
    }

    return newPict;
}

void Picture::serialize(SkWStream* stream) const {
    if (NULL != mRecorder.get()) {
        this->makePartialCopy()->serialize(stream);
    } else if (NULL != mPicture.get()) {
        mPicture->serialize(stream);
    } else {
        // serialize "empty" picture
        SkPictureRecorder recorder;
        recorder.beginRecording(0, 0);
        recorder.finishRecordingAsPicture()->serialize(stream);
    }
}

void Picture::draw(Canvas* canvas) {
    if (NULL != mRecorder.get()) {
        this->endRecording();
        SkASSERT(NULL != mPicture.get());
    }

    if (mPicture) {
        canvas->drawPicture(*mPicture);
    }
}

sk_sp<SkPicture> Picture::makePartialCopy() const {
    SkASSERT(NULL != mRecorder.get());

    SkPictureRecorder reRecorder;

    SkCanvas* canvas = reRecorder.beginRecording(mWidth, mHeight);
    mRecorder->partialReplay(canvas);
    return reRecorder.finishRecordingAsPicture();
}

}; // namespace android
