From 558d610bebb6967b4cfe922f62f1c4ba0df7daaf Mon Sep 17 00:00:00 2001 From: Alexey Ivanov Date: Thu, 19 Jan 2023 19:32:58 +0000 Subject: [PATCH] 8299553: Make ScaledEtchedBorderTest.java comprehensive Reviewed-by: serb, honkar, achung --- .../EtchedBorder/ScaledEtchedBorderTest.java | 362 +++++++++++------- .../LineBorder/ScaledLineBorderTest.java | 18 +- .../LineBorder/ScaledTextFieldBorderTest.java | 1 - 3 files changed, 236 insertions(+), 145 deletions(-) diff --git a/test/jdk/javax/swing/border/EtchedBorder/ScaledEtchedBorderTest.java b/test/jdk/javax/swing/border/EtchedBorder/ScaledEtchedBorderTest.java index 4db602f0e4d..283e80d7ea6 100644 --- a/test/jdk/javax/swing/border/EtchedBorder/ScaledEtchedBorderTest.java +++ b/test/jdk/javax/swing/border/EtchedBorder/ScaledEtchedBorderTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,6 @@ import java.awt.BorderLayout; import java.awt.Color; -import java.awt.Component; import java.awt.Dimension; import java.awt.Graphics2D; import java.awt.Point; @@ -31,30 +30,36 @@ import java.awt.image.BufferedImage; import java.io.File; import java.io.IOException; import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; import java.util.List; import javax.imageio.ImageIO; -import javax.swing.BorderFactory; import javax.swing.Box; -import javax.swing.BoxLayout; +import javax.swing.JComponent; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.SwingUtilities; +import static javax.swing.BorderFactory.createEmptyBorder; +import static javax.swing.BorderFactory.createEtchedBorder; + /* * @test - * @bug 8279614 + * @bug 8279614 8294921 * @summary The left line of the TitledBorder is not painted on 150 scale factor * @requires (os.family == "windows") * @run main ScaledEtchedBorderTest */ - public class ScaledEtchedBorderTest { - public static final Dimension SIZE = new Dimension(120, 20); + private static final Dimension SIZE = new Dimension(125, 25); - public static Color highlight = Color.RED; - public static Color shadow = Color.BLUE; + private static final Color OUTER_COLOR = Color.BLACK; + private static final Color INSIDE_COLOR = Color.WHITE; + private static final Color HIGHLIGHT = Color.RED; + private static final Color SHADOW = Color.BLUE; + private static final Color TRANSPARENT_COLOR = new Color(0x00000000, true); private static final double[] scales = {1.00, 1.25, 1.50, 1.75, 2.00, 2.50, 3.00}; @@ -66,165 +71,256 @@ public class ScaledEtchedBorderTest { new ArrayList<>(4); public static void main(String[] args) throws Exception { - boolean showFrame = args.length > 0 && "-show".equals(args[0]); - SwingUtilities.invokeAndWait(() -> testScaling(showFrame)); + Collection params = Arrays.asList(args); + final boolean showFrame = params.contains("-show"); + final boolean saveImages = params.contains("-save"); + SwingUtilities.invokeAndWait(() -> testScaling(showFrame, saveImages)); } - private static void testScaling(boolean show) { - createGUI(show); + private static void testScaling(boolean showFrame, boolean saveImages) { + JComponent content = createUI(); + if (showFrame) { + showFrame(content); + } - for (int i = 0; i < scales.length; i++) { + paintToImages(content, saveImages); + verifyBorderRendering(saveImages); + } + + private static void verifyBorderRendering(final boolean saveImages) { + String errorMessage = null; + int errorCount = 0; + for (int i = 0; i < images.size(); i++) { BufferedImage img = images.get(i); double scaling = scales[i]; - System.out.println("Testing scaling: " + scaling); + try { + int thickness = (int) Math.floor(scaling); + checkVerticalBorders(SIZE.width / 2, thickness, img); - // checking vertical border - int x = SIZE.width / 2; - checkVerticalBorder(x, img, scaling); - - for (Point p : panelLocations) { - int y = (int) (p.y * scaling) + SIZE.height / 2; - checkHorizontalBorder(y, img, scaling); - } - } - } - - private static void checkHorizontalBorder(int y, BufferedImage img, double scaling) { - int thickness = 0; - boolean checkShadow = false; - boolean checkHighlight = false; - for (int x = 0; x < img.getWidth(); x++) { - int color = img.getRGB(x, y); - if (!checkHighlight && !checkShadow) { - if (color == shadow.getRGB()) { - checkHighlight = true; - thickness++; - } else if (color == highlight.getRGB()) { - throw new RuntimeException("Horizontal Border was clipped or overdrawn."); + for (Point p : panelLocations) { + int y = (int) (p.y * scaling) + SIZE.height / 2; + checkHorizontalBorder(y, thickness, img); } - } else if (checkHighlight) { - if (color == shadow.getRGB()) { - thickness++; - } else if (color == highlight.getRGB()) { - verifyThickness(x, y, thickness, scaling, "Horizontal"); - checkHighlight = false; - checkShadow = true; - thickness = 1; - } else { - throw new RuntimeException("Horizontal Border has empty space between highlight and shadow."); + } catch (Error e) { + if (errorMessage == null) { + errorMessage = e.getMessage(); } - } else { - if (color == shadow.getRGB()) { - throw new RuntimeException("Border colors reversed."); - } else if (color == highlight.getRGB()) { - thickness++; - } else { - verifyThickness(x, y, thickness, scaling, "Horizontal"); - checkShadow = false; - thickness = 0; + errorCount++; + + System.err.printf("Scaling: %.2f\n", scaling); + e.printStackTrace(); + + // Save the image if it wasn't already saved + if (!saveImages) { + saveImage(img, getImageFileName(scaling)); } } } - } - private static void verifyThickness(int x, int y, int thickness, double scaling, String orientation) { - int expected = (int) Math.floor(scaling); - if (thickness != expected) { - throw new RuntimeException("Unexpected " + orientation + " Border thickness at x:" - + x + " y: " + y + ". Expected: " + expected + " Actual: " + thickness); + if (errorCount > 0) { + throw new Error("Test failed: " + + errorCount + " error(s) detected - " + + errorMessage); } } - private static void checkVerticalBorder(int x, BufferedImage img, double scaling) { - int thickness = 0; - boolean checkShadow = false; - boolean checkHighlight = false; - for (int y = 0; y < img.getHeight(); y++) { - int color = img.getRGB(x, y); - if (!checkHighlight && !checkShadow) { - if (color == shadow.getRGB()) { - checkHighlight = true; - thickness++; - } else if (color == highlight.getRGB()) { - throw new RuntimeException("Vertical Border was clipped or overdrawn."); - } - } else if (checkHighlight) { - if (color == shadow.getRGB()) { - thickness++; - } else if (color == highlight.getRGB()) { - verifyThickness(x, y, thickness, scaling, "Vertical"); - checkHighlight = false; - checkShadow = true; - thickness = 1; - } else { - throw new RuntimeException("Vertical Border has empty space between highlight and shadow."); - } - } else { - if (color == shadow.getRGB()) { - throw new RuntimeException("Border colors reversed."); - } else if (color == highlight.getRGB()) { - thickness++; - } else { - verifyThickness(x, y, thickness, scaling, "Vertical"); - checkShadow = false; - thickness = 0; - } - } - } + private static void checkVerticalBorders(final int x, + final int thickness, + final BufferedImage img) { + checkBorder(x, 0, + 0, 1, + thickness, img); } - private static void createGUI(boolean show) { - // Render content panel - JPanel contentPanel = new JPanel(); - contentPanel.setLayout(new BoxLayout(contentPanel, BoxLayout.Y_AXIS)); + private static void checkHorizontalBorder(final int y, + final int thickness, + final BufferedImage img) { + checkBorder(0, y, + 1, 0, + thickness, img); + } + + private enum State { + BACKGROUND, + LEFT_SHADOW, LEFT_HIGHLIGHT, + INSIDE, + RIGHT_SHADOW, RIGHT_HIGHLIGHT + } + + private static void checkBorder(final int xStart, final int yStart, + final int xStep, final int yStep, + final int thickness, + final BufferedImage img) { + final int width = img.getWidth(); + final int height = img.getHeight(); + + State state = State.BACKGROUND; + int borderThickness = 0; + + int x = xStart; + int y = yStart; + do { + do { + final int color = img.getRGB(x, y); + switch (state) { + case BACKGROUND: + if (color == SHADOW.getRGB()) { + state = State.LEFT_SHADOW; + borderThickness = 1; + } else if (color != OUTER_COLOR.getRGB() + && color != TRANSPARENT_COLOR.getRGB()) { + throwUnexpectedColor(x, y, color); + } + break; + + case LEFT_SHADOW: + if (color == SHADOW.getRGB()) { + borderThickness++; + } else if (color == HIGHLIGHT.getRGB()) { + if (borderThickness != thickness) { + throwWrongThickness(thickness, borderThickness, x, y); + } + borderThickness = 1; + state = State.LEFT_HIGHLIGHT; + } else { + throwUnexpectedColor(x, y, color); + } + break; + + case LEFT_HIGHLIGHT: + if (color == HIGHLIGHT.getRGB()) { + borderThickness++; + } else if (color == INSIDE_COLOR.getRGB()) { + if (borderThickness != thickness) { + throwWrongThickness(thickness, borderThickness, x, y); + } + borderThickness = 0; + state = State.INSIDE; + } else { + throwUnexpectedColor(x, y, color); + } + break; + + case INSIDE: + if (color == SHADOW.getRGB()) { + state = State.RIGHT_SHADOW; + borderThickness = 1; + } else if (color != INSIDE_COLOR.getRGB()) { + throwUnexpectedColor(x, y, color); + } + break; + + case RIGHT_SHADOW: + if (color == SHADOW.getRGB()) { + borderThickness++; + } else if (color == HIGHLIGHT.getRGB()) { + if (borderThickness != thickness) { + throwWrongThickness(thickness, borderThickness, x, y); + } + borderThickness = 1; + state = State.RIGHT_HIGHLIGHT; + } else { + throwUnexpectedColor(x, y, color); + } + break; + + case RIGHT_HIGHLIGHT: + if (color == HIGHLIGHT.getRGB()) { + borderThickness++; + } else if (color == OUTER_COLOR.getRGB()) { + if (borderThickness != thickness) { + throwWrongThickness(thickness, borderThickness, x, y); + } + borderThickness = 0; + state = State.BACKGROUND; + } else { + throwUnexpectedColor(x, y, color); + } + break; + } + } while (yStep > 0 && ((y += yStep) < height)); + } while (xStep > 0 && ((x += xStep) < width)); + } + + private static void throwWrongThickness(int thickness, int borderThickness, + int x, int y) { + throw new Error( + String.format("Wrong border thickness at %d, %d: %d vs %d", + x, y, borderThickness, thickness)); + } + + private static void throwUnexpectedColor(int x, int y, int color) { + throw new Error( + String.format("Unexpected color at %d, %d: %08x", + x, y, color)); + } + + private static JComponent createUI() { + Box contentPanel = Box.createVerticalBox(); + contentPanel.setBackground(OUTER_COLOR); Dimension childSize = null; for (int i = 0; i < 4; i++) { + JComponent filler = new JPanel(null); + filler.setBackground(INSIDE_COLOR); + filler.setPreferredSize(SIZE); + filler.setBounds(i, 0, SIZE.width, SIZE.height); + filler.setBorder(createEtchedBorder(HIGHLIGHT, SHADOW)); + JPanel childPanel = new JPanel(new BorderLayout()); - childPanel.setBorder(BorderFactory.createCompoundBorder( - BorderFactory.createEmptyBorder(0, i, 4, 4), - BorderFactory.createEtchedBorder(highlight, shadow))); - childPanel.add(Box.createRigidArea(SIZE), BorderLayout.CENTER); + childPanel.setBorder(createEmptyBorder(0, i, 4, 4)); + childPanel.add(filler, BorderLayout.CENTER); + childPanel.setBackground(OUTER_COLOR); contentPanel.add(childPanel); if (childSize == null) { childSize = childPanel.getPreferredSize(); } - childPanel.setBounds(0, childSize.height * i, childSize.width, childSize.height); + childPanel.setBounds(0, childSize.height * i, + childSize.width, childSize.height); + + panelLocations.add(childPanel.getLocation()); } contentPanel.setSize(childSize.width, childSize.height * 4); - for (double scaling : scales) { - // Create BufferedImage - BufferedImage buff = new BufferedImage((int) Math.ceil(contentPanel.getWidth() * scaling), - (int) Math.ceil(contentPanel.getHeight() * scaling), - BufferedImage.TYPE_INT_ARGB); - Graphics2D graph = buff.createGraphics(); - graph.scale(scaling, scaling); - // Painting panel onto BufferedImage - contentPanel.paint(graph); - graph.dispose(); - // Save each image ? -- Here it's useful for debugging - saveImage(buff, String.format("test%.2f.png", scaling)); - images.add(buff); - } - // Save coordinates of the panels - for (Component comp : contentPanel.getComponents()) { - panelLocations.add(comp.getLocation()); - } + return contentPanel; + } - if (show) { - JFrame frame = new JFrame("Swing Test"); - frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); - frame.getContentPane().add(contentPanel, BorderLayout.CENTER); - frame.pack(); - frame.setLocationRelativeTo(null); - frame.setVisible(true); + private static void showFrame(final JComponent content) { + JFrame frame = new JFrame("Scaled Etched Border Test"); + frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + frame.getContentPane().add(content, BorderLayout.CENTER); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + private static void paintToImages(final JComponent content, + final boolean saveImages) { + for (double scaling : scales) { + BufferedImage image = + new BufferedImage((int) Math.ceil(content.getWidth() * scaling), + (int) Math.ceil(content.getHeight() * scaling), + BufferedImage.TYPE_INT_ARGB); + + Graphics2D g2d = image.createGraphics(); + g2d.scale(scaling, scaling); + content.paint(g2d); + g2d.dispose(); + + if (saveImages) { + saveImage(image, getImageFileName(scaling)); + } + images.add(image); } } + private static String getImageFileName(final double scaling) { + return String.format("test%.2f.png", scaling); + } + private static void saveImage(BufferedImage image, String filename) { try { ImageIO.write(image, "png", new File(filename)); diff --git a/test/jdk/javax/swing/border/LineBorder/ScaledLineBorderTest.java b/test/jdk/javax/swing/border/LineBorder/ScaledLineBorderTest.java index 2d858a8039b..fc83b49597d 100644 --- a/test/jdk/javax/swing/border/LineBorder/ScaledLineBorderTest.java +++ b/test/jdk/javax/swing/border/LineBorder/ScaledLineBorderTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,6 @@ import java.awt.BorderLayout; import java.awt.Color; -import java.awt.Component; import java.awt.Dimension; import java.awt.Graphics2D; import java.awt.Point; @@ -138,6 +137,10 @@ public class ScaledLineBorderTest { thickness, img); } + private enum State { + BACKGROUND, LEFT, INSIDE, RIGHT + } + private static void checkBorder(final int xStart, final int yStart, final int xStep, final int yStep, final int thickness, @@ -204,10 +207,6 @@ public class ScaledLineBorderTest { } while (xStep > 0 && ((x += xStep) < width)); } - private enum State { - BACKGROUND, LEFT, INSIDE, RIGHT - } - private static void throwWrongThickness(int thickness, int borderThickness, int x, int y) { throw new Error( @@ -243,15 +242,12 @@ public class ScaledLineBorderTest { childSize = childPanel.getPreferredSize(); } childPanel.setBounds(0, childSize.height * i, childSize.width, childSize.height); + + panelLocations.add(childPanel.getLocation()); } contentPanel.setSize(childSize.width, childSize.height * 4); - // Save coordinates of the panels - for (Component comp : contentPanel.getComponents()) { - panelLocations.add(comp.getLocation()); - } - return contentPanel; } diff --git a/test/jdk/javax/swing/border/LineBorder/ScaledTextFieldBorderTest.java b/test/jdk/javax/swing/border/LineBorder/ScaledTextFieldBorderTest.java index ea8254c401a..4b076977313 100644 --- a/test/jdk/javax/swing/border/LineBorder/ScaledTextFieldBorderTest.java +++ b/test/jdk/javax/swing/border/LineBorder/ScaledTextFieldBorderTest.java @@ -23,7 +23,6 @@ import java.awt.BorderLayout; import java.awt.Color; -import java.awt.Component; import java.awt.Dimension; import java.awt.Graphics2D; import java.awt.Point;