Community
Participate
Working Groups
Hi, I would like to know why is the draw2d so inaccurate when zooming is in use. I have added two screenshots with 100%(good.png) and 300%(bad.png) zoom. You can see the gaps between cells.
Created attachment 223351 [details] 100% zoom
Created attachment 223352 [details] 300% zoom
Created attachment 223353 [details] 50% zoom
Did you make use of the double-precision geometry classes when performing calculations with your layout constraints. This may be caused by rounding effects that occur when using the integer-based precision.
*** Bug 392759 has been marked as a duplicate of this bug. ***
Well, there is a test case. You can see there are gaps between cells with zoom bigger than 1.2 or something. If you debug it, you will find that bounds are set correctly (it means all figures are just next to each other), but drawing is somehow broken. import org.eclipse.draw2d.ColorConstants; import org.eclipse.draw2d.Figure; import org.eclipse.draw2d.FigureCanvas; import org.eclipse.draw2d.GridData; import org.eclipse.draw2d.GridLayout; import org.eclipse.draw2d.IFigure; import org.eclipse.draw2d.Label; import org.eclipse.draw2d.Layer; import org.eclipse.draw2d.LineBorder; import org.eclipse.draw2d.MarginBorder; import org.eclipse.draw2d.RectangleFigure; import org.eclipse.draw2d.ScalableLayeredPane; import org.eclipse.draw2d.XYLayout; import org.eclipse.draw2d.geometry.Rectangle; import org.eclipse.swt.SWT; import org.eclipse.swt.events.MouseEvent; import org.eclipse.swt.events.MouseWheelListener; import org.eclipse.swt.layout.FillLayout; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; public class Test { /** * This is a separator figure. Just using the LineBorder leads to double lines * between all cells in the table. */ private static class Separator extends RectangleFigure { public Separator() { setOutline(false); setBackgroundColor(ColorConstants.black); } } public static void main(String[] args) { final Display display = new Display(); final Shell shell = new Shell(display); shell.setLayout(new FillLayout()); final FigureCanvas canvas = new FigureCanvas(shell); final ScalableLayeredPane pane = new ScalableLayeredPane(); final Layer layer = new Layer(); layer.setLayoutManager(new XYLayout()); final IFigure table = new Figure(); table.setBackgroundColor(display.getSystemColor(SWT.COLOR_WHITE)); table.setBorder(new LineBorder(1)); table.setOpaque(true); final GridLayout layout = new GridLayout(); layout.marginWidth = 0; layout.marginHeight = 0; layout.horizontalSpacing = 0; layout.verticalSpacing = 0; layout.numColumns = 9; table.setLayoutManager(layout); for (int i = 0; i < 3; i++) { for (int j = 0; j < 5; j++) { final Label label = new Label("Test"); label.setBackgroundColor(display.getSystemColor(SWT.COLOR_GRAY)); label.setOpaque(true); label.setBorder(new MarginBorder(2)); GridData gridData = new GridData(); gridData.horizontalAlignment = SWT.FILL; gridData.verticalAlignment = SWT.FILL; table.add(label, gridData); if (j < 4) { gridData = new GridData(); gridData.horizontalAlignment = SWT.FILL; gridData.verticalAlignment = SWT.FILL; gridData.widthHint = 1; table.add(new Separator(), gridData); } } if (i < 2) { GridData gridData = new GridData(); gridData.horizontalAlignment = SWT.FILL; gridData.verticalAlignment = SWT.FILL; gridData.heightHint = 1; gridData.horizontalSpan = 9; table.add(new Separator(), gridData); } } layer.add(table, new Rectangle(50, 50, -1, -1)); pane.add(layer, "root layer"); canvas.addMouseWheelListener(new MouseWheelListener() { @Override public void mouseScrolled(MouseEvent e) { double scale = pane.getScale(); pane.setScale(e.count < 0 ? scale * 0.95 : scale * 1.05); } }); canvas.setContents(pane); shell.open(); shell.setSize(600, 600); while (!shell.isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); } } } }
Hi, How could we set precision to double Alexander ? Regards, BiM
Well, you would have to make use of the double-based "Precision*" classes instead of the integer-based ones (e.g. PrecisionRectangle). However, from the example you provided I have the impression that the problem does not rely within your client code. It seems Label is not robust against rounding effects on scaling. But I am not sure how well we can circumvent this. I will have to dig deeper into it.
Ok, thank you!
Default figures as RectangleFigure (for example) using Rectangle class and not PrecisionRectangle class. Do I need to redefine all figures ?
Also, on normal zoom (100%), if you draw two ellipses side to side, the second should start where the first stop, but the second ellipse start one pixel after the first one. This problem is only increase by zooming. See bug 392759 to understand what I speak about.
There is another simple runnable example showing inaccuracy of the draw2d: public class Example { public static void main(String[] args) { Display d = new Display(); final Shell shell = new Shell(); shell.setLayout(new FillLayout()); FigureCanvas canvas = new FigureCanvas(shell); canvas.setBackground(ColorConstants.white); final ScalableLayeredPane pane = new ScalableLayeredPane(); canvas.setContents(pane); Layer layer = new Layer(); layer.setLayoutManager(new XYLayout()); pane.add(layer); final IFigure panel = new Figure(); panel.setBorder(new LineBorder()); panel.setLayoutManager(new StackLayout()); final IFigure content = new Panel(); content.setLayoutManager(new StackLayout()); RectangleFigure rec = new RectangleFigure(); rec.setBackgroundColor(ColorConstants.yellow); content.add(rec); panel.add(content); final Point location = new PrecisionPoint(50, 50); final Dimension dimension = new PrecisionDimension(100, 60); layer.add(panel, new PrecisionRectangle(location, dimension)); canvas.addMouseListener(new MouseAdapter() { @Override public void mouseUp(MouseEvent e) { if (e.button == 1) { pane.setScale(pane.getScale() + 0.1); } else { pane.setScale(pane.getScale() - 0.1); } shell.setText("Zoom: " + pane.getScale()); } }); shell.setText("Zoom: " + pane.getScale()); shell.setSize(600, 400); shell.open(); while (!shell.isDisposed()) { if (!d.readAndDispatch()) { d.sleep(); } } d.dispose(); } } click left - it scales up click right - it scales down I would expect yellow rectangle with black border just around that rectangle. The border line should scale. But when you scale, it behaves really weird. The border is bad.