Terminal sim - Need to rescale fonts using 1.1 JVM



All,

I posted a similar question a while back, with some useful answers, but...

I have a requirement to create a terminal emulation style applet using only
features supported by JVM 1.1 (Groan.. Yeah yeah, I know!)

I need to be able to fill the screen by streching the fonts of the text in
both directions, so if the user likes they may have extremely long but thin
fonts...

Now, Java2D handles this just great with the Font.deriveFont() created using
an AffineTransform. But, of course none of this exists in Java 1.1 so I am
left with trying other things...

My first attempt at this has been to recalculate the nearest fitting font
size that will fit a string on the screen (or actually just fitting outside
it). Then i create an image which is the actual width of the string using
the new font, and the height is the number of strings * the
FontMetrics.getHeight(). I then scale the image to the size of my window and
draw it.

This works, but the quality is a bit naff. If I use SCALE_AREA_AVERAGING or
SCALE_SMOOTH, the scaled image takes a bit longer to create obviously, but
event hen the resulting image is not great (fonts are smoother, but colour
is somewhat washed out..). Using SCALE_FAST or SCALE_REPLICATE then we start
getting lots of jaggedy edges and blocky drawing.

What I realyl would like to do is find a way to mimic the Java2D
deriveFont() functionality, but cannot seem to find anywhere on the web that
seems to have done this successfully.

Below is a snippet of what I have got so far.. Ugly as sin!

Steve

<snip>
private class DrawPanel extends Panel {
Font _font;
int _size;
Rectangle _bounds;
private String[] _data;

public int RENDER_HINT = Image.SCALE_FAST;
public boolean _useBold = false;

public static void main(String[] args){
Frame f = new Frame();
f.add(new DrawPanel());
f.show();
}

public DrawPanel() {
super();
setupTestData();
super.addComponentListener(new ComponentListener() {
public void componentHidden(ComponentEvent e) {}

public void componentMoved(ComponentEvent e) {}

public void componentResized(ComponentEvent e) {
rescaleFont();
}
public void componentShown(ComponentEvent e) {
rescaleFont();
}
});
}
/**
* Generate 25 rows x 80 chars (123456789.....)
*/
private void setupTestData() {
_data = new String[25];
String str = new String();
for (int i = 1; i <= 80; i++) {
str += (i % 10);
_space += " ";
}
for (int i = 0; i < _data.length; i++) {
_data[i] = str;
}
}

private Font createFont(int size){
return new Font("Monospaced", _useBold ? Font.BOLD : Font.PLAIN,
size);
}

public void rescaleFont() {
rescaleFontAwt(getGraphics(), getBounds());
}

public void rescaleFontAwt(Graphics g, Rectangle bounds) {
if (g == null) {
return;
}
if ( bounds.equals( _bounds )){
return;
}
_bounds = bounds;


int border = 2;
int numRows = _data.length;
int size = 1;
int maxWidth = bounds.width - (border * 2);
int maxHeight = (bounds.height) / (numRows);

FontMetrics fm = g.getFontMetrics();
Font f = _font;
//Find font size that will create
while (true) {
f = createFont( size );
fm = g.getFontMetrics(f);
int width = fm.stringWidth(_data[0]);
if (width >= maxWidth) {
break;
}
else {
size++;
}
}

_font = f;
g.setFont(_font);
_size = size;
System.out.println("Width= " + bounds.width + ", StrWidth = " +
g.getFontMetrics().stringWidth(_data[0]));
}

public void paint(Graphics g){

if(_font==null){
//Safety Catch to make sure we have at least scaled once!
//Also assume this is called by the parent container on resize!
rescaleFont();
}

Rectangle bounds = getBounds();
int border = 2;
int numRows = _data.length;

//Clear the rectangle
g.setColor(Color.black);
g.fillRect(0, 0, bounds.width, bounds.height);

g.setFont(_font);
FontMetrics fm = g.getFontMetrics(_font);

int fontHeight = fm.getHeight()- fm.getDescent() + 2;
//Height of the rendered image based on font size
int fontWidth = fm.stringWidth(_data[0]); //The width of the string
based on the font
int scaledHeight = fontHeight * numRows;

int rowHeight = (bounds.height / numRows); //The height of a row
int rowWidth = bounds.width - (border*2); //The width of a row

int x = 0 + border;
int y = border;
//Generate the main image that fits the width and height of data to be
drawn
Image img = this.createImage(fontWidth, scaledHeight);
//Now prepare to draw on it
Graphics g2 = img.getGraphics();
g2.setFont(_font);
FontMetrics fm2 = g2.getFontMetrics();
int stringYPos = fm2.getHeight() - (fm2.getDescent() * 2)+ 3;
//Black backgroung
g2.setColor(Color.black);
g2.fillRect(0, 0, fontWidth, scaledHeight);

//Draw the data
g2.setColor(Color.green);

//Draw each data line
for (int i = 0; i < _data.length; i++) {
g2.drawString(_data[i], 0, y + stringYPos);
y += fontHeight;
}

//Now create a scaled image to fit our panel's bounds
Image scaledImg = img.getScaledInstance(bounds.width, bounds.height,
RENDER_HINT);
g.drawImage(scaledImg, 0, 0, null);
}
}
</snip>


.



Relevant Pages

  • RE: Install font from ClickOnce application
    ... and the new font works fine. ... private void installButton_Click ... string fontsPath = GetFontsPath; ... private static extern int SHGetFolderPath(IntPtr hwndOwner, int nFolder, ...
    (microsoft.public.dotnet.framework)
  • RE: Install font from ClickOnce application
    ... private font since the application can write files for use by other ... private static extern int SHGetFolderPath(IntPtr hwndOwner, int nFolder, ... private static string GetFontsPath() ...
    (microsoft.public.dotnet.framework)
  • Re: font size in pixels?
    ... or measures the size in pixels of an existing font? ... public void mousePressed{ ... int h = fm.getHeight; ... private static Font retcod; ...
    (comp.lang.java.gui)
  • Re: Suggested Newbie project, FontShower
    ... * An applet that lets you choose the font family, size, style ... * @author Fahd SHARIFF ... private JComboBox fonts, sizes; ... public void changeSize ...
    (comp.lang.java.help)
  • Re: Suggested Newbie project, FontShower
    ... * An applet that lets you choose the font family, size, style ... * @author Fahd SHARIFF ... private JComboBox fonts, sizes; ... public void changeSize ...
    (comp.lang.java.help)