use contour with global ymax to determine direction
git-svn-id: http://skia.googlecode.com/svn/trunk@3110 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
3e5afe7c57
commit
ac8543ff57
@ -1926,6 +1926,21 @@ static int find_diff_pt(const SkPoint pts[], int index, int n, int inc) {
|
||||
return i;
|
||||
}
|
||||
|
||||
static bool crossToDir(SkScalar cross, SkPath::Direction* dir) {
|
||||
if (dir) {
|
||||
*dir = cross > 0 ? SkPath::kCW_Direction : SkPath::kCCW_Direction;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* We loop through all contours, and keep the computed cross-product of the
|
||||
* contour that contained the global y-max. If we just look at the first
|
||||
* contour, we may find one that is wound the opposite way (correctly) since
|
||||
* it is the interior of a hole (e.g. 'o'). Thus we must find the contour
|
||||
* that is outer most (or at least has the global y-max) before we can consider
|
||||
* its cross product.
|
||||
*/
|
||||
bool SkPath::cheapComputeDirection(Direction* dir) const {
|
||||
// don't want to pay the cost for computing this if it
|
||||
// is unknown, so we don't call isConvex()
|
||||
@ -1933,12 +1948,16 @@ bool SkPath::cheapComputeDirection(Direction* dir) const {
|
||||
|
||||
ContourIter iter(fVerbs, fPts);
|
||||
|
||||
// initialize with our logical y-min
|
||||
SkScalar ymax = this->getBounds().fTop;
|
||||
SkScalar ymaxCross = 0;
|
||||
|
||||
for (; !iter.done(); iter.next()) {
|
||||
int n = iter.count();
|
||||
if (n < 3) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
const SkPoint* pts = iter.pts();
|
||||
SkScalar cross = 0;
|
||||
if (kConvex_Convexity == conv) {
|
||||
@ -1947,11 +1966,17 @@ bool SkPath::cheapComputeDirection(Direction* dir) const {
|
||||
for (int i = 0; i < n - 2; ++i) {
|
||||
cross = cross_prod(pts[i], pts[i + 1], pts[i + 2]);
|
||||
if (cross) {
|
||||
break;
|
||||
// early-exit, as kConvex is assumed to have only 1
|
||||
// non-degenerate contour
|
||||
return crossToDir(cross, dir);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int index = find_max_y(pts, n);
|
||||
if (pts[index].fY < ymax) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Find a next and prev index to use for the cross-product test,
|
||||
// but we try to find pts that form non-zero vectors from pts[index]
|
||||
//
|
||||
@ -1975,14 +2000,14 @@ bool SkPath::cheapComputeDirection(Direction* dir) const {
|
||||
// construct the subtract so we get the correct Direction below
|
||||
cross = pts[index].fX - pts[next].fX;
|
||||
}
|
||||
}
|
||||
if (cross) {
|
||||
if (dir) {
|
||||
*dir = cross > 0 ? kCW_Direction : kCCW_Direction;
|
||||
|
||||
if (cross) {
|
||||
// record our best guess so far
|
||||
ymax = pts[index].fY;
|
||||
ymaxCross = cross;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false; // unknown
|
||||
}
|
||||
|
||||
return ymaxCross ? crossToDir(ymaxCross, dir) : false;
|
||||
}
|
||||
|
@ -58,6 +58,18 @@ static void test_direction(skiatest::Reporter* reporter) {
|
||||
REPORTER_ASSERT(reporter, valid);
|
||||
REPORTER_ASSERT(reporter, path.cheapIsDirection(SkPath::kCCW_Direction));
|
||||
}
|
||||
|
||||
// Test two donuts, each wound a different direction. Only the outer contour
|
||||
// determines the cheap direction
|
||||
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));
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
static void add_rect(SkPath* path, const SkRect& r) {
|
||||
|
Loading…
Reference in New Issue
Block a user