Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to fix text quality in Java graphics?

Tags:

java

graphics

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:

result screenshot

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.

problem details

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.

like image 564
Lukasz Wiktor Avatar asked Jul 21 '15 10:07

Lukasz Wiktor


People also ask

What is antialiasing in Java?

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.

Can Java make graphics?

There are several ways to create graphics in Java; the simplest way is to use java. awt. Canvas and java. awt.

What is the font used in Java?

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.

What is Java AWT graphics?

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.


1 Answers

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);

enter image description here

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);

enter image description here

There are 4 modes:

  • VALUE_TEXT_ANTIALIAS_LCD_HRGB: horizontally oriented RGB
  • VALUE_TEXT_ANTIALIAS_LCD_HBGR: horizontally oriented BGR
  • VALUE_TEXT_ANTIALIAS_LCD_VRGB: vertically oriented RGB
  • VALUE_TEXT_ANTIALIAS_LCD_VBGR: vertically oriented BGR

I 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:

  • Text-specific antialiasing enable key: LCD HRGB antialiasing text mode
  • Text-specific LCD contrast key: 120
like image 162
Peter Walser Avatar answered Nov 13 '22 12:11

Peter Walser