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

Fixed Program Icon Scaling for Multi Zoom #1709

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

amartya4256
Copy link
Contributor

@amartya4256 amartya4256 commented Jan 7, 2025

In the previous implementation, according to the documentation, SHGetFileInfo retrieves a system icon at the primary monitor native zoom. It means if the primary monitor is 175%, the dimension of the icon will be 56 x 56 (considering the standard dimension of 16 x 16 at 100%). Previously, the Image::win32_new was used to create an image object by passing the handle. Since the support of multi zoom, we know that now an image can have multiple handles, each for a zoom level. Image::win32_new used to assign the handle to the image at DPIUtil::getDeviceZoom regarless of what zoom level the handle was created for (in our case primary monitor native zoom, e.g. 175%). And it used to do some calcultation what proportion of primary monitor zoom would be this assigned zoom of the image. In other words, if you wanna obtain an image for 100% zoom, it will be 57% of 175%. Since, it used to call image.getImageData(57), which kinda seems like a hack to obtain the icon with the right dimension.

Another problem that was quite visible was that if the monitor to draw the icon has a higher zoom level (say 300%) than the primary monitor zoom, the icon will be pixelated because the retrieved icon from SHGetFileInfo is 175% (primary montior native zoom)

This contribution reimplements the logic for scaling the Program Icons while getting rid of the DPIUtil::getDeviceZoom usage and enhancing the image quality of icons on scaling up using the Small Icon in case we have to scale down and using the Large Icon in case we have to scale up.

contributes to #62 and #127

Note: Only the last commit belongs to this PR and this PR should not be merged before #1713

Copy link
Contributor

github-actions bot commented Jan 7, 2025

Test Results

   486 files  ±0     486 suites  ±0   9m 43s ⏱️ -8s
 4 308 tests +1   4 295 ✅ +1   13 💤 ±0  0 ❌ ±0 
16 413 runs  +1  16 305 ✅ +1  108 💤 ±0  0 ❌ ±0 

Results for commit 2b5e970. ± Comparison against base commit d7febc4.

♻️ This comment has been updated with latest results.

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.

The code looks good to me. If I understand everything correctly, the change to Program makes total sense and the implementaton is far more clean and reasonable with the change than it was before.
I currently only have one comment regarding a change to Image, as from my understanding that change indicates an existing bug, independent from the changes to program icons, so I would propose to extract that one into a dedicated PR for that specific issue.

I have not tested the changes so far, but will do that as soon as possible.

Comment on lines 1365 to +1368
if (isDisposed()) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
int currentZoom = getZoom();
if (zoom == currentZoom) {
return getImageDataAtCurrentZoom();
} else if (imageProvider != null) {
if (zoomLevelToImageHandle.get(zoom) != null) {
return zoomLevelToImageHandle.get(zoom).getImageData();
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Isn't this something was wrong wrong anyway, independent from Program icons? Querying the image data for specific zoom value should not consider any autoscaling-value-based correction of that zoom value anyway, should it? So I think this change should be extracted into a separate PR with an according regression test, e.g., for autoscaling integer200 retrieving image data for zoom 125 and 150 one after another and assuming that they do not deliver the same image data.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have adjusted the PR as per requested. Here's the PR for the Image::getImageData fix: #1713

@amartya4256 amartya4256 force-pushed the program_icon_scaling branch 2 times, most recently from 66f1c89 to 8fecf0b Compare January 9, 2025 15:04
This contribution helps retrieve the imageData for the
requested zoom by searching for the zoom in the zoomToHandleMap
followed by (if not available) scaling the handle at the zoom nearest to
it while getting rid of only searching among the autoscaled zoom values.

Contributes to eclipse-platform#62 and eclipse-platform#127
This contribution reimplements the logic for scaling the Program Icons
while getting rid of the DPIUtil::getDeviceZoom usage and enhancing the image
quality of icons on scaling up.

contributes to eclipse-platform#62 and eclipse-platform#127
@amartya4256 amartya4256 force-pushed the program_icon_scaling branch from 8fecf0b to 2b5e970 Compare January 9, 2025 15:14
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've now also tested the change and have some findings. Some are expected and unavoidable with the current type of implementation whereas at least seems to be a regression.

Expected Limitations

Since the used Windows API methods return icons scaled according to the primary monitor, you will often have two scalings applied: first by Windows scaling one of the original 16x16, 32x32, ... icons to what is required for the zoom level of the primary monitor, and second, by the application to use it in the scaling required for the monitor the window is currently placed on.

This means for example means if your primary monitor has a rather high resolution (e.g., scaled at 200% or more), the icons for other, lower resolution monitors (e.g., at 100%) are scaled down dramatically, leading to information loss. E.g., at 200% primary zoom the large icon is loaded and scaled down to 100% for a 100% secondary monitor:
image

It even looks bad if you have an "ordinary" 100% monitor but the primary monitor has, e.g., 150% scaling on the 100%, for which you would expect the original 100% icons to be loaded:
image

Regression

Environment:

  • Single monitor sufficient
  • Primary monitor scaling 150%
  • Auto scale mode quarter

Original appearance:
image

Appearance with this PR:
image

You can see the information, in particular in the icons for PowerPoint and Excel documents. They become hardly comprehensible.
The reason is that the package explorer loads 200% images, thus making the new implementation retrieve the large icon, which is delivered at 300% (two times the native zoom) and then for final rendering scaled down to 150%.

Note that this effect was also covered in #1014. The following code has been used there to determine when to use large icons (note that comment and implementation are not aligned):

// Use small icon if expected icon size is less than 150% of delivered icon size
// and use large icon if it is more than 150% of the delivered icon size
boolean useLargeIcon = 100 * zoom /  primaryMonitorZoom > 200;

Maybe that's something to reuse.

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.

Improve dynamic scaling of external Program icons
2 participants