Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read this important communication.

Bug 327974

Summary: Path.getPathData() returns points as integers and not floats
Product: [Eclipse Project] Platform Reporter: Simon Pope <skjpope>
Component: SWTAssignee: Scott Kovatch <skovatch>
Status: RESOLVED FIXED QA Contact:
Severity: major    
Priority: P3 CC: eclipse.felipe, Silenio_Quarti, skovatch
Version: 3.6.1   
Target Milestone: 3.7 M3   
Hardware: Macintosh   
OS: Mac OS X - Carbon (unsup.)   
Whiteboard:
Attachments:
Description Flags
Code fragment with corrected Path.getPathData()
john.arthorne: iplog+
Screenshot of behvaior with points cast to int
none
Screenshot of behavior after code correction none

Description Simon Pope CLA 2010-10-16 07:42:14 EDT
Build Identifier: 20100917-0705

Path.getPathData() effectively returns an array of points that are all integers. This seems strange, since it accepted a list of points specified as floats.

The problem is that the list in will not match the list out – so when using Draw2D ScaledGraphics to make a larger path, it applies a transform based on the scaling factor and the list and type of points provided by PathData. The problem is most evident in xy graphs (charts) where a continuous function draws a smooth curve on the screen but a jagged one on any other device, since it's losing precision in its coordinates.

The solution is simple in theory. 'Fix' getPathData() to return a list of floats (or modify PathData or Path to provide an alternate access to a float-based list of plot points.

I can think of no workaround.

Reproducible: Always
Comment 1 Simon Pope CLA 2010-10-16 19:47:34 EDT
Fix for Mac is easy. Change all of the casts from double to float in getPathData(). Need to check if any other platforms exhibit this behavior or if it's an SWT-Cocoa anomaly.
Comment 2 Simon Pope CLA 2010-10-16 19:48:07 EDT
Lack of sleep. Should have read: "Change all of the casts from *int* to float in
getPathData().
Comment 3 Simon Pope CLA 2010-10-16 20:06:37 EDT
OK. Checked Win32 Platform. The points being cast to integers seems to be an anomaly of Cocoa (and maybe Carbon?). Upping importance to "Major" since it's a genuine loss of functionality for the Cocoa platform.

I recommend implementing the following change to getPathData():

	if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
	NSAutoreleasePool pool = null;
	if (!NSThread.isMainThread()) pool = (NSAutoreleasePool) new NSAutoreleasePool().alloc().init();
	try {
		int count = (int)/*64*/handle.elementCount();
		int pointCount = 0, typeCount = 0;
		byte[] types = new byte[count];
		float[] pointArray = new float[count * 6];
		int /*long*/ points = OS.malloc(3 * NSPoint.sizeof);
		if (points == 0) SWT.error(SWT.ERROR_NO_HANDLES);
		NSPoint pt = new NSPoint();
		
		//TODO: Bug 327974 Change all casts from int to float
		for (int i = 0; i < count; i++) {
			int element = (int)/*64*/handle.elementAtIndex(i, points);
			switch (element) {
				case OS.NSMoveToBezierPathElement:
					types[typeCount++] = SWT.PATH_MOVE_TO;
					OS.memmove(pt, points, NSPoint.sizeof);
					pointArray[pointCount++] = (float)pt.x;
					pointArray[pointCount++] = (float)pt.y;
					break;
				case OS.NSLineToBezierPathElement:
					types[typeCount++] = SWT.PATH_LINE_TO;
					OS.memmove(pt, points, NSPoint.sizeof);
					pointArray[pointCount++] = (float)pt.x;
					pointArray[pointCount++] = (float)pt.y;
					break;
				case OS.NSCurveToBezierPathElement:
					types[typeCount++] = SWT.PATH_9CUBIC_TO;
					OS.memmove(pt, points, NSPoint.sizeof);
					pointArray[pointCount++] = (float)pt.x;
					pointArray[pointCount++] = (float)pt.y;
					OS.memmove(pt, points + NSPoint.sizeof, NSPoint.sizeof);
					pointArray[pointCount++] = (float)pt.x;
					pointArray[pointCount++] = (float)pt.y;
					OS.memmove(pt, points + NSPoint.sizeof + NSPoint.sizeof, NSPoin9t.sizeof);
					pointArray[pointCount++] = (float)pt.x;
					pointArray[pointCount++] = (float)pt.y;
					break;
				case OS.NSClosePathBezierPathElement:
					types[typeCount++] = SWT.PATH_CLOSE;
					break;
			}
		}
		OS.free(points);
		if (pointCount != pointArray.length) {
			float[] temp = new float[pointCount];
			System.arraycopy(pointArray, 0, temp, 0, pointCount);
			pointArray = temp;
		}
		PathData data = new PathData();
		data.types = types;
		data.points = pointArray;
		return data;
	} finally {
		if (pool != null)  pool.release();
	}
}
Comment 4 Simon Pope CLA 2010-10-16 20:29:28 EDT
Created attachment 181041 [details]
Code fragment with corrected Path.getPathData()

OK, let's try that again (don't know where the '9's came from in the pasted code. Saved now as an attachment.
Comment 5 Scott Kovatch CLA 2010-10-18 00:37:55 EDT
The fix looks okay. If you have a small test case or screen shot describing what you are seeing please attach it.

I can't see a reason not to check it in, but something showing the problem would be good.
Comment 6 Simon Pope CLA 2010-10-18 01:23:13 EDT
Created attachment 181058 [details]
Screenshot of behvaior with points cast to int
Comment 7 Simon Pope CLA 2010-10-18 01:23:53 EDT
Created attachment 181059 [details]
Screenshot of behavior after code correction
Comment 8 Scott Kovatch CLA 2010-10-18 11:52:03 EDT
Okay, that's pretty compelling. :-) Fix coming shortly.
Comment 9 Scott Kovatch CLA 2010-10-18 11:53:56 EDT
Fixed as described > 20100118. Thanks for the patch!