diff --git a/src/java.desktop/share/classes/java/awt/font/TextLine.java b/src/java.desktop/share/classes/java/awt/font/TextLine.java index 6db1bc723607f..858c35ede873c 100644 --- a/src/java.desktop/share/classes/java/awt/font/TextLine.java +++ b/src/java.desktop/share/classes/java/awt/font/TextLine.java @@ -396,10 +396,7 @@ public Rectangle getPixelBounds(FontRenderContext frc, float x, float y) { BufferedImage.TYPE_INT_ARGB); Graphics2D g2d = im.createGraphics(); - g2d.setColor(Color.WHITE); - g2d.fillRect(0, 0, im.getWidth(), im.getHeight()); - - g2d.setColor(Color.BLACK); + g2d.setColor(Color.WHITE); // white over transparent black bg draw(g2d, rx + MARGIN - bounds.x, ry + MARGIN - bounds.y); result = computePixelBounds(im); @@ -428,7 +425,7 @@ static Rectangle computePixelBounds(BufferedImage im) { loop: while (++t < h) { im.getRGB(0, t, buf.length, 1, buf, 0, w); // w ignored for (int i = 0; i < buf.length; i++) { - if (buf[i] != -1) { + if (buf[i] != 0) { break loop; } } @@ -441,7 +438,7 @@ static Rectangle computePixelBounds(BufferedImage im) { loop: while (--b > t) { im.getRGB(0, b, buf.length, 1, buf, 0, w); // w ignored for (int i = 0; i < buf.length; ++i) { - if (buf[i] != -1) { + if (buf[i] != 0) { break loop; } } @@ -454,7 +451,7 @@ static Rectangle computePixelBounds(BufferedImage im) { loop: while (++l < r) { for (int i = t; i < b; ++i) { int v = im.getRGB(l, i); - if (v != -1) { + if (v != 0) { break loop; } } @@ -466,7 +463,7 @@ static Rectangle computePixelBounds(BufferedImage im) { loop: while (--r > l) { for (int i = t; i < b; ++i) { int v = im.getRGB(r, i); - if (v != -1) { + if (v != 0) { break loop; } } diff --git a/test/jdk/java/awt/font/TextLayout/TestGetPixelBoundsWithColors.java b/test/jdk/java/awt/font/TextLayout/TestGetPixelBoundsWithColors.java new file mode 100644 index 0000000000000..dd1fb2f1842fc --- /dev/null +++ b/test/jdk/java/awt/font/TextLayout/TestGetPixelBoundsWithColors.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2025, 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 6562639 + * @summary Verify correct getPixelBounds() behavior regardless of text color. + */ + +import java.awt.Color; +import java.awt.Font; +import java.awt.Rectangle; +import java.awt.font.FontRenderContext; +import java.awt.font.TextAttribute; +import java.awt.font.TextLayout; +import java.awt.geom.Rectangle2D; +import java.util.HashMap; +import java.util.Map; + +public class TestGetPixelBoundsWithColors { + + private static final Color TRANSPARENT_BLACK = new Color(0, 0, 0, 0); + private static final Color TRANSPARENT_WHITE = new Color(255, 255, 255, 0); + + public static void main(String[] args) throws Exception { + + Color[] colors = new Color[] { + Color.WHITE, Color.BLACK, Color.YELLOW, Color.RED, Color.GREEN, + Color.GRAY, Color.LIGHT_GRAY, Color.DARK_GRAY, Color.PINK, + Color.CYAN, Color.MAGENTA, Color.BLUE, null + }; + + for (Color color : colors) { + test(color); + } + + testTransparent(TRANSPARENT_BLACK); + testTransparent(TRANSPARENT_WHITE); + } + + private static void test(Color c) { + Map< TextAttribute, Object > underline = new HashMap<>(); + underline.put(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON); + Font font1 = new Font(Font.DIALOG, Font.PLAIN, 60).deriveFont(underline); + Map< TextAttribute, Object > foreground = new HashMap<>(); + foreground.put(TextAttribute.FOREGROUND, c); + Font font2 = font1.deriveFont(foreground); + FontRenderContext frc = new FontRenderContext(null, true, true); + TextLayout layout1 = new TextLayout("TEST", font1, frc); + TextLayout layout2 = new TextLayout("TEST", font2, frc); + Rectangle r1 = layout1.getPixelBounds(frc, 0, 0); + Rectangle r2 = layout2.getPixelBounds(frc, 0, 0); + if (!r1.equals(r2)) { + throw new RuntimeException("For color " + c + ", " + r1 + " != " + r2); + } + Rectangle2D bounds = layout1.getBounds(); + if (Math.abs(bounds.getX() - r1.x) > 3 || + Math.abs(bounds.getY() - r1.y) > 3 || + Math.abs(bounds.getWidth() - r1.width) > 6 || + Math.abs(bounds.getHeight() - r1.height) > 6) { + throw new RuntimeException("For color " + c + ", pixel bounds " + + r1 + " not similar to " + bounds); + } + } + + private static void testTransparent(Color c) { + Font font1 = new Font(Font.DIALOG, Font.PLAIN, 60); + Map< TextAttribute, Object > attributes = new HashMap<>(); + attributes.put(TextAttribute.FOREGROUND, c); + Font font2 = font1.deriveFont(attributes); + FontRenderContext frc = new FontRenderContext(null, true, true); + TextLayout layout = new TextLayout("TEST", font2, frc); + Rectangle r = layout.getPixelBounds(frc, 0, 0); + if (!r.isEmpty()) { + throw new RuntimeException("Expected empty pixel bounds for " + c + " but got " + r); + } + } +}