Replacing Internal sun.font.FontDesignMetrics When Upgrading to JDK 17
When upgrading a project from JDK 1.8 to JDK 17, the following code:
java FontMetrics fontMetrics = FontDesignMetrics.getMetrics(font);
Throws an error:
cannot access class sun.font.FontDesignMetrics (in module java.desktop) because module java.desktop does not export sun.font
The most common solution found online is to add --add-exports configurations in your pom.xml file (as suggested in various StackOverflow discussions). However, I found that this approach occasionally fails both locally and in production environments, and the exact cause remains unclear.
After further research, I discovered a reliable alternative to replace FontDesignMetrics for calculating text dimensions:
java FontRenderContext renderContext = new FontRenderContext(new AffineTransform(), true, true); Font textFont = new Font("Microsoft YaHei", Font.ITALIC, 28); String sampleText = "Hello there! My Friend"; Rectangle textBounds = textFont.getStringBounds(sampleText, renderContext).getBounds(); int textHeight = textBounds.height; int textWidth = textBounds.width;
Below is a complete example demonstrating how to draw text onto an image using this approach:
java public static void createTextWatermark(String content, File targetFile) throws IOException { Font customFont = new Font("Microsoft YaHei", Font.ITALIC, 28); FontRenderContext frc = new FontRenderContext(new AffineTransform(), true, true);
Rectangle bounds = customFont.getStringBounds(content, frc).getBounds();
int textHeight = bounds.height;
int textWidth = bounds.width;
BufferedImage image = ImageIO.read(targetFile);
Graphics2D g2d = (Graphics2D) image.getGraphics();
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
GradientPaint gradient = new GradientPaint(0, 0, Color.PINK, (textWidth + 100) / 2, 0, Color.RED, true);
g2d.setPaint(gradient);
g2d.fillRect(0, 0, textWidth + 100, textHeight);
g2d.setFont(customFont);
g2d.setColor(Color.WHITE);
g2d.drawString(content, 150, -bounds.y);
g2d.dispose();
writeImageToFile(image, targetFile.getPath());
}
private static void writeImageToFile(BufferedImage image, String destinationPath) throws IOException { File outputFile = new File(destinationPath); if (!outputFile.getParentFile().exists()) { outputFile.getParentFile().mkdirs(); } try (OutputStream outputStream = new FileOutputStream(destinationPath)) { ImageIO.write(image, "JPG", outputStream); } }