Skip to content

[macOS] Consider transformation scale in GC.drawImage(image, x, y) #2919#3246

Draft
HeikoKlare wants to merge 1 commit intoeclipse-platform:masterfrom
HeikoKlare:cocoa-drawImage-transform-scale
Draft

[macOS] Consider transformation scale in GC.drawImage(image, x, y) #2919#3246
HeikoKlare wants to merge 1 commit intoeclipse-platform:masterfrom
HeikoKlare:cocoa-drawImage-transform-scale

Conversation

@HeikoKlare
Copy link
Copy Markdown
Contributor

Summary

This PR ports the transformation-scale-aware image drawing logic to Cocoa/macOS, following the same approach previously applied to Windows (e97143c) and currently being introduced for GTK in #3201.

Background

When a scaled Transform is set on a GC and drawImage(image, x, y) is called, SWT should select the best-fitting image representation (e.g. the high-resolution variant of an SVG-backed image) for the effective on-screen size — accounting for both the destination rectangle and the active transformation scale. Without this fix, the code ignores the transformation scale and passes only the nominal destination size to the image-selection logic, which causes a lower-resolution representation to be rendered and then upscaled, producing blurry results especially noticeable with SVG images.

Changes

bundles/org.eclipse.swt/Eclipse SWT/cocoa/org/eclipse/swt/graphics/GC.java

  • Added calculateTransformationScale() — extracts the effective scale factor from the active NSAffineTransform using Math.hypot() on the matrix columns (m11/m21 and m12/m22), which yields the correct scale even when the transform combines scaling with rotation.
  • Modified drawImage(Image, int, int) — when a non-null transform is active, delegates to drawImage(image, x, y, w, h) using the image's natural bounds, routing through the scale-aware path instead of the legacy simple path.
  • Modified drawImage(Image, int, int, int, int) — multiplies the destination dimensions by the transformation scale before passing them to executeOnImageAtSizeBestFittingSize(), ensuring the most appropriate image representation is loaded at the effective rendered resolution.

tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/Test_org_eclipse_swt_graphics_GC.java

  • Removed the @EnabledOnOs(OS.WINDOWS) guard (and now-unused EnabledOnOs/OS imports) from test_drawImageLorg_eclipse_swt_graphics_ImageIIII_withTransform — the test now runs on all platforms.
  • Added the missing @Test annotation to test_drawImageLorg_eclipse_swt_graphics_ImageIIII_withTransform_zeroTargetSize, which was previously never executed.

Both tests pass on macOS.

Relation to other PRs

⚠️ This PR is inspired by, built on top of, and must be merged after #3201.

PR #3201 introduces the equivalent fix for GTK and changes the test annotation from @EnabledOnOs(OS.WINDOWS) to @DisabledOnOs(OS.MAC). This PR removes the remaining OS restriction entirely, completing the cross-platform rollout. Merging this PR before #3201 would result in a trivially conflicting annotation change on the test method.

Test plan

  • test_drawImageLorg_eclipse_swt_graphics_ImageIIII_withTransform passes on macOS
  • test_drawImageLorg_eclipse_swt_graphics_ImageIIII_withTransform_zeroTargetSize passes on macOS
  • Verify visually that SVG images drawn via drawImage(image, x, y) under a scaled Transform render at full sharpness on macOS

This change was created with the assistance of Claude Code (Anthropic).

…lipse-platform#2919

With e97143c, support was added on
Windows to take the Transform scaling into consideration when calling
drawImage(image, x, y). Especially when used in combination with an
SVG-based image, this leads to better results as the best-fitting image
representation is used for painting, rather than relying on
interpolation.

This change follows the same logic for Cocoa/macOS, equivalent to what
has already been done for Windows and is being done for GTK in eclipse-platform#3201.

When a Transform is active on the GC, the call to drawImage(image, x, y)
is delegated to drawImage(image, x, y, w, h), using the image's natural
bounds as the destination size. Within that method, the destination
dimensions are multiplied by the effective transformation scale before
being passed to executeOnImageAtSizeBestFittingSize(), so that the
higher-resolution image representation is selected and rendered at its
full quality rather than being upscaled from a lower-resolution variant.

The effective scale is derived from the active NSAffineTransform via
Math.hypot() on the matrix columns, which correctly handles transforms
that combine scaling with rotation.

The existing test test_drawImageLorg_eclipse_swt_graphics_ImageIIII_withTransform,
which was previously restricted to Windows only, is now enabled on all
platforms (the @EnabledOnOs(OS.WINDOWS) guard and its now-unused imports
are removed). The previously un-annotated companion test
test_drawImageLorg_eclipse_swt_graphics_ImageIIII_withTransform_zeroTargetSize
receives the missing @test annotation so it is actually executed.

Contributes to
eclipse-platform#2919
@github-actions
Copy link
Copy Markdown
Contributor

Test Results

  174 files   -   8    174 suites   - 8   26m 36s ⏱️ -42s
4 628 tests  -  74  4 608 ✅  -  73   17 💤  -  4  3 ❌ +3 
6 555 runs   - 155  6 405 ✅  - 147  144 💤  - 14  6 ❌ +6 

For more details on these failures, see this check.

Results for commit a084b4b. ± Comparison against base commit 57fe5a5.

This pull request removes 76 and adds 2 tests. Note that renamed tests count towards both.
org.eclipse.swt.graphics.ImageWin32Tests ‑ testDisposeDrawnImageBeforeRequestingTargetForOtherZoom
org.eclipse.swt.graphics.ImageWin32Tests ‑ testDrawImageAtDifferentZooms(boolean)[1] true
org.eclipse.swt.graphics.ImageWin32Tests ‑ testDrawImageAtDifferentZooms(boolean)[2] false
org.eclipse.swt.graphics.ImageWin32Tests ‑ testImageDataForDifferentFractionalZoomsShouldBeDifferent
org.eclipse.swt.graphics.ImageWin32Tests ‑ testImageShouldHaveDimesionAsPerZoomLevel
org.eclipse.swt.graphics.ImageWin32Tests ‑ testRetrieveImageDataAtDifferentZooms(boolean)[1] true
org.eclipse.swt.graphics.ImageWin32Tests ‑ testRetrieveImageDataAtDifferentZooms(boolean)[2] false
org.eclipse.swt.graphics.ImageWin32Tests ‑ test_getImageData_fromCopiedImage
org.eclipse.swt.graphics.ImageWin32Tests ‑ test_getImageData_fromImageForImageDataFromImage
org.eclipse.swt.tests.gtk.Test_GtkConverter ‑ test_HeuristicASCII_dollarSign
…
org.eclipse.swt.tests.junit.AllNonBrowserTests ‑ Unknown test
org.eclipse.swt.tests.junit.Test_org_eclipse_swt_graphics_GC ‑ test_drawImageLorg_eclipse_swt_graphics_ImageIIII_withTransform_zeroTargetSize

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.

1 participant