Java 2D Graphics Table 14-1, Frame Rates for the Bouncer Animation Antialiasing Transform Gradient Outline Dotted Axes Clip Frame Rate (fps) 70 x 70 x x 70 x x x 66 x x x x 21 x x x x x 15 x x x x x x 12 x 42 x x 37 x x x 37 x x x x 32 x x x x x 15 x x x x x x 17 x x x x x x x 14 There are a few interesting tidbits to be gleaned from Table 14-1: The rotational transformation costs almost nothing at all. Drawing the dotted outline is much slower than drawing a solid outline. This makes sense, since each dot of the outline is a separate shape. The solid outline could be one shape. The combination of a clipping shape and a dotted outline actually performs faster when antialiasing is on. 14.2.4 Animated Text This section contains an application, structurally similar to Bouncer, which will help you examine the performance properties of rendering text. Figure 15.31 shows the application, TextBouncer. TextBouncer is a lot like Bouncer, but it adds support for choosing the font that will be used to display the text. It also includes separate checkboxes for shearing and rotational transformations. Here’s the example application: import java.awt.*; import java.awt.event.*; import java.awt.font.*; import java.awt.geom.*; import java.util.Random; public class TextBouncerextends AnimationComponent { public static void main(String[] args) { String s = “Firenze”; final int size = 64; if (args.length > 0) s = args[0]; Panel controls = new Panel(); final Choice choice = new Choice(); GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); Font[] allFonts = ge.getAllFonts(); for (int i = 0; i < allFonts.length; i++) choice.addItem(allFonts[i].getName()); Font defaultFont = new Font(allFonts[0].getName(), Font.PLAIN, size); page 263
Note: If you are looking for good and high quality web space to host and run your application check Lunarwebhost Tomcat Web Hosting services
Java 2D Graphics public void itemStateChanged(ItemEvent ie) { setSwitch(item, (ie.getStateChange() == ie.SELECTED)); } }); return check; } public void timeStep() { Dimension d = getSize(); for (int i = 0; i < mN; i++) { float value = mPoints[i] + mDeltas[i]; int limit = ((i % 2) == 0) ? d.width : d.height; if (value < 0 || value > limit) { mDeltas[i] = -mDeltas[i]; mPoints[i] += mDeltas[i]; } else mPoints[i] = value; } mTheta += Math.PI / 192; if (mTheta > (2 * Math.PI)) mTheta -= (2 * Math.PI); } public void paint(Graphics g) { Graphics2D g2 = (Graphics2D)g; setAntialiasing(g2); setClip(g2); setTransform(g2); Shape shape = createShape(); setPaint(g2); // Fill the shape. g2.fill(shape); // Maybe draw the outline. if (mOutline) { setStroke(g2); g2.setPaint(Color.blue); g2.draw(shape); } drawAxes(g2); } protected void setAntialiasing(Graphics2D g2) { if (mAntialiasing == false) return; g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); } protected void setClip(Graphics2D g2) { if (mClip == false) return; if (mClipShape == null) { Dimension d = getSize(); FontRenderContext frc = g2.getFontRenderContext(); Font font = new Font(”Serif”, Font.PLAIN, 144); String s = “Spoon!”; GlyphVector gv = font.createGlyphVector(frc, s); Rectangle2D bounds = font.getStringBounds(s, frc); mClipShape = gv.getOutline((d.width - (float)bounds.getWidth()) / 2, (d.height + (float)bounds.getHeight()) / 2); } g2.clip(mClipShape); } protected void setTransform(Graphics2D g2) { if (mTransform == false) return; Dimension d = getSize(); page 261
Note: If you are looking for good and high quality web space to host and run your application check Lunarwebhost Tomcat Web Hosting services
Java 2D Graphics controls.add(bouncer.createCheckbox(”Dotted”, Bouncer.DOTTED)); controls.add(bouncer.createCheckbox(”Axes”, Bouncer.AXES)); controls.add(bouncer.createCheckbox(”Clip”, Bouncer.CLIP)); f.add(controls, BorderLayout.NORTH); f.setVisible(true); } // Tweakable variables private boolean mAntialiasing, mGradient, mOutline; private boolean mTransform, mDotted, mAxes, mClip; // …and the constants that represent them. See setSwitch(). public static final int ANTIALIASING = 0; public static final int GRADIENT = 1; public static final int OUTLINE = 2; public static final int TRANSFORM = 3; public static final int DOTTED = 4; public static final int AXES = 5; public static final int CLIP = 6; private float[] mPoints; private float[] mDeltas; private float mTheta; private int mN; private Shape mClipShape; public Bouncer() { mN = 38; mPoints = new float[mN]; mDeltas = new float[mN]; Random random = new Random(); for (int i = 0; i < mN; i++) { mPoints[i] = random.nextFloat() * 500; mDeltas[i] = random.nextFloat() * 3; } // Make sure points are within range. addComponentListener(new ComponentAdapter() { public void componentResized(ComponentEvent ce) { Dimension d = getSize(); for (int i = 0; i < mN; i++) { int limit = ((i % 2) == 0) ? d.width : d.height; if (mPoints[i] < 0) mPoints[i] = 0; else if (mPoints[i] >= limit) mPoints[i] = limit - 1; } } }); } public void setSwitch(int item, boolean value) { switch(item) { case ANTIALIASING: mAntialiasing = value; break; case GRADIENT: mGradient = value; break; case OUTLINE: mOutline = value; break; case TRANSFORM: mTransform = value; break; case DOTTED: mDotted = value; break; case AXES: mAxes = value; break; case CLIP: mClip = value; break; default: break; } } protected Checkbox createCheckbox(String label, final int item) { Checkbox check = new Checkbox(label); check.addItemListener(new ItemListener() { page 260
Note: If you are looking for good and high quality web space to host and run your application check Lunarwebhost Tomcat Web Hosting services
Java 2D Graphics Gradient When this option is checked, the shape is filled with a color gradient. Otherwise, the shape is filled with a solid color. Outline This option controls whether the outline of the shape is stroked. Dotted If the Outline option is checked, this checkbox determines whether the outline is a solid or a dashed line. Axes If this checkbox is checked, coordinate axes will be drawn. The axes are useful in observing the effects of the Trans option. Clip When this option is checked, all rendering is clipped to a text shape. Bouncer follows the conventions for an AnimationComponent subclass: it updates its state in timeStep() and renders itself in paint(). Notice, however, that a lot of the rendering depends on boolean member variables. Bouncer’s main() method wires checkboxes to these boolean variables, so you can adjust what Bouncer renders and how it’s rendered as it’s running. The curvy shape is stored as an array of floating point coordinates called mPoints. Each of these coordinates has a corresponding delta value, stored in mDeltas. For each new frame, timeStep() adds the deltas to the coordinates. If any coordinates are at the edges of the component, the delta value is negated so that the point appears to bounce off the edges of the component. The paint() method, at its core, is very simple. It creates the curvy shape, using the createShape() method, then fills it. It uses a handful of helper methods to accomplish all the other neat features, like turning on antialiasing or using a gradient paint. Here’s the code for Bouncer: import java.awt.*; import java.awt.event.*; import java.awt.font.*; import java.awt.geom.*; import java.util.Random; public class Bouncerextends AnimationComponent { public static void main(String[] args) { final Bouncer bouncer = new Bouncer(); Frame f = new AnimationFrame(bouncer); f.setFont(new Font(”Serif”, Font.PLAIN, 12)); Panel controls = new Panel(); controls.add(bouncer.createCheckbox(”Anti.”, Bouncer.ANTIALIASING)); controls.add(bouncer.createCheckbox(”Trans.”, Bouncer.TRANSFORM)); controls.add(bouncer.createCheckbox(”Gradient”, Bouncer.GRADIENT)); controls.add(bouncer.createCheckbox(”Outline”, Bouncer.OUTLINE)); page 259
Note: If you are looking for good and high quality web space to host and run your application check Lunarwebhost JSP Web Hosting services
Java 2D Graphics } } 14.2.2 AnimationFrame The AnimationFrame class is considerably simpler. It displays a single AnimationComponent in the main part of a frame window. It registers itself to be notified when the AnimationComponent’s frame rate changes, and it displays the frame rate in the bottom part of the window. Here’s the AnimationFrame class: import java.awt.*; import java.text.NumberFormat; public class AnimationFrame extends ApplicationFrame { private Label mStatusLabel; private NumberFormat mFormat; public AnimationFrame(AnimationComponent ac) { super(”AnimationFrame v1.0″); setLayout(new BorderLayout()); add(ac, BorderLayout.CENTER); add(mStatusLabel = new Label(), BorderLayout.SOUTH); // Create a number formatter. mFormat = NumberFormat.getInstance(); mFormat.setMaximumFractionDigits(1); // Listen for the frame rate changes. ac.setRateListener(this); // Kick off the animation. Thread t = new Thread(ac); t.start(); } public void rateChanged(double frameRate) { mStatusLabel.setText(mFormat.format(frameRate) + ” fps”); } } 14.2.3 Animated Shapes Let’s take this animation framework out for a test drive. The following class, Bouncer, uses the framework to animate a curvy shape made from a series of cubic curves. Each of the endpoints and control points of the curves moves around the window, bouncing off the edges. The rendered shape is constantly changing as the endpoints and control points of its segments move around the window. Figure 15.30 shows a snapshot of this example in action. The options are as follows: Anti This checkbox controls whether antialiasing is used to render the shape. Trans When checked, this option causes the entire shape to rotate slowly. page 258
Note: If you are looking for good and high quality web space to host and run your application check Lunarwebhost JSP Web Hosting services