/*
 * Copyright 2016 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/SkColor.h"
#include "include/core/SkImage.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPath.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkScalar.h"
#include "include/core/SkShader.h"
#include "include/core/SkSize.h"
#include "include/core/SkString.h"
#include "include/core/SkSurface.h"
#include "tools/ToolUtils.h"

namespace skiagm {

constexpr SkRect kSrcImageClip{75, 75, 275, 275};

static sk_sp<SkImage> create_image(SkCanvas* destCanvas) {
    sk_sp<SkSurface> srcSurface = SkSurface::MakeRasterN32Premul(500, 500);
    SkCanvas* srcCanvas = srcSurface->getCanvas();

    srcCanvas->clear(SK_ColorRED);

    SkPaint paint;
    paint.setColor(0xff00ff00);
    srcCanvas->drawRect(kSrcImageClip, paint);

    constexpr SkScalar kStrokeWidth = 10;
    SkPaint stroke;
    stroke.setStyle(SkPaint::kStroke_Style);
    stroke.setStrokeWidth(kStrokeWidth);
    stroke.setColor(0xff008800);
    srcCanvas->drawRect(kSrcImageClip.makeInset(kStrokeWidth / 2, kStrokeWidth / 2), stroke);

    return ToolUtils::MakeTextureImage(destCanvas, srcSurface->makeImageSnapshot());
}

/*
 * The purpose of this test is to exercise all three codepaths in skgpu::v1::SurfaceDrawContext
 * (drawFilledRect, fillRectToRect, fillRectWithLocalMatrix) that pre-crop filled rects based on the
 * clip.
 *
 * The test creates an image of a green square surrounded by red background, then draws this image
 * in various ways with the red clipped out. The test is successful if there is no visible red
 * background, scissor is never used, and ideally, all the rectangles draw in one GrDrawOp.
 */
class CroppedRectsGM : public GM {
private:
    SkString onShortName() final { return SkString("croppedrects"); }
    SkISize onISize() override { return SkISize::Make(500, 500); }

    void onDraw(SkCanvas* canvas) override {
        if (!fSrcImage) {
            fSrcImage = create_image(canvas);
            fSrcImageShader = fSrcImage->makeShader(SkSamplingOptions());
        }

        canvas->clear(SK_ColorWHITE);

        {
            // skgpu::v1::SurfaceDrawContext::drawFilledRect.
            SkAutoCanvasRestore acr(canvas, true);
            SkPaint paint;
            paint.setShader(fSrcImageShader);
            canvas->clipRect(kSrcImageClip);
            canvas->drawPaint(paint);
        }

        {
            // skgpu::v1::SurfaceDrawContext::fillRectToRect.
            SkAutoCanvasRestore acr(canvas, true);
            SkRect drawRect = SkRect::MakeXYWH(350, 100, 100, 300);
            canvas->clipRect(drawRect);
            canvas->drawImageRect(fSrcImage.get(),
                                  kSrcImageClip.makeOutset(0.5f * kSrcImageClip.width(),
                                                           kSrcImageClip.height()),
                                  drawRect.makeOutset(0.5f * drawRect.width(), drawRect.height()),
                                  SkSamplingOptions(), nullptr,
                                  SkCanvas::kStrict_SrcRectConstraint);
        }

        {
            // skgpu::v1::SurfaceDrawContext::fillRectWithLocalMatrix.
            SkAutoCanvasRestore acr(canvas, true);
            SkPath path = SkPath::Line(
                   {kSrcImageClip.fLeft - kSrcImageClip.width(), kSrcImageClip.centerY()},
                   {kSrcImageClip.fRight + 3 * kSrcImageClip.width(), kSrcImageClip.centerY()});
            SkPaint paint;
            paint.setStyle(SkPaint::kStroke_Style);
            paint.setStrokeWidth(2 * kSrcImageClip.height());
            paint.setShader(fSrcImageShader);
            canvas->translate(23, 301);
            canvas->scale(300 / kSrcImageClip.width(), 100 / kSrcImageClip.height());
            canvas->translate(-kSrcImageClip.left(), -kSrcImageClip.top());
            canvas->clipRect(kSrcImageClip);
            canvas->drawPath(path, paint);
        }

        // TODO: assert the draw target only has one op in the post-MDB world.
    }

    sk_sp<SkImage> fSrcImage;
    sk_sp<SkShader> fSrcImageShader;

    using INHERITED = GM;
};

DEF_GM( return new CroppedRectsGM(); )

}  // namespace skiagm
