RFR: JDK-8294427 - Check boxes and radio buttons have rendering issues on Windows in High DPI env [v12]

Rajat Mahajan rmahajan at openjdk.org
Thu Jun 8 20:41:49 UTC 2023


On Thu, 8 Jun 2023 07:37:41 GMT, Sergey Bylokhov <serb at openjdk.org> wrote:

>> So, we ask Windows for the component image based on a particular DPI , not some specific size.
>> The basic premise here is that we expect Windows returning image that would match the DPI , and then we perform our calculations accordingly. In the case above (if Region.clipRound is used) that basic premise is not met (if w, h=19) due to us calculating a DPI value of 140 which is closer to 120 or 125% scaling while our scaling is acytually 150% and Windows returns us a smaller size of the component than expected.
>> So we don't need to add extra code to rescale , I believe.
>> If we provide windows with correctly calculated DPI value which my code change does it should work fine as Windows will give us image of the correct size.
>
>> So, we ask Windows for the component image based on a particular DPI , not some specific size. The basic premise here is that we expect Windows returning image that would match the DPI , and then we perform our calculations accordingly. In the case above (if Region.clipRound is used) that basic premise is not met (if w, h=19) due to us calculating a DPI value of 140 which is closer to 120 or 125% scaling while our scaling is acytually 150% and Windows returns us a smaller size of the component than expected. So we don't need to add extra code to rescale , I believe. If we provide windows with correctly calculated DPI value which my code change does it should work fine as Windows will give us image of the correct size.
> 
> 
> =( I am still missing something.
> This is the code we discussing:
> 
>             int w = (int) Math.floor(destWidth + 0.5);
>             int h = (int) Math.floor(destHeight + 0.5);
> 
> It calculates the size of the image we would like to render, it does not calculate the DPI. So if our component is 100x100 in pixels we create the image of that [size](https://github.com/openjdk/jdk/blob/79a4ac791c826656b3e984fe54dc472c62efd028/src/java.desktop/share/classes/sun/swing/CachedPainter.java#L155) and put it into the cache. Later when want to render that image to the place where the component of size 100x100 is located we request it from the PainterMultiResolutionCachedImage.getResolutionVariant.
> 
> After this patch we create the image of one size using ceil, then request the image using floor, and it is somehow affected by the fact that the WIndows may return something different than requested.

The above code calls getImage() and passes width and height to it.

This is the flow :
getImage(){CachedPainter.java} -> paintToImage() {XPStyle.java} -> ThemeReader.paintBackground ()

We calculate and set scale in getImage() with this:

Line 172, CachedPainter.java

 if (volatileImage == null) {
     if ((w != baseWidth || h != baseHeight)) {
         g2.scale((double) w / baseWidth, 
                 (double) h / baseHeight); 
     }
     paintToImage(c, image, g2, baseWidth, baseHeight, args);
 }
 
 So, scale changes based on height and width of the image which we get from the
 code you mentioned above.
 
 This scale is then used in paintToImage() to calculate DPI at Line 711 of XPStyle.java:
 
   // Get DPI to pass further to ThemeReader.paintBackground()
  Graphics2D g2d = (Graphics2D) g;
  AffineTransform at = g2d.getTransform();
  int dpi = (int)(at.getScaleX() * 96);
 
 
 This DPI is then used to get the part size from windows and it changes as I explained in the previous comment.

-------------

PR Review Comment: https://git.openjdk.org/jdk/pull/13701#discussion_r1223525747



More information about the client-libs-dev mailing list