/*
 * 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/SkImageInfo.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRRect.h"
#include "include/core/SkRect.h"
#include "include/core/SkScalar.h"
#include "include/core/SkSize.h"
#include "include/core/SkString.h"
#include "include/core/SkTypes.h"
#include "include/private/base/SkTArray.h"
#include "src/base/SkRandom.h"

using namespace skia_private;

namespace skiagm {

/*
 * This is the base class for two GMs that cover various corner cases with primitive Skia shapes
 * (zero radius, near-zero radius, inner shape overlap, etc.) It uses an xfermode of darken to help
 * double-blended and/or dropped pixels stand out.
 */
class ShapesGM : public GM {
protected:
    ShapesGM(const char* name, bool antialias) : fName(name), fAntialias(antialias) {
        if (!antialias) {
            fName.append("_bw");
        }
    }

    SkString onShortName() final { return fName; }
    SkISize onISize() override { return SkISize::Make(500, 500); }

    void onOnceBeforeDraw() override {
        fShapes.push_back().setOval(SkRect::MakeXYWH(-5, 25, 200, 100));
        fRotations.push_back(21);

        fShapes.push_back().setRect(SkRect::MakeXYWH(95, 75, 125, 100));
        fRotations.push_back(94);

        fShapes.push_back().setRectXY(SkRect::MakeXYWH(0, 75, 150, 100), 1e-5f, 1e-5f);
        fRotations.push_back(132);

        fShapes.push_back().setRectXY(SkRect::MakeXYWH(15, -20, 100, 100), 20, 15);
        fRotations.push_back(282);

        fSimpleShapeCount = fShapes.size();

        fShapes.push_back().setNinePatch(SkRect::MakeXYWH(140, -50, 90, 110), 10, 5, 25, 35);
        fRotations.push_back(0);

        fShapes.push_back().setNinePatch(SkRect::MakeXYWH(160, -60, 60, 90), 10, 60, 50, 30);
        fRotations.push_back(-35);

        fShapes.push_back().setNinePatch(SkRect::MakeXYWH(220, -120, 60, 90), 1, 89, 59, 1);
        fRotations.push_back(65);

        SkVector radii[4] = {{4, 6}, {12, 8}, {24, 16}, {32, 48}};
        fShapes.push_back().setRectRadii(SkRect::MakeXYWH(150, -129, 80, 160), radii);
        fRotations.push_back(265);

        SkVector radii2[4] = {{0, 0}, {80, 60}, {0, 0}, {80, 60}};
        fShapes.push_back().setRectRadii(SkRect::MakeXYWH(180, -30, 80, 60), radii2);
        fRotations.push_back(295);

        fPaint.setAntiAlias(fAntialias);
    }

    void onDraw(SkCanvas* canvas) override {
        canvas->clear(SK_ColorWHITE);

        canvas->save();
        canvas->translate(canvas->imageInfo().width() / 2.f, canvas->imageInfo().height() / 2.f);
        this->drawShapes(canvas);
        canvas->restore();
    }

    virtual void drawShapes(SkCanvas* canvas) const = 0;

protected:
    SkString             fName;
    bool                 fAntialias;
    SkPaint              fPaint;
    TArray<SkRRect>    fShapes;
    TArray<SkScalar>   fRotations;
    int                  fSimpleShapeCount;

private:
    using INHERITED = GM;
};

class SimpleShapesGM : public ShapesGM {
public:
    SimpleShapesGM(bool antialias) : INHERITED("simpleshapes", antialias) {}

private:
    void drawShapes(SkCanvas* canvas) const override {
        SkRandom rand(2);
        for (int i = 0; i < fShapes.size(); i++) {
            SkPaint paint(fPaint);
            paint.setColor(rand.nextU() & ~0x808080);
            paint.setAlphaf(0.5f);  // Use alpha to detect double blends.
            const SkRRect& shape = fShapes[i];
            canvas->save();
            canvas->rotate(fRotations[i]);
            switch (shape.getType()) {
                case SkRRect::kRect_Type:
                    canvas->drawRect(shape.rect(), paint);
                    break;
                case SkRRect::kOval_Type:
                    canvas->drawOval(shape.rect(), paint);
                    break;
                default:
                    canvas->drawRRect(shape, paint);
                    break;
            }
            canvas->restore();
        }
    }

    using INHERITED = ShapesGM;
};

class InnerShapesGM : public ShapesGM {
public:
    InnerShapesGM(bool antialias) : INHERITED("innershapes", antialias) {}

private:
    void drawShapes(SkCanvas* canvas) const override {
        SkRandom rand;
        for (int i = 0; i < fShapes.size(); i++) {
            const SkRRect& outer = fShapes[i];
            const SkRRect& inner = fShapes[(i * 7 + 11) % fSimpleShapeCount];
            float s = 0.95f * std::min(outer.rect().width() / inner.rect().width(),
                                       outer.rect().height() / inner.rect().height());
            SkMatrix innerXform;
            float dx = (rand.nextF() - 0.5f) * (outer.rect().width() - s * inner.rect().width());
            float dy = (rand.nextF() - 0.5f) * (outer.rect().height() - s * inner.rect().height());
            // Fixup inner rects so they don't reach outside the outer rect.
            switch (i) {
                case 0:
                    s *= .85f;
                    break;
                case 8:
                    s *= .4f;
                    dx = dy = 0;
                    break;
                case 5:
                    s *= .75f;
                    dx = dy = 0;
                    break;
                case 6:
                    s *= .65f;
                    dx = -5;
                    dy = 10;
                    break;
            }
            innerXform.setTranslate(outer.rect().centerX() + dx, outer.rect().centerY() + dy);
            if (s < 1) {
                innerXform.preScale(s, s);
            }
            innerXform.preTranslate(-inner.rect().centerX(), -inner.rect().centerY());
            SkRRect xformedInner;
            inner.transform(innerXform, &xformedInner);
            SkPaint paint(fPaint);
            paint.setColor(rand.nextU() & ~0x808080);
            paint.setAlphaf(0.5f);  // Use alpha to detect double blends.
            canvas->save();
            canvas->rotate(fRotations[i]);
            canvas->drawDRRect(outer, xformedInner, paint);
            canvas->restore();
        }
    }

    using INHERITED = ShapesGM;
};

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

DEF_GM( return new SimpleShapesGM(true); )
DEF_GM( return new SimpleShapesGM(false); )
DEF_GM( return new InnerShapesGM(true); )
DEF_GM( return new InnerShapesGM(false); )

}  // namespace skiagm
