/*
 * Copyright 2013 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/SkTypes.h"

#include "include/core/SkBitmap.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPath.h"
#include "include/core/SkRRect.h"
#include "include/core/SkRect.h"
#include "include/core/SkSurface.h"
#include "include/effects/SkDashPathEffect.h"
#include "include/gpu/GrContext.h"
#include "src/gpu/GrPath.h"
#include "src/gpu/geometry/GrShape.h"
#include "tests/Test.h"

#include <initializer_list>

static void test_drawPathEmpty(skiatest::Reporter*, SkCanvas* canvas) {
    // Filling an empty path should not crash.
    SkPaint paint;
    SkRect emptyRect = SkRect::MakeEmpty();
    canvas->drawRect(emptyRect, paint);
    canvas->drawPath(SkPath(), paint);
    canvas->drawOval(emptyRect, paint);
    canvas->drawRect(emptyRect, paint);
    canvas->drawRRect(SkRRect::MakeRect(emptyRect), paint);

    // Stroking an empty path should not crash.
    paint.setAntiAlias(true);
    paint.setStyle(SkPaint::kStroke_Style);
    paint.setColor(SK_ColorGRAY);
    paint.setStrokeWidth(SkIntToScalar(20));
    paint.setStrokeJoin(SkPaint::kRound_Join);
    canvas->drawRect(emptyRect, paint);
    canvas->drawPath(SkPath(), paint);
    canvas->drawOval(emptyRect, paint);
    canvas->drawRect(emptyRect, paint);
    canvas->drawRRect(SkRRect::MakeRect(emptyRect), paint);
}

static void fill_and_stroke(SkCanvas* canvas, const SkPath& p1, const SkPath& p2,
                            sk_sp<SkPathEffect> effect) {
    SkPaint paint;
    paint.setAntiAlias(true);
    paint.setPathEffect(effect);

    canvas->drawPath(p1, paint);
    canvas->drawPath(p2, paint);

    paint.setStyle(SkPaint::kStroke_Style);
    canvas->drawPath(p1, paint);
    canvas->drawPath(p2, paint);
}

static void test_drawSameRectOvals(skiatest::Reporter*, SkCanvas* canvas) {
    // Drawing ovals with similar bounds but different points order should not crash.

    SkPath oval1, oval2;
    const SkRect rect = SkRect::MakeWH(100, 50);
    oval1.addOval(rect, SkPathDirection::kCW);
    oval2.addOval(rect, SkPathDirection::kCCW);

    fill_and_stroke(canvas, oval1, oval2, nullptr);

    const SkScalar intervals[] = { 1, 1 };
    fill_and_stroke(canvas, oval1, oval2, SkDashPathEffect::Make(intervals, 2, 0));
}

DEF_GPUTEST_FOR_ALL_GL_CONTEXTS(GpuDrawPath, reporter, ctxInfo) {
    for (auto& test_func : { &test_drawPathEmpty, &test_drawSameRectOvals }) {
        for (auto& sampleCount : {1, 4, 16}) {
            SkImageInfo info = SkImageInfo::MakeN32Premul(255, 255);
            auto surface(
                SkSurface::MakeRenderTarget(ctxInfo.grContext(), SkBudgeted::kNo, info,
                                            sampleCount, nullptr));
            if (!surface) {
                continue;
            }
            test_func(reporter, surface->getCanvas());
        }
    }
}

DEF_GPUTEST_FOR_ALL_CONTEXTS(GrDrawCollapsedPath, reporter, ctxInfo) {
    // From https://bugs.fuchsia.dev/p/fuchsia/issues/detail?id=37330, it's possible for a convex
    // path to be accepted by AAConvexPathRenderer, then be transformed to something without a
    // computable first direction by a perspective matrix.
    SkImageInfo info = SkImageInfo::MakeN32Premul(100, 100);
    auto surface(SkSurface::MakeRenderTarget(ctxInfo.grContext(), SkBudgeted::kNo, info));

    SkPaint paint;
    paint.setAntiAlias(true);

    SkPath path;
    path.moveTo(0, 0);
    path.lineTo(50, 0);
    path.lineTo(0, 50);
    path.close();

    SkMatrix m;
    m.setAll( 0.966006875f   , -0.125156224f  , 72.0899811f,
             -0.00885376986f , -0.112347461f  , 64.7121124f,
             -8.94321693e-06f, -0.00173384184f, 0.998692870f);
    surface->getCanvas()->setMatrix(m);
    surface->getCanvas()->drawPath(path, paint);
    surface->flush();
}

DEF_GPUTEST(GrPathKeys, reporter, /* options */) {
    SkPaint strokePaint;
    strokePaint.setStyle(SkPaint::kStroke_Style);
    strokePaint.setStrokeWidth(10.f);
    GrStyle styles[] = {
        GrStyle::SimpleFill(),
        GrStyle::SimpleHairline(),
        GrStyle(strokePaint)
    };

    for (const GrStyle& style : styles) {
        // Keys should not ignore conic weights.
        SkPath path1, path2;
        SkPoint p0 = SkPoint::Make(100, 0);
        SkPoint p1 = SkPoint::Make(100, 100);

        path1.conicTo(p0, p1, .5f);
        path2.conicTo(p0, p1, .7f);

        GrUniqueKey key1, key2;
        // We expect these small paths to be keyed based on their data.
        bool isVolatile;
        GrPath::ComputeKey(GrShape(path1, GrStyle::SimpleFill()), &key1, &isVolatile);
        REPORTER_ASSERT(reporter, !isVolatile);
        REPORTER_ASSERT(reporter, key1.isValid());
        GrPath::ComputeKey(GrShape(path2, GrStyle::SimpleFill()), &key2, &isVolatile);
        REPORTER_ASSERT(reporter, !isVolatile);
        REPORTER_ASSERT(reporter, key1.isValid());
        REPORTER_ASSERT(reporter, key1 != key2);
        {
            GrUniqueKey tempKey;
            path1.setIsVolatile(true);
            GrPath::ComputeKey(GrShape(path1, style), &key1, &isVolatile);
            REPORTER_ASSERT(reporter, isVolatile);
            REPORTER_ASSERT(reporter, !tempKey.isValid());
        }

        // Ensure that recreating the GrShape doesn't change the key.
        {
            GrUniqueKey tempKey;
            GrPath::ComputeKey(GrShape(path2, GrStyle::SimpleFill()), &tempKey, &isVolatile);
            REPORTER_ASSERT(reporter, key2 == tempKey);
        }

        // Try a large path that is too big to be keyed off its data.
        SkPath path3;
        SkPath path4;
        for (int i = 0; i < 1000; ++i) {
            SkScalar s = SkIntToScalar(i);
            path3.conicTo(s, 3.f * s / 4, s + 1.f, s, 0.5f + s / 2000.f);
            path4.conicTo(s, 3.f * s / 4, s + 1.f, s, 0.3f + s / 2000.f);
        }

        GrUniqueKey key3, key4;
        // These aren't marked volatile and so should have keys
        GrPath::ComputeKey(GrShape(path3, style), &key3, &isVolatile);
        REPORTER_ASSERT(reporter, !isVolatile);
        REPORTER_ASSERT(reporter, key3.isValid());
        GrPath::ComputeKey(GrShape(path4, style), &key4, &isVolatile);
        REPORTER_ASSERT(reporter, !isVolatile);
        REPORTER_ASSERT(reporter, key4.isValid());
        REPORTER_ASSERT(reporter, key3 != key4);

        {
            GrUniqueKey tempKey;
            path3.setIsVolatile(true);
            GrPath::ComputeKey(GrShape(path3, style), &key1, &isVolatile);
            REPORTER_ASSERT(reporter, isVolatile);
            REPORTER_ASSERT(reporter, !tempKey.isValid());
        }
    }
}
