/*
 * Copyright 2012 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/SkMatrix.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPathBuilder.h"
#include "include/core/SkPathEffect.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkScalar.h"
#include "include/core/SkSize.h"
#include "include/core/SkString.h"
#include "include/core/SkTypes.h"
#include "include/effects/Sk1DPathEffect.h"
#include "include/effects/Sk2DPathEffect.h"
#include "include/effects/SkCornerPathEffect.h"
#include "include/effects/SkDashPathEffect.h"
#include "include/effects/SkDiscretePathEffect.h"
#include "include/effects/SkOpPathEffect.h"
#include "include/pathops/SkPathOps.h"

#include <initializer_list>

namespace skiagm {

static void compose_pe(SkPaint* paint) {
    SkPathEffect* pe = paint->getPathEffect();
    sk_sp<SkPathEffect> corner = SkCornerPathEffect::Make(25);
    sk_sp<SkPathEffect> compose;
    if (pe) {
        compose = SkPathEffect::MakeCompose(sk_ref_sp(pe), corner);
    } else {
        compose = corner;
    }
    paint->setPathEffect(compose);
}

static void hair_pe(SkPaint* paint) {
    paint->setStrokeWidth(0);
}

static void hair2_pe(SkPaint* paint) {
    paint->setStrokeWidth(0);
    compose_pe(paint);
}

static void stroke_pe(SkPaint* paint) {
    paint->setStrokeWidth(12);
    compose_pe(paint);
}

static void dash_pe(SkPaint* paint) {
    SkScalar inter[] = { 20, 10, 10, 10 };
    paint->setStrokeWidth(12);
    paint->setPathEffect(SkDashPathEffect::Make(inter, std::size(inter), 0));
    compose_pe(paint);
}

constexpr int gXY[] = {
4, 0, 0, -4, 8, -4, 12, 0, 8, 4, 0, 4
};

static SkPath scale(const SkPath& path, SkScalar scale) {
    SkMatrix m;
    m.setScale(scale, scale);
    return path.makeTransform(m);
}

static void one_d_pe(SkPaint* paint) {
    SkPathBuilder b;
    b.moveTo(SkIntToScalar(gXY[0]), SkIntToScalar(gXY[1]));
    for (unsigned i = 2; i < std::size(gXY); i += 2) {
        b.lineTo(SkIntToScalar(gXY[i]), SkIntToScalar(gXY[i+1]));
    }
    b.close().offset(SkIntToScalar(-6), 0);
    SkPath path = scale(b.detach(), 1.5f);

    paint->setPathEffect(SkPath1DPathEffect::Make(path, SkIntToScalar(21), 0,
                                                  SkPath1DPathEffect::kRotate_Style));
    compose_pe(paint);
}

typedef void (*PE_Proc)(SkPaint*);
constexpr PE_Proc gPE[] = { hair_pe, hair2_pe, stroke_pe, dash_pe, one_d_pe };

static void fill_pe(SkPaint* paint) {
    paint->setStyle(SkPaint::kFill_Style);
    paint->setPathEffect(nullptr);
}

static void discrete_pe(SkPaint* paint) {
    paint->setPathEffect(SkDiscretePathEffect::Make(10, 4));
}

static sk_sp<SkPathEffect> MakeTileEffect() {
    SkMatrix m;
    m.setScale(SkIntToScalar(12), SkIntToScalar(12));

    return SkPath2DPathEffect::Make(m, SkPath::Circle(0,0,5));
}

static void tile_pe(SkPaint* paint) {
    paint->setPathEffect(MakeTileEffect());
}

constexpr PE_Proc gPE2[] = { fill_pe, discrete_pe, tile_pe };

class PathEffectGM : public GM {
public:
    PathEffectGM() {}

protected:

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

    SkISize onISize() override { return SkISize::Make(800, 600); }

    void onDraw(SkCanvas* canvas) override {
        SkPaint paint;
        paint.setAntiAlias(true);
        paint.setStyle(SkPaint::kStroke_Style);

        SkPath path = SkPath::Polygon({
            {20, 20},
            {70, 120},
            {120, 30},
            {170, 80},
            {240, 50},
        }, false);

        canvas->save();
        for (size_t i = 0; i < std::size(gPE); i++) {
            gPE[i](&paint);
            canvas->drawPath(path, paint);
            canvas->translate(0, 75);
        }
        canvas->restore();

        path.reset();
        SkRect r = { 0, 0, 250, 120 };
        path = SkPathBuilder().addOval(r, SkPathDirection::kCW)
                              .addRect(r.makeInset(50, 50), SkPathDirection::kCCW)
                              .detach();

        canvas->translate(320, 20);
        for (size_t i = 0; i < std::size(gPE2); i++) {
            gPE2[i](&paint);
            canvas->drawPath(path, paint);
            canvas->translate(0, 160);
        }

        const SkIRect rect = SkIRect::MakeXYWH(20, 20, 60, 60);
        for (size_t i = 0; i < std::size(gPE); i++) {
            SkPaint p;
            p.setAntiAlias(true);
            p.setStyle(SkPaint::kFill_Style);
            gPE[i](&p);
            canvas->drawIRect(rect, p);
            canvas->translate(75, 0);
        }
    }

private:
    using INHERITED = GM;
};

DEF_GM( return new PathEffectGM; )

}  // namespace skiagm

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

class ComboPathEfectsGM : public skiagm::GM {
public:
    ComboPathEfectsGM() {}

protected:

    SkString onShortName() override {
        return SkString("combo-patheffects");
    }

    SkISize onISize() override { return SkISize::Make(360, 630); }

    void onDraw(SkCanvas* canvas) override {
        SkPath path0 = SkPath::Circle(100, 100, 60),
               path1 = SkPathBuilder().moveTo(20, 20)
                                      .cubicTo(20, 180, 140, 0, 140, 140)
                                      .detach();

        sk_sp<SkPathEffect> effects[] = {
            nullptr,
            SkStrokePathEffect::Make(20, SkPaint::kRound_Join, SkPaint::kRound_Cap, 0),
            SkMergePathEffect::Make(nullptr,
                                    SkStrokePathEffect::Make(20, SkPaint::kRound_Join,
                                                             SkPaint::kRound_Cap, 0),
                                    kDifference_SkPathOp),
            SkMergePathEffect::Make(SkMatrixPathEffect::MakeTranslate(50, 30),
                                    SkStrokePathEffect::Make(20, SkPaint::kRound_Join,
                                                             SkPaint::kRound_Cap, 0),
                                    kReverseDifference_SkPathOp),
        };

        SkPaint wireframe;
        wireframe.setStyle(SkPaint::kStroke_Style);
        wireframe.setAntiAlias(true);

        SkPaint paint;
        paint.setColor(0xFF8888FF);
        paint.setAntiAlias(true);

        for (const SkPath& path : { path0, path1 }) {
            canvas->save();
            for (const sk_sp<SkPathEffect>& pe : effects) {
                paint.setPathEffect(pe);
                canvas->drawPath(path, paint);
                canvas->drawPath(path, wireframe);

                canvas->translate(0, 150);
            }
            canvas->restore();
            canvas->translate(180, 0);
        }
    }

private:
    using INHERITED = GM;
};
DEF_GM(return new ComboPathEfectsGM;)

#include "include/effects/SkStrokeAndFillPathEffect.h"

// Test that we can replicate SkPaint::kStrokeAndFill_Style
// with a patheffect. We expect the 2nd and 3rd columns to draw the same.
DEF_SIMPLE_GM(stroke_and_fill_patheffect, canvas, 900, 450) {
    const float kStrokeWidth = 20;

    typedef SkPath (*Maker)();
    const Maker makers[] = {
        []() { return SkPath::Oval({0, 0, 100, 100}, SkPathDirection::kCW); },
        []() { return SkPath::Oval({0, 0, 100, 100}, SkPathDirection::kCCW); },
        []() {
            const SkPoint pts[] = {
                {0, 0}, {100, 100}, {0, 100}, {100, 0},
            };
            return SkPath::Polygon(pts, std::size(pts), true);
        },
    };

    const struct {
        SkPaint::Style  fStyle;
        float           fWidth;
        bool            fUsePE;
        bool            fExpectStrokeAndFill;
    } rec[] = {
        { SkPaint::kStroke_Style,                   0, false, false },
        { SkPaint::kFill_Style,                     0,  true, false },
        { SkPaint::kStroke_Style,                   0,  true, false },
        { SkPaint::kStrokeAndFill_Style, kStrokeWidth, false, true  },
        { SkPaint::kStroke_Style,        kStrokeWidth,  true, true  },
        { SkPaint::kStrokeAndFill_Style, kStrokeWidth,  true, true  },
    };

    SkPaint paint;
    canvas->translate(20, 20);
    for (auto maker : makers) {
        const SkPath path = maker();
        canvas->save();
        for (const auto& r : rec) {
            paint.setStyle(r.fStyle);
            paint.setStrokeWidth(r.fWidth);
            paint.setPathEffect(r.fUsePE ? SkStrokeAndFillPathEffect::Make() : nullptr);
            paint.setColor(r.fExpectStrokeAndFill ? SK_ColorGRAY : SK_ColorBLACK);

            canvas->drawPath(path, paint);
            canvas->translate(150, 0);
        }
        canvas->restore();

        canvas->translate(0, 150);
    }
}

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

#include "include/core/SkStrokeRec.h"
#include "src/core/SkPathEffectBase.h"

namespace {
/**
 * Example path effect using CTM. This "strokes" a single line segment with some stroke width,
 * and then inflates the result by some number of pixels.
 */
class StrokeLineInflated : public SkPathEffectBase {
public:
    StrokeLineInflated(float strokeWidth, float pxInflate)
            : fRadius(strokeWidth / 2.f), fPxInflate(pxInflate) {}

    bool onNeedsCTM() const final { return true; }

    bool onFilterPath(SkPath* dst,
                      const SkPath& src,
                      SkStrokeRec* rec,
                      const SkRect* cullR,
                      const SkMatrix& ctm) const final {
        SkASSERT(src.countPoints() == 2);
        const SkPoint pts[2] = {src.getPoint(0), src.getPoint(1)};

        SkMatrix invCtm;
        if (!ctm.invert(&invCtm)) {
            return false;
        }

        // For a line segment, we can just map the (scaled) normal vector to pixel-space,
        // increase its length by the desired number of pixels, and then map back to canvas space.
        SkPoint n = {pts[0].fY - pts[1].fY, pts[1].fX - pts[0].fX};
        if (!n.setLength(fRadius)) {
            return false;
        }

        SkPoint mappedN = ctm.mapVector(n.fX, n.fY);
        if (!mappedN.setLength(mappedN.length() + fPxInflate)) {
            return false;
        }
        n = invCtm.mapVector(mappedN.fX, mappedN.fY);

        dst->moveTo(pts[0] + n);
        dst->lineTo(pts[1] + n);
        dst->lineTo(pts[1] - n);
        dst->lineTo(pts[0] - n);
        dst->close();

        rec->setFillStyle();

        return true;
    }

protected:
    void flatten(SkWriteBuffer&) const final {}

private:
    SK_FLATTENABLE_HOOKS(StrokeLineInflated)

    bool computeFastBounds(SkRect* bounds) const final { return false; }

    const float fRadius;
    const float fPxInflate;
};

sk_sp<SkFlattenable> StrokeLineInflated::CreateProc(SkReadBuffer&) { return nullptr; }

}  // namespace

class CTMPathEffectGM : public skiagm::GM {
protected:
    SkString onShortName() override { return SkString("ctmpatheffect"); }

    SkISize onISize() override { return SkISize::Make(800, 600); }

    // TODO: ctm-aware path effects are currently CPU only
    DrawResult onGpuSetup(GrDirectContext* dctx, SkString*) override {
        return dctx == nullptr ? DrawResult::kOk : DrawResult::kSkip;
    }

    void onDraw(SkCanvas* canvas) override {
        const float strokeWidth = 16;
        const float pxInflate = 0.5f;
        sk_sp<SkPathEffect> pathEffect(new StrokeLineInflated(strokeWidth, pxInflate));

        SkPath path;
        path.moveTo(100, 100);
        path.lineTo(200, 200);

        // Draw the inflated path, and a scaled version, in blue.
        SkPaint paint;
        paint.setAntiAlias(true);
        paint.setColor(SkColorSetA(SK_ColorBLUE, 0xff));
        paint.setPathEffect(pathEffect);
        canvas->drawPath(path, paint);
        canvas->save();
        canvas->translate(150, 0);
        canvas->scale(2.5, 0.5f);
        canvas->drawPath(path, paint);
        canvas->restore();

        // Draw the regular stroked version on top in green.
        // The inflated version should be visible underneath as a blue "border".
        paint.setPathEffect(nullptr);
        paint.setStyle(SkPaint::kStroke_Style);
        paint.setStrokeWidth(strokeWidth);
        paint.setColor(SkColorSetA(SK_ColorGREEN, 0xff));
        canvas->drawPath(path, paint);
        canvas->save();
        canvas->translate(150, 0);
        canvas->scale(2.5, 0.5f);
        canvas->drawPath(path, paint);
        canvas->restore();
    }

private:
    using INHERITED = GM;
};
DEF_GM(return new CTMPathEffectGM;)
