/*
 * 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.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<String,Font> 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<Integer> pixelVals = new LinkedHashSet<Integer>();
        for (int p=0;p<pixels.length;p++) {
            pixelVals.add(pixels[p]);
        }

        // If two or less colors detected (black and white), return AA_OFF
        if (pixelVals.size() <= 2)
            return AA_OFF;

        // If more than two colors, then determine if the set of colors are all
        // gray for AA_ON, or if there are non-grey colors for AA_LCD
        //
        // Gray pixels have no dominant color so red, green, blue values match
        Object[] colors = pixelVals.toArray();
        for (int i=0; i<colors.length; i++) {
            int rgb = ((Integer)colors[i]).intValue();
            Color color = new Color(rgb);
            int red = color.getRed();
            int green = color.getGreen();
            int blue = color.getBlue();
            if ( !(red == green && red == blue) )
                return AA_LCD;
        }
        return AA_ON;
    }

    /**
     * Method for determining the antialias mode of Default Antialias
     *
     * The antialias setting for VALUE_TEXT_ANTIALIAS_DEFAULT is set by the JRE.
     * The default is compared to possible values and the status is updated.
     */
    private void setDefaultAntialiasStatus() {
        Object defaultAA = AAValues.getNonDefaultValue( VALUE_TEXT_ANTIALIAS_DEFAULT );
        jLabelDefaultAA.setText(defaultAA.toString());
    }

    /**
     * Method for determining the actual Desktop Antialias setting
     * This antialias value is automatically applied to Swing Components
     *
     * Note: Some platforms may not support desktop antialias property
     */
    private void setDesktopAntialiasStatus() {
        Map hints = (Map)tk.getDesktopProperty(dtprop);
        if (hints != null) {
            Object desktopAA = AAValues.getNonDefaultValue( hints.get(KEY_TEXT_ANTIALIASING) );
            jLabelDesktopAA.setText(desktopAA.toString());
        } else {
            jLabelDesktopAA.setText(DESKTOP_HINT_UNAVAILABLE);
        }
    }

    /**
     * Listener for OS changes in antialias desktop property
     */
    private void desktopAntialiasPropertyStateChanged(PropertyChangeEvent e) {
        System.out.println("PropertyChangeEvent: " + e.getPropertyName()+
            "\n   old value =" + e.getOldValue()+
            "\n   new value =" + e.getNewValue());
        setDesktopAntialiasStatus();
    }

    /**
     * Updates BufferedImage of current font rendering
     */
    private void setTextPanelBufferedImage(BufferedImage img) {
        textPanelImage = img;
        // Check antialias mode used in current rednering and update GUI status
        jLabelRenderingAA.setText( getAntialiasMode(img) );
    }

    /**
     * Gets BufferedImage of current font rendering
     */
    private BufferedImage getTextPanelBufferedImage() {
        return textPanelImage;
    }

    /**
     * Enumeration for Antialias values
     * (this section was copied from Font2DTest and updated)
     */
    enum AAValues {
        AADEFAULT("DEFAULT",  VALUE_TEXT_ANTIALIAS_DEFAULT),
        AAOFF    ("OFF",      VALUE_TEXT_ANTIALIAS_OFF),
        AAON     ("ON",       VALUE_TEXT_ANTIALIAS_ON),
        AAGASP   ("GASP",     VALUE_TEXT_ANTIALIAS_GASP),
        AALCDHRGB("LCD_HRGB", VALUE_TEXT_ANTIALIAS_LCD_HRGB),
        AALCDHBGR("LCD_HBGR", VALUE_TEXT_ANTIALIAS_LCD_HBGR),
        AALCDVRGB("LCD_VRGB", VALUE_TEXT_ANTIALIAS_LCD_VRGB),
        AALCDVBGR("LCD_VBGR", VALUE_TEXT_ANTIALIAS_LCD_VBGR);

        private String name;
        private Object hint;

        private static AAValues[] valArray;

        AAValues(String s, Object o) {
            name = s;
            hint = o;
        }

        public String toString() {
            return name;
        }

        public Object getHint() {
            return hint;
        }

        public static boolean isLCDMode(Object o) {
            return (o instanceof AAValues &&
            ((AAValues)o).ordinal() >= 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<valArray.length;i++) {
                if (valArray[i].toString().equals(name)) {
                    return valArray[i];
                }
            }
            return valArray[0];
        }

        public static Object getNonDefaultValue(Object o) {
            if (valArray == null) {
                valArray = (AAValues[])EnumSet.allOf(AAValues.class).toArray(new AAValues[0]);
            }
            for (int i=1;i<valArray.length;i++) {
                if (valArray[i].getHint() == o) {
                    return valArray[i];
                }
            }
            return valArray[1];
        }

        private static AAValues[] getArray() {
            if (valArray == null) {
                valArray = (AAValues[])(EnumSet.allOf(AAValues.class).toArray(new AAValues[0]));
            }
            return valArray;
        }
    }

    /**
     * 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, 65));
        jPanelFontSelection.setPreferredSize(new java.awt.Dimension(280, 65));
        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);

        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


    /** 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();

            BufferedImage img = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
            Graphics2D g2Image = (Graphics2D)img.getGraphics();

            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);

            g2Image.drawString(textString, 10, 130);

            Graphics2D g2d = (Graphics2D)g;
            g2d.drawImage(img,null,0,0);

            // Dynamically update antialias mode
            setTextPanelBufferedImage(img);

            // 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<String> fontList = new HashSet<String>();

        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<String,Font>();
            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.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.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;
    // End of variables declaration//GEN-END:variables

}
