/*
 * 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 "include/core/SkPaint.h"
#include "include/core/SkPath.h"
#include "include/core/SkPathUtils.h"
#include "include/core/SkPoint.h"
#include "include/core/SkRect.h"
#include "include/core/SkScalar.h"
#include "include/core/SkStrokeRec.h"
#include "include/private/SkFloatBits.h"
#include "src/core/SkPathPriv.h"
#include "tests/Test.h"

#include <array>
#include <cstddef>
#include <cstdint>

static bool equal(const SkRect& a, const SkRect& b) {
    return  SkScalarNearlyEqual(a.left(), b.left()) &&
            SkScalarNearlyEqual(a.top(), b.top()) &&
            SkScalarNearlyEqual(a.right(), b.right()) &&
            SkScalarNearlyEqual(a.bottom(), b.bottom());
}

static void test_strokecubic(skiatest::Reporter* reporter) {
    uint32_t hexCubicVals[] = {
        0x424c1086, 0x44bcf0cb,  // fX=51.0161362 fY=1511.52478
        0x424c107c, 0x44bcf0cb,  // fX=51.0160980 fY=1511.52478
        0x424c10c2, 0x44bcf0cb,  // fX=51.0163651 fY=1511.52478
        0x424c1119, 0x44bcf0ca,  // fX=51.0166969 fY=1511.52466
    };
    SkPoint cubicVals[] = {
        {51.0161362f, 1511.52478f },
        {51.0160980f, 1511.52478f },
        {51.0163651f, 1511.52478f },
        {51.0166969f, 1511.52466f },
    };
    SkPaint paint;

    paint.setStyle(SkPaint::kStroke_Style);
    paint.setStrokeWidth(0.394537568f);
    SkPath path, fillPath;
    path.moveTo(cubicVals[0]);
    path.cubicTo(cubicVals[1], cubicVals[2], cubicVals[3]);
    skpathutils::FillPathWithPaint(path, paint, &fillPath);
    path.reset();
    path.moveTo(SkBits2Float(hexCubicVals[0]), SkBits2Float(hexCubicVals[1]));
    path.cubicTo(SkBits2Float(hexCubicVals[2]), SkBits2Float(hexCubicVals[3]),
            SkBits2Float(hexCubicVals[4]), SkBits2Float(hexCubicVals[5]),
            SkBits2Float(hexCubicVals[6]), SkBits2Float(hexCubicVals[7]));
    skpathutils::FillPathWithPaint(path, paint, &fillPath);
}

static void test_strokerect(skiatest::Reporter* reporter) {
    const SkScalar width = SkIntToScalar(10);
    SkPaint paint;

    paint.setStyle(SkPaint::kStroke_Style);
    paint.setStrokeWidth(width);

    SkRect r = { 0, 0, SkIntToScalar(200), SkIntToScalar(100) };

    SkRect outer(r);
    outer.outset(width/2, width/2);

    static const SkPaint::Join joins[] = {
        SkPaint::kMiter_Join, SkPaint::kRound_Join, SkPaint::kBevel_Join
    };

    for (size_t i = 0; i < std::size(joins); ++i) {
        paint.setStrokeJoin(joins[i]);

        SkPath path, fillPath;
        path.addRect(r);
        skpathutils::FillPathWithPaint(path, paint, &fillPath);

        REPORTER_ASSERT(reporter, equal(outer, fillPath.getBounds()));

        bool isMiter = SkPaint::kMiter_Join == joins[i];
        SkRect nested[2];
        REPORTER_ASSERT(reporter, SkPathPriv::IsNestedFillRects(fillPath, nested) == isMiter);
        if (isMiter) {
            SkRect inner(r);
            inner.inset(width/2, width/2);
            REPORTER_ASSERT(reporter, equal(nested[0], outer));
            REPORTER_ASSERT(reporter, equal(nested[1], inner));
        }
    }
}

static void test_strokerec_equality(skiatest::Reporter* reporter) {
    {
        SkStrokeRec s1(SkStrokeRec::kFill_InitStyle);
        SkStrokeRec s2(SkStrokeRec::kFill_InitStyle);
        REPORTER_ASSERT(reporter, s1.hasEqualEffect(s2));

        // Test that style mismatch is detected.
        s2.setHairlineStyle();
        REPORTER_ASSERT(reporter, !s1.hasEqualEffect(s2));

        s1.setHairlineStyle();
        REPORTER_ASSERT(reporter, s1.hasEqualEffect(s2));

        // ResScale is not part of equality.
        s1.setResScale(2.1f);
        s2.setResScale(1.2f);
        REPORTER_ASSERT(reporter, s1.hasEqualEffect(s2));
        s1.setFillStyle();
        s2.setFillStyle();
        REPORTER_ASSERT(reporter, s1.hasEqualEffect(s2));
        s1.setStrokeStyle(1.0f, false);
        s2.setStrokeStyle(1.0f, false);
        s1.setStrokeParams(SkPaint::kButt_Cap, SkPaint::kRound_Join, 2.9f);
        s2.setStrokeParams(SkPaint::kButt_Cap, SkPaint::kRound_Join, 2.9f);
        REPORTER_ASSERT(reporter, s1.hasEqualEffect(s2));
    }

    // Stroke parameters on fill or hairline style are not part of equality.
    {
        SkStrokeRec s1(SkStrokeRec::kFill_InitStyle);
        SkStrokeRec s2(SkStrokeRec::kFill_InitStyle);
        for (int i = 0; i < 2; ++i) {
            s1.setStrokeParams(SkPaint::kButt_Cap, SkPaint::kRound_Join, 2.9f);
            s2.setStrokeParams(SkPaint::kButt_Cap, SkPaint::kRound_Join, 2.1f);
            REPORTER_ASSERT(reporter, s1.hasEqualEffect(s2));
            s2.setStrokeParams(SkPaint::kButt_Cap, SkPaint::kBevel_Join, 2.9f);
            REPORTER_ASSERT(reporter, s1.hasEqualEffect(s2));
            s2.setStrokeParams(SkPaint::kRound_Cap, SkPaint::kRound_Join, 2.9f);
            REPORTER_ASSERT(reporter, s1.hasEqualEffect(s2));
            s1.setHairlineStyle();
            s2.setHairlineStyle();
        }
    }

    // Stroke parameters on stroke style are part of equality.
    {
        SkStrokeRec s1(SkStrokeRec::kFill_InitStyle);
        SkStrokeRec s2(SkStrokeRec::kFill_InitStyle);
        s1.setStrokeParams(SkPaint::kButt_Cap, SkPaint::kRound_Join, 2.9f);
        s2.setStrokeParams(SkPaint::kButt_Cap, SkPaint::kRound_Join, 2.9f);
        s1.setStrokeStyle(1.0f, false);

        s2.setStrokeStyle(1.0f, true);
        REPORTER_ASSERT(reporter, !s1.hasEqualEffect(s2));

        s2.setStrokeStyle(2.1f, false);
        REPORTER_ASSERT(reporter, !s1.hasEqualEffect(s2));

        s2.setStrokeStyle(1.0f, false);
        REPORTER_ASSERT(reporter, s1.hasEqualEffect(s2));

        s2.setStrokeParams(SkPaint::kButt_Cap, SkPaint::kRound_Join, 2.1f);
        REPORTER_ASSERT(reporter, s1.hasEqualEffect(s2));  // Miter limit not relevant to butt caps.
        s2.setStrokeParams(SkPaint::kButt_Cap, SkPaint::kBevel_Join, 2.9f);
        REPORTER_ASSERT(reporter, !s1.hasEqualEffect(s2));
        s2.setStrokeParams(SkPaint::kRound_Cap, SkPaint::kRound_Join, 2.9f);
        REPORTER_ASSERT(reporter, !s1.hasEqualEffect(s2));

        // Sets fill.
        s1.setStrokeStyle(0.0f, true);
        s2.setStrokeStyle(0.0f, true);
        REPORTER_ASSERT(reporter, s1.hasEqualEffect(s2));
    }
}

// From skbug.com/6491. The large stroke width can cause numerical instabilities.
static void test_big_stroke(skiatest::Reporter* reporter) {
    SkPaint paint;
    paint.setStyle(SkPaint::kStrokeAndFill_Style);
    paint.setStrokeWidth(1.49679073e+10f);

    SkPath path;
    path.moveTo(SkBits2Float(0x46380000), SkBits2Float(0xc6380000));  // 11776, -11776
    path.lineTo(SkBits2Float(0x46a00000), SkBits2Float(0xc6a00000));  // 20480, -20480
    path.lineTo(SkBits2Float(0x468c0000), SkBits2Float(0xc68c0000));  // 17920, -17920
    path.lineTo(SkBits2Float(0x46100000), SkBits2Float(0xc6100000));  // 9216, -9216
    path.lineTo(SkBits2Float(0x46380000), SkBits2Float(0xc6380000));  // 11776, -11776
    path.close();

    SkPath strokeAndFillPath;
    skpathutils::FillPathWithPaint(path, paint, &strokeAndFillPath);
}

DEF_TEST(Stroke, reporter) {
    test_strokecubic(reporter);
    test_strokerect(reporter);
    test_strokerec_equality(reporter);
    test_big_stroke(reporter);
}
