/* * AntialiasDemo.java 1.0 * * @summary * * AntialiasDemo application works similarly to Font2DTest and is designed for * testing various font configurations with new Mustang (1.6) antialiasing features * such as GASP and LCD text. * * As the application renders the font configuration, it dynamically detects the * type on antialiasing used, Antialias OFF, Antialias ON (gray-scale), or * Antialias LCD (lcd-text). For example with GASP feature, the font size slider * can be moved across the size ranges and observe changes in antialiasing modes * between OFF and ON. * * The application also displays the current value for Default Antialias (set by JRE), * and the current Desktop Antialias used by Swing components. The Desktop Antialias * Listener monitors for OS changes and will also dynamically update the current * setting. * * For automated testing, API is provided for creating any font rendering and * returning a BufferedImage. Optionally the returned BufferedImage can be tested * for Antialiasing setting and/or saved to an image file. * * Methods are available for adding user fonts to those already included with * the OS. This allows for testing with Type1 fonts and also testing the same * set of fonts across different platforms. * * Created using Sun One Studio 5, for Swing Component Layout. * * @author Rick Reynaga (rick.reynaga@sun.com) area=2D-Font */ import java.awt.*; import javax.swing.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.geom.Rectangle2D; import java.awt.image.*; import java.util.*; import java.io.*; import java.beans.*; import static java.awt.RenderingHints.*; import javax.imageio.*; public class AntialiasDemo extends javax.swing.JFrame { private String textString = "The sky is blue"; private String fontName = "Dialog"; private int fontStyle = Font.PLAIN; private int fontSize = 12; private HashMap userFonts = null; public static String AA_OFF = "OFF"; public static String AA_ON = "ON"; public static String AA_LCD = "LCD"; public static String DESKTOP_HINT_UNAVAILABLE = "Unavailable"; private Object antiAliasType = VALUE_TEXT_ANTIALIAS_DEFAULT; private Object lcdContrast = getDefaultLCDContrast(); private int fontStyles[] = {Font.PLAIN, Font.BOLD, Font.ITALIC, Font.BOLD | Font.ITALIC}; private TextPanel textPanel = null; private BufferedImage textPanelImage = null; // Desktop Properties static String dtprop = "awt.font.desktophints"; static Toolkit tk = Toolkit.getDefaultToolkit(); private static Object lockObject = new Object(); private static boolean available = true; /** Creates new form AntialiasDemo */ public AntialiasDemo() { // Setup frame and font control panel initComponents(); // Setup font style settings jComboBoxStyleMenu.addItem( "Plain" ); jComboBoxStyleMenu.addItem( "Bold" ); jComboBoxStyleMenu.addItem( "Italic" ); jComboBoxStyleMenu.addItem( "Bold Italic" ); fontStyle = fontStyles[jComboBoxStyleMenu.getSelectedIndex()]; // Setup font antialias settings AAValues[] aaValues = AAValues.getArray(); for ( int i = 0; i < aaValues.length; i++ ) jComboBoxAntialias.addItem( aaValues[i] ); antiAliasType = ((AAValues)jComboBoxAntialias.getSelectedItem()).getHint(); // Setup LCD Contrast jSliderContrast.setValue(getDefaultLCDContrast().intValue()); // Load available fonts String fontList[] = GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames(); for ( int i = 0; i < fontList.length; i++ ) jComboBoxFontMenu.addItem( fontList[i] ); jComboBoxFontMenu.setSelectedItem( "Dialog" ); // Default antialias status setDefaultAntialiasStatus(); // Desktop antialias status setDesktopAntialiasStatus(); // Desktop antialias property change listener // Any changes to OS antialias setting will be dynamically updated tk.addPropertyChangeListener(dtprop, new PropertyChangeListener() { public void propertyChange(PropertyChangeEvent e) { desktopAntialiasPropertyStateChanged(e); } }); // Add font rendering panel to frame and bring up GUI textPanel = new TextPanel(); textPanel.setPreferredSize(new java.awt.Dimension(700, 240)); getContentPane().add(textPanel, java.awt.BorderLayout.CENTER); pack(); setVisible(true); } /** * Method for testing the font rendering for Antialiasing mode * * This will test if antialiasing is not present (AA_OFF), gray-scale (AA_ON), * or lcd-text antialising (AA_LCD). */ public String getAntialiasMode(BufferedImage img) { // Determine the set of pixel colors for the BufferedImage DataBuffer b = img.getRaster().getDataBuffer(); int[] pixels = ((DataBufferInt)b).getData(); LinkedHashSet pixelVals = new LinkedHashSet(); for (int p=0;p= AALCDHRGB.ordinal()); } public static Object getValue(String name) { if (valArray == null) { valArray = (AAValues[])EnumSet.allOf(AAValues.class).toArray(new AAValues[0]); } for (int i=0;i cls) { this.name = name; this.theClass = cls; } private final String name; private final Class theClass; public Class getDstClass() { return theClass; } public String toString() { return name; } } /** * Returns the system default contrast setting * (this section was copied from Font2DTest) */ private static Integer defaultContrast; static Integer getDefaultLCDContrast() { if (defaultContrast == null) { GraphicsConfiguration gc = GraphicsEnvironment.getLocalGraphicsEnvironment(). getDefaultScreenDevice().getDefaultConfiguration(); Graphics2D g2d = (Graphics2D)(gc.createCompatibleImage(1,1).getGraphics()); defaultContrast = (Integer) g2d.getRenderingHint(RenderingHints.KEY_TEXT_LCD_CONTRAST); } return defaultContrast; } /** This method is called from within the constructor to * initialize the form. * WARNING: Do NOT modify this code. The content of this method is * always regenerated by the Form Editor. */ private void initComponents() {//GEN-BEGIN:initComponents jPanelControls = new javax.swing.JPanel(); jPanelFontSelection = new javax.swing.JPanel(); jLabelFont = new javax.swing.JLabel(); jComboBoxFontMenu = new javax.swing.JComboBox(); jLabelStyle = new javax.swing.JLabel(); jComboBoxStyleMenu = new javax.swing.JComboBox(); jPanelFontAntialias = new javax.swing.JPanel(); jLabelAntialias = new javax.swing.JLabel(); jComboBoxAntialias = new javax.swing.JComboBox(); jLabelContrast = new javax.swing.JLabel(); jSliderContrast = new javax.swing.JSlider(); jPanelSizeControls = new javax.swing.JPanel(); jLabelSize = new javax.swing.JLabel(); jSliderSize = new javax.swing.JSlider(); jPanelStatus = new javax.swing.JPanel(); jLabelDefaultAA = new javax.swing.JLabel(); jLabelDesktopAA = new javax.swing.JLabel(); jLabelRenderingAA = new javax.swing.JLabel(); setTitle("AntialiasDemo"); addWindowListener(new java.awt.event.WindowAdapter() { public void windowClosing(java.awt.event.WindowEvent evt) { exitForm(evt); } }); jPanelControls.setMinimumSize(new java.awt.Dimension(700, 150)); jPanelControls.setPreferredSize(new java.awt.Dimension(700, 150)); jPanelFontSelection.setMinimumSize(new java.awt.Dimension(280, 95)); jPanelFontSelection.setPreferredSize(new java.awt.Dimension(280, 95)); jLabelFont.setText("Font"); jLabelFont.setPreferredSize(new java.awt.Dimension(40, 16)); jPanelFontSelection.add(jLabelFont); jComboBoxFontMenu.setMinimumSize(new java.awt.Dimension(150, 25)); jComboBoxFontMenu.setPreferredSize(new java.awt.Dimension(200, 25)); jComboBoxFontMenu.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jComboBoxFontMenuActionPerformed(evt); } }); jPanelFontSelection.add(jComboBoxFontMenu); jLabelStyle.setText("Style"); jLabelStyle.setMaximumSize(new java.awt.Dimension(30, 16)); jLabelStyle.setPreferredSize(new java.awt.Dimension(40, 16)); jPanelFontSelection.add(jLabelStyle); jComboBoxStyleMenu.setPreferredSize(new java.awt.Dimension(200, 25)); jComboBoxStyleMenu.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jComboBoxStyleMenuActionPerformed(evt); } }); jPanelFontSelection.add(jComboBoxStyleMenu); useVolatile = new JCheckBox("Use volatile image", true); jPanelFontSelection.add(useVolatile); useVolatile.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent actionEvent) { repaint(); } }); jPanelControls.add(jPanelFontSelection); jPanelFontAntialias.setMinimumSize(new java.awt.Dimension(300, 65)); jPanelFontAntialias.setPreferredSize(new java.awt.Dimension(300, 80)); jLabelAntialias.setText("Antialias"); jLabelAntialias.setMaximumSize(new java.awt.Dimension(80, 16)); jLabelAntialias.setPreferredSize(new java.awt.Dimension(80, 16)); jPanelFontAntialias.add(jLabelAntialias); jComboBoxAntialias.setPreferredSize(new java.awt.Dimension(200, 25)); jComboBoxAntialias.addActionListener(new java.awt.event.ActionListener() { public void actionPerformed(java.awt.event.ActionEvent evt) { jComboBoxAntialiasActionPerformed(evt); } }); jPanelFontAntialias.add(jComboBoxAntialias); jLabelContrast.setText("LCD Contrast"); jLabelContrast.setPreferredSize(new java.awt.Dimension(80, 16)); jPanelFontAntialias.add(jLabelContrast); jSliderContrast.setFont(new java.awt.Font("Dialog", 0, 10)); jSliderContrast.setMajorTickSpacing(20); jSliderContrast.setMaximum(250); jSliderContrast.setMinimum(100); jSliderContrast.setMinorTickSpacing(10); jSliderContrast.setPaintLabels(true); jSliderContrast.setPaintTicks(true); jSliderContrast.setValue(140); jSliderContrast.setPreferredSize(new java.awt.Dimension(200, 50)); jSliderContrast.setEnabled(false); jSliderContrast.addChangeListener(new javax.swing.event.ChangeListener() { public void stateChanged(javax.swing.event.ChangeEvent evt) { jSliderContrastStateChanged(evt); } }); jPanelFontAntialias.add(jSliderContrast); jPanelControls.add(jPanelFontAntialias); jPanelSizeControls.setMinimumSize(new java.awt.Dimension(580, 50)); jPanelSizeControls.setPreferredSize(new java.awt.Dimension(580, 50)); jLabelSize.setText("Size"); jLabelSize.setPreferredSize(new java.awt.Dimension(40, 16)); jPanelSizeControls.add(jLabelSize); jSliderSize.setMajorTickSpacing(10); jSliderSize.setMinorTickSpacing(1); jSliderSize.setPaintLabels(true); jSliderSize.setPaintTicks(true); jSliderSize.setValue(12); jSliderSize.setBorder(new javax.swing.border.EmptyBorder(new java.awt.Insets(0, 0, 10, 0))); jSliderSize.setMinimumSize(new java.awt.Dimension(600, 53)); jSliderSize.setPreferredSize(new java.awt.Dimension(510, 53)); jSliderSize.addChangeListener(new javax.swing.event.ChangeListener() { public void stateChanged(javax.swing.event.ChangeEvent evt) { jSliderSizeStateChanged(evt); } }); jPanelSizeControls.add(jSliderSize); jPanelControls.add(jPanelSizeControls); getContentPane().add(jPanelControls, java.awt.BorderLayout.NORTH); jPanelStatus.setBackground(new java.awt.Color(204, 255, 255)); jPanelStatus.setPreferredSize(new java.awt.Dimension(700, 70)); jLabelDefaultAA.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); jLabelDefaultAA.setBorder(new javax.swing.border.TitledBorder("Default Antialias (JRE)")); jLabelDefaultAA.setPreferredSize(new java.awt.Dimension(165, 50)); jPanelStatus.add(jLabelDefaultAA); jLabelDesktopAA.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); jLabelDesktopAA.setBorder(new javax.swing.border.TitledBorder("Desktop Antialias (Swing)")); jLabelDesktopAA.setPreferredSize(new java.awt.Dimension(165, 50)); jPanelStatus.add(jLabelDesktopAA); jLabelRenderingAA.setForeground(new java.awt.Color(0, 0, 255)); jLabelRenderingAA.setHorizontalAlignment(javax.swing.SwingConstants.CENTER); jLabelRenderingAA.setBorder(new javax.swing.border.TitledBorder("Rendering Antialias")); jLabelRenderingAA.setPreferredSize(new java.awt.Dimension(165, 50)); jPanelStatus.add(jLabelRenderingAA); getContentPane().add(jPanelStatus, java.awt.BorderLayout.SOUTH); pack(); }//GEN-END:initComponents private void jSliderContrastStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_jSliderContrastStateChanged // Add your handling code here: JSlider source = (JSlider)evt.getSource(); lcdContrast = Integer.valueOf(source.getValue()); repaint(); }//GEN-LAST:event_jSliderContrastStateChanged private void jComboBoxAntialiasActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jComboBoxAntialiasActionPerformed // Add your handling code here: JComboBox cb = (JComboBox)evt.getSource(); antiAliasType = ((AAValues)cb.getSelectedItem()).getHint(); boolean enabled = AAValues.isLCDMode(cb.getSelectedItem()); jSliderContrast.setEnabled(enabled); repaint(); }//GEN-LAST:event_jComboBoxAntialiasActionPerformed private void jComboBoxStyleMenuActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jComboBoxStyleMenuActionPerformed // Add your handling code here: JComboBox cb = (JComboBox)evt.getSource(); fontStyle = fontStyles[cb.getSelectedIndex()]; repaint(); }//GEN-LAST:event_jComboBoxStyleMenuActionPerformed private void jComboBoxFontMenuActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jComboBoxFontMenuActionPerformed // Add your handling code here: JComboBox cb = (JComboBox)evt.getSource(); fontName = (String)cb.getSelectedItem(); repaint(); }//GEN-LAST:event_jComboBoxFontMenuActionPerformed private void jSliderSizeStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_jSliderSizeStateChanged // Add your handling code here: JSlider source = (JSlider)evt.getSource(); int value = (int)(source.getValue()); fontSize=value; repaint(); }//GEN-LAST:event_jSliderSizeStateChanged /** Exit the Application */ private void exitForm(java.awt.event.WindowEvent evt) {//GEN-FIRST:event_exitForm System.exit(0); }//GEN-LAST:event_exitForm final Color testFgColor = new Color(0.65f, 0.78f, 0.99f); final Color testBgColor = new Color(0.15f, 0.15f, 0.15f); /** Font rendering panel */ private class TextPanel extends JPanel { private Font font = null; public void paintComponent(Graphics g) { super.paintComponent(g); int width = getWidth(); int height = getHeight(); Image img; Graphics2D g2Image; if (useVolatile.isSelected()) { VolatileImage v = this.getGraphicsConfiguration().createCompatibleVolatileImage(width, height, Transparency.OPAQUE); img = v; g2Image = v.createGraphics(); } else { BufferedImage b = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); g2Image = b.createGraphics(); img = b; } g2Image.setColor(Color.white); g2Image.fillRect(0, 0, width, height); g2Image.setColor(Color.black); // Determine if using user provided font or resident font if ( isUserFont(fontName) ) { font = getUserFont(fontName); font = font.deriveFont(fontStyle, fontSize); } else { font = new Font(fontName, fontStyle, fontSize); } g2Image.setFont(font); g2Image.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, antiAliasType); g2Image.setRenderingHint(KEY_TEXT_LCD_CONTRAST, lcdContrast); final FontMetrics m = g2Image.getFontMetrics(); final Rectangle2D b = m.getStringBounds(textString, g2Image); g2Image.translate(10, 10); g2Image.drawString(textString, (int)(-b.getX()), (int)(-b.getY())); // Dynamically update antialias mode BufferedImage test = null; if ((Image)img instanceof BufferedImage) { test = (BufferedImage)((Image)img); } else if (((Image)img) instanceof VolatileImage) { test = ((VolatileImage)((Image)img)).getSnapshot(); } if (test != null) { setTextPanelBufferedImage(test); } // try other colors // white on black g2Image.translate(0, b.getHeight() + 10 - b.getY()); g2Image.setColor(Color.black); g2Image.fill(b); g2Image.setColor(Color.white); g2Image.drawString(textString, 0, 0); g2Image.translate(0, b.getHeight() + 10); g2Image.setColor(testBgColor); g2Image.fill(b); g2Image.setColor(testFgColor); g2Image.drawString(textString, 0, 0); g2Image.dispose(); Graphics2D g2d = (Graphics2D)g; g2d.drawImage(img, 0, 0, this); // Notify any waiters (when run in auto mode) that rendering has completed Toolkit.getDefaultToolkit().sync(); synchronized (lockObject) { available = true; lockObject.notifyAll(); } } } /** * @param args the command line arguments */ public static void main(String args[]) { boolean runAuto = false; AntialiasDemo demo = new AntialiasDemo(); try { Thread.sleep(2000); } catch (Exception e1) { } for (int i = 0; i < args.length; i++) { if (args[i].equals("-auto")) { runAuto = true; continue; } } // Example for running in automated mode if (runAuto == true ) { for (int i = 5; i <= 27; i = i + 2) { BufferedImage img = demo.runAutoTest("Lucida Sans", Font.ITALIC, i, "GASP", 180); if (img != null) { System.out.println("Font size = " + i + " Antialias detected = " + demo.getAntialiasMode(img)); } } System.exit(0); } } // ******************************************************* // ************* Test Automation Methods ***************** // ******************************************************* /** * Method for automated testing to render a particular font configuration * Returns the rendering as BufferedImage * * Optionally the returned BufferedImage can be tested for Antialiasing setting * and/or saved to an image file. */ public BufferedImage runAutoTest(String fontName, int fontStyle, int fontSize, String antialias, int contrast) { final String testFontName = fontName; final int testFontStyle = fontStyle; final int testFontSize = fontSize; final int testContrast = contrast; final String testAntialias = antialias; try { Thread.sleep(200); } catch (Exception e1) { } available = false; try{ javax.swing.SwingUtilities.invokeAndWait(new Runnable() { public void run() { // Set font attributes for test. Events are triggered for each JComponent update jComboBoxFontMenu.setSelectedItem(testFontName); jComboBoxStyleMenu.setSelectedIndex(testFontStyle); jSliderSize.setValue(testFontSize); AAValues aa = (AAValues)AAValues.getValue(testAntialias); jComboBoxAntialias.setSelectedItem(aa); jSliderContrast.setValue(testContrast); } }); } catch (Exception ex) { throw new RuntimeException("AntialiasDemo: runAutoTest method error in running test"); } // Wait for rendering to complete and return synchronized (lockObject) { while (available == false) { try { lockObject.wait(5000); // timeout after 5 seconds break; } catch (Exception e1) { e1.printStackTrace(); } } } return getTextPanelBufferedImage(); } /** * Method for automated testing to change the default rendered text string */ public void setTextString(String textString) { this.textString = textString; } /** * Clear all fonts from the Font Selection ComboBox, including any user added fonts * * The Font Selection ComboBox will be cleared and then populated with provided * Java logical fonts. Current selected font will be set to Dialog. */ public void clearFontList() { jComboBoxFontMenu.removeAllItems(); jComboBoxFontMenu.addItem("Dialog"); jComboBoxFontMenu.addItem("Serif"); jComboBoxFontMenu.addItem("Sans-serif"); jComboBoxFontMenu.addItem("Monospaced"); jComboBoxFontMenu.addItem("DialogInput"); jComboBoxFontMenu.setSelectedItem("Dialog"); if (userFonts != null) userFonts = null; } /** * Get all fonts from the Font Selection ComboBox, including any user added fonts */ public Set getFontList() { HashSet fontList = new HashSet(); int fontItems = jComboBoxFontMenu.getItemCount(); for ( int i = 0; i < fontItems; i++ ) { String fontName = (String)jComboBoxFontMenu.getItemAt(i); fontList.add(fontName); } return fontList; } /** * Add user font to the Font Selection ComboBox * * The user font will not be added if it already exists in the Font Selector */ public void addUserFont(Font font) { // Check for duplicate entry before adding HashSet fontItems = (HashSet)getFontList(); String fontName = font.getFontName(); if ( !fontItems.contains( fontName ) ) { if (userFonts == null) userFonts = new HashMap(); userFonts.put(fontName,font); jComboBoxFontMenu.addItem(fontName); } } /** * Check for user added font */ public boolean isUserFont(String fontName) { boolean userFont = false; if (userFonts != null) userFont = userFonts.containsKey(fontName); return userFont; } /** * Return user added font */ public Font getUserFont(String fontName) { Font userFont = null; if ( isUserFont(fontName) ) { userFont = userFonts.get(fontName); } return userFont; } /** * Returns current Desktop Antialias Setting */ public String getDesktopAntialiasStatus() { return jLabelDesktopAA.getText(); } /** * Returns antialias status for the current font rendering */ public String getRenderingAntialiasStatus() { return jLabelRenderingAA.getText(); } /** * Save BufferedImage to PNG file */ public void saveFontPanelImage(BufferedImage img, File file) { if(img != null) { try { ImageIO.write(img, "PNG", file); } catch (Exception e) { throw new RuntimeException("Could not write image file"); } } else { throw new RuntimeException("BufferedImage was set to null"); } } // Variables declaration - do not modify//GEN-BEGIN:variables private javax.swing.JComboBox jComboBoxAntialias; private javax.swing.JComboBox jComboBoxFontMenu; private javax.swing.JComboBox jComboBoxStyleMenu; private javax.swing.JComboBox jComboBoxDestMenu; private javax.swing.JLabel jLabelAntialias; private javax.swing.JLabel jLabelContrast; private javax.swing.JLabel jLabelDefaultAA; private javax.swing.JLabel jLabelDesktopAA; private javax.swing.JLabel jLabelFont; private javax.swing.JLabel jLabelRenderingAA; private javax.swing.JLabel jLabelSize; private javax.swing.JLabel jLabelStyle; private javax.swing.JLabel jLabelDestination; private javax.swing.JPanel jPanelControls; private javax.swing.JPanel jPanelFontAntialias; private javax.swing.JPanel jPanelFontSelection; private javax.swing.JPanel jPanelSizeControls; private javax.swing.JPanel jPanelStatus; private javax.swing.JSlider jSliderContrast; private javax.swing.JSlider jSliderSize; private JCheckBox useVolatile; // End of variables declaration//GEN-END:variables }