RFR: JDK-8294427 - Check boxes and radio buttons have rendering issues on Windows in High DPI env [v14]
Sergey Bylokhov
serb at openjdk.org
Mon Jun 12 20:42:01 UTC 2023
On Mon, 12 Jun 2023 19:59:00 GMT, Alexey Ivanov <aivanov at openjdk.org> wrote:
>> II am not sure that is correct way to calculate the dpi based on the "adhoc" change of the image size. That will add the mismatch between the code where we create the image, and the code where we request the image. We probably should change them both, or calculate the dpi in some other way.
>>
>> Also the fact that on the image above one component is rendered twice smaller that another make me think that we did not rescale the image if the Windows return the image of the different size(You probably can prove that by always returning the wrong size from the native and check how it will look on HiDPI screen)
>
>> II am not sure that is correct way to calculate the dpi based on the "adhoc" change of the image size. That will add the mismatch between the code where we create the image, and the code where we request the image.
>
> There's always a mismatch (at this time). We already discussed it [above](https://github.com/openjdk/jdk/pull/13701#discussion_r1195604571).
>
> For example, for 125% scale, Windows returns 13×13 like for 100%; yet Swing expects 16.25. This is handled by rendering the 13×13-sized theme background into 16×16-sized bitmap — *to avoid any scale transformations being applied* to keep the image *crisp*.
>
>> We probably should change them both, or calculate the dpi in some other way.
>
> The DPI is calculated based on the scale set on the Graphics. Rajat provided the relevant excerpt:
>
> https://github.com/openjdk/jdk/blob/727836ea85394b8baacd19a834f2993f06084c44/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/XPStyle.java#L708-L711
>
> This scale is calculated based on the size of the image.
>
> So, we probably should… change. As [I already said](https://github.com/openjdk/jdk/pull/13701#discussion_r1195604571), this fix should've been as simple as a `MultiResolutionImage` where [`getResolutionVariant`](https://github.com/openjdk/jdk/blob/a780bf0dda4c2c3dce4337ccea37bcdce52045de/src/java.desktop/share/classes/sun/swing/CachedPainter.java#L316) returns the image of the correct size if it's already stored or retrieves it from the system. But it's not the case, and `CachedPainter` seems to be a hindrance rather than a helper.
>
> That being said, we're planning to look further into simplifying it. Perhaps, `XPStyle.SkinPainter` shouldn't extend `CachedPainter`…
>
>> Also the fact that on the image above one component is rendered twice smaller that another make me think that we did not rescale the image if the Windows return the image of the different size(You probably can prove that by always returning the wrong size from the native and check how it will look on HiDPI screen)
>
> The point of the this fix is to *avoid rescaling* what Windows returns. And it *succeeds*: check boxes and radio buttons look much better — sharper and crisper — when you drag Swing UI frame from a display with one DPI to that with another; they even look better on the main display if its DPI is 120 or 168, that is 125% and 175% correspondingly.
> > II am not sure that is correct way to calculate the dpi based on the "adhoc" change of the image size. That will add the mismatch between the code where we create the image, and the code where we request the image.
>
> There's always a mismatch (at this time). We already discussed it [above](https://github.com/openjdk/jdk/pull/13701#discussion_r1195604571).
>
> For example, for 125% scale, Windows returns 13×13 like for 100%; yet Swing expects 16.25. This is handled by rendering the 13×13-sized theme background into 16×16-sized bitmap — _to avoid any scale transformations being applied_ to keep the image _crisp_.
Are you sure? Currently the code for image [creation](https://github.com/openjdk/jdk/blob/79a4ac791c826656b3e984fe54dc472c62efd028/src/java.desktop/share/classes/sun/swing/CachedPainter.java#L155) and the image [requests](https://github.com/openjdk/jdk/blob/79a4ac791c826656b3e984fe54dc472c62efd028/src/java.desktop/share/classes/sun/swing/CachedPainter.java#L317) use the same "ceil" logic.
> The DPI is calculated based on the scale set on the Graphics. Rajat provided the relevant excerpt:
>
> https://github.com/openjdk/jdk/blob/727836ea85394b8baacd19a834f2993f06084c44/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/XPStyle.java#L708-L711
>
> This scale is calculated based on the size of the image.
I am still would like to get clarification about the size we changed by the patch, is it a size of the destination area we should render the component to, or something different. If it is a size of the destination area how we can change that to calculate the DPI?
> > Also the fact that on the image above one component is rendered twice smaller that another make me think that we did not rescale the image if the Windows return the image of the different size(You probably can prove that by always returning the wrong size from the native and check how it will look on HiDPI screen)
>
> The point of the this fix is to _avoid rescaling_ what Windows returns. And it _succeeds_: check boxes and radio buttons look much better — sharper and crisper — when you drag Swing UI frame from a display with one DPI to that with another; they even look better on the main display if its DPI is 120 or 168, that is 125% and 175% correspondingly.
Since we cannot guarantee that the Windows always return exact size we should have a backup code to rescale the image.
-------------
PR Review Comment: https://git.openjdk.org/jdk/pull/13701#discussion_r1227217269
More information about the client-libs-dev
mailing list