/*
 * 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/SkFloatBits.h"
#include "include/private/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.count(); ++p) {
            canvas->save();
            for (size_t a = 0; a < SK_ARRAY_COUNT(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);
}
