Bug 571401 - Make Transform lightweight and platform-independent
Summary: Make Transform lightweight and platform-independent
Status: REOPENED
Alias: None
Product: Platform
Classification: Eclipse Project
Component: SWT (show other bugs)
Version: 4.20   Edit
Hardware: PC All
: P3 enhancement (vote)
Target Milestone: ---   Edit
Assignee: Nikita Nemkin CLA
QA Contact:
URL:
Whiteboard:
Keywords: noteworthy
Depends on:
Blocks:
 
Reported: 2021-02-22 07:07 EST by Nikita Nemkin CLA
Modified: 2022-06-03 01:18 EDT (History)
12 users (show)

See Also:


Attachments
Screenshot of wrong figure placement (53.96 KB, image/png)
2021-07-28 14:34 EDT, Phil Beauvoir CLA
no flags Details
Screenshot of correct image (55.96 KB, image/png)
2021-07-28 14:35 EDT, Phil Beauvoir CLA
no flags Details
Screenshot of Ecore Editor in Windows 200% (11.87 KB, image/png)
2021-07-29 01:44 EDT, Phil Beauvoir CLA
no flags Details
Screenshot of Eclipse BPMN2 diagrams at 100% and 200% on Windows (43.28 KB, image/png)
2021-07-30 06:41 EDT, Phil Beauvoir CLA
no flags Details
Screenshot of Eclipse BPMN Editor (515.35 KB, image/png)
2021-08-19 03:17 EDT, Phil Beauvoir CLA
no flags Details
Transform.java patch (12.46 KB, text/plain)
2021-08-23 02:11 EDT, Phil Beauvoir CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Nikita Nemkin CLA 2021-02-22 07:07:59 EST
Graphics Transform class represents a 3x2 affine transformation matrix.
Given how small and simple it is, there's no need to use native matrix implementations. Shared pure Java implementation is enough and native matrices could be created on demand at the point of use (GC.getTransform and GC.setTransform).

This change makes dispose() optional, similarly to what was done to Color in Bug 563018.
Comment 1 Eclipse Genie CLA 2021-02-22 07:24:15 EST
New Gerrit change created: https://git.eclipse.org/r/c/platform/eclipse.platform.swt/+/176681
Comment 2 Alexander Kurtakov CLA 2021-03-22 05:03:03 EDT
Bug 572167 looks like duplicate of this one.
Comment 3 Christoph Laeubrich CLA 2021-03-22 05:36:09 EDT
@Nikita that's really cool :-)

I also commented on the gerrit I think it would be good to have Transform support double variants of all methods too

BTW: Can have something similar for Path as well? If yes it would finally be possible to emulate Java2D's geometric package with Circle2D, Recangele2D and so on what is currently a major benefit over using SWT...
Comment 5 Nikita Nemkin CLA 2021-03-22 06:07:22 EDT
(In reply to Christoph Laeubrich from comment #3)
> @Nikita that's really cool :-)
> 
> I also commented on the gerrit I think it would be good to have Transform
> support double variants of all methods too

This one is tricky. I'm not sure if having both is desirable (API bloat and illusion of precision).
Cairo and CoreGraphics do use double in their API, but GDI+ and Direct2D use float. The trend is towards float, because of GPU acceleration.

Moreover, most SWT GC methods lack even float variants, let alone double.

> BTW: Can have something similar for Path as well? If yes it would finally be
> possible to emulate Java2D's geometric package with Circle2D, Recangele2D
> and so on what is currently a major benefit over using SWT...

Unfortunately, Path to native conversion is potentially much more expensive than Transform or Color. Converting every time a Path is drawn could be expensive. Caching the native path transparently raises the problem of invalidation.

So, not impossible and probably desirable, but not easily achieved. BTW if you like Java2D it's probably not that hard to make it draw to an in-memory surface of SWT Image.
Comment 6 Christoph Laeubrich CLA 2021-03-22 06:32:20 EDT
(In reply to Nikita Nemkin from comment #5)
> This one is tricky. I'm not sure if having both is desirable (API bloat and
> illusion of precision).
> Cairo and CoreGraphics do use double in their API, but GDI+ and Direct2D use
> float. The trend is towards float, because of GPU acceleration.

While the final matrix might only have float precision the intermediate operations could benefit from double precision. And as the matrix is internally stored as double it makes sense to offer such methods, the float methods can simply delegate to the double ones.

> Moreover, most SWT GC methods lack even float variants, let alone double.

One needs to start at some point... For example in my data model there are all doubles, I need to cast them to float all the time. With the new code I cast my double to float just for the transform internally convert to double again...

> Unfortunately, Path to native conversion is potentially much more expensive
> than Transform or Color. Converting every time a Path is drawn could be
> expensive. Caching the native path transparently raises the problem of
> invalidation.

I would think of the following: If a Path is created with a Device it uses that to cache the native path (and creator of such a path needs to call dispose).

> Converting every time a Path is drawn could be expensive

I can remember of nearly no case where I was actually able to reuse a path... 

1) as Path objects needs to be disposed  and there is no "PathManager" caching them is a real PITA
2) a path can not be reset / modified so I can't reuse the same instance for different operations

so usually I create a path, draw it and dispose it.
Comment 7 Lars Vogel CLA 2021-03-30 08:26:23 EDT
Please add to N&N.
Comment 8 Romain Bioteau CLA 2021-06-24 09:29:40 EDT
I think this change has introduced a regression in 4.20 on Windows with org.eclipse.swt.internal.deviceZoom=200

I have a RCP that uses GMF, and when I want to draw a gradient somewhere on my diagram, the coordinate are messed up.

After digging a little, I saw that to draw the gradient I use a org.eclipse.swt.graphics.Pattern which uses a transformation and this change (https://github.com/eclipse/eclipse.platform.swt/commit/b50f25cf21afe45c8699f4c4ed1878792d69bb8f#diff-123cdea57a765f8a9bfcbf420155fae82a328a463a11862df704f5e5badb33e6) seems to be a good candidate.
Comment 9 Phil Beauvoir CLA 2021-07-28 14:34:13 EDT
Created attachment 286843 [details]
Screenshot of wrong figure placement

Sorry, but this change has completely broken our RCP app, Archi[0] on Windows at 200% scaling.

Our app uses Draw2D[1] figures to create diagrams and since Eclipse 4.20 M1 the figures are drawn incorrectly on Windows 200% scaling.

Mac is OK, but I haven't tested on Linux at 200% scaling yet.

We need to update our app to use Eclipse 4.20 in order to support the latest fixes for Eclipse and support of Mac ARM64 so we would appreciate if this could either be patched or rolled back.

Attached is a screenshot of how an example diagram looks.

[0] https://www.archimatetool.com/
[1] Draw2D is also the foundation of other Eclipse frameworks such as GMF and Sirius. There are several RCP apps that use Draw2D as well as Archi (Modelio, Obeo.)
Comment 10 Phil Beauvoir CLA 2021-07-28 14:35:31 EDT
Created attachment 286844 [details]
Screenshot of correct image

This is a screenshot of how the diagram should look using Eclipse 4.19.
Comment 11 Nikita Nemkin CLA 2021-07-29 01:17:57 EDT
Hi Phil,

Does it work normally on Windows at 100% scale?
Comment 12 Phil Beauvoir CLA 2021-07-29 01:42:14 EDT
(In reply to Nikita Nemkin from comment #11)
> Hi Phil,
> 
> Does it work normally on Windows at 100% scale?

Hi Nikita, yes it does. Also, Linux 200% seems to be OK. It only seems to be Windows 200%.

You can also see this in the Ecore Diagram Editor (based on Eclipse Sirius) in Eclipse 4.20 itself if an Ecore diagram has a container object.

There is also lots of cheese when working in the diagram.
Comment 13 Phil Beauvoir CLA 2021-07-29 01:44:34 EDT
Created attachment 286851 [details]
Screenshot of Ecore Editor in Windows 200%

Here's a screenshot of part of an Ecore diagram. The yellow part and the grey part should be aligned.
Comment 14 Phil Beauvoir CLA 2021-07-29 01:50:30 EDT
Just a note to explain how to test on Windows at 200% scaling if one doesn't have a hi-res monitor.

1. Right-click Desktop and select "Display Settings"
2. Click the "Advanced scaling settings" link in the "Scale and layout" section
3. Enter a custom scaling size of 200% and click "Apply"
4. Select "Sign out now" and log back in to Windows

Everything in Windows will now be massive but it's possible to do some tests at 200% scaling.
Comment 15 Thomas Wolf CLA 2021-07-29 03:03:13 EDT
I suspect bug 574167 (on Mac, OS X 10.14.6) may also be caused by this.
Comment 16 Phil Beauvoir CLA 2021-07-30 06:41:39 EDT
Created attachment 286860 [details]
Screenshot of Eclipse BPMN2 diagrams at 100% and 200% on Windows

Attached is a combined image of two screenshots of a diagram created with the Eclipse BPMN2 editor. On the left is a screenshot taken at Windows 100% and on the right is one taken at Windows 200%.

I've ringed in red the text which is displaced.

There are other artefacts that appear when using Windows at 200%, but this is a good example.
Comment 17 Nikita Nemkin CLA 2021-07-30 06:53:18 EDT
I'm working on it.
Comment 18 Phil Beauvoir CLA 2021-07-30 06:54:45 EDT
(In reply to Nikita Nemkin from comment #17)
> I'm working on it.

Thanks, Nikita. My last comment was not intended to hurry things, I just thought it might help as an example. :-)
Comment 19 Phil Beauvoir CLA 2021-08-11 04:43:17 EDT
Hi,

(without wanting to sound impatient ;-) ) do you think this will be fixed for 4.21?

Regards,

Phil
Comment 20 Eclipse Genie CLA 2021-08-11 05:35:25 EDT
New Gerrit change created: https://git.eclipse.org/r/c/platform/eclipse.platform.swt/+/183886
Comment 22 Nikita Nemkin CLA 2021-08-11 06:00:39 EDT
(In reply to Phil Beauvoir from comment #19)
> Hi,
> 
> (without wanting to sound impatient ;-) ) do you think this will be fixed
> for 4.21?

Yes, I've merged a fix. It's a major regression and has to be fixed for 4.21.

BTW to test scaling on Windows, it's sufficient to set a property -Dswt.autoScale=200. For GTK there's an environment variable GTK_SCALE=2 and macOS port doesn't use manual scaling.
Comment 23 Phil Beauvoir CLA 2021-08-11 07:48:40 EDT
(In reply to Nikita Nemkin from comment #22)
> (In reply to Phil Beauvoir from comment #19)
> > Hi,
> > 
> > (without wanting to sound impatient ;-) ) do you think this will be fixed
> > for 4.21?
> 
> Yes, I've merged a fix. It's a major regression and has to be fixed for 4.21.
> 
> BTW to test scaling on Windows, it's sufficient to set a property
> -Dswt.autoScale=200. For GTK there's an environment variable GTK_SCALE=2 and
> macOS port doesn't use manual scaling.

This is wonderful! Thanks for this, and the autoScale setting will save me a lot of time. :-)

I'll test on the next I-build.
Comment 24 Phil Beauvoir CLA 2021-08-12 02:10:30 EDT
Hi Nikita,

I tested with eclipse-SDK-I20210811-1800-win32-x86_64 and it all looks good on Windows at 200% scaling.

Many thanks!

Phil
Comment 25 Phil Beauvoir CLA 2021-08-15 07:22:13 EDT
(In reply to Nikita Nemkin from comment #22)

> BTW to test scaling on Windows, it's sufficient to set a property
> -Dswt.autoScale=200. For GTK there's an environment variable GTK_SCALE=2 and
> macOS port doesn't use manual scaling.

(I found that the setting for GTK is actually GDK_SCALE=2. Just noting it here in case anyone else wants to use it.)
Comment 26 Phil Beauvoir CLA 2021-08-18 13:55:11 EDT
Hi Nikita,

can we re-open this, there's still a big problem on Mac.

I've tested more on Mac and diagrams are not being drawn properly when the drawing viewport area needs to be scrolled.

I need to narrow things down a bit more, but maybe there's something obvious in your code for Mac to do with transform?
Comment 27 Phil Beauvoir CLA 2021-08-18 14:52:33 EDT
Hi Nikita, I can confirm this is a regression with the latest fix as I'm not seeing the problem on Mac Retina when building Archi with Eclipse I20210809-1800.

The problem occurs on Mac with retina screen (200% scaling) and, in fact, can be seen when using a non-retina screen with the argument -Dswt.autoScale=200.

In Archi, when a diagram takes up more space than the viewport and scroll bars are required, figures are drawn incorrectly. I can create some screenshots if needed but looking at your recent fix I wonder if DPIUtil.autoScaleUp and DPIUtil.autoScaleDown should not be called if on Mac Retina?

Regards,

Phil
Comment 28 Phil Beauvoir CLA 2021-08-19 03:17:12 EDT
Created attachment 286971 [details]
Screenshot of Eclipse BPMN Editor

To see the problem in Eclipse:

1. Install latest Eclipse I build for Mac
2. Install the Eclipse BPMN2 diagram editor and create a Collaboration diagram with Pools and Swimlanes
3. Resize the diagram viewport area so scroll bars are used
4. Scroll around the diagram and add/move new components
Comment 29 Nikita Nemkin CLA 2021-08-20 02:30:07 EDT
DPIUtil.autoScaleUp should have no effect on retina screen, I'll re-check it.
Comment 30 Phil Beauvoir CLA 2021-08-20 03:52:13 EDT
(In reply to Nikita Nemkin from comment #29)
> DPIUtil.autoScaleUp should have no effect on retina screen, I'll re-check it.

Thanks.

As I trace through the org.eclipse.swt.graphics.Transform code on Mac retina I am seeing doubled values returned for DPIUtil.autoScaleUp() in the translate(float offsetX, float offsetY) method.
Comment 31 Phil Beauvoir CLA 2021-08-20 04:16:27 EDT
I tested some more on Linux, Windows and Mac.

On Linux 200% scale, DPIUtil#getScalingFactor returns 1 so DPIUtil.autoScaleXX() has no effect.

On Windows 200% scale, DPIUtil#getScalingFactor returns 2 so DPIUtil.autoScaleXX() has desired affect, and so the recent patch is correct.

On Mac Retina, DPIUtil#getScalingFactor returns 2 so DPIUtil.autoScaleXX() has undesired affect.
Comment 32 Phil Beauvoir CLA 2021-08-20 06:39:50 EDT
Here's a Snippet that demonstrates the problem:

https://git.eclipse.org/c/platform/eclipse.platform.swt.git/tree/examples/org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet10.java

The "SWT" text should be inside the red oval.
Comment 33 Niraj Modi CLA 2021-08-20 07:55:54 EDT
Moving out of M3, please re-target as required.
Comment 34 Phil Beauvoir CLA 2021-08-23 02:11:35 EDT
Created attachment 286985 [details]
Transform.java patch

Attached is a version of Transform.java that has two new methods:

float autoScaleUp(Drawable drawable, float size) {
    return "cocoa".equals(SWT.getPlatform()) ? size : DPIUtil.autoScaleUp(drawable, size);
}

float autoScaleDown(Drawable drawable, float size) {
    return "cocoa".equals(SWT.getPlatform()) ? size : DPIUtil.autoScaleDown(drawable, size);
}

These are called in place of all original occurrences of DPIUtil#autoScaleXX() so that the DPIUtil.autoScaleXX() methods are ignored on Mac.

It seems that DPIUtil#autoScaleXX() is only needed for Windows at 200%. Linux ignores it because DPIUtil#getScalingFactor returns 1.

I've tested on all platforms at 100% and 200% scale.

I don't know whether you already had a better patch lined up?

BTW - your simplification of the Transform code from what it was is quite impressive. :-)
Comment 35 Andrey Loskutov CLA 2021-08-23 06:54:07 EDT
(In reply to Phil Beauvoir from comment #32)
> Here's a Snippet that demonstrates the problem:
> 
> https://git.eclipse.org/c/platform/eclipse.platform.swt.git/tree/examples/
> org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet10.java
> 
> The "SWT" text should be inside the red oval.

@Simeon: please check on Linux too.

@Phil: could you please provide a summary which platform is how broken at which resolution at current master?

Breaking Transform is bad, this is basic functionality.

We should consider a fix for RC1 or a revert of *all* changes. 
An "enhancement request" shouldn't break the functionality it tries to improve.
Comment 36 Phil Beauvoir CLA 2021-08-23 07:00:23 EDT
Andrey,

Originally it was broken on Windows at 200% and working on Mac and Linux at 100 % and 200%.

Nikita's recent patch fixed the Windows 200% issue but now not working on Mac 200% (retina display).

I have been testing with SWT diagrams in our RCP app, Archi, also the Eclipse BPMN2 editor and the Eclipse Ecore Editor.

There may be other problems that I have not discovered, such as https://bugs.eclipse.org/bugs/show_bug.cgi?id=575398#c12

Phil
Comment 37 Thomas Wolf CLA 2021-08-23 07:02:22 EDT
See also comment 15.
Comment 38 Rolf Theunissen CLA 2021-08-23 07:27:55 EDT
I found another problem on windows, while working on Bug 575398.

The following code does not render the close button in CTabFolderRenderer, when using a 45 degree rotation, while e.g. 44 degrees works.

private void drawCloseLines(GC gc, int x, int y, int lineLength, boolean hot) {
  gc.setLineWidth(1);
  if (hot) {
    gc.setLineWidth(gc.getLineWidth() + 1);
    gc.setForeground(getFillColor());
  }

  Transform transform = new Transform(gc.getDevice());
  transform.translate(x, y);
  transform.rotate(45); /* Rotating by 44 degrees works */
  gc.setTransform(transform);

  int ll = (lineLength )/2;
  gc.drawLine(-ll, 0, ll, 0);
  gc.drawLine(0, -ll, 0, ll);
}
Comment 39 Simeon Andreev CLA 2021-08-23 08:03:56 EDT
(In reply to Andrey Loskutov from comment #35)
> (In reply to Phil Beauvoir from comment #32)
> > Here's a Snippet that demonstrates the problem:
> > 
> > https://git.eclipse.org/c/platform/eclipse.platform.swt.git/tree/examples/
> > org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet10.java
> > 
> > The "SWT" text should be inside the red oval.
> 
> @Simeon: please check on Linux too.

Snippet10.java works fine (text is in the oval).

With GTK_SCALE=2 I see no change.

With GDK_SCALE=2 I see the shell is twice as large, and the snippet is still fine (I assume this is expected behaviour).

How do I set DPI to 200%? I'm not familiar with that unfortunately. Is it some KDE setting?

Snippets that use Transform that I find are:

Snippet10.java
Snippet207.java
Snippet279.java
Snippet298.java
Snippet353.java
Snippet361.java

I've compared with this build (that doesn't have the changes here):

Eclipse SDK
Version: 2020-12 (4.18)
Build id: I20201103-0030

Snippet361 allows rotating/translating any image, but its behaviour is weird both bfor 4.18 and 4.21. So I assume no change there.

I also checked the manual test snippets that have Transform (we added them some time ago):

Bug531667_GC_transform_is_wrong
Bug545226_GC_getClipping_is_wrong

Same, I see no regression when comparing 4.18 and 4.21.
Comment 40 Phil Beauvoir CLA 2021-08-23 08:46:36 EDT
I tested the above Snippets on Mac retina (200% scaling). The following render incorrectly:

Snippet10.java
Snippet279.java
Snippet298.java

The following render correctly:

Snippet207.java
Snippet353.java


Snippet361.java doesn't use SWT Transform it uses AWT AffineTransform so we can discount this one.
Comment 41 Phil Beauvoir CLA 2021-08-23 13:18:08 EDT
(In reply to Simeon Andreev from comment #39)
> (In reply to Andrey Loskutov from comment #35)
> > (In reply to Phil Beauvoir from comment #32)
> > > Here's a Snippet that demonstrates the problem:
> > > 
> > > https://git.eclipse.org/c/platform/eclipse.platform.swt.git/tree/examples/
> > > org.eclipse.swt.snippets/src/org/eclipse/swt/snippets/Snippet10.java
> > > 
> > > The "SWT" text should be inside the red oval.
> > 
> > @Simeon: please check on Linux too.
> 
> Snippet10.java works fine (text is in the oval).
> 
> With GTK_SCALE=2 I see no change.
> 
> With GDK_SCALE=2 I see the shell is twice as large, and the snippet is still
> fine (I assume this is expected behaviour).
> 
> How do I set DPI to 200%? I'm not familiar with that unfortunately. Is it
> some KDE setting?
> 

You need GDK_SCALE=2. On a non hi-dpi monitor it will make everything twice as large.

I have tested on Linux on hi-res monitor at 200% scale but, as I mentioned, above the current Transform problems really affect Mac at 200% (and perhaps Rolf's issue).
Comment 42 Eclipse Genie CLA 2021-08-24 02:29:41 EDT
New Gerrit change created: https://git.eclipse.org/r/c/platform/eclipse.platform.swt/+/184342
Comment 43 Nikita Nemkin CLA 2021-08-24 02:30:36 EDT
I'm reverting the Transform change for RC1.
Comment 45 Niraj Modi CLA 2021-08-27 02:25:43 EDT
Moving to 4.22
Comment 46 Niraj Modi CLA 2022-03-04 00:01:54 EST
Moving out of 4.23