8168992: Add floating point implementation for new BasicGraphicsUtils text related methods use floating point API
Reviewed-by: serb, ssadetsky
This commit is contained in:
parent
57dc20d541
commit
36bb41faf9
@ -403,7 +403,7 @@ public class BasicGraphicsUtils
|
||||
*/
|
||||
public static void drawString(JComponent c, Graphics2D g, String string,
|
||||
float x, float y) {
|
||||
SwingUtilities2.drawString(c, g, string, (int) x, (int) y);
|
||||
SwingUtilities2.drawString(c, g, string, x, y, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -439,7 +439,7 @@ public class BasicGraphicsUtils
|
||||
public static void drawStringUnderlineCharAt(JComponent c, Graphics2D g,
|
||||
String string, int underlinedIndex, float x, float y) {
|
||||
SwingUtilities2.drawStringUnderlineCharAt(c, g, string, underlinedIndex,
|
||||
(int) x, (int) y);
|
||||
x, y, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -482,6 +482,6 @@ public class BasicGraphicsUtils
|
||||
* @since 9
|
||||
*/
|
||||
public static float getStringWidth(JComponent c, FontMetrics fm, String string) {
|
||||
return SwingUtilities2.stringWidth(c, fm, string);
|
||||
return SwingUtilities2.stringWidth(c, fm, string, true);
|
||||
}
|
||||
}
|
||||
|
@ -107,7 +107,7 @@ public class Utilities {
|
||||
TabExpander e,
|
||||
int startOffset)
|
||||
{
|
||||
return drawTabbedText(s, (int) x, (int) y, (Graphics) g, e, startOffset);
|
||||
return drawTabbedText(null, s, x, y, g, e, startOffset, null, true);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -318,7 +318,21 @@ public class SwingUtilities2 {
|
||||
* @param fm FontMetrics used to measure the String width
|
||||
* @param string String to get the width of
|
||||
*/
|
||||
public static int stringWidth(JComponent c, FontMetrics fm, String string){
|
||||
public static int stringWidth(JComponent c, FontMetrics fm, String string) {
|
||||
return (int) stringWidth(c, fm, string, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the width of the passed in String.
|
||||
* If the passed String is {@code null}, returns zero.
|
||||
*
|
||||
* @param c JComponent that will display the string, may be null
|
||||
* @param fm FontMetrics used to measure the String width
|
||||
* @param string String to get the width of
|
||||
* @param useFPAPI use floating point API
|
||||
*/
|
||||
public static float stringWidth(JComponent c, FontMetrics fm, String string,
|
||||
boolean useFPAPI){
|
||||
if (string == null || string.equals("")) {
|
||||
return 0;
|
||||
}
|
||||
@ -333,9 +347,9 @@ public class SwingUtilities2 {
|
||||
if (needsTextLayout) {
|
||||
TextLayout layout = createTextLayout(c, string,
|
||||
fm.getFont(), fm.getFontRenderContext());
|
||||
return (int) layout.getAdvance();
|
||||
return layout.getAdvance();
|
||||
} else {
|
||||
return fm.stringWidth(string);
|
||||
return getFontStringWidth(string, fm, useFPAPI);
|
||||
}
|
||||
}
|
||||
|
||||
@ -426,6 +440,21 @@ public class SwingUtilities2 {
|
||||
*/
|
||||
public static void drawString(JComponent c, Graphics g, String text,
|
||||
int x, int y) {
|
||||
drawString(c, g, text, x, y, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draws the string at the specified location.
|
||||
*
|
||||
* @param c JComponent that will display the string, may be null
|
||||
* @param g Graphics to draw the text to
|
||||
* @param text String to display
|
||||
* @param x X coordinate to draw the text at
|
||||
* @param y Y coordinate to draw the text at
|
||||
* @param useFPAPI use floating point API
|
||||
*/
|
||||
public static void drawString(JComponent c, Graphics g, String text,
|
||||
float x, float y, boolean useFPAPI) {
|
||||
// c may be null
|
||||
|
||||
// All non-editable widgets that draw strings call into this
|
||||
@ -509,7 +538,7 @@ public class SwingUtilities2 {
|
||||
g2.getFontRenderContext());
|
||||
layout.draw(g2, x, y);
|
||||
} else {
|
||||
g.drawString(text, x, y);
|
||||
g2.drawString(text, x, y);
|
||||
}
|
||||
|
||||
if (oldAAValue != null) {
|
||||
@ -530,7 +559,7 @@ public class SwingUtilities2 {
|
||||
}
|
||||
}
|
||||
|
||||
g.drawString(text, x, y);
|
||||
g.drawString(text, (int) x, (int) y);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -544,17 +573,36 @@ public class SwingUtilities2 {
|
||||
* @param x X coordinate to draw the text at
|
||||
* @param y Y coordinate to draw the text at
|
||||
*/
|
||||
|
||||
public static void drawStringUnderlineCharAt(JComponent c,Graphics g,
|
||||
String text, int underlinedIndex, int x,int y) {
|
||||
String text, int underlinedIndex, int x, int y) {
|
||||
drawStringUnderlineCharAt(c, g, text, underlinedIndex, x, y, false);
|
||||
}
|
||||
/**
|
||||
* Draws the string at the specified location underlining the specified
|
||||
* character.
|
||||
*
|
||||
* @param c JComponent that will display the string, may be null
|
||||
* @param g Graphics to draw the text to
|
||||
* @param text String to display
|
||||
* @param underlinedIndex Index of a character in the string to underline
|
||||
* @param x X coordinate to draw the text at
|
||||
* @param y Y coordinate to draw the text at
|
||||
* @param useFPAPI use floating point API
|
||||
*/
|
||||
public static void drawStringUnderlineCharAt(JComponent c, Graphics g,
|
||||
String text, int underlinedIndex,
|
||||
float x, float y,
|
||||
boolean useFPAPI) {
|
||||
if (text == null || text.length() <= 0) {
|
||||
return;
|
||||
}
|
||||
SwingUtilities2.drawString(c, g, text, x, y);
|
||||
SwingUtilities2.drawString(c, g, text, x, y, useFPAPI);
|
||||
int textLength = text.length();
|
||||
if (underlinedIndex >= 0 && underlinedIndex < textLength ) {
|
||||
int underlineRectY = y;
|
||||
float underlineRectY = y;
|
||||
int underlineRectHeight = 1;
|
||||
int underlineRectX = 0;
|
||||
float underlineRectX = 0;
|
||||
int underlineRectWidth = 0;
|
||||
boolean isPrinting = isPrinting(g);
|
||||
boolean needsTextLayout = isPrinting;
|
||||
@ -594,7 +642,7 @@ public class SwingUtilities2 {
|
||||
underlineRectWidth = rect.width;
|
||||
}
|
||||
}
|
||||
g.fillRect(underlineRectX, underlineRectY + 1,
|
||||
g.fillRect((int) underlineRectX, (int) underlineRectY + 1,
|
||||
underlineRectWidth, underlineRectHeight);
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,339 @@
|
||||
/*
|
||||
* Copyright (c) 2016, 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.
|
||||
*/
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Font;
|
||||
import java.awt.FontMetrics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.awt.font.FontRenderContext;
|
||||
import java.awt.font.NumericShaper;
|
||||
import java.awt.font.TextAttribute;
|
||||
import java.awt.font.TextLayout;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.util.HashMap;
|
||||
import javax.swing.JComponent;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.UIManager;
|
||||
import javax.swing.plaf.basic.BasicGraphicsUtils;
|
||||
import javax.swing.plaf.metal.MetalLookAndFeel;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8132119 8168992
|
||||
* @author Alexandr Scherbatiy
|
||||
* @summary Provide public API for text related methods in SwingBasicGraphicsUtils2
|
||||
*/
|
||||
public class bug8132119 {
|
||||
|
||||
private static final int WIDTH = 50;
|
||||
private static final int HEIGHT = 50;
|
||||
private static final Color DRAW_COLOR = Color.RED;
|
||||
private static final Color BACKGROUND_COLOR = Color.GREEN;
|
||||
private static final NumericShaper NUMERIC_SHAPER = NumericShaper.getShaper(
|
||||
NumericShaper.ARABIC);
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
SwingUtilities.invokeAndWait(bug8132119::testStringMethods);
|
||||
}
|
||||
|
||||
private static void testStringMethods() {
|
||||
setMetalLAF();
|
||||
testStringWidth();
|
||||
testStringClip();
|
||||
testDrawEmptyString();
|
||||
testDrawString(false);
|
||||
testDrawString(true);
|
||||
checkNullArguments();
|
||||
}
|
||||
|
||||
private static void testStringWidth() {
|
||||
|
||||
String str = "12345678910\u036F";
|
||||
JComponent comp = createComponent(str);
|
||||
Font font = comp.getFont();
|
||||
FontMetrics fontMetrics = comp.getFontMetrics(font);
|
||||
float stringWidth = BasicGraphicsUtils.getStringWidth(comp, fontMetrics, str);
|
||||
|
||||
if (stringWidth == fontMetrics.stringWidth(str)) {
|
||||
throw new RuntimeException("Numeric shaper is not used!");
|
||||
}
|
||||
|
||||
if (stringWidth != getLayoutWidth(str, font, NUMERIC_SHAPER)) {
|
||||
throw new RuntimeException("Wrong text width!");
|
||||
}
|
||||
}
|
||||
|
||||
private static void testStringClip() {
|
||||
|
||||
String str = "1234567890";
|
||||
JComponent comp = createComponent(str);
|
||||
FontMetrics fontMetrics = comp.getFontMetrics(comp.getFont());
|
||||
|
||||
int width = (int) BasicGraphicsUtils.getStringWidth(comp, fontMetrics, str);
|
||||
|
||||
String clip = BasicGraphicsUtils.getClippedString(comp, fontMetrics, str, width);
|
||||
checkClippedString(str, clip, str);
|
||||
|
||||
clip = BasicGraphicsUtils.getClippedString(comp, fontMetrics, str, width + 1);
|
||||
checkClippedString(str, clip, str);
|
||||
|
||||
clip = BasicGraphicsUtils.getClippedString(comp, fontMetrics, str, -1);
|
||||
checkClippedString(str, clip, "...");
|
||||
|
||||
clip = BasicGraphicsUtils.getClippedString(comp, fontMetrics, str, 0);
|
||||
checkClippedString(str, clip, "...");
|
||||
|
||||
clip = BasicGraphicsUtils.getClippedString(comp, fontMetrics,
|
||||
str, width - width / str.length());
|
||||
int endIndex = str.length() - 3;
|
||||
checkClippedString(str, clip, str.substring(0, endIndex) + "...");
|
||||
}
|
||||
|
||||
private static void checkClippedString(String str, String res, String golden) {
|
||||
if (!golden.equals(res)) {
|
||||
throw new RuntimeException(String.format("The string '%s' is not "
|
||||
+ "properly clipped. The result is '%s' instead of '%s'",
|
||||
str, res, golden));
|
||||
}
|
||||
}
|
||||
|
||||
private static void testDrawEmptyString() {
|
||||
JLabel label = new JLabel();
|
||||
BufferedImage buffImage = createBufferedImage(50, 50);
|
||||
Graphics2D g2 = buffImage.createGraphics();
|
||||
g2.setColor(DRAW_COLOR);
|
||||
BasicGraphicsUtils.drawString(null, g2, null, 0, 0);
|
||||
BasicGraphicsUtils.drawString(label, g2, null, 0, 0);
|
||||
BasicGraphicsUtils.drawString(null, g2, "", 0, 0);
|
||||
BasicGraphicsUtils.drawString(label, g2, "", 0, 0);
|
||||
BasicGraphicsUtils.drawStringUnderlineCharAt(null, g2, null, 3, 0, 0);
|
||||
BasicGraphicsUtils.drawStringUnderlineCharAt(label, g2, null, 3, 0, 0);
|
||||
BasicGraphicsUtils.drawStringUnderlineCharAt(null, g2, "", 3, 0, 0);
|
||||
BasicGraphicsUtils.drawStringUnderlineCharAt(label, g2, "", 3, 0, 0);
|
||||
g2.dispose();
|
||||
checkImageIsEmpty(buffImage);
|
||||
}
|
||||
|
||||
private static void testDrawString(boolean underlined) {
|
||||
String str = "AOB";
|
||||
JComponent comp = createComponent(str);
|
||||
|
||||
BufferedImage buffImage = createBufferedImage(WIDTH, HEIGHT);
|
||||
Graphics2D g2 = buffImage.createGraphics();
|
||||
|
||||
g2.setColor(DRAW_COLOR);
|
||||
g2.setFont(comp.getFont());
|
||||
|
||||
FontMetrics fontMetrices = comp.getFontMetrics(comp.getFont());
|
||||
float width = BasicGraphicsUtils.getStringWidth(comp, fontMetrices, str);
|
||||
float x = (WIDTH - width) / 2;
|
||||
int y = 3 * HEIGHT / 4;
|
||||
|
||||
if (underlined) {
|
||||
BasicGraphicsUtils.drawStringUnderlineCharAt(comp, g2, str, 1, x, y);
|
||||
} else {
|
||||
BasicGraphicsUtils.drawString(comp, g2, str, x, y);
|
||||
}
|
||||
g2.dispose();
|
||||
|
||||
float xx = (WIDTH - width / 8) / 2;
|
||||
checkImageContainsSymbol(buffImage, (int) xx, underlined ? 3 : 2);
|
||||
}
|
||||
|
||||
private static void checkNullArguments() {
|
||||
|
||||
Graphics2D g = null;
|
||||
try {
|
||||
String text = "Test";
|
||||
JComponent component = new JLabel(text);
|
||||
BufferedImage img = createBufferedImage(100, 100);
|
||||
g = img.createGraphics();
|
||||
checkNullArguments(component, g, text);
|
||||
} finally {
|
||||
g.dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkNullArguments(JComponent comp, Graphics2D g,
|
||||
String text) {
|
||||
|
||||
checkNullArgumentsDrawString(comp, g, text);
|
||||
checkNullArgumentsDrawStringUnderlineCharAt(comp, g, text);
|
||||
checkNullArgumentsGetClippedString(comp, text);
|
||||
checkNullArgumentsGetStringWidth(comp, text);
|
||||
}
|
||||
|
||||
private static void checkNullArgumentsDrawString(JComponent comp, Graphics2D g,
|
||||
String text) {
|
||||
|
||||
float x = 50;
|
||||
float y = 50;
|
||||
BasicGraphicsUtils.drawString(null, g, text, x, y);
|
||||
BasicGraphicsUtils.drawString(comp, g, null, x, y);
|
||||
|
||||
try {
|
||||
BasicGraphicsUtils.drawString(comp, null, text, x, y);
|
||||
} catch (NullPointerException e) {
|
||||
return;
|
||||
}
|
||||
|
||||
throw new RuntimeException("NPE is not thrown");
|
||||
}
|
||||
|
||||
private static void checkNullArgumentsDrawStringUnderlineCharAt(
|
||||
JComponent comp, Graphics2D g, String text) {
|
||||
|
||||
int x = 50;
|
||||
int y = 50;
|
||||
BasicGraphicsUtils.drawStringUnderlineCharAt(null, g, text, 1, x, y);
|
||||
BasicGraphicsUtils.drawStringUnderlineCharAt(comp, g, null, 1, x, y);
|
||||
|
||||
try {
|
||||
BasicGraphicsUtils.drawStringUnderlineCharAt(comp, null, text, 1, x, y);
|
||||
} catch (NullPointerException e) {
|
||||
return;
|
||||
}
|
||||
|
||||
throw new RuntimeException("NPE is not thrown");
|
||||
}
|
||||
|
||||
private static void checkNullArgumentsGetClippedString(
|
||||
JComponent comp, String text) {
|
||||
|
||||
FontMetrics fontMetrics = comp.getFontMetrics(comp.getFont());
|
||||
|
||||
BasicGraphicsUtils.getClippedString(null, fontMetrics, text, 1);
|
||||
String result = BasicGraphicsUtils.getClippedString(comp, fontMetrics, null, 1);
|
||||
if (!"".equals(result)) {
|
||||
throw new RuntimeException("Empty string is not returned!");
|
||||
}
|
||||
|
||||
try {
|
||||
BasicGraphicsUtils.getClippedString(comp, null, text, 1);
|
||||
} catch (NullPointerException e) {
|
||||
return;
|
||||
}
|
||||
|
||||
throw new RuntimeException("NPE is not thrown");
|
||||
}
|
||||
|
||||
private static void checkNullArgumentsGetStringWidth(JComponent comp,
|
||||
String text) {
|
||||
|
||||
FontMetrics fontMetrics = comp.getFontMetrics(comp.getFont());
|
||||
BasicGraphicsUtils.getStringWidth(null, fontMetrics, text);
|
||||
float result = BasicGraphicsUtils.getStringWidth(comp, fontMetrics, null);
|
||||
|
||||
if (result != 0) {
|
||||
throw new RuntimeException("The string length is not 0");
|
||||
}
|
||||
|
||||
try {
|
||||
BasicGraphicsUtils.getStringWidth(comp, null, text);
|
||||
} catch (NullPointerException e) {
|
||||
return;
|
||||
}
|
||||
|
||||
throw new RuntimeException("NPE is not thrown");
|
||||
}
|
||||
|
||||
private static void setMetalLAF() {
|
||||
try {
|
||||
UIManager.setLookAndFeel(new MetalLookAndFeel());
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private static JComponent createComponent(String str) {
|
||||
JComponent comp = new JLabel(str);
|
||||
comp.setSize(WIDTH, HEIGHT);
|
||||
comp.putClientProperty(TextAttribute.NUMERIC_SHAPING, NUMERIC_SHAPER);
|
||||
comp.setFont(getFont());
|
||||
return comp;
|
||||
}
|
||||
|
||||
private static Font getFont() {
|
||||
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
|
||||
String[] fontNames = ge.getAvailableFontFamilyNames();
|
||||
String fontName = fontNames[0];
|
||||
for (String name : fontNames) {
|
||||
if ("Arial".equals(name)) {
|
||||
fontName = name;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return new Font(fontName, Font.PLAIN, 28);
|
||||
}
|
||||
|
||||
private static float getLayoutWidth(String text, Font font, NumericShaper shaper) {
|
||||
HashMap map = new HashMap();
|
||||
map.put(TextAttribute.FONT, font);
|
||||
map.put(TextAttribute.NUMERIC_SHAPING, shaper);
|
||||
FontRenderContext frc = new FontRenderContext(null, false, false);
|
||||
TextLayout layout = new TextLayout(text, map, frc);
|
||||
return layout.getAdvance();
|
||||
}
|
||||
|
||||
private static void checkImageIsEmpty(BufferedImage buffImage) {
|
||||
int background = BACKGROUND_COLOR.getRGB();
|
||||
|
||||
for (int i = 0; i < buffImage.getWidth(); i++) {
|
||||
for (int j = 0; j < buffImage.getHeight(); j++) {
|
||||
if (background != buffImage.getRGB(i, j)) {
|
||||
throw new RuntimeException("Image is not empty!");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkImageContainsSymbol(BufferedImage buffImage,
|
||||
int x, int intersections) {
|
||||
int background = BACKGROUND_COLOR.getRGB();
|
||||
boolean isBackground = true;
|
||||
int backgroundChangesCount = 0;
|
||||
|
||||
for (int y = 0; y < buffImage.getHeight(); y++) {
|
||||
if (!(isBackground ^ (background != buffImage.getRGB(x, y)))) {
|
||||
isBackground = !isBackground;
|
||||
backgroundChangesCount++;
|
||||
}
|
||||
}
|
||||
if (backgroundChangesCount != intersections * 2) {
|
||||
throw new RuntimeException("String is not properly drawn!");
|
||||
}
|
||||
}
|
||||
|
||||
private static BufferedImage createBufferedImage(int width, int height) {
|
||||
BufferedImage bufffImage = new BufferedImage(width, height,
|
||||
BufferedImage.TYPE_INT_RGB);
|
||||
|
||||
Graphics2D g = bufffImage.createGraphics();
|
||||
g.setColor(BACKGROUND_COLOR);
|
||||
g.fillRect(0, 0, width, height);
|
||||
g.dispose();
|
||||
return bufffImage;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user