/*
 * 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 "client_utils/android/BitmapRegionDecoder.h"
#include "client_utils/android/BitmapRegionDecoderPriv.h"
#include "include/codec/SkAndroidCodec.h"
#include "src/codec/SkCodecPriv.h"

namespace android {
namespace skia {

std::unique_ptr<BitmapRegionDecoder> BitmapRegionDecoder::Make(sk_sp<SkData> data) {
    auto codec = SkAndroidCodec::MakeFromData(std::move(data));
    if (nullptr == codec) {
        SkCodecPrintf("Error: Failed to create codec.\n");
        return nullptr;
    }

    switch (codec->getEncodedFormat()) {
        case SkEncodedImageFormat::kJPEG:
        case SkEncodedImageFormat::kPNG:
        case SkEncodedImageFormat::kWEBP:
        case SkEncodedImageFormat::kHEIF:
            break;
        default:
            return nullptr;
    }

    return std::unique_ptr<BitmapRegionDecoder>(new BitmapRegionDecoder(std::move(codec)));
}

BitmapRegionDecoder::BitmapRegionDecoder(std::unique_ptr<SkAndroidCodec> codec)
    : fCodec(std::move(codec))
{}

int BitmapRegionDecoder::width() const {
    return fCodec->getInfo().width();
}

int BitmapRegionDecoder::height() const {
    return fCodec->getInfo().height();
}

bool BitmapRegionDecoder::decodeRegion(SkBitmap* bitmap, BRDAllocator* allocator,
        const SkIRect& desiredSubset, int sampleSize, SkColorType dstColorType,
        bool requireUnpremul, sk_sp<SkColorSpace> dstColorSpace) {

    // Fix the input sampleSize if necessary.
    if (sampleSize < 1) {
        sampleSize = 1;
    }

    // The size of the output bitmap is determined by the size of the
    // requested subset, not by the size of the intersection of the subset
    // and the image dimensions.
    // If inputX is negative, we will need to place decoded pixels into the
    // output bitmap starting at a left offset.  Call this outX.
    // If outX is non-zero, subsetX must be zero.
    // If inputY is negative, we will need to place decoded pixels into the
    // output bitmap starting at a top offset.  Call this outY.
    // If outY is non-zero, subsetY must be zero.
    int outX;
    int outY;
    SkIRect subset = desiredSubset;
    SubsetType type = adjust_subset_rect(fCodec->getInfo().dimensions(), &subset, &outX, &outY);
    if (SubsetType::kOutside_SubsetType == type) {
        return false;
    }

    // Ask the codec for a scaled subset
    if (!fCodec->getSupportedSubset(&subset)) {
        SkCodecPrintf("Error: Could not get subset.\n");
        return false;
    }
    SkISize scaledSize = fCodec->getSampledSubsetDimensions(sampleSize, subset);

    // Create the image info for the decode
    SkAlphaType dstAlphaType = fCodec->computeOutputAlphaType(requireUnpremul);
    SkImageInfo decodeInfo =
            SkImageInfo::Make(scaledSize, dstColorType, dstAlphaType, dstColorSpace);

    // Initialize the destination bitmap
    int scaledOutX = 0;
    int scaledOutY = 0;
    int scaledOutWidth = scaledSize.width();
    int scaledOutHeight = scaledSize.height();
    if (SubsetType::kPartiallyInside_SubsetType == type) {
        scaledOutX = outX / sampleSize;
        scaledOutY = outY / sampleSize;
        // We need to be safe here because getSupportedSubset() may have modified the subset.
        const int extraX = std::max(0, desiredSubset.width() - outX - subset.width());
        const int extraY = std::max(0, desiredSubset.height() - outY - subset.height());
        const int scaledExtraX = extraX / sampleSize;
        const int scaledExtraY = extraY / sampleSize;
        scaledOutWidth += scaledOutX + scaledExtraX;
        scaledOutHeight += scaledOutY + scaledExtraY;
    }
    SkImageInfo outInfo = decodeInfo.makeWH(scaledOutWidth, scaledOutHeight);
    if (kGray_8_SkColorType == dstColorType) {
        // The legacy implementations of BitmapFactory and BitmapRegionDecoder
        // used kAlpha8 for grayscale images (before kGray8 existed).  While
        // the codec recognizes kGray8, we need to decode into a kAlpha8
        // bitmap in order to avoid a behavior change.
        outInfo = outInfo.makeColorType(kAlpha_8_SkColorType).makeAlphaType(kPremul_SkAlphaType);
    }
    bitmap->setInfo(outInfo);
    if (!bitmap->tryAllocPixels(allocator)) {
        SkCodecPrintf("Error: Could not allocate pixels.\n");
        return false;
    }

    // Zero the bitmap if the region is not completely within the image.
    // TODO (msarett): Can we make this faster by implementing it to only
    //                 zero parts of the image that we won't overwrite with
    //                 pixels?
    SkCodec::ZeroInitialized zeroInit = allocator ? allocator->zeroInit() :
            SkCodec::kNo_ZeroInitialized;
    if (SubsetType::kPartiallyInside_SubsetType == type &&
            SkCodec::kNo_ZeroInitialized == zeroInit) {
        void* pixels = bitmap->getPixels();
        size_t bytes = outInfo.computeByteSize(bitmap->rowBytes());
        memset(pixels, 0, bytes);
    }

    // Decode into the destination bitmap
    SkAndroidCodec::AndroidOptions options;
    options.fSampleSize = sampleSize;
    options.fSubset = &subset;
    options.fZeroInitialized = zeroInit;
    void* dst = bitmap->getAddr(scaledOutX, scaledOutY);

    SkCodec::Result result = fCodec->getAndroidPixels(decodeInfo, dst, bitmap->rowBytes(),
            &options);
    switch (result) {
        case SkCodec::kSuccess:
        case SkCodec::kIncompleteInput:
        case SkCodec::kErrorInInput:
            return true;
        default:
            SkCodecPrintf("Error: Could not get pixels with message \"%s\".\n",
                          SkCodec::ResultToString(result));
            return false;
    }
}

} // namespace skia
} // namespace android
