About fonts:

Chapter: Writing with fonts
...Section: About fonts:

AWT's font functionality is found in the classes Font and FontMetrics. Take a moment now to read the javadocs for these two classes.

Fonts come in many styles. Java emphasizes PLAIN, ITALIC, and BOLD and combinations. This code will get you a fuller list of the font names available in your graphics environment.

Fonts come in different sizes. A font's size is specified using the standard "printer's point" measure: one "point" is about 1/72 inches. AWT does not guarantee that your size specification will be implemented exactly - only a "best attempt" is made. The FontMetrics class provides more information about a font's sizes. Note: a font size is not specified in pixels.

To use a font, you need to create a Font object, passing the name, style and size to the constructor. To specify a style, use the constants in class Font. Pass the Font instance to the Graphics context using the setFont() method. Consider this example, which prints out Serif and SansSerif strings in two sizes and all the available styles:

import java.awt.*;
import java.awt.event.*;

class NewFrame extends Frame {
    
    // Constructors. 
    public NewFrame (int width, int height)
    {
        // Set the title and other parameters. 
        setTitle ("Fonts");
        setResizable (true);
        setBackground (Color.cyan);
        setSize (width, height);
        addWindowListener(new WindowAdapter() {
                public void windowClosing(WindowEvent e) {
                    System.exit(0);
                }
            });
        
        // Show the frame. 
        setVisible (true);
    }
    
    // No-parameter constructor - use a default size. 
    public NewFrame ()
    {
        this (500, 300);
    }
    
    // Override paint(): 
    public void paint (Graphics g)
    {
        // Create 10-point Serif fonts in all styles: 
        Font f1 = new Font ("Serif", Font.PLAIN, 10);
        g.setFont (f1);
        g.drawString ("Serif-Plain-10pt", 30, 60);
        
        f1 = new Font ("Serif", Font.ITALIC, 10);
        g.setFont (f1);
        g.drawString ("Serif-Italic-10pt", 30, 90);
        
        f1 = new Font ("Serif", Font.PLAIN | Font.BOLD, 10);    
        g.setFont (f1);
        g.drawString ("Serif-Plain-Bold-10pt", 30, 120);
        
        f1 = new Font ("Serif", Font.ITALIC | Font.BOLD, 10);    
        g.setFont (f1);
        g.drawString ("Serif-Italic-Bold-10pt", 30, 150);
        
        // Create 20-point SansSerif fonts in all styles: 
        f1 = new Font ("SansSerif", Font.PLAIN, 20);
        g.setFont (f1);
        g.drawString ("SansSerif-Plain-20pt", 140, 60);
        
        f1 = new Font ("SansSerif", Font.ITALIC, 20);
        g.setFont (f1);
        g.drawString ("SansSerif-Italic-20pt", 140, 90);
        
        f1 = new Font ("SansSerif", Font.PLAIN | Font.BOLD, 20);    
        g.setFont (f1);
        g.drawString ("SansSerif-Plain-Bold-20pt", 140, 120 );
        
        f1 = new Font ("SansSerif", Font.ITALIC | Font.BOLD, 20);    
        g.setFont (f1);
        g.drawString ("SansSerif-Italic-Bold-20pt", 140, 150);
    }
    
}

public class TestAwt11 {
    
    public static void main (String[] argv) {
        NewFrame nf = new NewFrame (450,200);
    }
    
}

Run it to see the result produced.

The font name is passed as a string: Font f1 = new Font ("Serif", Font.PLAIN, 10);

The font style is an OR'ed combination of constants, e.g., f1 = new Font ("SansSerif", Font.ITALIC | Font.BOLD, 20);

To use a font, you first "set" the font using the setFont() method in the graphics context.

The drawString method of Graphics will then draw the specified fonts at a given location. g.drawString ("Hello World!", 30, 60);

The lowest point of a non-descending letter like "h" is used for the y-value.

You, the programmer, are responsible for laying out the strings (typesetting): - you need to compute line lengths, inter-word spacing, etc. Typesetting:

A font has several measurements (characteristics) useful in typesetting:

The font characteristics depend on the letters in the text. An accent is not counted in the ascent.

A FontMetrics instance provides the characteristics for a particular font, style and size.

A FontMetrics instance is usually obtained as follows:

  public void paint (Graphics g)
  {
    // Create a font. 
    Font f = new Font ("Serif", Font.PLAIN | Font.BOLD, fontsize);    

    // Set the font in the graphics instance. 
    g.setFont (f);

    // Get a FontMetrics instance from the graphics instance. 
    FontMetrics fm = g.getFontMetrics();
  }
The class FontMetrics in java.awt has several methods:
  public abstract FontMetrics implements Serializable {

    //... 

    // Some methods that return a font characteristic. 
    public int getAscent ();
    public int getDescent ();
    public int getLeading ();
    public int getHeight ();
    public int maxAscent ();
    public int maxDescent ();

    // Get the resulting width of a string. 
    public int stringWidth (String s);

    //... 

  }

If accents are being used, it may be advisable to use the sum of maxAscent, maxDescent and leading.

We will consider an example in which we are given a piece of text as an array of Strings, and we want to write out the words so that words are not broken up. We will allow the font size to be specified. We will use the stringWidth() method in FontMetrics to get the size of a string in pixels. Here is code:

import java.awt.*;
import java.awt.event.*;

class NewFrame extends Frame {
    
    String[] words; // List of words to display. 
    int fontsize;   // Size of font. 
    
    // Constructor. 
    public NewFrame (int width, int height, String[] words, int fontsize)
    {
	// Retain data and font size. 
	this.words = words;
	this.fontsize = fontsize;
	
	// Set the title and other frame parameters. 
	setTitle ("Font metrics");
	setResizable (true);
	setBackground (Color.cyan);
	setSize (width, height);
        addWindowListener(new WindowAdapter() {
                public void windowClosing(WindowEvent e) {
                    System.exit(0);
                }
            });	
	// Show the frame. 
	setVisible (true);
    }
    
    // Override paint(): 
    public void paint (Graphics g)
    {
	// Create a Serif font in the given font size. 
	Font f = new Font ("Serif", Font.PLAIN | Font.BOLD, fontsize);    
	g.setFont (f);
	
	// Get a FontMetrics instance from the graphics context. 
	FontMetrics fm = g.getFontMetrics();
	
	// Get the height (height of font plus separator). 
	int fontheight = fm.getHeight ();
	
	// Size of frame plus insets. 
	Dimension d = this.getSize ();
	Insets i = this.getInsets ();
	
	// Visible drawing area 
	int max_width = d.width - i.left - i.right - 1;
	int max_height = d.height - i.top - i.bottom - 1;
	
	// Start at topleft. 
	int startx = 0 + i.left;
	
	// Must add font height since bottom left corner  
	// of font is used as starting point. 
	int y = 0 + i.top + fontheight;
	
	int x = startx;
	for (int j=0; j < words.length; j++) {
	    
	    // Obtain pixel-length of string (with blank) 
	    int len = fm.stringWidth (" " + words[j]);
	    
	    if (x + len < max_width) {
		// If it fits within the current line, draw it 
		g.drawString (" " + words[j], x, y);
		x += len;
	    }
	    else {
		// Go to next line. 
		x = startx;
		y += fontheight;
		g.drawString (" " + words[j], x, y);
		x += len;
	    }
	}
	
    } // "paint" 
    
} // End of class "NewFrame" 

public class TestAwt12 {
    
    public static void main (String[] argv)
    {
	String[] testwords = {
	    "There", "once", "was", "a", "poet", "named", "Heinz",
	    "Whose", "poems", "had", "only", "two", "lines."
	};
	NewFrame nf = new NewFrame (600,200, testwords, 35);
    }
    
}

Try it!


Exercise 5

Create a frame in which you write the largest possible "GWU Colonials!" that will fit into the drawable area. Start with a font size of 10 and increase the size in increments of 10 until you find the largest possible font that will fit into the drawable area. Allow for the situation where the window may be resized.



rhyspj@gwu.edu