Make cross_prod used in SkPath::cheapComputeDirection fallback to double computation when result is 0. Verbal LGTM from reed.
git-svn-id: http://skia.googlecode.com/svn/trunk@3216 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
c2c80c42e2
commit
f0ed80a7eb
@ -1909,8 +1909,26 @@ CONTOUR_END:
|
||||
SkDEBUGCODE(++fContourCounter;)
|
||||
}
|
||||
|
||||
// returns cross product of (p1 - p0) and (p2 - p0)
|
||||
static SkScalar cross_prod(const SkPoint& p0, const SkPoint& p1, const SkPoint& p2) {
|
||||
return SkPoint::CrossProduct(p1 - p0, p2 - p0);
|
||||
SkScalar cross = SkPoint::CrossProduct(p1 - p0, p2 - p0);
|
||||
// We may get 0 when the above subtracts underflow. We expect this to be
|
||||
// very rare and lazily promote to double.
|
||||
if (0 == cross) {
|
||||
double p0x = SkScalarToDouble(p0.fX);
|
||||
double p0y = SkScalarToDouble(p0.fY);
|
||||
|
||||
double p1x = SkScalarToDouble(p1.fX);
|
||||
double p1y = SkScalarToDouble(p1.fY);
|
||||
|
||||
double p2x = SkScalarToDouble(p2.fX);
|
||||
double p2y = SkScalarToDouble(p2.fY);
|
||||
|
||||
cross = SkDoubleToScalar((p1x - p0x) * (p2y - p0y) -
|
||||
(p1y - p0y) * (p2x - p0x));
|
||||
|
||||
}
|
||||
return cross;
|
||||
}
|
||||
|
||||
// Returns the first pt with the maximum Y coordinate
|
||||
|
@ -15,6 +15,21 @@
|
||||
#include "SkSize.h"
|
||||
#include "SkWriter32.h"
|
||||
|
||||
/**
|
||||
* cheapIsDirection can take a shortcut when a path is marked convex.
|
||||
* This function ensures that we always test cheapIsDirection when the path
|
||||
* is flagged with unknown convexity status.
|
||||
*/
|
||||
static void check_direction(SkPath* path,
|
||||
SkPath::Direction expectedDir,
|
||||
skiatest::Reporter* reporter) {
|
||||
if (SkPath::kConvex_Convexity == path->getConvexity()) {
|
||||
REPORTER_ASSERT(reporter, path->cheapIsDirection(expectedDir));
|
||||
path->setConvexity(SkPath::kUnknown_Convexity);
|
||||
}
|
||||
REPORTER_ASSERT(reporter, path->cheapIsDirection(expectedDir));
|
||||
}
|
||||
|
||||
static void test_direction(skiatest::Reporter* reporter) {
|
||||
size_t i;
|
||||
SkPath path;
|
||||
@ -46,7 +61,7 @@ static void test_direction(skiatest::Reporter* reporter) {
|
||||
path.reset();
|
||||
bool valid = SkParsePath::FromSVGString(gCW[i], &path);
|
||||
REPORTER_ASSERT(reporter, valid);
|
||||
REPORTER_ASSERT(reporter, path.cheapIsDirection(SkPath::kCW_Direction));
|
||||
check_direction(&path, SkPath::kCW_Direction, reporter);
|
||||
}
|
||||
|
||||
static const char* gCCW[] = {
|
||||
@ -58,7 +73,7 @@ static void test_direction(skiatest::Reporter* reporter) {
|
||||
path.reset();
|
||||
bool valid = SkParsePath::FromSVGString(gCCW[i], &path);
|
||||
REPORTER_ASSERT(reporter, valid);
|
||||
REPORTER_ASSERT(reporter, path.cheapIsDirection(SkPath::kCCW_Direction));
|
||||
check_direction(&path, SkPath::kCCW_Direction, reporter);
|
||||
}
|
||||
|
||||
// Test two donuts, each wound a different direction. Only the outer contour
|
||||
@ -66,12 +81,20 @@ static void test_direction(skiatest::Reporter* reporter) {
|
||||
path.reset();
|
||||
path.addCircle(0, 0, SkIntToScalar(2), SkPath::kCW_Direction);
|
||||
path.addCircle(0, 0, SkIntToScalar(1), SkPath::kCCW_Direction);
|
||||
REPORTER_ASSERT(reporter, path.cheapIsDirection(SkPath::kCW_Direction));
|
||||
|
||||
check_direction(&path, SkPath::kCW_Direction, reporter);
|
||||
|
||||
path.reset();
|
||||
path.addCircle(0, 0, SkIntToScalar(1), SkPath::kCW_Direction);
|
||||
path.addCircle(0, 0, SkIntToScalar(2), SkPath::kCCW_Direction);
|
||||
REPORTER_ASSERT(reporter, path.cheapIsDirection(SkPath::kCCW_Direction));
|
||||
check_direction(&path, SkPath::kCCW_Direction, reporter);
|
||||
|
||||
// triangle with one point really far from the origin.
|
||||
path.reset();
|
||||
// the first point is roughly 1.05e10, 1.05e10
|
||||
path.moveTo(SkFloatToScalar(SkBits2Float(0x501c7652)), SkFloatToScalar(SkBits2Float(0x501c7652)));
|
||||
path.lineTo(110 * SK_Scalar1, -10 * SK_Scalar1);
|
||||
path.lineTo(-10 * SK_Scalar1, 60 * SK_Scalar1);
|
||||
check_direction(&path, SkPath::kCCW_Direction, reporter);
|
||||
}
|
||||
|
||||
static void add_rect(SkPath* path, const SkRect& r) {
|
||||
|
Loading…
Reference in New Issue
Block a user