KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > FontPanel


1 /*
2  * @(#)FontPanel.java 1.20 05/11/17
3  *
4  * Copyright (c) 2006 Sun Microsystems, Inc. All Rights Reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  * -Redistribution of source code must retain the above copyright notice, this
10  * list of conditions and the following disclaimer.
11  *
12  * -Redistribution in binary form must reproduce the above copyright notice,
13  * this list of conditions and the following disclaimer in the documentation
14  * and/or other materials provided with the distribution.
15  *
16  * Neither the name of Sun Microsystems, Inc. or the names of contributors may
17  * be used to endorse or promote products derived from this software without
18  * specific prior written permission.
19  *
20  * This software is provided "AS IS," without a warranty of any kind. ALL
21  * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
22  * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
23  * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")
24  * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
25  * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
26  * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
27  * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
28  * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
29  * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
30  * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
31  *
32  * You acknowledge that this software is not designed, licensed or intended
33  * for use in the design, construction, operation or maintenance of any
34  * nuclear facility.
35  */

36
37 /*
38  * @(#)FontPanel.java 1.20 05/11/17
39  */

40
41 import java.awt.BorderLayout JavaDoc;
42 import java.awt.Color JavaDoc;
43 import java.awt.Cursor JavaDoc;
44 import java.awt.Dimension JavaDoc;
45 import java.awt.Font JavaDoc;
46 import java.awt.FontMetrics JavaDoc;
47 import java.awt.Graphics JavaDoc;
48 import java.awt.Graphics2D JavaDoc;
49 import java.awt.GraphicsConfiguration JavaDoc;
50 import java.awt.GraphicsEnvironment JavaDoc;
51 import java.awt.Point JavaDoc;
52 import java.awt.Rectangle JavaDoc;
53 import java.awt.RenderingHints JavaDoc;
54 import java.awt.Toolkit JavaDoc;
55 import java.awt.event.AdjustmentEvent JavaDoc;
56 import java.awt.event.AdjustmentListener JavaDoc;
57 import java.awt.event.ComponentAdapter JavaDoc;
58 import java.awt.event.ComponentEvent JavaDoc;
59 import java.awt.event.MouseEvent JavaDoc;
60 import java.awt.event.MouseListener JavaDoc;
61 import java.awt.event.MouseMotionListener JavaDoc;
62 import java.awt.font.FontRenderContext JavaDoc;
63 import java.awt.font.GlyphVector JavaDoc;
64 import java.awt.font.LineBreakMeasurer JavaDoc;
65 import java.awt.font.TextLayout JavaDoc;
66 import java.awt.geom.AffineTransform JavaDoc;
67 import java.awt.geom.NoninvertibleTransformException JavaDoc;
68 import java.awt.geom.Rectangle2D JavaDoc;
69 import java.awt.image.BufferedImage JavaDoc;
70 import java.awt.print.PageFormat JavaDoc;
71 import java.awt.print.Printable JavaDoc;
72 import java.awt.print.PrinterJob JavaDoc;
73 import java.io.BufferedOutputStream JavaDoc;
74 import java.io.FileOutputStream JavaDoc;
75 import java.text.AttributedString JavaDoc;
76 import java.util.EnumSet JavaDoc;
77 import java.util.Vector JavaDoc;
78
79 import javax.imageio.*;
80 import javax.swing.*;
81
82 import static java.awt.RenderingHints JavaDoc.*;
83
84 /**
85  * FontPanel.java
86  *
87  * @version @(#)FontPanel.java 1.1 00/08/22
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 JavaDoc {
96
97     /// Drawing Option Constants
98
private final String JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc MS_OPENING[] =
124       { " Unicode ", " Glyph Code ", " lines ", " lines " };
125     private final String JavaDoc 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 JavaDoc page = null;
144     private PrinterJob JavaDoc printer = null;
145
146     /// Text drawing variables
147
private String JavaDoc fontName = "Dialog";
148     private float fontSize = 12;
149     private int fontStyle = Font.PLAIN;
150     private int fontTransform = NONE;
151     private Font JavaDoc testFont = null;
152     private Object JavaDoc antiAliasType = VALUE_TEXT_ANTIALIAS_DEFAULT;
153     private Object JavaDoc fractionalMetricsType = VALUE_FRACTIONALMETRICS_DEFAULT;
154     private Object JavaDoc lcdContrast = getDefaultLCDContrast();
155     private int drawMethod = DRAW_STRING;
156     private int textToUse = RANGE_TEXT;
157     private String JavaDoc userText[] = null;
158     private String JavaDoc fileText[] = null;
159     private int drawRange[] = { 0x0000, 0x007f };
160     private String JavaDoc fontInfos[] = new String JavaDoc[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 JavaDoc() );
175         this.add( "Center", fc );
176         this.add( "East", verticalBar );
177
178         verticalBar.addAdjustmentListener( this );
179         this.addComponentListener( new ComponentAdapter JavaDoc() {
180             public void componentResized( ComponentEvent JavaDoc e ) {
181                 updateBackBuffer = true;
182                 updateFontMetrics = true;
183             }
184         });
185
186         /// Initialize font and its infos
187
testFont = new Font JavaDoc(fontName, fontStyle, (int)fontSize);
188     if ((float)((int)fontSize) != fontSize) {
189         testFont = testFont.deriveFont(fontSize);
190     }
191         updateFontInfo();
192     }
193
194     public Dimension JavaDoc getPreferredSize() {
195         return new Dimension JavaDoc(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 JavaDoc getAffineTransform( int transform ) {
209         /// ABP
210
AffineTransform JavaDoc at = new AffineTransform JavaDoc();
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 JavaDoc obj, float size,
230                   int style, int transform) {
231         setFontParams( (String JavaDoc)obj, size, style, transform );
232     }
233
234     public void setFontParams(String JavaDoc 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 JavaDoc(fontName, fontStyle, (int)fontSize);
247     if ((float)((int)fontSize) != fontSize) {
248         testFont = testFont.deriveFont(fontSize);
249     }
250
251         if ( fontTransform != NONE ) {
252             AffineTransform JavaDoc 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 JavaDoc aa, Object JavaDoc fm, Object JavaDoc 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 JavaDoc textSet[], String JavaDoc 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 JavaDoc 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 JavaDoc[] getFontInfo() {
360         return fontInfos;
361     }
362
363     /// Collects the currectly set options and returns them as string
364
public String JavaDoc 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 JavaDoc 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 JavaDoc name, float size, int style,
387                  int transform, int g2transform,
388                              int text, int method, int aa, int fm,
389                  int contrast, String JavaDoc 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 JavaDoc(contrast));
405     }
406
407     /// Writes the current screen to PNG file
408
public void doSavePNG( String JavaDoc fileName ) {
409         fc.writePNG( fileName );
410     }
411
412     /// When scrolled using the scroll bar, update the backbuffer
413
public void adjustmentValueChanged( AdjustmentEvent JavaDoc e ) {
414         updateBackBuffer = true;
415         fc.repaint();
416     }
417
418     public void paintComponent( Graphics JavaDoc 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 JavaDoc, MouseMotionListener JavaDoc, Printable JavaDoc {
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 JavaDoc backBuffer = null;
448
449         /// LineBreak'ed TextLayout vector
450
private Vector JavaDoc 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 JavaDoc 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 JavaDoc backupStatusString = null;
472
473         /// Error constants
474
private final String JavaDoc 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 JavaDoc 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 JavaDoc tk = Toolkit.getDefaultToolkit();
496             byte bogus[] = { (byte) 0 };
497             blankCursor =
498               tk.createCustomCursor( tk.createImage( bogus ), new Point JavaDoc(0, 0), "" );
499
500             zoomWindow = new JWindow( parent ) {
501                 public void paint( Graphics JavaDoc 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 JavaDoc 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 explictly 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 JavaDoc 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 JavaDoc g2, int charCode,
560                                           int baseX, int baseY ) {
561             GlyphVector JavaDoc gv;
562             int oneGlyph[] = { charCode };
563             char charArray[] = Character.toChars( charCode );
564
565             FontRenderContext JavaDoc frc = g2.getFontRenderContext();
566             AffineTransform JavaDoc 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 JavaDoc 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 JavaDoc 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 JavaDoc( 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 JavaDoc tl = new TextLayout JavaDoc( new String JavaDoc( 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 JavaDoc tlo =
633                       new TextLayout JavaDoc( new String JavaDoc( 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         // Java2D!\\U01d586\\U01d587\\U01d588
644

645         /// Draws one line of text at given position
646
private void modeSpecificDrawLine( Graphics2D JavaDoc g2, String JavaDoc line,
647                                            int baseX, int baseY ) {
648         /// ABP - keep track of old tform, restore it later
649
AffineTransform JavaDoc oldTx = null;
650         oldTx = g2.getTransform();
651         g2.translate( baseX, baseY );
652         g2.transform( getAffineTransform( g2Transform ) );
653         
654             switch ( drawMethod ) {
655               case DRAW_STRING:
656                 g2.drawString( line, 0, 0 );
657                 break;
658               case DRAW_CHARS:
659                 g2.drawChars( line.toCharArray(), 0, line.length(), 0, 0 );
660                 break;
661               case DRAW_BYTES:
662                 try {
663                     byte lineBytes[] = line.getBytes( "ISO-8859-1" );
664                     g2.drawBytes( lineBytes, 0, lineBytes.length, 0, 0 );
665                 }
666                 catch ( Exception JavaDoc e ) {
667                     e.printStackTrace();
668                 }
669                 break;
670               case DRAW_GLYPHV:
671                 GlyphVector JavaDoc gv =
672                   testFont.createGlyphVector( g2.getFontRenderContext(), line );
673                 g2.drawGlyphVector( gv, (float) 0, (float) 0 );
674                 break;
675               case TL_DRAW:
676                 TextLayout JavaDoc tl = new TextLayout JavaDoc( line, testFont,
677                                                 g2.getFontRenderContext() );
678                 tl.draw( g2, (float) 0, (float) 0 );
679                 break;
680               case GV_OUTLINE:
681                 GlyphVector JavaDoc gvo =
682                   testFont.createGlyphVector( g2.getFontRenderContext(), line );
683                 g2.draw( gvo.getOutline( (float) 0, (float) 0 ));
684                 break;
685               case TL_OUTLINE:
686                 TextLayout JavaDoc tlo =
687                   new TextLayout JavaDoc( line, testFont,
688                                   g2.getFontRenderContext() );
689                 AffineTransform JavaDoc at = new AffineTransform JavaDoc();
690                 g2.draw( tlo.getOutline( at ));
691             }
692             
693         /// ABP - restore old tform
694
g2.setTransform ( oldTx );
695             
696         }
697
698         /// Draws one line of text at given position
699
private void tlDrawLine( Graphics2D JavaDoc g2, TextLayout JavaDoc tl,
700                                            float baseX, float baseY ) {
701         /// ABP - keep track of old tform, restore it later
702
AffineTransform JavaDoc oldTx = null;
703         oldTx = g2.getTransform();
704         g2.translate( baseX, baseY );
705         g2.transform( getAffineTransform( g2Transform ) );
706     
707             tl.draw( g2, (float) 0, (float) 0 );
708
709         /// ABP - restore old tform
710
g2.setTransform ( oldTx );
711             
712         }
713
714
715         /// If textToUse is set to range drawing, then convert
716
/// int to hex string and prepends 0s to make it length 4
717
/// Otherwise line number was fed; simply return number + 1 converted to String
718
/// (This is because first line is 1, not 0)
719
private String JavaDoc modeSpecificNumStr( int i ) {
720             if ( textToUse == USER_TEXT || textToUse == FILE_TEXT )
721               return String.valueOf( i + 1 );
722
723             StringBuffer JavaDoc s = new StringBuffer JavaDoc( Integer.toHexString( i ));
724             while ( s.length() < 4 )
725               s.insert( 0, "0" );
726             return s.toString().toUpperCase();
727         }
728
729         /// Resets the scrollbar to display correct range of text currently on screen
730
/// (This scrollbar is not part of a "ScrollPane". It merely simulates its effect by
731
/// indicating the necessary area to be drawn within the panel.
732
/// By doing this, it prevents creating gigantic panel when large text range,
733
/// i.e. CJK Ideographs, is requested)
734
private void resetScrollbar( int oldValue ) {
735             int totalNumRows = 1, numCharToDisplay;
736             if ( textToUse == RANGE_TEXT || textToUse == ALL_GLYPHS ) {
737                 if ( textToUse == RANGE_TEXT )
738                   numCharToDisplay = drawRange[1] - drawRange[0];
739                 else /// textToUse == ALL_GLYPHS
740
numCharToDisplay = testFont.getNumGlyphs();
741
742                 totalNumRows = numCharToDisplay / numCharAcross;
743                 if ( numCharToDisplay % numCharAcross != 0 )
744                   totalNumRows++;
745                 if ( oldValue / numCharAcross > totalNumRows )
746                   oldValue = 0;
747
748                 verticalBar.setValues( oldValue / numCharAcross,
749                                        numCharDown, 0, totalNumRows );
750             }
751             else {
752                 if ( textToUse == USER_TEXT )
753                   totalNumRows = userText.length;
754                 else /// textToUse == FILE_TEXT;
755
totalNumRows = lineBreakTLs.size();
756                 verticalBar.setValues( oldValue, numCharDown, 0, totalNumRows );
757             }
758             if ( totalNumRows <= numCharDown && drawStart == 0) {
759               verticalBar.setEnabled( false );
760             }
761             else {
762               verticalBar.setEnabled( true );
763             }
764         }
765
766         /// Calculates the font's metrics that will be used for draw
767
private void calcFontMetrics( Graphics2D JavaDoc g2d, int w, int h ) {
768             FontMetrics JavaDoc fm;
769             Graphics2D JavaDoc g2 = (Graphics2D JavaDoc)g2d.create();
770             
771             /// ABP
772
if ( g2Transform != NONE && textToUse != FILE_TEXT ) {
773                 g2.setFont( g2.getFont().deriveFont( getAffineTransform( g2Transform )) );
774                 fm = g2.getFontMetrics();
775             }
776             else {
777                 fm = g2.getFontMetrics();
778             }
779
780             maxAscent = fm.getMaxAscent();
781             maxDescent = fm.getMaxDescent();
782         if (maxAscent == 0) maxAscent = 10;
783         if (maxDescent == 0) maxDescent = 5;
784             if ( textToUse == RANGE_TEXT || textToUse == ALL_GLYPHS ) {
785                 /// Give slight extra room for each character
786
maxAscent += 3;
787                 maxDescent += 3;
788                 gridWidth = fm.getMaxAdvance() + 6;
789                 gridHeight = maxAscent + maxDescent;
790                 if ( force16Cols )
791                   numCharAcross = 16;
792                 else
793                   numCharAcross = ( w - 10 ) / gridWidth;
794                 numCharDown = ( h - 10 ) / gridHeight;
795
796                 canvasInset_X = ( w - numCharAcross * gridWidth ) / 2;
797                 canvasInset_Y = ( h - numCharDown * gridHeight ) / 2;
798                 if ( numCharDown == 0 || numCharAcross == 0 )
799                   throw new CannotDrawException( isPrinting ? CANT_FIT_PRINT : CANT_FIT_DRAW );
800
801                 if ( !isPrinting )
802                   resetScrollbar( verticalBar.getValue() * numCharAcross );
803             }
804             else {
805                 maxDescent += fm.getLeading();
806                 canvasInset_X = 5;
807                 canvasInset_Y = 5;
808                 /// gridWidth and numCharAcross will not be used in this mode...
809
gridHeight = maxAscent + maxDescent;
810                 numCharDown = ( h - canvasInset_Y * 2 ) / gridHeight;
811
812                 if ( numCharDown == 0 )
813                   throw new CannotDrawException( isPrinting ? CANT_FIT_PRINT : CANT_FIT_DRAW );
814                 /// If this is text loaded from file, prepares the LineBreak'ed
815
/// text layout at this point
816
if ( textToUse == FILE_TEXT ) {
817                     if ( !isPrinting )
818                       f2dt.fireChangeStatus( "LineBreaking Text... Please Wait", false );
819                     lineBreakTLs = new Vector JavaDoc();
820                     for ( int i = 0; i < fileText.length; i++ ) {
821                         AttributedString JavaDoc as =
822                           new AttributedString JavaDoc( fileText[i], g2.getFont().getAttributes() );
823
824                         LineBreakMeasurer JavaDoc lbm =
825                           new LineBreakMeasurer JavaDoc( as.getIterator(), g2.getFontRenderContext() );
826
827                         while ( lbm.getPosition() < fileText[i].length() )
828                           lineBreakTLs.add( lbm.nextLayout( (float) w ));
829
830                     }
831                 }
832                 if ( !isPrinting )
833                   resetScrollbar( verticalBar.getValue() );
834             }
835         }
836
837         /// Calculates the amount of text that will be displayed on screen
838
private void calcTextRange() {
839             String JavaDoc displaying = null;
840
841             if ( textToUse == RANGE_TEXT || textToUse == ALL_GLYPHS ) {
842                 if ( isPrinting )
843                   if ( printMode == ONE_PAGE )
844                     drawStart = currentlyShownChar;
845                   else /// printMode == CUR_RANGE
846
drawStart = numCharAcross * numCharDown * printPageNumber;
847                 else
848                   drawStart = verticalBar.getValue() * numCharAcross;
849                 if ( textToUse == RANGE_TEXT ) {
850                     drawStart += drawRange[0];
851                     drawLimit = drawRange[1];
852                 }
853                 else
854                   drawLimit = testFont.getNumGlyphs();
855                 drawEnd = drawStart + numCharAcross * numCharDown - 1;
856
857                 if ( drawEnd >= drawLimit )
858                   drawEnd = drawLimit;
859             }
860             else {
861                 if ( isPrinting )
862                   if ( printMode == ONE_PAGE )
863                     drawStart = currentlyShownChar;
864                   else /// printMode == ALL_TEXT
865
drawStart = numCharDown * printPageNumber;
866                 else {
867                     drawStart = verticalBar.getValue();
868                 }
869
870                 drawEnd = drawStart + numCharDown - 1;
871
872                 if ( textToUse == USER_TEXT )
873                   drawLimit = userText.length - 1;
874                 else
875                   drawLimit = lineBreakTLs.size() - 1;
876
877                 if ( drawEnd >= drawLimit )
878                   drawEnd = drawLimit;
879             }
880
881             // ABP
882
if ( drawStart > drawEnd ) {
883               drawStart = 0;
884               verticalBar.setValue(drawStart);
885             }
886
887
888             /// Change the status bar if not printing...
889
if ( !isPrinting ) {
890                 backupStatusString = ( "Displaying" + MS_OPENING[textToUse] +
891                                        modeSpecificNumStr( drawStart ) + " to " +
892                                        modeSpecificNumStr( drawEnd ) +
893                                        MS_CLOSING[textToUse] );
894                 f2dt.fireChangeStatus( backupStatusString, false );
895             }
896         }
897
898         /// Draws text according to the parameters set by Font2DTest GUI
899
private void drawText( Graphics JavaDoc g, int w, int h ) {
900             Graphics2D JavaDoc g2;
901
902             /// Create back buffer when not printing, and its Graphics2D
903
/// Then set drawing parameters for that Graphics2D object
904
if ( isPrinting )
905               g2 = (Graphics2D JavaDoc) g;
906             else {
907                 backBuffer = (BufferedImage JavaDoc) this.createImage( w, h );
908                 g2 = backBuffer.createGraphics();
909                 g2.setColor(Color.white);
910                 g2.fillRect(0, 0, w, h);
911                 g2.setColor(Color.black);
912             }
913             
914             /// sets font, RenderingHints.
915
setParams( g2 );
916
917             /// If flag is set, recalculate fontMetrics and reset the scrollbar
918
if ( updateFontMetrics || isPrinting ) {
919                 /// NOTE: re-calculates in case G2 transform
920
/// is something other than NONE
921
calcFontMetrics( g2, w, h );
922                 updateFontMetrics = false;
923             }
924             /// Calculate the amount of text that can be drawn...
925
calcTextRange();
926
927             /// Draw according to the set "Text to Use" mode
928
if ( textToUse == RANGE_TEXT || textToUse == ALL_GLYPHS ) {
929                 int charToDraw = drawStart;
930                 if ( showGrid )
931                   drawGrid( g2 );
932                 if ( !isPrinting )
933                   g.drawImage( backBuffer, 0, 0, this );
934
935                 for ( int i = 0; i < numCharDown && charToDraw <= drawEnd; i++ ) {
936                   for ( int j = 0; j < numCharAcross && charToDraw <= drawEnd; j++, charToDraw++ ) {
937                       int gridLocX = j * gridWidth + canvasInset_X;
938                       int gridLocY = i * gridHeight + canvasInset_Y;
939
940                       modeSpecificDrawChar( g2, charToDraw,
941                                             gridLocX + gridWidth / 2,
942                                             gridLocY + maxAscent );
943                       //if ( !isPrinting ) {
944
// g.setClip( gridLocX, gridLocY, gridWidth + 1, gridHeight + 1 );
945
// g.drawImage( backBuffer, 0, 0, this );
946
//}
947

948                   }
949                 }
950             }
951             else if ( textToUse == USER_TEXT ) {
952                 g2.drawRect( 0, 0, w - 1, h - 1 );
953                 if ( !isPrinting )
954                   g.drawImage( backBuffer, 0, 0, this );
955
956                 for ( int i = drawStart; i <= drawEnd; i++ ) {
957                     int lineStartX = canvasInset_Y;
958                     int lineStartY = ( i - drawStart ) * gridHeight + maxAscent;
959                     modeSpecificDrawLine( g2, userText[i], lineStartX, lineStartY );
960                 }
961             }
962             else {
963                 float xPos, yPos = (float) canvasInset_Y;
964                 g2.drawRect( 0, 0, w - 1, h - 1 );
965                 if ( !isPrinting )
966                   g.drawImage( backBuffer, 0, 0, this );
967
968                 for ( int i = drawStart; i <= drawEnd; i++ ) {
969                     TextLayout JavaDoc oneLine = (TextLayout JavaDoc) lineBreakTLs.elementAt( i );
970                     xPos =
971                       oneLine.isLeftToRight() ?
972                       canvasInset_X : ( (float) w - oneLine.getAdvance() - canvasInset_X );
973                     
974                     float fmData[] = {0, oneLine.getAscent(), 0, oneLine.getDescent(), 0, oneLine.getLeading()};
975                     if (g2Transform != NONE) {
976                         AffineTransform JavaDoc at = getAffineTransform(g2Transform);
977                         at.transform( fmData, 0, fmData, 0, 3);
978                     }
979                     //yPos += oneLine.getAscent();
980
yPos += fmData[1]; // ascent
981
//oneLine.draw( g2, xPos, yPos );
982
tlDrawLine( g2, oneLine, xPos, yPos );
983                     //yPos += oneLine.getDescent() + oneLine.getLeading();
984
yPos += fmData[3] + fmData[5]; // descent + leading
985
}
986             }
987         if ( !isPrinting )
988                 g.drawImage( backBuffer, 0, 0, this );
989             g2.dispose();
990         }
991
992         /// Component paintComponent function...
993
/// Draws/Refreshes canvas according to flag(s) set by other functions
994
public void paintComponent( Graphics JavaDoc g ) {
995             if ( updateBackBuffer ) {
996                 Dimension JavaDoc d = this.getSize();
997                 isPrinting = false;
998                 try {
999                     drawText( g, d.width, d.height );
1000                }
1001                catch ( CannotDrawException e ) {
1002                    f2dt.fireChangeStatus( ERRORS[ e.id ], true );
1003                    super.paintComponent(g);
1004                    return;
1005                }
1006            }
1007            else {
1008              /// Screen refresh
1009
g.drawImage( backBuffer, 0, 0, this );
1010            }
1011
1012            showingError = false;
1013            updateBackBuffer = false;
1014        }
1015
1016        /// Printable interface function
1017
/// Component print function...
1018
public int print( Graphics JavaDoc g, PageFormat JavaDoc pf, int pageIndex ) {
1019            if ( pageIndex == 0 ) {
1020                /// Reset the last page index to max...
1021
lastPage = Integer.MAX_VALUE;
1022                currentlyShownChar = verticalBar.getValue() * numCharAcross;
1023            }
1024
1025            if ( printMode == ONE_PAGE ) {
1026                if ( pageIndex > 0 )
1027                  return NO_SUCH_PAGE;
1028            }
1029            else {
1030                if ( pageIndex > lastPage )
1031                  return NO_SUCH_PAGE;
1032            }
1033
1034            int pageWidth = (int) pf.getImageableWidth();
1035            int pageHeight = (int) pf.getImageableHeight();
1036            /// Back up metrics and other drawing info before printing modifies it
1037
int backupDrawStart = drawStart, backupDrawEnd = drawEnd;
1038            int backupNumCharAcross = numCharAcross, backupNumCharDown = numCharDown;
1039            Vector JavaDoc backupLineBreakTLs = null;
1040            if ( textToUse == FILE_TEXT )
1041              backupLineBreakTLs = (Vector JavaDoc) lineBreakTLs.clone();
1042
1043            printPageNumber = pageIndex;
1044            isPrinting = true;
1045            /// Push the actual draw area 60 down to allow info to be printed
1046
g.translate( (int) pf.getImageableX(), (int) pf.getImageableY() + 60 );
1047            try {
1048                drawText( g, pageWidth, pageHeight - 60 );
1049            }
1050            catch ( CannotDrawException e ) {
1051                f2dt.fireChangeStatus( ERRORS[ e.id ], true );
1052                return NO_SUCH_PAGE;
1053            }
1054
1055            /// Draw information about what is being printed
1056
String JavaDoc hints = ( " with antialias " + antiAliasType + "and" +
1057                             " fractional metrics " + fractionalMetricsType +
1058                 " and lcd contrast = " + lcdContrast);
1059            String JavaDoc infoLine1 = ( "Printing" + MS_OPENING[textToUse] +
1060                                 modeSpecificNumStr( drawStart ) + " to " +
1061                                 modeSpecificNumStr( drawEnd ) + MS_CLOSING[textToUse] );
1062            String JavaDoc infoLine2 = ( "With " + fontName + " " + STYLES[fontStyle] + " at " +
1063                                 fontSize + " point size " + TRANSFORMS[fontTransform] );
1064            String JavaDoc infoLine3 = "Using " + METHODS[drawMethod] + hints;
1065            String JavaDoc infoLine4 = "Page: " + ( pageIndex + 1 );
1066            g.setFont( new Font JavaDoc( "dialog", Font.PLAIN, 12 ));
1067            g.setColor( Color.black );
1068            g.translate( 0, -60 );
1069            g.drawString( infoLine1, 15, 10 );
1070            g.drawString( infoLine2, 15, 22 );
1071            g.drawString( infoLine3, 15, 34 );
1072            g.drawString( infoLine4, 15, 46 );
1073
1074            if ( drawEnd == drawLimit )
1075              /// This indicates that the draw will be completed with this page
1076
lastPage = pageIndex;
1077
1078            /// Restore the changed values back...
1079
/// This is important for JScrollBar settings and LineBreak'ed TLs
1080
drawStart = backupDrawStart;
1081            drawEnd = backupDrawEnd;
1082            numCharAcross = backupNumCharAcross;
1083            numCharDown = backupNumCharDown;
1084            if ( textToUse == FILE_TEXT )
1085              lineBreakTLs = backupLineBreakTLs;
1086            return PAGE_EXISTS;
1087        }
1088
1089        /// Ouputs the current canvas into a given PNG file
1090
public void writePNG( String JavaDoc fileName ) {
1091            try {
1092        ImageIO.write(backBuffer, "png", new java.io.File JavaDoc(fileName));
1093            }
1094            catch ( Exception JavaDoc e ) {
1095                f2dt.fireChangeStatus( "ERROR: Failed to Save PNG image; See stack trace", true );
1096                e.printStackTrace();
1097            }
1098        }
1099
1100        /// Figures out whether a character at the pointer location is valid
1101
/// And if so, updates mouse location informations, as well as
1102
/// the information on the status bar
1103
private boolean checkMouseLoc( MouseEvent JavaDoc e ) {
1104            if ( gridWidth != 0 && gridHeight != 0 )
1105              if ( textToUse == RANGE_TEXT || textToUse == ALL_GLYPHS ) {
1106                  int charLocX = ( e.getX() - canvasInset_X ) / gridWidth;
1107                  int charLocY = ( e.getY() - canvasInset_Y ) / gridHeight;
1108
1109                  /// Check to make sure the mouse click location is within drawn area
1110
if ( charLocX >= 0 && charLocY >= 0 &&
1111                       charLocX < numCharAcross && charLocY < numCharDown ) {
1112                      int mouseOverChar =
1113                        charLocX + ( verticalBar.getValue() + charLocY ) * numCharAcross;
1114                      if ( textToUse == RANGE_TEXT )
1115                        mouseOverChar += drawRange[0];
1116                      if ( mouseOverChar > drawEnd )
1117                        return false;
1118
1119                      mouseOverCharX = charLocX;
1120                      mouseOverCharY = charLocY;
1121                      currMouseOverChar = mouseOverChar;
1122                      /// Update status bar
1123
f2dt.fireChangeStatus( "Pointing to" + MS_OPENING[textToUse] +
1124                                             modeSpecificNumStr( mouseOverChar ), false );
1125                      return true;
1126                  }
1127              }
1128            return false;
1129        }
1130
1131        /// Shows (updates) the character zoom window
1132
public void showZoomed() {
1133            GlyphVector JavaDoc gv;
1134            Font JavaDoc backup = testFont;
1135            Point JavaDoc canvasLoc = this.getLocationOnScreen();
1136
1137            /// Calculate the zoom area's location and size...
1138
int dialogOffsetX = (int) ( gridWidth * ( ZOOM - 1 ) / 2 );
1139            int dialogOffsetY = (int) ( gridHeight * ( ZOOM - 1 ) / 2 );
1140            int zoomAreaX =
1141              mouseOverCharX * gridWidth + canvasInset_X - dialogOffsetX;
1142            int zoomAreaY =
1143              mouseOverCharY * gridHeight + canvasInset_Y - dialogOffsetY;
1144            int zoomAreaWidth = (int) ( gridWidth * ZOOM );
1145            int zoomAreaHeight = (int) ( gridHeight * ZOOM );
1146
1147            /// Position and set size of zoom window as needed
1148
zoomWindow.setLocation( canvasLoc.x + zoomAreaX, canvasLoc.y + zoomAreaY );
1149            if ( !nowZooming ) {
1150                if ( zoomWindow.getWarningString() != null )
1151                  /// If this is not opened as a "secure" window,
1152
/// it has a banner below the zoom dialog which makes it look really BAD
1153
/// So enlarge it by a bit
1154
zoomWindow.setSize( zoomAreaWidth + 1, zoomAreaHeight + 20 );
1155                else
1156                  zoomWindow.setSize( zoomAreaWidth + 1, zoomAreaHeight + 1 );
1157            }
1158
1159            /// Prepare zoomed image
1160
zoomImage =
1161              (BufferedImage JavaDoc) zoomWindow.createImage( zoomAreaWidth + 1,
1162                                                      zoomAreaHeight + 1 );
1163            Graphics2D JavaDoc g2 = (Graphics2D JavaDoc) zoomImage.getGraphics();
1164            testFont = testFont.deriveFont( fontSize * ZOOM );
1165            setParams( g2 );
1166            g2.setColor( Color.white );
1167            g2.fillRect( 0, 0, zoomAreaWidth, zoomAreaHeight );
1168            g2.setColor( Color.black );
1169            g2.drawRect( 0, 0, zoomAreaWidth, zoomAreaHeight );
1170            modeSpecificDrawChar( g2, currMouseOverChar,
1171                                  zoomAreaWidth / 2, (int) ( maxAscent * ZOOM ));
1172            g2.dispose();
1173            if ( !nowZooming )
1174              zoomWindow.show();
1175            /// This is sort of redundant... since there is a paint function
1176
/// inside zoomWindow definition that does the drawImage.
1177
/// (I should be able to call just repaint() here)
1178
/// However, for some reason, that paint function fails to respond
1179
/// from second time and on; So I have to force the paint here...
1180
zoomWindow.getGraphics().drawImage( zoomImage, 0, 0, this );
1181
1182            nowZooming = true;
1183            prevZoomChar = currMouseOverChar;
1184            testFont = backup;
1185            
1186            // Windows does not repaint correctly, after
1187
// a zoom. Thus, we need to force the canvas
1188
// to repaint, but only once. After the first repaint,
1189
// everything stabilizes. [ABP]
1190
if ( firstTime() ) {
1191                refresh();
1192            }
1193        }
1194
1195        /// Listener Functions
1196

1197        /// MouseListener interface function
1198
/// Zooms a character when mouse is pressed above it
1199
public void mousePressed( MouseEvent JavaDoc e ) {
1200            if ( !showingError) {
1201                if ( checkMouseLoc( e )) {
1202                    showZoomed();
1203                    this.setCursor( blankCursor );
1204                }
1205            }
1206        }
1207
1208        /// MouseListener interface function
1209
/// Redraws the area that was drawn over by zoomed character
1210
public void mouseReleased( MouseEvent JavaDoc e ) {
1211            if ( textToUse == RANGE_TEXT || textToUse == ALL_GLYPHS ) {
1212                if ( nowZooming )
1213                  zoomWindow.hide();
1214                nowZooming = false;
1215            }
1216            this.setCursor( Cursor.getDefaultCursor() );
1217        }
1218
1219        /// MouseListener interface function
1220
/// Resets the status bar to display range instead of a specific character
1221
public void mouseExited( MouseEvent JavaDoc e ) {
1222            if ( !showingError && !nowZooming )
1223              f2dt.fireChangeStatus( backupStatusString, false );
1224        }
1225
1226        /// MouseMotionListener interface function
1227
/// Adjusts the status bar message when mouse moves over a character
1228
public void mouseMoved( MouseEvent JavaDoc e ) {
1229            if ( !showingError ) {
1230                if ( !checkMouseLoc( e ))
1231                  f2dt.fireChangeStatus( backupStatusString, false );
1232            }
1233        }
1234
1235        /// MouseMotionListener interface function
1236
/// Scrolls the zoomed character when mouse is dragged
1237
public void mouseDragged( MouseEvent JavaDoc e ) {
1238            if ( !showingError )
1239              if ( nowZooming ) {
1240                  if ( checkMouseLoc( e ) && currMouseOverChar != prevZoomChar )
1241                    showZoomed();
1242              }
1243        }
1244
1245        /// Empty function to comply with interface requirement
1246
public void mouseClicked( MouseEvent JavaDoc e ) {}
1247        public void mouseEntered( MouseEvent JavaDoc e ) {}
1248    }
1249
1250    private final class CannotDrawException extends RuntimeException JavaDoc {
1251        /// Error ID
1252
public final int id;
1253
1254        public CannotDrawException( int i ) {
1255            id = i;
1256        }
1257    }
1258
1259    enum FMValues {
1260       FMDEFAULT ("DEFAULT", VALUE_FRACTIONALMETRICS_DEFAULT),
1261       FMOFF ("OFF", VALUE_FRACTIONALMETRICS_OFF),
1262       FMON ("ON", VALUE_FRACTIONALMETRICS_ON);
1263
1264        private String JavaDoc name;
1265        private Object JavaDoc hint;
1266
1267        private static FMValues[] valArray;
1268
1269        FMValues(String JavaDoc s, Object JavaDoc o) {
1270            name = s;
1271            hint = o;
1272        }
1273
1274        public String JavaDoc toString() {
1275            return name;
1276        }
1277
1278       public Object JavaDoc getHint() {
1279           return hint;
1280       }
1281       public static Object JavaDoc getValue(int ordinal) {
1282       if (valArray == null) {
1283           valArray = (FMValues[])EnumSet.allOf(FMValues.class).toArray(new FMValues[0]);
1284       }
1285       for (int i=0;i<valArray.length;i++) {
1286           if (valArray[i].ordinal() == ordinal) {
1287           return valArray[i];
1288           }
1289       }
1290       return valArray[0];
1291       }
1292       private static FMValues[] getArray() {
1293       if (valArray == null) {
1294           valArray = (FMValues[])EnumSet.allOf(FMValues.class).toArray(new FMValues[0]);
1295       }
1296       return valArray;
1297       }
1298
1299       public static int getHintVal(Object JavaDoc hint) {
1300       getArray();
1301       for (int i=0;i<valArray.length;i++) {
1302           if (valArray[i].getHint() == hint) {
1303           return i;
1304           }
1305       }
1306       return 0;
1307       }
1308    }
1309
1310   enum AAValues {
1311       AADEFAULT ("DEFAULT", VALUE_TEXT_ANTIALIAS_DEFAULT),
1312       AAOFF ("OFF", VALUE_TEXT_ANTIALIAS_OFF),
1313       AAON ("ON", VALUE_TEXT_ANTIALIAS_ON),
1314       AAGASP ("GASP", VALUE_TEXT_ANTIALIAS_GASP),
1315       AALCDHRGB ("LCD_HRGB", VALUE_TEXT_ANTIALIAS_LCD_HRGB),
1316       AALCDHBGR ("LCD_HBGR", VALUE_TEXT_ANTIALIAS_LCD_HBGR),
1317       AALCDVRGB ("LCD_VRGB", VALUE_TEXT_ANTIALIAS_LCD_VRGB),
1318       AALCDVBGR ("LCD_VBGR", VALUE_TEXT_ANTIALIAS_LCD_VBGR);
1319
1320        private String JavaDoc name;
1321        private Object JavaDoc hint;
1322
1323        private static AAValues[] valArray;
1324
1325        AAValues(String JavaDoc s, Object JavaDoc o) {
1326            name = s;
1327            hint = o;
1328        }
1329
1330        public String JavaDoc toString() {
1331            return name;
1332        }
1333
1334       public Object JavaDoc getHint() {
1335           return hint;
1336       }
1337
1338       public static boolean isLCDMode(Object JavaDoc o) {
1339       return (o instanceof AAValues &&
1340           ((AAValues)o).ordinal() >= AALCDHRGB.ordinal());
1341       }
1342       
1343       public static Object JavaDoc getValue(int ordinal) {
1344       if (valArray == null) {
1345           valArray = (AAValues[])EnumSet.allOf(AAValues.class).toArray(new AAValues[0]);
1346       }
1347       for (int i=0;i<valArray.length;i++) {
1348           if (valArray[i].ordinal() == ordinal) {
1349           return valArray[i];
1350           }
1351       }
1352       return valArray[0];
1353       }
1354
1355       private static AAValues[] getArray() {
1356       if (valArray == null) {
1357           Object JavaDoc [] oa = EnumSet.allOf(AAValues.class).toArray(new AAValues[0]);
1358           valArray = (AAValues[])(EnumSet.allOf(AAValues.class).toArray(new AAValues[0]));
1359       }
1360       return valArray;
1361       }
1362
1363       public static int getHintVal(Object JavaDoc hint) {
1364       getArray();
1365       for (int i=0;i<valArray.length;i++) {
1366           if (valArray[i].getHint() == hint) {
1367           return i;
1368           }
1369       }
1370       return 0;
1371       }
1372
1373    }
1374
1375    private static Integer JavaDoc defaultContrast;
1376    static Integer JavaDoc getDefaultLCDContrast() {
1377    if (defaultContrast == null) {
1378        GraphicsConfiguration JavaDoc gc =
1379        GraphicsEnvironment.getLocalGraphicsEnvironment().
1380        getDefaultScreenDevice().getDefaultConfiguration();
1381    Graphics2D JavaDoc g2d =
1382        (Graphics2D JavaDoc)(gc.createCompatibleImage(1,1).getGraphics());
1383    defaultContrast = (Integer JavaDoc)
1384        g2d.getRenderingHint(RenderingHints.KEY_TEXT_LCD_CONTRAST);
1385    }
1386    return defaultContrast;
1387    }
1388}
1389
Popular Tags