Skip to content

Conversation

@al-noori
Copy link
Contributor

@al-noori al-noori commented Jan 6, 2026

If a transform is applied via the GC, then both drawImage APIs consider now the best fitting handle by requesting it through the width/height of the full image scaled by the scaleFactor (relating destination width/height to source width/height) times the width/height scaling induced by the transformation.

Note that only the second commit is relevant for the PR. The first one references to the changes made in #2913.

To easily see and test, use the following snippet:

package org.eclipse.swt.snippets;

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

public class Snippet389 {

public static void main (String [] args) {
	Display display = new Display ();
	Shell shell = new Shell(display);
	shell.setText("Snippet 389");
	ImageFileNameProvider fileNameProvider = zoom -> {
		if (zoom == 200) {
			return "src/org/eclipse/swt/snippets/eclipse32.png";
		} else if (zoom == 100) {
			return "src/org/eclipse/swt/snippets/eclipse16.png";
		}
		return null;
	};
	Image image = new Image(display, fileNameProvider);
	shell.addPaintListener(e -> {
		e.gc.drawImage(image, 0, 0, 32, 32);
		e.gc.drawImage(image, 0, 0, 16, 16, 0, 50, 32, 32);
	});

	shell.addPaintListener(e -> {
		e.gc.setTransform(new Transform(display, 2, 0, 0, 2, 0, 0));
		e.gc.drawImage(image, 25, 0, 16, 16);
		e.gc.drawImage(image, 0, 0, 16, 16, 25, 25, 16, 16);
		e.gc.setTransform(null);
	});

	shell.open ();

	while (!shell.isDisposed ()) {
		if (!display.readAndDispatch ()) display.sleep ();
	}
	display.dispose ();
}
}

Below are screenshots of the snippet on a 100% zoom.

Before:
Before

After:
After

@github-actions
Copy link
Contributor

github-actions bot commented Jan 6, 2026

Test Results (win32)

   34 files  ±0     34 suites  ±0   5m 7s ⏱️ +5s
4 632 tests ±0  4 559 ✅ ±0  73 💤 ±0  0 ❌ ±0 
  167 runs  ±0    164 ✅ ±0   3 💤 ±0  0 ❌ ±0 

Results for commit f9c3b63. ± Comparison against base commit 9602bf0.

♻️ This comment has been updated with latest results.

@arunjose696
Copy link
Contributor

Have tested the changes myself and can see it fixes the said issue.

@al-noori al-noori force-pushed the al-noori/FixDrawImageWithTransform branch 4 times, most recently from 7b86aef to aad59b7 Compare January 9, 2026 13:47
The GC#drawImage method takes
(image, srcX, srcY, srcWidth, srcHeight, destX, destY, destWidth, destHeight)
as arguments and crops and scales from the source region to the destination
region.

Passing an image drawn via ImageGCDrawer led to the following issue:

The image handle from the subcall is resolved using the monitor zoom
(data.nativeZoom) and the calculated scaledImageZoom (gcZoom * scaleFactor).
This handle corresponds to an ImageData initialized at scaledImageZoom,
whereas the drawings of the second GC are performed using the monitor zoom,
subject to the auto-scale property.

This mismatch results in unaligned sizing of drawings. For example, a 200%
monitor zoom combined with a scale factor of 0.5 produces a scaledImageZoom of
100%. As a result, the ImageData is initialized at 100%, while drawing occurs
at 200%. This exact case is demonstrated in
vi-eclipse/Eclipse-Platform#554
.

Furthermore, the calculation of scaledImageZoom uses fallback logic that only
allows 100% and 200% as possible outcomes, which is clearly unintended in this
context.

The fix delegates resolving the correct handle to the Image class by passing
the width/height of the full image scaled by the scaledImageZoom. This
is a space on where scaled src coordinates/width/height lie. A callback
then creates a new handle for the height/width and respects the auto-scale property.

If the returned handle matches the full image scaled to the requested
scaledImageZoom in width and height, the source region
coordinates/width/height are passed directly in pixels at that zoom. Otherwise,
the internal zoom factor is derived from the returned handle’s width relative to
the full image, and the source region coordinates are converted to pixel values
using this internal zoom.
@al-noori al-noori force-pushed the al-noori/FixDrawImageWithTransform branch from aad59b7 to 9e29da0 Compare January 9, 2026 13:53
If a transform is applied via the GC, then both drawImage
APIs consider now the best fitting handle by requesting it through the
width/height of the full image scaled by the scaleFactor (relating
destination width/height to source winowdth/height) times the width/height scaling induced by the transformation.
@al-noori al-noori force-pushed the al-noori/FixDrawImageWithTransform branch from 9e29da0 to f9c3b63 Compare January 9, 2026 14:13
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.

GC#drawImage() does not consider applied Transform when selecting best-fitting image source

2 participants