/*
 * 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 "SkBitmapRegionCanvas.h"
#include "SkCanvas.h"
#include "SkCodecPriv.h"
#include "SkCodecTools.h"

SkBitmapRegionCanvas::SkBitmapRegionCanvas(SkCodec* decoder)
    : INHERITED(decoder->getInfo().width(), decoder->getInfo().height())
    , fDecoder(decoder)
{}

bool SkBitmapRegionCanvas::decodeRegion(SkBitmap* bitmap, SkBitmap::Allocator* allocator,
        const SkIRect& desiredSubset, int sampleSize, SkColorType dstColorType,
        bool requireUnpremul) {
    // Reject color types not supported by this method
    if (kIndex_8_SkColorType == dstColorType || kGray_8_SkColorType == dstColorType) {
        SkCodecPrintf("Error: Color type not supported.\n");
        return false;
    }

    // Reject requests for unpremultiplied alpha
    if (requireUnpremul) {
        SkCodecPrintf("Error: Alpha type not supported.\n");
        return false;
    }
    SkAlphaType dstAlphaType = fDecoder->getInfo().alphaType();
    if (kUnpremul_SkAlphaType == dstAlphaType) {
        dstAlphaType = kPremul_SkAlphaType;
    }

    // FIXME: Can we add checks and support kIndex8 or unpremultiplied alpha in special cases?

    // 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(fDecoder->getInfo().dimensions(), &subset, &outX, &outY);
    if (SubsetType::kOutside_SubsetType == type) {
        return false;
    }

    // Create the image info for the decode
    SkImageInfo decodeInfo = SkImageInfo::Make(this->width(), this->height(),
            dstColorType, dstAlphaType);

    // Start the scanline decoder
    SkCodec::Result r = fDecoder->startScanlineDecode(decodeInfo);
    if (SkCodec::kSuccess != r) {
        SkCodecPrintf("Error: Could not start scanline decoder.\n");
        return false;
    }

    // Allocate a bitmap for the unscaled decode
    SkBitmap tmp;
    SkImageInfo tmpInfo = decodeInfo.makeWH(this->width(), subset.height());
    if (!tmp.tryAllocPixels(tmpInfo)) {
        SkCodecPrintf("Error: Could not allocate pixels.\n");
        return false;
    }

    // Skip the unneeded rows
    if (!fDecoder->skipScanlines(subset.y())) {
        SkCodecPrintf("Error: Failed to skip scanlines.\n");
        return false;
    }

    // Decode the necessary rows
    fDecoder->getScanlines(tmp.getAddr(0, 0), subset.height(), tmp.rowBytes());

    // Calculate the size of the output
    const int outWidth = get_scaled_dimension(desiredSubset.width(), sampleSize);
    const int outHeight = get_scaled_dimension(desiredSubset.height(), sampleSize);

    // Initialize the destination bitmap
    SkImageInfo dstInfo = decodeInfo.makeWH(outWidth, outHeight);
    bitmap->setInfo(dstInfo, dstInfo.minRowBytes());
    if (!bitmap->tryAllocPixels(allocator, nullptr)) {
        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?
    // TODO (msarett): This could be skipped if memory is zero initialized.
    //                 This would matter if this code is moved to Android and
    //                 uses Android bitmaps.
    if (SubsetType::kPartiallyInside_SubsetType == type) {
        bitmap->eraseColor(0);
    }

    // Use a canvas to crop and scale to the destination bitmap
    SkCanvas canvas(*bitmap);
    // TODO (msarett): Maybe we can take advantage of the fact that SkRect uses floats?
    SkRect src = SkRect::MakeXYWH((SkScalar) subset.x(), (SkScalar) 0,
            (SkScalar) subset.width(), (SkScalar) subset.height());
    SkRect dst = SkRect::MakeXYWH((SkScalar) (outX / sampleSize), (SkScalar) (outY / sampleSize),
            (SkScalar) get_scaled_dimension(subset.width(), sampleSize),
            (SkScalar) get_scaled_dimension(subset.height(), sampleSize));
    SkPaint paint;
    // Overwrite the dst with the src pixels
    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
    // TODO (msarett): Test multiple filter qualities.  kNone is the default.
    canvas.drawBitmapRect(tmp, src, dst, &paint);

    return true;
}

bool SkBitmapRegionCanvas::conversionSupported(SkColorType colorType) {
    // SkCanvas does not draw to these color types.
    if (kIndex_8_SkColorType == colorType || kGray_8_SkColorType == colorType) {
        return false;
    }

    // FIXME: Call virtual function when it lands.
    SkImageInfo info = SkImageInfo::Make(0, 0, colorType, fDecoder->getInfo().alphaType(),
            fDecoder->getInfo().profileType());
    return conversion_possible(info, fDecoder->getInfo());
}
