OSDN Git Service

Retina/NonRetinaのスクリーンスケールの認識
authorseraphy <seraphy@users.osdn.me>
Sun, 30 Dec 2018 18:29:57 +0000 (03:29 +0900)
committerseraphy <seraphy@users.osdn.me>
Sun, 30 Dec 2018 18:29:57 +0000 (03:29 +0900)
src/main/java/charactermanaj/ui/AboutBox.java
src/main/java/charactermanaj/ui/util/ScaleSupport.java

index 4f3b964..3be2099 100644 (file)
@@ -203,6 +203,22 @@ public class AboutBox {
                buf.append("<tr><td>Free Memory:</td><td>" + decimalFmt.format(freeMem) + " KiB</td></tr>");
                buf.append("</table>");
 
+               // スクリーンスケールの取得
+               ScaleSupport scaleSupport = ScaleSupport.getInstance(parent);
+               if (scaleSupport == null) {
+                       scaleSupport = ScaleSupport.getDefault();
+               }
+               String strRetina = scaleSupport.isRetina() ? "(Retina)" : "";
+               buf.append("<h2>Screen Scale</h2>");
+               buf.append("<table border=\"0\">");
+               buf.append("<tr><td>system scale x</td><td>" + scaleSupport.getDefaultScaleX() + strRetina + "</td></tr>");
+               buf.append("<tr><td>system scale y</td><td>" + scaleSupport.getDefaultScaleY() + strRetina + "</td></tr>");
+               buf.append("<tr><td>calibrate scale x</td><td>" + scaleSupport.getManualScaleX() + "</td></tr>");
+               buf.append("<tr><td>calibrate scale y</td><td>" + scaleSupport.getManualScaleY() + "</td></tr>");
+               buf.append("<tr><td>screen resolution</td><td>" + ScaleSupport.getScreenResolution() + "</td></tr>");
+               buf.append("<tr><td>screen scale</td><td>" + ScaleSupport.getScreenScale() + "</td></tr>");
+               buf.append("</table>");
+
                // キャラクターデータベースの取得
 
                DirectoryConfig dirConfig = DirectoryConfig.getInstance();
index c5aa7f8..74278f5 100644 (file)
@@ -7,6 +7,7 @@ import java.awt.GraphicsDevice;
 import java.awt.GraphicsEnvironment;
 import java.awt.Toolkit;
 import java.awt.geom.AffineTransform;
+import java.lang.reflect.Field;
 
 /**
  * スクリーンのスケールを取得する。
@@ -16,7 +17,9 @@ import java.awt.geom.AffineTransform;
  */
 public class ScaleSupport {
 
-       private static final float scale;
+       private static final int resolution;
+
+       private static final float computeScale;
 
        private double scaleX;
 
@@ -26,19 +29,50 @@ public class ScaleSupport {
 
        private double manualScaleY;
 
+       private boolean retina;
+
        static {
+               // デフォルトのスクリーン解像度を取得する
                Toolkit tk = Toolkit.getDefaultToolkit();
-               int resolution = tk.getScreenResolution();
+               resolution = tk.getScreenResolution();
 
-               float dpi = System.getProperty("os.name").startsWith("Windows") ? 96f : 72f;
-               scale = resolution / dpi;
+               // スクリーン解像度と標準のDPIから必要とされるスケールを計算する。
+               // ただし、Windowsでない場合はスケール1の等倍にする。
+               // (Retinaの場合はシステム側でスケールされるのでアプリ側でスケールする必要はないため)
+               float dpi = System.getProperty("os.name").startsWith("Windows") ? 96f : resolution;
+               computeScale = resolution / dpi;
        }
 
        private ScaleSupport(double scaleX, double scaleY) {
                this.scaleX = scaleX;
                this.scaleY = scaleY;
-               manualScaleX = scale / scaleX;
-               manualScaleY = scale / scaleX;
+               if (scaleX > 1 || scaleY > 1 || Boolean.getBoolean("disableScaleCalibrate")) {
+                       // システム側でスケールがかかっていれば、アプリ側ではスケールする必要はない。
+                       // もしくはシステムプロパティでアプリによるスケールを無効にしている場合。
+                       manualScaleX = 1;
+                       manualScaleY = 1;
+               } else {
+                       // システム側でスケールがかかっていない場合はアプリ側でスケールする
+                       // スクリーン解像度とDPIから必要なスケールを求める
+                       manualScaleX = computeScale;
+                       manualScaleY = computeScale;
+               }
+       }
+
+       public static int getScreenResolution() {
+               return resolution;
+       }
+
+       public static float getScreenScale() {
+               return computeScale;
+       }
+
+       private void setRetina(boolean retina) {
+               this.retina = retina;
+       }
+
+       public boolean isRetina() {
+               return retina;
        }
 
        /**
@@ -62,10 +96,38 @@ public class ScaleSupport {
        }
 
        public static ScaleSupport getInstance(GraphicsConfiguration gconf) {
+               // java9以降であれば、GraphicsConfigurationのデフォルトのアフィン変換に
+               // スクリーンのスケールがかけられている。
                AffineTransform trans = gconf.getDefaultTransform();
                double scaleX = trans.getScaleX();
                double scaleY = trans.getScaleY();
-               return new ScaleSupport(scaleX, scaleY);
+
+               boolean retina = false;
+               if (scaleX == 1 && scaleY == 1) {
+                       // Java8まではデフォルトのアフィン変換はスクリーンスケールは設定されていないので
+                       // 等倍を返してきた場合は、グラフィクスデバイスがスケーメメソッドをもっているか
+                       // リフレクションで確かめる。Mac版のJava8であればスケーメメソッドをもっている。
+                       // https://www.programcreek.com/java-api-examples/?code=SensorsINI/jaer/jaer-master/src/net/sf/jaer/graphics/ChipCanvas.java
+                       final GraphicsDevice device = gconf.getDevice();
+                       try {
+                               Field field = device.getClass().getDeclaredField("scale");
+                               field.setAccessible(true);
+                               Object scaleObj = field.get(device);
+
+                               if (scaleObj instanceof Number) {
+                                       int scale = ((Number) scaleObj).intValue();
+                                       scaleX = scaleY = scale;
+                                       if (scale >= 2) {
+                                               retina = true;
+                                       }
+                               }
+                       } catch (Exception ignore) {
+                               // 何もしない
+                       }
+               }
+               ScaleSupport inst = new ScaleSupport(scaleX, scaleY);
+               inst.setRetina(retina);
+               return inst;
        }
 
        public double getDefaultScaleX() {