Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/demo/jfc/Font2DTest/Font2DTest.java
38829 views
/*1* Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.2*3* Redistribution and use in source and binary forms, with or without4* modification, are permitted provided that the following conditions5* are met:6*7* - Redistributions of source code must retain the above copyright8* notice, this list of conditions and the following disclaimer.9*10* - Redistributions in binary form must reproduce the above copyright11* notice, this list of conditions and the following disclaimer in the12* documentation and/or other materials provided with the distribution.13*14* - Neither the name of Oracle nor the names of its15* contributors may be used to endorse or promote products derived16* from this software without specific prior written permission.17*18* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS19* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,20* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR21* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR22* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,23* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,24* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR25* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF26* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING27* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS28* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.29*/3031/*32* This source code is provided to illustrate the usage of a given feature33* or technique and has been deliberately simplified. Additional steps34* required for a production-quality application, such as security checks,35* input validation and proper error handling, might not be present in36* this sample code.37*/38394041import java.awt.Color;42import java.awt.Component;43import java.awt.BorderLayout;44import java.awt.CheckboxGroup;45import java.awt.Container;46import java.awt.Dimension;47import java.awt.Font;48import java.awt.Graphics;49import java.awt.Graphics2D;50import java.awt.GraphicsEnvironment;51import java.awt.GridBagConstraints;52import java.awt.GridBagLayout;53import java.awt.GridLayout;54import java.awt.Insets;55import java.awt.RenderingHints;56import java.awt.Toolkit;57import java.awt.event.ActionEvent;58import java.awt.event.ActionListener;59import java.awt.event.ItemEvent;60import java.awt.event.ItemListener;61import java.awt.event.WindowAdapter;62import java.awt.event.WindowEvent;63import java.awt.image.BufferedImage;64import java.io.BufferedInputStream;65import java.io.BufferedOutputStream;66import java.io.File;67import java.io.FileInputStream;68import java.io.FileOutputStream;69import java.util.EnumSet;70import java.util.StringTokenizer;71import java.util.BitSet;72import javax.swing.*;73import javax.swing.event.*;7475/**76* Font2DTest.java77*78* @author Shinsuke Fukuda79* @author Ankit Patel [Conversion to Swing - 01/07/30]80*/8182/// Main Font2DTest Class8384public final class Font2DTest extends JPanel85implements ActionListener, ItemListener, ChangeListener {8687/// JFrame that will contain Font2DTest88private final JFrame parent;89/// FontPanel class that will contain all graphical output90private final FontPanel fp;91/// RangeMenu class that contains info about the unicode ranges92private final RangeMenu rm;9394/// Other menus to set parameters for text drawing95private final ChoiceV2 fontMenu;96private final JTextField sizeField;97private final ChoiceV2 styleMenu;98private final ChoiceV2 textMenu;99private int currentTextChoice = 0;100private final ChoiceV2 transformMenu;101private final ChoiceV2 transformMenuG2;102private final ChoiceV2 methodsMenu;103private final JComboBox antiAliasMenu;104private final JComboBox fracMetricsMenu;105106private final JSlider contrastSlider;107108/// CheckboxMenuItems109private CheckboxMenuItemV2 displayGridCBMI;110private CheckboxMenuItemV2 force16ColsCBMI;111private CheckboxMenuItemV2 showFontInfoCBMI;112113/// JDialog boxes114private JDialog userTextDialog;115private JTextArea userTextArea;116private JDialog printDialog;117private JDialog fontInfoDialog;118private LabelV2 fontInfos[] = new LabelV2[2];119private JFileChooser filePromptDialog = null;120121private ButtonGroup printCBGroup;122private JRadioButton printModeCBs[] = new JRadioButton[3];123124/// Status bar125private final LabelV2 statusBar;126127private int fontStyles [] = {Font.PLAIN, Font.BOLD, Font.ITALIC, Font.BOLD | Font.ITALIC};128129/// Text filename130private String tFileName;131132// Enabled or disabled status of canDisplay check133private static boolean canDisplayCheck = true;134135/// Initialize GUI variables and its layouts136public Font2DTest( JFrame f, boolean isApplet ) {137parent = f;138139rm = new RangeMenu( this, parent );140fp = new FontPanel( this, parent );141statusBar = new LabelV2("");142143fontMenu = new ChoiceV2( this, canDisplayCheck );144sizeField = new JTextField( "12", 3 );145sizeField.addActionListener( this );146styleMenu = new ChoiceV2( this );147textMenu = new ChoiceV2( ); // listener added later148transformMenu = new ChoiceV2( this );149transformMenuG2 = new ChoiceV2( this );150methodsMenu = new ChoiceV2( this );151152antiAliasMenu =153new JComboBox(EnumSet.allOf(FontPanel.AAValues.class).toArray());154antiAliasMenu.addActionListener(this);155fracMetricsMenu =156new JComboBox(EnumSet.allOf(FontPanel.FMValues.class).toArray());157fracMetricsMenu.addActionListener(this);158159contrastSlider = new JSlider(JSlider.HORIZONTAL, 100, 250,160FontPanel.getDefaultLCDContrast().intValue());161contrastSlider.setEnabled(false);162contrastSlider.setMajorTickSpacing(20);163contrastSlider.setMinorTickSpacing(10);164contrastSlider.setPaintTicks(true);165contrastSlider.setPaintLabels(true);166contrastSlider.addChangeListener(this);167setupPanel();168setupMenu( isApplet );169setupDialog( isApplet );170171if(canDisplayCheck) {172fireRangeChanged();173}174}175176/// Set up the main interface panel177private void setupPanel() {178GridBagLayout gbl = new GridBagLayout();179GridBagConstraints gbc = new GridBagConstraints();180gbc.fill = GridBagConstraints.HORIZONTAL;181gbc.weightx = 1;182gbc.insets = new Insets( 2, 0, 2, 2 );183this.setLayout( gbl );184185addLabeledComponentToGBL( "Font: ", fontMenu, gbl, gbc, this );186addLabeledComponentToGBL( "Size: ", sizeField, gbl, gbc, this );187gbc.gridwidth = GridBagConstraints.REMAINDER;188addLabeledComponentToGBL( "Font Transform:",189transformMenu, gbl, gbc, this );190gbc.gridwidth = 1;191192addLabeledComponentToGBL( "Range: ", rm, gbl, gbc, this );193addLabeledComponentToGBL( "Style: ", styleMenu, gbl, gbc, this );194gbc.gridwidth = GridBagConstraints.REMAINDER;195addLabeledComponentToGBL( "Graphics Transform: ",196transformMenuG2, gbl, gbc, this );197gbc.gridwidth = 1;198199gbc.anchor = GridBagConstraints.WEST;200addLabeledComponentToGBL( "Method: ", methodsMenu, gbl, gbc, this );201addLabeledComponentToGBL("", null, gbl, gbc, this);202gbc.anchor = GridBagConstraints.EAST;203gbc.gridwidth = GridBagConstraints.REMAINDER;204addLabeledComponentToGBL( "Text to use:", textMenu, gbl, gbc, this );205206gbc.weightx=1;207gbc.gridwidth = 1;208gbc.fill = GridBagConstraints.HORIZONTAL;209gbc.anchor = GridBagConstraints.WEST;210addLabeledComponentToGBL("LCD contrast: ",211contrastSlider, gbl, gbc, this);212213gbc.gridwidth = 1;214gbc.fill = GridBagConstraints.NONE;215addLabeledComponentToGBL("Antialiasing: ",216antiAliasMenu, gbl, gbc, this);217218gbc.anchor = GridBagConstraints.EAST;219gbc.gridwidth = GridBagConstraints.REMAINDER;220addLabeledComponentToGBL("Fractional metrics: ",221fracMetricsMenu, gbl, gbc, this);222223gbc.weightx = 1;224gbc.weighty = 1;225gbc.anchor = GridBagConstraints.WEST;226gbc.insets = new Insets( 2, 0, 0, 2 );227gbc.fill = GridBagConstraints.BOTH;228gbl.setConstraints( fp, gbc );229this.add( fp );230231gbc.weighty = 0;232gbc.insets = new Insets( 0, 2, 0, 0 );233gbl.setConstraints( statusBar, gbc );234this.add( statusBar );235}236237/// Adds a component to a container with a label to its left in GridBagLayout238private void addLabeledComponentToGBL( String name,239JComponent c,240GridBagLayout gbl,241GridBagConstraints gbc,242Container target ) {243LabelV2 l = new LabelV2( name );244GridBagConstraints gbcLabel = (GridBagConstraints) gbc.clone();245gbcLabel.insets = new Insets( 2, 2, 2, 0 );246gbcLabel.gridwidth = 1;247gbcLabel.weightx = 0;248249if ( c == null )250c = new JLabel( "" );251252gbl.setConstraints( l, gbcLabel );253target.add( l );254gbl.setConstraints( c, gbc );255target.add( c );256}257258/// Sets up menu entries259private void setupMenu( boolean isApplet ) {260JMenu fileMenu = new JMenu( "File" );261JMenu optionMenu = new JMenu( "Option" );262263fileMenu.add( new MenuItemV2( "Save Selected Options...", this ));264fileMenu.add( new MenuItemV2( "Load Options...", this ));265fileMenu.addSeparator();266fileMenu.add( new MenuItemV2( "Save as PNG...", this ));267fileMenu.add( new MenuItemV2( "Load PNG File to Compare...", this ));268fileMenu.add( new MenuItemV2( "Page Setup...", this ));269fileMenu.add( new MenuItemV2( "Print...", this ));270fileMenu.addSeparator();271if ( !isApplet )272fileMenu.add( new MenuItemV2( "Exit", this ));273else274fileMenu.add( new MenuItemV2( "Close", this ));275276displayGridCBMI = new CheckboxMenuItemV2( "Display Grid", true, this );277force16ColsCBMI = new CheckboxMenuItemV2( "Force 16 Columns", false, this );278showFontInfoCBMI = new CheckboxMenuItemV2( "Display Font Info", false, this );279optionMenu.add( displayGridCBMI );280optionMenu.add( force16ColsCBMI );281optionMenu.add( showFontInfoCBMI );282283JMenuBar mb = parent.getJMenuBar();284if ( mb == null )285mb = new JMenuBar();286mb.add( fileMenu );287mb.add( optionMenu );288289parent.setJMenuBar( mb );290291String fontList[] =292GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();293294for ( int i = 0; i < fontList.length; i++ )295fontMenu.addItem( fontList[i] );296fontMenu.setSelectedItem( "Dialog" );297298styleMenu.addItem( "Plain" );299styleMenu.addItem( "Bold" );300styleMenu.addItem( "Italic" );301styleMenu.addItem( "Bold Italic" );302303transformMenu.addItem( "None" );304transformMenu.addItem( "Scale" );305transformMenu.addItem( "Shear" );306transformMenu.addItem( "Rotate" );307308transformMenuG2.addItem( "None" );309transformMenuG2.addItem( "Scale" );310transformMenuG2.addItem( "Shear" );311transformMenuG2.addItem( "Rotate" );312313methodsMenu.addItem( "drawString" );314methodsMenu.addItem( "drawChars" );315methodsMenu.addItem( "drawBytes" );316methodsMenu.addItem( "drawGlyphVector" );317methodsMenu.addItem( "TextLayout.draw" );318methodsMenu.addItem( "GlyphVector.getOutline + draw" );319methodsMenu.addItem( "TextLayout.getOutline + draw" );320321textMenu.addItem( "Unicode Range" );322textMenu.addItem( "All Glyphs" );323textMenu.addItem( "User Text" );324textMenu.addItem( "Text File" );325textMenu.addActionListener ( this ); // listener added later so unneeded events not thrown326}327328/// Sets up the all dialogs used in Font2DTest...329private void setupDialog( boolean isApplet ) {330if (!isApplet)331filePromptDialog = new JFileChooser( );332else333filePromptDialog = null;334335/// Prepare user text dialog...336userTextDialog = new JDialog( parent, "User Text", false );337JPanel dialogTopPanel = new JPanel();338JPanel dialogBottomPanel = new JPanel();339LabelV2 message1 = new LabelV2( "Enter text below and then press update" );340LabelV2 message2 = new LabelV2( "(Unicode char can be denoted by \\uXXXX)" );341LabelV2 message3 = new LabelV2( "(Supplementary chars can be denoted by \\UXXXXXX)" );342userTextArea = new JTextArea( "Font2DTest!" );343ButtonV2 bUpdate = new ButtonV2( "Update", this );344userTextArea.setFont( new Font( "dialog", Font.PLAIN, 12 ));345dialogTopPanel.setLayout( new GridLayout( 3, 1 ));346dialogTopPanel.add( message1 );347dialogTopPanel.add( message2 );348dialogTopPanel.add( message3 );349dialogBottomPanel.add( bUpdate );350//ABP351JScrollPane userTextAreaSP = new JScrollPane(userTextArea);352userTextAreaSP.setPreferredSize(new Dimension(300, 100));353354userTextDialog.getContentPane().setLayout( new BorderLayout() );355userTextDialog.getContentPane().add( "North", dialogTopPanel );356userTextDialog.getContentPane().add( "Center", userTextAreaSP );357userTextDialog.getContentPane().add( "South", dialogBottomPanel );358userTextDialog.pack();359userTextDialog.addWindowListener( new WindowAdapter() {360public void windowClosing( WindowEvent e ) {361userTextDialog.hide();362}363});364365/// Prepare printing dialog...366printCBGroup = new ButtonGroup();367printModeCBs[ fp.ONE_PAGE ] =368new JRadioButton( "Print one page from currently displayed character/line",369true );370printModeCBs[ fp.CUR_RANGE ] =371new JRadioButton( "Print all characters in currently selected range",372false );373printModeCBs[ fp.ALL_TEXT ] =374new JRadioButton( "Print all lines of text",375false );376LabelV2 l =377new LabelV2( "Note: Page range in native \"Print\" dialog will not affect the result" );378JPanel buttonPanel = new JPanel();379printModeCBs[ fp.ALL_TEXT ].setEnabled( false );380buttonPanel.add( new ButtonV2( "Print", this ));381buttonPanel.add( new ButtonV2( "Cancel", this ));382383printDialog = new JDialog( parent, "Print...", true );384printDialog.setResizable( false );385printDialog.addWindowListener( new WindowAdapter() {386public void windowClosing( WindowEvent e ) {387printDialog.hide();388}389});390printDialog.getContentPane().setLayout( new GridLayout( printModeCBs.length + 2, 1 ));391printDialog.getContentPane().add( l );392for ( int i = 0; i < printModeCBs.length; i++ ) {393printCBGroup.add( printModeCBs[i] );394printDialog.getContentPane().add( printModeCBs[i] );395}396printDialog.getContentPane().add( buttonPanel );397printDialog.pack();398399/// Prepare font information dialog...400fontInfoDialog = new JDialog( parent, "Font info", false );401fontInfoDialog.setResizable( false );402fontInfoDialog.addWindowListener( new WindowAdapter() {403public void windowClosing( WindowEvent e ) {404fontInfoDialog.hide();405showFontInfoCBMI.setState( false );406}407});408JPanel fontInfoPanel = new JPanel();409fontInfoPanel.setLayout( new GridLayout( fontInfos.length, 1 ));410for ( int i = 0; i < fontInfos.length; i++ ) {411fontInfos[i] = new LabelV2("");412fontInfoPanel.add( fontInfos[i] );413}414fontInfoDialog.getContentPane().add( fontInfoPanel );415416/// Move the location of the dialog...417userTextDialog.setLocation( 200, 300 );418fontInfoDialog.setLocation( 0, 400 );419}420421/// RangeMenu object signals using this function422/// when Unicode range has been changed and text needs to be redrawn423public void fireRangeChanged() {424int range[] = rm.getSelectedRange();425fp.setTextToDraw( fp.RANGE_TEXT, range, null, null );426if(canDisplayCheck) {427setupFontList(range[0], range[1]);428}429if ( showFontInfoCBMI.getState() )430fireUpdateFontInfo();431}432433/// Changes the message on the status bar434public void fireChangeStatus( String message, boolean error ) {435/// If this is not ran as an applet, use own status bar,436/// Otherwise, use the appletviewer/browser's status bar437statusBar.setText( message );438if ( error )439fp.showingError = true;440else441fp.showingError = false;442}443444/// Updates the information about the selected font445public void fireUpdateFontInfo() {446if ( showFontInfoCBMI.getState() ) {447String infos[] = fp.getFontInfo();448for ( int i = 0; i < fontInfos.length; i++ )449fontInfos[i].setText( infos[i] );450fontInfoDialog.pack();451}452}453454private void setupFontList(int rangeStart, int rangeEnd) {455456int listCount = fontMenu.getItemCount();457int size = 16;458459try {460size = Float.valueOf(sizeField.getText()).intValue();461}462catch ( Exception e ) {463System.out.println("Invalid font size in the size textField. Using default value of 16");464}465466int style = fontStyles[styleMenu.getSelectedIndex()];467Font f;468for (int i = 0; i < listCount; i++) {469String fontName = (String)fontMenu.getItemAt(i);470f = new Font(fontName, style, size);471if ((rm.getSelectedIndex() != RangeMenu.SURROGATES_AREA_INDEX) &&472canDisplayRange(f, rangeStart, rangeEnd)) {473fontMenu.setBit(i, true);474}475else {476fontMenu.setBit(i, false);477}478}479480fontMenu.repaint();481}482483protected boolean canDisplayRange(Font font, int rangeStart, int rangeEnd) {484for (int i = rangeStart; i < rangeEnd; i++) {485if (font.canDisplay(i)) {486return true;487}488}489return false;490}491492/// Displays a file load/save dialog and returns the specified file493private String promptFile( boolean isSave, String initFileName ) {494int retVal;495String str;496497/// ABP498if ( filePromptDialog == null)499return null;500501if ( isSave ) {502filePromptDialog.setDialogType( JFileChooser.SAVE_DIALOG );503filePromptDialog.setDialogTitle( "Save..." );504str = "Save";505506507}508else {509filePromptDialog.setDialogType( JFileChooser.OPEN_DIALOG );510filePromptDialog.setDialogTitle( "Load..." );511str = "Load";512}513514if (initFileName != null)515filePromptDialog.setSelectedFile( new File( initFileName ) );516retVal = filePromptDialog.showDialog( this, str );517518if ( retVal == JFileChooser.APPROVE_OPTION ) {519File file = filePromptDialog.getSelectedFile();520String fileName = file.getAbsolutePath();521if ( fileName != null ) {522return fileName;523}524}525526return null;527}528529/// Converts user text into arrays of String, delimited at newline character530/// Also replaces any valid escape sequence with appropriate unicode character531/// Support \\UXXXXXX notation for surrogates532private String[] parseUserText( String orig ) {533int length = orig.length();534StringTokenizer perLine = new StringTokenizer( orig, "\n" );535String textLines[] = new String[ perLine.countTokens() ];536int lineNumber = 0;537538while ( perLine.hasMoreElements() ) {539StringBuffer converted = new StringBuffer();540String oneLine = perLine.nextToken();541int lineLength = oneLine.length();542int prevEscapeEnd = 0;543int nextEscape = -1;544do {545int nextBMPEscape = oneLine.indexOf( "\\u", prevEscapeEnd );546int nextSupEscape = oneLine.indexOf( "\\U", prevEscapeEnd );547nextEscape = (nextBMPEscape < 0)548? ((nextSupEscape < 0)549? -1550: nextSupEscape)551: ((nextSupEscape < 0)552? nextBMPEscape553: Math.min(nextBMPEscape, nextSupEscape));554555if ( nextEscape != -1 ) {556if ( prevEscapeEnd < nextEscape )557converted.append( oneLine.substring( prevEscapeEnd, nextEscape ));558559prevEscapeEnd = nextEscape + (nextEscape == nextBMPEscape ? 6 : 8);560try {561String hex = oneLine.substring( nextEscape + 2, prevEscapeEnd );562if (nextEscape == nextBMPEscape) {563converted.append( (char) Integer.parseInt( hex, 16 ));564} else {565converted.append( new String( Character.toChars( Integer.parseInt( hex, 16 ))));566}567}568catch ( Exception e ) {569int copyLimit = Math.min(lineLength, prevEscapeEnd);570converted.append( oneLine.substring( nextEscape, copyLimit ));571}572}573} while (nextEscape != -1);574if ( prevEscapeEnd < lineLength )575converted.append( oneLine.substring( prevEscapeEnd, lineLength ));576textLines[ lineNumber++ ] = converted.toString();577}578return textLines;579}580581/// Reads the text from specified file, detecting UTF-16 encoding582/// Then breaks the text into String array, delimited at every line break583private void readTextFile( String fileName ) {584try {585String fileText, textLines[];586BufferedInputStream bis =587new BufferedInputStream( new FileInputStream( fileName ));588int numBytes = bis.available();589if (numBytes == 0) {590throw new Exception("Text file " + fileName + " is empty");591}592byte byteData[] = new byte[ numBytes ];593bis.read( byteData, 0, numBytes );594bis.close();595596/// If byte mark is found, then use UTF-16 encoding to convert bytes...597if (numBytes >= 2 &&598(( byteData[0] == (byte) 0xFF && byteData[1] == (byte) 0xFE ) ||599( byteData[0] == (byte) 0xFE && byteData[1] == (byte) 0xFF )))600fileText = new String( byteData, "UTF-16" );601/// Otherwise, use system default encoding602else603fileText = new String( byteData );604605int length = fileText.length();606StringTokenizer perLine = new StringTokenizer( fileText, "\n" );607/// Determine "Return Char" used in this file608/// This simply finds first occurrence of CR, CR+LF or LF...609for ( int i = 0; i < length; i++ ) {610char iTh = fileText.charAt( i );611if ( iTh == '\r' ) {612if ( i < length - 1 && fileText.charAt( i + 1 ) == '\n' )613perLine = new StringTokenizer( fileText, "\r\n" );614else615perLine = new StringTokenizer( fileText, "\r" );616break;617}618else if ( iTh == '\n' )619/// Use the one already created620break;621}622int lineNumber = 0, numLines = perLine.countTokens();623textLines = new String[ numLines ];624625while ( perLine.hasMoreElements() ) {626String oneLine = perLine.nextToken();627if ( oneLine == null )628/// To make LineBreakMeasurer to return a valid TextLayout629/// on an empty line, simply feed it a space char...630oneLine = " ";631textLines[ lineNumber++ ] = oneLine;632}633fp.setTextToDraw( fp.FILE_TEXT, null, null, textLines );634rm.setEnabled( false );635methodsMenu.setEnabled( false );636}637catch ( Exception ex ) {638fireChangeStatus( "ERROR: Failed to Read Text File; See Stack Trace", true );639ex.printStackTrace();640}641}642643/// Returns a String storing current configuration644private void writeCurrentOptions( String fileName ) {645try {646String curOptions = fp.getCurrentOptions();647BufferedOutputStream bos =648new BufferedOutputStream( new FileOutputStream( fileName ));649/// Prepend title and the option that is only obtainable here650int range[] = rm.getSelectedRange();651String completeOptions =652( "Font2DTest Option File\n" +653displayGridCBMI.getState() + "\n" +654force16ColsCBMI.getState() + "\n" +655showFontInfoCBMI.getState() + "\n" +656rm.getSelectedItem() + "\n" +657range[0] + "\n" + range[1] + "\n" + curOptions + tFileName);658byte toBeWritten[] = completeOptions.getBytes( "UTF-16" );659bos.write( toBeWritten, 0, toBeWritten.length );660bos.close();661}662catch ( Exception ex ) {663fireChangeStatus( "ERROR: Failed to Save Options File; See Stack Trace", true );664ex.printStackTrace();665}666}667668/// Updates GUI visibility/status after some parameters have changed669private void updateGUI() {670int selectedText = textMenu.getSelectedIndex();671672/// Set the visibility of User Text dialog673if ( selectedText == fp.USER_TEXT )674userTextDialog.show();675else676userTextDialog.hide();677/// Change the visibility/status/availability of Print JDialog buttons678printModeCBs[ fp.ONE_PAGE ].setSelected( true );679if ( selectedText == fp.FILE_TEXT || selectedText == fp.USER_TEXT ) {680/// ABP681/// update methodsMenu to show that TextLayout.draw is being used682/// when we are in FILE_TEXT mode683if ( selectedText == fp.FILE_TEXT )684methodsMenu.setSelectedItem("TextLayout.draw");685methodsMenu.setEnabled( selectedText == fp.USER_TEXT );686printModeCBs[ fp.CUR_RANGE ].setEnabled( false );687printModeCBs[ fp.ALL_TEXT ].setEnabled( true );688}689else {690/// ABP691/// update methodsMenu to show that drawGlyph is being used692/// when we are in ALL_GLYPHS mode693if ( selectedText == fp.ALL_GLYPHS )694methodsMenu.setSelectedItem("drawGlyphVector");695methodsMenu.setEnabled( selectedText == fp.RANGE_TEXT );696printModeCBs[ fp.CUR_RANGE ].setEnabled( true );697printModeCBs[ fp.ALL_TEXT ].setEnabled( false );698}699/// Modify RangeMenu and fontInfo label availabilty700if ( selectedText == fp.RANGE_TEXT ) {701fontInfos[1].setVisible( true );702rm.setEnabled( true );703}704else {705fontInfos[1].setVisible( false );706rm.setEnabled( false );707}708}709710/// Loads saved options and applies them711private void loadOptions( String fileName ) {712try {713BufferedInputStream bis =714new BufferedInputStream( new FileInputStream( fileName ));715int numBytes = bis.available();716byte byteData[] = new byte[ numBytes ];717bis.read( byteData, 0, numBytes );718bis.close();719if ( numBytes < 2 ||720(byteData[0] != (byte) 0xFE || byteData[1] != (byte) 0xFF) )721throw new Exception( "Not a Font2DTest options file" );722723String options = new String( byteData, "UTF-16" );724StringTokenizer perLine = new StringTokenizer( options, "\n" );725String title = perLine.nextToken();726if ( !title.equals( "Font2DTest Option File" ))727throw new Exception( "Not a Font2DTest options file" );728729/// Parse all options730boolean displayGridOpt = Boolean.parseBoolean( perLine.nextToken() );731boolean force16ColsOpt = Boolean.parseBoolean( perLine.nextToken() );732boolean showFontInfoOpt = Boolean.parseBoolean( perLine.nextToken() );733String rangeNameOpt = perLine.nextToken();734int rangeStartOpt = Integer.parseInt( perLine.nextToken() );735int rangeEndOpt = Integer.parseInt( perLine.nextToken() );736String fontNameOpt = perLine.nextToken();737float fontSizeOpt = Float.parseFloat( perLine.nextToken() );738int fontStyleOpt = Integer.parseInt( perLine.nextToken() );739int fontTransformOpt = Integer.parseInt( perLine.nextToken() );740int g2TransformOpt = Integer.parseInt( perLine.nextToken() );741int textToUseOpt = Integer.parseInt( perLine.nextToken() );742int drawMethodOpt = Integer.parseInt( perLine.nextToken() );743int antialiasOpt = Integer.parseInt(perLine.nextToken());744int fractionalOpt = Integer.parseInt(perLine.nextToken());745int lcdContrast = Integer.parseInt(perLine.nextToken());746String userTextOpt[] = { "Font2DTest!" };747String dialogEntry = "Font2DTest!";748if (textToUseOpt == fp.USER_TEXT ) {749int numLines = perLine.countTokens(), lineNumber = 0;750if ( numLines != 0 ) {751userTextOpt = new String[ numLines ];752dialogEntry = "";753for ( ; perLine.hasMoreElements(); lineNumber++ ) {754userTextOpt[ lineNumber ] = perLine.nextToken();755dialogEntry += userTextOpt[ lineNumber ] + "\n";756}757}758}759760/// Reset GUIs761displayGridCBMI.setState( displayGridOpt );762force16ColsCBMI.setState( force16ColsOpt );763showFontInfoCBMI.setState( showFontInfoOpt );764rm.setSelectedRange( rangeNameOpt, rangeStartOpt, rangeEndOpt );765fontMenu.setSelectedItem( fontNameOpt );766sizeField.setText( String.valueOf( fontSizeOpt ));767styleMenu.setSelectedIndex( fontStyleOpt );768transformMenu.setSelectedIndex( fontTransformOpt );769transformMenuG2.setSelectedIndex( g2TransformOpt );770textMenu.setSelectedIndex( textToUseOpt );771methodsMenu.setSelectedIndex( drawMethodOpt );772antiAliasMenu.setSelectedIndex( antialiasOpt );773fracMetricsMenu.setSelectedIndex( fractionalOpt );774contrastSlider.setValue(lcdContrast);775776userTextArea.setText( dialogEntry );777updateGUI();778779if ( textToUseOpt == fp.FILE_TEXT ) {780tFileName = perLine.nextToken();781readTextFile(tFileName );782}783784/// Reset option variables and repaint785fp.loadOptions( displayGridOpt, force16ColsOpt,786rangeStartOpt, rangeEndOpt,787fontNameOpt, fontSizeOpt,788fontStyleOpt, fontTransformOpt, g2TransformOpt,789textToUseOpt, drawMethodOpt,790antialiasOpt, fractionalOpt,791lcdContrast, userTextOpt );792if ( showFontInfoOpt ) {793fireUpdateFontInfo();794fontInfoDialog.show();795}796else797fontInfoDialog.hide();798}799catch ( Exception ex ) {800fireChangeStatus( "ERROR: Failed to Load Options File; See Stack Trace", true );801ex.printStackTrace();802}803}804805/// Loads a previously saved image806private void loadComparisonPNG( String fileName ) {807try {808BufferedImage image =809javax.imageio.ImageIO.read(new File(fileName));810JFrame f = new JFrame( "Comparison PNG" );811ImagePanel ip = new ImagePanel( image );812f.setResizable( false );813f.getContentPane().add( ip );814f.addWindowListener( new WindowAdapter() {815public void windowClosing( WindowEvent e ) {816( (JFrame) e.getSource() ).dispose();817}818});819f.pack();820f.show();821}822catch ( Exception ex ) {823fireChangeStatus( "ERROR: Failed to Load PNG File; See Stack Trace", true );824ex.printStackTrace();825}826}827828/// Interface functions...829830/// ActionListener interface function831/// Responds to JMenuItem, JTextField and JButton actions832public void actionPerformed( ActionEvent e ) {833Object source = e.getSource();834835if ( source instanceof JMenuItem ) {836JMenuItem mi = (JMenuItem) source;837String itemName = mi.getText();838839if ( itemName.equals( "Save Selected Options..." )) {840String fileName = promptFile( true, "options.txt" );841if ( fileName != null )842writeCurrentOptions( fileName );843}844else if ( itemName.equals( "Load Options..." )) {845String fileName = promptFile( false, "options.txt" );846if ( fileName != null )847loadOptions( fileName );848}849else if ( itemName.equals( "Save as PNG..." )) {850String fileName = promptFile( true, fontMenu.getSelectedItem() + ".png" );851if ( fileName != null )852fp.doSavePNG( fileName );853}854else if ( itemName.equals( "Load PNG File to Compare..." )) {855String fileName = promptFile( false, null );856if ( fileName != null )857loadComparisonPNG( fileName );858}859else if ( itemName.equals( "Page Setup..." ))860fp.doPageSetup();861else if ( itemName.equals( "Print..." ))862printDialog.show();863else if ( itemName.equals( "Close" ))864parent.dispose();865else if ( itemName.equals( "Exit" ))866System.exit(0);867}868869else if ( source instanceof JTextField ) {870JTextField tf = (JTextField) source;871float sz = 12f;872try {873sz = Float.parseFloat(sizeField.getText());874if (sz < 1f || sz > 120f) {875sz = 12f;876sizeField.setText("12");877}878} catch (Exception se) {879sizeField.setText("12");880}881if ( tf == sizeField )882fp.setFontParams( fontMenu.getSelectedItem(),883sz,884styleMenu.getSelectedIndex(),885transformMenu.getSelectedIndex() );886}887888else if ( source instanceof JButton ) {889String itemName = ( (JButton) source ).getText();890/// Print dialog buttons...891if ( itemName.equals( "Print" )) {892for ( int i = 0; i < printModeCBs.length; i++ )893if ( printModeCBs[i].isSelected() ) {894printDialog.hide();895fp.doPrint( i );896}897}898else if ( itemName.equals( "Cancel" ))899printDialog.hide();900/// Update button from Usert Text JDialog...901else if ( itemName.equals( "Update" ))902fp.setTextToDraw( fp.USER_TEXT, null,903parseUserText( userTextArea.getText() ), null );904}905else if ( source instanceof JComboBox ) {906JComboBox c = (JComboBox) source;907908/// RangeMenu handles actions by itself and then calls fireRangeChanged,909/// so it is not listed or handled here910if ( c == fontMenu || c == styleMenu || c == transformMenu ) {911float sz = 12f;912try {913sz = Float.parseFloat(sizeField.getText());914if (sz < 1f || sz > 120f) {915sz = 12f;916sizeField.setText("12");917}918} catch (Exception se) {919sizeField.setText("12");920}921fp.setFontParams(fontMenu.getSelectedItem(),922sz,923styleMenu.getSelectedIndex(),924transformMenu.getSelectedIndex());925} else if ( c == methodsMenu )926fp.setDrawMethod( methodsMenu.getSelectedIndex() );927else if ( c == textMenu ) {928929if(canDisplayCheck) {930fireRangeChanged();931}932933int selected = textMenu.getSelectedIndex();934935if ( selected == fp.RANGE_TEXT )936fp.setTextToDraw( fp.RANGE_TEXT, rm.getSelectedRange(),937null, null );938else if ( selected == fp.USER_TEXT )939fp.setTextToDraw( fp.USER_TEXT, null,940parseUserText( userTextArea.getText() ), null );941else if ( selected == fp.FILE_TEXT ) {942String fileName = promptFile( false, null );943if ( fileName != null ) {944tFileName = fileName;945readTextFile( fileName );946} else {947/// User cancelled selection; reset to previous choice948c.setSelectedIndex( currentTextChoice );949return;950}951}952else if ( selected == fp.ALL_GLYPHS )953fp.setTextToDraw( fp.ALL_GLYPHS, null, null, null );954955updateGUI();956currentTextChoice = selected;957}958else if ( c == transformMenuG2 ) {959fp.setTransformG2( transformMenuG2.getSelectedIndex() );960}961else if (c == antiAliasMenu || c == fracMetricsMenu) {962if (c == antiAliasMenu) {963boolean enabled = FontPanel.AAValues.964isLCDMode(antiAliasMenu.getSelectedItem());965contrastSlider.setEnabled(enabled);966}967fp.setRenderingHints(antiAliasMenu.getSelectedItem(),968fracMetricsMenu.getSelectedItem(),969contrastSlider.getValue());970}971}972}973974public void stateChanged(ChangeEvent e) {975Object source = e.getSource();976if (source instanceof JSlider) {977fp.setRenderingHints(antiAliasMenu.getSelectedItem(),978fracMetricsMenu.getSelectedItem(),979contrastSlider.getValue());980}981}982983/// ItemListener interface function984/// Responds to JCheckBoxMenuItem, JComboBox and JCheckBox actions985public void itemStateChanged( ItemEvent e ) {986Object source = e.getSource();987988if ( source instanceof JCheckBoxMenuItem ) {989JCheckBoxMenuItem cbmi = (JCheckBoxMenuItem) source;990if ( cbmi == displayGridCBMI )991fp.setGridDisplay( displayGridCBMI.getState() );992else if ( cbmi == force16ColsCBMI )993fp.setForce16Columns( force16ColsCBMI.getState() );994else if ( cbmi == showFontInfoCBMI ) {995if ( showFontInfoCBMI.getState() ) {996fireUpdateFontInfo();997fontInfoDialog.show();998}999else1000fontInfoDialog.hide();1001}1002}1003}10041005private static void printUsage() {1006String usage = "Usage: java -jar Font2DTest.jar [options]\n" +1007"\nwhere options include:\n" +1008" -dcdc | -disablecandisplaycheck disable canDisplay check for font\n" +1009" -? | -help print this help message\n" +1010"\nExample :\n" +1011" To disable canDisplay check on font for ranges\n" +1012" java -jar Font2DTest.jar -dcdc";1013System.out.println(usage);1014System.exit(0);1015}10161017/// Main function1018public static void main(String argv[]) {10191020if(argv.length > 0) {1021if(argv[0].equalsIgnoreCase("-disablecandisplaycheck") ||1022argv[0].equalsIgnoreCase("-dcdc")) {1023canDisplayCheck = false;1024}1025else {1026printUsage();1027}1028}10291030UIManager.put("swing.boldMetal", Boolean.FALSE);1031final JFrame f = new JFrame( "Font2DTest" );1032final Font2DTest f2dt = new Font2DTest( f, false );1033f.addWindowListener( new WindowAdapter() {1034public void windowOpening( WindowEvent e ) { f2dt.repaint(); }1035public void windowClosing( WindowEvent e ) { System.exit(0); }1036});10371038f.getContentPane().add( f2dt );1039f.pack();1040f.show();1041}10421043/// Inner class definitions...10441045/// Class to display just an image file1046/// Used to show the comparison PNG image1047private final class ImagePanel extends JPanel {1048private final BufferedImage bi;10491050public ImagePanel( BufferedImage image ) {1051bi = image;1052}10531054public Dimension getPreferredSize() {1055return new Dimension( bi.getWidth(), bi.getHeight() );1056}10571058public void paintComponent( Graphics g ) {1059g.drawImage( bi, 0, 0, this );1060}1061}10621063/// Classes made to avoid repetitive calls... (being lazy)1064private final class ButtonV2 extends JButton {1065public ButtonV2( String name, ActionListener al ) {1066super( name );1067this.addActionListener( al );1068}1069}10701071private final class ChoiceV2 extends JComboBox {10721073private BitSet bitSet = null;10741075public ChoiceV2() {;}10761077public ChoiceV2( ActionListener al ) {1078super();1079this.addActionListener( al );1080}10811082public ChoiceV2( ActionListener al, boolean fontChoice) {1083this(al);1084if(fontChoice) {1085//Register this component in ToolTipManager1086setToolTipText("");1087bitSet = new BitSet();1088setRenderer(new ChoiceV2Renderer(this));1089}1090}10911092public String getToolTipText() {1093int index = this.getSelectedIndex();1094String fontName = (String) this.getSelectedItem();1095if(fontName != null &&1096(textMenu.getSelectedIndex() == fp.RANGE_TEXT)) {1097if (getBit(index)) {1098return "Font \"" + fontName + "\" can display some characters in \"" +1099rm.getSelectedItem() + "\" range";1100}1101else {1102return "Font \"" + fontName + "\" cannot display any characters in \"" +1103rm.getSelectedItem() + "\" range";1104}1105}1106return super.getToolTipText();1107}11081109public void setBit(int bitIndex, boolean value) {1110bitSet.set(bitIndex, value);1111}11121113public boolean getBit(int bitIndex) {1114return bitSet.get(bitIndex);1115}1116}11171118private final class ChoiceV2Renderer extends DefaultListCellRenderer {11191120private ImageIcon yesImage, blankImage;1121private ChoiceV2 choice = null;11221123public ChoiceV2Renderer(ChoiceV2 choice) {1124BufferedImage yes =1125new BufferedImage(10, 10, BufferedImage.TYPE_INT_ARGB);1126Graphics2D g = yes.createGraphics();1127g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,1128RenderingHints.VALUE_ANTIALIAS_ON);1129g.setColor(Color.BLUE);1130g.drawLine(0, 5, 3, 10);1131g.drawLine(1, 5, 4, 10);1132g.drawLine(3, 10, 10, 0);1133g.drawLine(4, 9, 9, 0);1134g.dispose();1135BufferedImage blank =1136new BufferedImage(10, 10, BufferedImage.TYPE_INT_ARGB);1137yesImage = new ImageIcon(yes);1138blankImage = new ImageIcon(blank);1139this.choice = choice;1140}11411142public Component getListCellRendererComponent(JList list,1143Object value,1144int index,1145boolean isSelected,1146boolean cellHasFocus) {11471148if(textMenu.getSelectedIndex() == fp.RANGE_TEXT) {11491150super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);11511152//For JComboBox if index is -1, its rendering the selected index.1153if(index == -1) {1154index = choice.getSelectedIndex();1155}11561157if(choice.getBit(index)) {1158setIcon(yesImage);1159}1160else {1161setIcon(blankImage);1162}11631164} else {1165super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);1166setIcon(blankImage);1167}11681169return this;1170}1171}11721173private final class LabelV2 extends JLabel {1174public LabelV2( String name ) {1175super( name );1176}1177}11781179private final class MenuItemV2 extends JMenuItem {1180public MenuItemV2( String name, ActionListener al ) {1181super( name );1182this.addActionListener( al );1183}1184}11851186private final class CheckboxMenuItemV2 extends JCheckBoxMenuItem {1187public CheckboxMenuItemV2( String name, boolean b, ItemListener il ) {1188super( name, b );1189this.addItemListener( il );1190}1191}1192}119311941195