/*****************************************************************************/ // // Copyright (c) Jim Buzbee 1996 // // jbuzbee@nyx.net // House Blend Software // // Permission to use, copy, modify, and distribute this software // for non-commercial uses is hereby granted provided // this notice is kept intact within the source file // /***************************************************************************/ import java.awt.*; import java.awt.Graphics; import java.applet.Applet; import java.awt.Image; import java.awt.Event; import java.io.*; import java.net.URL; import java.net.*; import java.util.*; /***************************************************************************/ public class TumblinText extends java.applet.Applet implements Runnable { int count = 0; Image offscreen; Graphics g1; String string; String url; String fileName; Vector textLines = new Vector(); float charSize; int xOffset; int yOffset; int xOffsetPending; int yOffsetPending; int lineWidth; int wordDelay = 100; int tumbleDelay = 10; int currentString = 0; boolean threadSuspended = false; boolean xRotationPending; boolean yRotationPending; boolean zRotationPending; boolean xRotation; boolean yRotation; boolean zRotation; Color foreground; Color background; int loopCount; int origLoopCount; HersheyFont tumbleFont; Thread myThread = null; float values[] = { 1.0f, 0.9f, 0.8f, 0.7f, 0.6f, 0.5f, 0.4f, 0.3f, 0.2f, 0.1f, 0.05f, 0.1f, 0.2f, 0.3f, 0.4f, 0.5f, 0.6f, 0.7f, 0.8f, 0.9f, 1.0f, }; /*************************************************************************/ public void start() { // if we don't already have a running thread if ( myThread == null ) { // create one myThread = new Thread( this ); // start it myThread.start(); } return; } /*************************************************************************/ public void stop() { // it's all over now... myThread.stop(); // null out the thread for garbage collection myThread = null; return; } /*************************************************************************/ public void run() { // while we have a thread while (myThread != null) { try { // pause at the upright word Thread.sleep(wordDelay); } catch ( InterruptedException e ) { System.out.println("" + e ); } // do our main animation paintit( this.getGraphics() ); } myThread = null; return; } /*************************************************************************/ public void init( ) { String param; String font; // get the font name MUST BE A HERSHEY FONT param = getParameter("Font"); font = ( param == null ) ? "romans" : param; // build our font tumbleFont = new HersheyFont( getDocumentBase(), font ); // get the URL associated with the applet param = getParameter("URL"); url = ( param == null ) ? null : param; // double buffer offscreen = this.createImage( size().width, size().height ); g1 = offscreen.getGraphics(); // get the display string file fileName = getParameter("File"); // if we did not get a file if ( fileName == null ) { // make default display textLines = new Vector(); textLines.addElement( "Tumblin` Text!" ); } else { // load up from the file LoadTextStrings( fileName ); } // Get the center position param = getParameter("X"); xOffset = ( param != null ) ? Integer.parseInt( param ) : size().width/2; // get the center position param = getParameter("Y"); yOffset= ( param != null ) ? Integer.parseInt( param ) : size().height/2; // word delay param = getParameter("WD"); wordDelay = ( param != null ) ? Integer.parseInt( param ) : 10000; // tumble delay param = getParameter("TD"); tumbleDelay = ( param != null ) ? Integer.parseInt( param ) : 1; // loop count before re-read param = getParameter("lc"); origLoopCount = ( param != null ) ? Integer.parseInt( param ) : 1; loopCount = ++origLoopCount; // x rotation flag param = getParameter("xr"); xRotation = ( param != null ) ? Boolean.valueOf( param ).booleanValue() : false; // y rotation flag param = getParameter("yr"); yRotation = ( param != null ) ? Boolean.valueOf( param ).booleanValue() : false; // z rotation flag param = getParameter("zr"); zRotation = ( param != null ) ? Boolean.valueOf( param ).booleanValue() : false; // get the size of the character param = getParameter("CS"); charSize = ( param != null ) ? Float.valueOf(param).floatValue() : 1.0f; // get the line width for the character param = getParameter("CW"); lineWidth = ( param != null ) ? Integer.parseInt( param ) : 1; // get the foreground color foreground = getColorParameter( getParameter( "fg" )); // if we did not get it if ( foreground == null ) { // default to red foreground = Color.red ; } // get the background color background = getColorParameter(getParameter( "bg")); // if we did not get it if ( background == null ) { // default to wite background = Color.white ; } // adjust based on char size for( int i = 0; i < values.length; i++ ) { values[i] *= charSize; } // initialize tumbleFont.setHeight( charSize ); tumbleFont.setLineWidth( lineWidth ); tumbleFont.setHorizontalAlignment( HersheyFont.HORIZONTAL_CENTER ); tumbleFont.setVerticalAlignment( HersheyFont.VERTICAL_HALF ); } /**************************************************************************/ protected Color getColorParameter( String name ) { int hexValue; // parse the number try { hexValue = Integer.parseInt( name, 16 ); } catch ( NumberFormatException e ) { return( null ); } // return it return( new Color( hexValue )); } /**************************************************************************/ public void paint( Graphics g ) { g.drawImage( offscreen, 0,0, this ); return; } /**************************************************************************/ public void paintit( Graphics g ) { double increment = 360.0/values.length; double angle = increment; int c = currentString; // if we don't have a file and a string and we are starting over if ( ( fileName != null ) && ( currentString == 0 ) && (--loopCount == 0 ) ) { // reload the file LoadTextStrings( fileName ); // reset the count loopCount = origLoopCount; } // setup xOffsetPending = xOffset; yOffsetPending = yOffset; xRotationPending = xRotation; yRotationPending = yRotation; zRotationPending = zRotation; // do the background g1.setColor( background ); g1.fillRect( 0,0,this.size().width, this.size().height ); // re-parse the parameters string = parseString ((String)textLines.elementAt(currentString)); // set the foreground g1.setColor( foreground ); // draw the string into the offscreen buffer tumbleFont.drawString( string , xOffset, yOffset, g1 ); // update on screen g.drawImage( offscreen, 0,0, this ); // for all of our values for( int i = 0; i < values.length; i++ ) { // set the background color g1.setColor( background ); // clear the background g1.fillRect( 0,0,this.size().width, this.size().height ); // set the foreground color g1.setColor( foreground ); // if we are doing a y rotation if ( yRotation ) { // adjust the character width tumbleFont.setWidth( values[i] ); } // if we are doing an x rotation if ( xRotation ) { // adjust the height tumbleFont.setHeight( values[i] ); } // if we are doing a z rotation if ( zRotation ) { // adjust the rotation tumbleFont.setRotation( angle ); // move on to the next angle angle+=increment; } // if this is the time to switch if ( values[i] == 0.05f * charSize ) { // move to the next string index currentString++; // wrap around currentString %= textLines.size(); // pick the string out, and reset the animation parameters string = parseString ((String)textLines.elementAt(currentString)); } // draw the string tumbleFont.drawString( string, xOffset, yOffset, g1 ); // update the on-screen image with the offscreen image g.drawImage( offscreen, 0,0,this ); // slow down the pace... try { // slow it down Thread.sleep(tumbleDelay); } catch ( InterruptedException e ) { // ooops System.out.println("" + e ); } } // the rotation parameters will only be applied from the starting pos. xOffset = xOffsetPending; yOffset = yOffsetPending; xRotation = xRotationPending; yRotation = yRotationPending; zRotation = zRotationPending; return; } /************************************************************************/ public boolean mouseDown(java.awt.Event evt, int x, int y) { // if there is a URL associated with this if ( url != null ) { URL theURL = null; try { // build a URL object associated with the url string theURL = new URL( url ); // reset the browser getAppletContext().showDocument( theURL ); } catch ( java.net.MalformedURLException e ) { System.out.println("BAD URL " + theURL); } } else // treat the click as a pause/resume command { // if we are already suspended if (threadSuspended) { // start 'er up myThread.resume(); } else { // shut 'er down myThread.suspend(); } // flip the state flag threadSuspended = ! threadSuspended; } return true; } /************************************************************************/ private String parseString( String string ) { String textString = string; String param; try { int sp = string.indexOf('{'); int ep = string.indexOf('}'); // if we have a paramter section if ( ( sp >=0 ) && ( ep >= 0 ) ) { // pick it out String paramList = string.substring( sp+1, ep-1 ); // build a tokenizer to get the values StringTokenizer st = new StringTokenizer( paramList, " ="); // get the string portion textString = string.substring( ep+1 ); // for all of the tokens for (;;) { try { // start getting tokens String token = st.nextToken(); // x rotation flag if ( token.equals("xr") ) { xRotationPending = Boolean.valueOf( st.nextToken() ).booleanValue(); } // y rotation flag else if ( token.equals("yr") ) { yRotationPending = Boolean.valueOf( st.nextToken() ).booleanValue(); } // z rotation else if ( token.equals("zr") ) { zRotationPending = Boolean.valueOf( st.nextToken() ).booleanValue(); } // x position else if ( token.equals("x") ) { xOffsetPending = Integer.parseInt( st.nextToken() ); } // y position else if ( token.equals("y") ) { yOffsetPending = Integer.parseInt( st.nextToken() ); } // url string else if ( token.equals("url") ) { url = st.nextToken(); } // command file else if ( token.equals("file") ) { fileName = st.nextToken(); } // work delay else if ( token.equals("wd") ) { wordDelay = Integer.parseInt( st.nextToken() ); } // tumble delay else if ( token.equals("td") ) { tumbleDelay = Integer.parseInt( st.nextToken() ); } // foreground color else if ( token.equals("fg") ) { foreground = getColorParameter( st.nextToken() ); if ( foreground == null ) { foreground = Color.red ; } } // background color else if ( token.equals("bg") ) { background = getColorParameter( st.nextToken() ); if ( foreground == null ) { foreground = Color.white; } } } // no more tokens catch ( NoSuchElementException e ) { // break it down break; } } } } catch( StringIndexOutOfBoundsException e ) { // ooops System.out.println( e ); } // if we have a dynamic string if ( textString.equals("") ) { // translate it return( "" + new Date() ); } else if ( textString.equals("") ) { String hostname; try { // who are we ? hostname = InetAddress.getLocalHost().toString(); } catch(UnknownHostException u) { hostname = "unknown"; // oop's, can't figure it out } return( hostname ); } else { return( textString ); } } /************************************************************************/ private void LoadTextStrings( String fileName ) { int i = 0; String line; Vector temp = new Vector( ); currentString = 0; try { InputStream textStream = new URL( fileName ).openStream(); DataInput d = new DataInputStream( textStream ); // while there is data left to read while ( (line = d.readLine()) != null ) { // add the line to our list temp.addElement( line ); } textLines = temp; } catch ( java.net.MalformedURLException e ) { System.out.println("Malformed URL exception " + e ); // if we don't have any strings yet if ( textLines == null ) { textLines = new Vector(); textLines.addElement("Bad URL"); } } catch ( java.io.IOException e ) { System.out.println(" IO exception " + e ); // if we don't have any strings yet if ( textLines == null ) { textLines = new Vector(); textLines.addElement("IO Exception"); } } } /************************************************************************/ }