はじめに
JavaFx font rendering low quality などで検索すると山ほどでてくる昔からの問題。
実例
以下のようなコード。
public class App extends Application { @Override public void start(Stage stage) { var vbox = new VBox(canvas1(), canvas2(), stackPaneText(), stackPaneLabel()); vbox.setStyle("-fx-background-color: #000;"); var scene = new Scene(vbox, 600, 200); scene.setFill(Color.TRANSPARENT); stage.setScene(scene); stage.setTitle("font-rendering-quality"); stage.show(); } private Canvas canvas1() { var canvas = new Canvas(600, 25); var gc = canvas.getGraphicsContext2D(); gc.setFontSmoothingType(FontSmoothingType.LCD); gc.setFill(Color.WHITE); gc.fillText("Font Rendering Quality : フォントレンダリング品質(Canvas LCD)", 13, 20); return canvas; } private Canvas canvas2() { var canvas = new Canvas(600, 25); var gc = canvas.getGraphicsContext2D(); gc.setFontSmoothingType(FontSmoothingType.GRAY); gc.setFill(Color.WHITE); gc.fillText("Font Rendering Quality : フォントレンダリング品質(Canvas GRAY)", 13, 20); return canvas; } private Pane stackPaneText() { var pane = new StackPane(); Text text = new Text("Font Rendering Quality : フォントレンダリング品質(StackPane + Text)"); text.setFill(Color.WHITE); StackPane.setAlignment(text, Pos.CENTER_LEFT); StackPane.setMargin(text, new Insets(10, 0, 0, 13)); pane.getChildren().add(text); return pane; } private Pane stackPaneLabel() { var pane = new StackPane(); Label label = new Label("Font Rendering Quality : フォントレンダリング品質(StackPane + Label)"); label.setTextFill(Color.WHITE); label.setPadding(new Insets(10, 0, 0, 13)); StackPane.setAlignment(label, Pos.CENTER_LEFT); pane.getChildren().add(label); return pane; } private Canvas canvasRecoat() { var canvas = new Canvas(600, 25); var gc = canvas.getGraphicsContext2D(); gc.setFontSmoothingType(FontSmoothingType.LCD); gc.setFill(Color.WHITE); gc.fillText("Font Rendering Quality : フォントレンダリング品質(Canvas LCD 重ね塗り)", 13, 20); gc.fillText("Font Rendering Quality : フォントレンダリング品質(Canvas LCD 重ね塗り)", 13, 20); return canvas; } }
手元の MacOS 上(JavaFX25)での出力は以下。

拡大すると

漢字部分は特にぼやけ、明瞭ではない。
もっと拡大すると

フォントを選べば少しマシに見えることもあるが、いずれにしても日本語は厳しい。 これは Windows でも同様。
巷でよく聞く対応策
以下のシステムプロパティ設定
System.setProperty("prism.lcdtext", "false");
変わらず

以下のシステムプロパティ設定
System.setProperty("prism.text", "t2k");
変わらず

以下のシステムプロパティ設定
System.setProperty("prism.text", "t2k"); System.setProperty("prism", "lcdtext");
変わらず

あと、snapToPixel を有効にするもの。
vbox.setSnapToPixel(true);
まぁ、これはデフォルトで true なので変わるはずがない。

重ね塗り
唯一それなりにマシになるのは、重ね塗り。
private Canvas canvasRecoat() { var canvas = new Canvas(600, 25); var gc = canvas.getGraphicsContext2D(); gc.setFontSmoothingType(FontSmoothingType.LCD); gc.setFill(Color.WHITE); gc.fillText("Font Rendering Quality : フォントレンダリング品質(Canvas LCD 重ね塗り)", 13, 20); gc.fillText("Font Rendering Quality : フォントレンダリング品質(Canvas LCD 重ね塗り)", 13, 20); return canvas; }

拡大すると

根本的には Prism 側に直接手を入れないとダメそう。
Metal レンダリングパイプライン
JavaFX 27 では Metal が macOS のデフォルトレンダリングパイプラインになる(旧来はOpenGLベースのES2パイプラインがデフォルト)。これで多少は改善されるか?
JavaFX 26 でもシステムプロパティの設定で切り替えることができる。
System.setProperty("prism.order", "mtl,es2,sw"); System.setProperty("prism.verbose", "true");
このあたりの設定は以下を見ると良い
まぁ、以下のように変化は見られない。
