Skip to content

Use Float Aware Geometry for Scaling #62 #2200

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.eclipse.swt.graphics;

/**
* @since 3.130
*/
public sealed class FloatAwarePoint extends Point permits MonitorAwarePoint {

private static final long serialVersionUID = -1862062276431597053L;

public float residualX, residualY;

public FloatAwarePoint(int x, int y) {
super(x, y);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.eclipse.swt.graphics;

/**
* @since 3.130
*/
public sealed class FloatAwareRectangle extends Rectangle permits MonitorAwareRectangle {

private static final long serialVersionUID = -3006999002677468391L;

public float residualX, residualY, residualWidth, residualHeight;

public FloatAwareRectangle(int x, int y, int width, int height) {
super(x, y, width, height);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
* @since 3.129
* @noreference This class is not intended to be referenced by clients
*/
public final class MonitorAwarePoint extends Point {
public final class MonitorAwarePoint extends FloatAwarePoint {

private static final long serialVersionUID = 6077427420686999194L;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
* @since 3.129
* @noreference This class is not intended to be referenced by clients
*/
public final class MonitorAwareRectangle extends Rectangle {
public final class MonitorAwareRectangle extends FloatAwareRectangle {

private static final long serialVersionUID = 5041911840525116925L;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
* @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
*/

public sealed class Point implements Serializable permits MonitorAwarePoint {
public sealed class Point implements Serializable permits FloatAwarePoint {

/**
* the x coordinate of the point
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
* @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
*/

public sealed class Rectangle implements Serializable permits MonitorAwareRectangle {
public sealed class Rectangle implements Serializable permits FloatAwareRectangle {

/**
* the x coordinate of the rectangle
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -228,10 +228,17 @@ public static Point autoScaleDown(Point point) {

public static Point scaleDown(Point point, int zoom) {
if (zoom == 100 || point == null) return point;
FloatAwarePoint 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);
FloatAwarePoint scaledPoint = new FloatAwarePoint(0,0);

float absX = (fPoint.x + fPoint.residualX) / scaleFactor;
float absY = (fPoint.y + fPoint.residualY) / scaleFactor;

scaledPoint.x = Math.round (absX);
scaledPoint.y = Math.round (absY);
scaledPoint.residualX = absX - scaledPoint.x;
scaledPoint.residualY = absY - scaledPoint.y;
return scaledPoint;
}

Expand All @@ -255,16 +262,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.
Expand Down Expand Up @@ -333,12 +331,24 @@ public static boolean isSmoothScalingEnabled() {
*/
public static Rectangle scaleBounds (Rectangle rect, int targetZoom, int currentZoom) {
if (rect == null || targetZoom == currentZoom) return rect;
FloatAwareRectangle 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);
FloatAwareRectangle returnRect = new FloatAwareRectangle(0,0,0,0);

float absX = (fRect.x + fRect.residualX) * scaleFactor;
float absY = (fRect.y + fRect.residualY) * scaleFactor;
float absWidth = (fRect.width + fRect.residualWidth) * scaleFactor;
float absHeight = (fRect.height + fRect.residualHeight) * scaleFactor;

returnRect.x = Math.round (absX);
returnRect.y = Math.round (absY);
returnRect.width = Math.round (absWidth);
returnRect.height = Math.round (absHeight);

returnRect.residualX = absX - returnRect.x;
returnRect.residualY = absY - returnRect.y;
returnRect.residualWidth = absWidth - returnRect.width;
returnRect.residualHeight = absHeight - returnRect.height;
return returnRect;
}

Expand Down Expand Up @@ -436,10 +446,17 @@ public static Point autoScaleUp(Point point) {

public static Point scaleUp(Point point, int zoom) {
if (zoom == 100 || point == null) return point;
FloatAwarePoint 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);
FloatAwarePoint scaledPoint = new FloatAwarePoint(0,0);

float absX = (fPoint.x + fPoint.residualX) * scaleFactor;
float absY = (fPoint.y + fPoint.residualY) * scaleFactor;

scaledPoint.x = Math.round (absX);
scaledPoint.y = Math.round (absY);
scaledPoint.residualX = absX - scaledPoint.x;
scaledPoint.residualY = absY - scaledPoint.y;
return scaledPoint;
}

Expand All @@ -463,16 +480,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);
}

/**
Expand Down Expand Up @@ -751,4 +759,20 @@ public ImageData getImageData(int zoom) {
return DPIUtil.scaleImageData(device, imageData, zoom, currentZoom);
}
}

private class FloatAwareGeometryFactory {
static FloatAwareRectangle createFloatAwareRectangle(Rectangle rectangle) {
if (rectangle instanceof FloatAwareRectangle) {
return (FloatAwareRectangle) rectangle;
}
return new FloatAwareRectangle(rectangle.x, rectangle.y, rectangle.width, rectangle.height);
}

static FloatAwarePoint createFloatAwarePoint(Point point) {
if (point instanceof FloatAwarePoint) {
return (FloatAwarePoint) point;
}
return new FloatAwarePoint(point.x, point.y);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Copy link
Contributor

@arunjose696 arunjose696 Jun 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldnt the tests be testing FloatAwareRectangle too?

Copy link
Contributor Author

@amartya4256 amartya4256 Jun 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DPIUtil is responsible for creating the FloatAwareRectangle from Rectangle internally. Hence, this test is already testing FloatAwareRectangle internally.

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);
}
}
}
}
}
Loading