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:
java
public class Blur extends Application {
@Override
public void start(final Stage stage) throws Exception {
var root = new Pane();
root.setSnapToPixel(true);
var ctrl = new CheckBox("Cached");
ctrl.setLayoutX(0.5);
ctrl.setLayoutY(0.5);
ctrl.cacheProperty().bind(ctrl.selectedProperty());
ctrl.setSelected(true);
var ctrl2 = new Button("Foo");
ctrl2.setLayoutX(0.5);
ctrl2.setLayoutY(30.5);
ctrl2.cacheProperty().bind(ctrl.selectedProperty());
var ctrl3 = new Button("Bar");
ctrl3.setLayoutY(60);
ctrl3.cacheProperty().bind(ctrl.selectedProperty());
root.getChildren().addAll(ctrl, ctrl2, ctrl3);
Scene scene;
scene = new Scene(root, 200, 200);
stage.setTitle("Blur test");
stage.setScene(scene);
stage.show();
}
public static void main(String[] args) {
launch(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