JDK-8349188 : LineBorder does not scale correctly
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 11.0.19,17.0.7,20,21,23,24,25
  • Priority: P3
  • Status: In Progress
  • Resolution: Unresolved
  • OS: windows
  • CPU: x86_64
  • Submitted: 2025-01-31
  • Updated: 2025-06-10
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
tbdUnresolved
Related Reports
Causes :  
Relates :  
Description
ADDITIONAL SYSTEM INFORMATION :
Windows 11
JDK 21.0.3

A DESCRIPTION OF THE PROBLEM :
LineBorder does not scale correctly. With my OS set to 150% scale for example, the width of the LineBorder is the same as with my OS at 100% scale.

The bug is new since JDK 17.0.3. It works as expected in that version.

I believe the bug is in the following line of code in javax.swing.border.LineBorder:

  int offs = this.thickness * (int) scaleFactor;

Note how scaleFactor is cast to an int before being used, thus losing the fractional part! This means that a scaling factor of 1.5 will result in an effective scale factor of 1. And a scale factor of 0.5 will result in an effective scale factor of 0 (making the border disappear entirely).

REGRESSION : Last worked in version 17

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Set your OS scaling to 150% via the OS settings
2. Run the code below
3. Print screen the Java app and paste it to a paint program
4. Measure the width of the red border in pixels

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The border is 15 pixels wide
ACTUAL -
The border is 10 pixels wide

---------- BEGIN SOURCE ----------
import javax.swing.*;
import javax.swing.border.LineBorder;
import java.awt.*;

public class LineBorderBug {
    public static void main(String[] args) {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setSize(100, 100);
        JPanel panel = new JPanel();
        panel.setBorder(new LineBorder(Color.RED, 10));
        frame.add(panel);
        frame.setVisible(true);
    }
}
---------- END SOURCE ----------

FREQUENCY : always
Comments
Attached a screenshot, "LineBorder - 17.0.6 vs 17.0.7.png", of the reproducer running in 17.0.6 and 17.0.7 side by side at a display with 150% scale.
10-03-2025

This regression is caused by JDK-8282958 where the change was introduced. The referenced JDK-8294680 didn't change rendering, it just moved around the code to avoid duplicating code. I've updated the Affects Versions and Introduced in Version fields.
10-03-2025

It was a deliberate decision to lose the fractional part. This worked well for borders of 1-pixel thickness. However, for thicker borders, such calculations lead to losing pixels which otherwise would be rendered. A better solution is to use the following formula: int offs = (int) (this.thickness * scaleFactor); which preserves all the scaled non-fractional pixels. This means, 2-pixel border at 150% scale will be rendered as 3 pixels. At the same time, the above change may not play well with the content of the component inside: the rendered component, depending its location and size, may lose a pixel on the left or right, or at the top or bottom.
07-03-2025

LineBorder code refactored in JDK-8294680
03-02-2025

The observations on Windows 11: JDK 8: Passed, the border is 15 pixels wide JDK 11.0.18+10: Passed. JDK 11.0.18.0.1+1:Failed, the border is 10 pixels wide JDK 17: Failed. JDK 21: Failed. JDK 23: Failed. JDK 25ea+6: Failed.
02-02-2025