/*
 * 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/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/SkRect.h"
#include "include/pathops/SkPathOps.h"
#include "include/private/base/SkTDArray.h"
#include "src/base/SkRandom.h"
#include "src/pathops/SkPathOpsCommon.h"
#include "tests/PathOpsExtendedTest.h"
#include "tests/PathOpsThreadedCommon.h"
#include "tests/Test.h"

#include <algorithm>
#include <cstdint>

static void testTightBoundsLines(PathOpsThreadState* data) {
    SkRandom ran;
    for (int index = 0; index < 1000; ++index) {
        SkPath path;
        int contourCount = ran.nextRangeU(1, 10);
        for (int cIndex = 0; cIndex < contourCount; ++cIndex) {
            int lineCount = ran.nextRangeU(1, 10);
            path.moveTo(ran.nextRangeF(-1000, 1000), ran.nextRangeF(-1000, 1000));
            for (int lIndex = 0; lIndex < lineCount; ++lIndex) {
                path.lineTo(ran.nextRangeF(-1000, 1000), ran.nextRangeF(-1000, 1000));
            }
            if (ran.nextBool()) {
                path.close();
            }
        }
        SkRect classicBounds = path.getBounds();
        SkRect tightBounds;
        REPORTER_ASSERT(data->fReporter, ComputeTightBounds(path, &tightBounds));
        REPORTER_ASSERT(data->fReporter, classicBounds == tightBounds);
    }
}

DEF_TEST(PathOpsTightBoundsLines, reporter) {
    initializeTests(reporter, "tightBoundsLines");
    PathOpsThreadedTestRunner testRunner(reporter);
    int outerCount = reporter->allowExtendedTest() ? 100 : 1;
    for (int index = 0; index < outerCount; ++index) {
        for (int idx2 = 0; idx2 < 10; ++idx2) {
            *testRunner.fRunnables.append() =
                    new PathOpsThreadedRunnable(&testTightBoundsLines, 0, 0, 0, 0, &testRunner);
        }
    }
    testRunner.render();
}

static void testTightBoundsQuads(PathOpsThreadState* data) {
    SkRandom ran;
    const int bitWidth = 32;
    const int bitHeight = 32;
    const float pathMin = 1;
    const float pathMax = (float) (bitHeight - 2);
    SkBitmap& bits = *data->fBitmap;
    if (bits.width() == 0) {
        bits.allocN32Pixels(bitWidth, bitHeight);
    }
    SkCanvas canvas(bits);
    SkPaint paint;
    for (int index = 0; index < 100; ++index) {
        SkPath path;
        int contourCount = ran.nextRangeU(1, 10);
        for (int cIndex = 0; cIndex < contourCount; ++cIndex) {
            int lineCount = ran.nextRangeU(1, 10);
            path.moveTo(ran.nextRangeF(1, pathMax), ran.nextRangeF(pathMin, pathMax));
            for (int lIndex = 0; lIndex < lineCount; ++lIndex) {
                if (ran.nextBool()) {
                    path.lineTo(ran.nextRangeF(pathMin, pathMax), ran.nextRangeF(pathMin, pathMax));
                } else {
                    path.quadTo(ran.nextRangeF(pathMin, pathMax), ran.nextRangeF(pathMin, pathMax),
                            ran.nextRangeF(pathMin, pathMax), ran.nextRangeF(pathMin, pathMax));
                }
            }
            if (ran.nextBool()) {
                path.close();
            }
        }
        SkRect classicBounds = path.getBounds();
        SkRect tightBounds;
        REPORTER_ASSERT(data->fReporter, ComputeTightBounds(path, &tightBounds));
        REPORTER_ASSERT(data->fReporter, classicBounds.contains(tightBounds));
        canvas.drawColor(SK_ColorWHITE);
        canvas.drawPath(path, paint);
        SkIRect bitsWritten = {31, 31, 0, 0};
        for (int y = 0; y < bitHeight; ++y) {
            uint32_t* addr1 = data->fBitmap->getAddr32(0, y);
            bool lineWritten = false;
            for (int x = 0; x < bitWidth; ++x) {
                if (addr1[x] == (uint32_t) -1) {
                    continue;
                }
                lineWritten = true;
                bitsWritten.fLeft = std::min(bitsWritten.fLeft, x);
                bitsWritten.fRight = std::max(bitsWritten.fRight, x);
            }
            if (!lineWritten) {
                continue;
            }
            bitsWritten.fTop = std::min(bitsWritten.fTop, y);
            bitsWritten.fBottom = std::max(bitsWritten.fBottom, y);
        }
        if (!bitsWritten.isEmpty()) {
            SkIRect tightOut;
            tightBounds.roundOut(&tightOut);
            REPORTER_ASSERT(data->fReporter, tightOut.contains(bitsWritten));
        }
    }
}

DEF_TEST(PathOpsTightBoundsQuads, reporter) {
    initializeTests(reporter, "tightBoundsQuads");
    PathOpsThreadedTestRunner testRunner(reporter);
    int outerCount = reporter->allowExtendedTest() ? 100 : 1;
    for (int index = 0; index < outerCount; ++index) {
        for (int idx2 = 0; idx2 < 10; ++idx2) {
            *testRunner.fRunnables.append() =
                    new PathOpsThreadedRunnable(&testTightBoundsQuads, 0, 0, 0, 0, &testRunner);
        }
    }
    testRunner.render();
}

DEF_TEST(PathOpsTightBoundsMove, reporter) {
    SkPath path;
    path.moveTo(10, 10);
    path.close();
    path.moveTo(20, 20);
    path.lineTo(20, 20);
    path.close();
    path.moveTo(15, 15);
    path.lineTo(15, 15);
    path.close();
    const SkRect& bounds = path.getBounds();
    SkRect tight;
    REPORTER_ASSERT(reporter, ComputeTightBounds(path, &tight));
    REPORTER_ASSERT(reporter, bounds == tight);
}

DEF_TEST(PathOpsTightBoundsMoveOne, reporter) {
    SkPath path;
    path.moveTo(20, 20);
    const SkRect& bounds = path.getBounds();
    SkRect tight;
    REPORTER_ASSERT(reporter, ComputeTightBounds(path, &tight));
    REPORTER_ASSERT(reporter, bounds == tight);
}

DEF_TEST(PathOpsTightBoundsMoveTwo, reporter) {
    SkPath path;
    path.moveTo(20, 20);
    path.moveTo(40, 40);
    const SkRect& bounds = path.getBounds();
    SkRect tight;
    REPORTER_ASSERT(reporter, ComputeTightBounds(path, &tight));
    REPORTER_ASSERT(reporter, bounds == tight);
}

DEF_TEST(PathOpsTightBoundsTiny, reporter) {
    SkPath path;
    path.moveTo(1, 1);
    path.quadTo(1.000001f, 1, 1, 1);
    const SkRect& bounds = path.getBounds();
    SkRect tight;
    REPORTER_ASSERT(reporter, ComputeTightBounds(path, &tight));
    SkRect moveBounds = {1, 1, 1, 1};
    REPORTER_ASSERT(reporter, bounds != tight);
    REPORTER_ASSERT(reporter, moveBounds == tight);
}

DEF_TEST(PathOpsTightBoundsWellBehaved, reporter) {
    SkPath path;
    path.moveTo(1, 1);
    path.quadTo(2, 3, 4, 5);
    const SkRect& bounds = path.getBounds();
    SkRect tight;
    REPORTER_ASSERT(reporter, ComputeTightBounds(path, &tight));
    REPORTER_ASSERT(reporter, bounds == tight);
}

DEF_TEST(PathOpsTightBoundsIllBehaved, reporter) {
    SkPath path;
    path.moveTo(1, 1);
    path.quadTo(4, 3, 2, 2);
    const SkRect& bounds = path.getBounds();
    SkRect tight;
    REPORTER_ASSERT(reporter, ComputeTightBounds(path, &tight));
    REPORTER_ASSERT(reporter, bounds != tight);
}

DEF_TEST(PathOpsTightBoundsIllBehavedScaled, reporter) {
    SkPath path;
    path.moveTo(0, 0);
    path.quadTo(1048578, 1048577, 1048576, 1048576);
    const SkRect& bounds = path.getBounds();
    SkRect tight;
    REPORTER_ASSERT(reporter, ComputeTightBounds(path, &tight));
    REPORTER_ASSERT(reporter, bounds != tight);
    REPORTER_ASSERT(reporter, tight.right() == 1048576);
    REPORTER_ASSERT(reporter, tight.bottom() == 1048576);
}
