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

// This test only works with the GPU backend.

#include "gm/gm.h"
#include "include/core/SkBlendMode.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPaint.h"
#include "include/core/SkRect.h"
#include "include/core/SkScalar.h"
#include "include/core/SkSize.h"
#include "include/core/SkString.h"
#include "include/private/gpu/ganesh/GrTypesPriv.h"
#include "src/core/SkCanvasPriv.h"
#include "src/gpu/ganesh/GrFragmentProcessor.h"
#include "src/gpu/ganesh/GrPaint.h"
#include "src/gpu/ganesh/effects/GrPorterDuffXferProcessor.h"
#include "src/gpu/ganesh/v1/SurfaceDrawContext_v1.h"
#include "tools/gpu/TestOps.h"

#include <memory>
#include <utility>

class GrAppliedClip;

namespace skiagm {

/**
 * This GM directly exercises a GrProcessor that clips against rects.
 */
class AARectEffect : public GpuGM {
public:
    AARectEffect() { this->setBGColor(0xFFFFFFFF); }

protected:
    SkString onShortName() override { return SkString("aa_rect_effect"); }

    SkISize onISize() override { return SkISize::Make(210, 250); }

    void onOnceBeforeDraw() override {}

    DrawResult onDraw(GrRecordingContext* rContext, SkCanvas* canvas, SkString* errorMsg) override {
        auto sdc = SkCanvasPriv::TopDeviceSurfaceDrawContext(canvas);
        if (!sdc) {
            *errorMsg = kErrorMsg_DrawSkippedGpuOnly;
            return DrawResult::kSkip;
        }

        SkScalar y = 12.f;
        static constexpr SkScalar kDX = 12.f;
        static constexpr SkScalar kOutset = 5.f;

        static constexpr SkRect kRects[] = {
                // integer edges
                SkRect::MakeLTRB(5.f, 1.f, 30.f, 25.f),
                // half-integer edges
                SkRect::MakeLTRB(5.5f, 0.5f, 29.5f, 24.5f),
                // vertically/horizontally thin rects that cover pixel centers
                SkRect::MakeLTRB(5.25f, 0.5f, 5.75f, 24.5f),
                SkRect::MakeLTRB(5.5f,  0.5f, 29.5f, 0.75f),
                // vertically/horizontally thin rects that don't cover pixel centers
                SkRect::MakeLTRB(5.55f, 0.5f, 5.75f, 24.5f),
                SkRect::MakeLTRB(5.5f, .05f, 29.5f, .25f),
                // small in x and y
                SkRect::MakeLTRB(5.05f, .55f, 5.45f, .85f),
        };

        for (auto r : kRects) {
            SkScalar x = kDX;

            for (int et = 0; et < kGrClipEdgeTypeCnt; ++et) {
                SkRect rect = r.makeOffset(x, y);
                GrClipEdgeType edgeType = static_cast<GrClipEdgeType>(et);
                auto fp = GrFragmentProcessor::Rect(/*inputFP=*/nullptr, edgeType, rect);
                SkASSERT(fp);

                GrPaint grPaint;
                grPaint.setColor4f({ 0, 0, 0, 1.f });
                grPaint.setXPFactory(GrPorterDuffXPFactory::Get(SkBlendMode::kSrc));
                grPaint.setCoverageFragmentProcessor(std::move(fp));
                auto drawRect = rect.makeOutset(kOutset, kOutset);
                auto op = sk_gpu_test::test_ops::MakeRect(rContext, std::move(grPaint), drawRect);
                sdc->addDrawOp(std::move(op));

                x += SkScalarCeilToScalar(rect.width() + kDX);
            }

            // Draw rect without and with AA using normal API for reference
            canvas->save();
            canvas->translate(x, y);
            SkPaint paint;
            canvas->drawRect(r, paint);
            x += SkScalarCeilToScalar(r.width() + kDX);
            paint.setAntiAlias(true);
            canvas->drawRect(r, paint);
            canvas->restore();

            y += SkScalarCeilToScalar(r.height() + 20.f);
        }

        return DrawResult::kOk;
    }

private:
    using INHERITED = GM;
};

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