/*
 * 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, rt);
                    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
