Java Technology Home Page
A-Z Index

Java Developer Connection(SM)
Online Training

Downloads, APIs, Documentation
Java Developer Connection
Tutorials, Tech Articles, Training
Online Support
Community Discussion
News & Events from Everywhere
Products from Everywhere
How Java Technology is Used Worldwide
 
Training Index

2D Text Tutorial
Lesson 2: Drawing Styled Text

By Monica Pawlan

[<<BACK] [CONTENTS] [NEXT>>]

This lesson explains how to draw simple and complex styled text using the java.awt.font.TextLayout class to create interesting and pleasing visual effects.


Draw a Line of Text

The java.awt.font.TextLayout class lets you create styled text from combinations of strings, fonts, and attribute sets. Once created, a TextLayout object cannot be edited, but its methods give you access to layout, font, caret, selection, and hit test information.

The following code uses Font, TextLayout, and FontRenderContext objects to draw a simple text string in 24 point Times Bold. Here is the complete TimesB.java source code.

FontRenderContext frc = g2.getFontRenderContext();
Font f = new Font("Helvetica",Font.BOLD, 24);
String s = new String("24 Pont Helvetica Bold");
TextLayout tl = new TextLayout(s, f, frc);
Dimension theSize=getSize();
g2.setColor(Color.green);
tl.draw(g2, theSize.width/30, theSize.height/2);
  • Java.awt.Font represents an instance of a font face from the available system fonts.

  • java.awt.TextLayout represents unchangeable styled character data.

  • java.awt.font.FontRenderContext contains the information needed to correctly measure and position text when it is drawn.

Draw Multiple Lines of Text

You can use the TextLayout and java.awt.LineBreakMeasurer classes to draw a paragraph of styled text. This next example uses a LineBreakMeasurer object to create and draw lines of text (text layouts) that fit within the component's width. Information about the font returned by the TextLayout getAscent and getDescent methods is used to position the lines in the component. The text is stored as an AttributedCharacterIterator so the font and point size attributes can be stored with the text.

Here is the complete source code for the LineBreakSample.java example. The SampleUtils.java class contains the text displayed by the LineBreakSample application.


Note: The LineBreakSample application supports foreign language text. See Lesson 4: Foreign Language Support for more information.

public class LineBreakSample extends Component {

  private LineBreakMeasurer lineMeasurer;
  private int paragraphStart;
  private int paragraphEnd;

  public LineBreakSample
      (AttributedCharacterIterator paragraph) {

    FontRenderContext frc = 
      SampleUtils.getDefaultFontRenderContext();
    paragraphStart = paragraph.getBeginIndex();
    paragraphEnd = paragraph.getEndIndex();
    lineMeasurer = 
      new LineBreakMeasurer(paragraph, frc);
  }

  public void paint(Graphics g) {

    Graphics2D graphics2D = (Graphics2D) g;
    Dimension size = getSize();
    float formatWidth = (float) size.width;

    float drawPosY = 0;

    lineMeasurer.setPosition(paragraphStart);
    while (lineMeasurer.getPosition() < paragraphEnd) {

       TextLayout layout = 
		lineMeasurer.nextLayout(formatWidth);
       drawPosY += layout.getAscent();
       float drawPosX;
       if (layout.isLeftToRight()) {
        drawPosX = 0;
       }
       else {
         drawPosX = formatWidth - layout.getAdvance();
       }

       layout.draw(graphics2D, drawPosX, drawPosY);
       drawPosY += layout.getDescent() + 
				layout.getLeading();
     }
  }

A New Slant on Text

You can create a Font object from a transform object that provides information on how to rotate, scale, move, or shear the font. This next example uses a shear transformation to draw slanted text. First, the string is drawn without the transform, and then it is drawn in a different location with it. Here is the complete StillLife.java source code.

  int w = getSize().width;
  int h = getSize().height;

//Create transforms
  AffineTransform at = new AffineTransform();
  at.setToTranslation(30, 50);
  AffineTransform fontAT = new AffineTransform();
  fontAT.shear(0.2, 0.0);

//Create fonts and text layouts
  FontRenderContext frc = g2.getFontRenderContext();
  Font theFont = new Font("Times", Font.BOLD, w/25);
  String s = new String("Still Life with Text");
  TextLayout tstring = new TextLayout(s, theFont, frc);

  Font theDerivedFont = theFont.deriveFont(fontAT);
  String str = new String("Still Life with Slanted Text");
  TextLayout tstring2 = new TextLayout(str, 
			theDerivedFont, frc);

//Draw regular string
  g2.setColor(Color.blue);
  g2.transform(at);
  tstring.draw(g2, (float)0, (float)0);

//Draw string with shear transformation on the font
  g2.setColor(Color.green);
  g2.transform(at);
  tstring2.draw(g2, (float)0, (float)0);

Filling a Clipping Area with an Image

This next example creates a clipping area from the text string The Starry Night, and uses Vincent van Gogh's painting, The Starry Night, to fill the clipping area. Here is the complete Starry.java source code.

The Starry Night by Vincent van Gogh The example code creates a text layout with the string The Starry Night in Times Bold. Next, it gets the width of the TextLayout bounds. The bounds contains all the pixels the layout can draw.

Then, it gets the outline of the text layout and uses the width of the bounds to calculate the X and Y positions for the origins of the layout. The outline is used to create a Shape object, and a Rectangle object is created from the bounds of the Shape object.

At this point, the graphics context color is set to blue and the Shape object is drawn into the graphics context. The image and code segment below show what has happened so far.

FontRenderContext frc = g2.getFontRenderContext();
Font f = new Font("Times",Font.BOLD,w/10);
String s = new String("The Starry Night");
TextLayout tl = new TextLayout(s, f, frc);
float sw = (float) tl.getBounds().getWidth();
Shape shape = tl.getOutline(null,w/2-sw/2,h/4);
Rectangle r = shape.getBounds();
g2.setColor(Color.blue);
g2.draw(shape);

Lastly, a clipping area is set on the graphics context using the Shape object, and the starry.gif image is drawn into the clipping area starting at the lower-left corner of the Rectangle object (r.x and r.y) and filling the full height and width of the Rectangle object.

g2.setClip(shape);
g2.drawImage(img, r.x, r.y, r.width, r.height, this);

Filling a Clipping Area with Lines

For a slightly different effect, this next example creates a clipping area from the text layout By, fills the clipping area with blue, and draws yellow lines across the clipping area over the blue fill. Information returned by the TextLayout getAscent method is used to position the line on the display.

Here is the complete Clipping.java source code.

FontRenderContext frc = g2.getFontRenderContext();
Font f = new Font("Helvetica",Font.BOLD,w/8);
String s = new String("By");
TextLayout tl = new TextLayout(s, f, frc);
float sw = (float) tl.getBounds().getWidth();
Shape shape = tl.getOutline(null,w/2-sw/2,h/2);
g2.setClip(shape);
g2.setColor(Color.blue);
g2.fill(shape.getBounds());
g2.setColor(Color.yellow);
for (int j = shape.getBounds().y; 
    j < shape.getBounds().y + 
    shape.getBounds ().height; j=j+3) {
  Line2D line = new Line2D.Float( 0.0f, (float) j, 
			(float) w, (float) j);
  g2.draw(line);
}

Filling a Clipping Area with Characters

This next example creates a clipping area from the text layout Vincent van Gogh, fills it with blue, and draws white asterisks (*) into the clipping area over the blue fill to give the effect of white stars in a blue sky. Here is the complete TextClipping.java source code.

FontRenderContext frc = g2.getFontRenderContext();
Font f = 
  new Font("Times New Roman Bold",Font.PLAIN,w/8);
String s = new String("Vincent van Gogh");
TextLayout tl = new TextLayout(s, f, frc);
float sw = (float) tl.getBounds().getWidth();
Shape shape = tl.getOutline(null,w/2-sw/2,h-h/6);
g2.setClip(shape);
g2.setColor(Color.blue);
g2.fill(shape.getBounds());
g2.setColor(Color.white);
f = new Font("Helvetica",Font.BOLD,10);
tl = new TextLayout("+", f, frc);
sw = (float) tl.getBounds().getWidth();

Rectangle r = shape.getBounds();
int x = r.x;
int y = r.y;
while ( y < (r.y + r.height+(int) tl.getAscent()) ) {
      tl.draw(g2, x, y);
      if ((x += (int) sw) > (r.x+r.width)) {
      x = r.x;
      y += (int) tl.getAscent();
      }
}

Text Attributes and Replacement Graphics

The TextAttribute class defines text attributes so you can define an Attributed string with text attributes. This next example uses text attributes to define the font and a character replacement image for the java.awt.text.AttributedString that contains the text The Starry Night. An ImageGraphicAttribute is created from an image to do this. Here is the complete MakeImage.java source code.
public void paint(Graphics g) {
  Graphics2D g2;
  g2 = (Graphics2D) g;
  g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
                RenderingHints.VALUE_ANTIALIAS_ON);
  g2.setRenderingHint(RenderingHints.KEY_RENDERING,
                RenderingHints.VALUE_RENDER_QUALITY);

  Font f = new Font("Times",Font.BOLD, 24);
  AttributedString ats = 
    new AttributedString("The  Starry  Night");
  ImageGraphicAttribute iga = 
    new ImageGraphicAttribute(img, 
    (int) BOTTOM_ALIGNMENT);
  ats.addAttribute(
    TextAttribute.CHAR_REPLACEMENT, iga, 4, 5);
  ats.addAttribute(
    TextAttribute.CHAR_REPLACEMENT, iga, 11, 12);
  ats.addAttribute(TextAttribute.FONT, f, 0, 18);
  AttributedCharacterIterator iter = ats.getIterator();

  FontRenderContext frc = g2.getFontRenderContext();
  tl = new TextLayout(iter, frc);
  g2.setColor(Color.red);
  tl.draw(g2, (float)20, (float)30);
}

[ This page was updated: 12-Nov-99 ]

Products & APIs | Developer Connection | Docs & Training | Online Support
Community Discussion | Industry News | Solutions Marketplace | Case Studies
Glossary - Applets - Tutorial - Employment - Business & Licensing - Java Store - Java in the Real World
FAQ | Feedback | Map | A-Z Index
For more information on Java technology
and other software from Sun Microsystems, call:
(800) 786-7638
Outside the U.S. and Canada, dial your country's AT&T Direct Access Number first.
Sun Microsystems, Inc.
Copyright © 1995-99 Sun Microsystems, Inc.
All Rights Reserved. Legal Terms. Privacy Policy.