mirror of
https://github.com/gnustep/libs-gui.git
synced 2025-05-30 13:50:37 +00:00
2005-01-11 23:50 Alexander Malmberg <alexander@malmberg.org>
* Headers/AppKit/NSBezierPath.h (NSWindingRule) (-containsPoint): Document. (-windingCountAtPoint:): New method. * Source/NSBezierPath.m: Remove some trailing whitespace. (PI): Correct rounding. (contribution, -contributionToContains:): Remove. (winding_line, winding_curve): New functions. (-windingCountAtPoint:): New method. (-containsPoint:): Use -windingCountAtPoint: instead of -contributionToContains:. Don't flatten the path. git-svn-id: svn+ssh://svn.gna.org/svn/gnustep/libs/gui/trunk@20538 72102866-910b-0410-8b05-ffd578937521
This commit is contained in:
parent
3cbd603819
commit
ff7516df4b
3 changed files with 335 additions and 121 deletions
13
ChangeLog
13
ChangeLog
|
@ -1,3 +1,16 @@
|
||||||
|
2005-01-11 23:50 Alexander Malmberg <alexander@malmberg.org>
|
||||||
|
|
||||||
|
* Headers/AppKit/NSBezierPath.h (NSWindingRule)
|
||||||
|
(-containsPoint): Document.
|
||||||
|
(-windingCountAtPoint:): New method.
|
||||||
|
* Source/NSBezierPath.m: Remove some trailing whitespace.
|
||||||
|
(PI): Correct rounding.
|
||||||
|
(contribution, -contributionToContains:): Remove.
|
||||||
|
(winding_line, winding_curve): New functions.
|
||||||
|
(-windingCountAtPoint:): New method.
|
||||||
|
(-containsPoint:): Use -windingCountAtPoint: instead of
|
||||||
|
-contributionToContains:. Don't flatten the path.
|
||||||
|
|
||||||
2005-01-09 Matt Rice <ratmice@yahoo.com>
|
2005-01-09 Matt Rice <ratmice@yahoo.com>
|
||||||
|
|
||||||
* Source/NSTableHeaderCell.m (-drawInteriorWithFrame:inView:): Use
|
* Source/NSTableHeaderCell.m (-drawInteriorWithFrame:inView:): Use
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/*
|
/*
|
||||||
The NSBezierPath class
|
The NSBezierPath class
|
||||||
|
|
||||||
Copyright (C) 1999 Free Software Foundation, Inc.
|
Copyright (C) 1999, 2005 Free Software Foundation, Inc.
|
||||||
|
|
||||||
Author: Enrico Sersale <enrico@imago.ro>
|
Author: Enrico Sersale <enrico@imago.ro>
|
||||||
Date: Dec 1999
|
Date: Dec 1999
|
||||||
|
@ -45,6 +45,17 @@ typedef enum {
|
||||||
NSBevelLineJoinStyle = 2
|
NSBevelLineJoinStyle = 2
|
||||||
} NSLineJoinStyle;
|
} NSLineJoinStyle;
|
||||||
|
|
||||||
|
/** A winding rule defines which points are considered inside and which
|
||||||
|
points are considered outside a path.
|
||||||
|
<deflist>
|
||||||
|
<term>NSNonZeroWindingRule</term>
|
||||||
|
<desc>A point is inside the path iff the winding count at the point
|
||||||
|
is non-zero.</desc>
|
||||||
|
<term>NSEvenOddWindingRule</term>
|
||||||
|
<desc>A point is inside the path iff the winding count at the point
|
||||||
|
is odd.</desc>
|
||||||
|
</deflist>
|
||||||
|
*/
|
||||||
typedef enum {
|
typedef enum {
|
||||||
NSNonZeroWindingRule,
|
NSNonZeroWindingRule,
|
||||||
NSEvenOddWindingRule
|
NSEvenOddWindingRule
|
||||||
|
@ -209,7 +220,15 @@ typedef enum {
|
||||||
|
|
||||||
//
|
//
|
||||||
// Hit detection
|
// Hit detection
|
||||||
//
|
//
|
||||||
|
|
||||||
|
/** Returns the winding count, according to the PostScript definition,
|
||||||
|
at the given point. */
|
||||||
|
- (int) windingCountAtPoint: (NSPoint)point;
|
||||||
|
|
||||||
|
/** Returns YES iff the path contains, according to the current
|
||||||
|
<ref type="type" id="NSWindingRule">winding rule</ref>, the given point.
|
||||||
|
*/
|
||||||
- (BOOL)containsPoint:(NSPoint)point;
|
- (BOOL)containsPoint:(NSPoint)point;
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
<abstract>The NSBezierPath class</abstract>
|
<abstract>The NSBezierPath class</abstract>
|
||||||
|
|
||||||
Copyright (C) 1999 Free Software Foundation, Inc.
|
Copyright (C) 1999, 2005 Free Software Foundation, Inc.
|
||||||
|
|
||||||
Author: Enrico Sersale <enrico@imago.ro>
|
Author: Enrico Sersale <enrico@imago.ro>
|
||||||
Date: Dec 1999
|
Date: Dec 1999
|
||||||
|
@ -38,7 +38,7 @@
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
|
|
||||||
#ifndef PI
|
#ifndef PI
|
||||||
#define PI 3.1415926535897932384626433
|
#define PI 3.1415926535897932384626434
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// This magic number is 4 *(sqrt(2) -1)/3
|
// This magic number is 4 *(sqrt(2) -1)/3
|
||||||
|
@ -455,12 +455,12 @@ static float default_miter_limit = 10.0;
|
||||||
// FIXME: I don't see how this should work with color changes
|
// FIXME: I don't see how this should work with color changes
|
||||||
if(_cacheImage == nil)
|
if(_cacheImage == nil)
|
||||||
{
|
{
|
||||||
_cacheImage = [[NSImage alloc] initWithSize: bounds.size];
|
_cacheImage = [[NSImage alloc] initWithSize: bounds.size];
|
||||||
[_cacheImage lockFocus];
|
[_cacheImage lockFocus];
|
||||||
DPStranslate(ctxt, -origin.x, -origin.y);
|
DPStranslate(ctxt, -origin.x, -origin.y);
|
||||||
[ctxt GSSendBezierPath: self];
|
[ctxt GSSendBezierPath: self];
|
||||||
DPSstroke(ctxt);
|
DPSstroke(ctxt);
|
||||||
[_cacheImage unlockFocus];
|
[_cacheImage unlockFocus];
|
||||||
}
|
}
|
||||||
[_cacheImage compositeToPoint: origin operation: NSCompositeCopy];
|
[_cacheImage compositeToPoint: origin operation: NSCompositeCopy];
|
||||||
}
|
}
|
||||||
|
@ -483,7 +483,7 @@ static float default_miter_limit = 10.0;
|
||||||
// FIXME: I don't see how this should work with color changes
|
// FIXME: I don't see how this should work with color changes
|
||||||
if(_cacheImage == nil)
|
if(_cacheImage == nil)
|
||||||
{
|
{
|
||||||
_cacheImage = [[NSImage alloc] initWithSize: bounds.size];
|
_cacheImage = [[NSImage alloc] initWithSize: bounds.size];
|
||||||
[_cacheImage lockFocus];
|
[_cacheImage lockFocus];
|
||||||
DPStranslate(ctxt, -origin.x, -origin.y);
|
DPStranslate(ctxt, -origin.x, -origin.y);
|
||||||
[ctxt GSSendBezierPath: self];
|
[ctxt GSSendBezierPath: self];
|
||||||
|
@ -768,18 +768,18 @@ static float default_miter_limit = 10.0;
|
||||||
- (NSBezierPathElement) elementAtIndex: (int)index
|
- (NSBezierPathElement) elementAtIndex: (int)index
|
||||||
associatedPoints: (NSPoint *)points
|
associatedPoints: (NSPoint *)points
|
||||||
{
|
{
|
||||||
[self subclassResponsibility:_cmd];
|
[self subclassResponsibility:_cmd];
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSBezierPathElement) elementAtIndex: (int)index
|
- (NSBezierPathElement) elementAtIndex: (int)index
|
||||||
{
|
{
|
||||||
return [self elementAtIndex: index associatedPoints: NULL];
|
return [self elementAtIndex: index associatedPoints: NULL];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)setAssociatedPoints:(NSPoint *)points atIndex:(int)index
|
- (void)setAssociatedPoints:(NSPoint *)points atIndex:(int)index
|
||||||
{
|
{
|
||||||
[self subclassResponsibility:_cmd];
|
[self subclassResponsibility:_cmd];
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -1141,141 +1141,323 @@ static float default_miter_limit = 10.0;
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
|
||||||
// Hit detection
|
/* We use our own point structure with double elements while recursing to
|
||||||
//
|
avoid losing accuracy at really fine subdivisions of curves. */
|
||||||
/*
|
typedef struct
|
||||||
* Return the contribution of a path segment from start to end to
|
|
||||||
* the containsPoint method for point.
|
|
||||||
*/
|
|
||||||
static
|
|
||||||
int contribution(NSPoint point, float dir, NSPoint start, NSPoint end, BOOL *hit)
|
|
||||||
{
|
{
|
||||||
double t;
|
double x, y;
|
||||||
double len;
|
} double_point;
|
||||||
double a;
|
|
||||||
|
|
||||||
start.x -= point.x;
|
static int winding_line(double_point from, double_point to, double_point p)
|
||||||
start.y -= point.y;
|
{
|
||||||
len = sqrt(start.x * start.x + start.y * start.y);
|
int y_dir;
|
||||||
a = atan2(start.y, start.x);
|
double k, x;
|
||||||
start.x = cos(a - dir) * len;
|
|
||||||
start.y = sin(a - dir) * len;
|
|
||||||
end.x -= point.x;
|
|
||||||
end.y -= point.y;
|
|
||||||
len = sqrt(end.x * end.x + end.y * end.y);
|
|
||||||
a = atan2(end.y, end.x);
|
|
||||||
end.x = cos(a - dir) * len;
|
|
||||||
end.y = sin(a - dir) * len;
|
|
||||||
|
|
||||||
if ((start.y == 0) || (end.y == 0))
|
if (from.y == to.y)
|
||||||
{
|
return 0;
|
||||||
*hit = YES;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
*hit = NO;
|
|
||||||
|
|
||||||
// Both point on the same half plain
|
if (to.y < from.y)
|
||||||
if ((start.y < 0) == (end.y < 0))
|
|
||||||
{
|
{
|
||||||
return 0;
|
y_dir = -2;
|
||||||
|
if (p.y < to.y)
|
||||||
|
return 0;
|
||||||
|
if (p.y > from.y)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
y_dir = 2;
|
||||||
|
if (p.y < from.y)
|
||||||
|
return 0;
|
||||||
|
if (p.y > to.y)
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Does the line hit the coordinate line on the positive side?
|
|
||||||
t = (0 - start.y) * (end.x - start.x) / (end.y - start.y) + start.x;
|
|
||||||
|
|
||||||
if (t > 0)
|
if (p.y == from.y || p.y == to.y)
|
||||||
|
y_dir /= 2;
|
||||||
|
|
||||||
|
/* The line is intersected. Check if the intersection is outside the
|
||||||
|
line's bounding box. */
|
||||||
|
if (to.x < from.x)
|
||||||
{
|
{
|
||||||
if (start.y > 0)
|
if (p.x < to.x)
|
||||||
return 1;
|
return 0;
|
||||||
else
|
if (p.x > from.x)
|
||||||
return -1;
|
return y_dir;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (t == 0)
|
if (p.x < from.x)
|
||||||
*hit = YES;
|
return 0;
|
||||||
return 0;
|
if (p.x > to.x)
|
||||||
|
return y_dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Determine the exact x coordinate of the intersection. */
|
||||||
|
k = (double)(from.x - to.x) / (double)(from.y - to.y);
|
||||||
|
x = to.x + k * (double)(p.y - to.y);
|
||||||
|
if (x < p.x)
|
||||||
|
return y_dir;
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (int) contributionToContains: (NSPoint)point
|
static int winding_curve(double_point from, double_point to, double_point c1,
|
||||||
|
double_point c2, double_point p, int depth)
|
||||||
{
|
{
|
||||||
int i;
|
double x0, x1;
|
||||||
// Full total of contribution
|
double y0, y1;
|
||||||
int sum = 0;
|
double scale;
|
||||||
// running total for the current subpath
|
|
||||||
int sub = 0;
|
|
||||||
NSBezierPathElement type;
|
|
||||||
NSPoint p, pts[3];
|
|
||||||
NSPoint first_p, last_p;
|
|
||||||
int count = [self elementCount];
|
|
||||||
BOOL first = YES;
|
|
||||||
float dir = 2 * PI * rand() / RAND_MAX;
|
|
||||||
BOOL hit;
|
|
||||||
|
|
||||||
for(i = 0; i < count; i++)
|
/* Get the vertical extents of the convex hull. */
|
||||||
|
y0 = y1 = from.y;
|
||||||
|
if (to.y < y0)
|
||||||
|
y0 = to.y;
|
||||||
|
else if (to.y > y1)
|
||||||
|
y1 = to.y;
|
||||||
|
if (c1.y < y0)
|
||||||
|
y0 = c1.y;
|
||||||
|
else if (c1.y > y1)
|
||||||
|
y1 = c1.y;
|
||||||
|
if (c2.y < y0)
|
||||||
|
y0 = c2.y;
|
||||||
|
else if (c2.y > y1)
|
||||||
|
y1 = c2.y;
|
||||||
|
|
||||||
|
/* If the point is outside the convex hull, the line can't intersect the
|
||||||
|
curve. */
|
||||||
|
if (p.y < y0 || p.y > y1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Get the horizontal convex hull. */
|
||||||
|
x0 = x1 = from.x;
|
||||||
|
if (to.x < x0)
|
||||||
|
x0 = to.x;
|
||||||
|
else if (to.x > x1)
|
||||||
|
x1 = to.x;
|
||||||
|
if (c1.x < x0)
|
||||||
|
x0 = c1.x;
|
||||||
|
else if (c1.x > x1)
|
||||||
|
x1 = c1.x;
|
||||||
|
if (c2.x < x0)
|
||||||
|
x0 = c2.x;
|
||||||
|
else if (c2.x > x1)
|
||||||
|
x1 = c2.x;
|
||||||
|
|
||||||
|
/* If the point is left of the convex hull, the line doesn't intersect
|
||||||
|
the curve. */
|
||||||
|
if (p.x < x0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* If the point is right of the convex hull, the net winding count is 0,
|
||||||
|
1, or -1, and it depends only on how the end-points are placed in
|
||||||
|
relation to the point. Essentially, it's equivalent to a line. */
|
||||||
|
if (p.x > x1)
|
||||||
|
return winding_line(from, to, p);
|
||||||
|
|
||||||
|
/* Limit the recursion, just to be safe. */
|
||||||
|
if (depth >= 40)
|
||||||
|
return winding_line(from, to, p);
|
||||||
|
|
||||||
|
/* The line possibly intersects the curve in some interesting way. If the
|
||||||
|
curve is flat enough, we can pretend it's a line. Otherwise, we
|
||||||
|
subdivide and recurse.
|
||||||
|
|
||||||
|
First, calculate a suitable scale based on the coordinates of the
|
||||||
|
convex hull. This is used to get a good cutoff for the subdivision.
|
||||||
|
Since it's based on the coordinates in the curve, scaling the curve
|
||||||
|
up or down won't affect relative accuracy. Note that if the scale is
|
||||||
|
zero, the convex hull, and thus the curve, has no extent. */
|
||||||
|
|
||||||
|
scale = fabs(x0) + fabs(x1) + fabs(y0) + fabs(y1);
|
||||||
|
if (!scale)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
scale /= 40000000.0;
|
||||||
|
|
||||||
|
/* Deal with the degenerate case to == from. */
|
||||||
|
if (to.x == from.x && to.y == from.y)
|
||||||
|
{
|
||||||
|
if (x1 - x0 < scale && y1 - y0 < scale)
|
||||||
|
return winding_line(from, to, p);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
double dx, dy;
|
||||||
|
double nx, ny;
|
||||||
|
double d0, d1, d2, d3;
|
||||||
|
|
||||||
|
/* Get the direction vector and the normal vector. */
|
||||||
|
dx = to.x - from.x;
|
||||||
|
dy = to.y - from.y;
|
||||||
|
d0 = sqrt(dx * dx + dy * dy);
|
||||||
|
dx /= d0;
|
||||||
|
dy /= d0;
|
||||||
|
nx = dy;
|
||||||
|
ny = -dx;
|
||||||
|
|
||||||
|
/* Check that the distances along the direction vector are
|
||||||
|
monotone. */
|
||||||
|
|
||||||
|
d0 = from.x * dx + from.y * dy;
|
||||||
|
d1 = c1.x * dx + c1.y * dy;
|
||||||
|
d2 = c2.x * dx + c2.y * dy;
|
||||||
|
d3 = to.x * dx + to.y * dy;
|
||||||
|
|
||||||
|
if ((d3 > d2 && d2 > d1 && d1 > d0)
|
||||||
|
|| (d3 < d2 && d2 < d1 && d1 < d0))
|
||||||
|
{
|
||||||
|
/* Check that the control points are close to the straigt line
|
||||||
|
between from and to. */
|
||||||
|
d0 = to.x * nx + to.y * ny;
|
||||||
|
d1 = c1.x * nx + c1.y * ny;
|
||||||
|
d2 = c2.x * nx + c2.y * ny;
|
||||||
|
|
||||||
|
if (fabs(d0 - d1) < scale && fabs(d0 - d2) < scale)
|
||||||
|
{
|
||||||
|
/* It's flat enough. */
|
||||||
|
return winding_line(from, to, p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
/* Subdivide. */
|
||||||
|
double_point m, l1, l2, r1, r2;
|
||||||
|
|
||||||
|
m.x = (from.x + to.x + 3 * (c1.x + c2.x)) / 8;
|
||||||
|
m.y = (from.y + to.y + 3 * (c1.y + c2.y)) / 8;
|
||||||
|
|
||||||
|
l1.x = (from.x + c1.x) / 2;
|
||||||
|
l1.y = (from.y + c1.y) / 2;
|
||||||
|
|
||||||
|
l2.x = (from.x + 2 * c1.x + c2.x) / 4;
|
||||||
|
l2.y = (from.y + 2 * c1.y + c2.y) / 4;
|
||||||
|
|
||||||
|
r2.x = (to.x + c2.x) / 2;
|
||||||
|
r2.y = (to.y + c2.y) / 2;
|
||||||
|
|
||||||
|
r1.x = (to.x + 2 * c2.x + c1.x) / 4;
|
||||||
|
r1.y = (to.y + 2 * c2.y + c1.y) / 4;
|
||||||
|
|
||||||
|
return winding_curve(from, m, l1, l2, p, depth + 1)
|
||||||
|
+ winding_curve(m, to, r1, r2, p, depth + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (int) windingCountAtPoint: (NSPoint)point
|
||||||
|
{
|
||||||
|
int total;
|
||||||
|
NSBezierPathElement type;
|
||||||
|
int count;
|
||||||
|
BOOL first;
|
||||||
|
NSPoint pts[3];
|
||||||
|
NSPoint first_p, last_p;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* We trace a line from (-INF, point.y) to (point) and count the
|
||||||
|
intersections. Simple, really. ;)
|
||||||
|
|
||||||
|
Lines are trivially checked with a few complications:
|
||||||
|
|
||||||
|
a. Tangent lines, i.e. horizontal lines. These can be ignored since
|
||||||
|
the winding count is undefined on edges.
|
||||||
|
|
||||||
|
b. Lines whose endpoints are touched by our infinite line. To get
|
||||||
|
these right, we return half a winding for such intersections.
|
||||||
|
Except for intermediate horizontal lines, which are ignored, the
|
||||||
|
next line will also be intersected in one endpoint. If it's going
|
||||||
|
in the same direction as the first line, the two half intersections
|
||||||
|
will add up to one real intersection. If it isn't, the two half
|
||||||
|
intersections with opposite signs will cancel out. Either way, we
|
||||||
|
get the right results.
|
||||||
|
|
||||||
|
(If this happens for the first element, s/next/previous/ in the
|
||||||
|
explanation. In practice, we double the winding counts while
|
||||||
|
working and divide by 2 just before returning.)
|
||||||
|
|
||||||
|
Curves are checked first using the convex hull, and if necessary, by
|
||||||
|
subdividing until they are flat enough to check as lines. We use a
|
||||||
|
very fine subdivision, and thus get good accuracy. This is possible
|
||||||
|
because only the parts of the curve that might intersect the line are
|
||||||
|
subdivided (due to the convex hull checks). */
|
||||||
|
|
||||||
|
total = 0;
|
||||||
|
count = [self elementCount];
|
||||||
|
|
||||||
|
/* 'Unroll' the first element to avoid compiler warnings. It has to be
|
||||||
|
a MoveTo, anyway. */
|
||||||
|
type = [self elementAtIndex: 0 associatedPoints: pts];
|
||||||
|
if (type != NSMoveToBezierPathElement)
|
||||||
|
{
|
||||||
|
NSWarnLog(@"Invalid path, first element isn't MoveTo.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
last_p = first_p = pts[0];
|
||||||
|
first = NO;
|
||||||
|
|
||||||
|
#define D(a) (double_point){a.x,a.y}
|
||||||
|
for (i = 1; i < count; i++)
|
||||||
{
|
{
|
||||||
type = [self elementAtIndex: i associatedPoints: pts];
|
type = [self elementAtIndex: i associatedPoints: pts];
|
||||||
|
switch(type)
|
||||||
switch(type)
|
{
|
||||||
{
|
|
||||||
case NSMoveToBezierPathElement:
|
case NSMoveToBezierPathElement:
|
||||||
// Was the last sub path closed without close?
|
if (!first)
|
||||||
if (!first && NSEqualPoints(first_p, last_p))
|
{
|
||||||
{
|
total += winding_line(D(last_p), D(first_p), D(point));
|
||||||
sum += sub;
|
}
|
||||||
}
|
last_p = first_p = pts[0];
|
||||||
sub = 0;
|
first = NO;
|
||||||
first_p = last_p = pts[0];
|
break;
|
||||||
first = NO;
|
|
||||||
break;
|
|
||||||
case NSLineToBezierPathElement:
|
case NSLineToBezierPathElement:
|
||||||
p = pts[0];
|
if (first)
|
||||||
if (first)
|
{
|
||||||
{
|
NSWarnLog(@"Invalid path, LineTo without MoveTo.");
|
||||||
first_p = last_p = p;
|
|
||||||
first = NO;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
sub += contribution(point, dir, last_p, p, &hit);
|
|
||||||
if (hit)
|
|
||||||
return 0;
|
|
||||||
last_p = p;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case NSCurveToBezierPathElement:
|
|
||||||
// Not possible as flattend!
|
|
||||||
break;
|
|
||||||
case NSClosePathBezierPathElement:
|
|
||||||
sub += contribution(point, dir, last_p, first_p, &hit);
|
|
||||||
if (hit)
|
|
||||||
return 0;
|
return 0;
|
||||||
sum += sub;
|
}
|
||||||
sub = 0;
|
total += winding_line(D(last_p), D(pts[0]), D(point));
|
||||||
last_p = first_p;
|
last_p = pts[0];
|
||||||
first = YES;
|
break;
|
||||||
break;
|
case NSCurveToBezierPathElement:
|
||||||
|
if (first)
|
||||||
|
{
|
||||||
|
NSWarnLog(@"Invalid path, CurveTo without MoveTo.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
total += winding_curve(D(last_p), D(pts[2]), D(pts[0]), D(pts[1]), D(point), 0);
|
||||||
|
last_p = pts[2];
|
||||||
|
break;
|
||||||
|
case NSClosePathBezierPathElement:
|
||||||
|
if (first)
|
||||||
|
{
|
||||||
|
NSWarnLog(@"Invalid path, ClosePath with no open subpath.");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
first = YES;
|
||||||
|
total += winding_line(D(last_p), D(first_p), D(point));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
NSWarnLog(@"Invalid element in path.");
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Check if the last sub path was closed.
|
|
||||||
* It wont do any harm, if there was only one point in the subpath,
|
|
||||||
* as this will result in a subtotal of 0.
|
|
||||||
*/
|
|
||||||
if (!first && NSEqualPoints(first_p, last_p))
|
|
||||||
{
|
|
||||||
sum += sub;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return sum;
|
if (!first)
|
||||||
|
total += winding_line(D(last_p), D(first_p), D(point));
|
||||||
|
#undef D
|
||||||
|
|
||||||
|
if (total & 1)
|
||||||
|
{
|
||||||
|
/* This should only happen for points on edges, and the winding
|
||||||
|
count is undefined at such points. */
|
||||||
|
NSDebugLLog(@"NSBezierPath", @"winding count total is odd");
|
||||||
|
}
|
||||||
|
return total / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)containsPoint:(NSPoint)point
|
- (BOOL) containsPoint: (NSPoint)point
|
||||||
{
|
{
|
||||||
int sum;
|
int sum;
|
||||||
|
|
||||||
|
@ -1285,7 +1467,7 @@ int contribution(NSPoint point, float dir, NSPoint start, NSPoint end, BOOL *hit
|
||||||
if (!NSPointInRect(point, [self bounds]))
|
if (!NSPointInRect(point, [self bounds]))
|
||||||
return NO;
|
return NO;
|
||||||
|
|
||||||
sum = [[self bezierPathByFlatteningPath] contributionToContains: point];
|
sum = [self windingCountAtPoint: point];
|
||||||
if ([self windingRule] == NSNonZeroWindingRule)
|
if ([self windingRule] == NSNonZeroWindingRule)
|
||||||
{
|
{
|
||||||
if (sum == 0)
|
if (sum == 0)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue