/*
 * 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 "SkMath.h"
#include "SkPoint.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 points[1].distanceToLineSegmentBetween(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(SkScalarDiv(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);

}
