/*
 * Copyright 2020 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "include/core/SkCanvas.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkPaint.h"
#include "include/core/SkRect.h"
#include "include/core/SkSurface.h"

#include <cmath>

void SkRescaleAndReadPixels(SkBitmap bmp,
                            const SkImageInfo& resultInfo,
                            const SkIRect& srcRect,
                            SkImage::RescaleGamma rescaleGamma,
                            SkFilterQuality rescaleQuality,
                            SkImage::ReadPixelsCallback callback,
                            SkImage::ReadPixelsContext context) {
    int srcW = srcRect.width();
    int srcH = srcRect.height();

    float sx = (float)resultInfo.width() / srcW;
    float sy = (float)resultInfo.height() / srcH;
    // How many bilerp/bicubic steps to do in X and Y. + means upscaling, - means downscaling.
    int stepsX;
    int stepsY;
    if (rescaleQuality > kNone_SkFilterQuality) {
        stepsX = static_cast<int>((sx > 1.f) ? std::ceil(std::log2f(sx))
                                             : std::floor(std::log2f(sx)));
        stepsY = static_cast<int>((sy > 1.f) ? std::ceil(std::log2f(sy))
                                             : std::floor(std::log2f(sy)));
    } else {
        stepsX = sx != 1.f;
        stepsY = sy != 1.f;
    }

    SkPaint paint;
    paint.setBlendMode(SkBlendMode::kSrc);
    if (stepsX < 0 || stepsY < 0) {
        // Don't trigger MIP generation. We don't currently have a way to trigger bicubic for
        // downscaling draws.
        rescaleQuality = std::min(rescaleQuality, kLow_SkFilterQuality);
    }
    paint.setFilterQuality(rescaleQuality);
    sk_sp<SkSurface> tempSurf;
    sk_sp<SkImage> srcImage;
    int srcX = srcRect.fLeft;
    int srcY = srcRect.fTop;
    SkCanvas::SrcRectConstraint constraint = SkCanvas::kStrict_SrcRectConstraint;
    // Assume we should ignore the rescale linear request if the surface has no color space since
    // it's unclear how we'd linearize from an unknown color space.
    if (rescaleGamma == SkSurface::RescaleGamma::kLinear && bmp.info().colorSpace() &&
        !bmp.info().colorSpace()->gammaIsLinear()) {
        auto cs = bmp.info().colorSpace()->makeLinearGamma();
        // Promote to F16 color type to preserve precision.
        auto ii = SkImageInfo::Make(srcW, srcH, kRGBA_F16_SkColorType, bmp.info().alphaType(),
                                    std::move(cs));
        auto linearSurf = SkSurface::MakeRaster(ii);
        if (!linearSurf) {
            callback(context, nullptr);
            return;
        }
        linearSurf->getCanvas()->drawBitmap(bmp, -srcX, -srcY, &paint);
        tempSurf = std::move(linearSurf);
        srcImage = tempSurf->makeImageSnapshot();
        srcX = 0;
        srcY = 0;
        constraint = SkCanvas::kFast_SrcRectConstraint;
    } else {
        // MakeFromBitmap would trigger a copy if bmp is mutable.
        srcImage = SkImage::MakeFromRaster(bmp.pixmap(), nullptr, nullptr);
    }
    while (stepsX || stepsY) {
        int nextW = resultInfo.width();
        int nextH = resultInfo.height();
        if (stepsX < 0) {
            nextW = resultInfo.width() << (-stepsX - 1);
            stepsX++;
        } else if (stepsX != 0) {
            if (stepsX > 1) {
                nextW = srcW * 2;
            }
            --stepsX;
        }
        if (stepsY < 0) {
            nextH = resultInfo.height() << (-stepsY - 1);
            stepsY++;
        } else if (stepsY != 0) {
            if (stepsY > 1) {
                nextH = srcH * 2;
            }
            --stepsY;
        }
        auto ii = srcImage->imageInfo().makeWH(nextW, nextH);
        if (!stepsX && !stepsY) {
            // Might as well fold conversion to final info in the last step.
            ii = resultInfo;
        }
        auto next = SkSurface::MakeRaster(ii);
        if (!next) {
            callback(context, nullptr);
            return;
        }
        next->getCanvas()->drawImageRect(
                std::move(srcImage), SkIRect::MakeXYWH(srcX, srcY, srcW, srcH),
                SkRect::MakeWH((float)nextW, (float)nextH), &paint, constraint);
        tempSurf = std::move(next);
        srcImage = tempSurf->makeImageSnapshot();
        srcX = srcY = 0;
        srcW = nextW;
        srcH = nextH;
        constraint = SkCanvas::kFast_SrcRectConstraint;
    }

    size_t rowBytes = resultInfo.minRowBytes();
    std::unique_ptr<char[]> data(new char[resultInfo.height() * rowBytes]);
    SkPixmap pm(resultInfo, data.get(), rowBytes);
    if (srcImage->readPixels(pm, srcX, srcY)) {
        class Result : public SkImage::AsyncReadResult {
        public:
            Result(std::unique_ptr<const char[]> data, size_t rowBytes)
                    : fData(std::move(data)), fRowBytes(rowBytes) {}
            int count() const override { return 1; }
            const void* data(int i) const override { return fData.get(); }
            size_t rowBytes(int i) const override { return fRowBytes; }

        private:
            std::unique_ptr<const char[]> fData;
            size_t fRowBytes;
        };
        callback(context, std::make_unique<Result>(std::move(data), rowBytes));
    } else {
        callback(context, nullptr);
    }
}
