Results 1 to 5 of 5
  1. #1
    neptune692 is offline Member
    Join Date
    Jan 2011
    Posts
    20
    Rep Power
    0

    Question Rotated Text and Antialiasing on Windows

    I have posted this question on the Oracle forums under Java2D before realizing that that section of the forums is kind of dead or very slow moving and I was hoping for a little help on this problem today. So i'll go ahead and try asking here as well.

    I am creating an application that uses rotated text, i've been developing this application in Mac OS X and have had no problem with jagged edges on text as it seems Mac OS automatically antialiases text without using any rendering hints. However on Windows platforms I noticed the text appeared very jagged especially when rotated anywhere from five degrees up. I thought I could solve this problem by applying rendering hints specifying antialiasing on and text antialiasing on. This did help however it only appears smooth when the text is very large around 90-100pts and goes back to appearing jagged when below this size even with these rendering hints applied.

    I have developed a simple application that you can run that rotates a letter seven degrees and loops through the font sizes of 20 - 120. You should notice that at font sizes around 100-120 the letter appears way smoother then at font sizes around 80 and below.

    I have also uploaded an image comparing the letter D antialiased and rotated 7 degrees on both Mac OS and Windows you can see on the left (Mac OS) the letter appears smoother then then the letter on the right (Windows 7). It appears the letter on the right is still being antialiased but not as effectively as the letter on the left. Is there a way to fix this problem? The antialiased text on Windows 7 really doesn't appear all that smooth compared to Mac OS. In fact if I didn't know that I was explicitly telling it to use antialiasing it would be hard for me to tell it was antialiasing at all.

    The photo comparing antialiasing on Mac OS and Windows 7 can be found here: http://doodletype.com/Antialiasing/jagged.png



    The source code for my example:

    Java Code:
    /*
     * To change this template, choose Tools | Templates
     * and open the template in the editor.
     */
    
    package smoothtext;
    
    
    import java.awt.*;
    import javax.swing.*;
    import javax.swing.Action.*;
    import com.sun.awt.AWTUtilities.*;
    import java.awt.Rectangle;
    import java.awt.font.*;
    
    
    public class SmoothText {
    
        /**
         * @param args the command line arguments
         */
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater( new Runnable() {
                public void run() {
                    try {
                        UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
                    } catch(Exception err) {
                        System.out.println(err);
                    }
                    new SmoothText();
                }
            });
        }
    
    
        int offset = 1;
        Font font = new Font("Arial", Font.PLAIN, 20);
        PaintSurface canvas = new PaintSurface();
        JFrame frame = new JFrame("Smooth Text");
        
        public SmoothText() {
    
            frame.setSize(500,500);
            frame.setLocationRelativeTo(null);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
            frame.add(canvas);
            frame.setVisible(true);
    
            new Thread(new AnimationThread()).start();
        }
    
        class AnimationThread implements Runnable {
    
            public void run() {
    
                while(true) {
                    try {
                        Thread.sleep(30);
                    } catch(InterruptedException err) {
                        //handle interrupted exception
                    }
    
                    if(font.getSize()>120) {
                        offset = -1;
                    } else if(font.getSize()<20) {
                        offset = 1;
                    }
                    font = new Font(font.getFamily(), font.getStyle(), font.getSize()+offset);
                    canvas.repaint();
                }
            }
        }
    
        class PaintSurface extends JComponent {
    
            @Override
            public void paintComponent(Graphics g) {
    
                super.paintComponent(g);
    
                Graphics2D g2 = (Graphics2D)g;
                g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
                //This probably isn't necissary when I already specifed antialiasing on.
                g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
    
                g2.setColor(Color.red);
                g2.drawString("Font Size: "+font.getSize(), 20, 20);
                g2.setColor(Color.black);
                
                g2.setFont(font);
                TextLayout layout = new TextLayout("D", font, g2.getFontRenderContext());
                Rectangle bounds = layout.getPixelBounds(null, 0, 0);
    
                g2.rotate(Math.toRadians(7), (getWidth()/2 - bounds.width/2)+bounds.width/2, ((getHeight()/2 - bounds.height/2)-(int)bounds.getY())+bounds.height/2);
                g2.drawString("D", getWidth()/2 - bounds.width/2, (getHeight()/2 - bounds.height/2)-(int)bounds.getY());
            }
        }
    }
    I've only tested this on Windows 7 so this "problem" may only occur on Windows 7 but let me know if you see the same thing. I'm assuming there must be some way to make the letter on the right appear smoother as the letter on the left appears. But i'm just not sure how because I have already enabled antialiasing for text and it doesn't seem to me that it is working as it should. Any help with solving this problem would be great.

    Thank you. :)
    Last edited by neptune692; 04-26-2011 at 01:07 AM. Reason: Added content.

  2. #2
    ozzyman's Avatar
    ozzyman is offline Senior Member
    Join Date
    Mar 2011
    Location
    London, UK
    Posts
    797
    Blog Entries
    2
    Rep Power
    4

    Default

    I think its because the antialiasing only turns on at certain text sizes.

    Displaying Antialiased Text by Using Rendering Hints (The Java™ Tutorials > 2D Graphics > Working with Text APIs)

    try this instead
    TEXT_ANTIALIAS_LCD_HRGB

  3. #3
    neptune692 is offline Member
    Join Date
    Jan 2011
    Posts
    20
    Rep Power
    0

    Default

    Thank you for your suggestion, I tried the following:

    Java Code:
        class PaintSurface extends JComponent {
    
            @Override
            public void paintComponent(Graphics g) {
    
                super.paintComponent(g);
    
                Graphics2D g2 = (Graphics2D)g;
    
                g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
                
                g2.setColor(Color.red);
                g2.drawString("Font Size: "+font.getSize(), 20, 20);
                g2.setColor(Color.black);
    
                g2.setFont(font);
                
                TextLayout layout = new TextLayout("D", font, g2.getFontRenderContext());
                Rectangle bounds = layout.getPixelBounds(null, 0, 0);
    
                g2.rotate(Math.toRadians(7), (getWidth()/2 - bounds.width/2)+bounds.width/2, ((getHeight()/2 - bounds.height/2)-(int)bounds.getY())+bounds.height/2);
                g2.drawString("D", getWidth()/2 - bounds.width/2, (getHeight()/2 - bounds.height/2)-(int)bounds.getY());
            }
        }
    However this doesn't seem to make any difference on any Windows Vista or Windows 7 platform I try it on, I have not had a chance to try it on an older version of Windows.

    Here is a screen capture of the results:


    I can't imagine there isn't a way around this, I mean that letter really doesn't look smooth at all. :(

    Anyway thank you for your help I'm hoping to solve this problem its very important for a project i'm working on.

  4. #4
    ozzyman's Avatar
    ozzyman is offline Senior Member
    Join Date
    Mar 2011
    Location
    London, UK
    Posts
    797
    Blog Entries
    2
    Rep Power
    4

    Default

    I think its because you rotated it after i.e. you antialised the text before you rotated the graphic, so maybe if you use AffineTransform instead for rotating the text, with rendering hints.. it might work

    Java Code:
            java.awt.geom.AffineTransform at = new java.awt.geom.AffineTransform();
            at.rotate(20);
            Font font = new Font("Lucida Console", Font.PLAIN, 10);
            Font atFont = font.deriveFont(at);
            FontRenderContext frc = new FontRenderContext(atFont.getTransform(), true, true);
    then take it from there

  5. #5
    neptune692 is offline Member
    Join Date
    Jan 2011
    Posts
    20
    Rep Power
    0

    Default

    Thank you for your help, from what I have implemented it doesn't seem to improve the rendering quality however i'm not sure i've done what you expected.

    Anyway thank you for your help, here is the new PaintSurface class implementing what I think you were suggesting. If this is what you were suggesting is there anything else I might be doing wrong the text still doesn't seem smooth?

    Here are the results on Windows:


    Here are the results on Mac OS:


    Shouldn't the letter appear as smooth as on Mac OS? Or is this the best I can get on Windows?

    Java Code:
        class PaintSurface extends JComponent {
    
            Font atFont;
            FontRenderContext frc;
    
            public PaintSurface() {
                
                java.awt.geom.AffineTransform at = new java.awt.geom.AffineTransform();
                at.rotate(Math.toRadians(10));
                Font font = new Font("Arial", Font.PLAIN, 80);
                atFont = font.deriveFont(at);
                frc = new FontRenderContext(atFont.getTransform(), true, true);
            }
    
            @Override
            public void paintComponent(Graphics g) {
    
                super.paintComponent(g);
    
                Graphics2D g2 = (Graphics2D)g;            
                g2.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
    
                g2.setColor(Color.red);
                g2.drawString("Font Size: "+font.getSize(), 20, 20);
                g2.setColor(Color.black);            
                
                g2.setFont(atFont);
    
                TextLayout layout = new TextLayout("D", atFont, frc);
                Rectangle bounds = layout.getPixelBounds(null, 0, 0);
    
                g2.drawString("D", getWidth()/2 - bounds.width/2, (getHeight()/2 - bounds.height/2)-(int)bounds.getY());                        
            }
        }
    Last edited by neptune692; 05-05-2011 at 09:50 PM.

Similar Threads

  1. Replies: 7
    Last Post: 03-05-2011, 10:25 AM
  2. Windows java vs Windows AIX
    By sysp in forum New To Java
    Replies: 0
    Last Post: 01-26-2011, 06:32 AM
  3. Replies: 0
    Last Post: 12-09-2010, 06:56 PM
  4. Replies: 0
    Last Post: 09-28-2010, 10:52 AM
  5. Replies: 7
    Last Post: 10-06-2009, 06:58 AM

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •