Frames | No Frames |
1: /* ======================================================================== 2: * JCommon : a free general purpose class library for the Java(tm) platform 3: * ======================================================================== 4: * 5: * (C) Copyright 2000-2007, 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-2007, 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.13 2007/03/16 10:25:58 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: * 16-Mar-2007 : Fixed serialization for GradientPaint (DG); 49: * 50: */ 51: 52: package org.jfree.text; 53: 54: import java.awt.Color; 55: import java.awt.Font; 56: import java.awt.FontMetrics; 57: import java.awt.Graphics2D; 58: import java.awt.Paint; 59: import java.awt.font.LineMetrics; 60: import java.awt.geom.Rectangle2D; 61: import java.io.IOException; 62: import java.io.ObjectInputStream; 63: import java.io.ObjectOutputStream; 64: import java.io.Serializable; 65: 66: import org.jfree.io.SerialUtilities; 67: import org.jfree.ui.Size2D; 68: import org.jfree.ui.TextAnchor; 69: import org.jfree.util.Log; 70: import org.jfree.util.LogContext; 71: 72: /** 73: * A text item, with an associated font, that fits on a single line (see 74: * {@link TextLine}). Instances of the class are immutable. 75: */ 76: public class TextFragment implements Serializable { 77: 78: /** For serialization. */ 79: private static final long serialVersionUID = 4465945952903143262L; 80: 81: /** The default font. */ 82: public static final Font DEFAULT_FONT = new Font("Serif", Font.PLAIN, 12); 83: 84: /** The default text color. */ 85: public static final Paint DEFAULT_PAINT = Color.black; 86: 87: /** The text. */ 88: private String text; 89: 90: /** The font. */ 91: private Font font; 92: 93: /** The text color. */ 94: private transient Paint paint; 95: 96: /** 97: * The baseline offset (can be used to simulate subscripts and 98: * superscripts). 99: */ 100: private float baselineOffset; 101: 102: /** Access to logging facilities. */ 103: protected static final LogContext logger = Log.createContext( 104: TextFragment.class); 105: 106: /** 107: * Creates a new text fragment. 108: * 109: * @param text the text (<code>null</code> not permitted). 110: */ 111: public TextFragment(final String text) { 112: this(text, DEFAULT_FONT, DEFAULT_PAINT); 113: } 114: 115: /** 116: * Creates a new text fragment. 117: * 118: * @param text the text (<code>null</code> not permitted). 119: * @param font the font (<code>null</code> not permitted). 120: */ 121: public TextFragment(final String text, final Font font) { 122: this(text, font, DEFAULT_PAINT); 123: } 124: 125: /** 126: * Creates a new text fragment. 127: * 128: * @param text the text (<code>null</code> not permitted). 129: * @param font the font (<code>null</code> not permitted). 130: * @param paint the text color (<code>null</code> not permitted). 131: */ 132: public TextFragment(final String text, final Font font, final Paint paint) { 133: this(text, font, paint, 0.0f); 134: } 135: 136: /** 137: * Creates a new text fragment. 138: * 139: * @param text the text (<code>null</code> not permitted). 140: * @param font the font (<code>null</code> not permitted). 141: * @param paint the text color (<code>null</code> not permitted). 142: * @param baselineOffset the baseline offset. 143: */ 144: public TextFragment(final String text, final Font font, final Paint paint, 145: final float baselineOffset) { 146: if (text == null) { 147: throw new IllegalArgumentException("Null 'text' argument."); 148: } 149: if (font == null) { 150: throw new IllegalArgumentException("Null 'font' argument."); 151: } 152: if (paint == null) { 153: throw new IllegalArgumentException("Null 'paint' argument."); 154: } 155: this.text = text; 156: this.font = font; 157: this.paint = paint; 158: this.baselineOffset = baselineOffset; 159: } 160: 161: /** 162: * Returns the text. 163: * 164: * @return The text (possibly <code>null</code>). 165: */ 166: public String getText() { 167: return this.text; 168: } 169: 170: /** 171: * Returns the font. 172: * 173: * @return The font (never <code>null</code>). 174: */ 175: public Font getFont() { 176: return this.font; 177: } 178: 179: /** 180: * Returns the text paint. 181: * 182: * @return The text paint (never <code>null</code>). 183: */ 184: public Paint getPaint() { 185: return this.paint; 186: } 187: 188: /** 189: * Returns the baseline offset. 190: * 191: * @return The baseline offset. 192: */ 193: public float getBaselineOffset() { 194: return this.baselineOffset; 195: } 196: 197: /** 198: * Draws the text fragment. 199: * 200: * @param g2 the graphics device. 201: * @param anchorX the x-coordinate of the anchor point. 202: * @param anchorY the y-coordinate of the anchor point. 203: * @param anchor the location of the text that is aligned to the anchor 204: * point. 205: * @param rotateX the x-coordinate of the rotation point. 206: * @param rotateY the y-coordinate of the rotation point. 207: * @param angle the angle. 208: */ 209: public void draw(final Graphics2D g2, final float anchorX, 210: final float anchorY, final TextAnchor anchor, 211: final float rotateX, final float rotateY, 212: final double angle) { 213: 214: g2.setFont(this.font); 215: g2.setPaint(this.paint); 216: TextUtilities.drawRotatedString(this.text, g2, anchorX, anchorY 217: + this.baselineOffset, anchor, angle, rotateX, rotateY); 218: 219: } 220: 221: /** 222: * Calculates the dimensions of the text fragment. 223: * 224: * @param g2 the graphics device. 225: * 226: * @return The width and height of the text. 227: */ 228: public Size2D calculateDimensions(final Graphics2D g2) { 229: final FontMetrics fm = g2.getFontMetrics(this.font); 230: final Rectangle2D bounds = TextUtilities.getTextBounds(this.text, g2, 231: fm); 232: final Size2D result = new Size2D(bounds.getWidth(), bounds.getHeight()); 233: return result; 234: } 235: 236: /** 237: * Calculates the vertical offset between the baseline and the specified 238: * text anchor. 239: * 240: * @param g2 the graphics device. 241: * @param anchor the anchor. 242: * 243: * @return the offset. 244: */ 245: public float calculateBaselineOffset(final Graphics2D g2, 246: final TextAnchor anchor) { 247: float result = 0.0f; 248: final FontMetrics fm = g2.getFontMetrics(this.font); 249: final LineMetrics lm = fm.getLineMetrics("ABCxyz", g2); 250: if (anchor == TextAnchor.TOP_LEFT || anchor == TextAnchor.TOP_CENTER 251: || anchor == TextAnchor.TOP_RIGHT) { 252: result = lm.getAscent(); 253: } 254: else if (anchor == TextAnchor.BOTTOM_LEFT 255: || anchor == TextAnchor.BOTTOM_CENTER 256: || anchor == TextAnchor.BOTTOM_RIGHT) { 257: result = -lm.getDescent() - lm.getLeading(); 258: } 259: return result; 260: } 261: 262: /** 263: * Tests this instance for equality with an arbitrary object. 264: * 265: * @param obj the object to test against (<code>null</code> permitted). 266: * 267: * @return A boolean. 268: */ 269: public boolean equals(final Object obj) { 270: if (obj == null) { 271: return false; 272: } 273: if (obj == this) { 274: return true; 275: } 276: if (obj instanceof TextFragment) { 277: final TextFragment tf = (TextFragment) obj; 278: if (!this.text.equals(tf.text)) { 279: return false; 280: } 281: if (!this.font.equals(tf.font)) { 282: return false; 283: } 284: if (!this.paint.equals(tf.paint)) { 285: return false; 286: } 287: return true; 288: } 289: return false; 290: } 291: 292: /** 293: * Returns a hash code for this object. 294: * 295: * @return A hash code. 296: */ 297: public int hashCode() { 298: int result; 299: result = (this.text != null ? this.text.hashCode() : 0); 300: result = 29 * result + (this.font != null ? this.font.hashCode() : 0); 301: result = 29 * result + (this.paint != null ? this.paint.hashCode() : 0); 302: return result; 303: } 304: 305: /** 306: * Provides serialization support. 307: * 308: * @param stream the output stream. 309: * 310: * @throws IOException if there is an I/O error. 311: */ 312: private void writeObject(final ObjectOutputStream stream) 313: throws IOException { 314: stream.defaultWriteObject(); 315: SerialUtilities.writePaint(this.paint, stream); 316: } 317: 318: /** 319: * Provides serialization support. 320: * 321: * @param stream the input stream. 322: * 323: * @throws IOException if there is an I/O error. 324: * @throws ClassNotFoundException if there is a classpath problem. 325: */ 326: private void readObject(final ObjectInputStream stream) 327: throws IOException, ClassNotFoundException { 328: stream.defaultReadObject(); 329: this.paint = SerialUtilities.readPaint(stream); 330: } 331: 332: }