/******************************************************************************* * 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.GraphicsEnvironment; 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; if (!GraphicsEnvironment.isHeadless()) dpi = Toolkit.getDefaultToolkit().getScreenResolution(); else dpi = 96; 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())); } }