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

#include "gm.h"
#include "SkColorPriv.h"
#include "SkColorSpaceXform.h"
#include "SkColorSpaceXformPriv.h"
#include "SkOpts.h"
#include "SkUtils.h"

static void clamp_to_alpha(uint32_t* pixels, int count) {
    for (int i = 0; i < count; i++) {
        uint8_t a = SkGetPackedA32(pixels[i]);
        uint8_t r = SkGetPackedR32(pixels[i]);
        uint8_t g = SkGetPackedG32(pixels[i]);
        uint8_t b = SkGetPackedB32(pixels[i]);
        pixels[i] = SkPackARGB32(a,
                                 SkTMin(a, r),
                                 SkTMin(a, g),
                                 SkTMin(a, b));
    }
}

class GammaEncodedPremulGM : public skiagm::GM {
public:
    GammaEncodedPremulGM(sk_sp<SkColorSpace> dst, sk_sp<SkColorSpace> src, const char* desc)
        : fDstSpace(dst)
        , fSrcSpace(src)
        , fXform(SkColorSpaceXform::New(src.get(), dst.get()))
        , fName(SkStringPrintf("gamma_encoded_premul_dst-v-src_%s", desc))
    {
        int i = 0;
        for (int r = 0; r < kColorSteps; r++) {
            for (int g = 0; g < kColorSteps; g++) {
                for (int b = 0; b < kColorSteps; b++) {
                    fColors[i++] = SkColorSetRGB(r * kColorScale,
                                                 g * kColorScale,
                                                 b * kColorScale);
                }
            }
        }

    }

protected:
    virtual SkISize onISize() override {
        return SkISize::Make(kAlphaMax, kNumColors * 2 * kStripeHeight);
    }

    SkString onShortName() override {
        return fName;
    }

    void onDraw(SkCanvas* canvas) override {
        if (canvas->imageInfo().isOpaque()) {
            return;
        }

        SkBitmap bitmap;
        SkImageInfo bitmapInfo = SkImageInfo::MakeN32Premul(kAlphaMax, 1,
                canvas->imageInfo().refColorSpace());
        bitmap.allocPixels(bitmapInfo);
        uint32_t* pixels = bitmap.getAddr32(0, 0);

        for (int i = 0; i < kNumColors; i++) {
            // Create an entire row of the same color, with the alpha from 0 to kAlphaMax.
            uint32_t row[kAlphaMax];
            sk_memset32(row, fColors[i], kAlphaMax);
            for (int a = 0; a < kAlphaMax; a++) {
                row[a] = (row[a] & 0x00FFFFFF) | (a << 24);
            }

            // Tranform row to dst, then premultiply.
            fXform->apply(select_xform_format(kN32_SkColorType), pixels,
                          SkColorSpaceXform::kBGRA_8888_ColorFormat, row, kAlphaMax,
                          kUnpremul_SkAlphaType);
            SkOpts::RGBA_to_rgbA(pixels, pixels, kAlphaMax);
            bitmap.notifyPixelsChanged();

            // Write the dst space premultiplied row to the canvas.
            for (int j = 0; j < kStripeHeight; j++) {
                canvas->drawBitmap(bitmap, 0, 2 * i * kStripeHeight + j);
            }

            // Premultiply, then transform the row to dst.
            SkOpts::RGBA_to_rgbA(pixels, row, kAlphaMax);
            fXform->apply(select_xform_format(kN32_SkColorType), pixels,
                          SkColorSpaceXform::kBGRA_8888_ColorFormat, pixels, kAlphaMax,
                          kUnpremul_SkAlphaType);
            clamp_to_alpha(pixels, kAlphaMax);
            bitmap.notifyPixelsChanged();

            // Write the src space premultiplied row to the canvas.
            for (int j = 0; j < kStripeHeight; j++) {
                canvas->drawBitmap(bitmap, 0, (2 * i + 1) * kStripeHeight + j);
            }
        }
    }

private:
    static constexpr int kColorSteps = 4;
    static constexpr int kNumColors = kColorSteps * kColorSteps * kColorSteps;
    static constexpr int kColorScale = 255 / (kColorSteps - 1);
    static constexpr int kStripeHeight = 10;
    static constexpr int kAlphaMax = 255;

    sk_sp<SkColorSpace>                fDstSpace;
    sk_sp<SkColorSpace>                fSrcSpace;
    std::unique_ptr<SkColorSpaceXform> fXform;
    SkString                           fName;
    SkColor                            fColors[kNumColors];

    typedef GM INHERITED;
};

DEF_GM(return new GammaEncodedPremulGM(SkColorSpace::MakeSRGB(),
        SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma, SkColorSpace::kRec2020_Gamut),
        "toWideGamut");)
DEF_GM(return new GammaEncodedPremulGM(SkColorSpace::MakeRGB(SkColorSpace::kSRGB_RenderTargetGamma,
        SkColorSpace::kRec2020_Gamut), SkColorSpace::MakeSRGB(), "fromWideGamut");)
DEF_GM(return new GammaEncodedPremulGM(SkColorSpace::MakeSRGB(),
        SkColorSpace::MakeRGB(SkColorSpace::kLinear_RenderTargetGamma, SkColorSpace::kSRGB_Gamut),
        "toLinear");)
DEF_GM(return new GammaEncodedPremulGM(
        SkColorSpace::MakeRGB(SkColorSpace::kLinear_RenderTargetGamma, SkColorSpace::kSRGB_Gamut),
        SkColorSpace::MakeSRGB(), "fromLinear");)
DEF_GM(return new GammaEncodedPremulGM(
        SkColorSpace::MakeRGB({ 1.8f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f },
        SkColorSpace::kSRGB_Gamut), SkColorSpace::MakeSRGB(), "from1.8");)
