/*
 * Copyright 2015 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "src/codec/SkCodecImageGenerator.h"

#include "include/codec/SkEncodedOrigin.h"
#include "include/codec/SkPixmapUtils.h"
#include "include/core/SkAlphaType.h"
#include "include/core/SkData.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkPixmap.h"
#include "include/core/SkStream.h"
#include "include/core/SkTypes.h"
#include "src/codec/SkCodecPriv.h"
#include "src/codec/SkPixmapUtilsPriv.h"
#include "src/core/SkStreamPriv.h"

#include <utility>

std::unique_ptr<SkImageGenerator> SkCodecImageGenerator::MakeFromEncodedCodec(
        sk_sp<const SkData> data, std::optional<SkAlphaType> at) {
    auto codec = SkCodec::MakeFromData(data);
    if (codec == nullptr) {
        return nullptr;
    }

    return std::unique_ptr<SkImageGenerator>(new SkCodecImageGenerator(std::move(codec), at));
}

std::unique_ptr<SkImageGenerator> SkCodecImageGenerator::MakeFromCodec(
        std::unique_ptr<SkCodec> codec, std::optional<SkAlphaType> at) {
    return codec ? std::unique_ptr<SkImageGenerator>(
                           new SkCodecImageGenerator(std::move(codec), at))
                 : nullptr;
}

static SkImageInfo adjust_info(SkCodec* codec, std::optional<SkAlphaType> at) {
    SkASSERT(at != kOpaque_SkAlphaType);
    SkImageInfo info = codec->getInfo();
    if (at.has_value()) {
        // If a specific alpha type was requested, use that.
        info = info.makeAlphaType(*at);
    } else if (kUnpremul_SkAlphaType == info.alphaType()) {
        // Otherwise, prefer premul over unpremul (this produces better filtering in general)
        info = info.makeAlphaType(kPremul_SkAlphaType);
    }
    if (SkEncodedOriginSwapsWidthHeight(codec->getOrigin())) {
        info = SkPixmapUtils::SwapWidthHeight(info);
    }
    return info;
}

SkCodecImageGenerator::SkCodecImageGenerator(std::unique_ptr<SkCodec> codec,
                                             std::optional<SkAlphaType> at)
        : SkImageGenerator(adjust_info(codec.get(), at)), fCodec(std::move(codec)) {}

sk_sp<const SkData> SkCodecImageGenerator::onRefEncodedData() {
    SkASSERT(fCodec);
    if (!fCachedData) {
        fCachedData = SkCodecPriv::GetEncodedData(fCodec.get());
    }
    return fCachedData;
}

bool SkCodecImageGenerator::getPixels(const SkImageInfo& info, void* pixels, size_t rowBytes, const SkCodec::Options* options) {
    SkPixmap dst(info, pixels, rowBytes);

    auto decode = [this, options](const SkPixmap& pm) {
        SkCodec::Result result = fCodec->getPixels(pm, options);
        switch (result) {
            case SkCodec::kSuccess:
            case SkCodec::kIncompleteInput:
            case SkCodec::kErrorInInput:
                return true;
            default:
                return false;
        }
    };

    return SkPixmapUtils::Orient(dst, fCodec->getOrigin(), decode);
}

bool SkCodecImageGenerator::onGetPixels(const SkImageInfo& requestInfo, void* requestPixels,
                                        size_t requestRowBytes, const Options& options) {
    return this->getPixels(requestInfo, requestPixels, requestRowBytes, nullptr);
}

bool SkCodecImageGenerator::onQueryYUVAInfo(
        const SkYUVAPixmapInfo::SupportedDataTypes& supportedDataTypes,
        SkYUVAPixmapInfo* yuvaPixmapInfo) const {
    return fCodec->queryYUVAInfo(supportedDataTypes, yuvaPixmapInfo);
}

bool SkCodecImageGenerator::onGetYUVAPlanes(const SkYUVAPixmaps& yuvaPixmaps) {
    switch (fCodec->getYUVAPlanes(yuvaPixmaps)) {
        case SkCodec::kSuccess:
        case SkCodec::kIncompleteInput:
        case SkCodec::kErrorInInput:
            return true;
        default:
            return false;
    }
}

SkISize SkCodecImageGenerator::getScaledDimensions(float desiredScale) const {
    SkISize size = fCodec->getScaledDimensions(desiredScale);
    if (SkEncodedOriginSwapsWidthHeight(fCodec->getOrigin())) {
        std::swap(size.fWidth, size.fHeight);
    }
    return size;
}
