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:
parent
81d3ce0b63
commit
aa35831d1d
@ -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]);
|
||||||
|
@ -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)
|
||||||
|
@ -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;
|
||||||
|
@ -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;
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)) {
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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) {
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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) {
|
||||||
|
@ -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)
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
@ -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();
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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]);
|
||||||
}
|
}
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
|
@ -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];
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)) {
|
||||||
|
@ -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];
|
||||||
|
@ -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>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -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)) {
|
||||||
|
@ -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));
|
||||||
|
94
experimental/Intersection/ShapeOpCubic4x4_Test.cpp
Normal file
94
experimental/Intersection/ShapeOpCubic4x4_Test.cpp
Normal 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);
|
||||||
|
}
|
@ -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++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
}
|
}
|
||||||
|
@ -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
|
|
||||||
|
@ -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),
|
||||||
|
@ -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>
|
||||||
|
@ -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,
|
||||||
|
@ -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,
|
||||||
|
@ -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(©);
|
||||||
|
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();
|
||||||
|
@ -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',
|
||||||
|
Loading…
Reference in New Issue
Block a user