More anti-aliasing puzzles

R

Roedy Green

here is a simple extension to JTextArea to let you control whether the
fonts are displayed with anti-aliasing. The only catch is, it never
anti-aliases the fonts. Similar logic for AWT works fine. Does anyone
know what I am doing wrong? Do I have to override some method other
than paint?



package com.mindprod.fontshower;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;

import javax.swing.JTextArea;
import javax.swing.text.Document;

/**
* Like JTextArea, but allows you to control whether fonts are
anti-aliased.
*
* @author Roedy Green
*/
public class AntialiasedJTextArea extends JTextArea {

/**
* true if want extra debugging output
*/
public final static boolean DEBUGGING = true;

/**
* true if want anti-aliased fonts
*/
private boolean antialias = true;

/**
* called whenever system has a slice to render
*
* @param g
* Graphics defining where and region to paint.
*/
public void paint ( Graphics g )
{
Graphics2D g2d = (Graphics2D)g;
if ( antialias )
{
g2d.setRenderingHint(
RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON );
g2d.setRenderingHint( RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY );
}
if ( DEBUGGING )
{
System.out.println( "AntialiasedJTextArea.paint called
antialias:"
+ antialias );
}
super.paint( g2d );
}

/**
* Control whether fonts are antialiased. Takes extra time, but
makes
* smoother edges.
*
* @param antialias
* true if want anti-aliasing.
*/
public void setAntialias ( boolean antialias )
{
this.antialias = antialias;
this.repaint();
}

/**
* no arg constructor
*/
public AntialiasedJTextArea()
{
super();
}

/**
* Constructs a new AntialiasedJTextArea with the specified number
of rows
* and columns, and the given model. All of the constructors feed
through
* this constructor.
*
* @param doc
* the model to use, or create a default one if null
* @param text
* the text to be displayed, null if none
* @param rows
* the number of rows >= 0
* @param columns
* the number of columns >= 0
* @exception IllegalArgumentException
* if the rows or columns arguments are negative.
*/
public AntialiasedJTextArea( Document doc, String text, int rows,
int columns )
{
super( doc, text, rows, columns );
}

/**
* Constructs a new empty AntialiasedJTextArea with the specified
number of
* rows and columns. A default model is created, and the initial
string is
* null.
*
* @param rows
* the number of rows >= 0
* @param columns
* the number of columns >= 0
* @exception IllegalArgumentException
* if the rows or columns arguments are negative.
*/
public AntialiasedJTextArea( int rows, int columns )
{
super( rows, columns );
}

/**
* constructor
*
* @param message
* text to display
*/
public AntialiasedJTextArea( String message )
{
super( message );
}

/**
* Constructs a new AntialiasedJTextArea with the specified text
and number
* of rows and columns. A default model is created.
*
* @param text
* the text to be displayed, or null
* @param rows
* the number of rows >= 0
* @param columns
* the number of columns >= 0
* @exception IllegalArgumentException
* if the rows or columns arguments are negative.
*/
public AntialiasedJTextArea( String text, int rows, int columns )
{
super( text, rows, columns );
}

}



--
Bush crime family lost/embezzled $3 trillion from Pentagon.
Complicit Bush-friendly media keeps mum. Rumsfeld confesses on video.
http://www.infowars.com/articles/us/mckinney_grills_rumsfeld.htm

Canadian Mind Products, Roedy Green.
See http://mindprod.com/iraq.html photos of Bush's war crimes
 
A

Alan Moore

here is a simple extension to JTextArea to let you control whether the
fonts are displayed with anti-aliasing. The only catch is, it never
anti-aliases the fonts. Similar logic for AWT works fine. Does anyone
know what I am doing wrong? Do I have to override some method other
than paint?

You shouldn't need to override any method. Assuming you're using
v5.x, turning on antialiasing for a specific JComponent is a matter of
setting a client property, e.g.:

textArea.setClientProperty(
com.sun.java.swing.SwingUtilities2.AA_TEXT_PROPERTY_KEY,
Boolean.TRUE);

If you look at the source code for SwingUtilities2, you'll see that it
completely ignores whatever rendering hints have been set on the
graphics object. Instead, it looks for that client property or the
system property "swing.aatext" to decide whether to use antialiasing.

And, just to keep us on our toes, Mustang uses a completely different
system.
 
R

Roedy Green

You shouldn't need to override any method. Assuming you're using
v5.x, turning on antialiasing for a specific JComponent is a matter of
setting a client property, e.g.:

I was trying to write this for Java 1.3.
--
Bush crime family lost/embezzled $3 trillion from Pentagon.
Complicit Bush-friendly media keeps mum. Rumsfeld confesses on video.
http://www.infowars.com/articles/us/mckinney_grills_rumsfeld.htm

Canadian Mind Products, Roedy Green.
See http://mindprod.com/iraq.html photos of Bush's war crimes
 
D

Dilton McGowan II

Roedy Green said:
here is a simple extension to JTextArea to let you control whether the
fonts are displayed with anti-aliasing. The only catch is, it never
anti-aliases the fonts. Similar logic for AWT works fine. Does anyone
know what I am doing wrong? Do I have to override some method other
than paint?



package com.mindprod.fontshower;

import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;

import javax.swing.JTextArea;
import javax.swing.text.Document;

/**
* Like JTextArea, but allows you to control whether fonts are
anti-aliased.
*
* @author Roedy Green
*/
public class AntialiasedJTextArea extends JTextArea {

/**
* true if want extra debugging output
*/
public final static boolean DEBUGGING = true;

/**
* true if want anti-aliased fonts
*/
private boolean antialias = true;

/**
* called whenever system has a slice to render
*
* @param g
* Graphics defining where and region to paint.
*/
public void paint ( Graphics g )
{
Graphics2D g2d = (Graphics2D)g;
if ( antialias )
{
g2d.setRenderingHint(
RenderingHints.KEY_TEXT_ANTIALIASING,
RenderingHints.VALUE_TEXT_ANTIALIAS_ON );
g2d.setRenderingHint( RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY );
}
if ( DEBUGGING )
{
System.out.println( "AntialiasedJTextArea.paint called
antialias:"
+ antialias );
}
super.paint( g2d );
}

/**
* Control whether fonts are antialiased. Takes extra time, but
makes
* smoother edges.
*
* @param antialias
* true if want anti-aliasing.
*/
public void setAntialias ( boolean antialias )
{
this.antialias = antialias;
this.repaint();
}

/**
* no arg constructor
*/
public AntialiasedJTextArea()
{
super();
}

/**
* Constructs a new AntialiasedJTextArea with the specified number
of rows
* and columns, and the given model. All of the constructors feed
through
* this constructor.
*
* @param doc
* the model to use, or create a default one if null
* @param text
* the text to be displayed, null if none
* @param rows
* the number of rows >= 0
* @param columns
* the number of columns >= 0
* @exception IllegalArgumentException
* if the rows or columns arguments are negative.
*/
public AntialiasedJTextArea( Document doc, String text, int rows,
int columns )
{
super( doc, text, rows, columns );
}

/**
* Constructs a new empty AntialiasedJTextArea with the specified
number of
* rows and columns. A default model is created, and the initial
string is
* null.
*
* @param rows
* the number of rows >= 0
* @param columns
* the number of columns >= 0
* @exception IllegalArgumentException
* if the rows or columns arguments are negative.
*/
public AntialiasedJTextArea( int rows, int columns )
{
super( rows, columns );
}

/**
* constructor
*
* @param message
* text to display
*/
public AntialiasedJTextArea( String message )
{
super( message );
}

/**
* Constructs a new AntialiasedJTextArea with the specified text
and number
* of rows and columns. A default model is created.
*
* @param text
* the text to be displayed, or null
* @param rows
* the number of rows >= 0
* @param columns
* the number of columns >= 0
* @exception IllegalArgumentException
* if the rows or columns arguments are negative.
*/
public AntialiasedJTextArea( String text, int rows, int columns )
{
super( text, rows, columns );
}

}

I removed your sig to focus on Java.

Your code works for me on XP SP2. Due to a recent set of events I find
myself back in the Java world and your challenge looked very cool. :)

Still.. it worked for me? I created this humbel code:

---------------------------start code------------------------
import javax.swing.*;
import java.awt.*;

public class TestFrame extends javax.swing.JFrame
{
public TestFrame()
{
this.setBounds(400,400,400,400);
AntialiasedJTextArea a = new AntialiasedJTextArea();
//JTextArea a = new JTextArea();
getContentPane().add(a);
}

public static void main(String args[])
{
(new TestFrame()).setVisible(true);
}
}
---------------------------end code------------------------

I commented out your package line because I couldn't get the darn test
program to compile. <sg> (see I've been out of Java mode too long)

But, it does work, oh also to be sure I turned desktop anti-aliasing off to
check the differences in two versions of the test program, one with your AA
code and the other without.

Dilton
 
R

Roedy Green

I commented out your package line because I couldn't get the darn test
program to compile. <sg> (see I've been out of Java mode too long)

But, it does work, oh also to be sure I turned desktop anti-aliasing off to
check the differences in two versions of the test program, one with your AA
code and the other without.

Ok what is different between our two machines?

I ran JDK 1.5.0_04.

I am using Win2K.

I am dynamically flipping the aliasing on and off.

I am going to try it under JDK 1.4

--
Bush crime family lost/embezzled $3 trillion from Pentagon.
Complicit Bush-friendly media keeps mum. Rumsfeld confesses on video.
http://www.infowars.com/articles/us/mckinney_grills_rumsfeld.htm

Canadian Mind Products, Roedy Green.
See http://mindprod.com/iraq.html photos of Bush's war crimes
 
R

Roedy Green

Ok what is different between our two machines?

did you see both plain and anti-aliased fonts appear?

I tried it with JDK 1.4. no sign of anti-aliasing.

The weird thing is AWT works just fine.

In poking around at the Swing code, it looks as if my code SHOULD NOT
work, since Jcomponent.paintComponent clones the graphics object,
presumably stripping it of any added rendering hints.

Yet is see in two places on the net people claiming the code I wrote
should work.

--
Bush crime family lost/embezzled $3 trillion from Pentagon.
Complicit Bush-friendly media keeps mum. Rumsfeld confesses on video.
http://www.infowars.com/articles/us/mckinney_grills_rumsfeld.htm

Canadian Mind Products, Roedy Green.
See http://mindprod.com/iraq.html photos of Bush's war crimes
 
R

Roedy Green

if anyone is interested in pursuing this, to track down why
anti-aliasing sometimes works and sometimes does not, the code is
posted at

http://mindprod.com/products1.html#FONTSHOWER for the Swing version
and
http://mindprod.com/products1.html#FONTSHOWERAWT for the AWT version


--
Bush crime family lost/embezzled $3 trillion from Pentagon.
Complicit Bush-friendly media keeps mum. Rumsfeld confesses on video.
http://www.infowars.com/articles/us/mckinney_grills_rumsfeld.htm

Canadian Mind Products, Roedy Green.
See http://mindprod.com/iraq.html photos of Bush's war crimes
 
D

Dilton McGowan II

Roedy Green said:
On Tue, 9 Aug 2005 20:48:28 -0700, "Dilton McGowan II"


Ok what is different between our two machines?

I ran JDK 1.5.0_04.

I am using Win2K.

I am dynamically flipping the aliasing on and off.

I am going to try it under JDK 1.4

java version "1.5.0_04"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_04-b05)
Java HotSpot(TM) Client VM (build 1.5.0_04-b05, mixed mode, sharing)

You can see the results at http://www.mccomsoft.com/images/anti.png. Java's
anti-aliasing isn't the best I've seen but it seems to be working?

It shouldn't matter but I also had turned the XP desktop's cleartype off. I
wish tools like NetBeans would use AA on Windows so the text wouldn't be so
ugly.
 
L

Larry Barowski

Dilton McGowan II said:
It shouldn't matter but I also had turned the XP desktop's cleartype off. I
wish tools like NetBeans would use AA on Windows so the text wouldn't be so
ugly.

I don't use NetBeans, so I don't know how to pass in JVM
flags, but you can turn on antialiasing in Java 1.5 by
passing in -Dswing.aatext=true .
 
C

Cantankerous Old Git

Roedy said:
here is a simple extension to JTextArea to let you control whether the
fonts are displayed with anti-aliasing. The only catch is, it never
anti-aliases the fonts. Similar logic for AWT works fine. Does anyone
know what I am doing wrong? Do I have to override some method other
than paint?

Try this little thingy below. It has a main method, so you can
run it standalone.

I notice that I overrode paintComponent() rather than paint().

You can turn anti-alias on/off purely by clicking the antialias
button. This still hapens on 1.5 - look closely at the sample
text as you click the button.

HTH
The Cog



import java.util.*;
import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.*;


public class FontPicker
extends JPanel
implements ActionListener, ListSelectionListener, ChangeListener
{
private Font[] fonts;
private JList list;
private AAJTextField sampleText;
private JTextField sizeText;
private JToggleButton toggle;
private int size;
private Font selectedFont;
private boolean antiAlias;

private UIDefaults uid = UIManager.getDefaults();

/**
* Constructor for class FontPicker
*/
public FontPicker() {
size = 14;
GraphicsEnvironment ge =
GraphicsEnvironment.getLocalGraphicsEnvironment();
fonts = ge.getAllFonts();
Vector v = new Vector();
for(int x = 0 ; x < fonts.length ; x++) {
v.add(fonts[x].getFontName());
}
setLayout(new BorderLayout());
list = new JList(v);
list.addListSelectionListener(this);
add(new JScrollPane(list), BorderLayout.CENTER);
sampleText = new AAJTextField("Sample Text");
add(sampleText, BorderLayout.NORTH);
JPanel sizePanel = new JPanel();
sizePanel.add(new JLabel("Size : "));
sizeText = new JTextField(String.valueOf(size), 4);
sizeText.addActionListener(this);
sizePanel.add(sizeText);
toggle = new JCheckBox("Anti-Alias");
toggle.addChangeListener(this);
sizePanel.add(toggle);
add(sizePanel, BorderLayout.SOUTH);
}

/** Size JTextField event. */
public void actionPerformed(ActionEvent e) {
redisplay();
}

/** JToggleButton event. */
public void stateChanged(ChangeEvent e) {
redisplay();
}

/** JList event. */
public void valueChanged(ListSelectionEvent e) {
if(e.getValueIsAdjusting()) {
return;
}
redisplay();
}


/** Sets the font in the sample text area. */
private void redisplay() {
try {
size = Integer.parseInt(sizeText.getText().trim());
} catch(Exception ex) {
}
sizeText.setText(String.valueOf(size));
int sel = list.getSelectedIndex();
if(sel < 0) {
return;
}
selectedFont = fonts[sel].deriveFont((float)size);
antiAlias = toggle.isSelected();
sampleText.setAntiAlias(antiAlias);
sampleText.setFont(selectedFont);
validate();
repaint();
}

/** Return the selected Font. This is not the base font,
* but the derived font already in the chosen size.
*/
public Font getSelectedFont() {
return sampleText.getFont();
}

/** Return true is anti-alias is selected. */
public boolean getSelectedAntiAlias() {
return toggle.isSelected();
}

/** Return the selected font size.
* This isn't really needed since getSelectedFont already
supplies the
* font of the required size.
*/
public int getSelectedSize() {
return size;
}


/** Testing only. */
public static void main(String[] args) {
JFrame frame = new JFrame("Font Picker");
frame.getContentPane().add(new FontPicker());
frame.pack();
frame.setVisible(true);
// Platform look and feel
// try {
// UIManager.setLookAndFeel(
// UIManager.getCrossPlatformLookAndFeelClassName());
// } catch (Exception e) {
// System.out.println(e.toString());
// }
}

/** Override paintComponent in order to set rendering hint */
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
super.paintComponent(g);
}


/** A TextField with configurable antialias rendering hint. */
private class AAJTextField extends JTextField {
private Object hint;

private AAJTextField(String s) {
super(s);
hint = RenderingHints.VALUE_ANTIALIAS_OFF;
}

private void setAntiAlias(boolean b) {
hint = b ? RenderingHints.VALUE_ANTIALIAS_ON
: RenderingHints.VALUE_ANTIALIAS_OFF;
repaint();
}

/** Override paintComponent in order to set rendering
hint */
protected void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
hint);
super.paintComponent(g);
}
}
}
 
D

Dilton McGowan II

Roedy Green said:
I guess the problem in Win2K.

My conjecture that for AWT-Canvas Sun does the anti-aliasing itself,
but for Swing it relies on the OS. This is backwards to what you would
normally expect.

I'm confused, I'm on XP and had the OS ClearType off which means since it
works then I'm still not sure why it doesn't work for you unless you mean
you are on Win2k and that is where the Swing code is failing? If that's
happeneing then I have no clue why it would fail since it's not using the OS
to do the AA anyway?

Someone who has worked with Swing on Win2K and XP would have to comment like
a Sun developer? Maybe file a bug against Swing and let Sun sort it out. :)
 
R

Roedy Green

I notice that I overrode paintComponent() rather than paint().

In my latest version I too override paintComponent.

Observations:

my code works on XP but not Win2K (or at least on my machine)

Your code works fine on my machine.

I now have to track down what you did differently from me.

It have discovered it is not that you also overrode your JPanel
paintComponent.

It is not that I used g2d.setRenderingHint(
RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY );

It is not that you used a JTextField and I used a JTextArea.

it is not that I setEditable( false );

It is not that I was using -target 1.3

It is not that I was using KEY_TEXT_ANTIALIASING
where you were using KEY_ANTIALIASING.

Finally, I discovered the problem.

\u0e3f in a JTextArea inhibits antialiasing.
ditto \ufdfc.

\u0e3F is a Thai Baht currency sign like a capital B with a line
through it.

\ufdfc is the Yemini Rial currency sign. It looks like Arabic script.
 
R

Roedy Green

The anti-aliasing puzzle is slowly unraveling.

Here is what I have found:

In Swing you can override paintComponent to turn on antialiasing. This
works so long as you don't have inhibiting characters in your
JTextArea like the Thai Baht sign.

In AWT you can override paint in canvas to turn on antialiasing.
This gives you access to all the fonts, and all the characters in the
fonts. With Peer components you are restricted to the basic logical
fonts and only some of the characters in those fonts.

Now for the final strangeness. I tried overriding paint in AWT
TextArea and discovered it had no effect. No matter what you do,
anti-aliasing is turned ON. I gather this is because Windows peers do
the rendering out of Java control.
 
R

Roedy Green

I'm confused, I'm on XP and had the OS ClearType off which means since it
works then I'm still not sure why it doesn't work for you unless you mean
you are on Win2k and that is where the Swing code is failing? If that's
happeneing then I have no clue why it would fail since it's not using the OS
to do the AA anyway?

I have sorted it all out. I have documented it at
http://mindprod.com/jgloss/antialiasing.html

I have written two Applets that demonstrate the limitations of AWT and
Swing vis a vis fonts and anti-aliasing.

See http://mindprod.com/applets/fontshower.html
http://mindprod.com/applets/fontshowerawt.html
 
C

Cantankerous Old Git

Roedy said:
Finally, I discovered the problem.

\u0e3f in a JTextArea inhibits antialiasing.
ditto \ufdfc.

\u0e3F is a Thai Baht currency sign like a capital B with a line
through it.

\ufdfc is the Yemini Rial currency sign. It looks like Arabic script.

That's so bizarre it can't possibly be right!

Except that I can replicate it in Linux and java 5.0 too. The
text stays non-aliased even after you delete the offending
character again.

It must have taken you ages to track that down.
 
L

Larry Barowski

Roedy Green said:
Finally, I discovered the problem.

\u0e3f in a JTextArea inhibits antialiasing.
ditto \ufdfc.

\u0e3F is a Thai Baht currency sign like a capital B with a line
through it.

\ufdfc is the Yemini Rial currency sign. It looks like Arabic script.

Did you report this to Sun yet? It doesn't seem to be in the
bug database - at least I couldn't find it.
 
R

Roedy Green

Did you report this to Sun yet? It doesn't seem to be in the
bug database - at least I couldn't find it.

the Afghan char is probably a feature not a bug. The stuff done with
peers in Windows doing. However that leaven the mystery of the Swing
inhibiting antialias. If it as is a feature they should at least
document it to save people like me going mad with frustration trying
to figure out why it sometimes works but not always.

I will report it.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,011
Latest member
AjaUqq1950

Latest Threads

Top