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();
import java.awt.GraphicsEnvironment;
import java.awt.Toolkit;
import java.awt.geom.AffineTransform;
+import java.lang.reflect.Field;
/**
* スクリーンのスケールを取得する。
*/
public class ScaleSupport {
- private static final float scale;
+ private static final int resolution;
+
+ private static final float computeScale;
private double scaleX;
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;
}
/**
}
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() {