/*********************************************************************************************** * Copyright 2002 (C) Nathaniel G. Auvil. All Rights Reserved. * * Redistribution and use of this software and associated documentation ("Software"), with or * without modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain copyright statements and notices. * Redistributions must also contain a copy of this document. * * 2. 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. * * 3. The name "jCharts" or "Nathaniel G. Auvil" must not be used to endorse or promote * products derived from this Software without prior written permission of Nathaniel G. * Auvil. For written permission, please contact nathaniel_auvil@users.sourceforge.net * * 4. Products derived from this Software may not be called "jCharts" nor may "jCharts" appear * in their names without prior written permission of Nathaniel G. Auvil. jCharts is a * registered trademark of Nathaniel G. Auvil. * * 5. Due credit should be given to the jCharts Project (http://jcharts.sourceforge.net/). * * THIS SOFTWARE IS PROVIDED BY Nathaniel G. Auvil AND CONTRIBUTORS ``AS IS'' AND ANY * EXPRESSED 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 * jCharts OR ITS 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) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE ************************************************************************************************/ package org.krysalis.jcharts.chartText; import org.krysalis.jcharts.test.HTMLGenerator; import org.krysalis.jcharts.test.HTMLTestable; import com.google.code.appengine.awt.*; import com.google.code.appengine.awt.font.FontRenderContext; import com.google.code.appengine.awt.font.TextLayout; import com.google.code.appengine.awt.geom.Rectangle2D; import java.io.Serializable; import java.lang.reflect.Field; import java.util.Hashtable; /************************************************************************************* * * @author John Thomsen, Nathaniel Auvil * @version $Id: TextTag.java,v 1.2 2004/05/31 16:27:21 nathaniel_auvil Exp $ ************************************************************************************/ public class TextTag implements HTMLTestable, Serializable { //---Strangely, we don't need to store the text itself. (yet) private float xPosition = 0; private float yPosition = 0; private TextLayout textLayout = null; private Hashtable attributes = null; private boolean isHidden = false; //---derived values private float width = 0; private float height = 0; private float fontAscent = 0; private float fontDescent = 0; private boolean isDerived = false; private Font derivedFont = null; private String text; //for toString(); private Font font; //for toString(); /********************************************************************************************* * Default constructor - for untransformed fonts. * **********************************************************************************************/ public TextTag( String text, Font baseFont, FontRenderContext fontRenderContext ) { this( text, baseFont, null, fontRenderContext ); } /********************************************************************************************* * Constructor when using transformed (derived) fonts * * The need for this arises because the java metrics classes return either 0 or very strange * values for the width and height of a string (TextLayout, LineMetrics, etc..) when * the font is derived * * @param text * @param baseFont is the original (untransformed) font. * @param derivedFont is the transformed font * @param fontRenderContext **********************************************************************************************/ public TextTag( String text, Font baseFont, Font derivedFont, FontRenderContext fontRenderContext ) { this.textLayout = new TextLayout( text, baseFont, fontRenderContext ); this.isDerived = (derivedFont != null); this.derivedFont = derivedFont; //---Dimensions this.width = this.textLayout.getAdvance(); this.height = this.textLayout.getAscent() + this.textLayout.getDescent(); //---need this to offset font rendering, as rendering is at the baseline not bottom or top, this.fontAscent = this.textLayout.getAscent(); this.fontDescent = this.textLayout.getDescent(); this.font = (this.isDerived) ? derivedFont : baseFont; this.text = text; // System.out.println(">"+text+" Bounds:"+textLayout.getBounds() ); // System.out.println(" >Ascent "+textLayout.getAscent()+" Descent:"+textLayout.getDescent() ); // System.out.println(" >isVertical "+textLayout.isVertical()); // // LineMetrics lm = font.getLineMetrics(text, fontRenderContext); // System.out.println(" Metrics:" + lm.getHeight() + " " + lm.getAscent() + lm.getDescent()); } /******************************************************************************************** * ********************************************************************************************/ public float getWidth() { return this.width; } /******************************************************************************************** * ********************************************************************************************/ public float getHeight() { return this.height; } /******************************************************************************************** * ********************************************************************************************/ public float getFontAscent() { return this.fontAscent; } /******************************************************************************************** * ********************************************************************************************/ public float getFontDescent() { return this.fontDescent; } /******************************************************************************************** * ********************************************************************************************/ public void setPosition( float x, float y ) { this.xPosition = x; this.yPosition = y; //System.out.println("TEXT:==>"+text+"< at "+x+","+y); } /******************************************************************************************** * ********************************************************************************************/ public void setXPosition( float x ) { this.xPosition = x; } /******************************************************************************************** * ********************************************************************************************/ public void setYPosition( float y ) { this.yPosition = y; } /******************************************************************************************** * ********************************************************************************************/ public float getXPosition() { return this.xPosition; } /******************************************************************************************** * ********************************************************************************************/ public float getYPosition() { return this.yPosition; } /******************************************************************************************** * ********************************************************************************************/ public float getRightSide() { return this.xPosition + this.width; } /******************************************************************************************** * ********************************************************************************************/ public float getBottomSide() { return this.yPosition + this.height; } /******************************************************************************************** * ********************************************************************************************/ public Rectangle2D.Float getRectangle() { return new Rectangle2D.Float( this.xPosition, this.yPosition, this.width, this.height ); } /******************************************************************************************** * ********************************************************************************************/ public void setHidden( boolean b ) { this.isHidden = b; } /******************************************************************************************** * ********************************************************************************************/ public boolean getHidden() { return this.isHidden; } public String getText() { return text; } /******************************************************************************************** * ********************************************************************************************/ public void addAttribute( String name, Object o ) { if( attributes == null ) { attributes = new Hashtable(); } attributes.put( name, o ); } /******************************************************************************************** * ********************************************************************************************/ public Object getAttribute( String name ) { if( attributes == null ) { return null; } return attributes.get( name ); } /********************************************************************************************** * Renders the text, at the position - renders from the top (instead of baseline) * * @param g2d * @param fontColor **********************************************************************************************/ public void render( Graphics2D g2d, Paint fontColor ) { if( fontColor != null ) { g2d.setPaint( fontColor ); } if( this.isHidden == false ) { if( isDerived ) { g2d.setFont( this.derivedFont ); g2d.drawString( this.text, this.xPosition, this.yPosition ); } else { textLayout.draw( g2d, this.xPosition, this.yPosition ); } //---Debug comparison code. //g2d.setFont( this.font ); //g2d.drawString(this.text, this.xPosition, this.yPosition); /* Interesting... System.out.println("Ascent:"+this.fontAscent); System.out.println("Descent:"+this.fontDescent); System.out.println("Height:"+this.heightNeeded); System.out.println("Width:"+this.widthNeeded); */ } } /********************************************************************************************** * Renders the text, at the position - renders from the top (instead of baseline) * * @param g2d **********************************************************************************************/ public void render( Graphics2D g2d, float x, float y ) { textLayout.draw( g2d, x, y ); /* if( fontColor != null ) { g2d.setPaint( fontColor ); } if( this.isHidden == false ) { if( isDerived ) { g2d.drawString( this.text, x, y ); } else { textLayout.draw( g2d, x, y ); } } */ } /********************************************************************************************* * Enables the testing routines to display the contents of this Object. * * @param htmlGenerator **********************************************************************************************/ public void toHTML( HTMLGenerator htmlGenerator ) { htmlGenerator.propertiesTableStart( this.getClass().getName() ); Field[] fields = this.getClass().getDeclaredFields(); for( int i = 0; i < fields.length; i++ ) { try { htmlGenerator.addField( fields[ i ].getName(), fields[ i ].get( this ) ); } catch( IllegalAccessException illegalAccessException ) { illegalAccessException.printStackTrace(); } } htmlGenerator.propertiesTableEnd(); } /******************************************************************************************** * * @return String ********************************************************************************************/ public String toString() { String str = "TextTag: '" + this.text + "',x=" + this.xPosition + ",y=" + this.yPosition; str += "width=" + this.width + ",height=" + this.height; str += ",font=" + this.font.getName() + "," + this.font.getSize(); if( attributes != null && attributes.size() > 0 ) { java.util.Enumeration enumeration = attributes.keys(); str += "\nAttributes:"; while( enumeration.hasMoreElements() ) { Object ob = enumeration.nextElement(); str += " [" + ob.toString() + "]=[" + attributes.get( ob ).toString() + "]\n"; } } return str; } }