/*
 * Copyright 2006 The Android Open Source Project
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "include/core/SkPath.h"
#include "include/core/SkRegion.h"
#include "include/core/SkStrokeRec.h"
#include "include/effects/Sk2DPathEffect.h"
#include "src/core/SkPathEffectBase.h"
#include "src/core/SkReadBuffer.h"
#include "src/core/SkWriteBuffer.h"

class Sk2DPathEffect : public SkPathEffectBase {
public:
    Sk2DPathEffect(const SkMatrix& mat) : fMatrix(mat) {
        // Calling invert will set the type mask on both matrices, making them thread safe.
        fMatrixIsInvertible = fMatrix.invert(&fInverse);
    }

protected:
    /** New virtual, to be overridden by subclasses.
        This is called once from filterPath, and provides the
        uv parameter bounds for the path. Subsequent calls to
        next() will receive u and v values within these bounds,
        and then a call to end() will signal the end of processing.
    */
    virtual void begin(const SkIRect& uvBounds, SkPath* dst) const {}
    virtual void next(const SkPoint& loc, int u, int v, SkPath* dst) const {}
    virtual void end(SkPath* dst) const {}

    /** Low-level virtual called per span of locations in the u-direction.
        The default implementation calls next() repeatedly with each
        location.
    */
    virtual void nextSpan(int x, int y, int ucount, SkPath* path) const {
        if (!fMatrixIsInvertible) {
            return;
        }
    #if defined(SK_BUILD_FOR_FUZZER)
        if (count > 100) {
            return;
        }
    #endif

        const SkMatrix& mat = this->getMatrix();
        SkPoint src, dst;

        src.set(SkIntToScalar(x) + SK_ScalarHalf, SkIntToScalar(y) + SK_ScalarHalf);
        do {
            mat.mapPoints(&dst, &src, 1);
            this->next(dst, x++, y, path);
            src.fX += SK_Scalar1;
        } while (--ucount > 0);
    }

    const SkMatrix& getMatrix() const { return fMatrix; }

    void flatten(SkWriteBuffer& buffer) const override {
        this->INHERITED::flatten(buffer);
        buffer.writeMatrix(fMatrix);
    }

    bool onFilterPath(SkPath* dst, const SkPath& src, SkStrokeRec* rec,
                      const SkRect* cullRect) const override {
        if (!fMatrixIsInvertible) {
            return false;
        }

        SkPath  tmp;
        SkIRect ir;

        src.transform(fInverse, &tmp);
        tmp.getBounds().round(&ir);
        if (!ir.isEmpty()) {
            this->begin(ir, dst);

            SkRegion rgn;
            rgn.setPath(tmp, SkRegion(ir));
            SkRegion::Iterator iter(rgn);
            for (; !iter.done(); iter.next()) {
                const SkIRect& rect = iter.rect();
                for (int y = rect.fTop; y < rect.fBottom; ++y) {
                    this->nextSpan(rect.fLeft, y, rect.width(), dst);
                }
            }

            this->end(dst);
        }
        return true;
    }

private:
    SkMatrix    fMatrix, fInverse;
    bool        fMatrixIsInvertible;

    // For simplicity, assume fast bounds cannot be computed
    bool computeFastBounds(SkRect*) const override { return false; }

    friend class Sk2DPathEffectBlitter;
    using INHERITED = SkPathEffect;
};

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

class SkLine2DPathEffectImpl : public Sk2DPathEffect {
public:
    SkLine2DPathEffectImpl(SkScalar width, const SkMatrix& matrix)
        : Sk2DPathEffect(matrix)
        , fWidth(width)
    {
        SkASSERT(width >= 0);
    }

    bool onFilterPath(SkPath* dst, const SkPath& src, SkStrokeRec* rec,
                      const SkRect* cullRect) const override {
        if (this->INHERITED::onFilterPath(dst, src, rec, cullRect)) {
            rec->setStrokeStyle(fWidth);
            return true;
        }
        return false;
    }

    void nextSpan(int u, int v, int ucount, SkPath* dst) const override {
        if (ucount > 1) {
            SkPoint    src[2], dstP[2];

            src[0].set(SkIntToScalar(u) + SK_ScalarHalf, SkIntToScalar(v) + SK_ScalarHalf);
            src[1].set(SkIntToScalar(u+ucount) + SK_ScalarHalf, SkIntToScalar(v) + SK_ScalarHalf);
            this->getMatrix().mapPoints(dstP, src, 2);

            dst->moveTo(dstP[0]);
            dst->lineTo(dstP[1]);
        }
    }

    static sk_sp<SkFlattenable> CreateProc(SkReadBuffer& buffer) {
        SkMatrix matrix;
        buffer.readMatrix(&matrix);
        SkScalar width = buffer.readScalar();
        return SkLine2DPathEffect::Make(width, matrix);
    }

    void flatten(SkWriteBuffer &buffer) const override {
        buffer.writeMatrix(this->getMatrix());
        buffer.writeScalar(fWidth);
    }

    Factory getFactory() const override { return CreateProc; }
    const char* getTypeName() const override { return "SkLine2DPathEffect"; }

private:
    SkScalar fWidth;

    using INHERITED = Sk2DPathEffect;
};

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

class SK_API SkPath2DPathEffectImpl : public Sk2DPathEffect {
public:
    SkPath2DPathEffectImpl(const SkMatrix& m, const SkPath& p) : INHERITED(m), fPath(p) {}

    void next(const SkPoint& loc, int u, int v, SkPath* dst) const override {
        dst->addPath(fPath, loc.fX, loc.fY);
    }

    static sk_sp<SkFlattenable> CreateProc(SkReadBuffer& buffer) {
        SkMatrix matrix;
        buffer.readMatrix(&matrix);
        SkPath path;
        buffer.readPath(&path);
        return SkPath2DPathEffect::Make(matrix, path);
    }

    void flatten(SkWriteBuffer& buffer) const override {
        buffer.writeMatrix(this->getMatrix());
        buffer.writePath(fPath);
    }

    Factory getFactory() const override { return CreateProc; }
    const char* getTypeName() const override { return "SkPath2DPathEffect"; }

private:
    SkPath  fPath;

    using INHERITED = Sk2DPathEffect;
};

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

sk_sp<SkPathEffect> SkLine2DPathEffect::Make(SkScalar width, const SkMatrix& matrix) {
    if (!(width >= 0)) {
        return nullptr;
    }
    return sk_sp<SkPathEffect>(new SkLine2DPathEffectImpl(width, matrix));
}

sk_sp<SkPathEffect> SkPath2DPathEffect::Make(const SkMatrix& matrix, const SkPath& path) {
    return sk_sp<SkPathEffect>(new SkPath2DPathEffectImpl(matrix, path));
}

void SkLine2DPathEffect::RegisterFlattenables() {
    SK_REGISTER_FLATTENABLE(SkLine2DPathEffectImpl);
}

void SkPath2DPathEffect::RegisterFlattenables() {
    SK_REGISTER_FLATTENABLE(SkPath2DPathEffectImpl);
}
