| Summary: | org.eclipse.swt.graphics.Transform does not handle rotate 45 degree correctly. | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|
| Product: | [Eclipse Project] Platform | Reporter: | shawn.r.fisk | ||||||||
| Component: | SWT | Assignee: | Platform-SWT-Inbox <platform-swt-inbox> | ||||||||
| Status: | CLOSED WONTFIX | QA Contact: | |||||||||
| Severity: | major | ||||||||||
| Priority: | P3 | CC: | ctg, eclipse.felipe, ericwill, heiko.boettger, jolkdarr, mike, skovatch | ||||||||
| Version: | 4.1 | ||||||||||
| Target Milestone: | --- | ||||||||||
| Hardware: | PC | ||||||||||
| OS: | Windows 7 | ||||||||||
| See Also: | https://github.com/eclipse/eclipse.platform.swt/pull/1 | ||||||||||
| Whiteboard: | stalebug | ||||||||||
| Attachments: |
|
||||||||||
I see a few problems on your code:
First one is here:
public void paintControl(PaintEvent e) {
drawDonut(e);
e.gc.dispose(); <--You can not dispose this GC, you didn't create it
}
Then here:
Transform tr = new Transform(e.display);
tr.translate(w / 2, h / 2);
e.gc.setTransform(tr);
for (int rot = 0; rot < 36; rot++) {
tr.rotate(5f);
e.gc.drawOval(-125, -40, 250, 80);
e.gc.setTransform(tr);
}
You can't reuse a Transform.
Change to this:
Transform tr = new Transform(e.display);
tr.translate(w / 2, h / 2);
e.gc.setTransform(tr);
tr.dispose();
for (int rot = 0; rot < 36; rot++) {
tr = new Transform(e.display);
tr.rotate(5f);
e.gc.setTransform(tr);
tr.dispose();
e.gc.drawOval(-125, -40, 250, 80);
}
See if works after you fix your code.
I"m closing this now as not eclipse, reopen it if need it.
I'll reopen this, because I'm seeing a similar problem in Cocoa. However, in Cocoa only the ovals at 45 and 215 degrees. The behavior is unchanged on Windows 7. There may still be some kind of problem with the code, but with the changes from Felipe in comment #1 the problem doesn't go away. New code:
===============
import org.eclipse.swt.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.widgets.*;
/**
* ZetCode Java SWT tutorial
*
* This program creates a donut shape
*
* @author jan bodnar
* website zetcode.com
* last modified June 2009
*/
public class SWTApp {
private Shell shell;
public SWTApp(Display display) {
shell = new Shell(display);
shell.addPaintListener(new DonutPaintListener());
shell.setText("Donut");
shell.setSize(430, 300);
shell.setLocation(300, 300);
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch()) {
display.sleep();
}
}
}
private class DonutPaintListener implements PaintListener {
public void paintControl(PaintEvent e) {
drawDonut(e);
}
}
private void drawDonut(PaintEvent e) {
int w = e.width;
int h = e.height;
e.gc.setAntialias(SWT.ON);
for (int rot = 0; rot < 36; rot++) {
Transform tr = new Transform(e.display);
tr.translate(w / 2, h / 2);
tr.rotate(5f * rot);
e.gc.setTransform(tr);
tr.dispose();
e.gc.drawOval(-125, -40, 250, 80);
}
}
public static void main(String[] args) {
Display display = new Display();
new SWTApp(display);
display.dispose();
}
}
Interesting, we have the same problem on cairo (nothing draws when rot=45||rot==225). See Bug 253670 The problem is how we compute the x, y draw offset in checkGC (all platforms have the same code). Indeed it is. Adding the line e.gc.getGCData().state |= 1 << 9; before the drawOval call fixes it, and in my gesture snippet. As the rotation value gets closer to 45 or 225 the x offset goes out of wack. Removing the fix for bug 245523 fixed the problem on windows. But that is not the right solution neither. I just came across this bug. This is still not fixed in 4.2. Is the statement about not reusing a transform in comment #1, true? Does this mean that one could not set the same transform on another instance of GC? Then this should be clearly documented on GC.setTransform. Created attachment 255135 [details]
methods to fix
I use intensively the class GC in an experimental application.
Hopefully, the few information provided below will be helpful to fix the issue.
I observed the following differences:
- drawX methods failed when a rotation angle is specified around 45, 135, 315 degrees,
- fillX methods never fail.
I provide two attachments:
- report.html, listing all methods of the GC class that cannot be used.
- Transformation_checker.java, snippet showing the bug in action for various shapes.
I tried some workarounds but they caused performance difficulties.
I tried to patch some drawX methods like for the following:
public void drawOval(int x, int y, int width, int height) {
if (handle == 0) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
checkGC(DRAW);
if (width < 0) {
x = x + width;
width = -width;
}
if (height < 0) {
y = y + height;
height = -height;
}
long /*int*/ cairo = data.cairo;
if (cairo != 0) {
if (width == height) {
Cairo.cairo_arc_negative(cairo, x + width / 2f, y + height / 2f, width / 2f, 0, -2 * (float)Compatibility.PI);
} else {
Cairo.cairo_save(cairo);
Cairo.cairo_translate(cairo, x + width / 2f, y + height / 2f);
Cairo.cairo_scale(cairo, width / 2f, height / 2f);
Cairo.cairo_arc_negative(cairo, 0, 0, 1, 0, -2 * (float)Compatibility.PI);
Cairo.cairo_restore(cairo);
}
Cairo.cairo_stroke(cairo);
return;
}
OS.gdk_draw_arc(data.drawable, handle, 0, x, y, width, height, 0, 23040);
}
The shape is correctly displayed.
Created attachment 255136 [details]
Java snippet illustrating the bug
Comment on attachment 255135 [details] methods to fix ><?xml version='1.0' encoding='utf-8' ?><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"/></head><body><h2 id="45-degree_rotation_bug">45-degree rotation bug</h2><table class="wikitable" style="border=1;border-collapse=collapse;text-align:center;"><tr><td>GC class</td></tr><tr><td>drawArc</td><td style="background-color:#DB0D0D;">KO</td><td>fillArc</td><td style="background-color:#0DDD0D;">OK</td></tr><tr><td>drawLine</td><td style="background-color:#DB0D0D;">KO</td><td style="background-color:#cccccc;" colspan="2"></td></tr><tr><td>drawOval</td><td style="background-color:#DB0D0D;">KO</td><td>fillOval</td><td style="background-color:#0DDD0D;">OK</td></tr><tr><td>drawRectangle</td><td style="background-color:#DB0D0D;">KO</td><td>fillRectangle</td><td style="background-color:#0DDD0D;">OK</td></tr><tr><td>drawRoundRectangle</td><td style="background-color:#DB0D0D;">KO</td><td>fillRoundRectangle</td><td style="background-color:#0DDD0D;">OK</td></tr><tr><td>drawPolygon</td><td style="background-color:#DB0D0D;">KO</td><td>fillPolygon</td><td style="background-color:#0DDD0D;">OK</td></tr><tr><td>drawPolyline</td><td style="background-color:#DB0D0D;">KO</td><td style="background-color:#cccccc;" colspan="2"></td></tr><tr><td>drawText</td><td style="background-color:0DDD0D;">OK</td><td style="background-color:#cccccc;" colspan="2"></td></tr><tr><td>drawPath</td><td style="background-color:#DB0D0D;">KO</td><td>fillPath</td><td style="background-color:#0DDD0D;">OK</td></tr></table></body></html> DrawText is OK (in report.html). Sorry for the inconvenience. I am no longer working on SWT. Moving to INBOX so that the team see the new comments. Created attachment 265102 [details]
methods to fix
GitHub Pull Request 1 created by [jolkdarr] https://github.com/eclipse/eclipse.platform.swt/pull/1 (In reply to Eclipse Genie from comment #16) > GitHub Pull Request 1 created by [jolkdarr] > https://github.com/eclipse/eclipse.platform.swt/pull/1 Could you please upload your patch to Gerrit? This is where committers will be able to review it. For more info, see: https://wiki.eclipse.org/Gerrit *** Bug 198065 has been marked as a duplicate of this bug. *** 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. As such, we're closing this bug. If you have further information on the current state of the bug, please add it and reopen this bug. 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. |
Build Identifier: M20100909-0800 Use the following code. package com.zetcode; import org.eclipse.swt.SWT; import org.eclipse.swt.events.PaintEvent; import org.eclipse.swt.events.PaintListener; import org.eclipse.swt.graphics.Transform; import org.eclipse.swt.widgets.Display; import org.eclipse.swt.widgets.Shell; /** * ZetCode Java SWT tutorial * * This program creates a donut shape * * @author jan bodnar * website zetcode.com * last modified June 2009 */ public class SWTApp { private Shell shell; public SWTApp(Display display) { shell = new Shell(display); shell.addPaintListener(new DonutPaintListener()); shell.setText("Donut"); shell.setSize(430, 300); shell.setLocation(300, 300); shell.open(); while (!shell.isDisposed()) { if (!display.readAndDispatch()) { display.sleep(); } } } private class DonutPaintListener implements PaintListener { public void paintControl(PaintEvent e) { drawDonut(e); e.gc.dispose(); } } private void drawDonut(PaintEvent e) { int w = e.width; int h = e.height; e.gc.setAntialias(SWT.ON); Transform tr = new Transform(e.display); tr.translate(w / 2, h / 2); e.gc.setTransform(tr); for (int rot = 0; rot < 36; rot++) { tr.rotate(5f); e.gc.drawOval(-125, -40, 250, 80); e.gc.setTransform(tr); } } public static void main(String[] args) { Display display = new Display(); new SWTApp(display); display.dispose(); } } In this example, we create a donut. The shapes resembles a cookie, hence the name donut. Transform tr = new Transform(e.display); tr.translate(w / 2, h / 2); e.gc.setTransform(tr); We move the middle of the axis to the center of the window. for (int rot = 0; rot < 36; rot++) { tr.rotate(5f); e.gc.drawOval(-125, -40, 250, 80); e.gc.setTransform(tr); } Reproducible: Always Steps to Reproduce: 1.Run the code in the details. 2.Notice the ellipses at 45, 135, 225, and 315 are missing. It should be a perfect donut. 3.Can can simplify the example to rotate a simple line at 45 degrees and it does not show up on the screen. If you use the transform method on Transform class instance it works correctly, the issue is inside the GC class.