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