
/*
 * 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(SkScalarRound(dx));
    int idy = SkAbs32(SkScalarRound(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(SkScalarRound(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) {
            SkString errorDescription;
            errorDescription.printf(
                "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++;
            reporter->reportFailed(errorDescription);
        }
    }

    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);
}

static void TestPathCoverage(skiatest::Reporter* reporter) {
    TestQuadPointCount(reporter);

}

#include "TestClassDef.h"
DEFINE_TESTCLASS("PathCoverage", PathCoverageTestClass, TestPathCoverage)
