shape ops work in progress

git-svn-id: http://skia.googlecode.com/svn/trunk@7453 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
caryclark@google.com 2013-01-29 20:28:49 +00:00
parent 81d3ce0b63
commit aa35831d1d
44 changed files with 643 additions and 274 deletions

View File

@ -146,17 +146,17 @@ static int rotate_to_hull(const Cubic& cubic, char order[4], size_t idx, size_t
int zeroes; int zeroes;
zeroes = -1; zeroes = -1;
bzero(sides, sizeof(sides)); bzero(sides, sizeof(sides));
if (debug_rotate_to_hull) printf("%s [%d,%d] [o=%d,i=%d] src=(%g,%g) rot=", __FUNCTION__, if (debug_rotate_to_hull) SkDebugf("%s [%d,%d] [o=%d,i=%d] src=(%g,%g) rot=", __FUNCTION__,
(int)idx, (int)inr, (int)outer, (int)inner, (int)idx, (int)inr, (int)outer, (int)inner,
cubic[inner].x, cubic[inner].y); cubic[inner].x, cubic[inner].y);
for (int index = 0; index < 4; ++index) { for (int index = 0; index < 4; ++index) {
if (debug_rotate_to_hull) printf("(%g,%g) ", rotPath[index].x, rotPath[index].y); if (debug_rotate_to_hull) SkDebugf("(%g,%g) ", rotPath[index].x, rotPath[index].y);
sides[side(rotPath[index].y - rotPath[inner].y)]++; sides[side(rotPath[index].y - rotPath[inner].y)]++;
if (index != outer && index != inner if (index != outer && index != inner
&& side(rotPath[index].y - rotPath[inner].y) == 1) && side(rotPath[index].y - rotPath[inner].y) == 1)
zeroes = index; zeroes = index;
} }
if (debug_rotate_to_hull) printf("sides=(%d,%d,%d)\n", sides[0], sides[1], sides[2]); if (debug_rotate_to_hull) SkDebugf("sides=(%d,%d,%d)\n", sides[0], sides[1], sides[2]);
if (sides[0] && sides[2]) { if (sides[0] && sides[2]) {
continue; continue;
} }
@ -165,25 +165,25 @@ static int rotate_to_hull(const Cubic& cubic, char order[4], size_t idx, size_t
// if either of remaining two equals outer or equal, pick lower // if either of remaining two equals outer or equal, pick lower
if (rotPath[zeroes].approximatelyEqual(rotPath[inner]) if (rotPath[zeroes].approximatelyEqual(rotPath[inner])
&& zeroes < inner) { && zeroes < inner) {
if (debug_rotate_to_hull) printf("%s [%d,%d] [o=%d,i=%d] zeroes < inner\n", if (debug_rotate_to_hull) SkDebugf("%s [%d,%d] [o=%d,i=%d] zeroes < inner\n",
__FUNCTION__, (int)idx, (int)inr, (int)outer, (int)inner); __FUNCTION__, (int)idx, (int)inr, (int)outer, (int)inner);
continue; continue;
} }
if (rotPath[zeroes].approximatelyEqual(rotPath[outer]) if (rotPath[zeroes].approximatelyEqual(rotPath[outer])
&& zeroes < outer) { && zeroes < outer) {
if (debug_rotate_to_hull) printf("%s [%d,%d] [o=%d,i=%d] zeroes < outer\n", if (debug_rotate_to_hull) SkDebugf("%s [%d,%d] [o=%d,i=%d] zeroes < outer\n",
__FUNCTION__, (int)idx, (int)inr, (int)outer, (int)inner); __FUNCTION__, (int)idx, (int)inr, (int)outer, (int)inner);
continue; continue;
} }
if (rotPath[zeroes].x < rotPath[inner].x if (rotPath[zeroes].x < rotPath[inner].x
&& rotPath[zeroes].x < rotPath[outer].x) { && rotPath[zeroes].x < rotPath[outer].x) {
if (debug_rotate_to_hull) printf("%s [%d,%d] [o=%d,i=%d] zeroes < inner && outer\n", if (debug_rotate_to_hull) SkDebugf("%s [%d,%d] [o=%d,i=%d] zeroes < inner && outer\n",
__FUNCTION__, (int)idx, (int)inr, (int)outer, (int)inner); __FUNCTION__, (int)idx, (int)inr, (int)outer, (int)inner);
continue; continue;
} }
if (rotPath[zeroes].x > rotPath[inner].x if (rotPath[zeroes].x > rotPath[inner].x
&& rotPath[zeroes].x > rotPath[outer].x) { && rotPath[zeroes].x > rotPath[outer].x) {
if (debug_rotate_to_hull) printf("%s [%d,%d] [o=%d,i=%d] zeroes > inner && outer\n", if (debug_rotate_to_hull) SkDebugf("%s [%d,%d] [o=%d,i=%d] zeroes > inner && outer\n",
__FUNCTION__, (int)idx, (int)inr, (int)outer, (int)inner); __FUNCTION__, (int)idx, (int)inr, (int)outer, (int)inner);
continue; continue;
} }
@ -192,7 +192,7 @@ static int rotate_to_hull(const Cubic& cubic, char order[4], size_t idx, size_t
outsidePtSet[outer] = inner; outsidePtSet[outer] = inner;
} else { } else {
if (outsidePtSet[inner] > 0) { if (outsidePtSet[inner] > 0) {
if (debug_rotate_to_hull) printf("%s [%d,%d] [o=%d,i=%d] too many rays from one point\n", if (debug_rotate_to_hull) SkDebugf("%s [%d,%d] [o=%d,i=%d] too many rays from one point\n",
__FUNCTION__, (int)idx, (int)inr, (int)outer, (int)inner); __FUNCTION__, (int)idx, (int)inr, (int)outer, (int)inner);
} }
outsidePtSet[inner] = outer; outsidePtSet[inner] = outer;
@ -237,7 +237,7 @@ void ConvexHull_Test() {
} }
int result = convex_hull(cubic, order); int result = convex_hull(cubic, order);
if (cmp != result) { if (cmp != result) {
printf("%s [%d,%d] result=%d cmp=%d\n", __FUNCTION__, SkDebugf("%s [%d,%d] result=%d cmp=%d\n", __FUNCTION__,
(int)index, (int)inner, result, cmp); (int)index, (int)inner, result, cmp);
continue; continue;
} }
@ -247,23 +247,23 @@ void ConvexHull_Test() {
int pt, bit; int pt, bit;
for (pt = 0; pt < cmp; ++pt) { for (pt = 0; pt < cmp; ++pt) {
if (pts & 1 << order[pt]) { if (pts & 1 << order[pt]) {
printf("%s [%d,%d] duplicate index in order: %d,%d,%d", SkDebugf("%s [%d,%d] duplicate index in order: %d,%d,%d",
__FUNCTION__, (int)index, (int)inner, __FUNCTION__, (int)index, (int)inner,
order[0], order[1], order[2]); order[0], order[1], order[2]);
if (cmp == 4) { if (cmp == 4) {
printf(",%d", order[3]); SkDebugf(",%d", order[3]);
} }
printf("\n"); SkDebugf("\n");
goto next; goto next;
} }
if (cmpPts & 1 << cmpOrder[pt]) { if (cmpPts & 1 << cmpOrder[pt]) {
printf("%s [%d,%d] duplicate index in order: %d,%d,%d", SkDebugf("%s [%d,%d] duplicate index in order: %d,%d,%d",
__FUNCTION__, (int)index, (int)inner, __FUNCTION__, (int)index, (int)inner,
cmpOrder[0], cmpOrder[1], cmpOrder[2]); cmpOrder[0], cmpOrder[1], cmpOrder[2]);
if (cmp == 4) { if (cmp == 4) {
printf(",%d", cmpOrder[3]); SkDebugf(",%d", cmpOrder[3]);
} }
printf("\n"); SkDebugf("\n");
goto next; goto next;
} }
pts |= 1 << order[pt]; pts |= 1 << order[pt];
@ -296,17 +296,17 @@ void ConvexHull_Test() {
} }
} }
if (pts != cmpPts) { if (pts != cmpPts) {
printf("%s [%d,%d] mismatch indices: order=%d,%d,%d", SkDebugf("%s [%d,%d] mismatch indices: order=%d,%d,%d",
__FUNCTION__, (int)index, (int)inner, __FUNCTION__, (int)index, (int)inner,
order[0], order[1], order[2]); order[0], order[1], order[2]);
if (cmp == 4) { if (cmp == 4) {
printf(",%d", order[3]); SkDebugf(",%d", order[3]);
} }
printf(" cmpOrder=%d,%d,%d", cmpOrder[0], cmpOrder[1], cmpOrder[2]); SkDebugf(" cmpOrder=%d,%d,%d", cmpOrder[0], cmpOrder[1], cmpOrder[2]);
if (cmp == 4) { if (cmp == 4) {
printf(",%d", cmpOrder[3]); SkDebugf(",%d", cmpOrder[3]);
} }
printf("\n"); SkDebugf("\n");
continue; continue;
} }
if (cmp == 4) { // check for bow ties if (cmp == 4) { // check for bow ties
@ -315,7 +315,7 @@ void ConvexHull_Test() {
++match; ++match;
} }
if (cmpOrder[match ^ 2] != order[2]) { if (cmpOrder[match ^ 2] != order[2]) {
printf("%s [%d,%d] bowtie mismatch: order=%d,%d,%d,%d" SkDebugf("%s [%d,%d] bowtie mismatch: order=%d,%d,%d,%d"
" cmpOrder=%d,%d,%d,%d\n", " cmpOrder=%d,%d,%d,%d\n",
__FUNCTION__, (int)index, (int)inner, __FUNCTION__, (int)index, (int)inner,
order[0], order[1], order[2], order[3], order[0], order[1], order[2], order[3],
@ -365,12 +365,12 @@ void ConvexHull_X_Test() {
if (connectTo0[idx] >= 1 && connectTo0[idx] < 4) { if (connectTo0[idx] >= 1 && connectTo0[idx] < 4) {
continue; continue;
} else { } else {
printf("%s connectTo0[idx]=%d", __FUNCTION__, connectTo0[idx]); SkDebugf("%s connectTo0[idx]=%d", __FUNCTION__, connectTo0[idx]);
} }
if (connectTo3[idx] >= 0 && connectTo3[idx] < 3) { if (connectTo3[idx] >= 0 && connectTo3[idx] < 3) {
continue; continue;
} else { } else {
printf("%s connectTo3[idx]=%d", __FUNCTION__, connectTo3[idx]); SkDebugf("%s connectTo3[idx]=%d", __FUNCTION__, connectTo3[idx]);
} }
goto nextTest; goto nextTest;
} }
@ -398,7 +398,7 @@ void ConvexHull_X_Test() {
} }
if (connectTo0[0] != connectTo0[1]) { if (connectTo0[0] != connectTo0[1]) {
if (rOrder[0] == rOrder[1]) { if (rOrder[0] == rOrder[1]) {
printf("%s [%d] (1) order=(%d,%d,%d,%d) r_order=(%d,%d,%d,%d)\n", SkDebugf("%s [%d] (1) order=(%d,%d,%d,%d) r_order=(%d,%d,%d,%d)\n",
__FUNCTION__, (int)index, connectTo0[0], connectTo0[1], __FUNCTION__, (int)index, connectTo0[0], connectTo0[1],
connectTo3[0], connectTo3[1], connectTo3[0], connectTo3[1],
rOrder[0], rOrder[1], rOrder[2], rOrder[3]); rOrder[0], rOrder[1], rOrder[2], rOrder[3]);
@ -407,7 +407,7 @@ void ConvexHull_X_Test() {
int unused = 6 - connectTo0[0] - connectTo0[1]; int unused = 6 - connectTo0[0] - connectTo0[1];
int rUnused = 6 - rOrder[0] - rOrder[1]; int rUnused = 6 - rOrder[0] - rOrder[1];
if (unused != rUnused) { if (unused != rUnused) {
printf("%s [%d] (2) order=(%d,%d,%d,%d) r_order=(%d,%d,%d,%d)\n", SkDebugf("%s [%d] (2) order=(%d,%d,%d,%d) r_order=(%d,%d,%d,%d)\n",
__FUNCTION__, (int)index, connectTo0[0], connectTo0[1], __FUNCTION__, (int)index, connectTo0[0], connectTo0[1],
connectTo3[0], connectTo3[1], connectTo3[0], connectTo3[1],
rOrder[0], rOrder[1], rOrder[2], rOrder[3]); rOrder[0], rOrder[1], rOrder[2], rOrder[3]);
@ -415,14 +415,14 @@ void ConvexHull_X_Test() {
} }
} else { } else {
if (rOrder[0] != rOrder[1]) { if (rOrder[0] != rOrder[1]) {
printf("%s [%d] (3) order=(%d,%d,%d,%d) r_order=(%d,%d,%d,%d)\n", SkDebugf("%s [%d] (3) order=(%d,%d,%d,%d) r_order=(%d,%d,%d,%d)\n",
__FUNCTION__, (int)index, connectTo0[0], connectTo0[1], __FUNCTION__, (int)index, connectTo0[0], connectTo0[1],
connectTo3[0], connectTo3[1], connectTo3[0], connectTo3[1],
rOrder[0], rOrder[1], rOrder[2], rOrder[3]); rOrder[0], rOrder[1], rOrder[2], rOrder[3]);
continue; continue;
} }
if (connectTo0[0] != rOrder[0]) { if (connectTo0[0] != rOrder[0]) {
printf("%s [%d] (4) order=(%d,%d,%d,%d) r_order=(%d,%d,%d,%d)\n", SkDebugf("%s [%d] (4) order=(%d,%d,%d,%d) r_order=(%d,%d,%d,%d)\n",
__FUNCTION__, (int)index, connectTo0[0], connectTo0[1], __FUNCTION__, (int)index, connectTo0[0], connectTo0[1],
connectTo3[0], connectTo3[1], connectTo3[0], connectTo3[1],
rOrder[0], rOrder[1], rOrder[2], rOrder[3]); rOrder[0], rOrder[1], rOrder[2], rOrder[3]);
@ -431,7 +431,7 @@ void ConvexHull_X_Test() {
} }
if (connectTo3[0] != connectTo3[1]) { if (connectTo3[0] != connectTo3[1]) {
if (rOrder[2] == rOrder[3]) { if (rOrder[2] == rOrder[3]) {
printf("%s [%d] (5) order=(%d,%d,%d,%d) r_order=(%d,%d,%d,%d)\n", SkDebugf("%s [%d] (5) order=(%d,%d,%d,%d) r_order=(%d,%d,%d,%d)\n",
__FUNCTION__, (int)index, connectTo0[0], connectTo0[1], __FUNCTION__, (int)index, connectTo0[0], connectTo0[1],
connectTo3[0], connectTo3[1], connectTo3[0], connectTo3[1],
rOrder[0], rOrder[1], rOrder[2], rOrder[3]); rOrder[0], rOrder[1], rOrder[2], rOrder[3]);
@ -440,7 +440,7 @@ void ConvexHull_X_Test() {
int unused = 6 - connectTo3[0] - connectTo3[1]; int unused = 6 - connectTo3[0] - connectTo3[1];
int rUnused = 6 - rOrder[2] - rOrder[3]; int rUnused = 6 - rOrder[2] - rOrder[3];
if (unused != rUnused) { if (unused != rUnused) {
printf("%s [%d] (6) order=(%d,%d,%d,%d) r_order=(%d,%d,%d,%d)\n", SkDebugf("%s [%d] (6) order=(%d,%d,%d,%d) r_order=(%d,%d,%d,%d)\n",
__FUNCTION__, (int)index, connectTo0[0], connectTo0[1], __FUNCTION__, (int)index, connectTo0[0], connectTo0[1],
connectTo3[0], connectTo3[1], connectTo3[0], connectTo3[1],
rOrder[0], rOrder[1], rOrder[2], rOrder[3]); rOrder[0], rOrder[1], rOrder[2], rOrder[3]);
@ -448,14 +448,14 @@ void ConvexHull_X_Test() {
} }
} else { } else {
if (rOrder[2] != rOrder[3]) { if (rOrder[2] != rOrder[3]) {
printf("%s [%d] (7) order=(%d,%d,%d,%d) r_order=(%d,%d,%d,%d)\n", SkDebugf("%s [%d] (7) order=(%d,%d,%d,%d) r_order=(%d,%d,%d,%d)\n",
__FUNCTION__, (int)index, connectTo0[0], connectTo0[1], __FUNCTION__, (int)index, connectTo0[0], connectTo0[1],
connectTo3[0], connectTo3[1], connectTo3[0], connectTo3[1],
rOrder[0], rOrder[1], rOrder[2], rOrder[3]); rOrder[0], rOrder[1], rOrder[2], rOrder[3]);
continue; continue;
} }
if (connectTo3[1] != rOrder[3]) { if (connectTo3[1] != rOrder[3]) {
printf("%s [%d] (8) order=(%d,%d,%d,%d) r_order=(%d,%d,%d,%d)\n", SkDebugf("%s [%d] (8) order=(%d,%d,%d,%d) r_order=(%d,%d,%d,%d)\n",
__FUNCTION__, (int)index, connectTo0[0], connectTo0[1], __FUNCTION__, (int)index, connectTo0[0], connectTo0[1],
connectTo3[0], connectTo3[1], connectTo3[0], connectTo3[1],
rOrder[0], rOrder[1], rOrder[2], rOrder[3]); rOrder[0], rOrder[1], rOrder[2], rOrder[3]);

View File

@ -7,7 +7,6 @@
#include "CurveIntersection.h" #include "CurveIntersection.h"
#include "CurveUtilities.h" #include "CurveUtilities.h"
#include "LineParameters.h" #include "LineParameters.h"
#include <algorithm> // used for std::swap
// return false if unable to clip (e.g., unable to create implicit line) // return false if unable to clip (e.g., unable to create implicit line)
// caller should subdivide, or create degenerate if the values are too small // caller should subdivide, or create degenerate if the values are too small
@ -33,7 +32,7 @@ bool bezier_clip(const Cubic& cubic1, const Cubic& cubic2, double& minT, double&
double top = distance[0]; double top = distance[0];
double bottom = distance[1]; double bottom = distance[1];
if (top > bottom) { if (top > bottom) {
std::swap(top, bottom); SkTSwap(top, bottom);
} }
if (top * bottom >= 0) { if (top * bottom >= 0) {
const double scale = 3/4.0; // http://cagd.cs.byu.edu/~tom/papers/bezclip.pdf (13) const double scale = 3/4.0; // http://cagd.cs.byu.edu/~tom/papers/bezclip.pdf (13)

View File

@ -16,10 +16,10 @@ void CubicBezierClip_Test() {
int order1 = reduceOrder(cubic1, reduce1, kReduceOrder_NoQuadraticsAllowed); int order1 = reduceOrder(cubic1, reduce1, kReduceOrder_NoQuadraticsAllowed);
int order2 = reduceOrder(cubic2, reduce2, kReduceOrder_NoQuadraticsAllowed); int order2 = reduceOrder(cubic2, reduce2, kReduceOrder_NoQuadraticsAllowed);
if (order1 < 4) { if (order1 < 4) {
printf("%s [%d] cubic1 order=%d\n", __FUNCTION__, (int) index, order1); SkDebugf("%s [%d] cubic1 order=%d\n", __FUNCTION__, (int) index, order1);
} }
if (order2 < 4) { if (order2 < 4) {
printf("%s [%d] cubic2 order=%d\n", __FUNCTION__, (int) index, order2); SkDebugf("%s [%d] cubic2 order=%d\n", __FUNCTION__, (int) index, order2);
} }
if (order1 == 4 && order2 == 4) { if (order1 == 4 && order2 == 4) {
double minT = 0; double minT = 0;

View File

@ -287,7 +287,7 @@ static bool intersect2(const Cubic& cubic1, double t1s, double t1e, const Cubic&
} }
#if SK_DEBUG #if SK_DEBUG
++debugDepth; ++debugDepth;
assert(debugDepth < 10); SkASSERT(debugDepth < 10);
#endif #endif
i.swap(); i.swap();
intersect2(cubic2, SkTMax(to2 - dt2, 0.), SkTMin(to2 + dt2, 1.), intersect2(cubic2, SkTMax(to2 - dt2, 0.), SkTMin(to2 + dt2, 1.),
@ -340,12 +340,12 @@ static bool intersectEnd(const Cubic& cubic1, bool start, const Cubic& cubic2, c
double tMin, tMax; double tMin, tMax;
tMin = tMax = local1.fT[0][0]; tMin = tMax = local1.fT[0][0];
for (int index = 1; index < local1.fUsed; ++index) { for (int index = 1; index < local1.fUsed; ++index) {
tMin = std::min(tMin, local1.fT[0][index]); tMin = SkTMin(tMin, local1.fT[0][index]);
tMax = std::max(tMax, local1.fT[0][index]); tMax = SkTMax(tMax, local1.fT[0][index]);
} }
for (int index = 1; index < local2.fUsed; ++index) { for (int index = 1; index < local2.fUsed; ++index) {
tMin = std::min(tMin, local2.fT[0][index]); tMin = SkTMin(tMin, local2.fT[0][index]);
tMax = std::max(tMax, local2.fT[0][index]); tMax = SkTMax(tMax, local2.fT[0][index]);
} }
#if SK_DEBUG #if SK_DEBUG
debugDepth = 0; debugDepth = 0;

View File

@ -93,11 +93,14 @@ static void oneOff(const Cubic& cubic1, const Cubic& cubic2) {
SkDebugf("%s t1=%1.9g (%1.9g, %1.9g) (%1.9g, %1.9g) t2=%1.9g\n", __FUNCTION__, SkDebugf("%s t1=%1.9g (%1.9g, %1.9g) (%1.9g, %1.9g) t2=%1.9g\n", __FUNCTION__,
tt1, xy1.x, xy1.y, xy2.x, xy2.y, tt2); tt1, xy1.x, xy1.y, xy2.x, xy2.y, tt2);
#endif #endif
assert(xy1.approximatelyEqual(xy2)); SkASSERT(xy1.approximatelyEqual(xy2));
} }
} }
static const Cubic testSet[] = { static const Cubic testSet[] = {
{{0, 1}, {0, 2}, {1, 0}, {1, 0}},
{{0, 1}, {0, 1}, {1, 0}, {2, 0}},
{{0, 0}, {0, 1}, {1, 1}, {1, 0}}, {{0, 0}, {0, 1}, {1, 1}, {1, 0}},
{{1, 0}, {0, 0}, {0, 1}, {1, 1}}, {{1, 0}, {0, 0}, {0, 1}, {1, 1}},
@ -250,12 +253,12 @@ void CubicIntersection_RandTestOld() {
SkDebugf("%s %d unexpected intersection boundsIntersect=%d oldIntersects=%d" SkDebugf("%s %d unexpected intersection boundsIntersect=%d oldIntersects=%d"
" newIntersects=%d\n%s %s\n", __FUNCTION__, test, boundsIntersect, " newIntersects=%d\n%s %s\n", __FUNCTION__, test, boundsIntersect,
oldIntersects, newIntersects, __FUNCTION__, str); oldIntersects, newIntersects, __FUNCTION__, str);
assert(0); SkASSERT(0);
} }
if (oldIntersects && !newIntersects) { if (oldIntersects && !newIntersects) {
SkDebugf("%s %d missing intersection oldIntersects=%d newIntersects=%d\n%s %s\n", SkDebugf("%s %d missing intersection oldIntersects=%d newIntersects=%d\n%s %s\n",
__FUNCTION__, test, oldIntersects, newIntersects, __FUNCTION__, str); __FUNCTION__, test, oldIntersects, newIntersects, __FUNCTION__, str);
assert(0); SkASSERT(0);
} }
if (!oldIntersects && !newIntersects) { if (!oldIntersects && !newIntersects) {
continue; continue;
@ -336,7 +339,7 @@ void CubicIntersection_RandTest() {
SkDebugf("%s %d unexpected intersection boundsIntersect=%d " SkDebugf("%s %d unexpected intersection boundsIntersect=%d "
" newIntersects=%d\n%s %s\n", __FUNCTION__, test, boundsIntersect, " newIntersects=%d\n%s %s\n", __FUNCTION__, test, boundsIntersect,
newIntersects, __FUNCTION__, str); newIntersects, __FUNCTION__, str);
assert(0); SkASSERT(0);
} }
for (int pt = 0; pt < intersections2.used(); ++pt) { for (int pt = 0; pt < intersections2.used(); ++pt) {
double tt1 = intersections2.fT[0][pt]; double tt1 = intersections2.fT[0][pt];
@ -349,7 +352,7 @@ void CubicIntersection_RandTest() {
SkDebugf("%s t1=%1.9g (%1.9g, %1.9g) (%1.9g, %1.9g) t2=%1.9g\n", __FUNCTION__, SkDebugf("%s t1=%1.9g (%1.9g, %1.9g) (%1.9g, %1.9g) t2=%1.9g\n", __FUNCTION__,
tt1, xy1.x, xy1.y, xy2.x, xy2.y, tt2); tt1, xy1.x, xy1.y, xy2.x, xy2.y, tt2);
#endif #endif
assert(xy1.approximatelyEqual(xy2)); SkASSERT(xy1.approximatelyEqual(xy2));
} }
} }
} }

View File

@ -6,7 +6,6 @@
*/ */
#include "CubicLineSegments.h" #include "CubicLineSegments.h"
#include "QuadraticLineSegments.h" #include "QuadraticLineSegments.h"
#include <algorithm> // used for std::max
// http://cagd.cs.byu.edu/~557/text/cagd.pdf 2.7 // http://cagd.cs.byu.edu/~557/text/cagd.pdf 2.7
// A hodograph is the first derivative curve // A hodograph is the first derivative curve
@ -31,8 +30,8 @@ void secondHodograph(const Cubic& cubic, _Line& hodo2) {
double subDivisions(const Cubic& cubic) { double subDivisions(const Cubic& cubic) {
_Line hodo2; _Line hodo2;
secondHodograph(cubic, hodo2); secondHodograph(cubic, hodo2);
double maxX = std::max(hodo2[1].x, hodo2[1].x); double maxX = SkTMax(hodo2[1].x, hodo2[1].x);
double maxY = std::max(hodo2[1].y, hodo2[1].y); double maxY = SkTMax(hodo2[1].y, hodo2[1].y);
double dist = sqrt(maxX * maxX + maxY * maxY); double dist = sqrt(maxX * maxX + maxY * maxY);
double segments = sqrt(dist / (8 * FLT_EPSILON)); double segments = sqrt(dist / (8 * FLT_EPSILON));
return segments; return segments;

View File

@ -34,19 +34,19 @@ void CubicCoincidence_Test() {
quad_to_cubic(split.second(), second); quad_to_cubic(split.second(), second);
quad_to_cubic(midThird, mid); quad_to_cubic(midThird, mid);
if (!implicit_matches(whole, first)) { if (!implicit_matches(whole, first)) {
printf("%s-1 %d\n", __FUNCTION__, (int)index); SkDebugf("%s-1 %d\n", __FUNCTION__, (int)index);
} }
if (!implicit_matches(whole, second)) { if (!implicit_matches(whole, second)) {
printf("%s-2 %d\n", __FUNCTION__, (int)index); SkDebugf("%s-2 %d\n", __FUNCTION__, (int)index);
} }
if (!implicit_matches(mid, first)) { if (!implicit_matches(mid, first)) {
printf("%s-3 %d\n", __FUNCTION__, (int)index); SkDebugf("%s-3 %d\n", __FUNCTION__, (int)index);
} }
if (!implicit_matches(mid, second)) { if (!implicit_matches(mid, second)) {
printf("%s-4 %d\n", __FUNCTION__, (int)index); SkDebugf("%s-4 %d\n", __FUNCTION__, (int)index);
} }
if (!implicit_matches(first, second)) { if (!implicit_matches(first, second)) {
printf("%s-5 %d\n", __FUNCTION__, (int)index); SkDebugf("%s-5 %d\n", __FUNCTION__, (int)index);
} }
} }
} }
@ -98,16 +98,16 @@ void CubicParameterization_Test() {
for (size_t index = firstCubicParameterizationTest; index < cubics_count; ++index) { for (size_t index = firstCubicParameterizationTest; index < cubics_count; ++index) {
for (size_t inner = 0; inner < 4; inner += 3) { for (size_t inner = 0; inner < 4; inner += 3) {
if (!point_on_parameterized_curve(cubics[index], cubics[index][inner])) { if (!point_on_parameterized_curve(cubics[index], cubics[index][inner])) {
printf("%s [%zu,%zu] 1 parameterization failed\n", SkDebugf("%s [%zu,%zu] 1 parameterization failed\n",
__FUNCTION__, index, inner); __FUNCTION__, index, inner);
} }
if (!point_on_parameterized_curve(cubics[index], cubics[index ^ 1][inner])) { if (!point_on_parameterized_curve(cubics[index], cubics[index ^ 1][inner])) {
printf("%s [%zu,%zu] 2 parameterization failed\n", SkDebugf("%s [%zu,%zu] 2 parameterization failed\n",
__FUNCTION__, index, inner); __FUNCTION__, index, inner);
} }
} }
if (!implicit_matches(cubics[index], cubics[index ^ 1])) { if (!implicit_matches(cubics[index], cubics[index ^ 1])) {
printf("%s %d\n", __FUNCTION__, (int)index); SkDebugf("%s %d\n", __FUNCTION__, (int)index);
} }
} }
} }

View File

@ -93,7 +93,7 @@ static int check_linear(const Cubic& cubic, Cubic& reduction,
--endIndex; --endIndex;
if (endIndex == 0) { if (endIndex == 0) {
printf("%s shouldn't get here if all four points are about equal\n", __FUNCTION__); printf("%s shouldn't get here if all four points are about equal\n", __FUNCTION__);
assert(0); SkASSERT(0);
} }
} }
if (!isLinear(cubic, startIndex, endIndex)) { if (!isLinear(cubic, startIndex, endIndex)) {

View File

@ -33,64 +33,64 @@ void CubicReduceOrder_Test() {
run = RunComputedLines; run = RunComputedLines;
firstTestIndex = 18; firstTestIndex = 18;
#endif #endif
int firstPointDegeneratesTest = run == RunAll ? 0 : run == RunPointDegenerates ? firstTestIndex : INT_MAX; int firstPointDegeneratesTest = run == RunAll ? 0 : run == RunPointDegenerates ? firstTestIndex : SK_MaxS32;
int firstNotPointDegeneratesTest = run == RunAll ? 0 : run == RunNotPointDegenerates ? firstTestIndex : INT_MAX; int firstNotPointDegeneratesTest = run == RunAll ? 0 : run == RunNotPointDegenerates ? firstTestIndex : SK_MaxS32;
int firstLinesTest = run == RunAll ? 0 : run == RunLines ? firstTestIndex : INT_MAX; int firstLinesTest = run == RunAll ? 0 : run == RunLines ? firstTestIndex : SK_MaxS32;
int firstNotLinesTest = run == RunAll ? 0 : run == RunNotLines ? firstTestIndex : INT_MAX; int firstNotLinesTest = run == RunAll ? 0 : run == RunNotLines ? firstTestIndex : SK_MaxS32;
int firstModEpsilonTest = run == RunAll ? 0 : run == RunModEpsilonLines ? firstTestIndex : INT_MAX; int firstModEpsilonTest = run == RunAll ? 0 : run == RunModEpsilonLines ? firstTestIndex : SK_MaxS32;
int firstLessEpsilonTest = run == RunAll ? 0 : run == RunLessEpsilonLines ? firstTestIndex : INT_MAX; int firstLessEpsilonTest = run == RunAll ? 0 : run == RunLessEpsilonLines ? firstTestIndex : SK_MaxS32;
int firstNegEpsilonTest = run == RunAll ? 0 : run == RunNegEpsilonLines ? firstTestIndex : INT_MAX; int firstNegEpsilonTest = run == RunAll ? 0 : run == RunNegEpsilonLines ? firstTestIndex : SK_MaxS32;
int firstQuadraticLineTest = run == RunAll ? 0 : run == RunQuadraticLines ? firstTestIndex : INT_MAX; int firstQuadraticLineTest = run == RunAll ? 0 : run == RunQuadraticLines ? firstTestIndex : SK_MaxS32;
int firstQuadraticModLineTest = run == RunAll ? 0 : run == RunQuadraticModLines ? firstTestIndex : INT_MAX; int firstQuadraticModLineTest = run == RunAll ? 0 : run == RunQuadraticModLines ? firstTestIndex : SK_MaxS32;
int firstComputedLinesTest = run == RunAll ? 0 : run == RunComputedLines ? firstTestIndex : INT_MAX; int firstComputedLinesTest = run == RunAll ? 0 : run == RunComputedLines ? firstTestIndex : SK_MaxS32;
for (index = firstPointDegeneratesTest; index < pointDegenerates_count; ++index) { for (index = firstPointDegeneratesTest; index < pointDegenerates_count; ++index) {
const Cubic& cubic = pointDegenerates[index]; const Cubic& cubic = pointDegenerates[index];
order = reduceOrder(cubic, reduce, kReduceOrder_QuadraticsAllowed); order = reduceOrder(cubic, reduce, kReduceOrder_QuadraticsAllowed);
if (order != 1) { if (order != 1) {
printf("[%d] pointDegenerates order=%d\n", (int) index, order); SkDebugf("[%d] pointDegenerates order=%d\n", (int) index, order);
} }
} }
for (index = firstNotPointDegeneratesTest; index < notPointDegenerates_count; ++index) { for (index = firstNotPointDegeneratesTest; index < notPointDegenerates_count; ++index) {
const Cubic& cubic = notPointDegenerates[index]; const Cubic& cubic = notPointDegenerates[index];
order = reduceOrder(cubic, reduce, kReduceOrder_QuadraticsAllowed); order = reduceOrder(cubic, reduce, kReduceOrder_QuadraticsAllowed);
if (order == 1) { if (order == 1) {
printf("[%d] notPointDegenerates order=%d\n", (int) index, order); SkDebugf("[%d] notPointDegenerates order=%d\n", (int) index, order);
} }
} }
for (index = firstLinesTest; index < lines_count; ++index) { for (index = firstLinesTest; index < lines_count; ++index) {
const Cubic& cubic = lines[index]; const Cubic& cubic = lines[index];
order = reduceOrder(cubic, reduce, kReduceOrder_QuadraticsAllowed); order = reduceOrder(cubic, reduce, kReduceOrder_QuadraticsAllowed);
if (order != 2) { if (order != 2) {
printf("[%d] lines order=%d\n", (int) index, order); SkDebugf("[%d] lines order=%d\n", (int) index, order);
} }
} }
for (index = firstNotLinesTest; index < notLines_count; ++index) { for (index = firstNotLinesTest; index < notLines_count; ++index) {
const Cubic& cubic = notLines[index]; const Cubic& cubic = notLines[index];
order = reduceOrder(cubic, reduce, kReduceOrder_QuadraticsAllowed); order = reduceOrder(cubic, reduce, kReduceOrder_QuadraticsAllowed);
if (order == 2) { if (order == 2) {
printf("[%d] notLines order=%d\n", (int) index, order); SkDebugf("[%d] notLines order=%d\n", (int) index, order);
} }
} }
for (index = firstModEpsilonTest; index < modEpsilonLines_count; ++index) { for (index = firstModEpsilonTest; index < modEpsilonLines_count; ++index) {
const Cubic& cubic = modEpsilonLines[index]; const Cubic& cubic = modEpsilonLines[index];
order = reduceOrder(cubic, reduce, kReduceOrder_QuadraticsAllowed); order = reduceOrder(cubic, reduce, kReduceOrder_QuadraticsAllowed);
if (order == 2) { if (order == 2) {
printf("[%d] line mod by epsilon order=%d\n", (int) index, order); SkDebugf("[%d] line mod by epsilon order=%d\n", (int) index, order);
} }
} }
for (index = firstLessEpsilonTest; index < lessEpsilonLines_count; ++index) { for (index = firstLessEpsilonTest; index < lessEpsilonLines_count; ++index) {
const Cubic& cubic = lessEpsilonLines[index]; const Cubic& cubic = lessEpsilonLines[index];
order = reduceOrder(cubic, reduce, kReduceOrder_QuadraticsAllowed); order = reduceOrder(cubic, reduce, kReduceOrder_QuadraticsAllowed);
if (order != 2) { if (order != 2) {
printf("[%d] line less by epsilon/2 order=%d\n", (int) index, order); SkDebugf("[%d] line less by epsilon/2 order=%d\n", (int) index, order);
} }
} }
for (index = firstNegEpsilonTest; index < negEpsilonLines_count; ++index) { for (index = firstNegEpsilonTest; index < negEpsilonLines_count; ++index) {
const Cubic& cubic = negEpsilonLines[index]; const Cubic& cubic = negEpsilonLines[index];
order = reduceOrder(cubic, reduce, kReduceOrder_QuadraticsAllowed); order = reduceOrder(cubic, reduce, kReduceOrder_QuadraticsAllowed);
if (order != 2) { if (order != 2) {
printf("[%d] line neg by epsilon/2 order=%d\n", (int) index, order); SkDebugf("[%d] line neg by epsilon/2 order=%d\n", (int) index, order);
} }
} }
for (index = firstQuadraticLineTest; index < quadraticLines_count; ++index) { for (index = firstQuadraticLineTest; index < quadraticLines_count; ++index) {
@ -99,7 +99,7 @@ void CubicReduceOrder_Test() {
quad_to_cubic(quad, cubic); quad_to_cubic(quad, cubic);
order = reduceOrder(cubic, reduce, kReduceOrder_QuadraticsAllowed); order = reduceOrder(cubic, reduce, kReduceOrder_QuadraticsAllowed);
if (order != 2) { if (order != 2) {
printf("[%d] line quad order=%d\n", (int) index, order); SkDebugf("[%d] line quad order=%d\n", (int) index, order);
} }
} }
for (index = firstQuadraticModLineTest; index < quadraticModEpsilonLines_count; ++index) { for (index = firstQuadraticModLineTest; index < quadraticModEpsilonLines_count; ++index) {
@ -108,7 +108,7 @@ void CubicReduceOrder_Test() {
quad_to_cubic(quad, cubic); quad_to_cubic(quad, cubic);
order = reduceOrder(cubic, reduce, kReduceOrder_QuadraticsAllowed); order = reduceOrder(cubic, reduce, kReduceOrder_QuadraticsAllowed);
if (order != 3) { if (order != 3) {
printf("[%d] line mod quad order=%d\n", (int) index, order); SkDebugf("[%d] line mod quad order=%d\n", (int) index, order);
} }
} }
@ -118,14 +118,14 @@ void CubicReduceOrder_Test() {
bool controlsInside = controls_inside(cubic); bool controlsInside = controls_inside(cubic);
order = reduceOrder(cubic, reduce, kReduceOrder_QuadraticsAllowed); order = reduceOrder(cubic, reduce, kReduceOrder_QuadraticsAllowed);
if (reduce[0].x == reduce[1].x && reduce[0].y == reduce[1].y) { if (reduce[0].x == reduce[1].x && reduce[0].y == reduce[1].y) {
printf("[%d] line computed ends match order=%d\n", (int) index, order); SkDebugf("[%d] line computed ends match order=%d\n", (int) index, order);
} }
if (controlsInside) { if (controlsInside) {
if ( (reduce[0].x != cubic[0].x && reduce[0].x != cubic[3].x) if ( (reduce[0].x != cubic[0].x && reduce[0].x != cubic[3].x)
|| (reduce[0].y != cubic[0].y && reduce[0].y != cubic[3].y) || (reduce[0].y != cubic[0].y && reduce[0].y != cubic[3].y)
|| (reduce[1].x != cubic[0].x && reduce[1].x != cubic[3].x) || (reduce[1].x != cubic[0].x && reduce[1].x != cubic[3].x)
|| (reduce[1].y != cubic[0].y && reduce[1].y != cubic[3].y)) { || (reduce[1].y != cubic[0].y && reduce[1].y != cubic[3].y)) {
printf("[%d] line computed ends order=%d\n", (int) index, order); SkDebugf("[%d] line computed ends order=%d\n", (int) index, order);
} }
} else { } else {
// binary search for extrema, compare against actual results // binary search for extrema, compare against actual results
@ -136,7 +136,7 @@ void CubicReduceOrder_Test() {
|| (!AlmostEqualUlps(reduce[0].y, bounds.top) && !AlmostEqualUlps(reduce[0].y, bounds.bottom)) || (!AlmostEqualUlps(reduce[0].y, bounds.top) && !AlmostEqualUlps(reduce[0].y, bounds.bottom))
|| (!AlmostEqualUlps(reduce[1].x, bounds.left) && !AlmostEqualUlps(reduce[1].x, bounds.right)) || (!AlmostEqualUlps(reduce[1].x, bounds.left) && !AlmostEqualUlps(reduce[1].x, bounds.right))
|| (!AlmostEqualUlps(reduce[1].y, bounds.top) && !AlmostEqualUlps(reduce[1].y, bounds.bottom))) { || (!AlmostEqualUlps(reduce[1].y, bounds.top) && !AlmostEqualUlps(reduce[1].y, bounds.bottom))) {
printf("[%d] line computed tight bounds order=%d\n", (int) index, order); SkDebugf("[%d] line computed tight bounds order=%d\n", (int) index, order);
} }
} }

View File

@ -40,7 +40,7 @@ static void testC(const Cubic* cubics, const char* name, int firstTest, size_t t
const Cubic& cubic = cubics[index]; const Cubic& cubic = cubics[index];
double precision = calcPrecision(cubic); double precision = calcPrecision(cubic);
int order = cubic_to_quadratics(cubic, precision, quads); int order = cubic_to_quadratics(cubic, precision, quads);
assert(order != 4); SkASSERT(order != 4);
if (order < 3) { if (order < 3) {
continue; continue;
} }
@ -63,7 +63,7 @@ static void testC(const Cubic(* cubics)[2], const char* name, int firstTest, siz
const Cubic& cubic = cubics[index][idx2]; const Cubic& cubic = cubics[index][idx2];
double precision = calcPrecision(cubic); double precision = calcPrecision(cubic);
int order = cubic_to_quadratics(cubic, precision, quads); int order = cubic_to_quadratics(cubic, precision, quads);
assert(order != 4); SkASSERT(order != 4);
if (order < 3) { if (order < 3) {
continue; continue;
} }
@ -101,17 +101,17 @@ void CubicToQuadratics_Test() {
run = RunComputedLines; run = RunComputedLines;
firstTestIndex = 18; firstTestIndex = 18;
#endif #endif
int firstPointDegeneratesTest = run == RunAll ? 0 : run == RunPointDegenerates ? firstTestIndex : INT_MAX; int firstPointDegeneratesTest = run == RunAll ? 0 : run == RunPointDegenerates ? firstTestIndex : SK_MaxS32;
int firstNotPointDegeneratesTest = run == RunAll ? 0 : run == RunNotPointDegenerates ? firstTestIndex : INT_MAX; int firstNotPointDegeneratesTest = run == RunAll ? 0 : run == RunNotPointDegenerates ? firstTestIndex : SK_MaxS32;
int firstLinesTest = run == RunAll ? 0 : run == RunLines ? firstTestIndex : INT_MAX; int firstLinesTest = run == RunAll ? 0 : run == RunLines ? firstTestIndex : SK_MaxS32;
int firstNotLinesTest = run == RunAll ? 0 : run == RunNotLines ? firstTestIndex : INT_MAX; int firstNotLinesTest = run == RunAll ? 0 : run == RunNotLines ? firstTestIndex : SK_MaxS32;
int firstModEpsilonTest = run == RunAll ? 0 : run == RunModEpsilonLines ? firstTestIndex : INT_MAX; int firstModEpsilonTest = run == RunAll ? 0 : run == RunModEpsilonLines ? firstTestIndex : SK_MaxS32;
int firstLessEpsilonTest = run == RunAll ? 0 : run == RunLessEpsilonLines ? firstTestIndex : INT_MAX; int firstLessEpsilonTest = run == RunAll ? 0 : run == RunLessEpsilonLines ? firstTestIndex : SK_MaxS32;
int firstNegEpsilonTest = run == RunAll ? 0 : run == RunNegEpsilonLines ? firstTestIndex : INT_MAX; int firstNegEpsilonTest = run == RunAll ? 0 : run == RunNegEpsilonLines ? firstTestIndex : SK_MaxS32;
int firstQuadraticLineTest = run == RunAll ? 0 : run == RunQuadraticLines ? firstTestIndex : INT_MAX; int firstQuadraticLineTest = run == RunAll ? 0 : run == RunQuadraticLines ? firstTestIndex : SK_MaxS32;
int firstQuadraticModLineTest = run == RunAll ? 0 : run == RunQuadraticModLines ? firstTestIndex : INT_MAX; int firstQuadraticModLineTest = run == RunAll ? 0 : run == RunQuadraticModLines ? firstTestIndex : SK_MaxS32;
int firstComputedLinesTest = run == RunAll ? 0 : run == RunComputedLines ? firstTestIndex : INT_MAX; int firstComputedLinesTest = run == RunAll ? 0 : run == RunComputedLines ? firstTestIndex : SK_MaxS32;
int firstComputedCubicsTest = run == RunAll ? 0 : run == RunComputedTests ? firstTestIndex : INT_MAX; int firstComputedCubicsTest = run == RunAll ? 0 : run == RunComputedTests ? firstTestIndex : SK_MaxS32;
test(pointDegenerates, "pointDegenerates", firstPointDegeneratesTest, pointDegenerates_count); test(pointDegenerates, "pointDegenerates", firstPointDegeneratesTest, pointDegenerates_count);
test(notPointDegenerates, "notPointDegenerates", firstNotPointDegeneratesTest, notPointDegenerates_count); test(notPointDegenerates, "notPointDegenerates", firstNotPointDegeneratesTest, notPointDegenerates_count);
@ -191,8 +191,8 @@ void CubicsToQuadratics_RandTest() {
double precision = calcPrecision(cubic); double precision = calcPrecision(cubic);
(void) cubic_to_quadratics(cubic, precision, quads); (void) cubic_to_quadratics(cubic, precision, quads);
int count = quads.count(); int count = quads.count();
assert(count > 0); SkASSERT(count > 0);
assert(--count < arrayMax); SkASSERT(--count < arrayMax);
quadDist[count]++; quadDist[count]++;
int sCount = sampleCount[count]; int sCount = sampleCount[count];
if (sCount < sampleMax) { if (sCount < sampleMax) {

View File

@ -7,16 +7,10 @@
#ifndef __DataTypes_h__ #ifndef __DataTypes_h__
#define __DataTypes_h__ #define __DataTypes_h__
#include <assert.h> #include <float.h> // for FLT_EPSILON
#include <float.h> #include <math.h> // for fabs, sqrt
#include <limits.h>
#include <math.h> #include "SkTypes.h"
#include <stdarg.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <strings.h>
#include <sys/types.h>
extern bool AlmostEqualUlps(float A, float B); extern bool AlmostEqualUlps(float A, float B);
inline bool AlmostEqualUlps(double A, double B) { return AlmostEqualUlps((float) A, (float) B); } inline bool AlmostEqualUlps(double A, double B) { return AlmostEqualUlps((float) A, (float) B); }
@ -146,14 +140,14 @@ inline bool approximately_zero_or_more(double x) {
} }
inline bool approximately_between(double a, double b, double c) { inline bool approximately_between(double a, double b, double c) {
assert(a <= c); SkASSERT(a <= c);
return a <= c ? approximately_negative(a - b) && approximately_negative(b - c) return a <= c ? approximately_negative(a - b) && approximately_negative(b - c)
: approximately_negative(b - a) && approximately_negative(c - b); : approximately_negative(b - a) && approximately_negative(c - b);
} }
// returns true if (a <= b <= c) || (a >= b >= c) // returns true if (a <= b <= c) || (a >= b >= c)
inline bool between(double a, double b, double c) { inline bool between(double a, double b, double c) {
assert(((a <= b && b <= c) || (a >= b && b >= c)) == ((a - b) * (c - b) <= 0)); SkASSERT(((a <= b && b <= c) || (a >= b && b >= c)) == ((a - b) * (c - b) <= 0));
return (a - b) * (c - b) <= 0; return (a - b) * (c - b) <= 0;
} }
@ -252,10 +246,10 @@ struct _Rect {
} }
bool intersects(_Rect& r) const { bool intersects(_Rect& r) const {
assert(left <= right); SkASSERT(left <= right);
assert(top <= bottom); SkASSERT(top <= bottom);
assert(r.left <= r.right); SkASSERT(r.left <= r.right);
assert(r.top <= r.bottom); SkASSERT(r.top <= r.bottom);
return r.left <= right && left <= r.right && r.top <= bottom && top <= r.bottom; return r.left <= right && left <= r.right && r.top <= bottom && top <= r.bottom;
} }

View File

@ -150,6 +150,7 @@ static bool drawStars(SkCanvas* canvas, int step, bool useOld)
return drawPaths(canvas, path, useOld); return drawPaths(canvas, path, useOld);
} }
#if 0
static void tryRoncoOnce(const SkPath& path, const SkRect& target, bool show) { static void tryRoncoOnce(const SkPath& path, const SkRect& target, bool show) {
// capture everything in a desired rectangle // capture everything in a desired rectangle
SkPath tiny; SkPath tiny;
@ -226,7 +227,9 @@ static void tryRoncoOnce(const SkPath& path, const SkRect& target, bool show) {
} }
testSimplifyx(tiny); testSimplifyx(tiny);
} }
#endif
#if 0
static void tryRonco(const SkPath& path) { static void tryRonco(const SkPath& path) {
int divMax = 64; int divMax = 64;
int divMin = 1; int divMin = 1;
@ -261,6 +264,7 @@ static void tryRonco(const SkPath& path) {
} }
} }
} }
#endif
static bool drawLetters(SkCanvas* canvas, int step, bool useOld) static bool drawLetters(SkCanvas* canvas, int step, bool useOld)
{ {
@ -329,7 +333,7 @@ static bool (*drawDemos[])(SkCanvas* , int , bool ) = {
static size_t drawDemosCount = sizeof(drawDemos) / sizeof(drawDemos[0]); static size_t drawDemosCount = sizeof(drawDemos) / sizeof(drawDemos[0]);
static bool (*firstTest)(SkCanvas* , int , bool) = drawLetters; static bool (*firstTest)(SkCanvas* , int , bool) = drawStars;
bool DrawEdgeDemo(SkCanvas* canvas, int step, bool useOld) { bool DrawEdgeDemo(SkCanvas* canvas, int step, bool useOld) {

View File

@ -8,7 +8,6 @@
#include "Intersection_Tests.h" #include "Intersection_Tests.h"
#include "SkBitmap.h" #include "SkBitmap.h"
#include "SkCanvas.h" #include "SkCanvas.h"
#include <assert.h>
static void* testSimplify4x4QuadraticsMain(void* data) static void* testSimplify4x4QuadraticsMain(void* data)

View File

@ -12,7 +12,6 @@
#include "SkStream.h" #include "SkStream.h"
#include <algorithm> #include <algorithm>
#include <assert.h>
#include <errno.h> #include <errno.h>
#include <pthread.h> #include <pthread.h>
#include <unistd.h> #include <unistd.h>
@ -581,7 +580,11 @@ void outputToStream(const State4& state, const char* pathStr, const char* pathPr
outFile.writeText("static void "); outFile.writeText("static void ");
writeTestName(nameSuffix, outFile); writeTestName(nameSuffix, outFile);
outFile.writeText("() {\n SkPath path;\n"); outFile.writeText("() {\n SkPath path");
if (!pathPrefix) {
outFile.writeText(", pathB");
}
outFile.writeText(";\n");
if (pathPrefix) { if (pathPrefix) {
outFile.writeText(pathPrefix); outFile.writeText(pathPrefix);
} }

View File

@ -12,7 +12,7 @@ static void assert_that(int x, int y, const char* s) {
if (x == y) { if (x == y) {
return; return;
} }
printf("result=%d expected=%d %s\n", x, y, s); SkDebugf("result=%d expected=%d %s\n", x, y, s);
} }
static void side_test() { static void side_test() {
@ -41,7 +41,7 @@ static void other_two_test() {
if (all == 0x0F) { if (all == 0x0F) {
continue; continue;
} }
printf("[%d,%d] other_two failed mask=%d [%d,%d]\n", SkDebugf("[%d,%d] other_two failed mask=%d [%d,%d]\n",
x, y, mask, x ^ mask, y ^ mask); x, y, mask, x ^ mask, y ^ mask);
} }
} }

View File

@ -6,7 +6,6 @@
*/ */
#include "CubicIntersection_TestData.h" #include "CubicIntersection_TestData.h"
#include "Intersection_Tests.h" #include "Intersection_Tests.h"
#include "SkTypes.h"
void cubecode_test(int test); void cubecode_test(int test);
@ -16,8 +15,9 @@ void Intersection_Tests() {
int testsRun = 0; int testsRun = 0;
SimplifyNew_Test(); SimplifyNew_Test();
CubicToQuadratics_Test();
CubicIntersection_OneOffTest(); CubicIntersection_OneOffTest();
ShapeOps4x4CubicsThreaded_Test(testsRun);
CubicToQuadratics_Test();
QuadraticIntersection_Test(); QuadraticIntersection_Test();
QuarticRoot_Test(); QuarticRoot_Test();
CubicIntersection_RandTest(); CubicIntersection_RandTest();

View File

@ -41,6 +41,7 @@ void Simplify4x4QuadralateralsThreaded_Test(int& );
void Simplify4x4QuadraticsThreaded_Test(int& ); void Simplify4x4QuadraticsThreaded_Test(int& );
void Simplify4x4RectsThreaded_Test(int& ); void Simplify4x4RectsThreaded_Test(int& );
void SimplifyRectangularPaths_Test(); void SimplifyRectangularPaths_Test();
void ShapeOps4x4CubicsThreaded_Test(int& );
void ShapeOps4x4RectsThreaded_Test(int& ); void ShapeOps4x4RectsThreaded_Test(int& );
void QuadLineIntersectThreaded_Test(int& ); void QuadLineIntersectThreaded_Test(int& );
void QuadraticBezierClip_Test(); void QuadraticBezierClip_Test();

View File

@ -9,7 +9,7 @@
#include "Intersections.h" #include "Intersections.h"
void Intersections::addCoincident(double s1, double e1, double s2, double e2) { void Intersections::addCoincident(double s1, double e1, double s2, double e2) {
assert((fCoincidentUsed & 1) != 1); SkASSERT((fCoincidentUsed & 1) != 1);
for (int index = 0; index < fCoincidentUsed; index += 2) { for (int index = 0; index < fCoincidentUsed; index += 2) {
double cs1 = fCoincidentT[fSwap][index]; double cs1 = fCoincidentT[fSwap][index];
double ce1 = fCoincidentT[fSwap][index + 1]; double ce1 = fCoincidentT[fSwap][index + 1];
@ -20,7 +20,7 @@ void Intersections::addCoincident(double s1, double e1, double s2, double e2) {
bool s2in = approximately_between(cs2, s2, ce2); bool s2in = approximately_between(cs2, s2, ce2);
bool e2in = approximately_between(cs2, e2, ce2); bool e2in = approximately_between(cs2, e2, ce2);
if ((s1in | e1in) & (s2in | e2in)) { if ((s1in | e1in) & (s2in | e2in)) {
double lesser1 = std::min(cs1, ce1); double lesser1 = SkTMin(cs1, ce1);
index += cs1 > ce1; index += cs1 > ce1;
if (s1in < lesser1) { if (s1in < lesser1) {
fCoincidentT[fSwap][index] = s1in; fCoincidentT[fSwap][index] = s1in;
@ -35,7 +35,7 @@ void Intersections::addCoincident(double s1, double e1, double s2, double e2) {
fCoincidentT[fSwap][index] = e1in; fCoincidentT[fSwap][index] = e1in;
} }
index &= ~1; index &= ~1;
double lesser2 = std::min(cs2, ce2); double lesser2 = SkTMin(cs2, ce2);
index += cs2 > ce2; index += cs2 > ce2;
if (s2in < lesser2) { if (s2in < lesser2) {
fCoincidentT[fSwap ^ 1][index] = s2in; fCoincidentT[fSwap ^ 1][index] = s2in;
@ -52,7 +52,7 @@ void Intersections::addCoincident(double s1, double e1, double s2, double e2) {
return; return;
} }
} }
assert(fCoincidentUsed < 9); SkASSERT(fCoincidentUsed < 9);
fCoincidentT[fSwap][fCoincidentUsed] = s1; fCoincidentT[fSwap][fCoincidentUsed] = s1;
fCoincidentT[fSwap ^ 1][fCoincidentUsed] = s2; fCoincidentT[fSwap ^ 1][fCoincidentUsed] = s2;
++fCoincidentUsed; ++fCoincidentUsed;
@ -62,15 +62,15 @@ void Intersections::addCoincident(double s1, double e1, double s2, double e2) {
} }
void Intersections::cleanUp() { void Intersections::cleanUp() {
assert(fCoincidentUsed); SkASSERT(fCoincidentUsed);
assert(fUsed); SkASSERT(fUsed);
// find any entries in fT that could be part of the coincident range // find any entries in fT that could be part of the coincident range
} }
// FIXME: this doesn't respect swap, but add coincident does -- seems inconsistent // FIXME: this doesn't respect swap, but add coincident does -- seems inconsistent
void Intersections::insert(double one, double two) { void Intersections::insert(double one, double two) {
assert(fUsed <= 1 || fT[0][0] < fT[0][1]); SkASSERT(fUsed <= 1 || fT[0][0] < fT[0][1]);
int index; int index;
for (index = 0; index < fUsed; ++index) { for (index = 0; index < fUsed; ++index) {
if (approximately_equal(fT[0][index], one) if (approximately_equal(fT[0][index], one)
@ -81,7 +81,7 @@ void Intersections::insert(double one, double two) {
break; break;
} }
} }
assert(fUsed < 9); SkASSERT(fUsed < 9);
int remaining = fUsed - index; int remaining = fUsed - index;
if (remaining > 0) { if (remaining > 0) {
memmove(&fT[0][index + 1], &fT[0][index], sizeof(fT[0][0]) * remaining); memmove(&fT[0][index + 1], &fT[0][index], sizeof(fT[0][0]) * remaining);
@ -96,7 +96,7 @@ void Intersections::insert(double one, double two) {
// if two separate callers differ on whether ts are equal or not // if two separate callers differ on whether ts are equal or not
void Intersections::insertOne(double t, int side) { void Intersections::insertOne(double t, int side) {
int used = side ? fUsed2 : fUsed; int used = side ? fUsed2 : fUsed;
assert(used <= 1 || fT[side][0] < fT[side][1]); SkASSERT(used <= 1 || fT[side][0] < fT[side][1]);
int index; int index;
for (index = 0; index < used; ++index) { for (index = 0; index < used; ++index) {
if (approximately_equal(fT[side][index], t)) { if (approximately_equal(fT[side][index], t)) {
@ -106,7 +106,7 @@ void Intersections::insertOne(double t, int side) {
break; break;
} }
} }
assert(used < 9); SkASSERT(used < 9);
int remaining = used - index; int remaining = used - index;
if (remaining > 0) { if (remaining > 0) {
memmove(&fT[side][index + 1], &fT[side][index], sizeof(fT[side][0]) * remaining); memmove(&fT[side][index + 1], &fT[side][index], sizeof(fT[side][0]) * remaining);

View File

@ -7,9 +7,6 @@
#ifndef Intersections_DEFINE #ifndef Intersections_DEFINE
#define Intersections_DEFINE #define Intersections_DEFINE
#include <algorithm> // for std::min -- Skia doesn't have a SkMinDouble
#include "SkTypes.h"
class Intersections { class Intersections {
public: public:
Intersections() Intersections()
@ -29,7 +26,7 @@ public:
return; return;
} }
} }
assert(fUsed < 9); SkASSERT(fUsed < 9);
fT[fSwap][fUsed] = one; fT[fSwap][fUsed] = one;
fT[fSwap ^ 1][fUsed] = two; fT[fSwap ^ 1][fUsed] = two;
++fUsed; ++fUsed;
@ -43,7 +40,7 @@ public:
return; return;
} }
} }
assert(fCoincidentUsed < 9); SkASSERT(fCoincidentUsed < 9);
fCoincidentT[fSwap][fCoincidentUsed] = one; fCoincidentT[fSwap][fCoincidentUsed] = one;
fCoincidentT[fSwap ^ 1][fCoincidentUsed] = two; fCoincidentT[fSwap ^ 1][fCoincidentUsed] = two;
++fCoincidentUsed; ++fCoincidentUsed;

View File

@ -7,7 +7,6 @@
#include "CurveIntersection.h" #include "CurveIntersection.h"
#include "Intersections.h" #include "Intersections.h"
#include "LineIntersection.h" #include "LineIntersection.h"
#include <algorithm> // used for std::swap
/* Determine the intersection point of two lines. This assumes the lines are not parallel, /* Determine the intersection point of two lines. This assumes the lines are not parallel,
and that that the lines are infinite. and that that the lines are infinite.
@ -19,7 +18,7 @@ void lineIntersect(const _Line& a, const _Line& b, _Point& p) {
double bxLen = b[1].x - b[0].x; double bxLen = b[1].x - b[0].x;
double byLen = b[1].y - b[0].y; double byLen = b[1].y - b[0].y;
double denom = byLen * axLen - ayLen * bxLen; double denom = byLen * axLen - ayLen * bxLen;
assert(denom); SkASSERT(denom);
double term1 = a[1].x * a[0].y - a[1].y * a[0].x; double term1 = a[1].x * a[0].y - a[1].y * a[0].x;
double term2 = b[1].x * b[0].y - b[1].y * b[0].x; double term2 = b[1].x * b[0].y - b[1].y * b[0].x;
p.x = (term1 * bxLen - axLen * term2) / denom; p.x = (term1 * bxLen - axLen * term2) / denom;
@ -68,10 +67,10 @@ int intersect(const _Line& a, const _Line& b, double aRange[2], double bRange[2]
double bMin = bPtr[0]; double bMin = bPtr[0];
double bMax = bPtr[2]; double bMax = bPtr[2];
if (aMin > aMax) { if (aMin > aMax) {
std::swap(aMin, aMax); SkTSwap(aMin, aMax);
} }
if (bMin > bMax) { if (bMin > bMax) {
std::swap(bMin, bMax); SkTSwap(bMin, bMax);
} }
if (aMax < bMin || bMax < aMin) { if (aMax < bMin || bMax < aMin) {
return 0; return 0;
@ -87,8 +86,8 @@ int intersect(const _Line& a, const _Line& b, double aRange[2], double bRange[2]
} }
return 1 + ((aRange[0] != aRange[1]) || (bRange[0] != bRange[1])); return 1 + ((aRange[0] != aRange[1]) || (bRange[0] != bRange[1]));
#else #else
assert(aRange); SkASSERT(aRange);
assert(bRange); SkASSERT(bRange);
double a0 = aPtr[0]; double a0 = aPtr[0];
double a1 = aPtr[2]; double a1 = aPtr[2];
double b0 = bPtr[0]; double b0 = bPtr[0];
@ -101,13 +100,18 @@ int intersect(const _Line& a, const _Line& b, double aRange[2], double bRange[2]
if ((at0 < 0 && at1 < 0) || (at0 > 1 && at1 > 1)) { if ((at0 < 0 && at1 < 0) || (at0 > 1 && at1 > 1)) {
return 0; return 0;
} }
aRange[0] = std::max(std::min(at0, 1.0), 0.0); aRange[0] = SkTMax(SkTMin(at0, 1.0), 0.0);
aRange[1] = std::max(std::min(at1, 1.0), 0.0); aRange[1] = SkTMax(SkTMin(at1, 1.0), 0.0);
int bIn = (a0 - a1) * (b0 - b1) < 0; int bIn = (a0 - a1) * (b0 - b1) < 0;
bRange[bIn] = std::max(std::min((b0 - a0) / (b0 - b1), 1.0), 0.0); double bDenom = b0 - b1;
bRange[!bIn] = std::max(std::min((b0 - a1) / (b0 - b1), 1.0), 0.0); if (approximately_zero(bDenom)) {
bRange[0] = bRange[1] = 0;
} else {
bRange[bIn] = SkTMax(SkTMin((b0 - a0) / bDenom, 1.0), 0.0);
bRange[!bIn] = SkTMax(SkTMin((b0 - a1) / bDenom, 1.0), 0.0);
}
bool second = fabs(aRange[0] - aRange[1]) > FLT_EPSILON; bool second = fabs(aRange[0] - aRange[1]) > FLT_EPSILON;
assert((fabs(bRange[0] - bRange[1]) <= FLT_EPSILON) ^ second); SkASSERT((fabs(bRange[0] - bRange[1]) <= FLT_EPSILON) ^ second);
return 1 + second; return 1 + second;
#endif #endif
} }
@ -136,7 +140,7 @@ int horizontalIntersect(const _Line& line, double y, double tRange[2]) {
double min = line[0].y; double min = line[0].y;
double max = line[1].y; double max = line[1].y;
if (min > max) { if (min > max) {
std::swap(min, max); SkTSwap(min, max);
} }
if (min > y || max < y) { if (min > y || max < y) {
return 0; return 0;
@ -192,10 +196,10 @@ int horizontalIntersect(const _Line& line, double left, double right,
double lineL = line[0].x; double lineL = line[0].x;
double lineR = line[1].x; double lineR = line[1].x;
if (lineL > lineR) { if (lineL > lineR) {
std::swap(lineL, lineR); SkTSwap(lineL, lineR);
} }
double overlapL = std::max(left, lineL); double overlapL = SkTMax(left, lineL);
double overlapR = std::min(right, lineR); double overlapR = SkTMin(right, lineR);
if (overlapL > overlapR) { if (overlapL > overlapR) {
return 0; return 0;
} }
@ -219,16 +223,16 @@ int horizontalIntersect(const _Line& line, double left, double right,
if ((at0 < 0 && at1 < 0) || (at0 > 1 && at1 > 1)) { if ((at0 < 0 && at1 < 0) || (at0 > 1 && at1 > 1)) {
return 0; return 0;
} }
intersections.fT[0][0] = std::max(std::min(at0, 1.0), 0.0); intersections.fT[0][0] = SkTMax(SkTMin(at0, 1.0), 0.0);
intersections.fT[0][1] = std::max(std::min(at1, 1.0), 0.0); intersections.fT[0][1] = SkTMax(SkTMin(at1, 1.0), 0.0);
int bIn = (a0 - a1) * (b0 - b1) < 0; int bIn = (a0 - a1) * (b0 - b1) < 0;
intersections.fT[1][bIn] = std::max(std::min((b0 - a0) / (b0 - b1), intersections.fT[1][bIn] = SkTMax(SkTMin((b0 - a0) / (b0 - b1),
1.0), 0.0); 1.0), 0.0);
intersections.fT[1][!bIn] = std::max(std::min((b0 - a1) / (b0 - b1), intersections.fT[1][!bIn] = SkTMax(SkTMin((b0 - a1) / (b0 - b1),
1.0), 0.0); 1.0), 0.0);
bool second = fabs(intersections.fT[0][0] - intersections.fT[0][1]) bool second = fabs(intersections.fT[0][0] - intersections.fT[0][1])
> FLT_EPSILON; > FLT_EPSILON;
assert((fabs(intersections.fT[1][0] - intersections.fT[1][1]) SkASSERT((fabs(intersections.fT[1][0] - intersections.fT[1][1])
<= FLT_EPSILON) ^ second); <= FLT_EPSILON) ^ second);
return 1 + second; return 1 + second;
#endif #endif
@ -247,7 +251,7 @@ static int verticalIntersect(const _Line& line, double x, double tRange[2]) {
double min = line[0].x; double min = line[0].x;
double max = line[1].x; double max = line[1].x;
if (min > max) { if (min > max) {
std::swap(min, max); SkTSwap(min, max);
} }
if (min > x || max < x) { if (min > x || max < x) {
return 0; return 0;
@ -281,10 +285,10 @@ int verticalIntersect(const _Line& line, double top, double bottom,
double lineT = line[0].y; double lineT = line[0].y;
double lineB = line[1].y; double lineB = line[1].y;
if (lineT > lineB) { if (lineT > lineB) {
std::swap(lineT, lineB); SkTSwap(lineT, lineB);
} }
double overlapT = std::max(top, lineT); double overlapT = SkTMax(top, lineT);
double overlapB = std::min(bottom, lineB); double overlapB = SkTMin(bottom, lineB);
if (overlapT > overlapB) { if (overlapT > overlapB) {
return 0; return 0;
} }
@ -308,16 +312,16 @@ int verticalIntersect(const _Line& line, double top, double bottom,
if ((at0 < 0 && at1 < 0) || (at0 > 1 && at1 > 1)) { if ((at0 < 0 && at1 < 0) || (at0 > 1 && at1 > 1)) {
return 0; return 0;
} }
intersections.fT[0][0] = std::max(std::min(at0, 1.0), 0.0); intersections.fT[0][0] = SkTMax(SkTMin(at0, 1.0), 0.0);
intersections.fT[0][1] = std::max(std::min(at1, 1.0), 0.0); intersections.fT[0][1] = SkTMax(SkTMin(at1, 1.0), 0.0);
int bIn = (a0 - a1) * (b0 - b1) < 0; int bIn = (a0 - a1) * (b0 - b1) < 0;
intersections.fT[1][bIn] = std::max(std::min((b0 - a0) / (b0 - b1), intersections.fT[1][bIn] = SkTMax(SkTMin((b0 - a0) / (b0 - b1),
1.0), 0.0); 1.0), 0.0);
intersections.fT[1][!bIn] = std::max(std::min((b0 - a1) / (b0 - b1), intersections.fT[1][!bIn] = SkTMax(SkTMin((b0 - a1) / (b0 - b1),
1.0), 0.0); 1.0), 0.0);
bool second = fabs(intersections.fT[0][0] - intersections.fT[0][1]) bool second = fabs(intersections.fT[0][0] - intersections.fT[0][1])
> FLT_EPSILON; > FLT_EPSILON;
assert((fabs(intersections.fT[1][0] - intersections.fT[1][1]) SkASSERT((fabs(intersections.fT[1][0] - intersections.fT[1][1])
<= FLT_EPSILON) ^ second); <= FLT_EPSILON) ^ second);
return 1 + second; return 1 + second;
#endif #endif

View File

@ -81,7 +81,7 @@ public:
} }
double controlPtDistance(const Cubic& pts, int index) const { double controlPtDistance(const Cubic& pts, int index) const {
assert(index == 1 || index == 2); SkASSERT(index == 1 || index == 2);
return a * pts[index].x + b * pts[index].y + c; return a * pts[index].x + b * pts[index].y + c;
} }

View File

@ -57,7 +57,7 @@ void LineParameter_Test() {
if (AlmostEqualUlps(distSq, normalSquared * answersSq)) { if (AlmostEqualUlps(distSq, normalSquared * answersSq)) {
continue; continue;
} }
printf("%s [%d,%d] denormalizedDistance:%g != answer:%g" SkDebugf("%s [%d,%d] denormalizedDistance:%g != answer:%g"
" distSq:%g answerSq:%g normalSquared:%g\n", " distSq:%g answerSq:%g normalSquared:%g\n",
__FUNCTION__, (int)index, (int)inner, __FUNCTION__, (int)index, (int)inner,
denormalizedDistance[inner], answers[index][inner], denormalizedDistance[inner], answers[index][inner],
@ -71,7 +71,7 @@ void LineParameter_Test() {
if (AlmostEqualUlps(fabs(normalizedDistance[inner]), answers[index][inner])) { if (AlmostEqualUlps(fabs(normalizedDistance[inner]), answers[index][inner])) {
continue; continue;
} }
printf("%s [%d,%d] normalizedDistance:%1.10g != answer:%g\n", SkDebugf("%s [%d,%d] normalizedDistance:%1.10g != answer:%g\n",
__FUNCTION__, (int)index, (int)inner, __FUNCTION__, (int)index, (int)inner,
normalizedDistance[inner], answers[index][inner]); normalizedDistance[inner], answers[index][inner]);
} }

View File

@ -80,7 +80,7 @@ static void testOneOffs() {
double lineT = intersections.fT[1][inner]; double lineT = intersections.fT[1][inner];
double lineX, lineY; double lineX, lineY;
xy_at_t(line, lineT, lineX, lineY); xy_at_t(line, lineT, lineX, lineY);
assert(AlmostEqualUlps(quadX, lineX) SkASSERT(AlmostEqualUlps(quadX, lineX)
&& AlmostEqualUlps(quadY, lineY)); && AlmostEqualUlps(quadY, lineY));
} }
} }

View File

@ -7,7 +7,6 @@
#include "CurveIntersection.h" #include "CurveIntersection.h"
#include "CurveUtilities.h" #include "CurveUtilities.h"
#include "LineParameters.h" #include "LineParameters.h"
#include <algorithm> // used for std::swap
#define DEBUG_BEZIER_CLIP 1 #define DEBUG_BEZIER_CLIP 1
@ -24,7 +23,7 @@ bool bezier_clip(const Quadratic& q1, const Quadratic& q2, double& minT, double&
endLine.quadEndPoints(q1); endLine.quadEndPoints(q1);
if (!endLine.normalize()) { if (!endLine.normalize()) {
printf("line cannot be normalized: need more code here\n"); printf("line cannot be normalized: need more code here\n");
assert(0); SkASSERT(0);
return false; return false;
} }
@ -34,7 +33,7 @@ bool bezier_clip(const Quadratic& q1, const Quadratic& q2, double& minT, double&
double top = 0; double top = 0;
double bottom = distance / 2; // http://students.cs.byu.edu/~tom/557/text/cic.pdf (7.6) double bottom = distance / 2; // http://students.cs.byu.edu/~tom/557/text/cic.pdf (7.6)
if (top > bottom) { if (top > bottom) {
std::swap(top, bottom); SkTSwap(top, bottom);
} }
// compute intersecting candidate distance // compute intersecting candidate distance

View File

@ -50,10 +50,10 @@ static void standardTestCases() {
int order1 = reduceOrder(quad1, reduce1); int order1 = reduceOrder(quad1, reduce1);
int order2 = reduceOrder(quad2, reduce2); int order2 = reduceOrder(quad2, reduce2);
if (order1 < 3) { if (order1 < 3) {
printf("%s [%d] quad1 order=%d\n", __FUNCTION__, (int)index, order1); SkDebugf("%s [%d] quad1 order=%d\n", __FUNCTION__, (int)index, order1);
} }
if (order2 < 3) { if (order2 < 3) {
printf("%s [%d] quad2 order=%d\n", __FUNCTION__, (int)index, order2); SkDebugf("%s [%d] quad2 order=%d\n", __FUNCTION__, (int)index, order2);
} }
if (order1 == 3 && order2 == 3) { if (order1 == 3 && order2 == 3) {
double minT = 0; double minT = 0;

View File

@ -110,7 +110,7 @@ static bool onlyEndPtsInCommon(const Quadratic& q1, const Quadratic& q2, Interse
} }
} }
} }
assert(i.fUsed < 3); SkASSERT(i.fUsed < 3);
return true; return true;
tryNextHalfPlane: tryNextHalfPlane:
; ;
@ -340,7 +340,7 @@ static void unsortableExpanse(const Quadratic& q1, const Quadratic& q2, Intersec
perp[1].y += dxdy.x; perp[1].y += dxdy.x;
Intersections hitData; Intersections hitData;
int hits = intersectRay(*qs[qIdx ^ 1], perp, hitData); int hits = intersectRay(*qs[qIdx ^ 1], perp, hitData);
assert(hits <= 1); SkASSERT(hits <= 1);
if (hits) { if (hits) {
if (flip < 0) { if (flip < 0) {
_Point dxdy2; _Point dxdy2;
@ -397,7 +397,7 @@ bool intersect2(const Quadratic& q1, const Quadratic& q2, Intersections& i) {
if ((t = axialIntersect(q2, q1[2], useVertical)) >= 0) { if ((t = axialIntersect(q2, q1[2], useVertical)) >= 0) {
i.addCoincident(1, t); i.addCoincident(1, t);
} }
assert(i.fCoincidentUsed <= 2); SkASSERT(i.fCoincidentUsed <= 2);
return i.fCoincidentUsed > 0; return i.fCoincidentUsed > 0;
} }
double roots1[4], roots2[4]; double roots1[4], roots2[4];

View File

@ -76,7 +76,7 @@ bool intersect(double minT1, double maxT1, double minT2, double maxT2) {
smallT = minT1; smallT = minT1;
} else { } else {
xy_at_t(quad1, maxT1, q1pt.x, q1pt.y); // FIXME: debug code xy_at_t(quad1, maxT1, q1pt.x, q1pt.y); // FIXME: debug code
assert(AlmostEqualUlps(q2pt.x, q1pt.x) && AlmostEqualUlps(q2pt.y, q1pt.y)); SkASSERT(AlmostEqualUlps(q2pt.x, q1pt.x) && AlmostEqualUlps(q2pt.y, q1pt.y));
smallT = maxT1; smallT = maxT1;
} }
} else { } else {
@ -87,7 +87,7 @@ bool intersect(double minT1, double maxT1, double minT2, double maxT2) {
largeT = minT2; largeT = minT2;
} else { } else {
xy_at_t(quad2, maxT2, q2pt.x, q2pt.y); // FIXME: debug code xy_at_t(quad2, maxT2, q2pt.x, q2pt.y); // FIXME: debug code
assert(AlmostEqualUlps(q2pt.x, q1pt.x) && AlmostEqualUlps(q2pt.y, q1pt.y)); SkASSERT(AlmostEqualUlps(q2pt.x, q1pt.x) && AlmostEqualUlps(q2pt.y, q1pt.y));
largeT = maxT2; largeT = maxT2;
} }
} }
@ -127,9 +127,9 @@ bool intersectAsLine(double minT1, double maxT1, double minT2, double maxT2,
{ {
_Line line1, line2; _Line line1, line2;
if (intersections.swapped()) { if (intersections.swapped()) {
std::swap(treat1AsLine, treat2AsLine); SkTSwap(treat1AsLine, treat2AsLine);
std::swap(minT1, minT2); SkTSwap(minT1, minT2);
std::swap(maxT1, maxT2); SkTSwap(maxT1, maxT2);
} }
if (coinMinT1 >= 0) { if (coinMinT1 >= 0) {
bool earlyExit; bool earlyExit;
@ -388,7 +388,7 @@ bool intersect(const Quadratic& q1, const Quadratic& q2, Intersections& i) {
if ((t = axialIntersect(q2, q1[2], useVertical)) >= 0) { if ((t = axialIntersect(q2, q1[2], useVertical)) >= 0) {
i.addCoincident(1, t); i.addCoincident(1, t);
} }
assert(i.fCoincidentUsed <= 2); SkASSERT(i.fCoincidentUsed <= 2);
return i.fCoincidentUsed > 0; return i.fCoincidentUsed > 0;
} }
QuadraticIntersections q(q1, q2, i); QuadraticIntersections q(q1, q2, i);

View File

@ -10,7 +10,6 @@
#include "Intersections.h" #include "Intersections.h"
#include "QuadraticIntersection_TestData.h" #include "QuadraticIntersection_TestData.h"
#include "TestUtilities.h" #include "TestUtilities.h"
#include "SkTypes.h"
const int firstQuadIntersectionTest = 9; const int firstQuadIntersectionTest = 9;

View File

@ -34,12 +34,12 @@ void QuadraticCoincidence_Test() {
for (size_t two = 0; two < quadsCount; ++two) { for (size_t two = 0; two < quadsCount; ++two) {
for (size_t inner = 0; inner < 3; inner += 2) { for (size_t inner = 0; inner < 3; inner += 2) {
if (!point_on_parameterized_curve(*quads[one], (*quads[two])[inner])) { if (!point_on_parameterized_curve(*quads[one], (*quads[two])[inner])) {
printf("%s %zu [%zu,%zu] %zu parameterization failed\n", SkDebugf("%s %zu [%zu,%zu] %zu parameterization failed\n",
__FUNCTION__, index, one, two, inner); __FUNCTION__, index, one, two, inner);
} }
} }
if (!implicit_matches(*quads[one], *quads[two])) { if (!implicit_matches(*quads[one], *quads[two])) {
printf("%s %zu [%zu,%zu] coincidence failed\n", __FUNCTION__, SkDebugf("%s %zu [%zu,%zu] coincidence failed\n", __FUNCTION__,
index, one, two); index, one, two);
} }
} }

View File

@ -63,7 +63,7 @@ static int check_linear(const Quadratic& quad, Quadratic& reduction,
--endIndex; --endIndex;
if (endIndex == 0) { if (endIndex == 0) {
printf("%s shouldn't get here if all four points are about equal", __FUNCTION__); printf("%s shouldn't get here if all four points are about equal", __FUNCTION__);
assert(0); SkASSERT(0);
} }
} }
if (!isLinear(quad, startIndex, endIndex)) { if (!isLinear(quad, startIndex, endIndex)) {

View File

@ -8,7 +8,6 @@
#include "Intersection_Tests.h" #include "Intersection_Tests.h"
#include "QuadraticIntersection_TestData.h" #include "QuadraticIntersection_TestData.h"
#include "TestUtilities.h" #include "TestUtilities.h"
#include "SkTypes.h"
static const Quadratic testSet[] = { static const Quadratic testSet[] = {
{{1, 1}, {2, 2}, {1, 1.000003}}, {{1, 1}, {2, 2}, {1, 1.000003}},
@ -43,8 +42,8 @@ static void standardTestCases() {
run = RunQuadraticLines; run = RunQuadraticLines;
firstTestIndex = 1; firstTestIndex = 1;
#endif #endif
int firstQuadraticLineTest = run == RunAll ? 0 : run == RunQuadraticLines ? firstTestIndex : INT_MAX; int firstQuadraticLineTest = run == RunAll ? 0 : run == RunQuadraticLines ? firstTestIndex : SK_MaxS32;
int firstQuadraticModLineTest = run == RunAll ? 0 : run == RunQuadraticModLines ? firstTestIndex : INT_MAX; int firstQuadraticModLineTest = run == RunAll ? 0 : run == RunQuadraticModLines ? firstTestIndex : SK_MaxS32;
for (index = firstQuadraticLineTest; index < quadraticLines_count; ++index) { for (index = firstQuadraticLineTest; index < quadraticLines_count; ++index) {
const Quadratic& quad = quadraticLines[index]; const Quadratic& quad = quadraticLines[index];

View File

@ -5,7 +5,6 @@
* found in the LICENSE file. * found in the LICENSE file.
*/ */
#include "QuadraticUtilities.h" #include "QuadraticUtilities.h"
#include "SkTypes.h"
#include <math.h> #include <math.h>
/* /*

View File

@ -58,7 +58,7 @@ int reducedQuarticRoots(const double t4, const double t3, const double t2, const
return num; return num;
} }
if (oneHint) { if (oneHint) {
assert(approximately_zero(t4 + t3 + t2 + t1 + t0)); // 1 is one root SkASSERT(approximately_zero(t4 + t3 + t2 + t1 + t0)); // 1 is one root
int num = cubicRootsReal(t4, t4 + t3, -(t1 + t0), -t0, roots); // note that -C==A+B+D+E int num = cubicRootsReal(t4, t4 + t3, -(t1 + t0), -t0, roots); // note that -C==A+B+D+E
for (int i = 0; i < num; ++i) { for (int i = 0; i < num; ++i) {
if (approximately_equal(roots[i], 1)) { if (approximately_equal(roots[i], 1)) {

View File

@ -1,5 +1,3 @@
#include <assert.h>
#include <math.h>
#include "CubicUtilities.h" #include "CubicUtilities.h"
#include "Intersection_Tests.h" #include "Intersection_Tests.h"
#include "QuadraticUtilities.h" #include "QuadraticUtilities.h"
@ -41,15 +39,15 @@ static void quadraticTest(bool limit) {
} else { } else {
expected = 1 + (B != C); expected = 1 + (B != C);
} }
assert(rootCount == expected); SkASSERT(rootCount == expected);
if (!rootCount) { if (!rootCount) {
continue; continue;
} }
assert(approximately_equal(roots[0], -B) SkASSERT(approximately_equal(roots[0], -B)
|| approximately_equal(roots[0], -C)); || approximately_equal(roots[0], -C));
if (expected > 1) { if (expected > 1) {
assert(!approximately_equal(roots[0], roots[1])); SkASSERT(!approximately_equal(roots[0], roots[1]));
assert(approximately_equal(roots[1], -B) SkASSERT(approximately_equal(roots[1], -B)
|| approximately_equal(roots[1], -C)); || approximately_equal(roots[1], -C));
} }
} }
@ -81,26 +79,26 @@ static void testOneCubic(bool limit, size_t aIndex, size_t bIndex, size_t cIndex
} else { } else {
expected = 1 + (B != C) + (B != D && C != D); expected = 1 + (B != C) + (B != D && C != D);
} }
assert(rootCount == expected); SkASSERT(rootCount == expected);
if (!rootCount) { if (!rootCount) {
return; return;
} }
assert(approximately_equal(roots[0], -B) SkASSERT(approximately_equal(roots[0], -B)
|| approximately_equal(roots[0], -C) || approximately_equal(roots[0], -C)
|| approximately_equal(roots[0], -D)); || approximately_equal(roots[0], -D));
if (expected <= 1) { if (expected <= 1) {
return; return;
} }
assert(!approximately_equal(roots[0], roots[1])); SkASSERT(!approximately_equal(roots[0], roots[1]));
assert(approximately_equal(roots[1], -B) SkASSERT(approximately_equal(roots[1], -B)
|| approximately_equal(roots[1], -C) || approximately_equal(roots[1], -C)
|| approximately_equal(roots[1], -D)); || approximately_equal(roots[1], -D));
if (expected <= 2) { if (expected <= 2) {
return; return;
} }
assert(!approximately_equal(roots[0], roots[2]) SkASSERT(!approximately_equal(roots[0], roots[2])
&& !approximately_equal(roots[1], roots[2])); && !approximately_equal(roots[1], roots[2]));
assert(approximately_equal(roots[2], -B) SkASSERT(approximately_equal(roots[2], -B)
|| approximately_equal(roots[2], -C) || approximately_equal(roots[2], -C)
|| approximately_equal(roots[2], -D)); || approximately_equal(roots[2], -D));
} }
@ -136,35 +134,35 @@ static void testOneQuartic(size_t aIndex, size_t bIndex, size_t cIndex, size_t d
rootCount = quarticRootsReal(A, b, c, d, e, roots); rootCount = quarticRootsReal(A, b, c, d, e, roots);
} }
const int expected = 1 + (B != C) + (B != D && C != D) + (B != E && C != E && D != E); const int expected = 1 + (B != C) + (B != D && C != D) + (B != E && C != E && D != E);
assert(rootCount == expected); SkASSERT(rootCount == expected);
assert(AlmostEqualUlps(roots[0], -B) SkASSERT(AlmostEqualUlps(roots[0], -B)
|| AlmostEqualUlps(roots[0], -C) || AlmostEqualUlps(roots[0], -C)
|| AlmostEqualUlps(roots[0], -D) || AlmostEqualUlps(roots[0], -D)
|| AlmostEqualUlps(roots[0], -E)); || AlmostEqualUlps(roots[0], -E));
if (expected <= 1) { if (expected <= 1) {
return; return;
} }
assert(!AlmostEqualUlps(roots[0], roots[1])); SkASSERT(!AlmostEqualUlps(roots[0], roots[1]));
assert(AlmostEqualUlps(roots[1], -B) SkASSERT(AlmostEqualUlps(roots[1], -B)
|| AlmostEqualUlps(roots[1], -C) || AlmostEqualUlps(roots[1], -C)
|| AlmostEqualUlps(roots[1], -D) || AlmostEqualUlps(roots[1], -D)
|| AlmostEqualUlps(roots[1], -E)); || AlmostEqualUlps(roots[1], -E));
if (expected <= 2) { if (expected <= 2) {
return; return;
} }
assert(!AlmostEqualUlps(roots[0], roots[2]) SkASSERT(!AlmostEqualUlps(roots[0], roots[2])
&& !AlmostEqualUlps(roots[1], roots[2])); && !AlmostEqualUlps(roots[1], roots[2]));
assert(AlmostEqualUlps(roots[2], -B) SkASSERT(AlmostEqualUlps(roots[2], -B)
|| AlmostEqualUlps(roots[2], -C) || AlmostEqualUlps(roots[2], -C)
|| AlmostEqualUlps(roots[2], -D) || AlmostEqualUlps(roots[2], -D)
|| AlmostEqualUlps(roots[2], -E)); || AlmostEqualUlps(roots[2], -E));
if (expected <= 3) { if (expected <= 3) {
return; return;
} }
assert(!AlmostEqualUlps(roots[0], roots[3]) SkASSERT(!AlmostEqualUlps(roots[0], roots[3])
&& !AlmostEqualUlps(roots[1], roots[3]) && !AlmostEqualUlps(roots[1], roots[3])
&& !AlmostEqualUlps(roots[2], roots[3])); && !AlmostEqualUlps(roots[2], roots[3]));
assert(AlmostEqualUlps(roots[3], -B) SkASSERT(AlmostEqualUlps(roots[3], -B)
|| AlmostEqualUlps(roots[3], -C) || AlmostEqualUlps(roots[3], -C)
|| AlmostEqualUlps(roots[3], -D) || AlmostEqualUlps(roots[3], -D)
|| AlmostEqualUlps(roots[3], -E)); || AlmostEqualUlps(roots[3], -E));

View File

@ -0,0 +1,94 @@
/*
* Copyright 2012 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#include "EdgeWalker_Test.h"
#include "Intersection_Tests.h"
#include "ShapeOps.h"
// four rects, of four sizes
// for 3 smaller sizes, tall, wide
// top upper mid lower bottom aligned (3 bits, 5 values)
// same with x (3 bits, 5 values)
// not included, square, tall, wide (2 bits)
// cw or ccw (1 bit)
static void* testShapeOps4x4CubicsMain(void* data)
{
SkASSERT(data);
State4& state = *(State4*) data;
char pathStr[1024]; // gdb: set print elements 400
bzero(pathStr, sizeof(pathStr));
do {
for (int a = 0 ; a < 6; ++a) {
for (int b = a + 1 ; b < 7; ++b) {
for (int c = 0 ; c < 6; ++c) {
for (int d = c + 1 ; d < 7; ++d) {
for (int e = SkPath::kWinding_FillType ; e <= SkPath::kEvenOdd_FillType; ++e) {
for (int f = SkPath::kWinding_FillType ; f <= SkPath::kEvenOdd_FillType; ++f) {
SkPath pathA, pathB;
char* str = pathStr;
pathA.setFillType((SkPath::FillType) e);
str += sprintf(str, " path.setFillType(SkPath::k%s_FillType);\n",
e == SkPath::kWinding_FillType ? "Winding" : e == SkPath::kEvenOdd_FillType
? "EvenOdd" : "?UNDEFINED");
pathA.moveTo(state.a, state.b);
str += sprintf(str, " path.moveTo(%d,%d);\n", state.a, state.b);
pathA.cubicTo(state.c, state.d, b, a, d, c);
str += sprintf(str, " path.cubicTo(%d,%d, %d,%d, %d,%d);\n", state.c, state.d,
b, a, d, c);
pathA.close();
str += sprintf(str, " path.close();\n");
pathB.setFillType((SkPath::FillType) f);
str += sprintf(str, " pathB.setFillType(SkPath::k%s_FillType);\n",
f == SkPath::kWinding_FillType ? "Winding" : f == SkPath::kEvenOdd_FillType
? "EvenOdd" : "?UNDEFINED");
pathB.moveTo(a, b);
str += sprintf(str, " pathB.moveTo(%d,%d);\n", a, b);
pathB.cubicTo(c, d, state.b, state.a, state.d, state.c);
str += sprintf(str, " pathB.cubicTo(%d,%d, %d,%d, %d,%d);\n", c, d,
state.b, state.a, state.d, state.c);
pathB.close();
str += sprintf(str, " pathB.close();\n");
for (int op = 0 ; op < kShapeOp_Count; ++op) {
outputProgress(state, pathStr, (ShapeOp) op);
testShapeOp(pathA, pathB, (ShapeOp) op);
state.testsRun++;
}
}
}
}
}
}
}
} while (runNextTestSet(state));
return NULL;
}
void ShapeOps4x4CubicsThreaded_Test(int& testsRun)
{
SkDebugf("%s\n", __FUNCTION__);
#ifdef SK_DEBUG
gDebugMaxWindSum = 4;
gDebugMaxWindValue = 4;
#endif
const char testLineStr[] = "cubicOp";
initializeTests(testLineStr, sizeof(testLineStr));
int testsStart = testsRun;
for (int a = 0; a < 6; ++a) { // outermost
for (int b = a + 1; b < 7; ++b) {
for (int c = 0 ; c < 6; ++c) {
for (int d = c + 1; d < 7; ++d) {
testsRun += dispatchTest4(testShapeOps4x4CubicsMain, a, b, c, d);
}
if (!gRunTestsInOneThread) SkDebugf(".");
}
if (!gRunTestsInOneThread) SkDebugf("%d", b);
}
if (!gRunTestsInOneThread) SkDebugf("\n%d", a);
}
testsRun += waitForCompletion();
SkDebugf("%s tests=%d total=%d\n", __FUNCTION__, testsRun - testsStart, testsRun);
}

View File

@ -26,7 +26,6 @@ static void* testShapeOps4x4RectsMain(void* data)
for (int b = a + 1 ; b < 7; ++b) { for (int b = a + 1 ; b < 7; ++b) {
for (int c = 0 ; c < 6; ++c) { for (int c = 0 ; c < 6; ++c) {
for (int d = c + 1 ; d < 7; ++d) { for (int d = c + 1 ; d < 7; ++d) {
for (int op = 0 ; op < kShapeOp_Count; ++op) {
for (int e = SkPath::kWinding_FillType ; e <= SkPath::kEvenOdd_FillType; ++e) { for (int e = SkPath::kWinding_FillType ; e <= SkPath::kEvenOdd_FillType; ++e) {
for (int f = SkPath::kWinding_FillType ; f <= SkPath::kEvenOdd_FillType; ++f) { for (int f = SkPath::kWinding_FillType ; f <= SkPath::kEvenOdd_FillType; ++f) {
SkPath pathA, pathB; SkPath pathA, pathB;
@ -53,17 +52,9 @@ static void* testShapeOps4x4RectsMain(void* data)
str += sprintf(str, " pathB.addRect(%d, %d, %d, %d," str += sprintf(str, " pathB.addRect(%d, %d, %d, %d,"
" SkPath::kCW_Direction);\n", c, c, d, d); " SkPath::kCW_Direction);\n", c, c, d, d);
pathB.close(); pathB.close();
outputProgress(state, pathStr, kDifference_Op); for (int op = 0 ; op < kShapeOp_Count; ++op) {
testShapeOp(pathA, pathB, kDifference_Op); outputProgress(state, pathStr, (ShapeOp) op);
state.testsRun++; testShapeOp(pathA, pathB, (ShapeOp) op);
outputProgress(state, pathStr, kIntersect_Op);
testShapeOp(pathA, pathB, kIntersect_Op);
state.testsRun++;
outputProgress(state, pathStr, kUnion_Op);
testShapeOp(pathA, pathB, kUnion_Op);
state.testsRun++;
outputProgress(state, pathStr, kXor_Op);
testShapeOp(pathA, pathB, kXor_Op);
state.testsRun++; state.testsRun++;
} }
} }

View File

@ -392,34 +392,19 @@ static void (* const SegmentSubDivide[])(const SkPoint [], double , double ,
CubicSubDivide CubicSubDivide
}; };
static void LineSubDivideHD(const SkPoint a[2], double startT, double endT, static void LineSubDivideHD(const SkPoint a[2], double startT, double endT, _Line& dst) {
_Line sub) {
MAKE_CONST_LINE(aLine, a); MAKE_CONST_LINE(aLine, a);
_Line dst;
sub_divide(aLine, startT, endT, dst); sub_divide(aLine, startT, endT, dst);
sub[0] = dst[0];
sub[1] = dst[1];
} }
static void QuadSubDivideHD(const SkPoint a[3], double startT, double endT, static void QuadSubDivideHD(const SkPoint a[3], double startT, double endT, Quadratic& dst) {
Quadratic sub) {
MAKE_CONST_QUAD(aQuad, a); MAKE_CONST_QUAD(aQuad, a);
Quadratic dst;
sub_divide(aQuad, startT, endT, dst); sub_divide(aQuad, startT, endT, dst);
sub[0] = dst[0];
sub[1] = dst[1];
sub[2] = dst[2];
} }
static void CubicSubDivideHD(const SkPoint a[4], double startT, double endT, static void CubicSubDivideHD(const SkPoint a[4], double startT, double endT, Cubic& dst) {
Cubic sub) {
MAKE_CONST_CUBIC(aCubic, a); MAKE_CONST_CUBIC(aCubic, a);
Cubic dst;
sub_divide(aCubic, startT, endT, dst); sub_divide(aCubic, startT, endT, dst);
sub[0] = dst[0];
sub[1] = dst[1];
sub[2] = dst[2];
sub[3] = dst[3];
} }
#if DEBUG_UNUSED #if DEBUG_UNUSED
@ -780,12 +765,27 @@ public:
case SkPath::kQuad_Verb: case SkPath::kQuad_Verb:
QuadSubDivideHD(fPts, startT, endT, fQ); QuadSubDivideHD(fPts, startT, endT, fQ);
fTangent1.quadEndPoints(fQ, 0, 1); fTangent1.quadEndPoints(fQ, 0, 1);
#if 1 // FIXME: try enabling this and see if a) it's called and b) does it break anything
if (dx() == 0 && dy() == 0) {
SkDebugf("*** %s quad is line\n");
fTangent1.quadEndPoints(fQ);
}
#endif
fSide = -fTangent1.pointDistance(fQ[2]); // not normalized -- compare sign only fSide = -fTangent1.pointDistance(fQ[2]); // not normalized -- compare sign only
break; break;
case SkPath::kCubic_Verb: case SkPath::kCubic_Verb:
Cubic c; Cubic c;
CubicSubDivideHD(fPts, startT, endT, c); CubicSubDivideHD(fPts, startT, endT, c);
fTangent1.cubicEndPoints(c, 0, 1); fTangent1.cubicEndPoints(c, 0, 1);
if (dx() == 0 && dy() == 0) {
fTangent1.cubicEndPoints(c, 0, 2);
#if 1 // FIXME: try enabling this and see if a) it's called and b) does it break anything
if (dx() == 0 && dy() == 0) {
SkDebugf("*** %s cubic is line\n");
fTangent1.cubicEndPoints(c, 0, 3);
}
#endif
}
fSide = -fTangent1.pointDistance(c[2]); // not normalized -- compare sign only fSide = -fTangent1.pointDistance(c[2]); // not normalized -- compare sign only
break; break;
default: default:
@ -1792,7 +1792,7 @@ public:
} }
// FIXME: this doesn't prevent the same span from being added twice // FIXME: this doesn't prevent the same span from being added twice
// fix in caller, assert here? // fix in caller, SkASSERT here?
void addTPair(double t, Segment& other, double otherT, bool borrowWind) { void addTPair(double t, Segment& other, double otherT, bool borrowWind) {
int tCount = fTs.count(); int tCount = fTs.count();
for (int tIndex = 0; tIndex < tCount; ++tIndex) { for (int tIndex = 0; tIndex < tCount; ++tIndex) {
@ -3346,7 +3346,9 @@ the same winding is shared by both.
const Span& endSpan = fTs[end]; const Span& endSpan = fTs[end];
Segment* other = endSpan.fOther; Segment* other = endSpan.fOther;
index = endSpan.fOtherIndex; index = endSpan.fOtherIndex;
SkASSERT(index >= 0);
int otherEnd = other->nextExactSpan(index, step); int otherEnd = other->nextExactSpan(index, step);
SkASSERT(otherEnd >= 0);
min = SkMin32(index, otherEnd); min = SkMin32(index, otherEnd);
return other; return other;
} }
@ -3765,7 +3767,7 @@ the same winding is shared by both.
#endif #endif
#if DEBUG_CONCIDENT #if DEBUG_CONCIDENT
// assert if pair has not already been added // SkASSERT if pair has not already been added
void debugAddTPair(double t, const Segment& other, double otherT) const { void debugAddTPair(double t, const Segment& other, double otherT) const {
for (int i = 0; i < fTs.count(); ++i) { for (int i = 0; i < fTs.count(); ++i) {
if (fTs[i].fT == t && fTs[i].fOther == &other && fTs[i].fOtherT == otherT) { if (fTs[i].fT == t && fTs[i].fOther == &other && fTs[i].fOtherT == otherT) {
@ -6051,7 +6053,7 @@ static void assemble(const PathWrapper& path, PathWrapper& simple) {
eLink.setCount(count); eLink.setCount(count);
int rIndex, iIndex; int rIndex, iIndex;
for (rIndex = 0; rIndex < count; ++rIndex) { for (rIndex = 0; rIndex < count; ++rIndex) {
sLink[rIndex] = eLink[rIndex] = INT_MAX; sLink[rIndex] = eLink[rIndex] = SK_MaxS32;
} }
SkTDArray<double> distances; SkTDArray<double> distances;
const int ends = count * 2; // all starts and ends const int ends = count * 2; // all starts and ends
@ -6088,14 +6090,14 @@ static void assemble(const PathWrapper& path, PathWrapper& simple) {
int ndxOne = thingOne >> 1; int ndxOne = thingOne >> 1;
bool endOne = thingOne & 1; bool endOne = thingOne & 1;
int* linkOne = endOne ? eLink.begin() : sLink.begin(); int* linkOne = endOne ? eLink.begin() : sLink.begin();
if (linkOne[ndxOne] != INT_MAX) { if (linkOne[ndxOne] != SK_MaxS32) {
continue; continue;
} }
int thingTwo = row < col ? col : ends - row + col - 1; int thingTwo = row < col ? col : ends - row + col - 1;
int ndxTwo = thingTwo >> 1; int ndxTwo = thingTwo >> 1;
bool endTwo = thingTwo & 1; bool endTwo = thingTwo & 1;
int* linkTwo = endTwo ? eLink.begin() : sLink.begin(); int* linkTwo = endTwo ? eLink.begin() : sLink.begin();
if (linkTwo[ndxTwo] != INT_MAX) { if (linkTwo[ndxTwo] != SK_MaxS32) {
continue; continue;
} }
SkASSERT(&linkOne[ndxOne] != &linkTwo[ndxTwo]); SkASSERT(&linkOne[ndxOne] != &linkTwo[ndxTwo]);
@ -6120,17 +6122,17 @@ static void assemble(const PathWrapper& path, PathWrapper& simple) {
bool forward = true; bool forward = true;
bool first = true; bool first = true;
int sIndex = sLink[rIndex]; int sIndex = sLink[rIndex];
SkASSERT(sIndex != INT_MAX); SkASSERT(sIndex != SK_MaxS32);
sLink[rIndex] = INT_MAX; sLink[rIndex] = SK_MaxS32;
int eIndex; int eIndex;
if (sIndex < 0) { if (sIndex < 0) {
eIndex = sLink[~sIndex]; eIndex = sLink[~sIndex];
sLink[~sIndex] = INT_MAX; sLink[~sIndex] = SK_MaxS32;
} else { } else {
eIndex = eLink[sIndex]; eIndex = eLink[sIndex];
eLink[sIndex] = INT_MAX; eLink[sIndex] = SK_MaxS32;
} }
SkASSERT(eIndex != INT_MAX); SkASSERT(eIndex != SK_MaxS32);
#if DEBUG_ASSEMBLE #if DEBUG_ASSEMBLE
SkDebugf("%s sIndex=%c%d eIndex=%c%d\n", __FUNCTION__, sIndex < 0 ? 's' : 'e', SkDebugf("%s sIndex=%c%d eIndex=%c%d\n", __FUNCTION__, sIndex < 0 ? 's' : 'e',
sIndex < 0 ? ~sIndex : sIndex, eIndex < 0 ? 's' : 'e', sIndex < 0 ? ~sIndex : sIndex, eIndex < 0 ? 's' : 'e',
@ -6160,25 +6162,25 @@ static void assemble(const PathWrapper& path, PathWrapper& simple) {
} }
if (forward) { if (forward) {
eIndex = eLink[rIndex]; eIndex = eLink[rIndex];
SkASSERT(eIndex != INT_MAX); SkASSERT(eIndex != SK_MaxS32);
eLink[rIndex] = INT_MAX; eLink[rIndex] = SK_MaxS32;
if (eIndex >= 0) { if (eIndex >= 0) {
SkASSERT(sLink[eIndex] == rIndex); SkASSERT(sLink[eIndex] == rIndex);
sLink[eIndex] = INT_MAX; sLink[eIndex] = SK_MaxS32;
} else { } else {
SkASSERT(eLink[~eIndex] == ~rIndex); SkASSERT(eLink[~eIndex] == ~rIndex);
eLink[~eIndex] = INT_MAX; eLink[~eIndex] = SK_MaxS32;
} }
} else { } else {
eIndex = sLink[rIndex]; eIndex = sLink[rIndex];
SkASSERT(eIndex != INT_MAX); SkASSERT(eIndex != SK_MaxS32);
sLink[rIndex] = INT_MAX; sLink[rIndex] = SK_MaxS32;
if (eIndex >= 0) { if (eIndex >= 0) {
SkASSERT(eLink[eIndex] == rIndex); SkASSERT(eLink[eIndex] == rIndex);
eLink[eIndex] = INT_MAX; eLink[eIndex] = SK_MaxS32;
} else { } else {
SkASSERT(sLink[~eIndex] == ~rIndex); SkASSERT(sLink[~eIndex] == ~rIndex);
sLink[~eIndex] = INT_MAX; sLink[~eIndex] = SK_MaxS32;
} }
} }
rIndex = eIndex; rIndex = eIndex;
@ -6188,15 +6190,15 @@ static void assemble(const PathWrapper& path, PathWrapper& simple) {
} }
} while (true); } while (true);
for (rIndex = 0; rIndex < count; ++rIndex) { for (rIndex = 0; rIndex < count; ++rIndex) {
if (sLink[rIndex] != INT_MAX) { if (sLink[rIndex] != SK_MaxS32) {
break; break;
} }
} }
} while (rIndex < count); } while (rIndex < count);
#if DEBUG_ASSEMBLE #if DEBUG_ASSEMBLE
for (rIndex = 0; rIndex < count; ++rIndex) { for (rIndex = 0; rIndex < count; ++rIndex) {
SkASSERT(sLink[rIndex] == INT_MAX); SkASSERT(sLink[rIndex] == SK_MaxS32);
SkASSERT(eLink[rIndex] == INT_MAX); SkASSERT(eLink[rIndex] == SK_MaxS32);
} }
#endif #endif
} }

View File

@ -15,4 +15,3 @@
#include "SkTDArray.h" #include "SkTDArray.h"
#include "ShapeOps.h" #include "ShapeOps.h"
#include "TSearch.h" #include "TSearch.h"
#include <algorithm> // used for std::min

View File

@ -3536,6 +3536,7 @@ static void testCubic1() {
testSimplifyx(path); testSimplifyx(path);
} }
#if 0
static void testQuadratic93() { static void testQuadratic93() {
SkPath path; SkPath path;
path.moveTo(3, 0); path.moveTo(3, 0);
@ -3548,6 +3549,20 @@ static void testQuadratic93() {
path.close(); path.close();
testSimplifyx(path); testSimplifyx(path);
} }
#endif
static void cubicOp1d() {
SkPath path, pathB;
path.setFillType(SkPath::kWinding_FillType);
path.moveTo(0,1);
path.cubicTo(0,2, 1,0, 1,0);
path.close();
pathB.setFillType(SkPath::kWinding_FillType);
pathB.moveTo(0,1);
pathB.cubicTo(0,1, 1,0, 2,0);
pathB.close();
testShapeOp(path, pathB, kDifference_Op);
}
static void (*firstTest)() = 0; static void (*firstTest)() = 0;
@ -3555,7 +3570,8 @@ static struct {
void (*fun)(); void (*fun)();
const char* str; const char* str;
} tests[] = { } tests[] = {
TEST(testQuadratic93), TEST(cubicOp1d),
// TEST(testQuadratic93), // FIXME: gets stuck in a loop because top is unsortable
TEST(testCubic1), TEST(testCubic1),
TEST(testQuadralateral1), TEST(testQuadralateral1),
TEST(testLine85), TEST(testLine85),

View File

@ -7,8 +7,6 @@
#ifndef TSearch_DEFINED #ifndef TSearch_DEFINED
#define TSearch_DEFINED #define TSearch_DEFINED
#include "SkTypes.h"
// FIXME: Move this templated version into SKTSearch.h // FIXME: Move this templated version into SKTSearch.h
template <typename T> template <typename T>

View File

@ -3328,11 +3328,23 @@ path.addRect(4, 13, 13, 16, SkPath::kCCW_Direction);
path.close(); path.close();
</div> </div>
<div id="cubicOp1d">
path.setFillType(SkPath::kWinding_FillType);
path.moveTo(0,1);
path.cubicTo(0,2, 1,0, 1,0);
path.close();
pathB.setFillType(SkPath::kWinding_FillType);
pathB.moveTo(0,1);
pathB.cubicTo(0,1, 1,0, 2,0);
pathB.close();
</div>
</div> </div>
<script type="text/javascript"> <script type="text/javascript">
var testDivs = [ var testDivs = [
cubicOp1d,
testQuadratic93, testQuadratic93,
testCubic1, testCubic1,
testQuadralateral1, testQuadralateral1,

View File

@ -1703,11 +1703,26 @@ $7 = {{x = 24.006224853920855, y = 72.621119847810419}, {x = 29.758671200376888,
{{x = 0.30387252963474076, y = 0.69616688005807803}, {x = 0.3039751936710845, y = 0.69622610811401087}} {{x = 0.30387252963474076, y = 0.69616688005807803}, {x = 0.3039751936710845, y = 0.69622610811401087}}
</div> </div>
<div id="cubicOp1d">
{{0, 1}, {0, 2}, {1, 0}, {1, 0}},
{{0, 1}, {0, 1}, {1, 0}, {2, 0}},
{{0,1}, {0.0078125,1.35546875}, {0.15625,1.265625}},
{{0.15625,1.265625}, {0.3046875,1.17578125}, {0.5,0.875}},
{{0.5,0.875}, {0.6953125,0.57421875}, {0.84375,0.296875}},
{{0.84375,0.296875}, {0.9921875,0.01953125}, {1,0}},
{{0,1}, {0.00925925926,0.981481481}, {0.296296296,0.740740741}},
{{0.296296296,0.740740741}, {0.583333333,0.5}, {1.03703704,0.259259259}},
{{1.03703704,0.259259259}, {1.49074074,0.0185185185}, {2,0}},
</div>
</div> </div>
<script type="text/javascript"> <script type="text/javascript">
var testDivs = [ var testDivs = [
cubicOp1d,
testCubic1b, testCubic1b,
testCubic1a, testCubic1a,
testCubic1, testCubic1,

View File

@ -1,8 +1,53 @@
#import "SkCanvas.h" #include "SkCanvas.h"
#import "SkPaint.h"
#import "SkWindow.h"
#include "SkGraphics.h"
#include "SkCGUtils.h" #include "SkCGUtils.h"
#include "SkGraphics.h"
#include "SkImageDecoder.h"
#include "SkOSFile.h"
#include "SkPaint.h"
#include "SkPicture.h"
#include "SkStream.h"
#include "SkWindow.h"
static void make_filepath(SkString* path, const char* dir, const SkString& name) {
size_t len = strlen(dir);
path->set(dir);
if (len > 0 && dir[len - 1] != '/') {
path->append("/");
}
path->append(name);
}
static SkPicture* LoadPicture(const char path[]) {
SkPicture* pic = NULL;
SkBitmap bm;
if (SkImageDecoder::DecodeFile(path, &bm)) {
bm.setImmutable();
pic = SkNEW(SkPicture);
SkCanvas* can = pic->beginRecording(bm.width(), bm.height());
can->drawBitmap(bm, 0, 0, NULL);
pic->endRecording();
} else {
SkFILEStream stream(path);
if (stream.isValid()) {
pic = SkNEW_ARGS(SkPicture,
(&stream, NULL, &SkImageDecoder::DecodeStream));
}
if (false) { // re-record
SkPicture p2;
pic->draw(p2.beginRecording(pic->width(), pic->height()));
p2.endRecording();
SkString path2(path);
path2.append(".new.skp");
SkFILEWStream writer(path2.c_str());
p2.serialize(&writer);
}
}
return pic;
}
class SkSampleView : public SkView { class SkSampleView : public SkView {
public: public:
SkSampleView() { SkSampleView() {
@ -16,17 +61,216 @@ protected:
p.setTextSize(20); p.setTextSize(20);
p.setAntiAlias(true); p.setAntiAlias(true);
canvas->drawText("Hello World!", 13, 50, 30, p); canvas->drawText("Hello World!", 13, 50, 30, p);
SkRect r = {50, 50, 80, 80}; // SkRect r = {50, 50, 80, 80};
p.setColor(0xAA11EEAA); p.setColor(0xAA11EEAA);
canvas->drawRect(r, p); // canvas->drawRect(r, p);
SkRect result;
SkPath path;
path.moveTo(0, 0);
path.lineTo(1, 1);
path.lineTo(1, 8);
path.lineTo(0, 9);
SkASSERT(path.hasRectangularInterior(&result));
path.reset();
path.addRect(10, 10, 100, 100, SkPath::kCW_Direction);
path.addRect(20, 20, 50, 50, SkPath::kCW_Direction);
path.addRect(50, 50, 90, 90, SkPath::kCCW_Direction);
p.setColor(0xAA335577);
canvas->drawPath(path, p);
SkASSERT(!path.hasRectangularInterior(NULL));
path.reset();
path.addRect(10, 10, 100, 100, SkPath::kCW_Direction);
path.addRect(20, 20, 80, 80, SkPath::kCW_Direction);
SkRect expected = {20, 20, 80, 80};
SkASSERT(path.hasRectangularInterior(&result));
SkASSERT(result == expected);
} }
private: private:
typedef SkView INHERITED; typedef SkView INHERITED;
}; };
void application_init();
void application_term();
static int showPathContour(SkPath::Iter& iter) {
uint8_t verb;
SkPoint pts[4];
int moves = 0;
bool waitForClose = false;
while ((verb = iter.next(pts)) != SkPath::kDone_Verb) {
switch (verb) {
case SkPath::kMove_Verb:
if (!waitForClose) {
++moves;
waitForClose = true;
}
SkDebugf("path.moveTo(%1.9g, %1.9g);\n", pts[0].fX, pts[0].fY);
break;
case SkPath::kLine_Verb:
SkDebugf("path.lineTo(%1.9g, %1.9g);\n", pts[1].fX, pts[1].fY);
break;
case SkPath::kQuad_Verb:
SkDebugf("path.quadTo(%1.9g, %1.9g, %1.9g, %1.9g);\n",
pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY);
break;
case SkPath::kCubic_Verb:
SkDebugf("path.cubicTo(%1.9g, %1.9g, %1.9g, %1.9g, %1.9g, %1.9g);\n",
pts[1].fX, pts[1].fY, pts[2].fX, pts[2].fY,
pts[3].fX, pts[3].fY);
break;
case SkPath::kClose_Verb:
waitForClose = false;
SkDebugf("path.close();\n");
break;
default:
SkDEBUGFAIL("bad verb");
SkASSERT(0);
return 0;
}
}
return moves;
}
class PathCanvas : public SkCanvas {
virtual void drawPath(const SkPath& path, const SkPaint& paint) {
if (nameonly) {
SkDebugf(" %s%d,\n", filename.c_str(), ++count);
return;
}
SkPath::Iter iter(path, true);
SkDebugf("<div id=\"%s%d\">\n", filename.c_str(), ++count);
SkASSERT(path.getFillType() < SkPath::kInverseWinding_FillType);
SkDebugf("path.setFillType(SkPath::k%s_FillType);\n",
path.getFillType() == SkPath::kWinding_FillType ? "Winding" : "EvenOdd");
int contours = showPathContour(iter);
SkRect r;
SkRect copy = r;
bool hasOne = path.hasRectangularInterior(&r);
bool expected = (path.getFillType() == SkPath::kWinding_FillType && contours == 1)
|| (path.getFillType() == SkPath::kEvenOdd_FillType && contours == 2);
if (!expected) {
SkDebugf("suspect contours=%d\n", contours);
}
int verbs = path.countVerbs();
int points = path.countPoints();
if (hasOne) {
if (rectVerbsMin > verbs) {
rectVerbsMin = verbs;
}
if (rectVerbsMax < verbs) {
rectVerbsMax = verbs;
}
if (rectPointsMin > points) {
rectPointsMin = points;
}
if (rectPointsMax < points) {
rectPointsMax = points;
}
SkDebugf("path.addRect(%1.9g, %1.9g, %1.9g, %1.9g);\n",
r.fLeft, r.fTop, r.fRight, r.fBottom);
} else {
if (verbsMin > verbs) {
verbsMin = verbs;
}
if (verbsMax < verbs) {
verbsMax = verbs;
}
if (pointsMin > points) {
pointsMin = points;
}
if (pointsMax < points) {
pointsMax = points;
}
SkDebugf("no interior bounds\n");
}
path.hasRectangularInterior(&copy);
SkDebugf("</div>\n\n");
}
virtual void drawPosTextH(const void* text, size_t byteLength,
const SkScalar xpos[], SkScalar constY,
const SkPaint& paint) {
}
public:
void divName(const SkString& str, bool only) {
filename = str;
char* chars = filename.writable_str();
while (*chars) {
if (*chars == '.' || *chars == '-') *chars = '_';
chars++;
}
count = 0;
nameonly = only;
}
void init() {
pointsMin = verbsMin = SK_MaxS32;
pointsMax = verbsMax = SK_MinS32;
rectPointsMin = rectVerbsMin = SK_MaxS32;
rectPointsMax = rectVerbsMax = SK_MinS32;
}
SkString filename;
int count;
bool nameonly;
int pointsMin;
int pointsMax;
int verbsMin;
int verbsMax;
int rectPointsMin;
int rectPointsMax;
int rectVerbsMin;
int rectVerbsMax;
};
bool runone = false;
void application_init() { void application_init() {
SkGraphics::Init(); SkGraphics::Init();
SkEvent::Init(); SkEvent::Init();
if (runone) {
return;
}
const char pictDir[] = "/Volumes/chrome/nih/skia/skp/skp";
SkOSFile::Iter iter(pictDir, "skp");
SkString filename;
PathCanvas canvas;
canvas.init();
while (iter.next(&filename)) {
SkString path;
// if (true) filename.set("tabl_www_sahadan_com.skp");
make_filepath(&path, pictDir, filename);
canvas.divName(filename, false);
SkPicture* pic = LoadPicture(path.c_str());
pic->draw(&canvas);
SkDELETE(pic);
}
SkDebugf("\n</div>\n\n");
SkDebugf("<script type=\"text/javascript\">\n\n");
SkDebugf("var testDivs = [\n");
iter.reset(pictDir, "skp");
while (iter.next(&filename)) {
SkString path;
make_filepath(&path, pictDir, filename);
canvas.divName(filename, true);
SkPicture* pic = LoadPicture(path.c_str());
pic->draw(&canvas);
SkDELETE(pic);
}
SkDebugf("];\n\n");
SkDebugf("points min=%d max=%d verbs min=%d max=%d\n", canvas.pointsMin, canvas.pointsMax,
canvas.verbsMin, canvas.verbsMax);
SkDebugf("rect points min=%d max=%d verbs min=%d max=%d\n", canvas.rectPointsMin, canvas.rectPointsMax,
canvas.rectVerbsMin, canvas.rectVerbsMax);
SkDebugf("\n");
} }
void application_term() { void application_term() {
@ -46,7 +290,7 @@ protected:
@implementation SimpleNSView @implementation SimpleNSView
- (id)initWithDefaults { - (id)initWithDefaults {
if (self = [super initWithDefaults]) { if ((self = [super initWithDefaults])) {
fWind = new SkOSWindow(self); fWind = new SkOSWindow(self);
fWind->setLayout(new FillLayout, false); fWind->setLayout(new FillLayout, false);
fWind->attachChildToFront(new SkSampleView)->unref(); fWind->attachChildToFront(new SkSampleView)->unref();

View File

@ -75,6 +75,7 @@
'../experimental/Intersection/QuarticRoot.cpp', '../experimental/Intersection/QuarticRoot.cpp',
'../experimental/Intersection/QuarticRoot_Test.cpp', '../experimental/Intersection/QuarticRoot_Test.cpp',
'../experimental/Intersection/ShapeOps.cpp', '../experimental/Intersection/ShapeOps.cpp',
'../experimental/Intersection/ShapeOpCubic4x4_Test.cpp',
'../experimental/Intersection/ShapeOpRect4x4_Test.cpp', '../experimental/Intersection/ShapeOpRect4x4_Test.cpp',
'../experimental/Intersection/Simplify.cpp', '../experimental/Intersection/Simplify.cpp',
'../experimental/Intersection/SimplifyAddIntersectingTs_Test.cpp', '../experimental/Intersection/SimplifyAddIntersectingTs_Test.cpp',