+/*******************************************************************************
+ * 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()));
+ }
+
+}