Java Tip 81: Jazz up the standard Java fonts
Design a unique look with some simple tricks
A few simple tricks applied to standard Java fonts can help make your Web site stand out from the crowd. With the basic knowledge presented here, you will be able to create a set of font styles richer than the standard plain, bold, and italic. And do not confine yourself to these ideas — they just lay the groundwork. You only need a limited mathematical background to understand the computations. So read on and discover the possibilities!
Display your system fonts
Before I proceed, you need to find out what fonts are available on your system. These can vary between Java Virtual Machine (JVM) implementations. The following code displays the names of all the fonts available on a particular JVM. The screenshot on the right illustrates the fonts available on my PC. Yours may look different.
String [] fonts = getToolkit().getFontList();
Font font;
int font_size = 20;
int x = 20;
int y = 25;
int line_spacing = 25;
for (int i = 0; i < fonts.length; i++)
{
font = new Font(fonts[i], Font.BOLD, font_size);
g.setFont(font);
g.drawString(fonts[i], x, y);
y += line_spacing;
}
Position the points
For most of the seven drawing tricks in this article you duplicate the text, slightly reposition it, and color the duplicate appropriately. The image on the right shows eight positions surrounding a center point. On the horizontal axis x increases from west to east, and on the vertical axis y increases from north to south. For example, the coordinate for the northeast position is (x + 1, y - 1)
if the center is (x, y)
. I’ll use the positions of this image in explaining the drawing tricks. The coordinate for the center position is assumed to be (x, y)
.
The following functions are used to improve code readability:
int ShiftNorth(int p, int distance) {
return (p - distance);
}
int ShiftSouth(int p, int distance) {
return (p + distance);
}
int ShiftEast(int p, int distance) {
return (p + distance);
}
int ShiftWest(int p, int distance) {
return (p - distance);
}
Add a shadow
The easiest trick adds a shadow to the text. Use a dark color for the shadow and draw it near the center. Then draw the text in the center with its color on top of the shadow. The example here shows a shadow two points away in a southeasterly direction. The light looks as if it’s coming from the northwest.
g.setColor(new Color(50, 50, 50));
g.drawString("Shadow", ShiftEast(x, 2), ShiftSouth(y, 2));
g.setColor(new Color(220, 220, 220));
g.drawString("Shadow", x, y);
Engrave the text
You can achieve an engraved effect by using a darker color for the background than for the text. To emulate a light projected on the inner walls of the engraved text, use a brighter color and draw it near the center. Finally, draw the text in the center.
The example here draws the inner walls one point southeast of the center with the light coming from the northwest. This effect relies heavily on color selection, so be careful!
g.setColor(new Color(220, 220, 220));
g.drawString("Engrave", ShiftEast(x, 1), ShiftSouth(y, 1));
g.setColor(new Color(50, 50, 50));
g.drawString("Engrave", x, y);
Outline the letters You can outline the text by first drawing it at the northwest, southwest, northeast, and southeast positions with the outline color and then drawing the text in the center with the text color. The example here does exactly that with a red outline color and a yellow text color.
g.setColor(Color.red);
g.drawString("Outline", ShiftWest(x, 1), ShiftNorth(y, 1));
g.drawString("Outline", ShiftWest(x, 1), ShiftSouth(y, 1));
g.drawString("Outline", ShiftEast(x, 1), ShiftNorth(y, 1));
g.drawString("Outline", ShiftEast(x, 1), ShiftSouth(y, 1));
g.setColor(Color.yellow);
g.drawString("Outline", x, y);
Hollow them out
Hollowing is nearly the same as outlining. When you draw the text in the center, use the background color instead. That way, only the contour of the text appears. In the example, bg
is the background color used to draw the text.
g.setColor(Color.black);
g.drawString("Hollow", ShiftWest(x, 1), ShiftNorth(y, 1));
g.drawString("Hollow", ShiftWest(x, 1), ShiftSouth(y, 1));
g.drawString("Hollow", ShiftEast(x, 1), ShiftNorth(y, 1));
g.drawString("Hollow", ShiftEast(x, 1), ShiftSouth(y, 1));
g.setColor(bg);
g.drawString("Hollow", x, y);
Cut them into segments
An IBM-logo effect requires two major steps. First you carefully measure the font dimensions. Then you draw the horizontal lines on the text with the background color at computed positions. You start those lines from below the descenders.
The following example uses bg
as the background color. For each interval of three pixels, it draws a line from below the font’s descenders (descent
) and moves up until the ascenders (height
) are reached. The string width is w
, the ascender height is h
, and the descender is d
.
int w = (g.getFontMetrics()).stringWidth("Segment");
int h = (g.getFontMetrics()).getHeight();
int d = (g.getFontMetrics()).getDescent();
g.setColor(new Color(220, 220, 220));
g.drawString("Segment", x, y);
g.setColor(bg);
for (int i = 0; i < h; i += 3)
g.drawLine(x, y + d - i, x + w, y + d - i);
Open a third dimension
To achieve a three-dimensional effect, you first choose a color slightly darker than the text; then, for the main shadow, choose a second color much darker than the text. Duplicate the text in one color along one direction (say, north) and in the other color along another direction (say, west). This process results in two shadow faces for the text.
Finally, you draw the text in the center with its color on top of the shadows. The example here uses yellow as the text color and two darker yellows as the shadows. The thickness of the text is 5. The light comes roughly from the southeast.
Color top_color = new Color(200, 200, 0);
Color side_color = new Color(100, 100, 0);
for (int i = 0; i < 5; i++) {
g.setColor(top_color);
g.drawString("3-Dimension", ShiftEast(x, i), ShiftNorth(ShiftSouth(y, i), 1));
g.setColor(side_color);
g.drawString("3-Dimension", ShiftWest(ShiftEast(x, i), 1), ShiftSouth(y, i));
}
g.setColor(Color.yellow);
g.drawString("3-Dimension", ShiftEast(x, 5), ShiftSouth(y, 5));
Put the words in motion
The idea behind this effect is enlarging the font larger as the text approaches the viewer. At the same time the text color should be darker, the farther it is from the viewer. Also, you need to draw the text from far to near so you don’t block any part of the closest image. The example uses green as the text color. It increases the font size and makes the color brighter at a specified speed. width
is the window width and w
is the string width. This example centers the text and redraws it 20 times.
for (int i = 0; i < 20; i++) {
font_size = 12 + i;
g.setFont(new Font("TimesRoman", Font.PLAIN, font_size));
w = (g.getFontMetrics()).stringWidth("Motion");
g.setColor(new Color(0, 65 + i * 10, 0));
g.drawString("Motion", (width - w) / 2, ShiftSouth(y, speed * i));
}
Bonus tip: Test your applet in the applet viewer
Instead of creating an HTML file for your applet code, simply put a comment in the .java file like this:
/*<applet code=MyApplet.class width=300 height=400>
</applet>
*/
The applet viewer will parse the applet tag and display the applet, so you can just test it with this command line:
appletviewer MyApplet.java
by Todd M. Greanier, Frontier Corp.
Create your own effects
This article is intended to inspire you with a few codes that create font styles, but there are limitations. For example, the engraving effect does not work with many colors. Also, some GUI components are not always able to incorporate these effects. That means you may want to make a set of your own GUI components. In fact, building a set of such components is one of the major applications you can use in the future. Another application might use the same techniques in a general drawing context to embellish text buttons, borders, bars, and other geometric shapes. Other possibilities include animations, snazzy titles, logos, and so forth. More advanced developers can probably apply image processing techniques to make even cooler effects.