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

#include "include/core/SkContourMeasure.h"
#include "include/core/SkPath.h"
#include "include/core/SkPathBuilder.h"
#include "include/core/SkPathMeasure.h"
#include "include/core/SkPathTypes.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkScalar.h"
#include "include/core/SkTypes.h"
#include "src/core/SkPathMeasurePriv.h"
#include "tests/Test.h"

#include <array>
#include <cstddef>
#include <initializer_list>
#include <utility>

static void test_small_segment3(skiatest::Reporter* reporter) {
    constexpr auto pts = std::to_array<SkPoint>({
            SkPoint{0, 0},
            SkPoint{100000000000.0f, 100000000000.0f},
            SkPoint{0, 0},
            SkPoint{10, 10},
            SkPoint{10, 10},
            SkPoint{0, 0},
            SkPoint{10, 10},
    });

    SkPathBuilder builder;
    builder.moveTo(pts[0]);
    for (size_t i = 1; i < std::size(pts); i += 3) {
        builder.cubicTo(pts[i], pts[i + 1], pts[i + 2]);
    }

    SkPath path = builder.detach();
    SkPathMeasure meas(path, false);
    meas.getLength();

    // Now check that we cap the segment size even with very large resolution scales.
    // Earlier versions allowed the pathmeasure to recurse without limit in the face
    // of a very large scale.
    //
    //  Before this limit, the above meas had 15K segments, and when built with
    // a resScale of 100, it had 184K segments -- for 1 cubic!
    {
        auto n = SkPathMeasurePriv::CountSegments(meas);
        REPORTER_ASSERT(reporter, n < 300);

        constexpr float resScale = 1000;
        n = SkPathMeasurePriv::CountSegments(SkPathMeasure(path, false, resScale));
        REPORTER_ASSERT(reporter, n < 300);
    }
}

static void test_small_segment2() {
    constexpr auto pts = std::to_array<SkPoint>({
            SkPoint{0, 0},
            SkPoint{100000000000.0f, 100000000000.0f},
            SkPoint{0, 0},
            SkPoint{10, 10},
            SkPoint{0, 0},
    });

    SkPathBuilder builder;
    builder.moveTo(pts[0]);
    for (size_t i = 1; i < std::size(pts); i += 2) {
        builder.quadTo(pts[i], pts[i + 1]);
    }
    SkPathMeasure meas(builder.detach(), false);
    meas.getLength();
}

static void test_small_segment() {
    const SkPoint pts[] = {
        { 100000, 100000},
        // big jump between these points, makes a big segment
        { 1.0005f, 0.9999f },
        // tiny (non-zero) jump between these points
        { SK_Scalar1, SK_Scalar1 },
    };

    SkPathMeasure meas(SkPath::Polygon(pts, false), false);

    /*  this would assert (before a fix) because we added a segment with
        the same length as the prev segment, due to the follow (bad) pattern

        d = distance(pts[0], pts[1]);
        distance += d;
        seg->fDistance = distance;

        SkASSERT(d > 0);    // TRUE
        SkASSERT(seg->fDistance > prevSeg->fDistance);  // FALSE

        This 2nd assert failes because (distance += d) didn't affect distance
        because distance >>> d.
     */
    meas.getLength();
}

DEF_TEST(PathMeasure, reporter) {
    SkPath path = SkPathBuilder()
                  .moveTo(0, 0)
                  .lineTo(1, 0)
                  .lineTo(1, 1)
                  .lineTo(0, 1)
                  .detach();

    SkPathMeasure   meas(path, true);
    SkScalar        length = meas.getLength();
    SkASSERT(length == 4);

    path = SkPath::Line({0, 0}, {3, 4});
    meas.setPath(&path, false);
    length = meas.getLength();
    REPORTER_ASSERT(reporter, length == 5);

    path = SkPath::Circle(0, 0, 1);
    meas.setPath(&path, true);
    length = meas.getLength();
//    SkDebugf("circle arc-length = %g\n", length);

    // Test the behavior following a close not followed by a move.
    path = SkPathBuilder()
           .lineTo(1, 0)
           .lineTo(1, 1)
           .lineTo(0, 1)
           .close()
           .lineTo(-1, 0)
           .detach();
    meas.setPath(&path, false);
    length = meas.getLength();
    REPORTER_ASSERT(reporter, length == SK_Scalar1 * 4);
    meas.nextContour();
    length = meas.getLength();
    REPORTER_ASSERT(reporter, length == SK_Scalar1);
    SkPoint position;
    SkVector tangent;
    REPORTER_ASSERT(reporter, meas.getPosTan(SK_ScalarHalf, &position, &tangent));
    REPORTER_ASSERT(reporter,
        SkScalarNearlyEqual(position.fX,
                            -SK_ScalarHalf,
                            0.0001f));
    REPORTER_ASSERT(reporter, position.fY == 0);
    REPORTER_ASSERT(reporter, tangent.fX == -SK_Scalar1);
    REPORTER_ASSERT(reporter, tangent.fY == 0);

    // Test degenerate paths
    path = SkPathBuilder()
           .moveTo(0, 0)
           .lineTo(0, 0)
           .lineTo(1, 0)
           .quadTo(1, 0, 1, 0)
           .quadTo(1, 1, 1, 2)
           .cubicTo(1, 2, 1, 2, 1, 2)
           .cubicTo(2, 2, 3, 2, 4, 2)
           .detach();
    meas.setPath(&path, false);
    length = meas.getLength();
    REPORTER_ASSERT(reporter, length == SK_Scalar1 * 6);
    REPORTER_ASSERT(reporter, meas.getPosTan(SK_ScalarHalf, &position, &tangent));
    REPORTER_ASSERT(reporter,
        SkScalarNearlyEqual(position.fX,
                            SK_ScalarHalf,
                            0.0001f));
    REPORTER_ASSERT(reporter, position.fY == 0);
    REPORTER_ASSERT(reporter, tangent.fX == SK_Scalar1);
    REPORTER_ASSERT(reporter, tangent.fY == 0);
    REPORTER_ASSERT(reporter, meas.getPosTan(2.5f, &position, &tangent));
    REPORTER_ASSERT(reporter,
        SkScalarNearlyEqual(position.fX, SK_Scalar1, 0.0001f));
    REPORTER_ASSERT(reporter,
        SkScalarNearlyEqual(position.fY, 1.5f));
    REPORTER_ASSERT(reporter, tangent.fX == 0);
    REPORTER_ASSERT(reporter, tangent.fY == SK_Scalar1);
    REPORTER_ASSERT(reporter, meas.getPosTan(4.5f, &position, &tangent));
    REPORTER_ASSERT(reporter,
        SkScalarNearlyEqual(position.fX,
                            2.5f,
                            0.0001f));
    REPORTER_ASSERT(reporter,
        SkScalarNearlyEqual(position.fY,
                            2.0f,
                            0.0001f));
    REPORTER_ASSERT(reporter, tangent.fX == SK_Scalar1);
    REPORTER_ASSERT(reporter, tangent.fY == 0);

    path = SkPathBuilder()
           .moveTo(0, 0)
           .lineTo(1, 0)
           .moveTo(1, 1)
           .moveTo(2, 2)
           .lineTo(1, 2)
           .detach();
    meas.setPath(&path, false);
    length = meas.getLength();
    REPORTER_ASSERT(reporter, length == 1);
    REPORTER_ASSERT(reporter, meas.getPosTan(0.5f, &position, &tangent));
    REPORTER_ASSERT(reporter,
        SkScalarNearlyEqual(position.fX,
                            0.5f,
                            0.0001f));
    REPORTER_ASSERT(reporter, position.fY == 0);
    REPORTER_ASSERT(reporter, tangent.fX == 1);
    REPORTER_ASSERT(reporter, tangent.fY == 0);
    meas.nextContour();
    length = meas.getLength();
    REPORTER_ASSERT(reporter, length == 1);
    REPORTER_ASSERT(reporter, meas.getPosTan(0.5f, &position, &tangent));
    REPORTER_ASSERT(reporter,
        SkScalarNearlyEqual(position.fX,
                            1.5f,
                            0.0001f));
    REPORTER_ASSERT(reporter,
        SkScalarNearlyEqual(position.fY,
                            2.0f,
                            0.0001f));
    REPORTER_ASSERT(reporter, tangent.fX == -1);
    REPORTER_ASSERT(reporter, tangent.fY == 0);

    test_small_segment();
    test_small_segment2();
    test_small_segment3(reporter);

    // SkPathMeasure isn't copyable, but it should be move-able
    SkPathMeasure meas2(std::move(meas));
    meas = std::move(meas2);
}

DEF_TEST(PathMeasureConic, reporter) {
    SkPoint stdP, hiP, pts[] = {{0,0}, {100,0}, {100,0}};
    SkPath p = SkPathBuilder()
               .moveTo(0, 0)
               .conicTo(pts[1], pts[2], 1)
               .detach();
    SkPathMeasure stdm(p, false);
    REPORTER_ASSERT(reporter, stdm.getPosTan(20, &stdP, nullptr));
    p = SkPathBuilder()
        .moveTo(0, 0)
        .conicTo(pts[1], pts[2], 10)
        .detach();
    stdm.setPath(&p, false);
    REPORTER_ASSERT(reporter, stdm.getPosTan(20, &hiP, nullptr));
    REPORTER_ASSERT(reporter, 19.5f < stdP.fX && stdP.fX < 20.5f);
    REPORTER_ASSERT(reporter, 19.5f < hiP.fX && hiP.fX < 20.5f);
}

// Regression test for b/26425223
DEF_TEST(PathMeasure_nextctr, reporter) {
    SkPath path = SkPath::Line({0, 0}, {100, 0});

    SkPathMeasure meas(path, false);
    // only expect 1 contour, even if we didn't explicitly call getLength() ourselves
    REPORTER_ASSERT(reporter, !meas.nextContour());
}

static void test_90_degrees(const sk_sp<SkContourMeasure>& cm, SkScalar radius,
                            skiatest::Reporter* reporter) {
    SkPoint pos;
    SkVector tan;
    SkScalar distance = cm->length() / 4;
    bool success = cm->getPosTan(distance, &pos, &tan);

    REPORTER_ASSERT(reporter, success);
    REPORTER_ASSERT(reporter, SkScalarNearlyEqual(pos.fX, 0));
    REPORTER_ASSERT(reporter, SkScalarNearlyEqual(pos.fY, radius));
    REPORTER_ASSERT(reporter, SkScalarNearlyEqual(tan.fX, -1));
    REPORTER_ASSERT(reporter, SkScalarNearlyEqual(tan.fY, 0));
}

static void test_empty_contours(skiatest::Reporter* reporter) {
    SkPath path = SkPathBuilder()
                  .moveTo(0, 0).lineTo(100, 100).lineTo(200, 100)
                  .moveTo(2, 2).moveTo(3, 3)                  // zero-length(s)
                  .moveTo(4, 4).close().close().close()       // zero-length
                  .moveTo(5, 5).lineTo(5, 5)                  // zero-length
                  .moveTo(5, 5).lineTo(5, 5).close()          // zero-length
                  .moveTo(5, 5).lineTo(5, 5).close().close()  // zero-length
                  .moveTo(6, 6).lineTo(7, 7)
                  .moveTo(10, 10)                             // zero-length
                  .detach();

    SkContourMeasureIter fact(path, false);

    // given the above construction, we expect only 2 contours (the rest are "empty")

    REPORTER_ASSERT(reporter, fact.next());
    REPORTER_ASSERT(reporter, fact.next());
    REPORTER_ASSERT(reporter, !fact.next());
}

static void test_MLM_contours(skiatest::Reporter* reporter) {
    // This odd sequence (with a trailing moveTo) used to return a 2nd contour, which is
    // wrong, since the contract for a measure is to only return non-zero length contours.
    SkPath path = SkPathBuilder().moveTo(10, 10).lineTo(20, 20).moveTo(30, 30).detach();

    for (bool forceClosed : {false, true}) {
        SkContourMeasureIter fact(path, forceClosed);
        REPORTER_ASSERT(reporter, fact.next());
        REPORTER_ASSERT(reporter, !fact.next());
    }
}

DEF_TEST(contour_measure, reporter) {
    SkPath path = SkPathBuilder()
                  .addCircle(0, 0, 100)
                  .addCircle(0, 0, 10)
                  .detach();

    SkContourMeasureIter fact(path, false);

    auto cm0 = fact.next();
    auto cm1 = fact.next();

    REPORTER_ASSERT(reporter, cm0->isClosed());
    REPORTER_ASSERT(reporter, SkScalarNearlyEqual(cm0->length(), 200 * SK_ScalarPI, 1.5f));

    test_90_degrees(cm0, 100, reporter);

    REPORTER_ASSERT(reporter, cm1->isClosed());
    REPORTER_ASSERT(reporter, SkScalarNearlyEqual(cm1->length(), 20 * SK_ScalarPI, 0.5f));

    test_90_degrees(cm1, 10, reporter);

    auto cm2 = fact.next();
    REPORTER_ASSERT(reporter, !cm2);

    test_empty_contours(reporter);
    test_MLM_contours(reporter);
}

DEF_TEST(contour_measure_verbs, reporter) {
    SkPath path = SkPathBuilder()
                  .moveTo(10, 10)
                  .lineTo(10, 30)
                  .lineTo(30, 30)
                  .quadTo({40, 30}, {40, 40})
                  .cubicTo({50, 40}, {50, 50}, {40, 50})
                  .conicTo({50, 50}, {50, 60}, 1.2f)
                  .detach();

    SkContourMeasureIter measure(path, false);

    sk_sp<SkContourMeasure> cmeasure = measure.next();
    REPORTER_ASSERT(reporter, cmeasure);

    SkContourMeasure::ForwardVerbIterator viter = cmeasure->begin();
    {
        REPORTER_ASSERT(reporter, viter != cmeasure->end());
        const auto vmeasure = *viter;
        REPORTER_ASSERT(reporter, vmeasure.fVerb == SkPathVerb::kLine);
        REPORTER_ASSERT(reporter, SkScalarNearlyEqual(vmeasure.fDistance, 20));
        REPORTER_ASSERT(reporter, vmeasure.fPts.size() == 2);
        REPORTER_ASSERT(reporter, vmeasure.fPts[0] == SkPoint::Make(10, 10));
        REPORTER_ASSERT(reporter, vmeasure.fPts[1] == SkPoint::Make(10, 30));
    }

    ++viter;
    {
        REPORTER_ASSERT(reporter, viter != cmeasure->end());
        const auto vmeasure = *viter;
        REPORTER_ASSERT(reporter, vmeasure.fVerb == SkPathVerb::kLine);
        REPORTER_ASSERT(reporter, SkScalarNearlyEqual(vmeasure.fDistance, 40));
        REPORTER_ASSERT(reporter, vmeasure.fPts.size() == 2);
        REPORTER_ASSERT(reporter, vmeasure.fPts[0] == SkPoint::Make(10, 30));
        REPORTER_ASSERT(reporter, vmeasure.fPts[1] == SkPoint::Make(30, 30));
    }

    ++viter;
    {
        REPORTER_ASSERT(reporter, viter != cmeasure->end());
        const auto vmeasure = *viter;
        REPORTER_ASSERT(reporter, vmeasure.fVerb == SkPathVerb::kQuad);
        REPORTER_ASSERT(reporter, SkScalarNearlyEqual(vmeasure.fDistance, 56.127525f));
        REPORTER_ASSERT(reporter, vmeasure.fPts.size() == 3);
        REPORTER_ASSERT(reporter, vmeasure.fPts[0] == SkPoint::Make(30, 30));
        REPORTER_ASSERT(reporter, vmeasure.fPts[1] == SkPoint::Make(40, 30));
        REPORTER_ASSERT(reporter, vmeasure.fPts[2] == SkPoint::Make(40, 40));
    }

    ++viter;
    {
        REPORTER_ASSERT(reporter, viter != cmeasure->end());
        const auto vmeasure = *viter;
        REPORTER_ASSERT(reporter, vmeasure.fVerb == SkPathVerb::kCubic);
        REPORTER_ASSERT(reporter, SkScalarNearlyEqual(vmeasure.fDistance, 76.004692f));
        REPORTER_ASSERT(reporter, vmeasure.fPts.size() == 4);
        REPORTER_ASSERT(reporter, vmeasure.fPts[0] == SkPoint::Make(40, 40));
        REPORTER_ASSERT(reporter, vmeasure.fPts[1] == SkPoint::Make(50, 40));
        REPORTER_ASSERT(reporter, vmeasure.fPts[2] == SkPoint::Make(50, 50));
        REPORTER_ASSERT(reporter, vmeasure.fPts[3] == SkPoint::Make(40, 50));
    }

    ++viter;
    {
        REPORTER_ASSERT(reporter, viter != cmeasure->end());
        const auto vmeasure = *viter;
        REPORTER_ASSERT(reporter, vmeasure.fVerb == SkPathVerb::kConic);
        REPORTER_ASSERT(reporter, SkScalarNearlyEqual(vmeasure.fDistance, 92.428185f));
        REPORTER_ASSERT(reporter, vmeasure.fPts.size() == 4);
        REPORTER_ASSERT(reporter, vmeasure.fPts[0] == SkPoint::Make(40, 50));
        REPORTER_ASSERT(reporter, vmeasure.fPts[1] == SkPoint::Make(1.2f, 0));
        REPORTER_ASSERT(reporter, vmeasure.fPts[2] == SkPoint::Make(50, 50));
        REPORTER_ASSERT(reporter, vmeasure.fPts[3] == SkPoint::Make(50, 60));

        // The last verb distance should also match the contour length.
        REPORTER_ASSERT(reporter, SkScalarNearlyEqual(vmeasure.fDistance, cmeasure->length()));
    }

    ++viter;
    {
        REPORTER_ASSERT(reporter, viter == cmeasure->end());
    }

    // Exercise the range iterator form.
    float current_distance = 0;
    size_t verb_count = 0;
    for (const auto vmeasure : *cmeasure) {
        REPORTER_ASSERT(reporter, vmeasure.fDistance > current_distance);
        current_distance = vmeasure.fDistance;
        verb_count++;
    }
    REPORTER_ASSERT(reporter, verb_count == 5);
}
