Skip to content

Commit 12dc3a1

Browse files
committed
[macOS] Consider transformation scale in GC.drawImage(image, x, y) eclipse-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
1 parent 0c0c064 commit 12dc3a1

2 files changed

Lines changed: 23 additions & 5 deletions

File tree

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

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -281,6 +281,19 @@ static int checkStyle (int style) {
281281
return style & (SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT);
282282
}
283283

284+
private float calculateTransformationScale() {
285+
if (data.transform == null) {
286+
return 1.0f;
287+
}
288+
// this calculates the effective length in x and y
289+
// direction without being affected by the rotation
290+
// of the transformation
291+
NSAffineTransformStruct struct = data.transform.transformStruct();
292+
float scaleWidth = (float) Math.hypot(struct.m11, struct.m21);
293+
float scaleHeight = (float) Math.hypot(struct.m12, struct.m22);
294+
return Math.max(scaleWidth, scaleHeight);
295+
}
296+
284297
/**
285298
* Invokes platform specific functionality to allocate a new graphics context.
286299
* <p>
@@ -1143,7 +1156,12 @@ public void drawImage(Image image, int x, int y) {
11431156
if (handle == null) SWT.error(SWT.ERROR_GRAPHIC_DISPOSED);
11441157
if (image == null) SWT.error(SWT.ERROR_NULL_ARGUMENT);
11451158
if (image.isDisposed()) SWT.error(SWT.ERROR_INVALID_ARGUMENT);
1146-
drawImage(image, 0, 0, -1, -1, x, y, -1, -1, true);
1159+
if (data.transform != null) {
1160+
Rectangle imageBounds = image.getBounds();
1161+
drawImage(image, x, y, imageBounds.width, imageBounds.height);
1162+
} else {
1163+
drawImage(image, 0, 0, -1, -1, x, y, -1, -1, true);
1164+
}
11471165
}
11481166

11491167
/**
@@ -1238,9 +1256,12 @@ public void drawImage(Image image, int destX, int destY, int destWidth, int dest
12381256
if (image.isDisposed()) {
12391257
SWT.error(SWT.ERROR_INVALID_ARGUMENT);
12401258
}
1259+
float transformationScale = calculateTransformationScale();
1260+
int scaledWidth = Math.round(destWidth * transformationScale);
1261+
int scaledHeight = Math.round(destHeight * transformationScale);
12411262
image.executeOnImageAtSizeBestFittingSize(imageAtSize -> {
12421263
drawImage(imageAtSize, 0, 0, imageAtSize.width, imageAtSize.height, destX, destY, destWidth, destHeight, false);
1243-
}, destWidth, destHeight);
1264+
}, scaledWidth, scaledHeight);
12441265
}
12451266

12461267
void drawImage(Image srcImage, int srcX, int srcY, int srcWidth, int srcHeight, int destX, int destY, int destWidth, int destHeight, boolean simple) {

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

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,8 +58,6 @@
5858
import org.junit.jupiter.api.AfterEach;
5959
import org.junit.jupiter.api.BeforeEach;
6060
import org.junit.jupiter.api.Test;
61-
import org.junit.jupiter.api.condition.DisabledOnOs;
62-
import org.junit.jupiter.api.condition.OS;
6361
import org.junit.jupiter.params.ParameterizedTest;
6462
import org.junit.jupiter.params.provider.ValueSource;
6563

@@ -395,7 +393,6 @@ public void test_drawImageLorg_eclipse_swt_graphics_ImageIIII() {
395393
}
396394

397395
@Test
398-
@DisabledOnOs(OS.MAC)
399396
public void test_drawImageLorg_eclipse_swt_graphics_ImageIIII_withTransform() throws IOException {
400397
Image image = null;
401398
try (InputStream is = getClass().getResourceAsStream("collapseall.svg")) {

0 commit comments

Comments
 (0)