Skip to content

Commit 1a75066

Browse files
committed
When computing the size of a widget always return values rounded up
When converting pixels to point there can be depending on the zoom level be a fractional result. Currently in all cases these result is converted into an integer using `Math.round()` that will make values `+/-0.5` resulting in small values to be round towards a smaller value. While it is maybe valid for a _location_, when using points to express a _dimension_ this is not okay as it will result in the reported (integer) value to be to small leading to errors when the SWT API is then used after performing additional computations maybe. This now makes the following adjustments: 1. Introduce a rounding mode that allows different ways of rounding and adds as a first step ROUND (the previous default) and UP (for always round towards the largest integer) 2. Adjust the `Control` class to decide what mode is best in what situation. See - #2381 - #2166
1 parent c6a29a9 commit 1a75066

File tree

4 files changed

+34
-8
lines changed

4 files changed

+34
-8
lines changed

bundles/org.eclipse.swt/Eclipse SWT/common/org/eclipse/swt/graphics/Point.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
import java.io.*;
1818

19+
import org.eclipse.swt.internal.*;
1920
import org.eclipse.swt.widgets.*;
2021

2122
/**
@@ -135,8 +136,8 @@ public OfFloat(int x, int y) {
135136
super(x, y);
136137
}
137138

138-
public OfFloat(float x, float y) {
139-
super(Math.round(x), Math.round(y));
139+
public OfFloat(float x, float y, RoundingMode mode) {
140+
super(mode.round(x), mode.round(y));
140141
this.residualX = x - this.x;
141142
this.residualY = y - this.y;
142143
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
package org.eclipse.swt.internal;
2+
/**
3+
* @noreference This class is not intended to be referenced by clients
4+
*/
5+
public enum RoundingMode {
6+
ROUND, UP;
7+
8+
int round(float x) {
9+
if (this == ROUND) {
10+
return Math.round(x);
11+
}
12+
if (this == UP) {
13+
return (int) Math.ceil(x);
14+
}
15+
return (int) x;
16+
}
17+
}

bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/internal/Win32DPIUtils.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,12 +114,17 @@ public static float pixelToPoint(Drawable drawable, float size, int zoom) {
114114
}
115115

116116
public static Point pixelToPoint(Point point, int zoom) {
117+
//TODO actually all callers should explicitly state what mode the want!
118+
return pixelToPoint(point, zoom, RoundingMode.ROUND);
119+
}
120+
121+
public static Point pixelToPoint(Point point, int zoom, RoundingMode mode) {
117122
if (zoom == 100 || point == null) return point;
118123
Point.OfFloat fPoint = FloatAwareGeometryFactory.createFrom(point);
119124
float scaleFactor = DPIUtil.getScalingFactor(zoom);
120125
float scaledX = fPoint.getX() / scaleFactor;
121126
float scaledY = fPoint.getY() / scaleFactor;
122-
return new Point.OfFloat(scaledX, scaledY);
127+
return new Point.OfFloat(scaledX, scaledY, mode);
123128
}
124129

125130
public static Point pixelToPoint(Drawable drawable, Point point, int zoom) {
@@ -225,7 +230,7 @@ public static Point pointToPixel(Point point, int zoom) {
225230
float scaleFactor = DPIUtil.getScalingFactor(zoom);
226231
float scaledX = fPoint.getX() * scaleFactor;
227232
float scaledY = fPoint.getY() * scaleFactor;
228-
return new Point.OfFloat(scaledX, scaledY);
233+
return new Point.OfFloat(scaledX, scaledY, RoundingMode.ROUND);
229234
}
230235

231236
public static Point pointToPixel(Drawable drawable, Point point, int zoom) {

bundles/org.eclipse.swt/Eclipse SWT/win32/org/eclipse/swt/widgets/Control.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -620,7 +620,9 @@ public Point computeSize (int wHint, int hHint, boolean changed){
620620
int zoom = getZoom();
621621
wHint = (wHint != SWT.DEFAULT ? Win32DPIUtils.pointToPixel(wHint, zoom) : wHint);
622622
hHint = (hHint != SWT.DEFAULT ? Win32DPIUtils.pointToPixel(hHint, zoom) : hHint);
623-
return Win32DPIUtils.pixelToPoint(computeSizeInPixels(wHint, hHint, changed), zoom);
623+
//We should never return a size that is to small, RoundingMode.UP ensures we at worst case report
624+
//a size that is a bit too large by half a point
625+
return Win32DPIUtils.pixelToPoint(computeSizeInPixels(wHint, hHint, changed), zoom, RoundingMode.UP);
624626
}
625627

626628
Point computeSizeInPixels (int wHint, int hHint, boolean changed) {
@@ -1372,7 +1374,8 @@ public Object getLayoutData () {
13721374
*/
13731375
public Point getLocation () {
13741376
checkWidget ();
1375-
return Win32DPIUtils.pixelToPoint(getLocationInPixels(), getZoom());
1377+
//For a location the closest point values is okay
1378+
return Win32DPIUtils.pixelToPoint(getLocationInPixels(), getZoom(), RoundingMode.ROUND);
13761379
}
13771380

13781381
Point getLocationInPixels () {
@@ -1528,7 +1531,7 @@ public Shell getShell () {
15281531
*/
15291532
public Point getSize (){
15301533
checkWidget ();
1531-
return Win32DPIUtils.pixelToPoint(getSizeInPixels (), getZoom());
1534+
return Win32DPIUtils.pixelToPoint(getSizeInPixels (), getZoom(), RoundingMode.UP);
15321535
}
15331536

15341537
Point getSizeInPixels () {
@@ -4030,7 +4033,7 @@ public Point toControl (int x, int y) {
40304033
checkWidget ();
40314034
Point displayPointInPixels = getDisplay().translateToDisplayCoordinates(new Point(x, y));
40324035
final Point controlPointInPixels = toControlInPixels(displayPointInPixels.x, displayPointInPixels.y);
4033-
return Win32DPIUtils.pixelToPoint(controlPointInPixels, getZoom());
4036+
return Win32DPIUtils.pixelToPoint(controlPointInPixels, getZoom(), RoundingMode.ROUND);
40344037
}
40354038

40364039
Point toControlInPixels (int x, int y) {

0 commit comments

Comments
 (0)