Skip to content

[win32] Choose best Image handle drawing with GC #2138

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

Conversation

akoch-yatta
Copy link
Contributor

This commit adapts the drawImage method in GC in the windows implementation for copying and (probably) scaling an area from a source image into the GC target. With the Image supporting multiple handles now, the handle from the source image is no longer always chosen by the zoom context of the GC but sometimes from the target size, e.g. if an image should be drawn with a scale of 2 on a 100% monitor, it might provide better results to use an image handle fitting for 200%.

How to test

If you execute the Snippet below with and without the PR you should see something like below: left with this PR and right without this PR. Top row is simulating a GC on 100%, bottom row on 200% zoom. Scale factors for each of each of the three images are 1, 1.5 and 2, so100%, 150% and 200% on top and 200%, 300% and 400% in the bottom. Most images will remain as they were before, but you see a difference in the top row, image to the right. This PR proposes a simple first approach to improve drawing scaled variants of an Image with a GC. Testing another approach in #2134 had some disadvantages, that led us to the decision, to start with a rather simple approach and extend on that.

image

package org.eclipse.swt.snippets;

import org.eclipse.swt.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;

public class Snippet384 {
	private static final String IMAGE_100 = "eclipse16.png";
	private static final String IMAGE_200 = "eclipse32.png";
	private static final String IMAGES_ROOT = "bin/org/eclipse/swt/snippets/";

	private static final String IMAGE_PATH_100 = IMAGES_ROOT + IMAGE_100;
	private static final String IMAGE_PATH_200 = IMAGES_ROOT + IMAGE_200;

	public static void main (String [] args) {
		final ImageFileNameProvider filenameProvider = zoom -> {
			switch (zoom) {
			case 100:
				return IMAGE_PATH_100;
			case 200:
				return IMAGE_PATH_200;
			default:
				return null;
			}
		};

		final Display display = new Display ();

		final Image imageWithFileNameProvider = new Image (display, filenameProvider);

		final Shell shell = new Shell (display);
		shell.setText("Snippet384");
		shell.setLayout (new GridLayout (3, false));
		Listener l = new Listener() {
			@Override
			public void handleEvent(Event e)  {
				if (e.type == SWT.Paint) {
					GC mainGC = e.gc;
					GCData gcData = mainGC.getGCData();

					try {
						int baseY = 50;
						int itemCount = 1;
						gcData.nativeZoom = 100;
						drawText(mainGC, gcData,"--ImageFileNameProvider 100%--", baseY*itemCount++);
						drawImages(mainGC, gcData, "Normal",baseY*itemCount++, imageWithFileNameProvider);

						gcData.nativeZoom = 200;
						drawText(mainGC, gcData,"--ImageFileNameProvider 200%--", baseY*itemCount++);
						drawImages(mainGC, gcData, "Normal",baseY*itemCount++, imageWithFileNameProvider);
					} finally {
						mainGC.dispose ();
					}
				}
			}

			private void drawText(GC mainGC, GCData gcData, String text, int y) {
				mainGC.drawText(text, 20, y);
			}

			private void drawImages(GC mainGC, GCData gcData, String text, int y, final Image image) {
				drawImages(mainGC, 50, y, image, 1f);
				drawImages(mainGC, 100, y, image, 1.5f);
				drawImages(mainGC, 150, y, image, 2f);
			}

			private void drawImages(GC mainGC, int x,  int y, final Image image, float factor) {
				int width = image.getBounds().width;
				int height = image.getBounds().height;
				int scaledWidth = Math.round(width*factor);
				int scaledHeight = Math.round(height*factor);
				mainGC.drawImage(image, 0, 0, width, height, x, y, scaledWidth, scaledHeight);
			}
		};
		shell.addListener(SWT.Paint, l);

		shell.setSize(400, 750);
		shell.open ();
		while (!shell.isDisposed ()) {
			if (!display.readAndDispatch ()) display.sleep ();
		}
		display.dispose ();
	}
}

Copy link
Contributor

github-actions bot commented May 9, 2025

Test Results

   545 files  ±0     545 suites  ±0   36m 0s ⏱️ + 3m 1s
 4 377 tests ±0   4 359 ✅ ±0   18 💤 ±0  0 ❌ ±0 
16 647 runs  ±0  16 506 ✅ ±0  141 💤 ±0  0 ❌ ±0 

Results for commit 00a867e. ± Comparison against base commit 0642bb4.

♻️ This comment has been updated with latest results.

@akoch-yatta akoch-yatta force-pushed the win32-gc-draw-image-better-handle-check branch 2 times, most recently from 19c4313 to 0620de6 Compare May 12, 2025 09:51
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 change looks sound to me and is a nice improvement for the rendering of images that are scaled by the GC.

I also tested the monitor-aware capability (using Image rescaling for monitor zooms) and found it to be working nicely. I tested at 150% monitor zoom and the second image in the top row then also has improved quality (compared to the screenshot in the original post as found at 100% monitor zoom) as that image's zoom then fits with monitor zoom:
image

@akoch-yatta akoch-yatta force-pushed the win32-gc-draw-image-better-handle-check branch from 0620de6 to e18ff63 Compare May 13, 2025 05:38
This commit adapts the drawImage method in GC in the windows
implementation for copying and (probably) scaling an area from a source
image into the GC target. With the Image supporting multiple handles now,
the handle from the source image is no longer chosen by the zoom context
of the GC but from the target size, e.g. if an image should be drawn
with a scale of 2 on a 100% monitor, it might provide better results to
use an image handle fitting for 200%.
@HeikoKlare HeikoKlare force-pushed the win32-gc-draw-image-better-handle-check branch from e18ff63 to 00a867e Compare May 13, 2025 08:04
@HeikoKlare HeikoKlare merged commit 63048a2 into eclipse-platform:master May 13, 2025
17 checks passed
@HeikoKlare HeikoKlare deleted the win32-gc-draw-image-better-handle-check branch May 13, 2025 08:19
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.

2 participants