Bad character spacing (kerning) in JavaFX's font rendering (in Linux)
Asked Answered
L

2

7

I've started developing an application in JavaFX and I've run in an issue, I could find very little helpful information about: The spacing of between characters in Linux is very uneven. I'm not talking about the width of different characters but of the spaces between the characters.

It's visible in normal text, but the following example illustrates the effect better than normal text. Take a look at the first row. The space between the first two characters is smaller than between the second and third. This also happens between the sixth and seventh character and several others:

Uneven spacing of characters

Swing does not have this problem and JavaFX doesn't have this problem in Windows or it is barely visible on that OS. Neither does it appear to be a major issue on Mac. For comparison, here is a sample output on a Mac Retina MacBook Pro, mid-2014, running OS X 10.12.6 and Java 9.0.4:

enter image description here

Does anyone know if this is a bug in JavaFX's font rendering engine? If so, is there a workaround?

I'm really starting to wonder if I should change the framework as in my opinion such bad font rendering is not acceptable.

There is another question regarding this issue but it hasn't been answered, yet: Why does JavaFX add extra spacing between letters when using the Text component and how do I fix it?

I have been able reproduce this issue on two different Linux machines running Manjaro and in a virtual machine running Debian with the following code:

package de.localtoast.fonttest;

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class FontTest extends Application {

    @Override
    public void start(Stage primaryStage) {
        VBox root = new VBox();
        Label label1 = new Label("0000000000000000000000");
        Label label2 = new Label("OOOOOOOOOOOOOOOOOOOOOO");
        Label label3 = new Label("oooooooooooooooooooooo");

        root.getChildren().add(label1);
        root.getChildren().add(label2);
        root.getChildren().add(label3);

        Scene scene = new Scene(root, 300, 250);

        primaryStage.setTitle("Font Test");
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}
Longwood answered 6/3, 2018 at 16:54 Comment(9)
Characters have different widths in general. If you do not want this you need to use a monospaced font.Hausa
I've improved my explanation of the problem as my first explanation was misleading. I hope it can be better understood now.Longwood
It could be related to specific font kerning. Does changing the system font change/mitigate the problem?Reisman
I've done quite a bit of googling with the keyword kerning in the past few weeks and not a lot of good results turned up. I always end up on the same reddit page and two JDK bug reports: reddit.com/r/JavaFX/comments/5tswef/kerning_or_letter_spacing bugs.openjdk.java.net/browse/JDK-8091616 bugs.openjdk.java.net/browse/JDK-8136593 (but I'm not sure if the problems described there are my problem). I haven't tried changing the system font, but I have changed the font of my application to Roboto (and at some point Open Sans, I think). The problem persists.Longwood
Seems like the problem also exists on Macs: github.com/cryptomator/cryptomator/issues/540Longwood
Post your question to openjfx-dev mailing list. Some of the developers there will have a good understanding of the font rendering system used in JavaFX and may be able to provide you with some advice, explanations or input. As an aside, I don't think "Kerning" is the correct technical term for the output you are seeing, so it is perhaps not surprising that your googling for it does not show up much relevant info.Matty
I edited your question to also provide the output sample for a Mac, for comparison's sake.Matty
@jewelsea: Thanks for adding the output sample for Mac. I will follow your advice and post this problem to the mailing list.Longwood
Posting to the mailing list was a very good idea. I've already got an answer from the mailing list. Thanks again, jewelsea. It seems that it is a problem with the configuration of my Linux system and not with JavaFX itself. Subpixel rendering is disabled by default on Archlinux and that is probably the reason for the described effect. I will need a few days to verify this. If it can be solved by activating subpixel rendering I will post an appropriate answer and accept it.Longwood
L
5

jewelsea advised me to put my question on the openjfx-dex mailing list. The guys over there could explain what's going on:

It is not a problem of JavaFX but a configuration issue on my Linux system. JavaFX needs subpixel rendering to position the glyphs correctly. I'm using Manjaro, which is a derivative of Archlinux. In Archlinux, subpixel rendering is disabled by default, which has to do with patents covered by Microsoft.

In my case the problem could be solved by installing the freetype2-ultimate5 package from AUR, although the in the wiki mentioned freetype2-cleartype package is probably the better choice. But the latter one currently doesn't compile on my system because of another issue.

Longwood answered 7/3, 2018 at 21:24 Comment(0)
A
4

Adding -Dprism.lcdtext=false might help, at least on Linux it removes the painful off-colour sub-pixel antialiasing attempt by using grayscale instead which is much cleaner.

Ailsa answered 17/1, 2019 at 14:44 Comment(1)
This prism option completely solved my issue on Mac as well, which was displaying text both jagged and fragmented, as well as with multiple prism-like colours. Thank you so much! I was almost about to abandon the use of Java FX.Akkadian

© 2022 - 2024 — McMap. All rights reserved.