On Sat, 12 Dec 2020 22:31:56 GMT, Kevin Rushforth <k...@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