/*
 * Copyright 2022 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/SkImage.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPixmap.h"
#include "include/core/SkShader.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] = {SkImages::RasterFromPixmapCopy(cpmx), SkImages::RasterFromPixmapCopy(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] = {SkImages::RasterFromPixmapCopy(apmx), SkImages::RasterFromPixmapCopy(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(SkFilterMode::kNearest));
        }
        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, SkFilterMode::kNearest, &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;
}
