What Is Java 2D?

   

Java 2D enhances the AWT's support for graphics, fonts, colors, and images by introducing additional rendering options, new shapes , improved text management, buffered images, and a uniform rendering model for both screen and printer devices. These enhancements can lead to richer user interfaces and new kinds of Java applications.

The Java 2D API enables the creation of graphics libraries (such as CAD ”Computer Assisted Drafting ”libraries), special effects libraries for images, and read/write filters for use with the Java Media Framework (JMF). In fact, JMF uses Java 2D to perform its rendering tasks .

Graphics2D

When the time comes for a component to render its appearance, the component's paint method is called with a reference to a Graphics subclass object that represents a graphics context. However, this object is really a Graphics2D object. When accessed via a Graphics reference, only Graphics methods can be called. If this object is cast to a Graphics2D object, all of Graphics2D 's methods, along with inherited Graphics methods, can be called.

Like Graphics, Graphics2D is located in the java.awt package. To access Graphics2D methods, cast the Graphics reference to a Graphics2D reference, as shown in the following code fragment:

 public void paint (Graphics g) {    Graphics2D g2 = (Graphics2D) g;    // Java2D stuff } 

Coordinate Systems

Java 2D works with a pair of coordinate systems: user space and device space. User space is a device-independent logical coordinate system that's automatically used by applications. All coordinates passed to Java 2D methods are specified in terms of user space. These coordinates are floating point numbers that represent logical pixel locations, instead of physical locations. For example, you can refer to a logical pixel at (50.392, -45.3). Obviously, these are not the coordinates of a physical pixel. In contrast, device space is a device-dependent physical coordinate system that varies with the target rendering device. Device space coordinates are integer values that identify physical pixel locations.

Java 2D automatically converts from user space to device space, by using an affine transformation (a mathematical concept whereby straight lines are transformed into straight lines and parallel lines are transformed into parallel lines, but the distance between points and the angles between lines can be altered ). The default affine transform maps the origins of both coordinates systems to the upper-left corner, causes x values to increase to the right, and y values to increase to the bottom. However, it's possible to introduce a new transform that changes the location of either origin along with the directions in which x/y increase through positive values. This is accomplished by way of the AffineTransform class (discussed in a later section).

Java 2D maintains compatibility with Graphics methods (such as the drawLine method), by regarding the integer coordinates passed to these methods as device space coordinates. However, Java 2D still uses its affine transform to transform these coordinates into other device space coordinates.

Environments, Devices, and Configurations

Java 2D identifies three levels of configuration information that support the conversion from user space to device space. This information is encapsulated in objects created from subclasses of the abstract GraphicsEnvironment, GraphicsDevice, and GraphicsConfiguration classes (located in the java.awt package).

GraphicsEnvironment describes the collection of rendering devices visible to a Java application on a particular platform. Rendering devices include screens, printers, and image buffers. GraphicsEnvironment also includes a list of all available fonts. Each GraphicsEnvironment is associated with at least one GraphicsDevice.

GraphicsDevice describes an application-visible rendering device, such as a screen or printer. Each possible configuration of this device is represented by a GraphicsConfiguration subclass object.

GraphicsConfiguration describes a single mode of operation for a GraphicsDevice. For example, a super-VGA screen device can operate in several modes: 640 480 16 colors, 640 480 256 colors, 800 600 256 colors, and so on. Its screen is represented by a GraphicsDevice subclass object, and each of these modes is represented by a GraphicsConfiguration object.

To work with these classes, you first need to get a copy of the local graphics environment, as demonstrated by the following code fragment:

 GraphicsEnvironment ge; ge = GraphicsEnvironment.getLocalGraphicsEnvironment (); 

After you have a graphics environment, a GraphicsDevice subclass object describing the default screen can be obtained by calling getDefaultScreenDevice. Alternatively, you can obtain an array of GraphicsDevice subclass objects describing all available screens by calling getScreenDevices. The following code fragment shows both approaches:

 GraphicsDevice default = ge.getDefaultScreenDevice (); GraphicsDevice [] all = ge.getScreenDevices (); 

If you are more interested in retrieving information about fonts, you can call getAllFonts or getAvailableFontFamilyNames. The getAllFonts method returns an array of Font objects. (Each object describes a font with a one-point size. To create an identical font with a different size , you would call Font 's deriveFont method.) The getAvailableFontFamilyNames method returns an array of String objects that contain font family names . Your program might present this information to a user in a list box. Both of these methods are demonstrated in the following code fragment:

 Font [] fontList = ge.getAllFonts (); Font f = fontList [0].deriveFont (2.0); String [] fnames = ge.getAvailableFontFamilyNames (); 

Listing 18.1 presents source code to a ListFonts application that obtains the local graphics environment and an array of all installed fonts, and then prints out the family and font names for each font.

Listing 18.1 The ListFonts Application Source Code
 // ListFonts.java import java.awt.*; class ListFonts {    public static void main (String [] args)    {       GraphicsEnvironment ge;       ge = GraphicsEnvironment.getLocalGraphicsEnvironment ();        Font [] fonts = ge.getAllFonts ();       for (int i = 0; i < fonts.length; i++)            System.out.println ("Family = " + fonts [i].getFamily ()                                + ", " + " Font = "                                + fonts [i].getFontName ());    } } 
Multiple-Screen Environments

You've probably heard about computers that support multiple screens. In one case, each screen displays different content. In a second case, all screens display the same content. In a third case, these screens are configured into one large virtual desktop. The desktop's upper-left corner is usually located in the upper-left corner of the screen that, in turn, is located in the upper-left corner of a rectangular grid of screens, whereas the desktop's lower-right corner is usually located in the lower-right corner of the screen that, in turn , is located in the lower-right corner of this screen grid.

When two or more screens are used to form a virtual desktop, a virtual desktop coordinate system existing outside the bounds of any screen is used to identify the coordinates of a pixel. One of these screens is designated the primary screen, and its upper-left corner is located at ( 0, ). Usually, the primary screen is positioned in the upper-left corner of a rectangular screen grid. If not, the virtual desktop might use negative coordinates. Figure 18.1 illustrates a virtual desktop.

Figure 18.1. A virtual desktop is composed of multiple screens.

graphics/18fig01.gif

Version 1.3 of the Java 2 SDK supports the use of multiple screens. You can create Frame, JFrame, Window, or JWindow objects with a GraphicsConfiguration argument that targets a specific screen using one of its configurations (screen dimensions and number of colors). For example, the following code fragment constructs a frame that takes an argument consisting of the default (primary) screen's default graphics configuration:

 GraphicsEnvironment ge; ge = GraphicsEnvironment.getLocalGraphicsEnvironment (); GraphicsDevice gd = ge.getDefaultScreenDevice (); Frame f = new Frame (gd.getDefaultConfiguration ()); 

You can determine if a screen is the primary screen by calling its default graphics configuration's getBounds method and checking for a (0, 0) origin. This is shown in the following code fragment:

 Rectangle bounds = gd.getDefaultConfiguration ().getBounds (); Point origin = bounds.getLocation (); if (origin.x == 0 && origin.y == 0)     System.out.println ("primary screen"); 

Tip

You can determine if you are working in a multiple-screen environment by doing the following: Obtain an array of all screen devices. For each device, obtain an array of that device's configurations. For each configuration, call its getBounds method and examine the origin value. If this value is anything other than (0, 0), you are working in a multiple-screen environment.


Just as getBounds returns a screen's origin, it also returns a screen's size. It's possible to obtain the total size of the virtual desktop by taking the union of each getBounds 'return value for all screens and configurations. Listing 18.2 presents source code to the MultipleScreenDemo1 application, which shows how this is done.

Listing 18.2 The MultipleScreenDemo1 Application Source Code
 // MultipleScreenDemo1.java import java.awt.*; class MultipleScreenDemo1 {    public static void main (String [] args)    {       GraphicsEnvironment ge;       ge = GraphicsEnvironment.getLocalGraphicsEnvironment ();       Rectangle vBounds = new Rectangle ();       GraphicsDevice [] gdArray = ge.getScreenDevices();       for (int i = 0; i < gdArray.length; i++)       {            GraphicsDevice gd = gdArray [i];            GraphicsConfiguration [] gcArray = gd.getConfigurations ();            for (int j = 0; j < gcArray.length; j++)                 vBounds = vBounds.union (gcArray [j].getBounds ());       }       Point origin = vBounds.getLocation ();       System.out.println ("Virtual x = " + origin.x);       System.out.println ("Virtual y = " + origin.y);       Dimension size = vBounds.getSize ();       System.out.println ("Virtual width = " + size.width);       System.out.println ("Virtual height = " + size.height);    } } 

How would you go about writing a program that displays a separate frame on each screen? Listing 18.3 presents source code to the MultipleScreenDemo2 application that shows how to accomplish this task.

Listing 18.3 The MultipleScreenDemo2 Application Source Code
 // MultipleScreenDemo2.java import java.awt.*; import java.awt.event.*; class MultipleScreenDemo2 {    public static void main (String [] args)    {       GraphicsEnvironment ge;       ge = GraphicsEnvironment.getLocalGraphicsEnvironment ();       GraphicsDevice [] gdArray = ge.getScreenDevices ();       for (int i = 0; i < gdArray.length; i++)       {            GraphicsDevice gd = gdArray [i];            GraphicsConfiguration [] gcArray = gd.getConfigurations ();            for (int j = 0; j < gcArray.length; j++)            {                 Frame f = new Frame (gdArray [i].                                      getDefaultConfiguration ());                 Rectangle bounds = gcArray [j].getBounds ();                 int xoffset = bounds.x;                 int yoffset = bounds.y;                 f.addWindowListener (new wClose ());                 f.setTitle ("Screen "+ Integer.toString (i)                            + ", GC# " + Integer.toString (j));                 f.setSize (200, 200);                 f.setLocation ((j * 50) + xoffset, (j * 60) + yoffset);                 f.setVisible (true);            }       }    } } class wClose extends WindowAdapter {    public void windowClosing (WindowEvent e)    {       System.exit (0);    } } 

When you run MultipleScreenDemo2 on a computer that uses multiple screens, you'll see a separate frame appearing on each screen. If you are fortunate enough to have a rectangular grid of screens in front of you, you'll see the position of each frame staggered to the right and below the frame appearing on the screen to its immediate left.

The API

Java 2D is organized into eight packages that contain many classes and interfaces. Although most of these are new, some are AWT classes/interfaces that have been enhanced for use with Java 2D. Table 18.1 presents the names and contents of these packages, along with a list of affected classes and interfaces.

Table 18.1. Java's Java 2D packages
Package Description
java.awt Classes and interfaces that are general in nature or enhance legacy classes. These include AlphaComposite, BasicStroke, Color , Composite, CompositeContext, Font, GradientPaint, Graphics2D, GraphicsConfiguration, GraphicsDevice, GraphicsEnvironment, Paint, PaintContext, Rectangle, RenderingHints, Shape, Stroke, TexturePaint, and Transparency.
java.awt.color Classes and interfaces for the definition of color spaces and color profiles. These include ColorSpace, ICC_ColorSpace, ICC_Profile, ICC_ProfileGray, and ICC_ProfileRGB. (Consult the Java 2D user guide to learn more about ICC and color spaces. This guide is part of the Java 2 SDK 1.3 documentation.)
java.awt.font Classes and interfaces for text layouts and the definition of fonts. These include FontRenderContext, GlyphJustificationInfo, GlyphMetrics, GlyphVector, GraphicAttribute, ImageGraphicAttribute, LineBreakMeasurer, LineMetrics, MultipleMaster, OpenType, ShapeGraphicAttribute, TextAttribute, TextHitInfo, TextLayout, TextLayout.CaretPolicy, TextMeasurer, and TransformAttribute.
java.awt.geom Classes and interfaces related to the definition of geometric primitives. These include AffineTransform, Arc2D, Arc2D.Double, Arc2D.Float, Area, CubicCurve2D, CubicCurve2D.Double, CubicCurve2D.Float, Dimension2D, Ellipse2D, Ellipse2D.Double, Ellipse2D.Float, FlatteningPathIterator, GeneralPath, Line2D, Line2D.Double, Line2D.Float, PathIterator, Point2D, Point2D.Double, Point2D.Float, QuadCurve2D, QuadCurve2D.Double, QuadCurve2D.Float, Rectangle2D, Rectangle2D.Double, Rectangle2D.Float, RectangularShape, RoundRectangle2D, RoundRectangle2D.Double, and RoundRectangle2D.Float.
java.awt.image Classes and interfaces for creating and modifying images. These include AffineTransformOp, BandCombineOp, BandedSampleModel, BufferedImage, BufferedImageFilter, BufferedImageOp, ByteLookupTable, ColorConvertOp, ColorModel, ComponentColorModel, ComponentSampleModel, ConvolveOp, DataBuffer, DataBufferByte, DataBufferInt, DataBufferShort, DataBufferUShort, DirectColorModel, IndexColorModel, Kernel, LookupOp, LookupTable, MultiPixelPackedSampleModel, PackedColorModel, PixelInterleavedSampleModel, Raster, RasterOp, RescaleOp, SampleModel, ShortLookupTable, SinglePixelPackedSampleModel, TileObserver, WritableRaster, and WritableRenderedImage. (Some of these classes ”such as ColorModel ”have been examined to some degree in previous chapters.)
java.awt.image.renderable Classes and interfaces for producing rendering-independent images. These include ContextualRenderedImageFactory, ParameterBlock, RenderableImage, RenderableImageOp, RenderableImageProducer, RenderContext, and RenderedImageFactory.
java.awt.print Classes and interfaces for printing non-Java 2D and Java 2D graphics, text, and images. These include Book, Pageable, PageFormat, Paper, Printable, PrinterGraphics, and PrinterJob.
java.text Classes and interfaces for text layout. These include AttributedCharacterIterator, AttributedCharacterIterator.Attribute, and AttributedString.
   


Special Edition Using Java 2 Standard Edition
Special Edition Using Java 2, Standard Edition (Special Edition Using...)
ISBN: 0789724685
EAN: 2147483647
Year: 1999
Pages: 353

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net