Code:
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import javax.swing.JFrame;
public class TextRectangle extends JFrame {
private static final long serialVersionUID = 1L;
public static void main(String[] a) {
TextRectangle f = new TextRectangle();
f.setSize(300, 300);
f.setVisible(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void paint(Graphics g) {
Graphics2D g2d = (Graphics2D) g;
g2d.setRenderingHint(
RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
g2d.setRenderingHint(
RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
g2d.setColor(Color.WHITE);
g2d.fillRect(0, 0, getWidth(), getHeight());
g2d.setColor(Color.BLACK);
g2d.setFont(new Font("Calibri", Font.BOLD, 18));
g2d.drawString("Why does this text look so ugly?", 30, 150);
}
}
Result:
As you can see the letter spacing is uneven. Sometimes it's 1px, sometimes it's 2 or even 3 pixels. Another issue is the dot above 'i' is wider than the bottom part.
The same text written in a text editor looks much better. Do you know how to fix this problem?
My environment is Windows 8.1, Java 1.8.
Anti-aliasing is the processes of making the edges of lines on shapes or text less jagged. This is done by fooling the eye – intermediate pixels are added to smooth the color transition. So you might add some grey pixels between a black and a white point.
There are several ways to create graphics in Java; the simplest way is to use java. awt. Canvas and java. awt.
All implementations of the Java Platform must support TrueType fonts; support for other font technologies is implementation dependent. Physical fonts may use names such as Helvetica, Palatino, HonMincho, or any number of other font names.
The Graphics class is the abstract super class for all graphics contexts which allow an application to draw onto components that can be realized on various devices, or onto off-screen images as well. A Graphics object encapsulates all state information required for the basic rendering operations that Java supports.
The graphics context uses integer metrics by default - meaning that rounding is applied to the location vectors of the glyph shapes.
You can switch to fractional metrics using:
g2d.setRenderingHint(RenderingHints.KEY_FRACTIONALMETRICS,
RenderingHints.VALUE_FRACTIONALMETRICS_ON);
As you can see, no subpixel antialiasing was used (only gray antialias pixel). You can enable subpixel antialiasing for better legibility on LCD screens:
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
There are 4 modes:
VALUE_TEXT_ANTIALIAS_LCD_HRGB
: horizontally oriented RGBVALUE_TEXT_ANTIALIAS_LCD_HBGR
: horizontally oriented BGRVALUE_TEXT_ANTIALIAS_LCD_VRGB
: vertically oriented RGBVALUE_TEXT_ANTIALIAS_LCD_VBGR
: vertically oriented BGRI haven't found out where to query the appropriate value of the current display and orientation. Some displays can be tilted (landscape/portrait) or even rotated, requiring to redetect the mode when painting.
EDIT
I found something in the Filthy Rich Clients book: apparently, the Java AWT Toolkit can provide appropriate rendering hints:
Map<?, ?> desktopHints =
(Map<?, ?>) Toolkit.getDefaultToolkit().getDesktopProperty("awt.font.desktophints");
Graphics2D g2d = (Graphics2D) g;
if (desktopHints != null) {
g2d.setRenderingHints(desktopHints);
}
// no need to set more rendering hints
On my system, this renders the text with fractional metrics and LCD HRGB antialiasing, same as with the code above. The hints on my system are:
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With