/*
 * Copyright 2013 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/SkPaint.h"
#include "include/core/SkPathBuilder.h"
#include "include/core/SkPoint.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/SkFloatBits.h"
#include "include/private/base/SkTArray.h"

using namespace skia_private;

class ConicPathsGM : public skiagm::GM {
protected:

    SkString onShortName() override {
        return SkString("conicpaths");
    }

    SkISize onISize() override {
        return SkISize::Make(920, 960);
    }

    template <typename Proc> void append_path(Proc proc) {
        SkPathBuilder b;
        proc(&b);
        fPaths.push_back(b.detach());
    }

    void onOnceBeforeDraw() override {
        this->append_path([](SkPathBuilder* conicCircle) {
            const SkScalar w = SkScalarSqrt(2)/2;
            conicCircle->moveTo(0, 0);
            conicCircle->conicTo(0, 50, 50, 50, w);
            conicCircle->rConicTo(50, 0, 50, -50, w);
            conicCircle->rConicTo(0, -50, -50, -50, w);
            conicCircle->rConicTo(-50, 0, -50, 50, w);
        });

        this->append_path([](SkPathBuilder* hyperbola) {
            hyperbola->moveTo(0, 0);
            hyperbola->conicTo(0, 100, 100, 100, 2);
        });

        this->append_path([](SkPathBuilder* thinHyperbola) {
            thinHyperbola->moveTo(0, 0);
            thinHyperbola->conicTo(100, 100, 5, 0, 2);
        });

        this->append_path([](SkPathBuilder* veryThinHyperbola) {
            veryThinHyperbola->moveTo(0, 0);
            veryThinHyperbola->conicTo(100, 100, 1, 0, 2);
        });

        this->append_path([](SkPathBuilder* closedHyperbola) {
            closedHyperbola->moveTo(0, 0);
            closedHyperbola->conicTo(100, 100, 0, 0, 2);
        });

        this->append_path([](SkPathBuilder* nearParabola) {
            // using 1 as weight defaults to using quadTo
            nearParabola->moveTo(0, 0);
            nearParabola->conicTo(0, 100, 100, 100, 0.999f);
        });

        this->append_path([](SkPathBuilder* thinEllipse) {
            thinEllipse->moveTo(0, 0);
            thinEllipse->conicTo(100, 100, 5, 0, SK_ScalarHalf);
        });

        this->append_path([](SkPathBuilder* veryThinEllipse) {
            veryThinEllipse->moveTo(0, 0);
            veryThinEllipse->conicTo(100, 100, 1, 0, SK_ScalarHalf);
        });

        this->append_path([](SkPathBuilder* closedEllipse) {
            closedEllipse->moveTo(0,  0);
            closedEllipse->conicTo(100, 100, 0, 0, SK_ScalarHalf);
        });

        {
            SkPathBuilder b;
            const SkScalar w = SkScalarSqrt(2)/2;
            b.moveTo(2.1e+11f, -1.05e+11f);
            b.conicTo(2.1e+11f, 0, 1.05e+11f, 0, w);
            b.conicTo(0, 0, 0, -1.05e+11f, w);
            b.conicTo(0, -2.1e+11f, 1.05e+11f, -2.1e+11f, w);
            b.conicTo(2.1e+11f, -2.1e+11f, 2.1e+11f, -1.05e+11f, w);
            fGiantCircle = b.detach();
        }
    }

    void drawGiantCircle(SkCanvas* canvas) {
        SkPaint paint;
        canvas->drawPath(fGiantCircle, paint);
    }

    void onDraw(SkCanvas* canvas) override {
        const SkAlpha kAlphaValue[] = { 0xFF, 0x40 };

        const SkScalar margin = 15;
        canvas->translate(margin, margin);

        SkPaint paint;
        for (int p = 0; p < fPaths.size(); ++p) {
            canvas->save();
            for (size_t a = 0; a < std::size(kAlphaValue); ++a) {
                paint.setARGB(kAlphaValue[a], 0, 0, 0);
                for (int aa = 0; aa < 2; ++aa) {
                    paint.setAntiAlias(SkToBool(aa));
                    for (int fh = 0; fh < 2; ++fh) {
                        paint.setStroke(fh != 0);

                        const SkRect& bounds = fPaths[p].getBounds();
                        canvas->save();
                        canvas->translate(-bounds.fLeft, -bounds.fTop);
                        canvas->drawPath(fPaths[p], paint);
                        canvas->restore();

                        canvas->translate(110, 0);
                    }
                }
            }
            canvas->restore();
            canvas->translate(0, 110);
        }
        canvas->restore();

        this->drawGiantCircle(canvas);
    }

private:
    TArray<SkPath> fPaths;
    SkPath           fGiantCircle;
    using INHERITED = skiagm::GM;
};
DEF_GM(return new ConicPathsGM;)

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

/* arc should be on top of circle */
DEF_SIMPLE_GM(arccirclegap, canvas, 250, 250) {
    canvas->translate(50, 100);
    SkPoint c = { 1052.5390625f, 506.8760978034711f };
    SkScalar radius = 1096.702150363923f;
    SkPaint paint;
    paint.setAntiAlias(true);
    paint.setStroke(true);
    canvas->drawCircle(c, radius, paint);
    SkPath path = SkPathBuilder().moveTo(288.88884710654133f, -280.26680862609f)
                                 .arcTo({0, 0}, {-39.00216443306411f, 400.6058925796476f}, radius)
                                 .detach();
    paint.setColor(0xff007f00);
    canvas->drawPath(path, paint);
}

/* circle should be antialiased */
DEF_SIMPLE_GM(largecircle, canvas, 250, 250) {
    canvas->translate(50, 100);
    SkPoint c = { 1052.5390625f, 506.8760978034711f };
    SkScalar radius = 1096.702150363923f;
    SkPaint paint;
    paint.setAntiAlias(true);
    paint.setStroke(true);
    canvas->drawCircle(c, radius, paint);
}

/* ovals should not be blurry */
DEF_SIMPLE_GM(largeovals, canvas, 250, 250) {
    // Test EllipseOp
    SkRect r = SkRect::MakeXYWH(-520, -520, 5000, 4000);
    SkPaint paint;
    paint.setAntiAlias(true);
    paint.setStroke(true);
    paint.setStrokeWidth(100);
    canvas->drawOval(r, paint);
    r.offset(-15, -15);
    paint.setColor(SK_ColorDKGRAY);
    // we use stroke and fill to avoid falling into the SimpleFill path
    paint.setStyle(SkPaint::kStrokeAndFill_Style);
    paint.setStrokeWidth(1);
    canvas->drawOval(r, paint);

    // Test DIEllipseOp
    canvas->rotate(1.0f);
    r.offset(55, 55);
    paint.setColor(SK_ColorGRAY);
    paint.setStroke(true);
    paint.setStrokeWidth(100);
    canvas->drawOval(r, paint);
    r.offset(-15, -15);
    paint.setColor(SK_ColorLTGRAY);
    paint.setStyle(SkPaint::kStrokeAndFill_Style);
    paint.setStrokeWidth(1);
    canvas->drawOval(r, paint);
}

DEF_SIMPLE_GM(crbug_640176, canvas, 250, 250) {
    SkPathBuilder path;
    path.moveTo(SkBits2Float(0x00000000), SkBits2Float(0x00000000));  // 0, 0
    path.lineTo(SkBits2Float(0x42cfd89a), SkBits2Float(0xc2700000));  // 103.923f, -60
    path.lineTo(SkBits2Float(0x42cfd899), SkBits2Float(0xc2700006));  // 103.923f, -60
    path.conicTo(SkBits2Float(0x42f00000), SkBits2Float(0xc2009d9c),
            SkBits2Float(0x42f00001), SkBits2Float(0x00000000),
            SkBits2Float(0x3f7746ea));  // 120, -32.1539f, 120, 0, 0.965926f

    SkPaint paint;
    paint.setAntiAlias(true);
    canvas->translate(125, 125);
    canvas->drawPath(path.detach(), paint);
}
