From 66ba81cf89165657c750f98431936bd81eb615d6 Mon Sep 17 00:00:00 2001 From: Amartya Parijat Date: Thu, 12 Jun 2025 11:46:25 +0200 Subject: [PATCH 1/3] Internalize MonitorAware* Classes to Parent #62 This commit moves the classes MonitorAwareRectangle and MonitorAwarePoint to Rectangle and Point as a static class and renames them to WithMonitor to allow them to be used as Rectangle.WithMonitor and Point.WithMonitor. contributes to https://github.com/eclipse-platform/eclipse.platform.swt/issues/62 and https://github.com/eclipse-platform/eclipse.platform.swt/issues/128 --- .../widgets/CoordinateSystemMapperTests.java | 6 +- .../swt/graphics/MonitorAwarePoint.java | 62 ------------------ .../swt/graphics/MonitorAwareRectangle.java | 64 ------------------- .../org/eclipse/swt/graphics/Point.java | 40 +++++++++++- .../org/eclipse/swt/graphics/Rectangle.java | 41 +++++++++++- .../MultiZoomCoordinateSystemMapper.java | 10 +-- .../win32/org/eclipse/swt/widgets/Tree.java | 6 +- 7 files changed, 90 insertions(+), 139 deletions(-) delete mode 100644 bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/MonitorAwarePoint.java delete mode 100644 bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/MonitorAwareRectangle.java diff --git a/bundles/org.eclipse.swt/Eclipse SWT Tests/win32/org/eclipse/swt/widgets/CoordinateSystemMapperTests.java b/bundles/org.eclipse.swt/Eclipse SWT Tests/win32/org/eclipse/swt/widgets/CoordinateSystemMapperTests.java index 5fc56ba05d1..4f4b1989663 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT Tests/win32/org/eclipse/swt/widgets/CoordinateSystemMapperTests.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Tests/win32/org/eclipse/swt/widgets/CoordinateSystemMapperTests.java @@ -137,7 +137,7 @@ void translateRectangleInGapPartiallyInRightBackAndForthInSingleZoomShouldBeTheS void translateRectangleInGapPartiallyInRightBackAndForthInMultiZoomShouldBeInside() { MultiZoomCoordinateSystemMapper mapper = getMultiZoomCoordinateSystemMapper(); setupMonitors(mapper); - Rectangle rectInPts = new MonitorAwareRectangle(1950, 400, 150, 100, monitors[1]); + Rectangle rectInPts = new Rectangle.WithMonitor(1950, 400, 150, 100, monitors[1]); Rectangle rectInPxs = mapper.translateToDisplayCoordinates(rectInPts, monitors[0].getZoom()); assertEquals(rectInPts, mapper.translateFromDisplayCoordinates(rectInPxs, monitors[0].getZoom())); } @@ -223,7 +223,7 @@ private Point createExpectedPoint(CoordinateSystemMapper mapper, int x, int y, M if (mapper instanceof SingleZoomCoordinateSystemMapper) { return new Point(x, y); } else { - return new MonitorAwarePoint(x, y, monitor); + return new Point.WithMonitor(x, y, monitor); } } @@ -231,7 +231,7 @@ private Rectangle createExpectedRectangle(CoordinateSystemMapper mapper, int x, if (mapper instanceof SingleZoomCoordinateSystemMapper) { return new Rectangle(x, y, width, height); } else { - return new MonitorAwareRectangle(x, y, width, height, monitor); + return new Rectangle.WithMonitor(x, y, width, height, monitor); } } diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/MonitorAwarePoint.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/MonitorAwarePoint.java deleted file mode 100644 index 5e73e051e69..00000000000 --- a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/MonitorAwarePoint.java +++ /dev/null @@ -1,62 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2025 Yatta Solutions and others. - * - * This program and the accompanying materials - * are made available under the terms of the Eclipse Public License 2.0 - * which accompanies this distribution, and is available at - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Yatta Solutions - initial API and implementation - *******************************************************************************/ -package org.eclipse.swt.graphics; - -import org.eclipse.swt.widgets.*; - -/** - * Instances of this class represent {@link org.eclipse.swt.graphics.Point} - * objects along with the context of the monitor in relation to which they are - * placed on the display. The monitor awareness makes it easy to scale and - * translate the points between pixels and points. - * - * @since 3.129 - * @noreference This class is not intended to be referenced by clients - */ -public final class MonitorAwarePoint extends Point { - - private static final long serialVersionUID = 6077427420686999194L; - - private final Monitor monitor; - - /** - * Constructs a new MonitorAwarePoint - * - * @param x the x coordinate of the point - * @param y the y coordinate of the point - * @param monitor the monitor with whose context the point is created - */ - public MonitorAwarePoint(int x, int y, Monitor monitor) { - super(x, y); - this.monitor = monitor; - } - - /** - * {@return the monitor with whose context the instance is created} - */ - public Monitor getMonitor() { - return monitor; - } - - @Override - public boolean equals(Object object) { - return super.equals(object); - } - - @Override - public int hashCode() { - return super.hashCode(); - } - -} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/MonitorAwareRectangle.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/MonitorAwareRectangle.java deleted file mode 100644 index c71ea94a389..00000000000 --- a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/MonitorAwareRectangle.java +++ /dev/null @@ -1,64 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2025 Yatta Solutions and others. - * - * This program and the accompanying materials - * are made available under the terms of the Eclipse Public License 2.0 - * which accompanies this distribution, and is available at - * https://www.eclipse.org/legal/epl-2.0/ - * - * SPDX-License-Identifier: EPL-2.0 - * - * Contributors: - * Yatta Solutions - initial API and implementation - *******************************************************************************/ -package org.eclipse.swt.graphics; - -import org.eclipse.swt.widgets.*; - -/** - * Instances of this class represent {@link org.eclipse.swt.graphics.Rectangle} - * objects along with the context of the monitor in relation to which they are - * placed on the display. The monitor awareness makes it easy to scale and - * translate the rectangles between pixels and points. - * - * @since 3.129 - * @noreference This class is not intended to be referenced by clients - */ -public final class MonitorAwareRectangle extends Rectangle { - - private static final long serialVersionUID = 5041911840525116925L; - - private final Monitor monitor; - - /** - * Constructs a new MonitorAwareRectangle - * - * @param x the x coordinate of the top left corner of the rectangle - * @param y the y coordinate of the top left corner of the rectangle - * @param width the width of the rectangle - * @param height the height of the rectangle - * @param monitor the monitor with whose context the rectangle is created - */ - public MonitorAwareRectangle(int x, int y, int width, int height, Monitor monitor) { - super(x, y, width, height); - this.monitor = monitor; - } - - /** - * {@return the monitor with whose context the instance is created} - */ - public Monitor getMonitor() { - return monitor; - } - - @Override - public boolean equals(Object object) { - return super.equals(object); - } - - @Override - public int hashCode() { - return super.hashCode(); - } - -} diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/Point.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/Point.java index 2aef2d06820..182cc734d49 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/Point.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/Point.java @@ -16,6 +16,8 @@ import java.io.*; +import org.eclipse.swt.widgets.*; + /** * Instances of this class represent places on the (x, y) * coordinate plane. @@ -41,7 +43,7 @@ * @see Sample code and further information */ -public sealed class Point implements Serializable permits MonitorAwarePoint { +public sealed class Point implements Serializable permits Point.WithMonitor { /** * the x coordinate of the point @@ -116,5 +118,41 @@ public String toString () { return "Point {" + x + ", " + y + "}"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ } +/** + * Instances of this class represent {@link org.eclipse.swt.graphics.Point} + * objects along with the context of the monitor in relation to which they are + * placed on the display. The monitor awareness makes it easy to scale and + * translate the points between pixels and points. + * + * @since 3.130 + * @noreference This class is not intended to be referenced by clients + */ +public static final class WithMonitor extends Point { + + private static final long serialVersionUID = 6077427420686999194L; + + private final Monitor monitor; + + /** + * Constructs a new Point.WithMonitor + * + * @param x the x coordinate of the point + * @param y the y coordinate of the point + * @param monitor the monitor with whose context the point is created + */ + public WithMonitor(int x, int y, Monitor monitor) { + super(x, y); + this.monitor = monitor; + } + + /** + * {@return the monitor with whose context the instance is created} + */ + public Monitor getMonitor() { + return monitor; + } + +} + } diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/Rectangle.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/Rectangle.java index e8060493d7e..2f9719919ea 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/Rectangle.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/Rectangle.java @@ -17,6 +17,7 @@ import java.io.*; import org.eclipse.swt.*; +import org.eclipse.swt.widgets.*; /** * Instances of this class represent rectangular areas in an @@ -45,7 +46,7 @@ * @see Sample code and further information */ -public sealed class Rectangle implements Serializable permits MonitorAwareRectangle { +public sealed class Rectangle implements Serializable permits Rectangle.WithMonitor { /** * the x coordinate of the rectangle @@ -356,4 +357,42 @@ public Rectangle union (Rectangle rect) { return new Rectangle (left, top, right - left, bottom - top); } +/** + * Instances of this class represent {@link org.eclipse.swt.graphics.Rectangle} + * objects along with the context of the monitor in relation to which they are + * placed on the display. The monitor awareness makes it easy to scale and + * translate the rectangles between pixels and points. + * + * @since 3.130 + * @noreference This class is not intended to be referenced by clients + */ +public static final class WithMonitor extends Rectangle { + + private static final long serialVersionUID = 5041911840525116925L; + + private final Monitor monitor; + + /** + * Constructs a new Rectangle.WithMonitor + * + * @param x the x coordinate of the top left corner of the rectangle + * @param y the y coordinate of the top left corner of the rectangle + * @param width the width of the rectangle + * @param height the height of the rectangle + * @param monitor the monitor with whose context the rectangle is created + */ + public WithMonitor(int x, int y, int width, int height, Monitor monitor) { + super(x, y, width, height); + this.monitor = monitor; + } + + /** + * {@return the monitor with whose context the instance is created} + */ + public Monitor getMonitor() { + return monitor; + } + +} + } diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/MultiZoomCoordinateSystemMapper.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/MultiZoomCoordinateSystemMapper.java index 0edae112b5f..693b76e96aa 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/MultiZoomCoordinateSystemMapper.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/MultiZoomCoordinateSystemMapper.java @@ -98,19 +98,19 @@ public Point translateFromDisplayCoordinates(Point point, int zoom) { @Override public Point translateToDisplayCoordinates(Point point, int zoom) { - Monitor monitor = point instanceof MonitorAwarePoint monitorAwarePoint ? monitorAwarePoint.getMonitor() : null; + Monitor monitor = point instanceof Point.WithMonitor pointWithMonitor ? pointWithMonitor.getMonitor() : null; return translateLocationInPointsToPixels(point.x, point.y, monitor); } @Override public Rectangle translateFromDisplayCoordinates(Rectangle rect, int zoom) { - Monitor monitor = rect instanceof MonitorAwareRectangle monitorAwareRect ? monitorAwareRect.getMonitor() : null; + Monitor monitor = rect instanceof Rectangle.WithMonitor rectWithMonitor ? rectWithMonitor.getMonitor() : null; return translateRectangleInPixelsToPoints(rect.x, rect.y, rect.width, rect.height, monitor); } @Override public Rectangle translateToDisplayCoordinates(Rectangle rect, int zoom) { - Monitor monitor = rect instanceof MonitorAwareRectangle monitorAwareRect ? monitorAwareRect.getMonitor() : null; + Monitor monitor = rect instanceof Rectangle.WithMonitor rectWithMonitor ? rectWithMonitor.getMonitor() : null; return translateRectangleInPointsToPixels(rect.x, rect.y, rect.width, rect.height, monitor); } @@ -152,7 +152,7 @@ private Rectangle translateRectangleInPixelsToPoints(int x, int y, int widthInPi Point topLeft = getPointFromPixels(monitor, x, y); int width = DPIUtil.scaleDown(widthInPixels, zoom); int height = DPIUtil.scaleDown(heightInPixels, zoom); - MonitorAwareRectangle rect = new MonitorAwareRectangle(topLeft.x, topLeft.y, width, height, monitor); + Rectangle.WithMonitor rect = new Rectangle.WithMonitor(topLeft.x, topLeft.y, width, height, monitor); return rect; } @@ -264,7 +264,7 @@ private Point getPointFromPixels(Monitor monitor, int x, int y) { int zoom = getApplicableMonitorZoom(monitor); int mappedX = DPIUtil.scaleDown(x - monitor.clientX, zoom) + monitor.clientX; int mappedY = DPIUtil.scaleDown(y - monitor.clientY, zoom) + monitor.clientY; - return new MonitorAwarePoint(mappedX, mappedY, monitor); + return new Point.WithMonitor(mappedX, mappedY, monitor); } private int getApplicableMonitorZoom(Monitor monitor) { diff --git a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Tree.java b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Tree.java index ef7f6ca9d8d..3d236a591fe 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Tree.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Tree.java @@ -8176,8 +8176,8 @@ private LRESULT positionTooltip(NMHDR hdr, long wParam, long lParam, boolean man // of positioning and re-scaling events. // Refer: https://github.com/eclipse-platform/eclipse.platform.swt/issues/557 Point cursorLocation = display.getCursorLocation(); - Rectangle monitorBounds = cursorLocation instanceof MonitorAwarePoint monitorAwarePoint - ? getContainingMonitorBoundsInMultiZoomCoordinateSystem(monitorAwarePoint) + Rectangle monitorBounds = cursorLocation instanceof Point.WithMonitor pointWithMonitor + ? getContainingMonitorBoundsInMultiZoomCoordinateSystem(pointWithMonitor) : getContainingMonitorBoundsInSingleZoomCoordinateSystem(cursorLocation); if (monitorBounds != null) { Rectangle adjustedTooltipBounds = fitTooltipBoundsIntoMonitor(toolRect, monitorBounds); @@ -8229,7 +8229,7 @@ private Rectangle getContainingMonitorBoundsInSingleZoomCoordinateSystem(Point p return null; } -private Rectangle getContainingMonitorBoundsInMultiZoomCoordinateSystem(MonitorAwarePoint point) { +private Rectangle getContainingMonitorBoundsInMultiZoomCoordinateSystem(Point.WithMonitor point) { Monitor monitor = point.getMonitor(); return new Rectangle(monitor.x, monitor.y, DPIUtil.scaleUp(monitor.width, monitor.zoom), DPIUtil.scaleUp(monitor.height, monitor.zoom)); From 1f6354be208e6ccec15e9d3541a65d1320366594 Mon Sep 17 00:00:00 2001 From: Amartya Parijat Date: Thu, 12 Jun 2025 13:23:49 +0200 Subject: [PATCH 2/3] Introduce OfFloat classes for better scaling #62 This commit introduces Rectangle.OfFloat and Point.OfFloat classes as an extension of Rectangle and Point respectively to improve scaling precision in the DPIUtil by using residuals obtained from rounding. Contributes to https://github.com/eclipse-platform/eclipse.platform.swt/issues/62 and https://github.com/eclipse-platform/eclipse.platform.swt/issues/128 --- .../org/eclipse/swt/graphics/Point.java | 51 ++++++++++++- .../org/eclipse/swt/graphics/Rectangle.java | 75 ++++++++++++++++++- .../org/eclipse/swt/internal/DPIUtil.java | 66 ++++++++-------- .../eclipse/swt/tests/junit/DPIUtilTests.java | 36 +++++++++ 4 files changed, 188 insertions(+), 40 deletions(-) diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/Point.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/Point.java index 182cc734d49..715eb83a965 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/Point.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/Point.java @@ -43,7 +43,7 @@ * @see Sample code and further information */ -public sealed class Point implements Serializable permits Point.WithMonitor { +public sealed class Point implements Serializable permits Point.OfFloat { /** * the x coordinate of the point @@ -68,6 +68,8 @@ public Point (int x, int y) { this.y = y; } +private Point() {} + /** * Compares the argument to the receiver, and returns true * if they represent the same object using a class @@ -120,6 +122,50 @@ public String toString () { /** * Instances of this class represent {@link org.eclipse.swt.graphics.Point} + * objects with the fields capable of storing more precise value in float. + * + * @since 3.130 + * @noreference This class is not intended to be referenced by clients + */ +public static sealed class OfFloat extends Point permits Point.WithMonitor { + + private static final long serialVersionUID = -1862062276431597053L; + + public float residualX, residualY; + + public OfFloat(int x, int y) { + super(x, y); + } + + public OfFloat(float x, float y) { + super(); + this.x = Math.round(x); + this.y = Math.round(y); + this.residualX = x - this.x; + this.residualY = y - this.y; + } + + public float getX() { + return x + residualX; + } + + public float getY() { + return y + residualY; + } + + public void setX(float x) { + this.x = Math.round(x); + this.residualX = x - this.x; + } + + public void setY(float y) { + this.y = Math.round(y); + this.residualY = y - this.y; + } +} + +/** + * Instances of this class represent {@link org.eclipse.swt.graphics.Point.OfFloat} * objects along with the context of the monitor in relation to which they are * placed on the display. The monitor awareness makes it easy to scale and * translate the points between pixels and points. @@ -127,7 +173,7 @@ public String toString () { * @since 3.130 * @noreference This class is not intended to be referenced by clients */ -public static final class WithMonitor extends Point { +public static final class WithMonitor extends Point.OfFloat { private static final long serialVersionUID = 6077427420686999194L; @@ -155,4 +201,3 @@ public Monitor getMonitor() { } } - diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/Rectangle.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/Rectangle.java index 2f9719919ea..d22bfdaf96a 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/Rectangle.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/Rectangle.java @@ -46,7 +46,7 @@ * @see Sample code and further information */ -public sealed class Rectangle implements Serializable permits Rectangle.WithMonitor { +public sealed class Rectangle implements Serializable permits Rectangle.OfFloat { /** * the x coordinate of the rectangle @@ -86,6 +86,8 @@ public Rectangle (int x, int y, int width, int height) { this.height = height; } +private Rectangle() {} + /** * Destructively replaces the x, y, width and height values * in the receiver with ones which represent the union of the @@ -359,6 +361,73 @@ public Rectangle union (Rectangle rect) { /** * Instances of this class represent {@link org.eclipse.swt.graphics.Rectangle} + * objects which supports values of Float type for it's fields + * + * @since 3.130 + * @noreference This class is not intended to be referenced by clients + */ +public static sealed class OfFloat extends Rectangle permits Rectangle.WithMonitor { + + private static final long serialVersionUID = -3006999002677468391L; + + private float residualX, residualY, residualWidth, residualHeight; + + public OfFloat(int x, int y, int width, int height) { + super(x, y, width, height); + } + + public OfFloat(float x, float y, float width, float height) { + super(); + this.x = Math.round(x); + this.y = Math.round(y); + this.width = Math.round(width); + this.height = Math.round(height); + this.residualX = x - this.x; + this.residualY = y - this.y; + this.residualWidth = width - this.width; + this.residualHeight = height - this.height; + } + + public float getX() { + return x + residualX; + } + + public float getY() { + return y + residualY; + } + + public float getWidth() { + return width + residualWidth; + } + + public float getHeight() { + return height + residualHeight; + } + + public void setX(float x) { + this.x = Math.round(x); + this.residualX = x - this.x; + } + + public void setY(float y) { + this.y = Math.round(y); + this.residualY = y - this.y; + } + + public void setWidth(float width) { + this.width = Math.round(width); + this.residualWidth = width - this.width; + } + + public void setHeight(float height) { + this.height = Math.round(height); + this.residualHeight = height - this.height; + } + +} + +/** + * Instances of this class represent {@link org.eclipse.swt.graphics.Rectangle.OfFloat} * objects along with the context of the monitor in relation to which they are * placed on the display. The monitor awareness makes it easy to scale and * translate the rectangles between pixels and points. @@ -366,7 +435,7 @@ public Rectangle union (Rectangle rect) { * @since 3.130 * @noreference This class is not intended to be referenced by clients */ -public static final class WithMonitor extends Rectangle { +public static final class WithMonitor extends Rectangle.OfFloat { private static final long serialVersionUID = 5041911840525116925L; @@ -395,4 +464,4 @@ public Monitor getMonitor() { } -} +} \ No newline at end of file diff --git a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/DPIUtil.java b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/DPIUtil.java index a15f4683ae3..505cd4da67d 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/DPIUtil.java +++ b/bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/internal/DPIUtil.java @@ -228,11 +228,11 @@ public static Point autoScaleDown(Point point) { public static Point scaleDown(Point point, int zoom) { if (zoom == 100 || point == null) return point; + Point.OfFloat fPoint = FloatAwareGeometryFactory.createFloatAwarePoint(point); float scaleFactor = getScalingFactor(zoom); - Point scaledPoint = new Point (0,0); - scaledPoint.x = Math.round (point.x / scaleFactor); - scaledPoint.y = Math.round (point.y / scaleFactor); - return scaledPoint; + float scaledX = fPoint.getX() / scaleFactor; + float scaledY = fPoint.getY() / scaleFactor; + return new Point.OfFloat(scaledX, scaledY); } /** @@ -255,16 +255,7 @@ public static Rectangle autoScaleDown(Rectangle rect) { } public static Rectangle scaleDown(Rectangle rect, int zoom) { - if (zoom == 100 || rect == null) return rect; - Rectangle scaledRect = new Rectangle (0,0,0,0); - Point scaledTopLeft = scaleDown(new Point (rect.x, rect.y), zoom); - Point scaledBottomRight = scaleDown(new Point (rect.x + rect.width, rect.y + rect.height), zoom); - - scaledRect.x = scaledTopLeft.x; - scaledRect.y = scaledTopLeft.y; - scaledRect.width = scaledBottomRight.x - scaledTopLeft.x; - scaledRect.height = scaledBottomRight.y - scaledTopLeft.y; - return scaledRect; + return scaleBounds(rect, 100, zoom); } /** * Returns a new scaled down Rectangle if enabled for Drawable class. @@ -333,13 +324,13 @@ public static boolean isSmoothScalingEnabled() { */ public static Rectangle scaleBounds (Rectangle rect, int targetZoom, int currentZoom) { if (rect == null || targetZoom == currentZoom) return rect; + Rectangle.OfFloat fRect = FloatAwareGeometryFactory.createFloatAwareRectangle(rect); float scaleFactor = ((float)targetZoom) / (float)currentZoom; - Rectangle returnRect = new Rectangle (0,0,0,0); - returnRect.x = Math.round (rect.x * scaleFactor); - returnRect.y = Math.round (rect.y * scaleFactor); - returnRect.width = Math.round (rect.width * scaleFactor); - returnRect.height = Math.round (rect.height * scaleFactor); - return returnRect; + float scaledX = fRect.getX() * scaleFactor; + float scaledY = fRect.getY() * scaleFactor; + float scaledWidth = fRect.getWidth() * scaleFactor; + float scaledHeight = fRect.getHeight() * scaleFactor; + return new Rectangle.OfFloat(scaledX, scaledY, scaledWidth, scaledHeight); } /** @@ -436,11 +427,11 @@ public static Point autoScaleUp(Point point) { public static Point scaleUp(Point point, int zoom) { if (zoom == 100 || point == null) return point; + Point.OfFloat fPoint = FloatAwareGeometryFactory.createFloatAwarePoint(point); float scaleFactor = getScalingFactor(zoom); - Point scaledPoint = new Point(0,0); - scaledPoint.x = Math.round (point.x * scaleFactor); - scaledPoint.y = Math.round (point.y * scaleFactor); - return scaledPoint; + float scaledX = fPoint.getX() * scaleFactor; + float scaledY = fPoint.getY() * scaleFactor; + return new Point.OfFloat(scaledX, scaledY); } /** @@ -463,16 +454,7 @@ public static Rectangle autoScaleUp(Rectangle rect) { } public static Rectangle scaleUp(Rectangle rect, int zoom) { - if (zoom == 100 || rect == null) return rect; - Rectangle scaledRect = new Rectangle(0,0,0,0); - Point scaledTopLeft = scaleUp (new Point(rect.x, rect.y), zoom); - Point scaledBottomRight = scaleUp (new Point(rect.x + rect.width, rect.y + rect.height), zoom); - - scaledRect.x = scaledTopLeft.x; - scaledRect.y = scaledTopLeft.y; - scaledRect.width = scaledBottomRight.x - scaledTopLeft.x; - scaledRect.height = scaledBottomRight.y - scaledTopLeft.y; - return scaledRect; + return scaleBounds(rect, zoom, 100); } /** @@ -751,4 +733,20 @@ public ImageData getImageData(int zoom) { return DPIUtil.scaleImageData(device, imageData, zoom, currentZoom); } } + +private class FloatAwareGeometryFactory { + static Rectangle.OfFloat createFloatAwareRectangle(Rectangle rectangle) { + if (rectangle instanceof Rectangle.OfFloat) { + return (Rectangle.OfFloat) rectangle; + } + return new Rectangle.OfFloat(rectangle.x, rectangle.y, rectangle.width, rectangle.height); + } + + static Point.OfFloat createFloatAwarePoint(Point point) { + if (point instanceof Point.OfFloat) { + return (Point.OfFloat) point; + } + return new Point.OfFloat(point.x, point.y); + } +} } \ No newline at end of file diff --git a/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/DPIUtilTests.java b/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/DPIUtilTests.java index a517ed9942b..1bd1bcb29de 100644 --- a/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/DPIUtilTests.java +++ b/tests/org.eclipse.swt.tests/JUnit Tests/org/eclipse/swt/tests/junit/DPIUtilTests.java @@ -318,4 +318,40 @@ public void scaleUpRectangle() { scaledValue = DPIUtil.scaleUp((Device) null, valueAt100, 100); assertSame(valueAt100, scaledValue, "Scaling up Rectangle without zoom change with device failed"); } + + @Test + public void scaleDownscaleUpRectangleInvertible() { + int[] zooms = new int[] {25, 50, 75, 100, 125, 150, 175, 200, 225, 250, 275, 300, 325, 350, 375, 400}; + for (int zoom1 : zooms) { + for (int zoom2 : zooms) { + for (int i = 1; i <= 10000; i++) { + Rectangle rect = new Rectangle(0, 0, i, i); + Rectangle scaleDown = DPIUtil.scaleDown(rect, zoom1); + Rectangle scaleUp = DPIUtil.scaleUp(scaleDown, zoom2); + scaleDown = DPIUtil.scaleDown(scaleUp, zoom2); + scaleUp = DPIUtil.scaleUp(scaleDown, zoom1); + assertEquals(rect.width, scaleUp.width); + assertEquals(rect.height, scaleUp.height); + } + } + } + } + + @Test + public void scaleDownscaleUpPointInvertible() { + int[] zooms = new int[] {25, 50, 75, 100, 125, 150, 175, 200, 225, 250, 275, 300, 325, 350, 375, 400}; + for (int zoom1 : zooms) { + for (int zoom2 : zooms) { + for (int i = 1; i <= 10000; i++) { + Point pt = new Point(i, i); + Point scaleDown = DPIUtil.scaleDown(pt, zoom1); + Point scaleUp = DPIUtil.scaleUp(scaleDown, zoom2); + scaleDown = DPIUtil.scaleDown(scaleUp, zoom2); + scaleUp = DPIUtil.scaleUp(scaleDown, zoom1); + assertEquals(pt.x, scaleUp.x); + assertEquals(pt.y, scaleUp.y); + } + } + } + } } From fd97443ea2677b49d96d1ba4a492d9be8d4b9c95 Mon Sep 17 00:00:00 2001 From: Amartya Parijat Date: Fri, 6 Jun 2025 14:13:15 +0200 Subject: [PATCH 3/3] Fix CTabFolder border with FloatAwareRectangle WIP --- .../common/org/eclipse/swt/custom/CTabFolder.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CTabFolder.java b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CTabFolder.java index 0aaa92847f3..0a901967da1 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CTabFolder.java +++ b/bundles/org.eclipse.swt/Eclipse SWT Custom Widgets/common/org/eclipse/swt/custom/CTabFolder.java @@ -892,9 +892,10 @@ public Rectangle getClientArea() { trim.height += wrapHeight; } if (minimized) return new Rectangle(-trim.x, -trim.y, 0, 0); - int width = size.x - trim.width; - int height = size.y - trim.height; - return new Rectangle(-trim.x, -trim.y, width, height); + float width = ((Point.OfFloat) size).getX() - trim.width; + float height = ((Point.OfFloat) size).getY() - trim.height; + Rectangle.OfFloat r = new Rectangle.OfFloat(-trim.x, -trim.y, width, height); + return r; } /**