Hi,
I have an app that is trying to render a set of strings onto a panel, but
the strings must fillthe entire screen (Therefore I must strech the fonts
etc).
I have to support the MS JVM for this, so I have made two classes, one for
Java2D, and one for AWT 1.1.
Anyway, I am trying to get the cleanest looking rendering on the Java2D side
of things, but seem to be missing something as the image looks to be missing
something still..
The jist of things are as follows:
1. Get the bounds of the panel.
2. Determine the scale from old to new size
3. Derive a new font based on the new scaling
4. Create an image which will fit the strings onto exactly using the new
font metrics to derive size
5. Scale the image to fit the dimensions of the panel
Now, This seems a bit convoluted I know, but I have to fill the screen right
up, regardless of the shape and size! (Users huh?). Simply rescaling the
font is not good enough because you can only scale in steps, the previous
step may be too small, and the next step may be too big...
Anyway, here is a bit of sample code, I wonder if there are better rendering
options I could be using?
Steve
<SNIP>
package com.spg.terminal;
import java.awt.*;
import java.awt.event.*;
import java.awt.geom.AffineTransform;
import javax.swing.JFrame;
public class TestCanvas extends Canvas{
private String[] _dataSet;
private int _maxRows;
private String _sampleString;
private Font _originalFont;
private double _scaleXFactor;
private double _scaleYFactor;
private int _scaledWidth;
private int _scaledHeight;
private int _scaledRowHeight;
private Font _scaledFont;
private Rectangle _currentBounds;
public TestCanvas() {
super();
super.addComponentListener(new ComponentListener() {
public void componentHidden(ComponentEvent e) {}
public void componentMoved(ComponentEvent e) {}
public void componentResized(ComponentEvent e) {
rescale(getGraphics(), getBounds());
}
public void componentShown(ComponentEvent e) {
rescale(getGraphics(), getBounds());
}
});
}
public static void main(String[] args) {
String[] data = new String[25];
String[] data2 = new String[25];
String temp = new String();
for(int i=0; i < 80; i++){
if( i % 7 == 0){
temp+="|";
}else{
temp += (i % 10);
}
}
for( int i=0; i < data.length; i++){
data[i] = new String(temp);
data2[i] = new String(temp);
}
JFrame frame = new JFrame("Test Terminal");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Canvas canvas2d = create2dCanvas();
frame.getContentPane().add(canvas2d);
frame.setBounds(100,100, 800,600);
frame.show();
}
private static Canvas create2dCanvas(){
TestCanvas canvas = new TestCanvas();
canvas.setBackground(Color.black);
canvas.setForeground(Color.green);
canvas.initialize(25, 80);
return canvas;
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//Public methods
public void initialize(int maxRows, int maxCols){
_originalFont = createOriginalFont();
_scaleXFactor = 1.0d;
_scaleYFactor = 1.0d;
_maxRows = maxRows;
//Initialise the Data Set to empty strings
_dataSet = new String[maxRows];
String temp = new String();
_sampleString = new String();
for(int i=0; i < maxCols; i++){
temp+= (i%10);
_sampleString+="X";
}
for(int i=0; i < _dataSet.length; i++){
_dataSet[i] = new String(temp);
}
}
public void paint(Graphics g){
Rectangle bounds = this.getBounds();
//Check that the current bounds have not changed/
//If so, do a rescale before painting
if( _currentBounds == null || !_currentBounds.equals(bounds) ){
rescale(g, bounds);
_currentBounds = bounds;
}
g.setColor(getBackground());
g.fillRect(0, 0, bounds.width, bounds.height);
Image img = getDrawingImage(_scaledWidth, _scaledHeight);
Graphics g2 = img.getGraphics();
g2.setFont(_scaledFont);
FontMetrics fm = g2.getFontMetrics();
g2.setColor(Color.black);
g2.fillRect(0, 0, _scaledWidth, _scaledHeight);
g2.setColor(getForeground());
int y = 0;
int maxDecent = fm.getDescent();
setRenderingProperties(g2);
//Draw each data line
for (int i = 0; i < _dataSet.length; i++) {
y += _scaledRowHeight;
g2.drawString(_dataSet[i], 0, y-maxDecent);
}
Image scaledImg = getScaledImage(img, bounds.width, bounds.height);
g.drawImage(scaledImg, 0, 0, null);
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
//Protected methods
protected synchronized void rescale(Graphics g, Rectangle bounds){
if( g==null){
return;
}
g.setFont(_originalFont);
FontMetrics fm = g.getFontMetrics();
int maxStringWidth = getMaxStringLength(fm);
int maxStringHeight = fm.getHeight()- fm.getDescent();
int gridHeight = maxStringHeight * _maxRows;
//Now try and work out the scaling!!!
_scaleXFactor = (double)bounds.width / (double)maxStringWidth;
_scaleYFactor = (double)bounds.height / (double)gridHeight;
//New Scaled Font
Font f = g.getFont();
if( f== null){
f = _originalFont;
}
//Scale up the font till it is >= the bounds
while(true){
AffineTransform fontTransform = new AffineTransform();
fontTransform.scale( _scaleXFactor, _scaleYFactor );
//New Scaled Font
_scaledFont = f.deriveFont(fontTransform);
fm = g.getFontMetrics(_scaledFont);
maxStringWidth = getMaxStringLength(fm);
maxStringHeight = fm.getHeight()-fm.getDescent() ;
gridHeight = maxStringHeight * _maxRows;
boolean bChanged = false;
if( maxStringWidth < (bounds.width)){
_scaleXFactor += 0.1;
bChanged =true;
}
if( gridHeight < (bounds.height)){
_scaleYFactor += 0.1;
bChanged = true;
}
System.out.println("Width=" + maxStringWidth + "("+ bounds.width
+"), Height=" + gridHeight + "("+ bounds.height +")");
if( !bChanged){
break;
}
}
fm = g.getFontMetrics(_scaledFont);
_scaledRowHeight = fm.getHeight() - fm.getDescent();
_scaledHeight = _scaledRowHeight * _maxRows;
_scaledWidth = getMaxStringLength(fm);
}
protected int getMaxStringLength(FontMetrics fm){
int len = 0;
for( int i=0; i < _dataSet.length; i++){
int val = fm.stringWidth(_dataSet[i]);
if( val > len){
len = val;
}
}
return len;
}
protected Font createOriginalFont(){
return new Font("Courier", Font.PLAIN, 12);
}
protected Image getDrawingImage(int width, int height){
Image img = this.createImage(width, height);
Graphics2D g = (Graphics2D)img.getGraphics();
setRenderingProperties(g);
return img;
}
protected Image getScaledImage(Image imgToScale, int width, int height){
return imgToScale.getScaledInstance(width, height,
Image.SCALE_DEFAULT);
}
protected void setRenderingProperties(Graphics g){
Graphics2D g2d = (Graphics2D)g;
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
}
}
</SNIP
SPG - 07 Jun 2005 11:57 GMT
> Hi,
>
[quoted text clipped - 256 lines]
>
> </SNIP
Burgers
Under
My
Pillow
Any takers?