/*
 * Copyright 2021 Google LLC
 *
 * 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/core/SkCanvas.h"
#include "include/core/SkColorSpace.h"
#include "include/core/SkFont.h"
#include "include/core/SkSurface.h"
#include "tools/DecodeUtils.h"
#include "tools/Resources.h"
#include "tools/fonts/FontToolUtils.h"

static const skcms_TransferFunction gTFs[] = {
    SkNamedTransferFn::kSRGB,
    SkNamedTransferFn::k2Dot2,
    SkNamedTransferFn::kLinear,
    SkNamedTransferFn::kRec2020,
    SkNamedTransferFn::kPQ,
    SkNamedTransferFn::kHLG,
    SkNamedTransferFn::kRec709,
};

static const skcms_Matrix3x3 gGamuts[] = {
    SkNamedGamut::kSRGB,
    SkNamedGamut::kAdobeRGB,
    SkNamedGamut::kDisplayP3,
    SkNamedGamut::kRec2020,
    SkNamedGamut::kXYZ,
};

static const int W = 128,
                 H = 128;

// These GMs demonstrate that our color space management is self-consistent.
// (Important to note, self-consistent, not necessarily correct in an objective sense.)
//
// Let's let,
//
//     SkColorSpace* imgCS = img->colorSpace();
//     SkColorSpace* dstCS = canvas->imageInfo().colorSpace();
//
// Ordinarily we'd just
//
//     canvas->drawImage(img, 0,0);
//
// which would convert that img's pixels from imgCS to dstCS while drawing.
//
// But before we draw in these GMs, we convert the image to an arbitrarily different color space,
// letting midCS range over the cross-product gTFs × gGamuts:
//
//     canvas->drawImage(img->makeColorSpace(midCS), 0,0);
//
// This converts img first from imgCS to midCS, treating midCS as a destination color space,
// and then draws that midCS image to the dstCS canvas, treating midCS as a source color space.
// This should draw a grid of images that look identical except for small precision loss.
//
// If instead of calling SkImage::makeColorSpace() we use SkCanvas::makeSurface() to create a
// midCS offscreen, we construct the same logical imgCS -> midCS -> dstCS transform chain while
// exercising different drawing code paths.  Both strategies should draw roughly the same.

namespace {
    enum Strategy { SkImage_makeColorSpace, SkCanvas_makeSurface };
}

static void draw_colorspace_gm(Strategy strategy, SkCanvas* canvas) {
    SkFont font = ToolUtils::DefaultPortableFont();
    if (!canvas->imageInfo().colorSpace()) {
        canvas->drawString("This GM only makes sense with color-managed drawing.",
                           W,H, font, SkPaint{});
        return;
    }

    sk_sp<SkImage> img = ToolUtils::GetResourceAsImage("images/mandrill_128.png");
    if (!img) {
        canvas->drawString("Could not load our test image!",
                           W,H, font, SkPaint{});
        return;
    }

    SkASSERT(img->width()  == W);
    SkASSERT(img->height() == H);
    SkASSERT(img->colorSpace());

    for (skcms_Matrix3x3 gamut : gGamuts) {
        canvas->save();
        for (skcms_TransferFunction tf : gTFs) {
            sk_sp<SkColorSpace> midCS = SkColorSpace::MakeRGB(tf, gamut);

            switch (strategy) {
                case SkImage_makeColorSpace: {
                    canvas->drawImage(img->makeColorSpace(nullptr, midCS, {}), 0, 0);
                } break;

                case SkCanvas_makeSurface: {
                    sk_sp<SkSurface> offscreen =
                        canvas->makeSurface(canvas->imageInfo().makeColorSpace(midCS));
                    if (!offscreen) {
                        canvas->drawString("Could not allocate offscreen surface!",
                                           W,H, font, SkPaint{});
                        return;
                    }
                    offscreen->getCanvas()->drawImage(img, 0,0);
                    canvas->drawImage(offscreen->makeImageSnapshot(), 0,0);
                } break;
            }

            canvas->translate(W, 0);
        }
        canvas->restore();
        canvas->translate(0, H);
    }
}

DEF_SIMPLE_GM(colorspace, canvas, W*std::size(gTFs), H*std::size(gGamuts)) {
    draw_colorspace_gm(SkImage_makeColorSpace, canvas);
}

DEF_SIMPLE_GM(colorspace2, canvas, W*std::size(gTFs), H*std::size(gGamuts)) {
    draw_colorspace_gm(SkCanvas_makeSurface, canvas);
}
