1 36 37 40 41 import java.awt.BorderLayout ; 42 import java.awt.Color ; 43 import java.awt.Cursor ; 44 import java.awt.Dimension ; 45 import java.awt.Font ; 46 import java.awt.FontMetrics ; 47 import java.awt.Graphics ; 48 import java.awt.Graphics2D ; 49 import java.awt.GraphicsConfiguration ; 50 import java.awt.GraphicsEnvironment ; 51 import java.awt.Point ; 52 import java.awt.Rectangle ; 53 import java.awt.RenderingHints ; 54 import java.awt.Toolkit ; 55 import java.awt.event.AdjustmentEvent ; 56 import java.awt.event.AdjustmentListener ; 57 import java.awt.event.ComponentAdapter ; 58 import java.awt.event.ComponentEvent ; 59 import java.awt.event.MouseEvent ; 60 import java.awt.event.MouseListener ; 61 import java.awt.event.MouseMotionListener ; 62 import java.awt.font.FontRenderContext ; 63 import java.awt.font.GlyphVector ; 64 import java.awt.font.LineBreakMeasurer ; 65 import java.awt.font.TextLayout ; 66 import java.awt.geom.AffineTransform ; 67 import java.awt.geom.NoninvertibleTransformException ; 68 import java.awt.geom.Rectangle2D ; 69 import java.awt.image.BufferedImage ; 70 import java.awt.print.PageFormat ; 71 import java.awt.print.Printable ; 72 import java.awt.print.PrinterJob ; 73 import java.io.BufferedOutputStream ; 74 import java.io.FileOutputStream ; 75 import java.text.AttributedString ; 76 import java.util.EnumSet ; 77 import java.util.Vector ; 78 79 import javax.imageio.*; 80 import javax.swing.*; 81 82 import static java.awt.RenderingHints .*; 83 84 91 92 95 public final class FontPanel extends JPanel implements AdjustmentListener { 96 97 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 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; 138 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 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 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 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 200 public void setTransformG2( int transform ) { 201 g2Transform = transform; 202 updateBackBuffer = true; 203 updateFontMetrics = true; 204 fc.repaint(); 205 } 206 207 private AffineTransform getAffineTransform( int transform ) { 209 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 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 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 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 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 public void doPageSetup() { 335 if ( printer == null ) { 336 printer = PrinterJob.getPrinterJob(); 337 page = printer.defaultPage(); 338 } 339 page = printer.pageDialog( page ); 340 } 341 342 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 public String [] getFontInfo() { 360 return fontInfos; 361 } 362 363 public String getCurrentOptions() { 365 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 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 setGridDisplay( grid ); 395 setForce16Columns( force16 ); 396 if (textToUse != FILE_TEXT) { 398 setTextToDraw( text, range, user, null ); 399 } 400 setFontParams( name, size, style, transform ); 401 setTransformG2( g2transform ); setDrawMethod( method ); 403 setRenderingHints(AAValues.getValue(aa), FMValues.getValue(fm), 404 new Integer (contrast)); 405 } 406 407 public void doSavePNG( String fileName ) { 409 fc.writePNG( fileName ); 410 } 411 412 public void adjustmentValueChanged( AdjustmentEvent e ) { 414 updateBackBuffer = true; 415 fc.repaint(); 416 } 417 418 public void paintComponent( Graphics g ) { 419 fc.repaint(); 424 } 425 426 428 private class FontCanvas extends JPanel implements MouseListener , MouseMotionListener , Printable { 430 431 private int numCharAcross, numCharDown; 433 434 private int drawStart, drawEnd, drawLimit; 437 438 private int maxAscent, maxDescent, gridWidth = 0, gridHeight = 0; 442 443 private int canvasInset_X = 5, canvasInset_Y = 5; 445 446 private BufferedImage backBuffer = null; 448 449 private Vector lineBreakTLs = null; 451 452 private boolean isPrinting = false; 454 455 private int lastPage, printPageNumber, currentlyShownChar = 0; 457 private final int PR_OFFSET = 10; 458 private final int PR_TITLE_LINEHEIGHT = 30; 459 460 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 470 private String backupStatusString = null; 472 473 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 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 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 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 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 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 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 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 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 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 g2.setTransform ( oldTX ); 641 } 642 643 645 private void modeSpecificDrawLine( Graphics2D g2, String line, 647 int baseX, int baseY ) { 648 AffineTransform 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 e ) { 667 e.printStackTrace(); 668 } 669 break; 670 case DRAW_GLYPHV: 671 GlyphVector gv = 672 testFont.createGlyphVector( g2.getFontRenderContext(), line ); 673 g2.drawGlyphVector( gv, (float) 0, (float) 0 ); 674 break; 675 case TL_DRAW: 676 TextLayout tl = new TextLayout ( line, testFont, 677 g2.getFontRenderContext() ); 678 tl.draw( g2, (float) 0, (float) 0 ); 679 break; 680 case GV_OUTLINE: 681 GlyphVector gvo = 682 testFont.createGlyphVector( g2.getFontRenderContext(), line ); 683 g2.draw( gvo.getOutline( (float) 0, (float) 0 )); 684 break; 685 case TL_OUTLINE: 686 TextLayout tlo = 687 new TextLayout ( line, testFont, 688 g2.getFontRenderContext() ); 689 AffineTransform at = new AffineTransform (); 690 g2.draw( tlo.getOutline( at )); 691 } 692 693 g2.setTransform ( oldTx ); 695 696 } 697 698 private void tlDrawLine( Graphics2D g2, TextLayout tl, 700 float baseX, float baseY ) { 701 AffineTransform 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 g2.setTransform ( oldTx ); 711 712 } 713 714 715 private String modeSpecificNumStr( int i ) { 720 if ( textToUse == USER_TEXT || textToUse == FILE_TEXT ) 721 return String.valueOf( i + 1 ); 722 723 StringBuffer s = new StringBuffer ( Integer.toHexString( i )); 724 while ( s.length() < 4 ) 725 s.insert( 0, "0" ); 726 return s.toString().toUpperCase(); 727 } 728 729 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 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 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 private void calcFontMetrics( Graphics2D g2d, int w, int h ) { 768 FontMetrics fm; 769 Graphics2D g2 = (Graphics2D )g2d.create(); 770 771 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 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 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 ( textToUse == FILE_TEXT ) { 817 if ( !isPrinting ) 818 f2dt.fireChangeStatus( "LineBreaking Text... Please Wait", false ); 819 lineBreakTLs = new Vector (); 820 for ( int i = 0; i < fileText.length; i++ ) { 821 AttributedString as = 822 new AttributedString ( fileText[i], g2.getFont().getAttributes() ); 823 824 LineBreakMeasurer lbm = 825 new LineBreakMeasurer ( 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 private void calcTextRange() { 839 String displaying = null; 840 841 if ( textToUse == RANGE_TEXT || textToUse == ALL_GLYPHS ) { 842 if ( isPrinting ) 843 if ( printMode == ONE_PAGE ) 844 drawStart = currentlyShownChar; 845 else 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 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 if ( drawStart > drawEnd ) { 883 drawStart = 0; 884 verticalBar.setValue(drawStart); 885 } 886 887 888 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 private void drawText( Graphics g, int w, int h ) { 900 Graphics2D g2; 901 902 if ( isPrinting ) 905 g2 = (Graphics2D ) g; 906 else { 907 backBuffer = (BufferedImage ) 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 setParams( g2 ); 916 917 if ( updateFontMetrics || isPrinting ) { 919 calcFontMetrics( g2, w, h ); 922 updateFontMetrics = false; 923 } 924 calcTextRange(); 926 927 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 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 oneLine = (TextLayout ) 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 at = getAffineTransform(g2Transform); 977 at.transform( fmData, 0, fmData, 0, 3); 978 } 979 yPos += fmData[1]; tlDrawLine( g2, oneLine, xPos, yPos ); 983 yPos += fmData[3] + fmData[5]; } 986 } 987 if ( !isPrinting ) 988 g.drawImage( backBuffer, 0, 0, this ); 989 g2.dispose(); 990 } 991 992 public void paintComponent( Graphics g ) { 995 if ( updateBackBuffer ) { 996 Dimension 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 g.drawImage( backBuffer, 0, 0, this ); 1010 } 1011 1012 showingError = false; 1013 updateBackBuffer = false; 1014 } 1015 1016 public int print( Graphics g, PageFormat pf, int pageIndex ) { 1019 if ( pageIndex == 0 ) { 1020 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 int backupDrawStart = drawStart, backupDrawEnd = drawEnd; 1038 int backupNumCharAcross = numCharAcross, backupNumCharDown = numCharDown; 1039 Vector backupLineBreakTLs = null; 1040 if ( textToUse == FILE_TEXT ) 1041 backupLineBreakTLs = (Vector ) lineBreakTLs.clone(); 1042 1043 printPageNumber = pageIndex; 1044 isPrinting = true; 1045 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 String hints = ( " with antialias " + antiAliasType + "and" + 1057 " fractional metrics " + fractionalMetricsType + 1058 " and lcd contrast = " + lcdContrast); 1059 String infoLine1 = ( "Printing" + MS_OPENING[textToUse] + 1060 modeSpecificNumStr( drawStart ) + " to " + 1061 modeSpecificNumStr( drawEnd ) + MS_CLOSING[textToUse] ); 1062 String infoLine2 = ( "With " + fontName + " " + STYLES[fontStyle] + " at " + 1063 fontSize + " point size " + TRANSFORMS[fontTransform] ); 1064 String infoLine3 = "Using " + METHODS[drawMethod] + hints; 1065 String infoLine4 = "Page: " + ( pageIndex + 1 ); 1066 g.setFont( new Font ( "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 lastPage = pageIndex; 1077 1078 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 public void writePNG( String fileName ) { 1091 try { 1092 ImageIO.write(backBuffer, "png", new java.io.File (fileName)); 1093 } 1094 catch ( Exception e ) { 1095 f2dt.fireChangeStatus( "ERROR: Failed to Save PNG image; See stack trace", true ); 1096 e.printStackTrace(); 1097 } 1098 } 1099 1100 private boolean checkMouseLoc( MouseEvent 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 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 f2dt.fireChangeStatus( "Pointing to" + MS_OPENING[textToUse] + 1124 modeSpecificNumStr( mouseOverChar ), false ); 1125 return true; 1126 } 1127 } 1128 return false; 1129 } 1130 1131 public void showZoomed() { 1133 GlyphVector gv; 1134 Font backup = testFont; 1135 Point canvasLoc = this.getLocationOnScreen(); 1136 1137 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 zoomWindow.setLocation( canvasLoc.x + zoomAreaX, canvasLoc.y + zoomAreaY ); 1149 if ( !nowZooming ) { 1150 if ( zoomWindow.getWarningString() != null ) 1151 zoomWindow.setSize( zoomAreaWidth + 1, zoomAreaHeight + 20 ); 1155 else 1156 zoomWindow.setSize( zoomAreaWidth + 1, zoomAreaHeight + 1 ); 1157 } 1158 1159 zoomImage = 1161 (BufferedImage ) zoomWindow.createImage( zoomAreaWidth + 1, 1162 zoomAreaHeight + 1 ); 1163 Graphics2D g2 = (Graphics2D ) 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 zoomWindow.getGraphics().drawImage( zoomImage, 0, 0, this ); 1181 1182 nowZooming = true; 1183 prevZoomChar = currMouseOverChar; 1184 testFont = backup; 1185 1186 if ( firstTime() ) { 1191 refresh(); 1192 } 1193 } 1194 1195 1197 public void mousePressed( MouseEvent e ) { 1200 if ( !showingError) { 1201 if ( checkMouseLoc( e )) { 1202 showZoomed(); 1203 this.setCursor( blankCursor ); 1204 } 1205 } 1206 } 1207 1208 public void mouseReleased( MouseEvent 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 public void mouseExited( MouseEvent e ) { 1222 if ( !showingError && !nowZooming ) 1223 f2dt.fireChangeStatus( backupStatusString, false ); 1224 } 1225 1226 public void mouseMoved( MouseEvent e ) { 1229 if ( !showingError ) { 1230 if ( !checkMouseLoc( e )) 1231 f2dt.fireChangeStatus( backupStatusString, false ); 1232 } 1233 } 1234 1235 public void mouseDragged( MouseEvent e ) { 1238 if ( !showingError ) 1239 if ( nowZooming ) { 1240 if ( checkMouseLoc( e ) && currMouseOverChar != prevZoomChar ) 1241 showZoomed(); 1242 } 1243 } 1244 1245 public void mouseClicked( MouseEvent e ) {} 1247 public void mouseEntered( MouseEvent e ) {} 1248 } 1249 1250 private final class CannotDrawException extends RuntimeException { 1251 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 name; 1265 private Object hint; 1266 1267 private static FMValues[] valArray; 1268 1269 FMValues(String s, Object o) { 1270 name = s; 1271 hint = o; 1272 } 1273 1274 public String toString() { 1275 return name; 1276 } 1277 1278 public Object getHint() { 1279 return hint; 1280 } 1281 public static Object 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 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 name; 1321 private Object hint; 1322 1323 private static AAValues[] valArray; 1324 1325 AAValues(String s, Object o) { 1326 name = s; 1327 hint = o; 1328 } 1329 1330 public String toString() { 1331 return name; 1332 } 1333 1334 public Object getHint() { 1335 return hint; 1336 } 1337 1338 public static boolean isLCDMode(Object o) { 1339 return (o instanceof AAValues && 1340 ((AAValues)o).ordinal() >= AALCDHRGB.ordinal()); 1341 } 1342 1343 public static Object 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 [] 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 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 defaultContrast; 1376 static Integer getDefaultLCDContrast() { 1377 if (defaultContrast == null) { 1378 GraphicsConfiguration gc = 1379 GraphicsEnvironment.getLocalGraphicsEnvironment(). 1380 getDefaultScreenDevice().getDefaultConfiguration(); 1381 Graphics2D g2d = 1382 (Graphics2D )(gc.createCompatibleImage(1,1).getGraphics()); 1383 defaultContrast = (Integer ) 1384 g2d.getRenderingHint(RenderingHints.KEY_TEXT_LCD_CONTRAST); 1385 } 1386 return defaultContrast; 1387 } 1388} 1389 | Popular Tags |