Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/demo/share/jfc/Font2DTest/Font2DTest.java
41152 views
1
/*
2
* Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
3
*
4
* Redistribution and use in source and binary forms, with or without
5
* modification, are permitted provided that the following conditions
6
* are met:
7
*
8
* - Redistributions of source code must retain the above copyright
9
* notice, this list of conditions and the following disclaimer.
10
*
11
* - Redistributions in binary form must reproduce the above copyright
12
* notice, this list of conditions and the following disclaimer in the
13
* documentation and/or other materials provided with the distribution.
14
*
15
* - Neither the name of Oracle nor the names of its
16
* contributors may be used to endorse or promote products derived
17
* from this software without specific prior written permission.
18
*
19
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
26
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
27
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
*/
31
32
/*
33
* This source code is provided to illustrate the usage of a given feature
34
* or technique and has been deliberately simplified. Additional steps
35
* required for a production-quality application, such as security checks,
36
* input validation and proper error handling, might not be present in
37
* this sample code.
38
*/
39
40
41
42
import java.awt.Color;
43
import java.awt.Component;
44
import java.awt.BorderLayout;
45
import java.awt.CheckboxGroup;
46
import java.awt.Container;
47
import java.awt.Dimension;
48
import java.awt.Font;
49
import java.awt.Graphics;
50
import java.awt.Graphics2D;
51
import java.awt.GraphicsEnvironment;
52
import java.awt.GridBagConstraints;
53
import java.awt.GridBagLayout;
54
import java.awt.GridLayout;
55
import java.awt.Insets;
56
import java.awt.RenderingHints;
57
import java.awt.Toolkit;
58
import java.awt.event.ActionEvent;
59
import java.awt.event.ActionListener;
60
import java.awt.event.ItemEvent;
61
import java.awt.event.ItemListener;
62
import java.awt.event.WindowAdapter;
63
import java.awt.event.WindowEvent;
64
import java.awt.image.BufferedImage;
65
import java.io.BufferedInputStream;
66
import java.io.BufferedOutputStream;
67
import java.io.File;
68
import java.io.FileInputStream;
69
import java.io.FileOutputStream;
70
import java.util.StringTokenizer;
71
import java.util.BitSet;
72
import javax.swing.*;
73
import javax.swing.event.*;
74
75
/**
76
* Font2DTest.java
77
*
78
* @author Shinsuke Fukuda
79
* @author Ankit Patel [Conversion to Swing - 01/07/30]
80
*/
81
82
/// Main Font2DTest Class
83
84
public final class Font2DTest extends JPanel
85
implements ActionListener, ItemListener, ChangeListener {
86
87
/// JFrame that will contain Font2DTest
88
private final JFrame parent;
89
/// FontPanel class that will contain all graphical output
90
private final FontPanel fp;
91
/// RangeMenu class that contains info about the unicode ranges
92
private final RangeMenu rm;
93
94
/// Other menus to set parameters for text drawing
95
private final ChoiceV2 fontMenu;
96
private final JTextField sizeField;
97
private final ChoiceV2 styleMenu;
98
private final ChoiceV2 textMenu;
99
private int currentTextChoice = 0;
100
private final ChoiceV2 transformMenu;
101
private final ChoiceV2 transformMenuG2;
102
private final ChoiceV2 methodsMenu;
103
private final JComboBox<FontPanel.AAValues> antiAliasMenu;
104
private final JComboBox<FontPanel.FMValues> fracMetricsMenu;
105
106
private final JSlider contrastSlider;
107
108
/// CheckboxMenuItems
109
private CheckboxMenuItemV2 displayGridCBMI;
110
private CheckboxMenuItemV2 force16ColsCBMI;
111
private CheckboxMenuItemV2 showFontInfoCBMI;
112
113
/// JDialog boxes
114
private JDialog userTextDialog;
115
private JTextArea userTextArea;
116
private JDialog printDialog;
117
private JDialog fontInfoDialog;
118
private LabelV2[] fontInfos = new LabelV2[2];
119
private JFileChooser filePromptDialog = null;
120
121
private ButtonGroup printCBGroup;
122
private JRadioButton[] printModeCBs = new JRadioButton[3];
123
124
/// Status bar
125
private final LabelV2 statusBar;
126
127
private int[] fontStyles = {Font.PLAIN, Font.BOLD, Font.ITALIC, Font.BOLD | Font.ITALIC};
128
129
/// Text filename
130
private String tFileName;
131
132
// Enabled or disabled status of canDisplay check
133
private static boolean canDisplayCheck = true;
134
135
/// Initialize GUI variables and its layouts
136
public Font2DTest( JFrame f, boolean isApplet ) {
137
parent = f;
138
139
rm = new RangeMenu( this, parent );
140
fp = new FontPanel( this, parent );
141
statusBar = new LabelV2("");
142
143
fontMenu = new ChoiceV2( this, canDisplayCheck );
144
sizeField = new JTextField( "12", 3 );
145
sizeField.addActionListener( this );
146
styleMenu = new ChoiceV2( this );
147
textMenu = new ChoiceV2( ); // listener added later
148
transformMenu = new ChoiceV2( this );
149
transformMenuG2 = new ChoiceV2( this );
150
methodsMenu = new ChoiceV2( this );
151
152
antiAliasMenu =
153
new JComboBox<>(FontPanel.AAValues.values());
154
antiAliasMenu.addActionListener(this);
155
fracMetricsMenu =
156
new JComboBox<>(FontPanel.FMValues.values());
157
fracMetricsMenu.addActionListener(this);
158
159
contrastSlider = new JSlider(JSlider.HORIZONTAL, 100, 250,
160
FontPanel.getDefaultLCDContrast().intValue());
161
contrastSlider.setEnabled(false);
162
contrastSlider.setMajorTickSpacing(20);
163
contrastSlider.setMinorTickSpacing(10);
164
contrastSlider.setPaintTicks(true);
165
contrastSlider.setPaintLabels(true);
166
contrastSlider.addChangeListener(this);
167
setupPanel();
168
setupMenu( isApplet );
169
setupDialog( isApplet );
170
171
if(canDisplayCheck) {
172
fireRangeChanged();
173
}
174
}
175
176
/// Set up the main interface panel
177
private void setupPanel() {
178
GridBagLayout gbl = new GridBagLayout();
179
GridBagConstraints gbc = new GridBagConstraints();
180
gbc.fill = GridBagConstraints.HORIZONTAL;
181
gbc.weightx = 1;
182
gbc.insets = new Insets( 2, 0, 2, 2 );
183
this.setLayout( gbl );
184
185
addLabeledComponentToGBL( "Font: ", fontMenu, gbl, gbc, this );
186
addLabeledComponentToGBL( "Size: ", sizeField, gbl, gbc, this );
187
gbc.gridwidth = GridBagConstraints.REMAINDER;
188
addLabeledComponentToGBL( "Font Transform:",
189
transformMenu, gbl, gbc, this );
190
gbc.gridwidth = 1;
191
192
addLabeledComponentToGBL( "Range: ", rm, gbl, gbc, this );
193
addLabeledComponentToGBL( "Style: ", styleMenu, gbl, gbc, this );
194
gbc.gridwidth = GridBagConstraints.REMAINDER;
195
addLabeledComponentToGBL( "Graphics Transform: ",
196
transformMenuG2, gbl, gbc, this );
197
gbc.gridwidth = 1;
198
199
gbc.anchor = GridBagConstraints.WEST;
200
addLabeledComponentToGBL( "Method: ", methodsMenu, gbl, gbc, this );
201
addLabeledComponentToGBL("", null, gbl, gbc, this);
202
gbc.anchor = GridBagConstraints.EAST;
203
gbc.gridwidth = GridBagConstraints.REMAINDER;
204
addLabeledComponentToGBL( "Text to use:", textMenu, gbl, gbc, this );
205
206
gbc.weightx=1;
207
gbc.gridwidth = 1;
208
gbc.fill = GridBagConstraints.HORIZONTAL;
209
gbc.anchor = GridBagConstraints.WEST;
210
addLabeledComponentToGBL("LCD contrast: ",
211
contrastSlider, gbl, gbc, this);
212
213
gbc.gridwidth = 1;
214
gbc.fill = GridBagConstraints.NONE;
215
addLabeledComponentToGBL("Antialiasing: ",
216
antiAliasMenu, gbl, gbc, this);
217
218
gbc.anchor = GridBagConstraints.EAST;
219
gbc.gridwidth = GridBagConstraints.REMAINDER;
220
addLabeledComponentToGBL("Fractional metrics: ",
221
fracMetricsMenu, gbl, gbc, this);
222
223
gbc.weightx = 1;
224
gbc.weighty = 1;
225
gbc.anchor = GridBagConstraints.WEST;
226
gbc.insets = new Insets( 2, 0, 0, 2 );
227
gbc.fill = GridBagConstraints.BOTH;
228
gbl.setConstraints( fp, gbc );
229
this.add( fp );
230
231
gbc.weighty = 0;
232
gbc.insets = new Insets( 0, 2, 0, 0 );
233
gbl.setConstraints( statusBar, gbc );
234
this.add( statusBar );
235
}
236
237
/// Adds a component to a container with a label to its left in GridBagLayout
238
private void addLabeledComponentToGBL( String name,
239
JComponent c,
240
GridBagLayout gbl,
241
GridBagConstraints gbc,
242
Container target ) {
243
LabelV2 l = new LabelV2( name );
244
GridBagConstraints gbcLabel = (GridBagConstraints) gbc.clone();
245
gbcLabel.insets = new Insets( 2, 2, 2, 0 );
246
gbcLabel.gridwidth = 1;
247
gbcLabel.weightx = 0;
248
249
if ( c == null )
250
c = new JLabel( "" );
251
252
gbl.setConstraints( l, gbcLabel );
253
target.add( l );
254
gbl.setConstraints( c, gbc );
255
target.add( c );
256
}
257
258
/// Sets up menu entries
259
private void setupMenu( boolean isApplet ) {
260
JMenu fileMenu = new JMenu( "File" );
261
JMenu optionMenu = new JMenu( "Option" );
262
263
fileMenu.add( new MenuItemV2( "Save Selected Options...", this ));
264
fileMenu.add( new MenuItemV2( "Load Options...", this ));
265
fileMenu.addSeparator();
266
fileMenu.add( new MenuItemV2( "Save as PNG...", this ));
267
fileMenu.add( new MenuItemV2( "Load PNG File to Compare...", this ));
268
fileMenu.add( new MenuItemV2( "Page Setup...", this ));
269
fileMenu.add( new MenuItemV2( "Print...", this ));
270
fileMenu.addSeparator();
271
if ( !isApplet )
272
fileMenu.add( new MenuItemV2( "Exit", this ));
273
else
274
fileMenu.add( new MenuItemV2( "Close", this ));
275
276
displayGridCBMI = new CheckboxMenuItemV2( "Display Grid", true, this );
277
force16ColsCBMI = new CheckboxMenuItemV2( "Force 16 Columns", false, this );
278
showFontInfoCBMI = new CheckboxMenuItemV2( "Display Font Info", false, this );
279
optionMenu.add( displayGridCBMI );
280
optionMenu.add( force16ColsCBMI );
281
optionMenu.add( showFontInfoCBMI );
282
283
JMenuBar mb = parent.getJMenuBar();
284
if ( mb == null )
285
mb = new JMenuBar();
286
mb.add( fileMenu );
287
mb.add( optionMenu );
288
289
parent.setJMenuBar( mb );
290
291
String[] fontList =
292
GraphicsEnvironment.getLocalGraphicsEnvironment().getAvailableFontFamilyNames();
293
294
for ( int i = 0; i < fontList.length; i++ )
295
fontMenu.addItem( fontList[i] );
296
fontMenu.setSelectedItem( "Dialog" );
297
298
styleMenu.addItem( "Plain" );
299
styleMenu.addItem( "Bold" );
300
styleMenu.addItem( "Italic" );
301
styleMenu.addItem( "Bold Italic" );
302
303
transformMenu.addItem( "None" );
304
transformMenu.addItem( "Scale" );
305
transformMenu.addItem( "Shear" );
306
transformMenu.addItem( "Rotate" );
307
308
transformMenuG2.addItem( "None" );
309
transformMenuG2.addItem( "Scale" );
310
transformMenuG2.addItem( "Shear" );
311
transformMenuG2.addItem( "Rotate" );
312
313
methodsMenu.addItem( "drawString" );
314
methodsMenu.addItem( "drawChars" );
315
methodsMenu.addItem( "drawBytes" );
316
methodsMenu.addItem( "drawGlyphVector" );
317
methodsMenu.addItem( "TextLayout.draw" );
318
methodsMenu.addItem( "GlyphVector.getOutline + draw" );
319
methodsMenu.addItem( "TextLayout.getOutline + draw" );
320
321
textMenu.addItem( "Unicode Range" );
322
textMenu.addItem( "All Glyphs" );
323
textMenu.addItem( "User Text" );
324
textMenu.addItem( "Text File" );
325
textMenu.addActionListener ( this ); // listener added later so unneeded events not thrown
326
}
327
328
/// Sets up the all dialogs used in Font2DTest...
329
private void setupDialog( boolean isApplet ) {
330
if (!isApplet)
331
filePromptDialog = new JFileChooser( );
332
else
333
filePromptDialog = null;
334
335
/// Prepare user text dialog...
336
userTextDialog = new JDialog( parent, "User Text", false );
337
JPanel dialogTopPanel = new JPanel();
338
JPanel dialogBottomPanel = new JPanel();
339
LabelV2 message1 = new LabelV2( "Enter text below and then press update" );
340
LabelV2 message2 = new LabelV2( "(Unicode char can be denoted by \\uXXXX)" );
341
LabelV2 message3 = new LabelV2( "(Supplementary chars can be denoted by \\UXXXXXX)" );
342
userTextArea = new JTextArea( "Font2DTest!" );
343
ButtonV2 bUpdate = new ButtonV2( "Update", this );
344
userTextArea.setFont( new Font( "dialog", Font.PLAIN, 12 ));
345
dialogTopPanel.setLayout( new GridLayout( 3, 1 ));
346
dialogTopPanel.add( message1 );
347
dialogTopPanel.add( message2 );
348
dialogTopPanel.add( message3 );
349
dialogBottomPanel.add( bUpdate );
350
//ABP
351
JScrollPane userTextAreaSP = new JScrollPane(userTextArea);
352
userTextAreaSP.setPreferredSize(new Dimension(300, 100));
353
354
userTextDialog.getContentPane().setLayout( new BorderLayout() );
355
userTextDialog.getContentPane().add( "North", dialogTopPanel );
356
userTextDialog.getContentPane().add( "Center", userTextAreaSP );
357
userTextDialog.getContentPane().add( "South", dialogBottomPanel );
358
userTextDialog.pack();
359
userTextDialog.addWindowListener( new WindowAdapter() {
360
public void windowClosing( WindowEvent e ) {
361
userTextDialog.setVisible(false);
362
}
363
});
364
365
/// Prepare printing dialog...
366
printCBGroup = new ButtonGroup();
367
printModeCBs[ fp.ONE_PAGE ] =
368
new JRadioButton( "Print one page from currently displayed character/line",
369
true );
370
printModeCBs[ fp.CUR_RANGE ] =
371
new JRadioButton( "Print all characters in currently selected range",
372
false );
373
printModeCBs[ fp.ALL_TEXT ] =
374
new JRadioButton( "Print all lines of text",
375
false );
376
LabelV2 l =
377
new LabelV2( "Note: Page range in native \"Print\" dialog will not affect the result" );
378
JPanel buttonPanel = new JPanel();
379
printModeCBs[ fp.ALL_TEXT ].setEnabled( false );
380
buttonPanel.add( new ButtonV2( "Print", this ));
381
buttonPanel.add( new ButtonV2( "Cancel", this ));
382
383
printDialog = new JDialog( parent, "Print...", true );
384
printDialog.setResizable( false );
385
printDialog.addWindowListener( new WindowAdapter() {
386
public void windowClosing( WindowEvent e ) {
387
printDialog.setVisible(false);
388
}
389
});
390
printDialog.getContentPane().setLayout( new GridLayout( printModeCBs.length + 2, 1 ));
391
printDialog.getContentPane().add( l );
392
for ( int i = 0; i < printModeCBs.length; i++ ) {
393
printCBGroup.add( printModeCBs[i] );
394
printDialog.getContentPane().add( printModeCBs[i] );
395
}
396
printDialog.getContentPane().add( buttonPanel );
397
printDialog.pack();
398
399
/// Prepare font information dialog...
400
fontInfoDialog = new JDialog( parent, "Font info", false );
401
fontInfoDialog.setResizable( false );
402
fontInfoDialog.addWindowListener( new WindowAdapter() {
403
public void windowClosing( WindowEvent e ) {
404
fontInfoDialog.setVisible(false);
405
showFontInfoCBMI.setState( false );
406
}
407
});
408
JPanel fontInfoPanel = new JPanel();
409
fontInfoPanel.setLayout( new GridLayout( fontInfos.length, 1 ));
410
for ( int i = 0; i < fontInfos.length; i++ ) {
411
fontInfos[i] = new LabelV2("");
412
fontInfoPanel.add( fontInfos[i] );
413
}
414
fontInfoDialog.getContentPane().add( fontInfoPanel );
415
416
/// Move the location of the dialog...
417
userTextDialog.setLocation( 200, 300 );
418
fontInfoDialog.setLocation( 0, 400 );
419
}
420
421
/// RangeMenu object signals using this function
422
/// when Unicode range has been changed and text needs to be redrawn
423
public void fireRangeChanged() {
424
int[] range = rm.getSelectedRange();
425
fp.setTextToDraw( fp.RANGE_TEXT, range, null, null );
426
if(canDisplayCheck) {
427
setupFontList(range[0], range[1]);
428
}
429
if ( showFontInfoCBMI.getState() )
430
fireUpdateFontInfo();
431
}
432
433
/// Changes the message on the status bar
434
public 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 bar
437
statusBar.setText( message );
438
if ( error )
439
fp.showingError = true;
440
else
441
fp.showingError = false;
442
}
443
444
/// Updates the information about the selected font
445
public void fireUpdateFontInfo() {
446
if ( showFontInfoCBMI.getState() ) {
447
String[] infos = fp.getFontInfo();
448
for ( int i = 0; i < fontInfos.length; i++ )
449
fontInfos[i].setText( infos[i] );
450
fontInfoDialog.pack();
451
}
452
}
453
454
private void setupFontList(int rangeStart, int rangeEnd) {
455
456
int listCount = fontMenu.getItemCount();
457
int size = 16;
458
459
try {
460
size = Float.valueOf(sizeField.getText()).intValue();
461
}
462
catch ( Exception e ) {
463
System.out.println("Invalid font size in the size textField. Using default value of 16");
464
}
465
466
int style = fontStyles[styleMenu.getSelectedIndex()];
467
Font f;
468
for (int i = 0; i < listCount; i++) {
469
String fontName = fontMenu.getItemAt(i);
470
f = new Font(fontName, style, size);
471
if ((rm.getSelectedIndex() != RangeMenu.SURROGATES_AREA_INDEX) &&
472
canDisplayRange(f, rangeStart, rangeEnd)) {
473
fontMenu.setBit(i, true);
474
}
475
else {
476
fontMenu.setBit(i, false);
477
}
478
}
479
480
fontMenu.repaint();
481
}
482
483
protected boolean canDisplayRange(Font font, int rangeStart, int rangeEnd) {
484
for (int i = rangeStart; i < rangeEnd; i++) {
485
if (font.canDisplay(i)) {
486
return true;
487
}
488
}
489
return false;
490
}
491
492
/// Displays a file load/save dialog and returns the specified file
493
private String promptFile( boolean isSave, String initFileName ) {
494
int retVal;
495
String str;
496
497
/// ABP
498
if ( filePromptDialog == null)
499
return null;
500
501
if ( isSave ) {
502
filePromptDialog.setDialogType( JFileChooser.SAVE_DIALOG );
503
filePromptDialog.setDialogTitle( "Save..." );
504
str = "Save";
505
506
507
}
508
else {
509
filePromptDialog.setDialogType( JFileChooser.OPEN_DIALOG );
510
filePromptDialog.setDialogTitle( "Load..." );
511
str = "Load";
512
}
513
514
if (initFileName != null)
515
filePromptDialog.setSelectedFile( new File( initFileName ) );
516
retVal = filePromptDialog.showDialog( this, str );
517
518
if ( retVal == JFileChooser.APPROVE_OPTION ) {
519
File file = filePromptDialog.getSelectedFile();
520
String fileName = file.getAbsolutePath();
521
if ( fileName != null ) {
522
return fileName;
523
}
524
}
525
526
return null;
527
}
528
529
/// Converts user text into arrays of String, delimited at newline character
530
/// Also replaces any valid escape sequence with appropriate unicode character
531
/// Support \\UXXXXXX notation for surrogates
532
private String[] parseUserText( String orig ) {
533
int length = orig.length();
534
StringTokenizer perLine = new StringTokenizer( orig, "\n" );
535
String[] textLines = new String[ perLine.countTokens() ];
536
int lineNumber = 0;
537
538
while ( perLine.hasMoreElements() ) {
539
StringBuffer converted = new StringBuffer();
540
String oneLine = perLine.nextToken();
541
int lineLength = oneLine.length();
542
int prevEscapeEnd = 0;
543
int nextEscape = -1;
544
do {
545
int nextBMPEscape = oneLine.indexOf( "\\u", prevEscapeEnd );
546
int nextSupEscape = oneLine.indexOf( "\\U", prevEscapeEnd );
547
nextEscape = (nextBMPEscape < 0)
548
? ((nextSupEscape < 0)
549
? -1
550
: nextSupEscape)
551
: ((nextSupEscape < 0)
552
? nextBMPEscape
553
: Math.min(nextBMPEscape, nextSupEscape));
554
555
if ( nextEscape != -1 ) {
556
if ( prevEscapeEnd < nextEscape )
557
converted.append( oneLine.substring( prevEscapeEnd, nextEscape ));
558
559
prevEscapeEnd = nextEscape + (nextEscape == nextBMPEscape ? 6 : 8);
560
try {
561
String hex = oneLine.substring( nextEscape + 2, prevEscapeEnd );
562
if (nextEscape == nextBMPEscape) {
563
converted.append( (char) Integer.parseInt( hex, 16 ));
564
} else {
565
converted.append( new String( Character.toChars( Integer.parseInt( hex, 16 ))));
566
}
567
}
568
catch ( Exception e ) {
569
int copyLimit = Math.min(lineLength, prevEscapeEnd);
570
converted.append( oneLine.substring( nextEscape, copyLimit ));
571
}
572
}
573
} while (nextEscape != -1);
574
if ( prevEscapeEnd < lineLength )
575
converted.append( oneLine.substring( prevEscapeEnd, lineLength ));
576
textLines[ lineNumber++ ] = converted.toString();
577
}
578
return textLines;
579
}
580
581
/// Reads the text from specified file, detecting UTF-16 encoding
582
/// Then breaks the text into String array, delimited at every line break
583
private void readTextFile( String fileName ) {
584
try {
585
String fileText;
586
String[] textLines;
587
BufferedInputStream bis =
588
new BufferedInputStream( new FileInputStream( fileName ));
589
int numBytes = bis.available();
590
if (numBytes == 0) {
591
throw new Exception("Text file " + fileName + " is empty");
592
}
593
byte[] byteData = new byte[ numBytes ];
594
bis.read( byteData, 0, numBytes );
595
bis.close();
596
597
/// If byte mark is found, then use UTF-16 encoding to convert bytes...
598
if (numBytes >= 2 &&
599
(( byteData[0] == (byte) 0xFF && byteData[1] == (byte) 0xFE ) ||
600
( byteData[0] == (byte) 0xFE && byteData[1] == (byte) 0xFF )))
601
fileText = new String( byteData, "UTF-16" );
602
/// Otherwise, use system default encoding
603
else
604
fileText = new String( byteData );
605
606
int length = fileText.length();
607
StringTokenizer perLine = new StringTokenizer( fileText, "\n" );
608
/// Determine "Return Char" used in this file
609
/// This simply finds first occurrence of CR, CR+LF or LF...
610
for ( int i = 0; i < length; i++ ) {
611
char iTh = fileText.charAt( i );
612
if ( iTh == '\r' ) {
613
if ( i < length - 1 && fileText.charAt( i + 1 ) == '\n' )
614
perLine = new StringTokenizer( fileText, "\r\n" );
615
else
616
perLine = new StringTokenizer( fileText, "\r" );
617
break;
618
}
619
else if ( iTh == '\n' )
620
/// Use the one already created
621
break;
622
}
623
int lineNumber = 0, numLines = perLine.countTokens();
624
textLines = new String[ numLines ];
625
626
while ( perLine.hasMoreElements() ) {
627
String oneLine = perLine.nextToken();
628
if ( oneLine == null )
629
/// To make LineBreakMeasurer to return a valid TextLayout
630
/// on an empty line, simply feed it a space char...
631
oneLine = " ";
632
textLines[ lineNumber++ ] = oneLine;
633
}
634
fp.setTextToDraw( fp.FILE_TEXT, null, null, textLines );
635
rm.setEnabled( false );
636
methodsMenu.setEnabled( false );
637
}
638
catch ( Exception ex ) {
639
fireChangeStatus( "ERROR: Failed to Read Text File; See Stack Trace", true );
640
ex.printStackTrace();
641
}
642
}
643
644
/// Returns a String storing current configuration
645
private void writeCurrentOptions( String fileName ) {
646
try {
647
String curOptions = fp.getCurrentOptions();
648
BufferedOutputStream bos =
649
new BufferedOutputStream( new FileOutputStream( fileName ));
650
/// Prepend title and the option that is only obtainable here
651
int[] range = rm.getSelectedRange();
652
String completeOptions =
653
( "Font2DTest Option File\n" +
654
displayGridCBMI.getState() + "\n" +
655
force16ColsCBMI.getState() + "\n" +
656
showFontInfoCBMI.getState() + "\n" +
657
rm.getSelectedItem() + "\n" +
658
range[0] + "\n" + range[1] + "\n" + curOptions + tFileName);
659
byte[] toBeWritten = completeOptions.getBytes( "UTF-16" );
660
bos.write( toBeWritten, 0, toBeWritten.length );
661
bos.close();
662
}
663
catch ( Exception ex ) {
664
fireChangeStatus( "ERROR: Failed to Save Options File; See Stack Trace", true );
665
ex.printStackTrace();
666
}
667
}
668
669
/// Updates GUI visibility/status after some parameters have changed
670
private void updateGUI() {
671
int selectedText = textMenu.getSelectedIndex();
672
673
/// Set the visibility of User Text dialog
674
if ( selectedText == fp.USER_TEXT )
675
userTextDialog.setVisible(true);
676
else
677
userTextDialog.setVisible(false);
678
/// Change the visibility/status/availability of Print JDialog buttons
679
printModeCBs[ fp.ONE_PAGE ].setSelected( true );
680
if ( selectedText == fp.FILE_TEXT || selectedText == fp.USER_TEXT ) {
681
/// ABP
682
/// update methodsMenu to show that TextLayout.draw is being used
683
/// when we are in FILE_TEXT mode
684
if ( selectedText == fp.FILE_TEXT )
685
methodsMenu.setSelectedItem("TextLayout.draw");
686
methodsMenu.setEnabled( selectedText == fp.USER_TEXT );
687
printModeCBs[ fp.CUR_RANGE ].setEnabled( false );
688
printModeCBs[ fp.ALL_TEXT ].setEnabled( true );
689
}
690
else {
691
/// ABP
692
/// update methodsMenu to show that drawGlyph is being used
693
/// when we are in ALL_GLYPHS mode
694
if ( selectedText == fp.ALL_GLYPHS )
695
methodsMenu.setSelectedItem("drawGlyphVector");
696
methodsMenu.setEnabled( selectedText == fp.RANGE_TEXT );
697
printModeCBs[ fp.CUR_RANGE ].setEnabled( true );
698
printModeCBs[ fp.ALL_TEXT ].setEnabled( false );
699
}
700
/// Modify RangeMenu and fontInfo label availabilty
701
if ( selectedText == fp.RANGE_TEXT ) {
702
fontInfos[1].setVisible( true );
703
rm.setEnabled( true );
704
}
705
else {
706
fontInfos[1].setVisible( false );
707
rm.setEnabled( false );
708
}
709
}
710
711
/// Loads saved options and applies them
712
private void loadOptions( String fileName ) {
713
try {
714
BufferedInputStream bis =
715
new BufferedInputStream( new FileInputStream( fileName ));
716
int numBytes = bis.available();
717
byte[] byteData = new byte[ numBytes ];
718
bis.read( byteData, 0, numBytes );
719
bis.close();
720
if ( numBytes < 2 ||
721
(byteData[0] != (byte) 0xFE || byteData[1] != (byte) 0xFF) )
722
throw new Exception( "Not a Font2DTest options file" );
723
724
String options = new String( byteData, "UTF-16" );
725
StringTokenizer perLine = new StringTokenizer( options, "\n" );
726
String title = perLine.nextToken();
727
if ( !title.equals( "Font2DTest Option File" ))
728
throw new Exception( "Not a Font2DTest options file" );
729
730
/// Parse all options
731
boolean displayGridOpt = Boolean.parseBoolean( perLine.nextToken() );
732
boolean force16ColsOpt = Boolean.parseBoolean( perLine.nextToken() );
733
boolean showFontInfoOpt = Boolean.parseBoolean( perLine.nextToken() );
734
String rangeNameOpt = perLine.nextToken();
735
int rangeStartOpt = Integer.parseInt( perLine.nextToken() );
736
int rangeEndOpt = Integer.parseInt( perLine.nextToken() );
737
String fontNameOpt = perLine.nextToken();
738
float fontSizeOpt = Float.parseFloat( perLine.nextToken() );
739
int fontStyleOpt = Integer.parseInt( perLine.nextToken() );
740
int fontTransformOpt = Integer.parseInt( perLine.nextToken() );
741
int g2TransformOpt = Integer.parseInt( perLine.nextToken() );
742
int textToUseOpt = Integer.parseInt( perLine.nextToken() );
743
int drawMethodOpt = Integer.parseInt( perLine.nextToken() );
744
int antialiasOpt = Integer.parseInt(perLine.nextToken());
745
int fractionalOpt = Integer.parseInt(perLine.nextToken());
746
int lcdContrast = Integer.parseInt(perLine.nextToken());
747
String[] userTextOpt = { "Font2DTest!" };
748
String dialogEntry = "Font2DTest!";
749
if (textToUseOpt == fp.USER_TEXT ) {
750
int numLines = perLine.countTokens(), lineNumber = 0;
751
if ( numLines != 0 ) {
752
userTextOpt = new String[ numLines ];
753
dialogEntry = "";
754
for ( ; perLine.hasMoreElements(); lineNumber++ ) {
755
userTextOpt[ lineNumber ] = perLine.nextToken();
756
dialogEntry += userTextOpt[ lineNumber ] + "\n";
757
}
758
}
759
}
760
761
/// Reset GUIs
762
displayGridCBMI.setState( displayGridOpt );
763
force16ColsCBMI.setState( force16ColsOpt );
764
showFontInfoCBMI.setState( showFontInfoOpt );
765
rm.setSelectedRange( rangeNameOpt, rangeStartOpt, rangeEndOpt );
766
fontMenu.setSelectedItem( fontNameOpt );
767
sizeField.setText( String.valueOf( fontSizeOpt ));
768
styleMenu.setSelectedIndex( fontStyleOpt );
769
transformMenu.setSelectedIndex( fontTransformOpt );
770
transformMenuG2.setSelectedIndex( g2TransformOpt );
771
textMenu.setSelectedIndex( textToUseOpt );
772
methodsMenu.setSelectedIndex( drawMethodOpt );
773
antiAliasMenu.setSelectedIndex( antialiasOpt );
774
fracMetricsMenu.setSelectedIndex( fractionalOpt );
775
contrastSlider.setValue(lcdContrast);
776
777
userTextArea.setText( dialogEntry );
778
updateGUI();
779
780
if ( textToUseOpt == fp.FILE_TEXT ) {
781
tFileName = perLine.nextToken();
782
readTextFile(tFileName );
783
}
784
785
/// Reset option variables and repaint
786
fp.loadOptions( displayGridOpt, force16ColsOpt,
787
rangeStartOpt, rangeEndOpt,
788
fontNameOpt, fontSizeOpt,
789
fontStyleOpt, fontTransformOpt, g2TransformOpt,
790
textToUseOpt, drawMethodOpt,
791
antialiasOpt, fractionalOpt,
792
lcdContrast, userTextOpt );
793
if ( showFontInfoOpt ) {
794
fireUpdateFontInfo();
795
fontInfoDialog.setVisible(true);
796
}
797
else
798
fontInfoDialog.setVisible(false);
799
}
800
catch ( Exception ex ) {
801
fireChangeStatus( "ERROR: Failed to Load Options File; See Stack Trace", true );
802
ex.printStackTrace();
803
}
804
}
805
806
/// Loads a previously saved image
807
private void loadComparisonPNG( String fileName ) {
808
try {
809
BufferedImage image =
810
javax.imageio.ImageIO.read(new File(fileName));
811
JFrame f = new JFrame( "Comparison PNG" );
812
ImagePanel ip = new ImagePanel( image );
813
f.setResizable( false );
814
f.getContentPane().add( ip );
815
f.addWindowListener( new WindowAdapter() {
816
public void windowClosing( WindowEvent e ) {
817
( (JFrame) e.getSource() ).dispose();
818
}
819
});
820
f.pack();
821
f.setVisible(true);
822
}
823
catch ( Exception ex ) {
824
fireChangeStatus( "ERROR: Failed to Load PNG File; See Stack Trace", true );
825
ex.printStackTrace();
826
}
827
}
828
829
/// Interface functions...
830
831
/// ActionListener interface function
832
/// Responds to JMenuItem, JTextField and JButton actions
833
public void actionPerformed( ActionEvent e ) {
834
Object source = e.getSource();
835
836
if ( source instanceof JMenuItem ) {
837
JMenuItem mi = (JMenuItem) source;
838
String itemName = mi.getText();
839
840
if ( itemName.equals( "Save Selected Options..." )) {
841
String fileName = promptFile( true, "options.txt" );
842
if ( fileName != null )
843
writeCurrentOptions( fileName );
844
}
845
else if ( itemName.equals( "Load Options..." )) {
846
String fileName = promptFile( false, "options.txt" );
847
if ( fileName != null )
848
loadOptions( fileName );
849
}
850
else if ( itemName.equals( "Save as PNG..." )) {
851
String fileName = promptFile( true, fontMenu.getSelectedItem() + ".png" );
852
if ( fileName != null )
853
fp.doSavePNG( fileName );
854
}
855
else if ( itemName.equals( "Load PNG File to Compare..." )) {
856
String fileName = promptFile( false, null );
857
if ( fileName != null )
858
loadComparisonPNG( fileName );
859
}
860
else if ( itemName.equals( "Page Setup..." ))
861
fp.doPageSetup();
862
else if ( itemName.equals( "Print..." ))
863
printDialog.setVisible(true);
864
else if ( itemName.equals( "Close" ))
865
parent.dispose();
866
else if ( itemName.equals( "Exit" ))
867
System.exit(0);
868
}
869
870
else if ( source instanceof JTextField ) {
871
JTextField tf = (JTextField) source;
872
float sz = 12f;
873
try {
874
sz = Float.parseFloat(sizeField.getText());
875
if (sz < 1f || sz > 120f) {
876
sz = 12f;
877
sizeField.setText("12");
878
}
879
} catch (Exception se) {
880
sizeField.setText("12");
881
}
882
if ( tf == sizeField )
883
fp.setFontParams( fontMenu.getSelectedItem(),
884
sz,
885
styleMenu.getSelectedIndex(),
886
transformMenu.getSelectedIndex() );
887
}
888
889
else if ( source instanceof JButton ) {
890
String itemName = ( (JButton) source ).getText();
891
/// Print dialog buttons...
892
if ( itemName.equals( "Print" )) {
893
for ( int i = 0; i < printModeCBs.length; i++ )
894
if ( printModeCBs[i].isSelected() ) {
895
printDialog.setVisible(false);
896
fp.doPrint( i );
897
}
898
}
899
else if ( itemName.equals( "Cancel" ))
900
printDialog.setVisible(false);
901
/// Update button from Usert Text JDialog...
902
else if ( itemName.equals( "Update" ))
903
fp.setTextToDraw( fp.USER_TEXT, null,
904
parseUserText( userTextArea.getText() ), null );
905
}
906
else if ( source instanceof JComboBox ) {
907
JComboBox<?> c = (JComboBox<?>) source;
908
909
/// RangeMenu handles actions by itself and then calls fireRangeChanged,
910
/// so it is not listed or handled here
911
if ( c == fontMenu || c == styleMenu || c == transformMenu ) {
912
float sz = 12f;
913
try {
914
sz = Float.parseFloat(sizeField.getText());
915
if (sz < 1f || sz > 120f) {
916
sz = 12f;
917
sizeField.setText("12");
918
}
919
} catch (Exception se) {
920
sizeField.setText("12");
921
}
922
fp.setFontParams(fontMenu.getSelectedItem(),
923
sz,
924
styleMenu.getSelectedIndex(),
925
transformMenu.getSelectedIndex());
926
} else if ( c == methodsMenu )
927
fp.setDrawMethod( methodsMenu.getSelectedIndex() );
928
else if ( c == textMenu ) {
929
930
if(canDisplayCheck) {
931
fireRangeChanged();
932
}
933
934
int selected = textMenu.getSelectedIndex();
935
936
if ( selected == fp.RANGE_TEXT )
937
fp.setTextToDraw( fp.RANGE_TEXT, rm.getSelectedRange(),
938
null, null );
939
else if ( selected == fp.USER_TEXT )
940
fp.setTextToDraw( fp.USER_TEXT, null,
941
parseUserText( userTextArea.getText() ), null );
942
else if ( selected == fp.FILE_TEXT ) {
943
String fileName = promptFile( false, null );
944
if ( fileName != null ) {
945
tFileName = fileName;
946
readTextFile( fileName );
947
} else {
948
/// User cancelled selection; reset to previous choice
949
c.setSelectedIndex( currentTextChoice );
950
return;
951
}
952
}
953
else if ( selected == fp.ALL_GLYPHS )
954
fp.setTextToDraw( fp.ALL_GLYPHS, null, null, null );
955
956
updateGUI();
957
currentTextChoice = selected;
958
}
959
else if ( c == transformMenuG2 ) {
960
fp.setTransformG2( transformMenuG2.getSelectedIndex() );
961
}
962
else if (c == antiAliasMenu || c == fracMetricsMenu) {
963
if (c == antiAliasMenu) {
964
boolean enabled = FontPanel.AAValues.
965
isLCDMode(antiAliasMenu.getSelectedItem());
966
contrastSlider.setEnabled(enabled);
967
}
968
fp.setRenderingHints(antiAliasMenu.getSelectedItem(),
969
fracMetricsMenu.getSelectedItem(),
970
contrastSlider.getValue());
971
}
972
}
973
}
974
975
public void stateChanged(ChangeEvent e) {
976
Object source = e.getSource();
977
if (source instanceof JSlider) {
978
fp.setRenderingHints(antiAliasMenu.getSelectedItem(),
979
fracMetricsMenu.getSelectedItem(),
980
contrastSlider.getValue());
981
}
982
}
983
984
/// ItemListener interface function
985
/// Responds to JCheckBoxMenuItem, JComboBox and JCheckBox actions
986
public void itemStateChanged( ItemEvent e ) {
987
Object source = e.getSource();
988
989
if ( source instanceof JCheckBoxMenuItem ) {
990
JCheckBoxMenuItem cbmi = (JCheckBoxMenuItem) source;
991
if ( cbmi == displayGridCBMI )
992
fp.setGridDisplay( displayGridCBMI.getState() );
993
else if ( cbmi == force16ColsCBMI )
994
fp.setForce16Columns( force16ColsCBMI.getState() );
995
else if ( cbmi == showFontInfoCBMI ) {
996
if ( showFontInfoCBMI.getState() ) {
997
fireUpdateFontInfo();
998
fontInfoDialog.setVisible(true);
999
}
1000
else
1001
fontInfoDialog.setVisible(false);
1002
}
1003
}
1004
}
1005
1006
private static void printUsage() {
1007
String usage = "Usage: java -jar Font2DTest.jar [options]\n" +
1008
"\nwhere options include:\n" +
1009
" -dcdc | -disablecandisplaycheck disable canDisplay check for font\n" +
1010
" -? | -help print this help message\n" +
1011
"\nExample :\n" +
1012
" To disable canDisplay check on font for ranges\n" +
1013
" java -jar Font2DTest.jar -dcdc";
1014
System.out.println(usage);
1015
System.exit(0);
1016
}
1017
1018
/// Main function
1019
public static void main(String[] argv) {
1020
1021
if(argv.length > 0) {
1022
if(argv[0].equalsIgnoreCase("-disablecandisplaycheck") ||
1023
argv[0].equalsIgnoreCase("-dcdc")) {
1024
canDisplayCheck = false;
1025
}
1026
else {
1027
printUsage();
1028
}
1029
}
1030
1031
UIManager.put("swing.boldMetal", Boolean.FALSE);
1032
final JFrame f = new JFrame( "Font2DTest" );
1033
final Font2DTest f2dt = new Font2DTest( f, false );
1034
f.addWindowListener( new WindowAdapter() {
1035
public void windowOpening( WindowEvent e ) { f2dt.repaint(); }
1036
public void windowClosing( WindowEvent e ) { System.exit(0); }
1037
});
1038
1039
f.getContentPane().add( f2dt );
1040
f.pack();
1041
f.setVisible(true);
1042
}
1043
1044
/// Inner class definitions...
1045
1046
/// Class to display just an image file
1047
/// Used to show the comparison PNG image
1048
private final class ImagePanel extends JPanel {
1049
private final BufferedImage bi;
1050
1051
public ImagePanel( BufferedImage image ) {
1052
bi = image;
1053
}
1054
1055
public Dimension getPreferredSize() {
1056
return new Dimension( bi.getWidth(), bi.getHeight() );
1057
}
1058
1059
public void paintComponent( Graphics g ) {
1060
g.drawImage( bi, 0, 0, this );
1061
}
1062
}
1063
1064
/// Classes made to avoid repetitive calls... (being lazy)
1065
private final class ButtonV2 extends JButton {
1066
public ButtonV2( String name, ActionListener al ) {
1067
super( name );
1068
this.addActionListener( al );
1069
}
1070
}
1071
1072
private final class ChoiceV2 extends JComboBox<String> {
1073
1074
private BitSet bitSet = null;
1075
1076
public ChoiceV2() {;}
1077
1078
public ChoiceV2( ActionListener al ) {
1079
super();
1080
this.addActionListener( al );
1081
}
1082
1083
public ChoiceV2( ActionListener al, boolean fontChoice) {
1084
this(al);
1085
if(fontChoice) {
1086
//Register this component in ToolTipManager
1087
setToolTipText("");
1088
bitSet = new BitSet();
1089
setRenderer(new ChoiceV2Renderer(this));
1090
}
1091
}
1092
1093
public String getToolTipText() {
1094
int index = this.getSelectedIndex();
1095
String fontName = (String) this.getSelectedItem();
1096
if(fontName != null &&
1097
(textMenu.getSelectedIndex() == fp.RANGE_TEXT)) {
1098
if (getBit(index)) {
1099
return "Font \"" + fontName + "\" can display some characters in \"" +
1100
rm.getSelectedItem() + "\" range";
1101
}
1102
else {
1103
return "Font \"" + fontName + "\" cannot display any characters in \"" +
1104
rm.getSelectedItem() + "\" range";
1105
}
1106
}
1107
return super.getToolTipText();
1108
}
1109
1110
public void setBit(int bitIndex, boolean value) {
1111
bitSet.set(bitIndex, value);
1112
}
1113
1114
public boolean getBit(int bitIndex) {
1115
return bitSet.get(bitIndex);
1116
}
1117
}
1118
1119
private final class ChoiceV2Renderer extends DefaultListCellRenderer {
1120
1121
private ImageIcon yesImage, blankImage;
1122
private ChoiceV2 choice = null;
1123
1124
public ChoiceV2Renderer(ChoiceV2 choice) {
1125
BufferedImage yes =
1126
new BufferedImage(10, 10, BufferedImage.TYPE_INT_ARGB);
1127
Graphics2D g = yes.createGraphics();
1128
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
1129
RenderingHints.VALUE_ANTIALIAS_ON);
1130
g.setColor(Color.BLUE);
1131
g.drawLine(0, 5, 3, 10);
1132
g.drawLine(1, 5, 4, 10);
1133
g.drawLine(3, 10, 10, 0);
1134
g.drawLine(4, 9, 9, 0);
1135
g.dispose();
1136
BufferedImage blank =
1137
new BufferedImage(10, 10, BufferedImage.TYPE_INT_ARGB);
1138
yesImage = new ImageIcon(yes);
1139
blankImage = new ImageIcon(blank);
1140
this.choice = choice;
1141
}
1142
1143
public Component getListCellRendererComponent(JList<?> list,
1144
Object value,
1145
int index,
1146
boolean isSelected,
1147
boolean cellHasFocus) {
1148
1149
if(textMenu.getSelectedIndex() == fp.RANGE_TEXT) {
1150
1151
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
1152
1153
//For JComboBox if index is -1, its rendering the selected index.
1154
if(index == -1) {
1155
index = choice.getSelectedIndex();
1156
}
1157
1158
if(choice.getBit(index)) {
1159
setIcon(yesImage);
1160
}
1161
else {
1162
setIcon(blankImage);
1163
}
1164
1165
} else {
1166
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
1167
setIcon(blankImage);
1168
}
1169
1170
return this;
1171
}
1172
}
1173
1174
private final class LabelV2 extends JLabel {
1175
public LabelV2( String name ) {
1176
super( name );
1177
}
1178
}
1179
1180
private final class MenuItemV2 extends JMenuItem {
1181
public MenuItemV2( String name, ActionListener al ) {
1182
super( name );
1183
this.addActionListener( al );
1184
}
1185
}
1186
1187
private final class CheckboxMenuItemV2 extends JCheckBoxMenuItem {
1188
public CheckboxMenuItemV2( String name, boolean b, ItemListener il ) {
1189
super( name, b );
1190
this.addItemListener( il );
1191
}
1192
}
1193
}
1194
1195