/*
 * Copyright 2018 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "SkPathMeasure.h"
#include "SkTrimPathEffect.h"
#include "SkTrimPE.h"
#include "SkReadBuffer.h"
#include "SkWriteBuffer.h"

namespace {

class Segmentator : public SkNoncopyable {
public:
    Segmentator(const SkPath& src, SkPath* dst)
        : fMeasure(src, false)
        , fDst(dst) {}

    void add(SkScalar start, SkScalar stop) {
        SkASSERT(start < stop);

        // TODO: we appear to skip zero-length contours.
        do {
            const auto nextOffset = fCurrentSegmentOffset + fMeasure.getLength();

            if (start < nextOffset) {
                fMeasure.getSegment(start - fCurrentSegmentOffset,
                                    stop  - fCurrentSegmentOffset,
                                    fDst, true);

                if (stop < nextOffset)
                    break;
            }

            fCurrentSegmentOffset = nextOffset;
        } while (fMeasure.nextContour());
    }

private:
    SkPathMeasure fMeasure;
    SkPath*       fDst;

    SkScalar fCurrentSegmentOffset = 0;

    using INHERITED = SkNoncopyable;
};

} // namespace

SkTrimPE::SkTrimPE(SkScalar startT, SkScalar stopT, SkTrimPathEffect::Mode mode)
    : fStartT(startT), fStopT(stopT), fMode(mode) {}

bool SkTrimPE::filterPath(SkPath* dst, const SkPath& src, SkStrokeRec* rec,
                            const SkRect* cullRect) const {
    if (fStartT >= fStopT) {
        SkASSERT(fMode == SkTrimPathEffect::Mode::kNormal);
        return true;
    }

    // First pass: compute the total len.
    SkScalar len = 0;
    SkPathMeasure meas(src, false);
    do {
        len += meas.getLength();
    } while (meas.nextContour());

    const auto arcStart = len * fStartT,
               arcStop  = len * fStopT;

    // Second pass: actually add segments.
    Segmentator segmentator(src, dst);
    if (fMode == SkTrimPathEffect::Mode::kNormal) {
        if (arcStart < arcStop) segmentator.add(arcStart, arcStop);
    } else {
        if (0 <  arcStart) segmentator.add(0,  arcStart);
        if (arcStop < len) segmentator.add(arcStop, len);
    }

    return true;
}

void SkTrimPE::flatten(SkWriteBuffer& buffer) const {
    buffer.writeScalar(fStartT);
    buffer.writeScalar(fStopT);
    buffer.writeUInt(static_cast<uint32_t>(fMode));
}

sk_sp<SkFlattenable> SkTrimPE::CreateProc(SkReadBuffer& buffer) {
    const auto start = buffer.readScalar(),
               stop  = buffer.readScalar();
    const auto mode  = buffer.readUInt();

    return SkTrimPathEffect::Make(start, stop,
        (mode & 1) ? SkTrimPathEffect::Mode::kInverted : SkTrimPathEffect::Mode::kNormal);
}

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

sk_sp<SkPathEffect> SkTrimPathEffect::Make(SkScalar startT, SkScalar stopT, Mode mode) {
    if (!SkScalarsAreFinite(startT, stopT)) {
        return nullptr;
    }

    if (startT <= 0 && stopT >= 1 && mode == Mode::kNormal) {
        return nullptr;
    }

    startT = SkTPin(startT, 0.f, 1.f);
    stopT  = SkTPin(stopT,  0.f, 1.f);

    if (startT >= stopT && mode == Mode::kInverted) {
        return nullptr;
    }

    return sk_sp<SkPathEffect>(new SkTrimPE(startT, stopT, mode));
}
