]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/utils/DPIUtil.java
HiDPI scaling for diagram ruler and model activity tracker
[simantics/platform.git] / bundles / org.simantics.scenegraph / src / org / simantics / scenegraph / utils / DPIUtil.java
diff --git a/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/utils/DPIUtil.java b/bundles/org.simantics.scenegraph/src/org/simantics/scenegraph/utils/DPIUtil.java
new file mode 100644 (file)
index 0000000..0a138b3
--- /dev/null
@@ -0,0 +1,254 @@
+/*******************************************************************************
+ * Copyright (c) 2018 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Semantum Oy - initial API and implementation
+ *******************************************************************************/
+package org.simantics.scenegraph.utils;
+
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.Toolkit;
+import java.awt.geom.Point2D;
+import java.awt.geom.Rectangle2D;
+
+/**
+ * @author Tuukka Lehtonen
+ * @since 1.36.0
+ */
+public class DPIUtil {
+
+       private static boolean initialized = false;
+       private static boolean hasZoom;
+
+       private static float upscaleFactorF;
+       private static double upscaleFactorD;
+       private static float downscaleFactorF;
+       private static double downscaleFactorD;
+
+       private static void initialize() {
+               if (initialized)
+                       return;
+
+               double dpi = Toolkit.getDefaultToolkit().getScreenResolution();
+               double baseDpi = 96;
+               int zoom = (int) Math.round(100.0 * dpi / baseDpi);
+               hasZoom = zoom != 100;
+
+               upscaleFactorD   = dpi / baseDpi;
+               upscaleFactorF   = (float) upscaleFactorD;
+               downscaleFactorD = baseDpi / dpi;
+               downscaleFactorF   = (float) downscaleFactorD;
+
+//             System.out.format("DPIUtil:%n\tswt zoom = %d%n\tdownscale factor = %f%n\tupscale factor = %f%n",
+//                             zoom,
+//                             downscaleFactorD,
+//                             upscaleFactorD
+//                             );
+
+               initialized = true;
+       }
+
+       // Internals
+
+       private static Rectangle scale(float s, Rectangle r, Rectangle target) {
+               if (s == 1.0f) {
+                       if (r == target)
+                               return r;
+                       if (target == null) {
+                               return new Rectangle(r.x, r.y, r.width, r.height);
+                       } else {
+                               target.x = r.x;
+                               target.y = r.y;
+                               target.width = r.width;
+                               target.height = r.height;
+                               return target;
+                       }
+               }
+               if (target == null) {
+                       return new Rectangle(
+                                       Math.round(r.x*s),
+                                       Math.round(r.y*s),
+                                       Math.round(r.width*s),
+                                       Math.round(r.height*s));
+               } else {
+                       target.x = Math.round(r.x*s);
+                       target.y = Math.round(r.y*s);
+                       target.width = Math.round(r.width*s);
+                       target.height = Math.round(r.height*s);
+                       return target;
+               }
+       }
+
+       private static Rectangle2D scale(double s, Rectangle2D r, Rectangle2D target) {
+               if (s == 1.0) {
+                       if (r == target)
+                               return r;
+                       if (target == null)
+                               return (Rectangle2D) r.clone();
+                       target.setFrame(r);
+                       return target;
+               }
+               if (target == null)
+                       target = (Rectangle2D) r.clone();
+               target.setFrame(r.getX()*s, r.getY()*s, r.getWidth()*s, r.getHeight()*s);
+               return target;
+       }
+
+       private static double downscale0(double x) {
+               return hasZoom ? x * downscaleFactorD : x;
+       }
+
+       private static int downscaleToInteger0(double x) {
+               return (int)(hasZoom ? Math.round((double) x * downscaleFactorD) : x);
+       }
+
+       private static int downscale0(int x) {
+               return hasZoom ? (int) Math.round((double) x * downscaleFactorD) : x;
+       }
+
+       private static double upscale0(double x) {
+               return hasZoom ? x * upscaleFactorD : x;
+       }
+
+       private static int upscaleToInteger0(double x) {
+               return (int)(hasZoom ? Math.round((double) x * upscaleFactorD) : x);
+       }
+
+       private static int upscale0(int x) {
+               return hasZoom ? (int) Math.round((double) x * upscaleFactorD) : x;
+       }
+
+       // Downscaling
+
+       public static double downscale(double x) {
+               initialize();
+               return downscale0(x);
+       }
+
+       public static int downscale(int x) {
+               initialize();
+               return downscale0(x);
+       }
+
+       public static Point2D downscale(double x, double y) {
+               initialize();
+               if (!hasZoom)
+                       return new Point2D.Double(x, y);
+               double s = downscaleFactorD;
+               return new Point2D.Double(x * s, y * s);
+       }
+
+       public static Point downscale(int x, int y) {
+               initialize();
+               return new Point(downscale0(x), downscale0(y));
+       }
+
+       public static Point2D downscale(Point2D p) {
+               return downscale(p.getX(), p.getY());
+       }
+
+       public static Point downscaleToInteger(Point2D p) {
+               initialize();
+               return new Point(downscaleToInteger0(p.getX()), downscaleToInteger0(p.getY()));
+       }
+
+       public static Rectangle2D downscale(Rectangle2D r, Rectangle2D target) {
+               initialize();
+               return scale(downscaleFactorD, r, target);
+       }
+
+       public static Rectangle2D downscale(Rectangle2D r) {
+               return downscale(r, null);
+       }
+
+       public static Rectangle downscale(Rectangle r, Rectangle target) {
+               initialize();
+               return scale(downscaleFactorF, r, target);
+       }
+
+       public static Rectangle downscale(Rectangle r) {
+               return downscale(r, null);
+       }
+
+       public static Rectangle downscaleToInteger(Rectangle2D r) {
+               initialize();
+               return new Rectangle( 
+                               downscaleToInteger0(r.getMinX()),
+                               downscaleToInteger0(r.getMinY()),
+                               downscaleToInteger0(r.getWidth()),
+                               downscaleToInteger0(r.getHeight()));
+       }
+
+       // Upscaling
+
+       public static double upscale(double x) {
+               initialize();
+               return upscale0(x);
+       }
+
+       public static int upscale(int x) {
+               initialize();
+               return upscale0(x);
+       }
+
+       public static Point2D upscale(double x, double y) {
+               initialize();
+               if (!hasZoom)
+                       return new Point2D.Double(x, y);
+               double s = upscaleFactorD;
+               return new Point2D.Double(x * s, y * s);
+       }
+
+       public static Point upscale(int x, int y) {
+               initialize();
+               return new Point(upscale0(x), upscale0(y));
+       }
+
+       public static Point2D upscale(Point2D p) {
+               initialize();
+               return (hasZoom && p != null) ? upscale(p.getX(), p.getY()) : p;
+       }
+
+       public static Point upscaleToInteger(Point2D p) {
+               initialize();
+               return new Point(upscaleToInteger0(p.getX()), upscaleToInteger0(p.getY()));
+       }
+
+       public static Point upscale(Point p) {
+               initialize();
+               return (hasZoom && p != null) ? upscale(p.x, p.y) : p;
+       }
+
+       public static Rectangle2D upscale(Rectangle2D r, Rectangle2D target) {
+               initialize();
+               return scale(upscaleFactorD, r, target);
+       }
+
+       public static Rectangle upscale(Rectangle r, Rectangle target) {
+               initialize();
+               return scale(upscaleFactorF, r, target);
+       }
+
+       public static Rectangle2D upscale(Rectangle2D r) {
+               return upscale(r, null);
+       }
+
+       public static Rectangle upscale(Rectangle r) {
+               return upscale(r, null);
+       }
+
+       public static Rectangle upscaleToInteger(Rectangle2D r) {
+               return new Rectangle( 
+                               upscaleToInteger0(r.getMinX()),
+                               upscaleToInteger0(r.getMinY()),
+                               upscaleToInteger0(r.getWidth()),
+                               upscaleToInteger0(r.getHeight()));
+       }
+
+}