Download this source file

// Logo2D.java - Demos Many 2D graphics effects.  Note this
// Applet requires a Java 2 (version 1.4 or higher) JVM to run.
// This shows a fancy Java2D, internationalized logo.
// A special feature of this logo is the use of random numbers
// to control the appearence of the text.
//
// (C) 2003 by Wayne Pollock, Tampa FL USA.  All Rights Reserved.

/*
    <APPLET CODE="Logo2D" HEIGHT="250" WIDTH="400">
    </APPLET>
*/

import java.applet.*;
import java.awt.*;
import java.awt.font.*;  // For fancy text effects
import java.awt.geom.*;  // Shapes to draw and fill
import java.util.Random; // New random number generator class

public class Logo2D extends Applet
{
   long seed;  // value for random number generator.
   String logo, motto;

   public void init ()
   {
      seed = new Random().nextLong();
      setBackground( Color.pink );
      logo = "Miracle Widgets";
      motto = "It's a Miracle if it works well";
   }

   public void paint( Graphics gr )
   {
      Graphics2D g = (Graphics2D) gr;

      Random rng = new Random( seed ); // create random number generator.

      // Set the Font to something big:
      Font mottoFont = new Font( "Serif", Font.BOLD, 18 );
      Font logoFont = new Font( "Monospaced", Font.BOLD, 24 );
      FontMetrics fm;

      int hpos;        // The left edge for drawing text
      int ypos = 145;  // The baseline for drawing motto text

      // Draw simple text, centered:
      g.setFont( mottoFont );
      fm = g.getFontMetrics();
      hpos = ( getWidth() - fm.stringWidth(motto) ) / 2;
      g.drawString( motto, hpos, ypos );
      ypos -= (fm.getHeight() + 5);  // Place the logo above motto.

      // Draw "fun" text.  First convert a String into an array
      // of "glyphs" which are Font-specific Shapes.  Then before
      // drawing any letter shape, apply some random transformations:

      // Save original transformation and Paint:
      AffineTransform originalTransform = g.getTransform();
      Paint originalPaint = g.getPaint();

      // Set initial drawing position for logo:
      g.setFont( logoFont );
      fm = g.getFontMetrics();
      hpos = ( getWidth() - fm.stringWidth(logo) ) / 2;

      g.translate( hpos, ypos );

      // Create a GlyphVector (list of Shapes of letters):
      FontRenderContext frc = g.getFontRenderContext();
      GlyphVector gv = logoFont.createGlyphVector( frc, logo );

      // Create a Transform to "jiggle" each letter shape a bit
      // by small random scale, rotate, or shear transformations:
      for ( int i = 0; i < gv.getNumGlyphs(); ++i )
      {
         // Create the transform to use to jiggle the letter:
         AffineTransform at = new AffineTransform();

         // Move ("translate") to position to draw the letter:
         Point2D pos = gv.getGlyphPosition( i );
         at.translate( pos.getX(), pos.getY() );

         // Jiggle the letter:
         switch ( rng.nextInt(4) )
         {
         case 0: // Apply a rotate transformation by +/- 10..20 degrees:
            int sign = ( rng.nextInt( 2 ) == 0 ? -1 : 1 );
            double angle = sign * (rng.nextDouble()/2.0 + 0.5) * Math.PI / 9.0;
            at.rotate( angle );
           break;

         case 1: // Apply a scale traqnsformation:
            // Stretch/shrink letter by +/- 50%:
            double factor = (50 + rng.nextInt(100 + 1) ) / 100.0;
            at.scale( factor, factor );
            break;

         case 2: // Apply a 25%..50% shear transformation in Y dimension only:
            at.shear( ( 5 + rng.nextInt(6) ) / 20.0, 0.0 );
            break;

         default:  // Don't transform (do nothing):
            break;
         }

         // Set a random color to draw with:
         Color [] colors = { Color.red, Color.orange.darker(), Color.blue,
            Color.green.darker(), Color.darkGray, Color.magenta, Color.black
         };
         g.setPaint( colors[ rng.nextInt( colors.length ) ] );

         // Draw the glyph:  (The letter Shape is defined with (0,0) local to
         // upper left of the glyphVector.  As we have already used a translate
         // transform (so as to apply the other transforms), if we just draw
         // the Shapes they will all stack up on each other.  The Shapes must
         // be translated back to the correct positions.  This could be done
         // later using the Shape but Java 1.4 includes the method below,
         // which allows use to easily reverse the original translation.
         // (Prior to Java 1.4 each Shape in a GlyphVector had it's own
         // (0,0) coordinate, so you would just use gv.getGlyphOutline(i).)

         Shape letterShape = gv.getGlyphOutline( i, (float) -pos.getX(),
            (float) -pos.getY() );
         letterShape = at.createTransformedShape( letterShape );
         g.fill( letterShape );
      }

      // Restore original graphic context:
      g.setTransform( originalTransform );
      g.setPaint( originalPaint );


      // Draw a box using dashed lines and default Paint:
      float [] dashList = {
         5,   // First a dash of 5 pixels
         3,   // then a 3 pixel gap
         2,   // then a 2 pixel dash
         3    // a final 3 pixel gap before repeating
      };

      BasicStroke dashes = new BasicStroke(
         2,                       // Line thickness
         BasicStroke.CAP_ROUND,   // Line end style
         BasicStroke.JOIN_ROUND,  // Line joint style
         1,                       // Mitre join limit (joint extension)
         dashList,                // array of dash lengths
         0                        // Starting point of dashes
      );

      g.setStroke( dashes );
      g.draw( new Rectangle(75, 70, 250, 95) );

      // Draw a box using a thick diagonal rainbow line:
      GradientPaint rainbow = new GradientPaint(
         0, 0, Color.yellow,     // Starting point and Color
         20, 20, Color.blue,     // Ending point and Color
         true                    // Cycle through colors repeatedly
      );

      g.setPaint ( rainbow );
      g.setStroke( new BasicStroke(10) ); // a 10 pel thick line
      g.draw( new RoundRectangle2D.Double(30, 45, 340, 145, 5, 5) );
   }
}

 


Send comments and questions to pollock@acm.org.
Valid HTML 4.01!   Valid CSS!   CAST: Bobby WorldWide Approved 508   CAST: Bobby WorldWide Approved AAA