11/*
2- * Copyright (c) 2022, 2023 , Oracle and/or its affiliates. All rights reserved.
2+ * Copyright (c) 2022, 2025 , Oracle and/or its affiliates. All rights reserved.
33 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44 *
55 * This code is free software; you can redistribute it and/or modify it
4242import javax .swing .JPanel ;
4343import javax .swing .SwingUtilities ;
4444
45+ import static sun .java2d .pipe .Region .clipRound ;
46+
4547/*
4648 * @test
47- * @bug 8282958
49+ * @bug 8282958 8349188
4850 * @summary Verify LineBorder edges have the same width
4951 * @requires (os.family == "windows")
52+ * @modules java.desktop/sun.java2d.pipe
5053 * @run main ScaledLineBorderTest
5154 */
5255public class ScaledLineBorderTest {
53- private static final Dimension SIZE = new Dimension (120 , 25 );
56+ private static final Dimension SIZE = new Dimension (250 , 50 );
5457
5558 private static final Color OUTER_COLOR = Color .BLACK ;
5659 private static final Color BORDER_COLOR = Color .RED ;
@@ -59,12 +62,19 @@ public class ScaledLineBorderTest {
5962
6063 private static final double [] scales =
6164 {1.00 , 1.25 , 1.50 , 1.75 , 2.00 , 2.50 , 3.00 };
65+ private static final int [] thickness = {1 , 4 , 10 , 15 };
66+
67+ private record TestImage (BufferedImage image ,
68+ List <Point > panelLocations ,
69+ double scale ,
70+ int thickness ) {
71+ }
6272
63- private static final List <BufferedImage > images =
64- new ArrayList <>(scales .length );
73+ private record TestUI (JComponent content ,
74+ List <Point > panelLocations ,
75+ int thickness ) {
76+ }
6577
66- private static final List <Point > panelLocations =
67- new ArrayList <>(4 );
6878
6979 public static void main (String [] args ) throws Exception {
7080 Collection <String > params = Arrays .asList (args );
@@ -74,51 +84,52 @@ public static void main(String[] args) throws Exception {
7484 }
7585
7686 private static void testScaling (boolean showFrame , boolean saveImages ) {
77- JComponent content = createUI ();
78- if (showFrame ) {
79- showFrame (content );
87+ for (int thickness : thickness ) {
88+ TestUI testUI = createUI (thickness );
89+ if (showFrame ) {
90+ showFrame (testUI .content );
91+ }
92+
93+ List <TestImage > images = paintToImages (testUI , saveImages );
94+ verifyBorderRendering (images , saveImages );
95+ }
96+
97+ if (errorCount > 0 ) {
98+ throw new Error ("Test failed: "
99+ + errorCount + " error(s) detected - "
100+ + errorMessage );
80101 }
81102
82- paintToImages (content , saveImages );
83- verifyBorderRendering (saveImages );
84103 }
85104
86- private static void verifyBorderRendering (final boolean saveImages ) {
87- String errorMessage = null ;
88- int errorCount = 0 ;
89- for (int i = 0 ; i < images .size (); i ++) {
90- BufferedImage img = images .get (i );
91- double scaling = scales [i ];
92- try {
93- int thickness = (int ) Math .floor (scaling );
105+ private static String errorMessage = null ;
106+ private static int errorCount = 0 ;
94107
95- checkVerticalBorders (SIZE .width / 2 , thickness , img );
108+ private static void verifyBorderRendering (final List <TestImage > images ,
109+ final boolean saveImages ) {
110+ for (TestImage test : images ) {
111+ final BufferedImage img = test .image ;
112+ final int effectiveThickness = clipRound (test .thickness * test .scale );
113+ try {
114+ checkVerticalBorders ((int ) (SIZE .width * test .scale / 2 ), effectiveThickness , img );
96115
97- for (Point p : panelLocations ) {
98- int y = (int ) (p .y * scaling ) + SIZE .height / 2 ;
99- checkHorizontalBorder (y , thickness , img );
116+ for (Point p : test . panelLocations ) {
117+ int y = (int ) (( p .y + ( SIZE .height / 2 )) * test . scale ) ;
118+ checkHorizontalBorder (y , effectiveThickness , img );
100119 }
101120 } catch (Error e ) {
102121 if (errorMessage == null ) {
103122 errorMessage = e .getMessage ();
104123 }
105124 errorCount ++;
106125
107- System .err .printf ("Scaling: %.2f\n " , scaling );
126+ System .err .printf ("Scale: %.2f; thickness: %d, effective: %d\n " ,
127+ test .scale , test .thickness , effectiveThickness );
108128 e .printStackTrace ();
109129
110- // Save the image if it wasn't already saved
111- if (!saveImages ) {
112- saveImage (img , getImageFileName (scaling ));
113- }
130+ saveImage (img , getImageFileName (test .scale , test .thickness ));
114131 }
115132 }
116-
117- if (errorCount > 0 ) {
118- throw new Error ("Test failed: "
119- + errorCount + " error(s) detected - "
120- + errorMessage );
121- }
122133 }
123134
124135 private static void checkVerticalBorders (final int x ,
@@ -220,17 +231,19 @@ private static void throwUnexpectedColor(int x, int y, int color) {
220231 x , y , color ));
221232 }
222233
223- private static JComponent createUI () {
234+ private static TestUI createUI (int thickness ) {
224235 Box contentPanel = Box .createVerticalBox ();
225236 contentPanel .setBackground (OUTER_COLOR );
226237
238+ List <Point > panelLocations = new ArrayList <>(4 );
239+
227240 Dimension childSize = null ;
228241 for (int i = 0 ; i < 4 ; i ++) {
229242 JComponent filler = new JPanel (null );
230243 filler .setBackground (INSIDE_COLOR );
231244 filler .setPreferredSize (SIZE );
232245 filler .setBounds (i , 0 , SIZE .width , SIZE .height );
233- filler .setBorder (BorderFactory .createLineBorder (BORDER_COLOR ));
246+ filler .setBorder (BorderFactory .createLineBorder (BORDER_COLOR , thickness ));
234247
235248 JPanel childPanel = new JPanel (new BorderLayout ());
236249 childPanel .setBorder (BorderFactory .createEmptyBorder (0 , i , 4 , 4 ));
@@ -248,7 +261,7 @@ private static JComponent createUI() {
248261
249262 contentPanel .setSize (childSize .width , childSize .height * 4 );
250263
251- return contentPanel ;
264+ return new TestUI ( contentPanel , panelLocations , thickness ) ;
252265 }
253266
254267 private static void showFrame (JComponent content ) {
@@ -260,28 +273,33 @@ private static void showFrame(JComponent content) {
260273 frame .setVisible (true );
261274 }
262275
263- private static void paintToImages (final JComponent content ,
264- final boolean saveImages ) {
265- for (double scaling : scales ) {
276+ private static List <TestImage > paintToImages (final TestUI testUI ,
277+ final boolean saveImages ) {
278+ final List <TestImage > images = new ArrayList <>(scales .length );
279+ final JComponent content = testUI .content ;
280+ for (double scale : scales ) {
266281 BufferedImage image =
267- new BufferedImage ((int ) Math .ceil (content .getWidth () * scaling ),
268- (int ) Math .ceil (content .getHeight () * scaling ),
282+ new BufferedImage ((int ) Math .ceil (content .getWidth () * scale ),
283+ (int ) Math .ceil (content .getHeight () * scale ),
269284 BufferedImage .TYPE_INT_ARGB );
270285
271286 Graphics2D g2d = image .createGraphics ();
272- g2d .scale (scaling , scaling );
287+ g2d .scale (scale , scale );
273288 content .paint (g2d );
274289 g2d .dispose ();
275290
276291 if (saveImages ) {
277- saveImage (image , getImageFileName (scaling ));
292+ saveImage (image , getImageFileName (scale , testUI . thickness ));
278293 }
279- images .add (image );
294+ images .add (new TestImage (image , testUI .panelLocations ,
295+ scale , testUI .thickness ));
280296 }
297+ return images ;
281298 }
282299
283- private static String getImageFileName (final double scaling ) {
284- return String .format ("test%.2f.png" , scaling );
300+ private static String getImageFileName (final double scaling ,
301+ final int thickness ) {
302+ return String .format ("test%02d@%.2f.png" , thickness , scaling );
285303 }
286304
287305 private static void saveImage (BufferedImage image , String filename ) {
0 commit comments