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

#include "gm/gm.h"
#include "include/codec/SkEncodedImageFormat.h"
#include "include/core/SkBitmap.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkData.h"
#include "include/core/SkImage.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkPixmap.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkSize.h"
#include "include/core/SkStream.h"
#include "include/core/SkString.h"
#include "include/core/SkTypes.h"
#include "include/encode/SkJpegEncoder.h"
#include "include/encode/SkPngEncoder.h"
#include "include/encode/SkWebpEncoder.h"
#include "tools/DecodeUtils.h"
#include "tools/Resources.h"

namespace {

static const struct {
    SkEncodedImageFormat format;
    int                  quality;
} gRecs[] = {
    // We don't support GIF, BMP, or ICO. This applies to both NDK and SkEncoder.
    { SkEncodedImageFormat::kPNG,  100},
    { SkEncodedImageFormat::kJPEG, 100},
    { SkEncodedImageFormat::kWEBP, 100}, // Lossless
    { SkEncodedImageFormat::kWEBP,  80}, // Lossy
    { SkEncodedImageFormat::kPNG,  100},
};

} // anonymous namespace

static sk_sp<SkData> encode_data(SkEncodedImageFormat type, const SkBitmap& bitmap, int quality) {
    SkPixmap src;
    if (!bitmap.peekPixels(&src)) {
        return nullptr;
    }
    switch (type) {
        case SkEncodedImageFormat::kPNG:
            return SkPngEncoder::Encode(src, {});
        case SkEncodedImageFormat::kJPEG: {
            SkJpegEncoder::Options opts;
            opts.fQuality = quality;
            return SkJpegEncoder::Encode(src, opts);
        }
        case SkEncodedImageFormat::kWEBP: {
            SkWebpEncoder::Options opts;
            opts.fQuality = quality;
            return SkWebpEncoder::Encode(src, opts);
        }
        default:
            SkUNREACHABLE;
    }
}

namespace skiagm {

class EncodePlatformGM : public GM {
public:
    EncodePlatformGM() {}

protected:
    SkString getName() const override { return SkString("encode-platform"); }

    SkISize getISize() override { return SkISize::Make(256 * std::size(gRecs), 256 * 3); }

    DrawResult onDraw(SkCanvas* canvas, SkString* errorMsg) override {
        SkBitmap opaqueBm, premulBm, unpremulBm;

        if (!ToolUtils::GetResourceAsBitmap("images/mandrill_256.png", &opaqueBm)) {
            *errorMsg = "Could not load images/mandrill_256.png.png. "
                        "Did you forget to set the resourcePath?";
            return DrawResult::kFail;
        }
        SkBitmap tmp;
        if (!ToolUtils::GetResourceAsBitmap("images/yellow_rose.png", &tmp)) {
            *errorMsg = "Could not load images/yellow_rose.png. "
                        "Did you forget to set the resourcePath?";
            return DrawResult::kFail;
        }
        tmp.extractSubset(&premulBm, SkIRect::MakeWH(256, 256));
        tmp.reset();
        unpremulBm.allocPixels(premulBm.info().makeAlphaType(kUnpremul_SkAlphaType));
        SkAssertResult(premulBm.readPixels(unpremulBm.pixmap()));

        for (const auto& rec : gRecs) {
            auto fmt = rec.format; int q = rec.quality;
            auto opaqueImage = SkImages::DeferredFromEncodedData(encode_data(fmt, opaqueBm, q));
            auto premulImage = SkImages::DeferredFromEncodedData(encode_data(fmt, premulBm, q));
            auto unpremulImage = SkImages::DeferredFromEncodedData(encode_data(fmt, unpremulBm, q));

            canvas->drawImage(opaqueImage.get(), 0.0f, 0.0f);
            canvas->drawImage(premulImage.get(), 0.0f, 256.0f);
            canvas->drawImage(unpremulImage.get(), 0.0f, 512.0f);

            canvas->translate(256.0f, 0.0f);
        }
        return DrawResult::kOk;
    }

private:
    using INHERITED = GM;
};

DEF_GM( return new EncodePlatformGM; )
}  // namespace skiagm
