/*
 * 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"

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:
    SkTArray<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);
}
