JaVa
   

Fonts

The class java.awt.Font is used to represent a font in Java. Again, as with colors, the Graphics object has a current font object associated with it, which can be set using the method setFont(Font). We should take a look at creating a font object using the Font class to begin with. The main constructor to use for creating your ideal font is as follows:

Font(String name, int style, int size);


The name of the Font object is a String representation of the font (for example, Arial, Courier New, Times New Roman, etc.). We will see about getting the available fonts at the end of this section. The style can be one of the following: Font.PLAIN, Font.BOLD, Font.ITALIC, or (Font.BOLD | Font.ITALIC). The bold and italic constant ID values are 1 and 2, respectively, and the value for both is the bitwise OR value of 3, so we can simply OR these constants in this fashion. The size is simply the size of the font in standard point sizes (think Word).

Font Objects Are Immutable

Recall in , "Arrays and Strings," that we noted the main difference between String objects and StringBuffer objects is that String objects are immutable. This means that the data of this object cannot be changed; in order to have a String object with different data, you need to create a different object altogether. Similarly, Font objects are immutable; you cannot change the data of the Font object, such as its size or style, but you need to create a new object instead. There are some useful methods of a Font object that return new versions of a given Font object, with the specific changes (most notably the deriveFont methods). However, creating objects can be very expensive to Java, especially when continually creating objects in the main loop. We will have a detailed discussion on this in , "Game Programming Techniques," along with a discussion on the garbage collector.

Another object that we can note that is immutable is a Color object. You may be wondering why all of these objects are immutable. Well, it's quite simple. They are immutable because they need to be safe when used by AWT or Swing components internally for rendering by Java, hence it would be unsafe to alter their contents during this process.

Understanding the Fonts Coordinates

When a string value is drawn in a given font using the drawString(String text, int x, int y) method, the position of the string value is drawn starting at the x and y position specified, with x equaling the leftmost part of the first character in the String and y equaling the baseline of the font. To understand the coordinate system for fonts, take a look at the following figure.

Java Click To expand
Screenshot-6:

Using the drawString method, your text will sit on the baseline as if you were writing on lined paper (writing without a keyboard, that is—if you can imagine such a silly concept). The ascent is the pixel distance from the top of the font to the baseline, and the descent is the pixel distance from the bottom of the font to the baseline. In the following example, we will create a small, medium, and large font type and create a useful function for drawing text in a specified location relative to a given point, working irrespective of the current Graphics object's font type, style, or size. Let's first take a look at the code for the example UsingFonts.java, and then we'll discuss how it all works.

Code Listing 9-5: UsingFonts.java
import javax.swing.*;
import java.awt.*;
public class UsingFonts extends JFrame
{
 public UsingFonts()
 {
 super("Using Fonts");
 setDefaultCloseOperation(EXIT_ON_CLOSE);
 setResizable(false);
 getContentPane().setLayout(null);
 getContentPane().add(new FontArea(new Rectangle(0, 0,
 DISPLAY_WIDTH, DISPLAY_HEIGHT)));
 smallFont = new Font("Courier New", Font.BOLD, 12);
 mediumFont = new Font("Times New Roman", Font.PLAIN, 24);
 largeFont = new Font("Verdana", Font.BOLD+Font.ITALIC, 36);
 setVisible(true);
 resizeToInternalSize(DISPLAY_WIDTH, DISPLAY_HEIGHT);
 }
 public void resizeToInternalSize(int internalWidth, int
 internalHeight)
 {
 Insets insets = getInsets();
 final int newWidth = internalWidth + insets.left +
 insets.right;
 final int newHeight = internalHeight + insets.top +
 insets.bottom;
 Runnable resize = new Runnable()
 {
 public void run()
 {
 setSize(newWidth, newHeight);
 }
 };
 if(!SwingUtilities.isEventDispatchThread())
 {
 try
 {
 SwingUtilities.invokeAndWait(resize);
 }
 catch(Exception e) {}
 }
 else
 resize.run();
 validate();
 }
 public class FontArea extends JPanel
 {
 public FontArea(Rectangle bounds)
 {
 setLayout(null);
 setBounds(bounds);
 setOpaque(false);
 }
 public void paintComponent(Graphics g)
 {
 Graphics2D g2D = (Graphics2D)g;
 g2D.setColor(Color.black);
 g2D.fill(getBounds());
 g2D.setColor(Color.cyan);
 g2D.setFont(smallFont);
 drawFromPoint("This is the standard coding font from top
 left (0, 0)", 0, 0, -1, -1, g);
 g2D.setColor(Color.red);
 g2D.setFont(mediumFont);
 drawFromPoint(" text from bottom right ("+getWidth()+",
 "+getHeight()+")", getWidth(), getHeight(), 1, 1, g);
 g2D.setColor(Color.green);
 g2D.setFont(largeFont);
 drawFromPoint("text in the middle", getWidth()/2,
 getHeight()/2, 0, 0, g);
 }
 }
 public static void drawFromPoint(String text, int x, int y, int
 relativeToX, int relativeToY, Graphics g)
 {
 int widthOffset;
 int heightOffset;
 FontMetrics fm = g.getFontMetrics();
 if(relativeToX < 0)
 widthOffset = 0; // left point x
 else if(relativeToX==0)
 widthOffset = -(fm.stringWidth(text)/2); // from middle x
 else // relativeToX > 0
 widthOffset = -fm.stringWidth(text); // from right x
 if(relativeToY < 0)
 heightOffset = fm.getAscent(); // from top y
 else if(relativeToY==0)
 heightOffset = (fm.getHeight()/2)-fm.getDescent(); // from middle y
 else // relativeToY > 0
 heightOffset = -fm.getDescent(); // from bottom y
 x+=widthOffset;
 y+=heightOffset;
 g.drawString(text, x, y);
 }
 public static void main(String[] args)
 {
 new UsingFonts();
 }
 private Font smallFont;
 private Font mediumFont;
 private Font largeFont;
 private static final int DISPLAY_WIDTH = 400;
 private static final int DISPLAY_HEIGHT = 400;
}


Java End example

When you compile and run this example, your output should be similar to the figure at the top of the following page (Screenshot-7).

Java Click To expand
Screenshot-7:

The class java.awt.FontMetrics is used to hold information about a font on a given screen. This allows us to get information such as the font ascent and descent, as we discussed in an earlier figure. These values can be retrieved from the Graphics object that you are drawing to using the method getFontMetrics, as we do in the method drawFromPoint. This method is used to draw a given string value relative to a specified point. The first parameter is simply the string value to be drawn. The next two parameters are the coordinates of a point from which you wish to draw. Now, the next two parameters are the important ones. They define how the text will be displayed relative to the given point. For example, the first line of text that we draw is positioned relative to position (0, 0) of the displayable FontArea component. The relative position is defined by the values for x and y, as –1 and –1, respectively. The parameter relativeToX, when less than 0 (e.g., –1), tells the method that you want to draw the string from the leftmost position of the specified x position, which drawString does by default anyway. The parameter relativeToY, when less than 0 (e.g., –1), basically tells the method that you want to draw the string directly under the specified y position. We can find this new y position by adding the ascent distance of the font to the specified y position. If you look back at the font figure we discussed earlier, you will see that by moving the font text down from its default baseline y position by the ascent distance, the font text will be moved under the baseline. Thus, you have specified the y position below which your text will be displayed. Specifying the relative values 0 and 0 for x and y will display your text centered to the specified position, and specifying the relative values 1 and 1 for x and y, respectively, will display your text from the bottom-right of the specified location. Of course, you can mix these values (for example, relative values 1 and –1 for x and y, respectively, will display your text from top-right relative to the specified x and y position). By passing the Graphics object to the method drawFromPoint, we do not need to worry about the font type or color or passing in the font metrics, as this is all stored in the state of the Graphics object that we can set before we call this method. (Groovy and cool.)

Getting the Available Fonts

A list of available fonts and their text description, which is used as the identification of the font type when creating new Font objects, can be retrieved as an array of strings as follows.

GraphicsEnvironment ge = GraphicsEnvironment.getLocal
 GraphicsEnvironment();
String[] availableFonts = ge.getAvailableFontFamilyNames();
for(int i=0; i<availableFonts.length; i++)
{
 System.out.println(availableFonts[i]);
}


The class java.awt.GraphicsEnvironment is used to store a list of GraphicsDevice objects, which we will discuss later, and also a list of fonts available to your program.

Note that the static method createFont can be used to load your own fonts into a Font object. The only supported type is currently TrueType fonts (.ttf), which is the most commonly used font type anyway. Loading a font is done simply by creating an InputStream to read in the font file and passing this as the second parameter to the createFont method (the first parameter being the constant Font.TRUETYPE _FONT). This is actually a better method when using fonts, as by doing this you are guaranteed that the font you require is going to be available as you supply the file and load it in yourself.

JaVa
   
Comments