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