eclipse.platform.swt icon indicating copy to clipboard operation
eclipse.platform.swt copied to clipboard

[win32] Choose best Image handle drawing with GC

Open akoch-yatta opened this issue 7 months ago • 1 comments

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 ();
	}
}

akoch-yatta avatar May 09 '25 11:05 akoch-yatta

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 00a867e8. ± Comparison against base commit 0642bb40.

:recycle: This comment has been updated with latest results.

github-actions[bot] avatar May 09 '25 11:05 github-actions[bot]