/* * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * - Neither the name of Oracle nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/* * This source code is provided to illustrate the usage of a given feature * or technique and has been deliberately simplified. Additional steps * required for a production-quality application, such as security checks, * input validation and proper error handling, might not be present in * this sample code.
*/
/// JFrame that will contain Font2DTest privatefinal JFrame parent; /// FontPanel class that will contain all graphical output privatefinal FontPanel fp; /// RangeMenu class that contains info about the unicode ranges privatefinal RangeMenu rm;
/// Other menus to set parameters for text drawing privatefinal ChoiceV2 fontMenu; privatefinal JTextField sizeField; privatefinal ChoiceV2 styleMenu; privatefinal ChoiceV2 textMenu; privateint currentTextChoice = 0; privatefinal ChoiceV2 transformMenu; privatefinal ChoiceV2 transformMenuG2; privatefinal ChoiceV2 methodsMenu; privatefinal JComboBox<FontPanel.AAValues> antiAliasMenu; privatefinal JComboBox<FontPanel.FMValues> fracMetricsMenu;
// Enabled or disabled status of canDisplay check privatestaticboolean canDisplayCheck = true;
/// Initialize GUI variables and its layouts public Font2DTest( JFrame f) {
parent = f;
rm = new RangeMenu( this, parent );
fp = new FontPanel( this, parent );
statusBar = new LabelV2("");
fontMenu = new ChoiceV2( this, canDisplayCheck );
sizeField = new JTextField( "12", 3 );
sizeField.addActionListener( this );
styleMenu = new ChoiceV2( this );
textMenu = new ChoiceV2( ); // listener added later
transformMenu = new ChoiceV2( this );
transformMenuG2 = new ChoiceV2( this );
methodsMenu = new ChoiceV2( this );
antiAliasMenu = new JComboBox<>(FontPanel.AAValues.values());
antiAliasMenu.addActionListener(this);
fracMetricsMenu = new JComboBox<>(FontPanel.FMValues.values());
fracMetricsMenu.addActionListener(this);
/// Adds a component to a container with a label to its left in GridBagLayout privatevoid addLabeledComponentToGBL( String name,
JComponent c,
GridBagLayout gbl,
GridBagConstraints gbc,
Container target ) {
LabelV2 l = new LabelV2( name );
GridBagConstraints gbcLabel = (GridBagConstraints) gbc.clone();
gbcLabel.insets = new Insets( 2, 2, 2, 0 );
gbcLabel.gridwidth = 1;
gbcLabel.weightx = 0;
if ( c == null )
c = new JLabel( "" );
gbl.setConstraints( l, gbcLabel );
target.add( l );
gbl.setConstraints( c, gbc );
target.add( c );
}
/// Sets up menu entries privatevoid setupMenu() {
JMenu fileMenu = new JMenu( "File" );
JMenu optionMenu = new JMenu( "Option" );
fileMenu.add( new MenuItemV2( "Save Selected Options...", this ));
fileMenu.add( new MenuItemV2( "Load Options...", this ));
fileMenu.addSeparator();
fileMenu.add( new MenuItemV2( "Save as PNG...", this ));
fileMenu.add( new MenuItemV2( "Load PNG File to Compare...", this ));
fileMenu.add( new MenuItemV2( "Page Setup...", this ));
fileMenu.add( new MenuItemV2( "Print...", this ));
fileMenu.addSeparator();
fileMenu.add( new MenuItemV2( "Exit", this ));
displayGridCBMI = new CheckboxMenuItemV2( "Display Grid", true, this );
force16ColsCBMI = new CheckboxMenuItemV2( "Force 16 Columns", false, this );
showFontInfoCBMI = new CheckboxMenuItemV2( "Display Font Info", false, this );
optionMenu.add( displayGridCBMI );
optionMenu.add( force16ColsCBMI );
optionMenu.add( showFontInfoCBMI );
JMenuBar mb = parent.getJMenuBar(); if ( mb == null )
mb = new JMenuBar();
mb.add( fileMenu );
mb.add( optionMenu );
textMenu.addItem( "Unicode Range" );
textMenu.addItem( "All Glyphs" );
textMenu.addItem( "User Text" );
textMenu.addItem( "Text File" );
textMenu.addActionListener ( this ); // listener added later so unneeded events not thrown
}
/// Sets up the all dialogs used in Font2DTest... privatevoid setupDialog() {
filePromptDialog = new JFileChooser();
/// Prepare user text dialog...
userTextDialog = new JDialog( parent, "User Text", false );
JPanel dialogTopPanel = new JPanel();
JPanel dialogBottomPanel = new JPanel();
LabelV2 message1 = new LabelV2( "Enter text below and then press update" );
LabelV2 message2 = new LabelV2( "(Unicode char can be denoted by \\uXXXX)" );
LabelV2 message3 = new LabelV2( "(Supplementary chars can be denoted by \\UXXXXXX)" );
userTextArea = new JTextArea( "Font2DTest!" );
ButtonV2 bUpdate = new ButtonV2( "Update", this );
userTextArea.setFont( new Font( "dialog", Font.PLAIN, 12 ));
dialogTopPanel.setLayout( new GridLayout( 3, 1 ));
dialogTopPanel.add( message1 );
dialogTopPanel.add( message2 );
dialogTopPanel.add( message3 );
dialogBottomPanel.add( bUpdate ); //ABP
JScrollPane userTextAreaSP = new JScrollPane(userTextArea);
userTextAreaSP.setPreferredSize(new Dimension(300, 100));
userTextDialog.getContentPane().setLayout( new BorderLayout() );
userTextDialog.getContentPane().add( "North", dialogTopPanel );
userTextDialog.getContentPane().add( "Center", userTextAreaSP );
userTextDialog.getContentPane().add( "South", dialogBottomPanel );
userTextDialog.pack();
userTextDialog.addWindowListener( new WindowAdapter() { publicvoid windowClosing( WindowEvent e ) {
userTextDialog.setVisible(false);
}
});
/// Prepare printing dialog...
printCBGroup = new ButtonGroup();
printModeCBs[ fp.ONE_PAGE ] = new JRadioButton( "Print one page from currently displayed character/line", true );
printModeCBs[ fp.CUR_RANGE ] = new JRadioButton( "Print all characters in currently selected range", false );
printModeCBs[ fp.ALL_TEXT ] = new JRadioButton( "Print all lines of text", false );
LabelV2 l = new LabelV2( "Note: Page range in native \"Print\" dialog will not affect the result" );
JPanel buttonPanel = new JPanel();
printModeCBs[ fp.ALL_TEXT ].setEnabled( false );
buttonPanel.add( new ButtonV2( "Print", this ));
buttonPanel.add( new ButtonV2( "Cancel", this ));
printDialog = new JDialog( parent, "Print...", true );
printDialog.setResizable( false );
printDialog.addWindowListener( new WindowAdapter() { publicvoid windowClosing( WindowEvent e ) {
printDialog.setVisible(false);
}
});
printDialog.getContentPane().setLayout( new GridLayout( printModeCBs.length + 2, 1 ));
printDialog.getContentPane().add( l ); for ( int i = 0; i < printModeCBs.length; i++ ) {
printCBGroup.add( printModeCBs[i] );
printDialog.getContentPane().add( printModeCBs[i] );
}
printDialog.getContentPane().add( buttonPanel );
printDialog.pack();
/// Prepare font information dialog...
fontInfoDialog = new JDialog( parent, "Font info", false );
fontInfoDialog.setResizable( false );
fontInfoDialog.addWindowListener( new WindowAdapter() { publicvoid windowClosing( WindowEvent e ) {
fontInfoDialog.setVisible(false);
showFontInfoCBMI.setState( false );
}
});
JPanel fontInfoPanel = new JPanel();
fontInfoPanel.setLayout( new GridLayout( fontInfos.length, 1 )); for ( int i = 0; i < fontInfos.length; i++ ) {
fontInfos[i] = new LabelV2("");
fontInfoPanel.add( fontInfos[i] );
}
fontInfoDialog.getContentPane().add( fontInfoPanel );
/// Move the location of the dialog...
userTextDialog.setLocation( 200, 300 );
fontInfoDialog.setLocation( 0, 400 );
}
/// RangeMenu object signals using this function /// when Unicode range has been changed and text needs to be redrawn publicvoid fireRangeChanged() { int[] range = rm.getSelectedRange();
fp.setTextToDraw( fp.RANGE_TEXT, range, null, null ); if(canDisplayCheck) {
setupFontList(range[0], range[1]);
} if ( showFontInfoCBMI.getState() )
fireUpdateFontInfo();
}
/// Changes the message on the status bar publicvoid fireChangeStatus( String message, boolean error ) {
statusBar.setText( message ); if ( error )
fp.showingError = true; else
fp.showingError = false;
}
/// Updates the information about the selected font publicvoid fireUpdateFontInfo() { if ( showFontInfoCBMI.getState() ) {
String[] infos = fp.getFontInfo(); for ( int i = 0; i < fontInfos.length; i++ )
fontInfos[i].setText( infos[i] );
fontInfoDialog.pack();
}
}
privatevoid setupFontList(int rangeStart, int rangeEnd) {
int listCount = fontMenu.getItemCount(); int size = 16;
try {
size = Float.valueOf(sizeField.getText()).intValue();
} catch ( Exception e ) {
System.out.println("Invalid font size in the size textField. Using default value of 16");
}
int style = fontStyles[styleMenu.getSelectedIndex()];
Font f; for (int i = 0; i < listCount; i++) {
String fontName = fontMenu.getItemAt(i);
f = new Font(fontName, style, size); if ((rm.getSelectedIndex() != RangeMenu.SURROGATES_AREA_INDEX) &&
canDisplayRange(f, rangeStart, rangeEnd)) {
fontMenu.setBit(i, true);
} else {
fontMenu.setBit(i, false);
}
}
fontMenu.repaint();
}
protectedboolean canDisplayRange(Font font, int rangeStart, int rangeEnd) { for (int i = rangeStart; i < rangeEnd; i++) { if (font.canDisplay(i)) { returntrue;
}
} returnfalse;
}
/// Displays a file load/save dialog and returns the specified file private String promptFile( boolean isSave, String initFileName ) { int retVal;
String str;
/// ABP if ( filePromptDialog == null) returnnull;
/// Converts user text into arrays of String, delimited at newline character /// Also replaces any valid escape sequence with appropriate unicode character /// Support \\UXXXXXX notation for surrogates private String[] parseUserText( String orig ) { int length = orig.length();
StringTokenizer perLine = new StringTokenizer( orig, "\n" );
String[] textLines = new String[ perLine.countTokens() ]; int lineNumber = 0;
while ( perLine.hasMoreElements() ) {
StringBuffer converted = new StringBuffer();
String oneLine = perLine.nextToken(); int lineLength = oneLine.length(); int prevEscapeEnd = 0; int nextEscape = -1; do { int nextBMPEscape = oneLine.indexOf( "\\u", prevEscapeEnd ); int nextSupEscape = oneLine.indexOf( "\\U", prevEscapeEnd );
nextEscape = (nextBMPEscape < 0)
? ((nextSupEscape < 0)
? -1
: nextSupEscape)
: ((nextSupEscape < 0)
? nextBMPEscape
: Math.min(nextBMPEscape, nextSupEscape));
if ( nextEscape != -1 ) { if ( prevEscapeEnd < nextEscape )
converted.append( oneLine.substring( prevEscapeEnd, nextEscape ));
/// Reads the text from specified file, detecting UTF-16 encoding /// Then breaks the text into String array, delimited at every line break privatevoid readTextFile( String fileName ) { try {
String fileText;
String[] textLines;
BufferedInputStream bis = new BufferedInputStream( new FileInputStream( fileName )); int numBytes = bis.available(); if (numBytes == 0) { thrownew Exception("Text file " + fileName + " is empty");
} byte[] byteData = newbyte[ numBytes ];
bis.read( byteData, 0, numBytes );
bis.close();
/// If byte mark is found, then use UTF-16 encoding to convert bytes... if (numBytes >= 2 &&
(( byteData[0] == (byte) 0xFF && byteData[1] == (byte) 0xFE ) ||
( byteData[0] == (byte) 0xFE && byteData[1] == (byte) 0xFF )))
fileText = new String(byteData, UTF_16); /// Otherwise, use system default encoding else
fileText = new String( byteData );
int length = fileText.length();
StringTokenizer perLine = new StringTokenizer( fileText, "\n" ); /// Determine "Return Char" used in this file /// This simply finds first occurrence of CR, CR+LF or LF... for ( int i = 0; i < length; i++ ) { char iTh = fileText.charAt( i ); if ( iTh == '\r' ) { if ( i < length - 1 && fileText.charAt( i + 1 ) == '\n' )
perLine = new StringTokenizer( fileText, "\r\n" ); else
perLine = new StringTokenizer( fileText, "\r" ); break;
} elseif ( iTh == '\n' ) /// Use the one already created break;
} int lineNumber = 0, numLines = perLine.countTokens();
textLines = new String[ numLines ];
while ( perLine.hasMoreElements() ) {
String oneLine = perLine.nextToken(); if ( oneLine == null ) /// To make LineBreakMeasurer to return a valid TextLayout /// on an empty line, simply feed it a space char...
oneLine = " ";
textLines[ lineNumber++ ] = oneLine;
}
fp.setTextToDraw( fp.FILE_TEXT, null, null, textLines );
rm.setEnabled( false );
methodsMenu.setEnabled( false );
} catch ( Exception ex ) {
fireChangeStatus( "ERROR: Failed to Read Text File; See Stack Trace", true );
ex.printStackTrace();
}
}
/// Returns a String storing current configuration privatevoid writeCurrentOptions( String fileName ) { try {
String curOptions = fp.getCurrentOptions();
BufferedOutputStream bos = new BufferedOutputStream( new FileOutputStream( fileName )); /// Prepend title and the option that is only obtainable here int[] range = rm.getSelectedRange();
String completeOptions =
( "Font2DTest Option File\n" +
displayGridCBMI.getState() + "\n" +
force16ColsCBMI.getState() + "\n" +
showFontInfoCBMI.getState() + "\n" +
rm.getSelectedItem() + "\n" +
range[0] + "\n" + range[1] + "\n" + curOptions + tFileName); byte[] toBeWritten = completeOptions.getBytes(UTF_16);
bos.write( toBeWritten, 0, toBeWritten.length );
bos.close();
} catch ( Exception ex ) {
fireChangeStatus( "ERROR: Failed to Save Options File; See Stack Trace", true );
ex.printStackTrace();
}
}
/// Updates GUI visibility/status after some parameters have changed privatevoid updateGUI() { int selectedText = textMenu.getSelectedIndex();
/// Set the visibility of User Text dialog if ( selectedText == fp.USER_TEXT )
userTextDialog.setVisible(true); else
userTextDialog.setVisible(false); /// Change the visibility/status/availability of Print JDialog buttons
printModeCBs[ fp.ONE_PAGE ].setSelected( true ); if ( selectedText == fp.FILE_TEXT || selectedText == fp.USER_TEXT ) { /// ABP /// update methodsMenu to show that TextLayout.draw is being used /// when we are in FILE_TEXT mode if ( selectedText == fp.FILE_TEXT )
methodsMenu.setSelectedItem("TextLayout.draw");
methodsMenu.setEnabled( selectedText == fp.USER_TEXT );
printModeCBs[ fp.CUR_RANGE ].setEnabled( false );
printModeCBs[ fp.ALL_TEXT ].setEnabled( true );
} else { /// ABP /// update methodsMenu to show that drawGlyph is being used /// when we are in ALL_GLYPHS mode if ( selectedText == fp.ALL_GLYPHS )
methodsMenu.setSelectedItem("drawGlyphVector");
methodsMenu.setEnabled( selectedText == fp.RANGE_TEXT );
printModeCBs[ fp.CUR_RANGE ].setEnabled( true );
printModeCBs[ fp.ALL_TEXT ].setEnabled( false );
} /// Modify RangeMenu and fontInfo label availabilty if ( selectedText == fp.RANGE_TEXT ) {
fontInfos[1].setVisible( true );
rm.setEnabled( true );
} else {
fontInfos[1].setVisible( false );
rm.setEnabled( false );
}
}
/// Loads saved options and applies them privatevoid loadOptions( String fileName ) { try {
BufferedInputStream bis = new BufferedInputStream( new FileInputStream( fileName )); int numBytes = bis.available(); byte[] byteData = newbyte[ numBytes ];
bis.read( byteData, 0, numBytes );
bis.close(); if ( numBytes < 2 ||
(byteData[0] != (byte) 0xFE || byteData[1] != (byte) 0xFF) ) thrownew Exception( "Not a Font2DTest options file" );
String options = new String(byteData, UTF_16);
StringTokenizer perLine = new StringTokenizer( options, "\n" );
String title = perLine.nextToken(); if ( !title.equals( "Font2DTest Option File" )) thrownew Exception( "Not a Font2DTest options file" );
/// Parse all options boolean displayGridOpt = Boolean.parseBoolean( perLine.nextToken() ); boolean force16ColsOpt = Boolean.parseBoolean( perLine.nextToken() ); boolean showFontInfoOpt = Boolean.parseBoolean( perLine.nextToken() );
String rangeNameOpt = perLine.nextToken(); int rangeStartOpt = Integer.parseInt( perLine.nextToken() ); int rangeEndOpt = Integer.parseInt( perLine.nextToken() );
String fontNameOpt = perLine.nextToken(); float fontSizeOpt = Float.parseFloat( perLine.nextToken() ); int fontStyleOpt = Integer.parseInt( perLine.nextToken() ); int fontTransformOpt = Integer.parseInt( perLine.nextToken() ); int g2TransformOpt = Integer.parseInt( perLine.nextToken() ); int textToUseOpt = Integer.parseInt( perLine.nextToken() ); int drawMethodOpt = Integer.parseInt( perLine.nextToken() ); int antialiasOpt = Integer.parseInt(perLine.nextToken()); int fractionalOpt = Integer.parseInt(perLine.nextToken()); int lcdContrast = Integer.parseInt(perLine.nextToken());
String[] userTextOpt = { "Font2DTest!" };
String dialogEntry = "Font2DTest!"; if (textToUseOpt == fp.USER_TEXT ) { int numLines = perLine.countTokens(), lineNumber = 0; if ( numLines != 0 ) {
userTextOpt = new String[ numLines ];
dialogEntry = ""; for ( ; perLine.hasMoreElements(); lineNumber++ ) {
userTextOpt[ lineNumber ] = perLine.nextToken();
dialogEntry += userTextOpt[ lineNumber ] + "\n";
}
}
}
UIManager.put("swing.boldMetal", Boolean.FALSE); final JFrame f = new JFrame( "Font2DTest" ); final Font2DTest f2dt = new Font2DTest( f);
f.addWindowListener( new WindowAdapter() { publicvoid windowOpening( WindowEvent e ) { f2dt.repaint(); } publicvoid windowClosing( WindowEvent e ) { System.exit(0); }
});
/// Class to display just an image file /// Used to show the comparison PNG image privatefinalclass ImagePanel extends JPanel { privatefinal BufferedImage bi;
public ImagePanel( BufferedImage image ) {
bi = image;
}
public Dimension getPreferredSize() { returnnew Dimension( bi.getWidth(), bi.getHeight() );
}
publicvoid paintComponent( Graphics g ) {
g.drawImage( bi, 0, 0, this );
}
}
/// Classes made to avoid repetitive calls... (being lazy) privatefinalclass ButtonV2 extends JButton { public ButtonV2( String name, ActionListener al ) { super( name ); this.addActionListener( al );
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.