RFR: 8211294: [windows] TextArea content is blurry with 125% scaling

Frederic Thevenet fthevenet at openjdk.java.net
Mon Dec 14 11:20:00 UTC 2020

On Sat, 12 Dec 2020 22:31:56 GMT, Kevin Rushforth <kcr at openjdk.org> wrote:

>> I spent a bit of time looking at this. I think the root cause of the problem is in ScrollPane itself. It is attempting to layout its children by doing a snap to pixel (meaning that the final scaled translation should be an integer value), but it is failing to do so. This is mostly not a problem when caching is disabled, since our text rendering does sub-pixel antialiasing that looks crisp even at non-integer boundaries. However, translating an already-rendered image by a non-integer boundary will cause the blurriness we are seeing. There is another issue with the Y translation which isn't 0 even when  not using a ScrollPane.
>> I'll continue looking at this in the coming week.
> One more comment: given the quality problems that necessarily arise when the translation of a cached image is not on an integer boundary, part of the solution might be to snap the cached image to a pixel boundary as is done in this PR, but we would need to ensure that this doesn't impact smooth scrolling of a TextArea.

Further investigations on my part raised one more question, which hopefully you can answer:
To which extend should `setSnapToPixel` ensure children of a region are indeed snap to whole pixel coordinates?

To make it clearer, please consider the following sample:
public class Blur extends Application {
    public void start(final Stage stage) throws Exception {
        var root = new Pane();
        var ctrl = new CheckBox("Cached");


        var ctrl2 = new Button("Foo");

        var ctrl3 = new Button("Bar");

        root.getChildren().addAll(ctrl, ctrl2, ctrl3);
        Scene scene;
        scene = new Scene(root, 200, 200);

        stage.setTitle("Blur test");

    public static void main(String[] args) {


In this sample, LayoutX and Y properties are deliberately set to non integer values for the first two controls (the last one serves as a visual baseline, but `snapToPixel` is  set to true. Also clicking the check box toggles caching for all controls.

Here's what it looks looks **at 100% scaling**, (OpenJFX 15.0.1), with cache enabled:

and with cache disabled:

What is the legitimate result to expect here; should `root.setSnapToPixel(true);` override `setLayoutX(0.5);` and align everything for crisp rendering (as is my understanding)? Or am I misunderstanding the scope of `setSnapToPixel` and it has no effect when layout is set explicitly?


PR: https://git.openjdk.java.net/jfx/pull/308

More information about the openjfx-dev mailing list