Arbitrary polygons crash -[NSBezierPath stroke]
Arbitrary polygons crash -[NSBezierPath stroke]
- Subject: Arbitrary polygons crash -[NSBezierPath stroke]
- From: Tom Bernard <email@hidden>
- Date: Tue, 27 Jun 2006 17:05:54 -0600
Why do arbitrary polygons cause -[NSBezierPath stroke] to crash?
-[NSBezierPath fill] fills these polygons without incident. -stroke and
-fill accept other polygons without incident.
I have written a screensaver that creates objects, draws these objects on
the screen, ages the objects to maturity, then allows the objects to move
beyond the edge of the screen where they die. Objects may be stroked or
filled.
Stroked polygons sometimes crash. Filled polygons always draw. I have ruled
out premature release of the polygon, which is often a problem reported in
these archives. I have sometimes seen crashes caused by changing the view's
bounds. I have verified that I have not changed the bounds, nor has anything
changed the bounds behind my back.
Here are two methods, -[CirclesScreenSaverView drawRect:], and -[BISPolygon
draw] which is called by -drawRect:
- (void)drawRect:(NSRect)rect
{
OnScreenObject *anOnScreenObject;
NSEnumerator *enumerator;
int i;
// erase the whole view once, otherwise, erase each object
// if (viewNeedsErase || theControllerData.showGrid || [self isPreview])
if (viewNeedsErase || theControllerData.showGrid)
{
[eraseColor set];
[NSBezierPath fillRect:rect];
viewNeedsErase = NO;
}
else
{
[eraseColor set];
enumerator = [objectArray objectEnumerator];
while (anOnScreenObject = [enumerator nextObject])
{
[anOnScreenObject erase];
if (theControllerData.showOnScreenObjectLabel) [anOnScreenObject
eraseOnScreenObjectLabel];
}
}
...
// kill objects that are ready to die
enumerator = [executionList objectEnumerator];
while (anOnScreenObject = [enumerator nextObject])
{
[anOnScreenObject die];
[objectArray removeObject:anOnScreenObject];
}
[executionList removeAllObjects];
// draw the remaining objects
enumerator = [objectArray objectEnumerator];
while (anOnScreenObject = [enumerator nextObject])
{
[anOnScreenObject draw];
if (theControllerData.showOnScreenObjectLabel) [anOnScreenObject
drawOnScreenObjectLabel];
}
}
- (void) draw
{
if ((*theControllerDataPtr).showControlRects)
{
...
}
if ((*theControllerDataPtr).showObject)
{
transform = [NSAffineTransform transform];
[transform translateXBy:enclosingRectOfObject.origin.x
yBy:enclosingRectOfObject.origin.y];
[transform rotateByRadians:rotation];
eraseTransform = [transform retain];
{
NSBezierPath *transformedPath = [transform
transformBezierPath:bisPolygonPath];
[objectColor set];
// transformedPath = [self calculatePolygon];
// transformedPath = nil;
/*
[(*theControllerDataPtr).circlesScreenSaverView
outputObject:transformedPath
toFile:@"transformedPath.txt"
withFormat:@"transformedPath = %@\n"
andTag:[dateFormatter stringFromDate:[NSDate date]]];
*/
// if (YES) {[transformedPath fill];} else {[transformedPath
stroke];}
if (fillOrStroke) {[transformedPath fill];} else
{[transformedPath stroke];}
}
}
}
And here is a method added to BISPolygon.m for testing specific troubled
polygons (uncomment
// transformedPath = [self calculatePolygon];
in the above -draw method):
// this one crashes
- (NSBezierPath *)calculatePolygon
{
NSBezierPath *path = [NSBezierPath bezierPath];
[path moveToPoint:NSMakePoint(127.761421, 227.956528)];
[path lineToPoint:NSMakePoint(96.961540, 275.849915)];
[path lineToPoint:NSMakePoint(115.441422, 333.059204)];
[path lineToPoint:NSMakePoint(169.285324, 356.504639)];
[path lineToPoint:NSMakePoint(217.947693, 328.531311)];
[path lineToPoint:NSMakePoint(224.784775, 270.203705)];
[path lineToPoint:NSMakePoint(184.648117, 225.443726)];
[path lineToPoint:NSMakePoint(127.761436, 227.956512)];
[path closePath];
return path;
}
Here is a crash report showing the crash within -stroke called from -draw
Host Name: IntelMac2
Date/Time: 2006-06-27 04:03:25.189 -0600
OS Version: 10.4.4 (Build 8G1171)
Report Version: 4
Command: ScreenSaverEngine
Path:
/System/Library/Frameworks/ScreenSaver.framework/Resources/ScreenSaverEngine
.app/Contents/MacOS/ScreenSaverEngine
Parent: loginwindow [124]
Version: 1.5 (1.5)
Build Version: 60
Project Name: ScreenSaver
Source Version: 1220300
PID: 4779
Thread: 0
Exception: EXC_BAD_ACCESS (0x0001)
Codes: KERN_INVALID_ADDRESS (0x0001) at 0xc000388c
Thread 0 Crashed:
0 com.apple.CoreGraphics 0x903b635f draw_line + 5035
1 com.apple.CoreGraphics 0x903b4ef3 line_to + 1082
2 com.apple.CoreGraphics 0x903b47fc aa_line_render + 484
3 libRIP.A.dylib 0x943b2597 ripr_Coverage + 1020
4 libRIP.A.dylib 0x943b200b ripc_Render + 443
5 libRIP.A.dylib 0x943bd070 ripc_DrawPath + 300
6 com.apple.CoreGraphics 0x9038cff2 CGContextDrawPath + 169
7 com.apple.CoreGraphics 0x903b426b CGContextStrokePath + 25
8 com.apple.AppKit 0x9348a3ee
-[NSBezierPath(NSBezierPathDevicePrimitives) _doUserPathWithOp:inContext:] +
264
9 com.apple.AppKit 0x934cc216 -[NSBezierPath stroke] +
246
10 ...ersearch.CirclesScreenSaver 0x0027e4de -[BISPolygon draw] + 528
(BISPolygon.m:139)
11 ...ersearch.CirclesScreenSaver 0x00277eed -[CirclesScreenSaverView
drawRect:] + 2166 (CirclesScreenSaverView.m:376)
12 ...ersearch.CirclesScreenSaver 0x00281e4b -[BenchmarkCirclesSSView
drawRect:] + 98 (BenchmarkCirclesSSView.m:37)
13 com.apple.AppKit 0x933eea97 -[NSView _drawRect:clip:]
+ 3228
14 com.apple.AppKit 0x933edaf1 -[NSView
_recursiveDisplayAllDirtyWithLockFocus:visRect:] + 614
15 com.apple.AppKit 0x933ecb59 -[NSView
_recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRect
ForView:topView:] + 217
16 com.apple.AppKit 0x933ed727 -[NSView
_recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRect
ForView:topView:] + 3239
17 com.apple.AppKit 0x934cbcfd -[NSNextStepFrame
_recursiveDisplayRectIfNeededIgnoringOpacity:isVisibleRect:rectIsVisibleRect
ForView:topView:] + 601
18 com.apple.AppKit 0x933eba4c -[NSView
_displayRectIgnoringOpacity:isVisibleRect:rectIsVisibleRectForView:] + 523
19 com.apple.AppKit 0x933eb37c -[NSView displayIfNeeded]
+ 439
20 com.apple.AppKit 0x933eb11e -[NSWindow
displayIfNeeded] + 168
21 com.apple.AppKit 0x9343b3cc _handleWindowNeedsDisplay
+ 206
22 com.apple.CoreFoundation 0x90823419 __CFRunLoopDoObservers +
342
23 com.apple.CoreFoundation 0x908224bb CFRunLoopRunSpecific + 827
24 com.apple.CoreFoundation 0x90822179 CFRunLoopRunInMode + 61
25 com.apple.HIToolbox 0x92ecf8e0 RunCurrentEventLoopInMode
+ 285
26 com.apple.HIToolbox 0x92ecefe7 ReceiveNextEventCommon +
385
27 com.apple.HIToolbox 0x92ecee3e
BlockUntilNextEventMatchingListInMode + 81
28 com.apple.AppKit 0x9336fc11 _DPSNextEvent + 576
29 com.apple.AppKit 0x9336f7fe -[NSApplication
nextEventMatchingMask:untilDate:inMode:dequeue:] + 137
30 com.apple.ScreenSaver.Engine 0x00004cce 0x1000 + 15566
31 com.apple.AppKit 0x93369583 -[NSApplication run] + 512
32 com.apple.ScreenSaver.Engine 0x00002721 0x1000 + 5921
33 com.apple.ScreenSaver.Engine 0x000024aa 0x1000 + 5290
34 com.apple.ScreenSaver.Engine 0x000023c5 0x1000 + 5061
When I first saw these crashes, they were infrequent (one every 30 - 60
minutes), but always -stroke, never -fill. I changed
if (fillOrStroke) {[transformedPath fill];} else {[transformedPath stroke];}
to
if (YES) {[transformedPath fill];} else {[transformedPath stroke];}
to test if a filled polygon would crash; filled polygons always draw. When I
deliberately release transformedPath before the above line, the crash report
shows a released object, not an object being drawn:
Thread 0 Crashed:
0 libobjc.A.dylib 0x90a559c1 _objc_error + 86
1 libobjc.A.dylib 0x90a559f8 __objc_error + 45
2 libobjc.A.dylib 0x90a54060 _freedHandler + 53
3 ...ersearch.CirclesScreenSaver 0x0027e4db -[BISPolygon draw] + 489
(BISPolygon.m:141)
4 ...ersearch.CirclesScreenSaver 0x00277f12 -[CirclesScreenSaverView
drawRect:] + 2139 (CirclesScreenSaverView.m:371)
5 ...ersearch.CirclesScreenSaver 0x00281e48 -[BenchmarkCirclesSSView
drawRect:] + 98 (BenchmarkCirclesSSView.m:37)
Suspecting that I was somehow passing a troubled polygon, I inserted code to
output the polygon to a file. At the time of crash, the file contained the
polygon that was passed to stroke. When I stroke this polygon in a test
application containing a custom NSView, the polygon draws. When I stroke
this polygon within -[BISPolygon draw], crash occurs. If I fill the polygon
within -[BISPolygon draw], fill occurs.
I confirmed that the view's bounds are unchanged by requesting notification
and using printf within my note handler to record bounds changes. From
-[CirclesScreenSaverView initWithFrame:isPreview:]
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(noteBoundsChanged:)
name:NSViewBoundsDidChangeNotification
object:nil];
[self setPostsBoundsChangedNotifications:YES];
// [self setBounds:[self bounds]];
When I uncomment the last line, a bounds change is noted; with the last line
commented out, no bounds changes are noted.
So what is happening here? Thanks.
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden