42639cddc3
Fix these class of warnings: - unused functions - unused locals - sign mismatch - missing function prototypes - missing newline at end of file - 64 to 32 bit truncation The changes prefer to link in dead code in the debug build with 'if (false)' than to comment it out, but trivial cases are commented out or sometimes deleted if it appears to be a copy/paste error. Review URL: https://codereview.appspot.com/6301045 git-svn-id: http://skia.googlecode.com/svn/trunk@4175 2bbb7eff-a529-9590-31e7-b0007b416f81
170 lines
5.4 KiB
C++
170 lines
5.4 KiB
C++
|
|
/*
|
|
* 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[], SkScalar tol) {
|
|
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 tol) {
|
|
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, SkIntToScalar(1));
|
|
|
|
if (false) { // avoid bit rot, suppress warning
|
|
computedCount =
|
|
quadraticPointCount_EC(path, SkIntToScalar(1));
|
|
estimatedCount =
|
|
quadraticPointCount_CE(path, SkIntToScalar(1));
|
|
}
|
|
// 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)
|