Community
Participate
Working Groups
The following modified version org.eclipse.draw2d.tests.AdvancedGraphicsTests can be used to reproduce an invalid memory access on Mac Cocoa (tested with Eclipse 3.7M5). I was not able to reproduce the problem with an SWT-alone snippet yet, but the test case does only depends on Draw2d (SWTGraphics, ColorConstants), so it can quite easily be reproduced. /******************************************************************************* * Copyright (c) 2004, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package swt.bugs; import java.util.Stack; import junit.framework.TestCase; import org.eclipse.draw2d.ColorConstants; import org.eclipse.draw2d.SWTGraphics; import org.eclipse.swt.SWT; import org.eclipse.swt.events.PaintEvent; import org.eclipse.swt.events.PaintListener; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.ImageData; import org.eclipse.swt.graphics.PaletteData; import org.eclipse.swt.graphics.Path; import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.graphics.Resource; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; public class AdvancedGraphicsTests extends TestCase { private static final int PREVIEW_DELAY = 250; private SWTGraphics g; private Image image; private GC imageGC; private Path path1; private Path path2; private Stack resources = new Stack(); private void assertImageEquality(int width, int height) { ImageData data = image.getImageData(); int src, dst; PaletteData palette = data.palette; for (int y = 0; y < height; y++) for (int x = 0; x < width; x++) { src = data.getPixel(x, y); dst = data.getPixel(x, y + height); if (src != dst) { RGB rgb1 = palette.getRGB(src); RGB rgb2 = palette.getRGB(dst); // HACK, image operations seem to differ by as much as 4 if (Math.abs(rgb1.red - rgb2.red) > 4 || Math.abs(rgb1.green - rgb2.green) > 4 || Math.abs(rgb1.blue - rgb2.blue) > 4) assertEquals("Discrepancy at coordinates <" + x + ", " + y + ">", rgb1, rgb2); } } } private void displayImage() { final Shell shell = new Shell(SWT.DIALOG_TRIM); shell.addPaintListener(new PaintListener() { public void paintControl(PaintEvent e) { e.gc.drawImage(image, 0, 0); } }); shell.setBounds(100, 100, 800, 600); shell.open(); Display d = shell.getDisplay(); d.timerExec(PREVIEW_DELAY, new Runnable() { public void run() { if (!shell.isDisposed()) shell.close(); } }); while (!shell.isDisposed()) while (!d.readAndDispatch()) d.sleep(); } private void performTestcase(Runnable painter, Runnable tests[]) { g.pushState(); painter.run(); for (int i = 0; i < tests.length; i++) { g.translate(100, 0); tests[i].run(); g.pushState(); painter.run(); } for (int i = 0; i <= tests.length; i++) { g.popState(); g.translate(0, 100); painter.run(); } displayImage(); assertImageEquality(100 * tests.length, 100); } protected void setUp() throws Exception { path1 = new Path(null); path1.moveTo(20, 5); path1.quadTo(40, 5, 50, 25); path1.quadTo(20, 25, 20, 45); path1.lineTo(0, 25); path1.close(); path2 = new Path(null); path2.moveTo(15, 30); path2.cubicTo(50, 0, 50, 30, 20, 60); path2.close(); image = new Image(Display.getDefault(), 800, 600); imageGC = new GC(image, SWT.NONE); g = new SWTGraphics(imageGC); resources.push(path1); resources.push(path2); resources.push(image); resources.push(imageGC); } protected void tearDown() throws Exception { g.dispose(); while (!resources.isEmpty()) ((Resource) resources.pop()).dispose(); } public void testPathDraw() { class PathSettings implements Runnable { private final int antialias; private final Color color; private final int style; private final int width; PathSettings(int antialias, int width, int style, Color color) { this.antialias = antialias; this.width = width; this.style = style; this.color = color; } public void run() { g.setAntialias(antialias); g.setLineWidth(width); g.setLineStyle(style); g.setForegroundColor(color); } } g.setBackgroundColor(ColorConstants.darkBlue); Runnable tests[] = new Runnable[5]; tests[0] = new PathSettings(SWT.ON, 3, SWT.LINE_SOLID, ColorConstants.darkBlue); tests[1] = new PathSettings(SWT.OFF, 0, SWT.LINE_DOT, ColorConstants.red); tests[2] = new PathSettings(SWT.DEFAULT, 1, SWT.LINE_DOT, ColorConstants.darkBlue); tests[3] = new PathSettings(SWT.DEFAULT, 2, SWT.LINE_DOT, ColorConstants.darkGreen); tests[4] = new PathSettings(SWT.ON, 2, SWT.LINE_DASHDOTDOT, ColorConstants.black); for (int i = 0; i < tests.length; i++) { performTestcase(new Runnable() { public void run() { g.drawPath(path1); g.drawPath(path2); } }, new Runnable[] { tests[i] }); } } }
The following swt-alone snippet can be used to reproduce this issue (or at least a closely related one, as now we have: Invalid memory access of location 0x11bf2d160 rip=0x7fff831ef7b0) with SWT means alone: /******************************************************************************* * Copyright (c) 2004, 2010 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation *******************************************************************************/ package swt.bugs; import java.util.Stack; import junit.framework.TestCase; import org.eclipse.swt.SWT; import org.eclipse.swt.events.PaintEvent; import org.eclipse.swt.events.PaintListener; import org.eclipse.swt.graphics.Color; import org.eclipse.swt.graphics.GC; import org.eclipse.swt.graphics.Image; import org.eclipse.swt.graphics.ImageData; import org.eclipse.swt.graphics.PaletteData; import org.eclipse.swt.graphics.Path; import org.eclipse.swt.graphics.RGB; import org.eclipse.swt.graphics.Resource; import org.eclipse.swt.graphics.Transform; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; public class AdvancedGraphicsTests extends TestCase { private static final int PREVIEW_DELAY = 250; private static final Color red = new Color(null, 255, 0, 0); private static final Color darkGreen = new Color(null, 0, 127, 0); private static final Color darkBlue = new Color(null, 0, 0, 127); private static final Color black = new Color(null, 0, 0, 0); private Image image; private GC imageGC; private Path path1; private Path path2; private Stack resources = new Stack(); private void assertImageEquality(int width, int height) { ImageData data = image.getImageData(); int src, dst; PaletteData palette = data.palette; for (int y = 0; y < height; y++) for (int x = 0; x < width; x++) { src = data.getPixel(x, y); dst = data.getPixel(x, y + height); if (src != dst) { RGB rgb1 = palette.getRGB(src); RGB rgb2 = palette.getRGB(dst); // RGB values may differ by 1 (rounding effects?) if (Math.abs(rgb1.red - rgb2.red) > 1 || Math.abs(rgb1.green - rgb2.green) > 1 || Math.abs(rgb1.blue - rgb2.blue) > 1) assertEquals("Discrepancy at coordinates <" + x + ", " + y + ">", rgb1, rgb2); } } } private void displayImage() { final Shell shell = new Shell(SWT.DIALOG_TRIM); shell.addPaintListener(new PaintListener() { public void paintControl(PaintEvent e) { e.gc.drawImage(image, 0, 0); } }); shell.setBounds(100, 100, 800, 600); shell.open(); Display d = shell.getDisplay(); d.timerExec(PREVIEW_DELAY, new Runnable() { public void run() { if (!shell.isDisposed()) shell.close(); } }); while (!shell.isDisposed()) while (!d.readAndDispatch()) d.sleep(); } private void performTestcase(Runnable painter, Runnable tests[]) { Transform t = new Transform(imageGC.getDevice()); for (int i = 0; i < tests.length; i++) { t.translate(100, 0); imageGC.setTransform(t); tests[i].run(); painter.run(); } t.dispose(); t = new Transform(imageGC.getDevice()); t.translate(0, 100); imageGC.setTransform(t); for (int i = 0; i < tests.length; i++) { t.translate(100, 0); imageGC.setTransform(t); tests[i].run(); painter.run(); } t.dispose(); displayImage(); assertImageEquality(100 * tests.length, 100); } protected void setUp() throws Exception { path1 = new Path(null); path1.moveTo(20, 5); path1.quadTo(40, 5, 50, 25); path1.quadTo(20, 25, 20, 45); path1.lineTo(0, 25); path1.close(); path2 = new Path(null); path2.moveTo(15, 30); path2.cubicTo(50, 0, 50, 30, 20, 60); path2.close(); image = new Image(Display.getDefault(), 800, 600); imageGC = new GC(image, SWT.NONE); resources.push(path1); resources.push(path2); resources.push(image); resources.push(imageGC); } protected void tearDown() throws Exception { while (!resources.isEmpty()) ((Resource) resources.pop()).dispose(); } public void testPathDraw() { class PathSettings implements Runnable { private final int antialias; private final Color color; private final int style; private final int width; PathSettings(int antialias, int width, int style, Color color) { this.antialias = antialias; this.width = width; this.style = style; this.color = color; } public void run() { imageGC.setAntialias(antialias); imageGC.setLineWidth(width); imageGC.setLineStyle(style); imageGC.setForeground(color); } } imageGC.setBackground(darkBlue); Runnable tests[] = new Runnable[5]; tests[0] = new PathSettings(SWT.ON, 3, SWT.LINE_SOLID, darkBlue); tests[1] = new PathSettings(SWT.OFF, 0, SWT.LINE_DOT, red); tests[2] = new PathSettings(SWT.DEFAULT, 1, SWT.LINE_DOT, darkBlue); tests[3] = new PathSettings(SWT.DEFAULT, 2, SWT.LINE_DOT, darkGreen); tests[4] = new PathSettings(SWT.ON, 2, SWT.LINE_DASHDOTDOT, black); for (int i = 0; i < tests.length; i++) { performTestcase(new Runnable() { public void run() { imageGC.drawPath(path1); imageGC.drawPath(path2); } }, new Runnable[] { tests[i] }); } } }
If one changes the standalone SWT-snippet to not execute the tests one after another but within one pass, i.e. from for (int i = 0; i < tests.length; i++) { performTestcase(new Runnable() { public void run() { g.drawPath(path1); g.drawPath(path2); } }, new Runnable[] { tests[i] }); } to for (int i = 0; i < tests.length; i++) { performTestcase(new Runnable() { public void run() { imageGC.drawPath(path1); imageGC.drawPath(path2); } }, tests); } the invalid memory access (which seems to be only reproducible on the mac) does not occur. However, the modified snippet may be used to reproduce the issue that causes org.eclipse.draw2d.test.AdvancedGraphicsTests#testDrawPath() to fail on Mac and Windows with SWT means alone (on Linux GTK the modified test succeeds without any problems).
This bug hasn't had any activity in quite some time. Maybe the problem got resolved, was a duplicate of something else, or became less pressing for some reason - or maybe it's still relevant but just hasn't been looked at yet. If you have further information on the current state of the bug, please add it. The information can be, for example, that the problem still occurs, that you still want the feature, that more information is needed, or that the bug is (for whatever reason) no longer relevant. -- The automated Eclipse Genie.
I'm unable to reproduce the problem with the Snippet in comment#1 on 4.9 and macOS 10.13.6. Please reopen if the problem is still reproducible.