Getting started with Java 2D

New support for 2D shapes, transforms, curves, and fonts enters the core environment with Java 1.2

1 2 Page 2
Page 2 of 2

Each of these methods draws from the previous location of our path end point to the final pair of float parameters, our next end point. For lineTo(), this is the only pair given. For quadTo(), the first pair of floats refer to the one and only control point. For curveTo(), the first pair is the first control point and the middle pair is the second control point.

Confused? A simple example should help. Example03 modifies our previous paint() method slightly, drawing two of the green rectangle's edges as non-linear curves.

001   /**
002    * Here we use first-, second-, and third-order
003    * curves together in our GeneralPath.
004    **/
005   public void paint(Graphics g) {
006     g.setColor(Color.red);
007     g.drawRect(50,50,200,200);
008
009     Graphics2D g2d = (Graphics2D)g;
010     g2d.setColor(Color.blue);
011     g2d.drawRect(75,75,300,200);
012
013     //This time our GeneralPath will have nonlinear
014     //segments, one second-order (quadratic) and another
015     //third-order (cubic).  We translate and rotate this shape
016     //again, as we did before.
017     GeneralPath path = new GeneralPath(GeneralPath.EVEN_ODD);
018     path.moveTo(0.0f,0.0f);
019     path.lineTo(0.0f,125.0f);
020     path.quadTo(100.0f,100.0f,225.0f,125.0f);
021     path.curveTo(260.0f,100.0f,130.0f,50.0f,225.0f,0.0f);
022     path.closePath();
023
024     AffineTransform at = new AffineTransform();
025     at.setToRotation(-Math.PI/8.0);
026     g2d.transform(at);
027     at.setToTranslation(50.0f,200.0f);
028     g2d.transform(at);
029
030     g2d.setColor(Color.green);
031     g2d.fill(path);
032   }

Note the quadratic and cubic edges in the output.

GeneralPath is used to create arbitrary shapes using non-linear curve segments

Please consult the Resources below if you need more information on curves in Java 2D.

Fonts and text hit the big time

Java 2D puts fonts and text strings on the same footing as other 2D graphical objects. Text is transformable using AffineTransforms, just like any other 2D object. You can also get a Shape object describing the edges of an arbitrary string of text, then use this to clip other 2D objects or do anything else you can normally do with a Shape.

Let's try out some transforms on a simple text string in Example04.

001   /**
002    * In this example, I draw some text using Font and Graphics2D.
003    * You can see how Font has been extended within Java 2D
004    * with new capabilities, such as being transformable
005    * using AffineTransform.
006    **/
007   public void paint(Graphics g) {
008     //We've cleaned out some cruft (removed the two simple
009     //rectangles) from our Frame.  We are going to reuse
010     //our GeneralPath filled shape, however.  We translate
011     //and rotate this shape as we did before.
012     Graphics2D g2d = (Graphics2D) g;
013
014     GeneralPath path = new GeneralPath(GeneralPath.EVEN_ODD);
015     path.moveTo(0.0f,0.0f);
016     path.lineTo(0.0f,125.0f);
017     path.quadTo(100.0f,100.0f,225.0f,125.0f);
018     path.curveTo(260.0f,100.0f,130.0f,50.0f,225.0f,0.0f);
019     path.closePath();
020
021     AffineTransform at = new AffineTransform();
022     at.setToRotation(-Math.PI/8.0);
023     g2d.transform(at);
024     at.setToTranslation(0.0f,150.0f);
025     g2d.transform(at);
026
027     g2d.setColor(Color.green);
028     g2d.fill(path);
029
030     //Now, let's use some of the Java font and text support.
031     //Note that you need to be sure you have the same fonts I
032     //use in the example (Times New Roman True Type) if you
033     //execute this example code.
034     Font exFont = new Font("TimesRoman",Font.PLAIN,40);
035
036     //Un-comment the following diagnostic println's if you
037     //want to see what font was returned.  This can be useful
038     //when you have limited font support on your system and
039     //are not sure which font the Java runtime may have
040     //substituted for your requested font.
041     //System.out.println(exFont.getFamily());
042     //System.out.println(exFont.isPlain());
043     //System.out.println(exFont.getSize());
044
045     g2d.setFont(exFont);
046     g2d.setColor(Color.black);
047     g2d.drawString("JavaWorld",0.0f,0.0f);
048   }

The following figure shows the output of Example04.

Java 2D translates and rotates text strings using AffineTransforms

Note: There is a bug on at least some Windows NT 4.0 systems running JDK 1.2 Beta 3 whereby drawing the text string is seen to erase the green shape from the output. After this paint() completes, only the text remains showing. Forcing a repaint of the Frame (by resizing the window, for instance) results in the text and shape being drawn correctly. This bug is still under investigation as of this writing, however you can see the latest information on it by reading the java2d-interest mailing list thread discussing it (see Resources).

You probably noticed two things about our output:

  1. Our text string is sitting above the rectangle, which you might not expect
  2. Our text looks very blocky, or jaggy

The first problem occurs because text strings, unlike other Java 2D objects, have their positive y axis flipped relative to the User Space coordinates. This is done to ensure that when you draw text strings, you get readable (right-side up) strings when and where you expect. This flipping of the y axis for text can cause problems from time to time, and is a definite gotcha lurking within Java 2D.

The second problem is slightly more complex in nature but equally well understood: The text has jagged edges because of an aliasing effect. But fear not, all is not lost. We'll have a solution for this dilemma in next month's continuation of our Java 2D series.

Conclusions

Next month I will resume my discussion of Java 2D. I will start by presenting the aliasing workaround built into Java 2D, then show how you can get the Shape of a text string and use it to clip a second shape. I will also show you how to create and manipulate buffered images and how to use the new compositing capabilities in Java 2D to vary the opacity of an image and blend images together.

My thanks to Jonathan Knudsen for reviewing drafts of this Java 2D column and to fellow JavaWorld columnist Mark Johnson for use of his line-numbering script.

As always, please let me know about topics you would like to see covered. I received some wonderful feedback on the debut column, and I hope you will continue to send me your ideas and suggestions. If you have ideas for things you would like to see in a future installment of Media Programming, please let me know.

Bill Day is a software engineer at Silicon Graphics Computer Systems. In addition to writing for JavaWorld, Bill is authoring a book entitled Java Media Players for O'Reilly & Associates. When Bill is not writing or programming, he loves to travel with his wife, speak French, and enjoy life. Java, c'est magnifique!

Learn more about this topic

  • Download the source and class files as a jar file. By placing this jar in your classpath, you can execute the examples in this column without unzipping and compiling the code yourself. http://www.javaworld.com/jw-07-1998/media/jw-07-media.jar
  • Sun's Java 2D home page. This page links to many of the other available Java 2D references, such as the Sun FAQ, the API Specification and User Guide, and sample Java 2D applications. Sun's Windows NT/95 and Solaris implementations are available from this site. http://java.sun.com/products/java-media/2D/index.html
  • This Java Tip documents a workaround for the font-related bug in the Windows version of JDK 1.2 Beta 3. If you are using 1.2B3 on Windows NT/95, you should check this out. http://www.javaworld.com/javaworld/javatips/jw-javatip55.html
  • Haven't used AWT graphics much? Get a firm grounding in JDK 1.0 and 1.1 AWT graphics by reading up on the Graphics class. http://www.javaworld.com/javaworld/jw-11-1996/jw-11-howto.html
  • Developer.com published an article on getting started with Java 2D, titled "An introduction to the Java 2D API." This article goes into good depth explaining AffineTransforms and GeneralPaths, so I would encourage you to read through it if you need to know more about them. http://www.developer.com/news/techworkshop/020598_java2d.html
  • Foley et al.'s text, "Introduction to Computer Graphics", provides a great deal of information on the choice of Bezier and other higher-ordered curves. Chapter 9 explains the preference for cubic curves in the context of both 2D and 3D graphics. A classic graphics reference. http://www.amazon.com/exec/obidos/ASIN/0201609215/billday/ http://www.clbooks.com/sqlnut/SP/search/gtsumt?source=javaworld&isbn=0201609215
  • Knudsen's "Curves Ahead" explains the relationships between character glyphs and the Shape object for a string of text. It also discusses how paths are described using PathIterators and gives a little bit more information on how control points are used to generate curves in Java 2D. http://java.oreilly.com/news/knudsen/java_0398.html
  • Archive of the Java 2D interest mailing list. Where to go with in-depth technical questions about making Java 2D work in your programs. Be sure to search the archive before posting. http://java.sun.com/products/java-media/mail-archive/2D/index.html
  • Follow the thread discussing the Windows NT problem involving shapes and text strings. Begins with the first post relating to the bug. http://java.sun.com/products/java-media/mail-archive/2D/1409.html
  • I wrote a graphics feature for the JavaOne Today show daily for JavaOne 1998. This discusses changes and updates to the Java 2D, Advanced Imaging, and Printing APIs. http://www.javaworld.com/javaworld/javaone98/j1-98-graphics.html
  • Bill's other Media Programming columns /javaworld/topicalindex/jw-ti-media.html

This story, "Getting started with Java 2D" was originally published by JavaWorld.

Copyright © 1998 IDG Communications, Inc.

1 2 Page 2
Page 2 of 2