/** * Copyright (c) 2003-2009, Xith3D Project Group all rights reserved. * * Portions based on the Java3D interface, Copyright by Sun Microsystems. * Many thanks to the developers of Java3D and Sun Microsystems for their * innovation and design. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the 'Xith3D Project Group' nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) A * RISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE */ package org.xith3d.ui.text2d; import java.awt.Font; import java.util.HashMap; import java.util.Map; import java.util.StringTokenizer; import org.openmali.types.twodee.Sized2iRO; import org.openmali.vecmath2.Colorf; import org.openmali.vecmath2.TexCoord2f; import org.openmali.vecmath2.Tuple2f; import org.xith3d.scenegraph.ASCIITexture; import org.xith3d.scenegraph.Appearance; import org.xith3d.scenegraph.ColoringAttributes; import org.xith3d.scenegraph.Shape3D; import org.xith3d.scenegraph.TransparencyAttributes; import org.xith3d.scenegraph.TriangleStripArray; import org.xith3d.scenegraph.Geometry.Optimization; /** * Represents a character in 3D space. * This class is part of the DynamicText toolkit for Xith3d. * * @see <a href="DText2D.html">org.xith3d.text.Text2D</a> * * @author Florian Hofmann (aka Goliat) * @author Marvin Froehlich (aka Qudus) * * @version 2.0 */ public class Character2D extends Shape3D { private static float fontStretchFactor = 1.0f; // this HashMap contains all preloaded Characters // the key contains all character attributes ( char, font, resolution, flags ) // like this: "a-Arial-64-0" // ( char, fontname, resolution, fontflags ) private static final Map< String, Character2D > characterCache = new HashMap< String, Character2D >( 10, 10 ); // the charId of this Character //private String charId; private Tuple2f size; private char character; public static void setFontStretchFactor( float factor ) { fontStretchFactor = factor; } public static float getFontStretchFactor() { return ( fontStretchFactor ); } /** * @return the char this Character2D represents */ public char getChar() { return ( character ); } /** * For debuging purposes: </br> * Returns the number of currently loaded chars * * @return number of chars */ public static int numberOfLoadedChars() { return ( characterCache.size() ); } /** * Sets the color of this char. * * @param r new Color * @param g new Color * @param b new Color */ public void setColor( float r, float g, float b ) { this.getAppearance( true ).getColoringAttributes( true ).setColor( r, g, b ); } /** * Sets the color of this char. * * @param color new Color */ public void setColor( Colorf color ) { setColor( color.getRed(), color.getGreen(), color.getBlue() ); } /** * @return the current color of this Character */ public Colorf getColor() { return ( this.getAppearance( true ).getColoringAttributes( true ).getColor() ); } public Tuple2f getSize() { return ( size ); } public float getWidth() { return ( size.getX() ); } public float getHeight() { return ( size.getY() ); } /** * {@inheritDoc} */ @Override public String toString() { return ( super.toString() + " [" + this.getChar() + "]" ); } private Character2D( char character, Tuple2f size ) { super(); this.character = character; this.size = size; } private static Colorf tmpColor = new Colorf(); /** * Creates a new Character with all attributes. * * @param character new character * @param r the red value of the color * @param g the green value of the color * @param b the blue value of the color * @param font the font to use * @return returns a Node (should be casted to Character) */ public static Character2D loadCharacter( char character, float r, float g, float b, Font font ) { tmpColor.set( r, g, b ); // --- create the char id final String charId = String.valueOf( character ) + "--" + font.hashCode() + "--" + tmpColor.hashCode(); // --- lookup the character by id string if ( characterCache.containsKey( charId ) ) { // create a copy of this character using the cached content final Character2D original = characterCache.get( charId ); final Character2D copy = new Character2D( character, original.getSize() ); copy.setGeometry( original.getGeometry() ); copy.setAppearance( original.getAppearance() ); /* Appearance app = original.getAppearance().cloneNodeComponent( true ); app.setColoringAttributes( new ColoringAttributes( color, ColoringAttributes.FASTEST ) ); copy.setAppearance( app ); */ // return the copy return ( copy ); // if we have found the character -> return it //return characterCache.get( charId ).sharedCopy(); } // else: load the character //System.out.println( "Creating new Character2D " + character + "..." ); final ASCIITexture texture = Font2D.getFontTexture( font ); final Sized2iRO charSize = texture.getCharSize( character ); if ( charSize == null ) return ( null ); // --- create the geometry TriangleStripArray geometry = new TriangleStripArray( 4, null ); geometry.setOptimization( Optimization.USE_VBOS ); // create vertices float[] vertices = new float[] { 0.0f, -(float)charSize.getHeight() * getFontStretchFactor(), 0f, (float)charSize.getWidth() * getFontStretchFactor(), -(float)charSize.getHeight() * getFontStretchFactor(), 0f, 0.0f, 0.0f, 0.0f, (float)charSize.getWidth() * getFontStretchFactor(), 0.0f, 0.0f }; // add vertices to geometry geometry.setCoordinates( 0, vertices ); TexCoord2f[] tc = texture.getTextureCoordinates( character ); float[] texCoords = new float[] { tc[ 0 ].getS(), tc[ 0 ].getT(), tc[ 1 ].getS(), tc[ 0 ].getT(), tc[ 0 ].getS(), tc[ 1 ].getT(), tc[ 1 ].getS(), tc[ 1 ].getT() }; // add texture coords to geometry geometry.setTextureCoordinates( 0, 0, 2, texCoords ); // --- create appearance Appearance app = new Appearance(); // set transparency app.setTransparencyAttributes( new TransparencyAttributes( TransparencyAttributes.BLENDED, 0.0f ) ); // set color ColoringAttributes ca = new ColoringAttributes( r, g, b, ColoringAttributes.NICEST ); app.setColoringAttributes( ca ); // add texture app.setTexture( texture ); // --- create Character Character2D newCharacter = new Character2D( character, new Tuple2f( charSize.getWidth() * getFontStretchFactor(), charSize.getHeight() * getFontStretchFactor() ) ); // set geometry newCharacter.setGeometry( geometry ); // set appearance newCharacter.setAppearance( app ); // set charId //newCharacter.charId = charId; // --- add character to cache characterCache.put( charId, newCharacter ); // --- return character return ( newCharacter ); } /** * Creates a new Character with all attributes. * * @param character new character * @param color new Color * @param font the font to use * @return returns a Node (should be casted to Character) */ public static Character2D loadCharacter( char character, Colorf color, Font font ) { return ( loadCharacter( character, color.getRed(), color.getGreen(), color.getBlue(), font ) ); } /** * Creates a new Character with all attributes. * * @param character new character * @param r new Color * @param g new Color * @param b new Color * @param fontName the font to use * @param resolution resolution to use * @param fontFlags fontflags to use * @return returns a Node (should be casted to Character) */ public static Character2D loadCharacter( char character, float r, float g, float b, String fontName, int resolution, int fontFlags ) { return ( loadCharacter( character, r, g, b, new Font( fontName, fontFlags, resolution ) ) ); } public static Character2D loadCharacter( char character, Colorf color, String fontName, int resolution, int fontFlags ) { return ( loadCharacter( character, color.getRed(), color.getGreen(), color.getBlue(), fontName, fontFlags, resolution ) ); } /** * Creates a new Character by charId. * * @param character new character * @param r new Color * @param g new Color * @param b new Color * @param charId new charId * @return returns a Node (should be casted to Character) */ protected static Character2D loadCharacter( char character, float r, float g, float b, String charId ) { StringTokenizer charIdAttributes = new StringTokenizer( charId, "-" ); // as the charid contains the parameters we can use the following line to create the new character return ( loadCharacter( character, // char r, g, b, // color charIdAttributes.nextToken(), // font Integer.parseInt( charIdAttributes.nextToken() ), // resolution Integer.parseInt( charIdAttributes.nextToken() ) // fontflags ) ); } /** * Creates a new Character by charId. * * @param character new character * @param color new Color * @param charId new charId * @return returns a Node (should be casted to Character) */ protected static Character2D loadCharacter( char character, Colorf color, String charId ) { return ( loadCharacter( character, color.getRed(), color.getGreen(), color.getBlue(), charId ) ); } }