/*
 * Copyright 2022 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/core/SkCanvas.h"
#include "include/core/SkImage.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPixmap.h"
#include "include/core/SkSurface.h"

/**
 * Tests drawing images are half pixel offsets in device space with nearest filtering to show how
 * rasterization and image sample snapping at boundary points interact. Both drawImage and drawRect
 * with an image shader are tested. Scale factors 1 and -1 are tested. The images are all two pixels
 * wide or tall so we either get both values once each or one value repeated twice.
 */
DEF_SIMPLE_GM_CAN_FAIL(nearest_half_pixel_image, canvas, errorMsg, 264, 235) {
    // We don't run this test on the GPU because we're at the driver/hw's mercy for how this
    // is handled.
    if (canvas->recordingContext() || (canvas->getSurface() && canvas->getSurface()->recorder())) {
        *errorMsg = "Test is only relevant to CPU backend";
        return skiagm::DrawResult::kSkip;
    }

    // We make 2x1 and 1x2 images for each color type.
    struct Images {
        sk_sp<SkImage> imageX;
        sk_sp<SkImage> imageY;
    };

    Images images[2];
    uint32_t colors[] {0xFFFF0000, 0xFF0000FF};
    SkPixmap cpmx(SkImageInfo::Make({2, 1},
                                    kRGBA_8888_SkColorType,
                                    kPremul_SkAlphaType),
                  colors,
                  sizeof(colors));
    SkPixmap cpmy(SkImageInfo::Make({1, 2},
                                    kRGBA_8888_SkColorType,
                                    kPremul_SkAlphaType),
                  colors,
                  sizeof(colors[0]));
    images[0] = {SkImage::MakeRasterCopy(cpmx), SkImage::MakeRasterCopy(cpmy)};

    uint8_t alphas[] {0xFF, 0xAA};
    SkPixmap apmx(SkImageInfo::Make({2, 1},
                                    kAlpha_8_SkColorType,
                                    kPremul_SkAlphaType),
                  alphas,
                  sizeof(alphas));
    SkPixmap apmy(SkImageInfo::Make({1, 2},
                                    kAlpha_8_SkColorType,
                                    kPremul_SkAlphaType),
                  alphas,
                  sizeof(alphas[0]));
    images[1] = {SkImage::MakeRasterCopy(apmx), SkImage::MakeRasterCopy(apmy)};

    // We draw offscreen and then zoom that up to make the result clear.
    auto surf = canvas->makeSurface(canvas->imageInfo().makeWH(80, 80));
    if (!surf) {
        *errorMsg = "Test only works with SkSurface backed canvases";
        return skiagm::DrawResult::kSkip;
    }
    auto* c = surf->getCanvas();
    c->clear(SK_ColorWHITE);

    // We scale up in the direction not being tested, the one with image dimension of 1, to make the
    // result more easily visible.
    static const float kOffAxisScale = 4;

    auto draw = [&](sk_sp<SkImage> image, bool shader, bool doX, bool mirror, uint8_t alpha) {
        c->save();
        SkPaint paint;
        paint.setAlpha(alpha);
        if (shader) {
            paint.setShader(image->makeShader(SkSamplingOptions{}));
        }
        if (doX) {
            c->scale(mirror ? -1 : 1, kOffAxisScale);
            c->translate(mirror ? -2.5 : 0.5, 0);
        } else {
            c->scale(kOffAxisScale, mirror ? -1 : 1);
            c->translate(0, mirror ? -2.5 : 0.5);
        }

        if (shader) {
            c->drawRect(SkRect::Make(image->dimensions()), paint);
        } else {
            c->drawImage(image, 0, 0, SkSamplingOptions{}, &paint);
        }
        c->restore();
    };

    for (bool shader : {false, true})
    for (uint8_t alpha : {0xFF , 0x70}) {
        c->save();
        for (const auto& i : images)
        for (auto mirror : {false, true}) {
            draw(i.imageX, shader, /*doX=*/true, mirror, alpha);
            c->save();
            c->translate(4, 0);
            draw(i.imageY, shader, /*doX=*/false, mirror, alpha);
            c->restore();
            c->translate(0, kOffAxisScale*2);
        }
        c->restore();
        c->translate(kOffAxisScale*2, 0);
    }
    canvas->scale(8, 8);
    canvas->drawImage(surf->makeImageSnapshot(), 0, 0);

    return skiagm::DrawResult::kOk;
}
