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

#include "gm.h"
#if SK_SUPPORT_GPU
#include "GrTest.h"
#include "effects/GrRRectEffect.h"
#include "SkDevice.h"
#include "SkRRect.h"

namespace skiagm {

///////////////////////////////////////////////////////////////////////////////

class BigRRectAAEffectGM : public GM {
public:
    BigRRectAAEffectGM() {
        this->setBGColor(sk_tool_utils::color_to_565(0xFFDDDDDD));
        this->setUpRRects();
    }

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

    SkISize onISize() override { return SkISize::Make(kImageWidth, kImageHeight); }

    void onDraw(SkCanvas* canvas) override {
        GrRenderTarget* rt = canvas->internal_private_accessTopLayerRenderTarget();
        GrContext* context = rt ? rt->getContext() : nullptr;
        if (!context) {
            skiagm::GM::DrawGpuOnlyMessage(canvas);
            return;
        }

        SkPaint paint;

#ifdef SK_DEBUG
        static const SkRect kMaxRRectBound = SkRect::MakeWH(SkIntToScalar(kMaxSize),
                                                            SkIntToScalar(kMaxSize));
        static const SkRect kMaxImageBound = SkRect::MakeWH(SkIntToScalar(kImageWidth),
                                                            SkIntToScalar(kImageHeight));
#endif

        int y = kPad;
        int x = kPad;
        static const GrPrimitiveEdgeType kEdgeTypes[] = {
            kFillAA_GrProcessorEdgeType,
            kInverseFillAA_GrProcessorEdgeType,
        };
        for (size_t et = 0; et < SK_ARRAY_COUNT(kEdgeTypes); ++et) {
            GrPrimitiveEdgeType edgeType = kEdgeTypes[et];
            for (int curRRect = 0; curRRect < fRRects.count(); ++curRRect) {
#ifdef SK_DEBUG
                SkASSERT(kMaxRRectBound.contains(fRRects[curRRect].getBounds()));
                SkRect imageSpaceBounds = fRRects[curRRect].getBounds();
                imageSpaceBounds.offset(SkIntToScalar(x), SkIntToScalar(y));
                SkASSERT(kMaxImageBound.contains(imageSpaceBounds));
#endif
                canvas->save();
                    canvas->translate(SkIntToScalar(x), SkIntToScalar(y));
                    GrTestTarget tt;
                    context->getTestTarget(&tt);
                    if (nullptr == tt.target()) {
                        SkDEBUGFAIL("Couldn't get Gr test target.");
                        return;
                    }
                    GrPipelineBuilder pipelineBuilder;

                    SkRRect rrect = fRRects[curRRect];
                    rrect.offset(SkIntToScalar(x), SkIntToScalar(y));
                    SkAutoTUnref<GrFragmentProcessor> fp(GrRRectEffect::Create(edgeType, rrect));
                    SkASSERT(fp);
                    if (fp) {
                        pipelineBuilder.addCoverageFragmentProcessor(fp);
                        pipelineBuilder.setRenderTarget(rt);

                        SkRect bounds = SkRect::MakeWH(SkIntToScalar(kMaxSize),
                                                       SkIntToScalar(kMaxSize));
                        bounds.outset(2.f, 2.f);
                        bounds.offset(SkIntToScalar(x), SkIntToScalar(y));

                        tt.target()->drawNonAARect(pipelineBuilder,
                                                   0xff000000,
                                                   SkMatrix::I(),
                                                   bounds);
                    }
                canvas->restore();
                x = x + kDrawOffset;
                if (x + kMaxSize> kImageWidth) {
                    x = kPad;
                    y += kDrawOffset;
                }
            }
        }
    }

    void setUpRRects() {
        SkScalar maxSize = SkIntToScalar(kMaxSize);
        fRRects.push()->setRect(SkRect::MakeWH(maxSize, maxSize));
        fRRects.push()->setOval(SkRect::MakeWH(maxSize, maxSize));
        fRRects.push()->setOval(SkRect::MakeWH(maxSize - 1.f, maxSize - 10.f));
        fRRects.push()->setRectXY(SkRect::MakeWH(maxSize - 1.f, maxSize - 10.f),
                                  maxSize/2.f - 10.f, maxSize/2.f - 10.f);
        fRRects.push()->setRectXY(SkRect::MakeWH(maxSize - 1.f, maxSize - 10),
                                  maxSize/2.f - 10.f, maxSize/2.f - 20.f);
    }

private:
    static const int kPad = 5;
    static const int kMaxSize = 300;
    static const int kDrawOffset = kMaxSize + kPad;

    static const int kImageWidth = 4 * kDrawOffset + kPad;
    static const int kImageHeight = 3 * kDrawOffset + kPad;


    SkTDArray<SkRRect> fRRects;
    typedef GM INHERITED;
};

///////////////////////////////////////////////////////////////////////////////

DEF_GM( return new BigRRectAAEffectGM (); )

}
#endif
