/*
 * 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/effects/Sk2DPathEffect.h"

#include "include/core/SkFlattenable.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPath.h"
#include "include/core/SkPathBuilder.h"
#include "include/core/SkPathEffect.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRect.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkRegion.h"
#include "include/core/SkScalar.h"
#include "include/core/SkStrokeRec.h"
#include "include/core/SkTypes.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, SkPathBuilder* dst) const {}
    virtual void next(const SkPoint& loc, int u, int v, SkPathBuilder* dst) const {}
    virtual void end(SkPathBuilder* 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, SkPathBuilder* builder) const {
        if (!fMatrixIsInvertible) {
            return;
        }
    #if defined(SK_BUILD_FOR_FUZZER)
        if (ucount > 100) {
            return;
        }
    #endif

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

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

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

    void flatten(SkWriteBuffer& buffer) const override {
        buffer.writeMatrix(fMatrix);
    }

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

        SkPath tmp = src.makeTransform(fInverse);
        SkIRect ir = tmp.getBounds().round();
        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();
#if defined(SK_BUILD_FOR_FUZZER)
                if (rect.height() > 100) {
                    continue;
                }
#endif
                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;
};

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

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

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

    void nextSpan(int u, int v, int ucount, SkPathBuilder* 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);

            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 SkPath2DPathEffectImpl : public Sk2DPathEffect {
public:
    SkPath2DPathEffectImpl(const SkMatrix& m, const SkPath& p) : INHERITED(m), fPath(p) {}

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

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

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