Frames | No Frames |
1: /* ======================================================================== 2: * JCommon : a free general purpose class library for the Java(tm) platform 3: * ======================================================================== 4: * 5: * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors. 6: * 7: * Project Info: http://www.jfree.org/jcommon/index.html 8: * 9: * This library is free software; you can redistribute it and/or modify it 10: * under the terms of the GNU Lesser General Public License as published by 11: * the Free Software Foundation; either version 2.1 of the License, or 12: * (at your option) any later version. 13: * 14: * This library is distributed in the hope that it will be useful, but 15: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 16: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 17: * License for more details. 18: * 19: * You should have received a copy of the GNU Lesser General Public 20: * License along with this library; if not, write to the Free Software 21: * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, 22: * USA. 23: * 24: * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 25: * in the United States and other countries.] 26: * 27: * ----------------- 28: * TextFragment.java 29: * ----------------- 30: * (C) Copyright 2003-2005, by Object Refinery Limited and Contributors. 31: * 32: * Original Author: David Gilbert (for Object Refinery Limited); 33: * Contributor(s): -; 34: * 35: * $Id: TextFragment.java,v 1.12 2005/10/18 13:17:16 mungady Exp $ 36: * 37: * Changes 38: * ------- 39: * 07-Nov-2003 : Version 1 (DG); 40: * 25-Nov-2003 : Fixed bug in the dimension calculation (DG); 41: * 22-Dec-2003 : Added workaround for Java bug 4245442 (DG); 42: * 29-Jan-2004 : Added paint attribute (DG); 43: * 22-Mar-2004 : Added equals() method and implemented Serializable (DG); 44: * 01-Apr-2004 : Changed java.awt.geom.Dimension2D to org.jfree.ui.Size2D 45: * because of JDK bug 4976448 which persists on JDK 1.3.1 (DG); 46: * 30-Sep-2004 : Moved drawRotatedString() from RefineryUtilities 47: * --> TextUtilities (DG); 48: * 49: */ 50: 51: package org.jfree.text; 52: 53: import java.awt.Color; 54: import java.awt.Font; 55: import java.awt.FontMetrics; 56: import java.awt.Graphics2D; 57: import java.awt.Paint; 58: import java.awt.font.LineMetrics; 59: import java.awt.geom.Rectangle2D; 60: import java.io.IOException; 61: import java.io.ObjectInputStream; 62: import java.io.ObjectOutputStream; 63: import java.io.Serializable; 64: 65: import org.jfree.io.SerialUtilities; 66: import org.jfree.ui.Size2D; 67: import org.jfree.ui.TextAnchor; 68: import org.jfree.util.Log; 69: import org.jfree.util.LogContext; 70: 71: /** 72: * A text item, with an associated font, that fits on a single line (see 73: * {@link TextLine}). Instances of the class are immutable. 74: * 75: * @author David Gilbert 76: */ 77: public class TextFragment implements Serializable { 78: 79: /** For serialization. */ 80: private static final long serialVersionUID = 4465945952903143262L; 81: 82: /** The default font. */ 83: public static final Font DEFAULT_FONT = new Font("Serif", Font.PLAIN, 12); 84: 85: /** The default text color. */ 86: public static final Paint DEFAULT_PAINT = Color.black; 87: 88: /** The text. */ 89: private String text; 90: 91: /** The font. */ 92: private Font font; 93: 94: /** The text color. */ 95: private Paint paint; 96: 97: /** 98: * The baseline offset (can be used to simulate subscripts and 99: * superscripts). 100: */ 101: private float baselineOffset; 102: 103: /** Access to logging facilities. */ 104: protected static final LogContext logger 105: = Log.createContext(TextFragment.class); 106: 107: /** 108: * Creates a new text fragment. 109: * 110: * @param text the text (<code>null</code> not permitted). 111: */ 112: public TextFragment(final String text) { 113: this(text, DEFAULT_FONT, DEFAULT_PAINT); 114: } 115: 116: /** 117: * Creates a new text fragment. 118: * 119: * @param text the text (<code>null</code> not permitted). 120: * @param font the font (<code>null</code> not permitted). 121: */ 122: public TextFragment(final String text, final Font font) { 123: this(text, font, DEFAULT_PAINT); 124: } 125: 126: /** 127: * Creates a new text fragment. 128: * 129: * @param text the text (<code>null</code> not permitted). 130: * @param font the font (<code>null</code> not permitted). 131: * @param paint the text color (<code>null</code> not permitted). 132: */ 133: public TextFragment(final String text, final Font font, final Paint paint) { 134: this(text, font, paint, 0.0f); 135: } 136: 137: /** 138: * Creates a new text fragment. 139: * 140: * @param text the text (<code>null</code> not permitted). 141: * @param font the font (<code>null</code> not permitted). 142: * @param paint the text color (<code>null</code> not permitted). 143: * @param baselineOffset the baseline offset. 144: */ 145: public TextFragment(final String text, final Font font, final Paint paint, 146: final float baselineOffset) { 147: if (text == null) { 148: throw new IllegalArgumentException("Null 'text' argument."); 149: } 150: if (font == null) { 151: throw new IllegalArgumentException("Null 'font' argument."); 152: } 153: if (paint == null) { 154: throw new IllegalArgumentException("Null 'paint' argument."); 155: } 156: this.text = text; 157: this.font = font; 158: this.paint = paint; 159: this.baselineOffset = baselineOffset; 160: } 161: 162: /** 163: * Returns the text. 164: * 165: * @return The text (possibly <code>null</code>). 166: */ 167: public String getText() { 168: return this.text; 169: } 170: 171: /** 172: * Returns the font. 173: * 174: * @return The font (never <code>null</code>). 175: */ 176: public Font getFont() { 177: return this.font; 178: } 179: 180: /** 181: * Returns the text paint. 182: * 183: * @return The text paint (never <code>null</code>). 184: */ 185: public Paint getPaint() { 186: return this.paint; 187: } 188: 189: public float getBaselineOffset() { 190: return this.baselineOffset; 191: } 192: 193: /** 194: * Draws the text fragment. 195: * 196: * @param g2 the graphics device. 197: * @param anchorX the x-coordinate of the anchor point. 198: * @param anchorY the y-coordinate of the anchor point. 199: * @param anchor the location of the text that is aligned to the anchor 200: * point. 201: * @param rotateX the x-coordinate of the rotation point. 202: * @param rotateY the y-coordinate of the rotation point. 203: * @param angle the angle. 204: */ 205: public void draw(final Graphics2D g2, final float anchorX, 206: final float anchorY, final TextAnchor anchor, 207: final float rotateX, final float rotateY, 208: final double angle) { 209: 210: g2.setFont(this.font); 211: g2.setPaint(this.paint); 212: TextUtilities.drawRotatedString( 213: this.text, g2, anchorX, anchorY + this.baselineOffset, anchor, 214: angle, rotateX, rotateY 215: ); 216: 217: } 218: 219: /** 220: * Calculates the dimensions of the text fragment. 221: * 222: * @param g2 the graphics device. 223: * 224: * @return The width and height of the text. 225: */ 226: public Size2D calculateDimensions(final Graphics2D g2) { 227: final FontMetrics fm = g2.getFontMetrics(this.font); 228: final Rectangle2D bounds = TextUtilities.getTextBounds(this.text, g2, 229: fm); 230: final Size2D result = new Size2D(bounds.getWidth(), bounds.getHeight()); 231: return result; 232: } 233: 234: /** 235: * Calculates the vertical offset between the baseline and the specified 236: * text anchor. 237: * 238: * @param g2 the graphics device. 239: * @param anchor the anchor. 240: * 241: * @return the offset. 242: */ 243: public float calculateBaselineOffset(final Graphics2D g2, 244: final TextAnchor anchor) { 245: float result = 0.0f; 246: final FontMetrics fm = g2.getFontMetrics(this.font); 247: final LineMetrics lm = fm.getLineMetrics("ABCxyz", g2); 248: if (anchor == TextAnchor.TOP_LEFT || anchor == TextAnchor.TOP_CENTER 249: || anchor == TextAnchor.TOP_RIGHT) { 250: result = lm.getAscent(); 251: } 252: else if (anchor == TextAnchor.BOTTOM_LEFT 253: || anchor == TextAnchor.BOTTOM_CENTER 254: || anchor == TextAnchor.BOTTOM_RIGHT) { 255: result = -lm.getDescent() - lm.getLeading(); 256: } 257: return result; 258: } 259: 260: /** 261: * Tests this instance for equality with an arbitrary object. 262: * 263: * @param obj the object to test against (<code>null</code> permitted). 264: * 265: * @return A boolean. 266: */ 267: public boolean equals(final Object obj) { 268: if (obj == null) { 269: return false; 270: } 271: if (obj == this) { 272: return true; 273: } 274: if (obj instanceof TextFragment) { 275: final TextFragment tf = (TextFragment) obj; 276: if (!this.text.equals(tf.text)) { 277: return false; 278: } 279: if (!this.font.equals(tf.font)) { 280: return false; 281: } 282: if (!this.paint.equals(tf.paint)) { 283: return false; 284: } 285: return true; 286: } 287: return false; 288: } 289: 290: /** 291: * Returns a hash code for this object. 292: * 293: * @return A hash code. 294: */ 295: public int hashCode() { 296: int result; 297: result = (this.text != null ? this.text.hashCode() : 0); 298: result = 29 * result + (this.font != null ? this.font.hashCode() : 0); 299: result = 29 * result + (this.paint != null ? this.paint.hashCode() : 0); 300: return result; 301: } 302: 303: /** 304: * Provides serialization support. 305: * 306: * @param stream the output stream. 307: * 308: * @throws IOException if there is an I/O error. 309: */ 310: private void writeObject(final ObjectOutputStream stream) 311: throws IOException { 312: stream.defaultWriteObject(); 313: SerialUtilities.writePaint(this.paint, stream); 314: } 315: 316: /** 317: * Provides serialization support. 318: * 319: * @param stream the input stream. 320: * 321: * @throws IOException if there is an I/O error. 322: * @throws ClassNotFoundException if there is a classpath problem. 323: */ 324: private void readObject(final ObjectInputStream stream) 325: throws IOException, ClassNotFoundException { 326: stream.defaultReadObject(); 327: this.paint = SerialUtilities.readPaint(stream); 328: } 329: 330: }