Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[win32] Refactor path to support multiple handles #1856

Merged
merged 1 commit into from
Mar 7, 2025

Conversation

akoch-yatta
Copy link
Contributor

This PR refactors Path in the win32 implementation to better support multiple handles for different zoom settings of a Path when monitor-specific scaling is enables. The previous implementation only applied adaptions on the path to the initial handle and relied on the path not to be changed after usage. This doesn't cover all scenarios and can lead to incompletely rendered path when reusing Path object over different zoom settings.

How to test

You can test this adaption with the new "Path Re-usage"-Tab in the GraphicsExample. You need to:

  1. Set up at least two monitors with different zoom, e.g. 100% and 200%
  2. Start the GraphicsExample with additonal VM arguments:
-Dswt.autoScale.updateOnRuntime=true
-Dswt.autoScale=quarter
  1. Move to the "Path Re-usage"-Tab, play around with the buttons and switch monitors in between. Without the changes in Path you will loose operations or don't see some off them on the monitors the Path was not created on.

Copy link
Contributor

github-actions bot commented Feb 25, 2025

Test Results

   505 files  ±0     505 suites  ±0   8m 7s ⏱️ -27s
 4 303 tests +1   4 291 ✅ +1   11 💤 ±0  1 ❌ ±0 
16 559 runs  +1  16 452 ✅ +1  106 💤 ±0  1 ❌ ±0 

For more details on these failures, see this check.

Results for commit b0e34fa. ± Comparison against base commit 523a5d4.

♻️ This comment has been updated with latest results.

@amartya4256
Copy link
Contributor

amartya4256 commented Mar 6, 2025

Design-wise, looks good to me. I would approve it. @HeikoKlare I would request you to test it out as well.

@HeikoKlare HeikoKlare force-pushed the win32-refactor-path branch from f2e3e81 to f3eb0e3 Compare March 6, 2025 13:36
Copy link
Contributor

@HeikoKlare HeikoKlare left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most of the changes look fine to me (see my comments for exception).
I am just wondering what the introduced operations are used for in Path: if I am not mistaken, the stored operations are not used anywhere. Each operation is directly applied to all present handles for all zooms and in case a new handle for a new zoom is created, the existing logic via passing the PathData is used.

Gdip.GraphicsPath_AddPath(getHandle(initialZoom), path.getHandle(initialZoom), false);
currentPoint.X = path.currentPoint.X;
currentPoint.Y = path.currentPoint.Y;
this.operations.addAll(path.operations);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it correct to remove the original code here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Almost. I just missed to apply the new operation to add to the existing handles

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. We need to be aware that within the overall refactoring this is kind of a behavioral change. Of course the result should be the same, but maybe using Gdip to add a path based on its handle and re-applying its original operations may result in (slightly) different result (for whatever reason). Still, I understand and agree that this is the right thing to do.

Copy link
Contributor Author

@akoch-yatta akoch-yatta Mar 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could do something different. More or less:

  • Cache the old operations
  • Recreate a path on demand
  • Use Gdip.GraphicsPath_AddPath(getHandle(initialZoom), newTempHandle, false);

This would be more or less the same as before, but a bit more complex to understand, I would say

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure whether we should do that since actually the new operation does exactly what you would expect it to do. I just wanted to mentioned that we might oversee something that eventually leads to derivations of behavior, so that we are aware this change. But I don't see why this might be anything else than minor changes in result because of limited precision of float values and different ways of applying the operations.

But I just checked out the tab you added to the GraphicsExample, which shows that the old and new implementation of addPath behave different. So we may need to revise this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh damn, you are right. There is a connecting path if you have done something before. That could probably be emulated be an additional move operation, but I would probably favor my approach above more

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for that back and forth. So for this PR I just moved the original logic into an Operation, because in this PR all operations are always applied immediately and no handles are created dynamically yet. I will need to adapt this new opearation in the follow-up PR

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's perfectly fine. It's just that we now have the problem of storing a Path that might be disposed when querying the handle for the encapsulating Path at another zoom level. So we probably need to clone the path to be stored?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, in this PR the new Path is created on its path data and then scaled. The operations are always applied immediately. But I added a test to ensure it doesn't break later

@akoch-yatta akoch-yatta force-pushed the win32-refactor-path branch from f3eb0e3 to 3fffd59 Compare March 6, 2025 15:09
@akoch-yatta
Copy link
Contributor Author

Most of the changes look fine to me (see my comments for exception). I am just wondering what the introduced operations are used for in Path: if I am not mistaken, the stored operations are not used anywhere. Each operation is directly applied to all present handles for all zooms and in case a new handle for a new zoom is created, the existing logic via passing the PathData is used.

They have a use now. The are used in Path::addPath. Without that, we would have needed them only in #1869, because there the handles are completly generated on demand using the operations

@HeikoKlare HeikoKlare force-pushed the win32-refactor-path branch from 3fffd59 to 9233c3c Compare March 6, 2025 15:33
@akoch-yatta akoch-yatta force-pushed the win32-refactor-path branch 2 times, most recently from b9ab37f to 82e393b Compare March 7, 2025 10:54
Copy link
Contributor

@HeikoKlare HeikoKlare left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comment :

It's just that we now have the problem of storing a Path that might be disposed when querying the handle for the encapsulating Path at another zoom level. So we probably need to clone the path to be stored?

@akoch-yatta
Copy link
Contributor Author

akoch-yatta commented Mar 7, 2025

See comment :

It's just that we now have the problem of storing a Path that might be disposed when querying the handle for the encapsulating Path at another zoom level. So we probably need to clone the path to be stored?

Just answered above at the same time 😄 It is not an issue in this PR. I will need to address that in the next one

Copy link
Contributor

@HeikoKlare HeikoKlare left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see. I missed that the operations are not stored (anymore) in this PR. Thanks for the clarification!

This commit refactors Path in the win32 implementation to better
support multiple handles for different zoom settings of a Path when
monitor-specific scaling is enabled. The previous implementation
only applied adaptions to the initial handle of the path and relied
on the path not to be changed afterwards. This doesn't cover all
scenarios and can lead to unexpected behavior when re-using Path
objects over different zoom settings.
@HeikoKlare HeikoKlare force-pushed the win32-refactor-path branch from 82e393b to b0e34fa Compare March 7, 2025 11:14
@HeikoKlare
Copy link
Contributor

Failing test is unrelated and documented: #1843

@HeikoKlare HeikoKlare merged commit 29bae82 into eclipse-platform:master Mar 7, 2025
12 of 14 checks passed
@HeikoKlare HeikoKlare deleted the win32-refactor-path branch March 7, 2025 13:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Refactor Path to use Operations for all manipulations
3 participants