Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/src/demo/share/jfc/Font2DTest/FontPanel.java
41149 views
1
/*
2
* Copyright (c) 2000, 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.BorderLayout;
43
import java.awt.Color;
44
import java.awt.Cursor;
45
import java.awt.Dimension;
46
import java.awt.Font;
47
import java.awt.FontMetrics;
48
import java.awt.Graphics;
49
import java.awt.Graphics2D;
50
import java.awt.GraphicsConfiguration;
51
import java.awt.GraphicsEnvironment;
52
import java.awt.Point;
53
import java.awt.Rectangle;
54
import java.awt.RenderingHints;
55
import java.awt.Toolkit;
56
import java.awt.event.AdjustmentEvent;
57
import java.awt.event.AdjustmentListener;
58
import java.awt.event.ComponentAdapter;
59
import java.awt.event.ComponentEvent;
60
import java.awt.event.MouseEvent;
61
import java.awt.event.MouseListener;
62
import java.awt.event.MouseMotionListener;
63
import java.awt.font.FontRenderContext;
64
import java.awt.font.GlyphVector;
65
import java.awt.font.LineBreakMeasurer;
66
import java.awt.font.TextLayout;
67
import java.awt.geom.AffineTransform;
68
import java.awt.geom.NoninvertibleTransformException;
69
import java.awt.geom.Rectangle2D;
70
import java.awt.image.BufferedImage;
71
import java.awt.print.PageFormat;
72
import java.awt.print.Printable;
73
import java.awt.print.PrinterJob;
74
import java.io.BufferedOutputStream;
75
import java.io.FileOutputStream;
76
import java.text.AttributedString;
77
import java.util.Vector;
78
79
import javax.imageio.*;
80
import javax.swing.*;
81
82
import static java.awt.RenderingHints.*;
83
84
/**
85
* FontPanel.java
86
*
87
* @author Shinsuke Fukuda
88
* @author Ankit Patel [Conversion to Swing - 01/07/30]
89
*/
90
91
/// This panel is combination of the text drawing area of Font2DTest
92
/// and the custom controlled scroll bar
93
94
public final class FontPanel extends JPanel implements AdjustmentListener {
95
96
/// Drawing Option Constants
97
private final String[] STYLES =
98
{ "plain", "bold", "italic", "bold italic" };
99
100
private final int NONE = 0;
101
private final int SCALE = 1;
102
private final int SHEAR = 2;
103
private final int ROTATE = 3;
104
private final String[] TRANSFORMS =
105
{ "with no transforms", "with scaling", "with Shearing", "with rotation" };
106
107
private final int DRAW_STRING = 0;
108
private final int DRAW_CHARS = 1;
109
private final int DRAW_BYTES = 2;
110
private final int DRAW_GLYPHV = 3;
111
private final int TL_DRAW = 4;
112
private final int GV_OUTLINE = 5;
113
private final int TL_OUTLINE = 6;
114
private final String[] METHODS = {
115
"drawString", "drawChars", "drawBytes", "drawGlyphVector",
116
"TextLayout.draw", "GlyphVector.getOutline", "TextLayout.getOutline" };
117
118
public final int RANGE_TEXT = 0;
119
public final int ALL_GLYPHS = 1;
120
public final int USER_TEXT = 2;
121
public final int FILE_TEXT = 3;
122
private final String[] MS_OPENING =
123
{ " Unicode ", " Glyph Code ", " lines ", " lines " };
124
private final String[] MS_CLOSING =
125
{ "", "", " of User Text ", " of LineBreakMeasurer-reformatted Text " };
126
127
/// General Graphics Variable
128
private final JScrollBar verticalBar;
129
private final FontCanvas fc;
130
private boolean updateFontMetrics = true;
131
private boolean updateFont = true;
132
private boolean force16Cols = false;
133
public boolean showingError = false;
134
private int g2Transform = NONE; /// ABP
135
136
/// Printing constants and variables
137
public final int ONE_PAGE = 0;
138
public final int CUR_RANGE = 1;
139
public final int ALL_TEXT = 2;
140
private int printMode = ONE_PAGE;
141
private PageFormat page = null;
142
private PrinterJob printer = null;
143
144
/// Text drawing variables
145
private String fontName = "Dialog";
146
private float fontSize = 12;
147
private int fontStyle = Font.PLAIN;
148
private int fontTransform = NONE;
149
private Font testFont = null;
150
private Object antiAliasType = VALUE_TEXT_ANTIALIAS_DEFAULT;
151
private Object fractionalMetricsType = VALUE_FRACTIONALMETRICS_DEFAULT;
152
private Object lcdContrast = getDefaultLCDContrast();
153
private int drawMethod = DRAW_STRING;
154
private int textToUse = RANGE_TEXT;
155
private String[] userText = null;
156
private String[] fileText = null;
157
private int[] drawRange = { 0x0000, 0x007f };
158
private String[] fontInfos = new String[2];
159
private boolean showGrid = true;
160
161
/// Parent Font2DTest panel
162
private final Font2DTest f2dt;
163
private final JFrame parent;
164
165
public FontPanel( Font2DTest demo, JFrame f ) {
166
f2dt = demo;
167
parent = f;
168
169
verticalBar = new JScrollBar ( JScrollBar.VERTICAL );
170
fc = new FontCanvas();
171
172
this.setLayout( new BorderLayout() );
173
this.add( "Center", fc );
174
this.add( "East", verticalBar );
175
176
verticalBar.addAdjustmentListener( this );
177
this.addComponentListener( new ComponentAdapter() {
178
public void componentResized( ComponentEvent e ) {
179
updateFontMetrics = true;
180
}
181
});
182
183
/// Initialize font and its infos
184
testFont = new Font(fontName, fontStyle, (int)fontSize);
185
if ((float)((int)fontSize) != fontSize) {
186
testFont = testFont.deriveFont(fontSize);
187
}
188
updateFontInfo();
189
}
190
191
public Dimension getPreferredSize() {
192
return new Dimension(600, 200);
193
}
194
195
/// Functions called by the main programs to set the various parameters
196
197
public void setTransformG2( int transform ) {
198
g2Transform = transform;
199
updateFontMetrics = true;
200
fc.repaint();
201
}
202
203
/// convenience fcn to create AffineTransform of appropriate type
204
private AffineTransform getAffineTransform( int transform ) {
205
/// ABP
206
AffineTransform at = new AffineTransform();
207
switch ( transform )
208
{
209
case SCALE:
210
at.setToScale( 1.5f, 1.5f ); break;
211
case ROTATE:
212
at.setToRotation( Math.PI / 6 ); break;
213
case SHEAR:
214
at.setToShear( 0.4f, 0 ); break;
215
case NONE:
216
break;
217
default:
218
//System.err.println( "Illegal G2 Transform Arg: " + transform);
219
break;
220
}
221
222
return at;
223
}
224
225
public void setFontParams(Object obj, float size,
226
int style, int transform) {
227
setFontParams( (String)obj, size, style, transform );
228
}
229
230
public void setFontParams(String name, float size,
231
int style, int transform) {
232
boolean fontModified = false;
233
if ( !name.equals( fontName ) || style != fontStyle )
234
fontModified = true;
235
236
fontName = name;
237
fontSize = size;
238
fontStyle = style;
239
fontTransform = transform;
240
241
/// Recreate the font as specified
242
testFont = new Font(fontName, fontStyle, (int)fontSize);
243
if ((float)((int)fontSize) != fontSize) {
244
testFont = testFont.deriveFont(fontSize);
245
}
246
247
if ( fontTransform != NONE ) {
248
AffineTransform at = getAffineTransform( fontTransform );
249
testFont = testFont.deriveFont( at );
250
}
251
updateFontMetrics = true;
252
fc.repaint();
253
if ( fontModified ) {
254
/// Tell main panel to update the font info
255
updateFontInfo();
256
f2dt.fireUpdateFontInfo();
257
}
258
}
259
260
public void setRenderingHints( Object aa, Object fm, Object contrast) {
261
antiAliasType = ((AAValues)aa).getHint();
262
fractionalMetricsType = ((FMValues)fm).getHint();
263
lcdContrast = contrast;
264
updateFontMetrics = true;
265
fc.repaint();
266
}
267
268
public void setDrawMethod( int i ) {
269
drawMethod = i;
270
fc.repaint();
271
}
272
273
public void setTextToDraw( int i, int[] range,
274
String[] textSet, String[] fileData ) {
275
textToUse = i;
276
277
if ( textToUse == RANGE_TEXT )
278
drawRange = range;
279
else if ( textToUse == ALL_GLYPHS )
280
drawMethod = DRAW_GLYPHV;
281
else if ( textToUse == USER_TEXT )
282
userText = textSet;
283
else if ( textToUse == FILE_TEXT ) {
284
fileText = fileData;
285
drawMethod = TL_DRAW;
286
}
287
288
updateFontMetrics = true;
289
fc.repaint();
290
updateFontInfo();
291
}
292
293
public void setGridDisplay( boolean b ) {
294
showGrid = b;
295
fc.repaint();
296
}
297
298
public void setForce16Columns( boolean b ) {
299
force16Cols = b;
300
updateFontMetrics = true;
301
fc.repaint();
302
}
303
304
/// Prints out the text display area
305
public void doPrint( int i ) {
306
if ( printer == null ) {
307
printer = PrinterJob.getPrinterJob();
308
page = printer.defaultPage();
309
}
310
printMode = i;
311
printer.setPrintable( fc, page );
312
313
if ( printer.printDialog() ) {
314
try {
315
printer.print();
316
}
317
catch ( Exception e ) {
318
f2dt.fireChangeStatus( "ERROR: Printing Failed; See Stack Trace", true );
319
}
320
}
321
}
322
323
/// Displays the page setup dialog and updates PageFormat info
324
public void doPageSetup() {
325
if ( printer == null ) {
326
printer = PrinterJob.getPrinterJob();
327
page = printer.defaultPage();
328
}
329
page = printer.pageDialog( page );
330
}
331
332
/// Obtains the information about selected font
333
private void updateFontInfo() {
334
int numGlyphs = 0, numCharsInRange = drawRange[1] - drawRange[0] + 1;
335
fontInfos[0] = "Font Face Name: " + testFont.getFontName();
336
fontInfos[1] = "Glyphs in This Range: ";
337
338
if ( textToUse == RANGE_TEXT ) {
339
for ( int i = drawRange[0]; i < drawRange[1]; i++ )
340
if ( testFont.canDisplay( i ))
341
numGlyphs++;
342
fontInfos[1] = fontInfos[1] + numGlyphs + " / " + numCharsInRange;
343
}
344
else
345
fontInfos[1] = null;
346
}
347
348
/// Accessor for the font information
349
public String[] getFontInfo() {
350
return fontInfos;
351
}
352
353
/// Collects the currectly set options and returns them as string
354
public String getCurrentOptions() {
355
/// Create a new String to store the options
356
/// The array will contain all 8 setting (font name, size...) and
357
/// character range or user text data used (no file text data)
358
int userTextSize = 0;
359
String options;
360
361
options = ( fontName + "\n" + fontSize + "\n" + fontStyle + "\n" +
362
fontTransform + "\n" + g2Transform + "\n"+
363
textToUse + "\n" + drawMethod + "\n" +
364
AAValues.getHintVal(antiAliasType) + "\n" +
365
FMValues.getHintVal(fractionalMetricsType) + "\n" +
366
lcdContrast + "\n");
367
if ( textToUse == USER_TEXT )
368
for ( int i = 0; i < userText.length; i++ )
369
options += ( userText[i] + "\n" );
370
371
return options;
372
}
373
374
/// Reload all options and refreshes the canvas
375
public void loadOptions( boolean grid, boolean force16, int start, int end,
376
String name, float size, int style,
377
int transform, int g2transform,
378
int text, int method, int aa, int fm,
379
int contrast, String[] user ) {
380
int[] range = { start, end };
381
382
/// Since repaint call has a low priority, these functions will finish
383
/// before the actual repainting is done
384
setGridDisplay( grid );
385
setForce16Columns( force16 );
386
// previous call to readTextFile has already set the text to draw
387
if (textToUse != FILE_TEXT) {
388
setTextToDraw( text, range, user, null );
389
}
390
setFontParams( name, size, style, transform );
391
setTransformG2( g2transform ); // ABP
392
setDrawMethod( method );
393
setRenderingHints(AAValues.getValue(aa), FMValues.getValue(fm),
394
Integer.valueOf(contrast));
395
}
396
397
/// Writes the current screen to PNG file
398
public void doSavePNG( String fileName ) {
399
fc.writePNG( fileName );
400
}
401
402
/// When scrolled using the scroll bar, update the backbuffer
403
public void adjustmentValueChanged( AdjustmentEvent e ) {
404
fc.repaint();
405
}
406
407
public void paintComponent( Graphics g ) {
408
// Windows does not repaint correctly, after
409
// a zoom. Thus, we need to force the canvas
410
// to repaint, but only once. After the first repaint,
411
// everything stabilizes. [ABP]
412
fc.repaint();
413
}
414
415
/// Inner class definition...
416
417
/// Inner panel that holds the actual drawing area and its routines
418
private class FontCanvas extends JPanel implements MouseListener, MouseMotionListener, Printable {
419
420
/// Number of characters that will fit across and down this canvas
421
private int numCharAcross, numCharDown;
422
423
/// First and last character/line that will be drawn
424
/// Limit is the end of range/text where no more draw will be done
425
private int drawStart, drawEnd, drawLimit;
426
427
/// FontMetrics variables
428
/// Here, gridWidth is equivalent to maxAdvance (slightly bigger though)
429
/// and gridHeight is equivalent to lineHeight
430
private int maxAscent, maxDescent, gridWidth = 0, gridHeight = 0;
431
432
/// Offset from the top left edge of the canvas where the draw will start
433
private int canvasInset_X = 5, canvasInset_Y = 5;
434
435
/// LineBreak'ed TextLayout vector
436
private Vector<TextLayout> lineBreakTLs = null;
437
438
/// Whether the current draw command requested is for printing
439
private boolean isPrinting = false;
440
441
/// Other printing infos
442
private int lastPage, printPageNumber, currentlyShownChar = 0;
443
private final int PR_OFFSET = 10;
444
private final int PR_TITLE_LINEHEIGHT = 30;
445
446
/// Information about zooming (used with range text draw)
447
private final JWindow zoomWindow;
448
private BufferedImage zoomImage = null;
449
private int mouseOverCharX = -1, mouseOverCharY = -1;
450
private int currMouseOverChar = -1, prevZoomChar = -1;
451
private float ZOOM = 2.0f;
452
private boolean nowZooming = false;
453
private boolean firstTime = true;
454
// ABP
455
456
/// Status bar message backup
457
private String backupStatusString = null;
458
459
/// Error constants
460
private final String[] ERRORS = {
461
"ERROR: drawBytes cannot handle characters beyond 0x00FF. Select different range or draw methods.",
462
"ERROR: Cannot fit text with the current font size. Resize the window or use smaller font size.",
463
"ERROR: Cannot print with the current font size. Use smaller font size.",
464
};
465
466
private final int DRAW_BYTES_ERROR = 0;
467
private final int CANT_FIT_DRAW = 1;
468
private final int CANT_FIT_PRINT = 2;
469
470
/// Other variables
471
private final Cursor blankCursor;
472
473
public FontCanvas() {
474
this.addMouseListener( this );
475
this.addMouseMotionListener( this );
476
this.setForeground( Color.black );
477
this.setBackground( Color.white );
478
479
/// Creates an invisble pointer by giving it bogus image
480
/// Possibly find a workaround for this...
481
Toolkit tk = Toolkit.getDefaultToolkit();
482
byte[] bogus = { (byte) 0 };
483
blankCursor =
484
tk.createCustomCursor( tk.createImage( bogus ), new Point(0, 0), "" );
485
486
zoomWindow = new JWindow( parent ) {
487
public void paint( Graphics g ) {
488
g.drawImage( zoomImage, 0, 0, zoomWindow );
489
}
490
};
491
zoomWindow.setCursor( blankCursor );
492
zoomWindow.pack();
493
}
494
495
public boolean firstTime() { return firstTime; }
496
public void refresh() {
497
firstTime = false;
498
repaint();
499
}
500
501
/// Sets the font, hints, according to the set parameters
502
private void setParams( Graphics2D g2 ) {
503
g2.setFont( testFont );
504
g2.setRenderingHint(KEY_TEXT_ANTIALIASING, antiAliasType);
505
g2.setRenderingHint(KEY_FRACTIONALMETRICS, fractionalMetricsType);
506
g2.setRenderingHint(KEY_TEXT_LCD_CONTRAST, lcdContrast);
507
/* I am preserving a somewhat dubious behaviour of this program.
508
* Outline text would be drawn anti-aliased by setting the
509
* graphics anti-aliasing hint if the text anti-aliasing hint
510
* was set. The dubious element here is that people simply
511
* using this program may think this is built-in behaviour
512
* but its not - at least not when the app explicitly draws
513
* outline text.
514
* This becomes more dubious in cases such as "GASP" where the
515
* size at which text is AA'ed is not something you can easily
516
* calculate, so mimicing that behaviour isn't going to be easy.
517
* So I precisely preserve the behaviour : this is done only
518
* if the AA value is "ON". Its not applied in the other cases.
519
*/
520
if (antiAliasType == VALUE_TEXT_ANTIALIAS_ON &&
521
(drawMethod == TL_OUTLINE || drawMethod == GV_OUTLINE)) {
522
g2.setRenderingHint(KEY_ANTIALIASING, VALUE_ANTIALIAS_ON);
523
} else {
524
g2.setRenderingHint(KEY_ANTIALIASING, VALUE_ANTIALIAS_OFF);
525
}
526
}
527
528
/// Draws the grid (Used for unicode/glyph range drawing)
529
private void drawGrid( Graphics2D g2 ) {
530
int totalGridWidth = numCharAcross * gridWidth;
531
int totalGridHeight = numCharDown * gridHeight;
532
533
g2.setColor( Color.black );
534
for ( int i = 0; i < numCharDown + 1; i++ )
535
g2.drawLine( canvasInset_X, i * gridHeight + canvasInset_Y,
536
canvasInset_X + totalGridWidth, i * gridHeight + canvasInset_Y );
537
for ( int i = 0; i < numCharAcross + 1; i++ )
538
g2.drawLine( i * gridWidth + canvasInset_X, canvasInset_Y,
539
i * gridWidth + canvasInset_X, canvasInset_Y + totalGridHeight );
540
}
541
542
/// Draws one character at time onto the canvas according to
543
/// the method requested (Used for RANGE_TEXT and ALL_GLYPHS)
544
public void modeSpecificDrawChar( Graphics2D g2, int charCode,
545
int baseX, int baseY ) {
546
GlyphVector gv;
547
int[] oneGlyph = { charCode };
548
char[] charArray = Character.toChars( charCode );
549
550
FontRenderContext frc = g2.getFontRenderContext();
551
AffineTransform oldTX = g2.getTransform();
552
553
/// Create GlyphVector to measure the exact visual advance
554
/// Using that number, adjust the position of the character drawn
555
if ( textToUse == ALL_GLYPHS )
556
gv = testFont.createGlyphVector( frc, oneGlyph );
557
else
558
gv = testFont.createGlyphVector( frc, charArray );
559
Rectangle2D r2d2 = gv.getPixelBounds(frc, 0, 0);
560
int shiftedX = baseX;
561
// getPixelBounds returns a result in device space.
562
// we need to convert back to user space to be able to
563
// calculate the shift as baseX is in user space.
564
try {
565
double[] pt = new double[4];
566
pt[0] = r2d2.getX();
567
pt[1] = r2d2.getY();
568
pt[2] = r2d2.getX()+r2d2.getWidth();
569
pt[3] = r2d2.getY()+r2d2.getHeight();
570
oldTX.inverseTransform(pt,0,pt,0,2);
571
shiftedX = baseX - (int) ( pt[2] / 2 + pt[0] );
572
} catch (NoninvertibleTransformException e) {
573
}
574
575
/// ABP - keep track of old tform, restore it later
576
577
g2.translate( shiftedX, baseY );
578
g2.transform( getAffineTransform( g2Transform ) );
579
580
if ( textToUse == ALL_GLYPHS )
581
g2.drawGlyphVector( gv, 0f, 0f );
582
else {
583
if ( testFont.canDisplay( charCode ))
584
g2.setColor( Color.black );
585
else {
586
g2.setColor( Color.lightGray );
587
}
588
589
switch ( drawMethod ) {
590
case DRAW_STRING:
591
g2.drawString( new String( charArray ), 0, 0 );
592
break;
593
case DRAW_CHARS:
594
g2.drawChars( charArray, 0, 1, 0, 0 );
595
break;
596
case DRAW_BYTES:
597
if ( charCode > 0xff )
598
throw new CannotDrawException( DRAW_BYTES_ERROR );
599
byte[] oneByte = { (byte) charCode };
600
g2.drawBytes( oneByte, 0, 1, 0, 0 );
601
break;
602
case DRAW_GLYPHV:
603
g2.drawGlyphVector( gv, 0f, 0f );
604
break;
605
case TL_DRAW:
606
TextLayout tl = new TextLayout( new String( charArray ), testFont, frc );
607
tl.draw( g2, 0f, 0f );
608
break;
609
case GV_OUTLINE:
610
r2d2 = gv.getVisualBounds();
611
shiftedX = baseX - (int) ( r2d2.getWidth() / 2 + r2d2.getX() );
612
g2.draw( gv.getOutline( 0f, 0f ));
613
break;
614
case TL_OUTLINE:
615
r2d2 = gv.getVisualBounds();
616
shiftedX = baseX - (int) ( r2d2.getWidth() / 2 + r2d2.getX() );
617
TextLayout tlo =
618
new TextLayout( new String( charArray ), testFont,
619
g2.getFontRenderContext() );
620
g2.draw( tlo.getOutline( null ));
621
}
622
}
623
624
/// ABP - restore old tform
625
g2.setTransform ( oldTX );
626
}
627
628
/// Draws one line of text at given position
629
private void modeSpecificDrawLine( Graphics2D g2, String line,
630
int baseX, int baseY ) {
631
/// ABP - keep track of old tform, restore it later
632
AffineTransform oldTx = null;
633
oldTx = g2.getTransform();
634
g2.translate( baseX, baseY );
635
g2.transform( getAffineTransform( g2Transform ) );
636
637
switch ( drawMethod ) {
638
case DRAW_STRING:
639
g2.drawString( line, 0, 0 );
640
break;
641
case DRAW_CHARS:
642
g2.drawChars( line.toCharArray(), 0, line.length(), 0, 0 );
643
break;
644
case DRAW_BYTES:
645
try {
646
byte[] lineBytes = line.getBytes( "ISO-8859-1" );
647
g2.drawBytes( lineBytes, 0, lineBytes.length, 0, 0 );
648
}
649
catch ( Exception e ) {
650
e.printStackTrace();
651
}
652
break;
653
case DRAW_GLYPHV:
654
GlyphVector gv =
655
testFont.createGlyphVector( g2.getFontRenderContext(), line );
656
g2.drawGlyphVector( gv, (float) 0, (float) 0 );
657
break;
658
case TL_DRAW:
659
TextLayout tl = new TextLayout( line, testFont,
660
g2.getFontRenderContext() );
661
tl.draw( g2, (float) 0, (float) 0 );
662
break;
663
case GV_OUTLINE:
664
GlyphVector gvo =
665
testFont.createGlyphVector( g2.getFontRenderContext(), line );
666
g2.draw( gvo.getOutline( (float) 0, (float) 0 ));
667
break;
668
case TL_OUTLINE:
669
TextLayout tlo =
670
new TextLayout( line, testFont,
671
g2.getFontRenderContext() );
672
AffineTransform at = new AffineTransform();
673
g2.draw( tlo.getOutline( at ));
674
}
675
676
/// ABP - restore old tform
677
g2.setTransform ( oldTx );
678
679
}
680
681
/// Draws one line of text at given position
682
private void tlDrawLine( Graphics2D g2, TextLayout tl,
683
float baseX, float baseY ) {
684
/// ABP - keep track of old tform, restore it later
685
AffineTransform oldTx = null;
686
oldTx = g2.getTransform();
687
g2.translate( baseX, baseY );
688
g2.transform( getAffineTransform( g2Transform ) );
689
690
tl.draw( g2, (float) 0, (float) 0 );
691
692
/// ABP - restore old tform
693
g2.setTransform ( oldTx );
694
695
}
696
697
698
/// If textToUse is set to range drawing, then convert
699
/// int to hex string and prepends 0s to make it length 4
700
/// Otherwise line number was fed; simply return number + 1 converted to String
701
/// (This is because first line is 1, not 0)
702
private String modeSpecificNumStr( int i ) {
703
if ( textToUse == USER_TEXT || textToUse == FILE_TEXT )
704
return String.valueOf( i + 1 );
705
706
StringBuffer s = new StringBuffer( Integer.toHexString( i ));
707
while ( s.length() < 4 )
708
s.insert( 0, "0" );
709
return s.toString().toUpperCase();
710
}
711
712
/// Resets the scrollbar to display correct range of text currently on screen
713
/// (This scrollbar is not part of a "ScrollPane". It merely simulates its effect by
714
/// indicating the necessary area to be drawn within the panel.
715
/// By doing this, it prevents creating gigantic panel when large text range,
716
/// i.e. CJK Ideographs, is requested)
717
private void resetScrollbar( int oldValue ) {
718
int totalNumRows = 1, numCharToDisplay;
719
if ( textToUse == RANGE_TEXT || textToUse == ALL_GLYPHS ) {
720
if ( textToUse == RANGE_TEXT )
721
numCharToDisplay = drawRange[1] - drawRange[0];
722
else /// textToUse == ALL_GLYPHS
723
numCharToDisplay = testFont.getNumGlyphs();
724
725
totalNumRows = numCharToDisplay / numCharAcross;
726
if ( numCharToDisplay % numCharAcross != 0 )
727
totalNumRows++;
728
if ( oldValue / numCharAcross > totalNumRows )
729
oldValue = 0;
730
731
verticalBar.setValues( oldValue / numCharAcross,
732
numCharDown, 0, totalNumRows );
733
}
734
else {
735
if ( textToUse == USER_TEXT )
736
totalNumRows = userText.length;
737
else /// textToUse == FILE_TEXT;
738
totalNumRows = lineBreakTLs.size();
739
verticalBar.setValues( oldValue, numCharDown, 0, totalNumRows );
740
}
741
if ( totalNumRows <= numCharDown && drawStart == 0) {
742
verticalBar.setEnabled( false );
743
}
744
else {
745
verticalBar.setEnabled( true );
746
}
747
}
748
749
/// Calculates the font's metrics that will be used for draw
750
private void calcFontMetrics( Graphics2D g2d, int w, int h ) {
751
FontMetrics fm;
752
Graphics2D g2 = (Graphics2D)g2d.create();
753
754
/// ABP
755
if ( g2Transform != NONE && textToUse != FILE_TEXT ) {
756
g2.setFont( g2.getFont().deriveFont( getAffineTransform( g2Transform )) );
757
fm = g2.getFontMetrics();
758
}
759
else {
760
fm = g2.getFontMetrics();
761
}
762
763
maxAscent = fm.getMaxAscent();
764
maxDescent = fm.getMaxDescent();
765
if (maxAscent == 0) maxAscent = 10;
766
if (maxDescent == 0) maxDescent = 5;
767
if ( textToUse == RANGE_TEXT || textToUse == ALL_GLYPHS ) {
768
/// Give slight extra room for each character
769
maxAscent += 3;
770
maxDescent += 3;
771
gridWidth = fm.getMaxAdvance() + 6;
772
gridHeight = maxAscent + maxDescent;
773
if ( force16Cols )
774
numCharAcross = 16;
775
else
776
numCharAcross = ( w - 10 ) / gridWidth;
777
numCharDown = ( h - 10 ) / gridHeight;
778
779
canvasInset_X = ( w - numCharAcross * gridWidth ) / 2;
780
canvasInset_Y = ( h - numCharDown * gridHeight ) / 2;
781
if ( numCharDown == 0 || numCharAcross == 0 )
782
throw new CannotDrawException( isPrinting ? CANT_FIT_PRINT : CANT_FIT_DRAW );
783
784
if ( !isPrinting )
785
resetScrollbar( verticalBar.getValue() * numCharAcross );
786
}
787
else {
788
maxDescent += fm.getLeading();
789
canvasInset_X = 5;
790
canvasInset_Y = 5;
791
/// gridWidth and numCharAcross will not be used in this mode...
792
gridHeight = maxAscent + maxDescent;
793
numCharDown = ( h - canvasInset_Y * 2 ) / gridHeight;
794
795
if ( numCharDown == 0 )
796
throw new CannotDrawException( isPrinting ? CANT_FIT_PRINT : CANT_FIT_DRAW );
797
/// If this is text loaded from file, prepares the LineBreak'ed
798
/// text layout at this point
799
if ( textToUse == FILE_TEXT ) {
800
if ( !isPrinting )
801
f2dt.fireChangeStatus( "LineBreaking Text... Please Wait", false );
802
lineBreakTLs = new Vector<>();
803
for ( int i = 0; i < fileText.length; i++ ) {
804
AttributedString as =
805
new AttributedString( fileText[i], g2.getFont().getAttributes() );
806
807
LineBreakMeasurer lbm =
808
new LineBreakMeasurer( as.getIterator(), g2.getFontRenderContext() );
809
810
while ( lbm.getPosition() < fileText[i].length() )
811
lineBreakTLs.add( lbm.nextLayout( (float) w ));
812
813
}
814
}
815
if ( !isPrinting )
816
resetScrollbar( verticalBar.getValue() );
817
}
818
}
819
820
/// Calculates the amount of text that will be displayed on screen
821
private void calcTextRange() {
822
String displaying = null;
823
824
if ( textToUse == RANGE_TEXT || textToUse == ALL_GLYPHS ) {
825
if ( isPrinting )
826
if ( printMode == ONE_PAGE )
827
drawStart = currentlyShownChar;
828
else /// printMode == CUR_RANGE
829
drawStart = numCharAcross * numCharDown * printPageNumber;
830
else
831
drawStart = verticalBar.getValue() * numCharAcross;
832
if ( textToUse == RANGE_TEXT ) {
833
drawStart += drawRange[0];
834
drawLimit = drawRange[1];
835
}
836
else
837
drawLimit = testFont.getNumGlyphs();
838
drawEnd = drawStart + numCharAcross * numCharDown - 1;
839
840
if ( drawEnd >= drawLimit )
841
drawEnd = drawLimit;
842
}
843
else {
844
if ( isPrinting )
845
if ( printMode == ONE_PAGE )
846
drawStart = currentlyShownChar;
847
else /// printMode == ALL_TEXT
848
drawStart = numCharDown * printPageNumber;
849
else {
850
drawStart = verticalBar.getValue();
851
}
852
853
drawEnd = drawStart + numCharDown - 1;
854
855
if ( textToUse == USER_TEXT )
856
drawLimit = userText.length - 1;
857
else
858
drawLimit = lineBreakTLs.size() - 1;
859
860
if ( drawEnd >= drawLimit )
861
drawEnd = drawLimit;
862
}
863
864
// ABP
865
if ( drawStart > drawEnd ) {
866
drawStart = 0;
867
verticalBar.setValue(drawStart);
868
}
869
870
871
/// Change the status bar if not printing...
872
if ( !isPrinting ) {
873
backupStatusString = ( "Displaying" + MS_OPENING[textToUse] +
874
modeSpecificNumStr( drawStart ) + " to " +
875
modeSpecificNumStr( drawEnd ) +
876
MS_CLOSING[textToUse] );
877
f2dt.fireChangeStatus( backupStatusString, false );
878
}
879
}
880
881
/// Draws text according to the parameters set by Font2DTest GUI
882
private void drawText( Graphics g, int w, int h ) {
883
Graphics2D g2 = (Graphics2D) g;
884
g2.setColor(Color.white);
885
g2.fillRect(0, 0, w, h);
886
g2.setColor(Color.black);
887
888
/// sets font, RenderingHints.
889
setParams( g2 );
890
891
/// If flag is set, recalculate fontMetrics and reset the scrollbar
892
if ( updateFontMetrics || isPrinting ) {
893
/// NOTE: re-calculates in case G2 transform
894
/// is something other than NONE
895
calcFontMetrics( g2, w, h );
896
updateFontMetrics = false;
897
}
898
/// Calculate the amount of text that can be drawn...
899
calcTextRange();
900
901
/// Draw according to the set "Text to Use" mode
902
if ( textToUse == RANGE_TEXT || textToUse == ALL_GLYPHS ) {
903
int charToDraw = drawStart;
904
if ( showGrid )
905
drawGrid( g2 );
906
907
for ( int i = 0; i < numCharDown && charToDraw <= drawEnd; i++ ) {
908
for ( int j = 0; j < numCharAcross && charToDraw <= drawEnd; j++, charToDraw++ ) {
909
int gridLocX = j * gridWidth + canvasInset_X;
910
int gridLocY = i * gridHeight + canvasInset_Y;
911
912
modeSpecificDrawChar( g2, charToDraw,
913
gridLocX + gridWidth / 2,
914
gridLocY + maxAscent );
915
916
}
917
}
918
}
919
else if ( textToUse == USER_TEXT ) {
920
g2.drawRect( 0, 0, w - 1, h - 1 );
921
for ( int i = drawStart; i <= drawEnd; i++ ) {
922
int lineStartX = canvasInset_Y;
923
int lineStartY = ( i - drawStart ) * gridHeight + maxAscent;
924
modeSpecificDrawLine( g2, userText[i], lineStartX, lineStartY );
925
}
926
}
927
else {
928
float xPos, yPos = (float) canvasInset_Y;
929
g2.drawRect( 0, 0, w - 1, h - 1 );
930
for ( int i = drawStart; i <= drawEnd; i++ ) {
931
TextLayout oneLine = lineBreakTLs.elementAt( i );
932
xPos =
933
oneLine.isLeftToRight() ?
934
canvasInset_X : ( (float) w - oneLine.getAdvance() - canvasInset_X );
935
936
float[] fmData = {0, oneLine.getAscent(), 0, oneLine.getDescent(), 0, oneLine.getLeading()};
937
if (g2Transform != NONE) {
938
AffineTransform at = getAffineTransform(g2Transform);
939
at.transform( fmData, 0, fmData, 0, 3);
940
}
941
//yPos += oneLine.getAscent();
942
yPos += fmData[1]; // ascent
943
//oneLine.draw( g2, xPos, yPos );
944
tlDrawLine( g2, oneLine, xPos, yPos );
945
//yPos += oneLine.getDescent() + oneLine.getLeading();
946
yPos += fmData[3] + fmData[5]; // descent + leading
947
}
948
}
949
g2.dispose();
950
}
951
952
/// Component paintComponent function...
953
/// Draws/Refreshes canvas according to flag(s) set by other functions
954
public void paintComponent( Graphics g ) {
955
super.paintComponent(g);
956
957
Dimension d = this.getSize();
958
isPrinting = false;
959
try {
960
drawText( g, d.width, d.height );
961
}
962
catch ( CannotDrawException e ) {
963
super.paintComponent(g);
964
f2dt.fireChangeStatus( ERRORS[ e.id ], true );
965
return;
966
}
967
968
showingError = false;
969
}
970
971
/// Printable interface function
972
/// Component print function...
973
public int print( Graphics g, PageFormat pf, int pageIndex ) {
974
if ( pageIndex == 0 ) {
975
/// Reset the last page index to max...
976
lastPage = Integer.MAX_VALUE;
977
currentlyShownChar = verticalBar.getValue() * numCharAcross;
978
}
979
980
if ( printMode == ONE_PAGE ) {
981
if ( pageIndex > 0 )
982
return NO_SUCH_PAGE;
983
}
984
else {
985
if ( pageIndex > lastPage )
986
return NO_SUCH_PAGE;
987
}
988
989
int pageWidth = (int) pf.getImageableWidth();
990
int pageHeight = (int) pf.getImageableHeight();
991
/// Back up metrics and other drawing info before printing modifies it
992
int backupDrawStart = drawStart, backupDrawEnd = drawEnd;
993
int backupNumCharAcross = numCharAcross, backupNumCharDown = numCharDown;
994
Vector<TextLayout> backupLineBreakTLs = null;
995
if ( textToUse == FILE_TEXT )
996
backupLineBreakTLs = new Vector<>(lineBreakTLs);
997
998
printPageNumber = pageIndex;
999
isPrinting = true;
1000
/// Push the actual draw area 60 down to allow info to be printed
1001
g.translate( (int) pf.getImageableX(), (int) pf.getImageableY() + 60 );
1002
try {
1003
drawText( g, pageWidth, pageHeight - 60 );
1004
}
1005
catch ( CannotDrawException e ) {
1006
f2dt.fireChangeStatus( ERRORS[ e.id ], true );
1007
return NO_SUCH_PAGE;
1008
}
1009
1010
/// Draw information about what is being printed
1011
String hints = ( " with antialias " + antiAliasType + "and" +
1012
" fractional metrics " + fractionalMetricsType +
1013
" and lcd contrast = " + lcdContrast);
1014
String infoLine1 = ( "Printing" + MS_OPENING[textToUse] +
1015
modeSpecificNumStr( drawStart ) + " to " +
1016
modeSpecificNumStr( drawEnd ) + MS_CLOSING[textToUse] );
1017
String infoLine2 = ( "With " + fontName + " " + STYLES[fontStyle] + " at " +
1018
fontSize + " point size " + TRANSFORMS[fontTransform] );
1019
String infoLine3 = "Using " + METHODS[drawMethod] + hints;
1020
String infoLine4 = "Page: " + ( pageIndex + 1 );
1021
g.setFont( new Font( "dialog", Font.PLAIN, 12 ));
1022
g.setColor( Color.black );
1023
g.translate( 0, -60 );
1024
g.drawString( infoLine1, 15, 10 );
1025
g.drawString( infoLine2, 15, 22 );
1026
g.drawString( infoLine3, 15, 34 );
1027
g.drawString( infoLine4, 15, 46 );
1028
1029
if ( drawEnd == drawLimit )
1030
/// This indicates that the draw will be completed with this page
1031
lastPage = pageIndex;
1032
1033
/// Restore the changed values back...
1034
/// This is important for JScrollBar settings and LineBreak'ed TLs
1035
drawStart = backupDrawStart;
1036
drawEnd = backupDrawEnd;
1037
numCharAcross = backupNumCharAcross;
1038
numCharDown = backupNumCharDown;
1039
if ( textToUse == FILE_TEXT )
1040
lineBreakTLs = backupLineBreakTLs;
1041
return PAGE_EXISTS;
1042
}
1043
1044
/// Ouputs the current canvas into a given PNG file
1045
public void writePNG( String fileName ) {
1046
try {
1047
int w = this.getSize().width;
1048
int h = this.getSize().height;
1049
BufferedImage buffer = (BufferedImage) this.createImage( w, h );
1050
Graphics2D g2 = buffer.createGraphics();
1051
g2.setColor(Color.white);
1052
g2.fillRect(0, 0, w, h);
1053
g2.setColor(Color.black);
1054
updateFontMetrics = true;
1055
drawText(g2, w, h);
1056
updateFontMetrics = true;
1057
ImageIO.write(buffer, "png", new java.io.File(fileName));
1058
}
1059
catch ( Exception e ) {
1060
f2dt.fireChangeStatus( "ERROR: Failed to Save PNG image; See stack trace", true );
1061
e.printStackTrace();
1062
}
1063
}
1064
1065
/// Figures out whether a character at the pointer location is valid
1066
/// And if so, updates mouse location informations, as well as
1067
/// the information on the status bar
1068
private boolean checkMouseLoc( MouseEvent e ) {
1069
if ( gridWidth != 0 && gridHeight != 0 )
1070
if ( textToUse == RANGE_TEXT || textToUse == ALL_GLYPHS ) {
1071
int charLocX = ( e.getX() - canvasInset_X ) / gridWidth;
1072
int charLocY = ( e.getY() - canvasInset_Y ) / gridHeight;
1073
1074
/// Check to make sure the mouse click location is within drawn area
1075
if ( charLocX >= 0 && charLocY >= 0 &&
1076
charLocX < numCharAcross && charLocY < numCharDown ) {
1077
int mouseOverChar =
1078
charLocX + ( verticalBar.getValue() + charLocY ) * numCharAcross;
1079
if ( textToUse == RANGE_TEXT )
1080
mouseOverChar += drawRange[0];
1081
if ( mouseOverChar > drawEnd )
1082
return false;
1083
1084
mouseOverCharX = charLocX;
1085
mouseOverCharY = charLocY;
1086
currMouseOverChar = mouseOverChar;
1087
/// Update status bar
1088
f2dt.fireChangeStatus( "Pointing to" + MS_OPENING[textToUse] +
1089
modeSpecificNumStr( mouseOverChar ), false );
1090
return true;
1091
}
1092
}
1093
return false;
1094
}
1095
1096
/// Shows (updates) the character zoom window
1097
public void showZoomed() {
1098
GlyphVector gv;
1099
Font backup = testFont;
1100
Point canvasLoc = this.getLocationOnScreen();
1101
1102
/// Calculate the zoom area's location and size...
1103
int dialogOffsetX = (int) ( gridWidth * ( ZOOM - 1 ) / 2 );
1104
int dialogOffsetY = (int) ( gridHeight * ( ZOOM - 1 ) / 2 );
1105
int zoomAreaX =
1106
mouseOverCharX * gridWidth + canvasInset_X - dialogOffsetX;
1107
int zoomAreaY =
1108
mouseOverCharY * gridHeight + canvasInset_Y - dialogOffsetY;
1109
int zoomAreaWidth = (int) ( gridWidth * ZOOM );
1110
int zoomAreaHeight = (int) ( gridHeight * ZOOM );
1111
1112
/// Position and set size of zoom window as needed
1113
zoomWindow.setLocation( canvasLoc.x + zoomAreaX, canvasLoc.y + zoomAreaY );
1114
if ( !nowZooming ) {
1115
if ( zoomWindow.getWarningString() != null )
1116
/// If this is not opened as a "secure" window,
1117
/// it has a banner below the zoom dialog which makes it look really BAD
1118
/// So enlarge it by a bit
1119
zoomWindow.setSize( zoomAreaWidth + 1, zoomAreaHeight + 20 );
1120
else
1121
zoomWindow.setSize( zoomAreaWidth + 1, zoomAreaHeight + 1 );
1122
}
1123
1124
/// Prepare zoomed image
1125
zoomImage =
1126
(BufferedImage) zoomWindow.createImage( zoomAreaWidth + 1,
1127
zoomAreaHeight + 1 );
1128
Graphics2D g2 = (Graphics2D) zoomImage.getGraphics();
1129
testFont = testFont.deriveFont( fontSize * ZOOM );
1130
setParams( g2 );
1131
g2.setColor( Color.white );
1132
g2.fillRect( 0, 0, zoomAreaWidth, zoomAreaHeight );
1133
g2.setColor( Color.black );
1134
g2.drawRect( 0, 0, zoomAreaWidth, zoomAreaHeight );
1135
modeSpecificDrawChar( g2, currMouseOverChar,
1136
zoomAreaWidth / 2, (int) ( maxAscent * ZOOM ));
1137
g2.dispose();
1138
if ( !nowZooming )
1139
zoomWindow.setVisible(true);
1140
/// This is sort of redundant... since there is a paint function
1141
/// inside zoomWindow definition that does the drawImage.
1142
/// (I should be able to call just repaint() here)
1143
/// However, for some reason, that paint function fails to respond
1144
/// from second time and on; So I have to force the paint here...
1145
zoomWindow.getGraphics().drawImage( zoomImage, 0, 0, this );
1146
1147
nowZooming = true;
1148
prevZoomChar = currMouseOverChar;
1149
testFont = backup;
1150
1151
// Windows does not repaint correctly, after
1152
// a zoom. Thus, we need to force the canvas
1153
// to repaint, but only once. After the first repaint,
1154
// everything stabilizes. [ABP]
1155
if ( firstTime() ) {
1156
refresh();
1157
}
1158
}
1159
1160
/// Listener Functions
1161
1162
/// MouseListener interface function
1163
/// Zooms a character when mouse is pressed above it
1164
public void mousePressed( MouseEvent e ) {
1165
if ( !showingError) {
1166
if ( checkMouseLoc( e )) {
1167
showZoomed();
1168
this.setCursor( blankCursor );
1169
}
1170
}
1171
}
1172
1173
/// MouseListener interface function
1174
/// Redraws the area that was drawn over by zoomed character
1175
public void mouseReleased( MouseEvent e ) {
1176
if ( textToUse == RANGE_TEXT || textToUse == ALL_GLYPHS ) {
1177
if ( nowZooming )
1178
zoomWindow.setVisible(false);
1179
nowZooming = false;
1180
}
1181
this.setCursor( Cursor.getDefaultCursor() );
1182
}
1183
1184
/// MouseListener interface function
1185
/// Resets the status bar to display range instead of a specific character
1186
public void mouseExited( MouseEvent e ) {
1187
if ( !showingError && !nowZooming )
1188
f2dt.fireChangeStatus( backupStatusString, false );
1189
}
1190
1191
/// MouseMotionListener interface function
1192
/// Adjusts the status bar message when mouse moves over a character
1193
public void mouseMoved( MouseEvent e ) {
1194
if ( !showingError ) {
1195
if ( !checkMouseLoc( e ))
1196
f2dt.fireChangeStatus( backupStatusString, false );
1197
}
1198
}
1199
1200
/// MouseMotionListener interface function
1201
/// Scrolls the zoomed character when mouse is dragged
1202
public void mouseDragged( MouseEvent e ) {
1203
if ( !showingError )
1204
if ( nowZooming ) {
1205
if ( checkMouseLoc( e ) && currMouseOverChar != prevZoomChar )
1206
showZoomed();
1207
}
1208
}
1209
1210
/// Empty function to comply with interface requirement
1211
public void mouseClicked( MouseEvent e ) {}
1212
public void mouseEntered( MouseEvent e ) {}
1213
}
1214
1215
private final class CannotDrawException extends RuntimeException {
1216
/// Error ID
1217
public final int id;
1218
1219
public CannotDrawException( int i ) {
1220
id = i;
1221
}
1222
}
1223
1224
enum FMValues {
1225
FMDEFAULT ("DEFAULT", VALUE_FRACTIONALMETRICS_DEFAULT),
1226
FMOFF ("OFF", VALUE_FRACTIONALMETRICS_OFF),
1227
FMON ("ON", VALUE_FRACTIONALMETRICS_ON);
1228
1229
private String name;
1230
private Object hint;
1231
1232
private static FMValues[] valArray;
1233
1234
FMValues(String s, Object o) {
1235
name = s;
1236
hint = o;
1237
}
1238
1239
public String toString() {
1240
return name;
1241
}
1242
1243
public Object getHint() {
1244
return hint;
1245
}
1246
public static Object getValue(int ordinal) {
1247
if (valArray == null) {
1248
valArray = FMValues.values();
1249
}
1250
for (int i=0;i<valArray.length;i++) {
1251
if (valArray[i].ordinal() == ordinal) {
1252
return valArray[i];
1253
}
1254
}
1255
return valArray[0];
1256
}
1257
private static FMValues[] getArray() {
1258
if (valArray == null) {
1259
valArray = FMValues.values();
1260
}
1261
return valArray;
1262
}
1263
1264
public static int getHintVal(Object hint) {
1265
getArray();
1266
for (int i=0;i<valArray.length;i++) {
1267
if (valArray[i].getHint() == hint) {
1268
return i;
1269
}
1270
}
1271
return 0;
1272
}
1273
}
1274
1275
enum AAValues {
1276
AADEFAULT ("DEFAULT", VALUE_TEXT_ANTIALIAS_DEFAULT),
1277
AAOFF ("OFF", VALUE_TEXT_ANTIALIAS_OFF),
1278
AAON ("ON", VALUE_TEXT_ANTIALIAS_ON),
1279
AAGASP ("GASP", VALUE_TEXT_ANTIALIAS_GASP),
1280
AALCDHRGB ("LCD_HRGB", VALUE_TEXT_ANTIALIAS_LCD_HRGB),
1281
AALCDHBGR ("LCD_HBGR", VALUE_TEXT_ANTIALIAS_LCD_HBGR),
1282
AALCDVRGB ("LCD_VRGB", VALUE_TEXT_ANTIALIAS_LCD_VRGB),
1283
AALCDVBGR ("LCD_VBGR", VALUE_TEXT_ANTIALIAS_LCD_VBGR);
1284
1285
private String name;
1286
private Object hint;
1287
1288
private static AAValues[] valArray;
1289
1290
AAValues(String s, Object o) {
1291
name = s;
1292
hint = o;
1293
}
1294
1295
public String toString() {
1296
return name;
1297
}
1298
1299
public Object getHint() {
1300
return hint;
1301
}
1302
1303
public static boolean isLCDMode(Object o) {
1304
return (o instanceof AAValues &&
1305
((AAValues)o).ordinal() >= AALCDHRGB.ordinal());
1306
}
1307
1308
public static Object getValue(int ordinal) {
1309
if (valArray == null) {
1310
valArray = AAValues.values();
1311
}
1312
for (int i=0;i<valArray.length;i++) {
1313
if (valArray[i].ordinal() == ordinal) {
1314
return valArray[i];
1315
}
1316
}
1317
return valArray[0];
1318
}
1319
1320
private static AAValues[] getArray() {
1321
if (valArray == null) {
1322
valArray = AAValues.values();
1323
}
1324
return valArray;
1325
}
1326
1327
public static int getHintVal(Object hint) {
1328
getArray();
1329
for (int i=0;i<valArray.length;i++) {
1330
if (valArray[i].getHint() == hint) {
1331
return i;
1332
}
1333
}
1334
return 0;
1335
}
1336
1337
}
1338
1339
private static Integer defaultContrast;
1340
static Integer getDefaultLCDContrast() {
1341
if (defaultContrast == null) {
1342
GraphicsConfiguration gc =
1343
GraphicsEnvironment.getLocalGraphicsEnvironment().
1344
getDefaultScreenDevice().getDefaultConfiguration();
1345
Graphics2D g2d =
1346
(Graphics2D)(gc.createCompatibleImage(1,1).getGraphics());
1347
defaultContrast = (Integer)
1348
g2d.getRenderingHint(RenderingHints.KEY_TEXT_LCD_CONTRAST);
1349
}
1350
return defaultContrast;
1351
}
1352
}
1353
1354