On Mon, 21 Dec 2020 18:49:11 GMT, Frederic Thevenet <ftheve...@openjdk.org> wrote:
>> This PR aims to fix the blurriness to sometimes affects some controls (such >> as TextArea) in a scene when rendered with a scaling factor that is not an >> integer (typically when viewed on a HiDPI screen with a 125%, 150% or 175% >> output scaling). >> >> Please note that regardless of what the JBS issue (and therefore the title >> of this PR) states, this does not appear to be a Windows only issue as I >> have observed the same issue on Linux (Ubuntu 20.04). >> >> The following conditions are necessary for the blurriness to appear, but do >> not guarantee that it will: >> >> - The node, or one of its parents, must have set `Node::cacheProperty` to >> `true` >> >> - The scaling factor (as detected automatically or explicitly set via >> glass.win/gtk.uiScale) must be a non integer number (e.g. 1.25, 1.5, 175) >> >> - The effective layout X or Y coordinates for the cached node must be != 0; >> >> Under these conditions, the translate coordinates for the transform used >> when the cached image for a node is rendered to the screen may be non >> integer numbers, which is the cause for the blurriness. >> >> Based on these observations, this PR fixes the issue by simply rounding the >> translate coordinates (using `Math.round`) before the transform is applied >> in `renderCacheToScreen()` and as far as I can tell, it fixes the blurriness >> in all the previously affected applications (both trivial test cases or with >> complex scenegraphs) and does not appear to introduce other noticeable >> visual artifacts. >> >> Still, there might be a better place somewhere else higher up in the call >> chain where this should be addressed as it could maybe be the root cause for >> other rendering glitches, though I'm not yet familiar enough with the code >> to see if it is really the case. > > Frederic Thevenet has updated the pull request incrementally with one > additional commit since the last revision: > > Added a test The test and the fix look good. I left a couple inline comments. modules/javafx.graphics/src/main/java/javafx/scene/layout/Region.java line 947: > 945: > 946: /** > 947: * Cached snapScale values, used for to determine if snapped cached > insets values Minor typo: `for to` --> `to` modules/javafx.graphics/src/main/java/javafx/scene/layout/Region.java line 1825: > 1823: public final double snappedTopInset() { > 1824: // invalidate the cached values for snapped inset dimensions > 1825: // if the screen scale changed since they were last computed. Minor: Maybe copy this comment to the other 4 methods for consistency? tests/system/src/test/java/test/javafx/scene/UIRenderSnapToPixelTest.java line 77: > 75: if (node instanceof ScrollPane) { > 76: var sp = (ScrollPane) node; > 77: Assert.assertEquals("Top inset not snapped to pixel", 0, > (sp.snappedTopInset() * scale) % 1, 0.0001); This could fail if snapped inset * scale is just less than an integer pixel. For example, if `sp.snappedTopInset() * scale` is 1.999999, then `(sp.snappedTopInset() * scale) % 1` would be 0.999999 which would fail. I suggest adding an epsilon value (perhaps 0.00001 so it won't affect the delta comparison) before doing the modulo. ------------- PR: https://git.openjdk.java.net/jfx/pull/308