package graph; import java.awt.*; import java.util.*; import java.lang.*; import java.awt.image.*; /* ************************************************************************** ** ** Class RTextLine ** ************************************************************************** ** Copyright (C) 1996 Leigh Brookshaw ** ** This program is free software; you can redistribute it and/or modify ** it under the terms of the GNU General Public License as published by ** the Free Software Foundation; either version 2 of the License, or ** (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ** GNU General Public License for more details. ** ** You should have received a copy of the GNU General Public License ** along with this program; if not, write to the Free Software ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ************************************************************************** ** ** This class is an extension of TextLine that allows text to be rotated. ** Currently only multiples of 90 degrees is allowed but the Image filter ** could easily be extended to allow arbitrary rotation. ** *************************************************************************/ /** * * This class is an extension of the TextLine Class * that allows text to be rotated. To rotate the text the Component.createImage * method is used. This means that this class needs to know * the component that will receive the text. If the component is not * known the text cannot be rotated and the class will fall back to the * TextLine.draw method.

* * The text is rotated by running the image through an ImageFilter. This filter * can easily be modified to rotate text through an arbitrary angle but * unless the text is large the integer mapping will blur the text. * Also positioning of arbitrarily rotated text becomes problematic. * * @version $Revision: 1.5 $, $Date: 1996/10/23 03:13:45 $ * @author Leigh Brookshaw */ public class RTextLine extends TextLine { /* ************* ** ** Constants ** ************/ /* ********************** ** ** Protected Variables ** *********************/ /** * Rotation Angle of text in degrees */ protected int angle = 0; private double cos = 1.0; private double sin = 0.0; private Component component = null; /* ********************** ** ** Constructors ** *********************/ /** * Instantiate the class */ public RTextLine() { } /** * Instantiate the class. * @param s String to parse. */ public RTextLine(String s) { super(s); } /** * Instantiate the class. * @param c the Component the text will be drawn into. */ public RTextLine(Component c) { setDrawingComponent(c); } /** * Instantiate the class * @param s String to parse. * @param f Font to use. */ public RTextLine(String s, Font f) { super(s,f); } /** * Instantiate the class * @param s String to parse. * @param f Font to use. * @param c Color to use * @param j Justification */ public RTextLine(String s, Font f, Color c, int j) { super(s,f,c,j); } /** * Instantiate the class * @param s String to parse. * @param c Color to use */ public RTextLine(String s, Color c) { super(s,c); } /** * Instantiate the class * @param f Font to use. * @param c Color to use * @param j Justification * @param a Rotation angle in degrees */ public RTextLine(Font f, Color c, int j, int a) { super(f,c,j); setRotation(a); } /** * Instantiate the class * @param f Font to use. * @param c Color to use * @param j Justification */ public RTextLine(Font f, Color c, int j) { super(f,c,j); } /* ***************** ** ** Public Methods ** *****************/ /** * Copy the state of the parsed Textline into the existing * object. * @param t The TextLine to get the state information from. */ public void copyState(RTextLine t) { if(t==null) return; font = t.getFont(); color = t.getColor(); justification = t.getJustification(); setRotation(t.getRotation(),t.getComponent() ); if(font == null) return; fontname = font.getName(); fontstyle = font.getStyle(); fontsize = font.getSize(); parse = true; } /** * Set the text rotation angle. Only multiples of 90 degrees * are accepted * @param angle The angle to rotate the text */ public void setRotation(int angle) { this.angle = ((angle%360)/90)*90; cos = Math.cos(angle*Math.PI/180.0); sin = Math.sin(angle*Math.PI/180.0); } /** * Set the Component the text will be drawn into. This is required to rotate * the text. if it is not set the text will not be rotated. * @param c The drawing component */ public void setDrawingComponent( Component c ) { component = c; } /** * Set the Rotation and the Component that will be drawn into * @param angle The angle to rotate the text * @param c The drawing component */ public void setRotation(int angle, Component c) { setRotation(angle); setDrawingComponent(c); } /** * @return the Rotation angle in degrees. */ public int getRotation() { return angle; } /** * @return the Component that will receive the text. */ public Component getComponent() { return component; } /** * The width of the text after it has been rotated. * @param g Graphics context. * @return the width of the parsed text after it has been rotated. */ public int getRWidth(Graphics g) { parseText(g); return (int)(Math.abs(cos*width+sin*height) + 0.5); } /** * The height of the text after it has been rotated. * @param g Graphics context. * @return the height of the parsed text after it has been rotated. */ public int getRHeight(Graphics g) { parseText(g); return (int)(Math.abs(-sin*width+cos*height) + 0.5); } /** * Return the left edge of the rotated text. * This is dependent on the justification of the text. * @param g Graphics context. * @return the Left edge of the rotated text */ public int getLeftEdge(Graphics g) { return getLeftEdge(g,justification); } /** * Return the right edge of the rotated text. * This is dependent on the justification of the text. * @param g Graphics context. * @return the Right edge of the rotated text */ public int getRightEdge(Graphics g) { return getRightEdge(g,justification); } /** * Return the top edge of the rotated text. * This is dependent on the justification of the text. * @param g Graphics context. * @return the Top edge of the rotated text */ public int getTopEdge(Graphics g) { return getTopEdge(g,justification); } /** * Return the bottom edge of the rotated text. * This is dependent on the justification of the text. * @param g Graphics context. * @return the Bottom edge of the rotated text */ public int getBottomEdge(Graphics g) { return getBottomEdge(g,justification); } /** * Return the left edge of the rotated text. * @param g Graphics context. * @param j Text justification * @return the Left edge of the rotated text */ public int getLeftEdge(Graphics g, int j) { parseText(g); switch (angle) { case 90: case -270: return -ascent; case 180: case -180: if(j == CENTER ) return -width/2; else if(j == RIGHT ) return 0; else return -width; case 270: case -90: return -descent-leading; default: if(j == CENTER ) return -width/2; else if(j == RIGHT ) return -width; else return 0; } } /** * Return the right edge of the rotated text. * @param g Graphics context. * @param j Text justification * @return the Right edge of the rotated text */ public int getRightEdge(Graphics g, int j) { parseText(g); switch (angle) { case 90: case -270: return descent+leading; case 180: case -180: if(j == CENTER ) return width/2; else if(j == RIGHT ) return width; else return 0; case 270: case -90: return ascent; default: if(j == CENTER ) return width/2; else if(j == RIGHT ) return 0; else return width; } } /** * Return the top edge of the rotated text. * @param g Graphics context. * @param j Text justification * @return the Top edge of the rotated text */ public int getTopEdge(Graphics g, int j) { parseText(g); switch (angle) { case 90: case -270: if(j == CENTER ) return width/2; else if(j == RIGHT ) return 0; else return width; case 180: case -180: return descent+leading; case 270: case -90: if(j == CENTER ) return width/2; else if(j == RIGHT ) return width; else return 0; default: return ascent; } } /** * Return the bottom edge of the rotated text. * @param g Graphics context. * @param j Text justification * @return the Bottom edge of the rotated text */ public int getBottomEdge(Graphics g, int j) { parseText(g); switch (angle) { case 90: case -270: if(j == CENTER ) return -width/2; else if(j == RIGHT ) return -width; else return 0; case 180: case -180: return -ascent; case 270: case -90: if(j == CENTER ) return -width/2; else if(j == RIGHT ) return 0; else return -width; default: return -descent-leading; } } /** * Parse the text then draw it. * @param g Graphics context * @param x pixel position of the text * @param y pixel position of the text */ public void draw(Graphics g, int x, int y) { if( g == null ) return; if(component == null ) angle = 0; if(angle == 0 ) super.draw(g,x,y); else draw(component,g,x,y); } /** * Parse the text then draw it. * @param g Graphics context * @param x pixel position of the text * @param y pixel position of the text * @param j justification of the text */ public void draw(Graphics g, int x, int y, int j) { justification = j; if( g == null ) return; if(component == null ) angle = 0; if(angle == 0 ) super.draw(g,x,y); else draw(component,g,x,y); } /** * Parse the text, rotate it then draw it to the screen. * @param g Graphics context * @param x pixel position of the text * @param y pixel position of the text */ public synchronized void draw(Component comp, Graphics g, int x, int y) { TextState ts; int xoffset = 0; int yoffset = 0; Image offsI = null; Graphics offsG = null; Image rotatedImage = null; int maxHeight = 0; if(text == null || comp == null) return; parseText(g); maxHeight = maxAscent + maxDescent; /* ** Calculate the offset of the rotated image so that it ** will be positioned correctly. Remeber the image is calculated ** on the Maximum Ascent and descent so that no character ** is truncated */ switch (angle) { case 90: case -270: xoffset = -maxAscent; if(justification == CENTER ) yoffset = - width/2; else if(justification == RIGHT ) yoffset = 0; else yoffset = - width; break; case 180: case -180: yoffset = -maxDescent; if(justification == CENTER ) xoffset = - width/2; else if(justification == RIGHT ) xoffset = 0; else xoffset = - width; break; case 270: case -90: xoffset = -maxDescent; if(justification == CENTER ) yoffset = - width/2; else if(justification == RIGHT ) yoffset = - width; else yoffset = 0; break; default: xoffset = 0; yoffset = 0; break; } /* ** Create the offscreen image that the text will be written into */ offsI = comp.createImage(width,maxHeight); offsG = offsI.getGraphics(); /* ** Color the image with the background color */ if(background != null) { offsG.setColor(background); } else { offsG.setColor(comp.getBackground()); } offsG.fillRect(0,0,width,maxHeight); /* ** Set the image font and color */ offsG.setFont(g.getFont()); offsG.setColor(g.getColor()); if(font != null) offsG.setFont(font); if(color != null) offsG.setColor(color); /* ** Write to the offscreen image */ for(int i=0; i