/*
 * 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 "SkMathPriv.h"
#include "SkPointPriv.h"
#include "SkScalar.h"
#include "Test.h"

/*
   Duplicates lots of code from gpu/src/GrPathUtils.cpp
   It'd be nice not to do so, but that code's set up currently to only have
   a single implementation.
*/

// Sk uses 6, Gr (implicitly) used 10, both apparently arbitrarily.
#define MAX_COEFF_SHIFT     6
static const uint32_t MAX_POINTS_PER_CURVE = 1 << MAX_COEFF_SHIFT;

// max + 0.5 min has error [0.0, 0.12]
// max + 0.375 min has error [-.03, 0.07]
// 0.96043387 max + 0.397824735 min has error [-.06, +.05]
// For determining the maximum possible number of points to use in
// drawing a quadratic, we want to err on the high side.
static inline int cheap_distance(SkScalar dx, SkScalar dy) {
    int idx = SkAbs32(SkScalarRoundToInt(dx));
    int idy = SkAbs32(SkScalarRoundToInt(dy));
    if (idx > idy) {
        idx += idy >> 1;
    } else {
        idx = idy + (idx >> 1);
    }
    return idx;
}

static inline int estimate_distance(const SkPoint points[]) {
    return cheap_distance(points[1].fX * 2 - points[2].fX - points[0].fX,
                          points[1].fY * 2 - points[2].fY - points[0].fY);
}

static inline SkScalar compute_distance(const SkPoint points[]) {
    return SkPointPriv::DistanceToLineSegmentBetween(points[1], points[0], points[2]);
}

static inline uint32_t estimate_pointCount(int distance) {
    // Includes -2 bias because this estimator runs 4x high?
    int shift = 30 - SkCLZ(distance);
    // Clamp to zero if above subtraction went negative.
    shift &= ~(shift>>31);
    if (shift > MAX_COEFF_SHIFT) {
        shift = MAX_COEFF_SHIFT;
    }
    return 1 << shift;
}

static inline uint32_t compute_pointCount(SkScalar d, SkScalar tol) {
    if (d < tol) {
       return 1;
    } else {
       int temp = SkScalarCeilToInt(SkScalarSqrt(d / tol));
       uint32_t count = SkMin32(SkNextPow2(temp), MAX_POINTS_PER_CURVE);
       return count;
    }
}

static uint32_t quadraticPointCount_EE(const SkPoint points[]) {
    int distance = estimate_distance(points);
    return estimate_pointCount(distance);
}

static uint32_t quadraticPointCount_EC(const SkPoint points[], SkScalar tol) {
    int distance = estimate_distance(points);
    return compute_pointCount(SkIntToScalar(distance), tol);
}

static uint32_t quadraticPointCount_CE(const SkPoint points[]) {
    SkScalar distance = compute_distance(points);
    return estimate_pointCount(SkScalarRoundToInt(distance));
}

static uint32_t quadraticPointCount_CC(const SkPoint points[], SkScalar tol) {
    SkScalar distance = compute_distance(points);
    return compute_pointCount(distance, tol);
}

// Curve from samplecode/SampleSlides.cpp
static const int gXY[] = {
    4, 0, 0, -4, 8, -4, 12, 0, 8, 4, 0, 4
};

static const int gSawtooth[] = {
    0, 0, 10, 10, 20, 20, 30, 10, 40, 0, 50, -10, 60, -20, 70, -10, 80, 0
};

static const int gOvalish[] = {
    0, 0, 5, 15, 20, 20, 35, 15, 40, 0
};

static const int gSharpSawtooth[] = {
    0, 0, 1, 10, 2, 0, 3, -10, 4, 0
};

// Curve crosses back over itself around 0,10
static const int gRibbon[] = {
   -4, 0, 4, 20, 0, 25, -4, 20, 4, 0
};

static bool one_d_pe(const int* array, const unsigned int count,
                     skiatest::Reporter* reporter) {
    SkPoint path [3];
    path[1] = SkPoint::Make(SkIntToScalar(array[0]), SkIntToScalar(array[1]));
    path[2] = SkPoint::Make(SkIntToScalar(array[2]), SkIntToScalar(array[3]));
    int numErrors = 0;
    for (unsigned i = 4; i < count; i += 2) {
        path[0] = path[1];
        path[1] = path[2];
        path[2] = SkPoint::Make(SkIntToScalar(array[i]),
                                SkIntToScalar(array[i+1]));
        uint32_t computedCount =
            quadraticPointCount_CC(path, SkIntToScalar(1));
        uint32_t estimatedCount =
            quadraticPointCount_EE(path);

        if (false) { // avoid bit rot, suppress warning
            computedCount =
                    quadraticPointCount_EC(path, SkIntToScalar(1));
            estimatedCount =
                    quadraticPointCount_CE(path);
        }
        // Allow estimated to be high by a factor of two, but no less than
        // the computed value.
        bool isAccurate = (estimatedCount >= computedCount) &&
            (estimatedCount <= 2 * computedCount);

        if (!isAccurate) {
            ERRORF(reporter, "Curve from %.2f %.2f through %.2f %.2f to "
                   "%.2f %.2f computes %d, estimates %d\n",
                   path[0].fX, path[0].fY, path[1].fX, path[1].fY,
                   path[2].fX, path[2].fY, computedCount, estimatedCount);
            numErrors++;
        }
    }

    return (numErrors == 0);
}



static void TestQuadPointCount(skiatest::Reporter* reporter) {
    one_d_pe(gXY, SK_ARRAY_COUNT(gXY), reporter);
    one_d_pe(gSawtooth, SK_ARRAY_COUNT(gSawtooth), reporter);
    one_d_pe(gOvalish, SK_ARRAY_COUNT(gOvalish), reporter);
    one_d_pe(gSharpSawtooth, SK_ARRAY_COUNT(gSharpSawtooth), reporter);
    one_d_pe(gRibbon, SK_ARRAY_COUNT(gRibbon), reporter);
}

DEF_TEST(PathCoverage, reporter) {
    TestQuadPointCount(reporter);

}
