| /* |
| * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * - Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * |
| * - Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * - Neither the name of Oracle nor the names of its |
| * contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS |
| * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
| * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
| * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
| * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| /* |
| * This source code is provided to illustrate the usage of a given feature |
| * or technique and has been deliberately simplified. Additional steps |
| * required for a production-quality application, such as security checks, |
| * input validation and proper error handling, might not be present in |
| * this sample code. |
| */ |
| |
| |
| |
| import java.awt.BorderLayout; |
| import java.awt.Color; |
| import java.awt.Cursor; |
| import java.awt.Dimension; |
| import java.awt.Font; |
| import java.awt.FontMetrics; |
| import java.awt.Graphics; |
| import java.awt.Graphics2D; |
| import java.awt.GraphicsConfiguration; |
| import java.awt.GraphicsEnvironment; |
| import java.awt.Point; |
| import java.awt.Rectangle; |
| import java.awt.RenderingHints; |
| import java.awt.Toolkit; |
| import java.awt.event.AdjustmentEvent; |
| import java.awt.event.AdjustmentListener; |
| import java.awt.event.ComponentAdapter; |
| import java.awt.event.ComponentEvent; |
| import java.awt.event.MouseEvent; |
| import java.awt.event.MouseListener; |
| import java.awt.event.MouseMotionListener; |
| import java.awt.font.FontRenderContext; |
| import java.awt.font.GlyphVector; |
| import java.awt.font.LineBreakMeasurer; |
| import java.awt.font.TextLayout; |
| import java.awt.geom.AffineTransform; |
| import java.awt.geom.NoninvertibleTransformException; |
| import java.awt.geom.Rectangle2D; |
| import java.awt.image.BufferedImage; |
| import java.awt.print.PageFormat; |
| import java.awt.print.Printable; |
| import java.awt.print.PrinterJob; |
| import java.io.BufferedOutputStream; |
| import java.io.FileOutputStream; |
| import java.text.AttributedString; |
| import java.util.EnumSet; |
| import java.util.Vector; |
| |
| import javax.imageio.*; |
| import javax.swing.*; |
| |
| import static java.awt.RenderingHints.*; |
| |
| /** |
| * FontPanel.java |
| * |
| * @author Shinsuke Fukuda |
| * @author Ankit Patel [Conversion to Swing - 01/07/30] |
| */ |
| |
| /// This panel is combination of the text drawing area of Font2DTest |
| /// and the custom controlled scroll bar |
| |
| public final class FontPanel extends JPanel implements AdjustmentListener { |
| |
| /// Drawing Option Constants |
| private final String STYLES[] = |
| { "plain", "bold", "italic", "bold italic" }; |
| |
| private final int NONE = 0; |
| private final int SCALE = 1; |
| private final int SHEAR = 2; |
| private final int ROTATE = 3; |
| private final String TRANSFORMS[] = |
| { "with no transforms", "with scaling", "with Shearing", "with rotation" }; |
| |
| private final int DRAW_STRING = 0; |
| private final int DRAW_CHARS = 1; |
| private final int DRAW_BYTES = 2; |
| private final int DRAW_GLYPHV = 3; |
| private final int TL_DRAW = 4; |
| private final int GV_OUTLINE = 5; |
| private final int TL_OUTLINE = 6; |
| private final String METHODS[] = { |
| "drawString", "drawChars", "drawBytes", "drawGlyphVector", |
| "TextLayout.draw", "GlyphVector.getOutline", "TextLayout.getOutline" }; |
| |
| public final int RANGE_TEXT = 0; |
| public final int ALL_GLYPHS = 1; |
| public final int USER_TEXT = 2; |
| public final int FILE_TEXT = 3; |
| private final String MS_OPENING[] = |
| { " Unicode ", " Glyph Code ", " lines ", " lines " }; |
| private final String MS_CLOSING[] = |
| { "", "", " of User Text ", " of LineBreakMeasurer-reformatted Text " }; |
| |
| /// General Graphics Variable |
| private final JScrollBar verticalBar; |
| private final FontCanvas fc; |
| private boolean updateFontMetrics = true; |
| private boolean updateFont = true; |
| private boolean force16Cols = false; |
| public boolean showingError = false; |
| private int g2Transform = NONE; /// ABP |
| |
| /// Printing constants and variables |
| public final int ONE_PAGE = 0; |
| public final int CUR_RANGE = 1; |
| public final int ALL_TEXT = 2; |
| private int printMode = ONE_PAGE; |
| private PageFormat page = null; |
| private PrinterJob printer = null; |
| |
| /// Text drawing variables |
| private String fontName = "Dialog"; |
| private float fontSize = 12; |
| private int fontStyle = Font.PLAIN; |
| private int fontTransform = NONE; |
| private Font testFont = null; |
| private Object antiAliasType = VALUE_TEXT_ANTIALIAS_DEFAULT; |
| private Object fractionalMetricsType = VALUE_FRACTIONALMETRICS_DEFAULT; |
| private Object lcdContrast = getDefaultLCDContrast(); |
| private int drawMethod = DRAW_STRING; |
| private int textToUse = RANGE_TEXT; |
| private String userText[] = null; |
| private String fileText[] = null; |
| private int drawRange[] = { 0x0000, 0x007f }; |
| private String fontInfos[] = new String[2]; |
| private boolean showGrid = true; |
| |
| /// Parent Font2DTest panel |
| private final Font2DTest f2dt; |
| private final JFrame parent; |
| |
| public FontPanel( Font2DTest demo, JFrame f ) { |
| f2dt = demo; |
| parent = f; |
| |
| verticalBar = new JScrollBar ( JScrollBar.VERTICAL ); |
| fc = new FontCanvas(); |
| |
| this.setLayout( new BorderLayout() ); |
| this.add( "Center", fc ); |
| this.add( "East", verticalBar ); |
| |
| verticalBar.addAdjustmentListener( this ); |
| this.addComponentListener( new ComponentAdapter() { |
| public void componentResized( ComponentEvent e ) { |
| updateFontMetrics = true; |
| } |
| }); |
| |
| /// Initialize font and its infos |
| testFont = new Font(fontName, fontStyle, (int)fontSize); |
| if ((float)((int)fontSize) != fontSize) { |
| testFont = testFont.deriveFont(fontSize); |
| } |
| updateFontInfo(); |
| } |
| |
| public Dimension getPreferredSize() { |
| return new Dimension(600, 200); |
| } |
| |
| /// Functions called by the main programs to set the various parameters |
| |
| public void setTransformG2( int transform ) { |
| g2Transform = transform; |
| updateFontMetrics = true; |
| fc.repaint(); |
| } |
| |
| /// convenience fcn to create AffineTransform of appropriate type |
| private AffineTransform getAffineTransform( int transform ) { |
| /// ABP |
| AffineTransform at = new AffineTransform(); |
| switch ( transform ) |
| { |
| case SCALE: |
| at.setToScale( 1.5f, 1.5f ); break; |
| case ROTATE: |
| at.setToRotation( Math.PI / 6 ); break; |
| case SHEAR: |
| at.setToShear( 0.4f, 0 ); break; |
| case NONE: |
| break; |
| default: |
| //System.err.println( "Illegal G2 Transform Arg: " + transform); |
| break; |
| } |
| |
| return at; |
| } |
| |
| public void setFontParams(Object obj, float size, |
| int style, int transform) { |
| setFontParams( (String)obj, size, style, transform ); |
| } |
| |
| public void setFontParams(String name, float size, |
| int style, int transform) { |
| boolean fontModified = false; |
| if ( !name.equals( fontName ) || style != fontStyle ) |
| fontModified = true; |
| |
| fontName = name; |
| fontSize = size; |
| fontStyle = style; |
| fontTransform = transform; |
| |
| /// Recreate the font as specified |
| testFont = new Font(fontName, fontStyle, (int)fontSize); |
| if ((float)((int)fontSize) != fontSize) { |
| testFont = testFont.deriveFont(fontSize); |
| } |
| |
| if ( fontTransform != NONE ) { |
| AffineTransform at = getAffineTransform( fontTransform ); |
| testFont = testFont.deriveFont( at ); |
| } |
| updateFontMetrics = true; |
| fc.repaint(); |
| if ( fontModified ) { |
| /// Tell main panel to update the font info |
| updateFontInfo(); |
| f2dt.fireUpdateFontInfo(); |
| } |
| } |
| |
| public void setRenderingHints( Object aa, Object fm, Object contrast) { |
| antiAliasType = ((AAValues)aa).getHint(); |
| fractionalMetricsType = ((FMValues)fm).getHint(); |
| lcdContrast = contrast; |
| updateFontMetrics = true; |
| fc.repaint(); |
| } |
| |
| public void setDrawMethod( int i ) { |
| drawMethod = i; |
| fc.repaint(); |
| } |
| |
| public void setTextToDraw( int i, int range[], |
| String textSet[], String fileData[] ) { |
| textToUse = i; |
| |
| if ( textToUse == RANGE_TEXT ) |
| drawRange = range; |
| else if ( textToUse == ALL_GLYPHS ) |
| drawMethod = DRAW_GLYPHV; |
| else if ( textToUse == USER_TEXT ) |
| userText = textSet; |
| else if ( textToUse == FILE_TEXT ) { |
| fileText = fileData; |
| drawMethod = TL_DRAW; |
| } |
| |
| updateFontMetrics = true; |
| fc.repaint(); |
| updateFontInfo(); |
| } |
| |
| public void setGridDisplay( boolean b ) { |
| showGrid = b; |
| fc.repaint(); |
| } |
| |
| public void setForce16Columns( boolean b ) { |
| force16Cols = b; |
| updateFontMetrics = true; |
| fc.repaint(); |
| } |
| |
| /// Prints out the text display area |
| public void doPrint( int i ) { |
| if ( printer == null ) { |
| printer = PrinterJob.getPrinterJob(); |
| page = printer.defaultPage(); |
| } |
| printMode = i; |
| printer.setPrintable( fc, page ); |
| |
| if ( printer.printDialog() ) { |
| try { |
| printer.print(); |
| } |
| catch ( Exception e ) { |
| f2dt.fireChangeStatus( "ERROR: Printing Failed; See Stack Trace", true ); |
| } |
| } |
| } |
| |
| /// Displays the page setup dialog and updates PageFormat info |
| public void doPageSetup() { |
| if ( printer == null ) { |
| printer = PrinterJob.getPrinterJob(); |
| page = printer.defaultPage(); |
| } |
| page = printer.pageDialog( page ); |
| } |
| |
| /// Obtains the information about selected font |
| private void updateFontInfo() { |
| int numGlyphs = 0, numCharsInRange = drawRange[1] - drawRange[0] + 1; |
| fontInfos[0] = "Font Face Name: " + testFont.getFontName(); |
| fontInfos[1] = "Glyphs in This Range: "; |
| |
| if ( textToUse == RANGE_TEXT ) { |
| for ( int i = drawRange[0]; i < drawRange[1]; i++ ) |
| if ( testFont.canDisplay( i )) |
| numGlyphs++; |
| fontInfos[1] = fontInfos[1] + numGlyphs + " / " + numCharsInRange; |
| } |
| else |
| fontInfos[1] = null; |
| } |
| |
| /// Accessor for the font information |
| public String[] getFontInfo() { |
| return fontInfos; |
| } |
| |
| /// Collects the currectly set options and returns them as string |
| public String getCurrentOptions() { |
| /// Create a new String to store the options |
| /// The array will contain all 8 setting (font name, size...) and |
| /// character range or user text data used (no file text data) |
| int userTextSize = 0; |
| String options; |
| |
| options = ( fontName + "\n" + fontSize + "\n" + fontStyle + "\n" + |
| fontTransform + "\n" + g2Transform + "\n"+ |
| textToUse + "\n" + drawMethod + "\n" + |
| AAValues.getHintVal(antiAliasType) + "\n" + |
| FMValues.getHintVal(fractionalMetricsType) + "\n" + |
| lcdContrast + "\n"); |
| if ( textToUse == USER_TEXT ) |
| for ( int i = 0; i < userText.length; i++ ) |
| options += ( userText[i] + "\n" ); |
| |
| return options; |
| } |
| |
| /// Reload all options and refreshes the canvas |
| public void loadOptions( boolean grid, boolean force16, int start, int end, |
| String name, float size, int style, |
| int transform, int g2transform, |
| int text, int method, int aa, int fm, |
| int contrast, String user[] ) { |
| int range[] = { start, end }; |
| |
| /// Since repaint call has a low priority, these functions will finish |
| /// before the actual repainting is done |
| setGridDisplay( grid ); |
| setForce16Columns( force16 ); |
| // previous call to readTextFile has already set the text to draw |
| if (textToUse != FILE_TEXT) { |
| setTextToDraw( text, range, user, null ); |
| } |
| setFontParams( name, size, style, transform ); |
| setTransformG2( g2transform ); // ABP |
| setDrawMethod( method ); |
| setRenderingHints(AAValues.getValue(aa), FMValues.getValue(fm), |
| new Integer(contrast)); |
| } |
| |
| /// Writes the current screen to PNG file |
| public void doSavePNG( String fileName ) { |
| fc.writePNG( fileName ); |
| } |
| |
| /// When scrolled using the scroll bar, update the backbuffer |
| public void adjustmentValueChanged( AdjustmentEvent e ) { |
| fc.repaint(); |
| } |
| |
| public void paintComponent( Graphics g ) { |
| // Windows does not repaint correctly, after |
| // a zoom. Thus, we need to force the canvas |
| // to repaint, but only once. After the first repaint, |
| // everything stabilizes. [ABP] |
| fc.repaint(); |
| } |
| |
| /// Inner class definition... |
| |
| /// Inner panel that holds the actual drawing area and its routines |
| private class FontCanvas extends JPanel implements MouseListener, MouseMotionListener, Printable { |
| |
| /// Number of characters that will fit across and down this canvas |
| private int numCharAcross, numCharDown; |
| |
| /// First and last character/line that will be drawn |
| /// Limit is the end of range/text where no more draw will be done |
| private int drawStart, drawEnd, drawLimit; |
| |
| /// FontMetrics variables |
| /// Here, gridWidth is equivalent to maxAdvance (slightly bigger though) |
| /// and gridHeight is equivalent to lineHeight |
| private int maxAscent, maxDescent, gridWidth = 0, gridHeight = 0; |
| |
| /// Offset from the top left edge of the canvas where the draw will start |
| private int canvasInset_X = 5, canvasInset_Y = 5; |
| |
| /// LineBreak'ed TextLayout vector |
| private Vector lineBreakTLs = null; |
| |
| /// Whether the current draw command requested is for printing |
| private boolean isPrinting = false; |
| |
| /// Other printing infos |
| private int lastPage, printPageNumber, currentlyShownChar = 0; |
| private final int PR_OFFSET = 10; |
| private final int PR_TITLE_LINEHEIGHT = 30; |
| |
| /// Information about zooming (used with range text draw) |
| private final JWindow zoomWindow; |
| private BufferedImage zoomImage = null; |
| private int mouseOverCharX = -1, mouseOverCharY = -1; |
| private int currMouseOverChar = -1, prevZoomChar = -1; |
| private float ZOOM = 2.0f; |
| private boolean nowZooming = false; |
| private boolean firstTime = true; |
| // ABP |
| |
| /// Status bar message backup |
| private String backupStatusString = null; |
| |
| /// Error constants |
| private final String ERRORS[] = { |
| "ERROR: drawBytes cannot handle characters beyond 0x00FF. Select different range or draw methods.", |
| "ERROR: Cannot fit text with the current font size. Resize the window or use smaller font size.", |
| "ERROR: Cannot print with the current font size. Use smaller font size.", |
| }; |
| |
| private final int DRAW_BYTES_ERROR = 0; |
| private final int CANT_FIT_DRAW = 1; |
| private final int CANT_FIT_PRINT = 2; |
| |
| /// Other variables |
| private final Cursor blankCursor; |
| |
| public FontCanvas() { |
| this.addMouseListener( this ); |
| this.addMouseMotionListener( this ); |
| this.setForeground( Color.black ); |
| this.setBackground( Color.white ); |
| |
| /// Creates an invisble pointer by giving it bogus image |
| /// Possibly find a workaround for this... |
| Toolkit tk = Toolkit.getDefaultToolkit(); |
| byte bogus[] = { (byte) 0 }; |
| blankCursor = |
| tk.createCustomCursor( tk.createImage( bogus ), new Point(0, 0), "" ); |
| |
| zoomWindow = new JWindow( parent ) { |
| public void paint( Graphics g ) { |
| g.drawImage( zoomImage, 0, 0, zoomWindow ); |
| } |
| }; |
| zoomWindow.setCursor( blankCursor ); |
| zoomWindow.pack(); |
| } |
| |
| public boolean firstTime() { return firstTime; } |
| public void refresh() { |
| firstTime = false; |
| repaint(); |
| } |
| |
| /// Sets the font, hints, according to the set parameters |
| private void setParams( Graphics2D g2 ) { |
| g2.setFont( testFont ); |
| g2.setRenderingHint(KEY_TEXT_ANTIALIASING, antiAliasType); |
| g2.setRenderingHint(KEY_FRACTIONALMETRICS, fractionalMetricsType); |
| g2.setRenderingHint(KEY_TEXT_LCD_CONTRAST, lcdContrast); |
| /* I am preserving a somewhat dubious behaviour of this program. |
| * Outline text would be drawn anti-aliased by setting the |
| * graphics anti-aliasing hint if the text anti-aliasing hint |
| * was set. The dubious element here is that people simply |
| * using this program may think this is built-in behaviour |
| * but its not - at least not when the app explicitly draws |
| * outline text. |
| * This becomes more dubious in cases such as "GASP" where the |
| * size at which text is AA'ed is not something you can easily |
| * calculate, so mimicing that behaviour isn't going to be easy. |
| * So I precisely preserve the behaviour : this is done only |
| * if the AA value is "ON". Its not applied in the other cases. |
| */ |
| if (antiAliasType == VALUE_TEXT_ANTIALIAS_ON && |
| (drawMethod == TL_OUTLINE || drawMethod == GV_OUTLINE)) { |
| g2.setRenderingHint(KEY_ANTIALIASING, VALUE_ANTIALIAS_ON); |
| } else { |
| g2.setRenderingHint(KEY_ANTIALIASING, VALUE_ANTIALIAS_OFF); |
| } |
| } |
| |
| /// Draws the grid (Used for unicode/glyph range drawing) |
| private void drawGrid( Graphics2D g2 ) { |
| int totalGridWidth = numCharAcross * gridWidth; |
| int totalGridHeight = numCharDown * gridHeight; |
| |
| g2.setColor( Color.black ); |
| for ( int i = 0; i < numCharDown + 1; i++ ) |
| g2.drawLine( canvasInset_X, i * gridHeight + canvasInset_Y, |
| canvasInset_X + totalGridWidth, i * gridHeight + canvasInset_Y ); |
| for ( int i = 0; i < numCharAcross + 1; i++ ) |
| g2.drawLine( i * gridWidth + canvasInset_X, canvasInset_Y, |
| i * gridWidth + canvasInset_X, canvasInset_Y + totalGridHeight ); |
| } |
| |
| /// Draws one character at time onto the canvas according to |
| /// the method requested (Used for RANGE_TEXT and ALL_GLYPHS) |
| public void modeSpecificDrawChar( Graphics2D g2, int charCode, |
| int baseX, int baseY ) { |
| GlyphVector gv; |
| int oneGlyph[] = { charCode }; |
| char charArray[] = Character.toChars( charCode ); |
| |
| FontRenderContext frc = g2.getFontRenderContext(); |
| AffineTransform oldTX = g2.getTransform(); |
| |
| /// Create GlyphVector to measure the exact visual advance |
| /// Using that number, adjust the position of the character drawn |
| if ( textToUse == ALL_GLYPHS ) |
| gv = testFont.createGlyphVector( frc, oneGlyph ); |
| else |
| gv = testFont.createGlyphVector( frc, charArray ); |
| Rectangle2D r2d2 = gv.getPixelBounds(frc, 0, 0); |
| int shiftedX = baseX; |
| // getPixelBounds returns a result in device space. |
| // we need to convert back to user space to be able to |
| // calculate the shift as baseX is in user space. |
| try { |
| double pt[] = new double[4]; |
| pt[0] = r2d2.getX(); |
| pt[1] = r2d2.getY(); |
| pt[2] = r2d2.getX()+r2d2.getWidth(); |
| pt[3] = r2d2.getY()+r2d2.getHeight(); |
| oldTX.inverseTransform(pt,0,pt,0,2); |
| shiftedX = baseX - (int) ( pt[2] / 2 + pt[0] ); |
| } catch (NoninvertibleTransformException e) { |
| } |
| |
| /// ABP - keep track of old tform, restore it later |
| |
| g2.translate( shiftedX, baseY ); |
| g2.transform( getAffineTransform( g2Transform ) ); |
| |
| if ( textToUse == ALL_GLYPHS ) |
| g2.drawGlyphVector( gv, 0f, 0f ); |
| else { |
| if ( testFont.canDisplay( charCode )) |
| g2.setColor( Color.black ); |
| else { |
| g2.setColor( Color.lightGray ); |
| } |
| |
| switch ( drawMethod ) { |
| case DRAW_STRING: |
| g2.drawString( new String( charArray ), 0, 0 ); |
| break; |
| case DRAW_CHARS: |
| g2.drawChars( charArray, 0, 1, 0, 0 ); |
| break; |
| case DRAW_BYTES: |
| if ( charCode > 0xff ) |
| throw new CannotDrawException( DRAW_BYTES_ERROR ); |
| byte oneByte[] = { (byte) charCode }; |
| g2.drawBytes( oneByte, 0, 1, 0, 0 ); |
| break; |
| case DRAW_GLYPHV: |
| g2.drawGlyphVector( gv, 0f, 0f ); |
| break; |
| case TL_DRAW: |
| TextLayout tl = new TextLayout( new String( charArray ), testFont, frc ); |
| tl.draw( g2, 0f, 0f ); |
| break; |
| case GV_OUTLINE: |
| r2d2 = gv.getVisualBounds(); |
| shiftedX = baseX - (int) ( r2d2.getWidth() / 2 + r2d2.getX() ); |
| g2.draw( gv.getOutline( 0f, 0f )); |
| break; |
| case TL_OUTLINE: |
| r2d2 = gv.getVisualBounds(); |
| shiftedX = baseX - (int) ( r2d2.getWidth() / 2 + r2d2.getX() ); |
| TextLayout tlo = |
| new TextLayout( new String( charArray ), testFont, |
| g2.getFontRenderContext() ); |
| g2.draw( tlo.getOutline( null )); |
| } |
| } |
| |
| /// ABP - restore old tform |
| g2.setTransform ( oldTX ); |
| } |
| |
| /// Draws one line of text at given position |
| private void modeSpecificDrawLine( Graphics2D g2, String line, |
| int baseX, int baseY ) { |
| /// ABP - keep track of old tform, restore it later |
| AffineTransform oldTx = null; |
| oldTx = g2.getTransform(); |
| g2.translate( baseX, baseY ); |
| g2.transform( getAffineTransform( g2Transform ) ); |
| |
| switch ( drawMethod ) { |
| case DRAW_STRING: |
| g2.drawString( line, 0, 0 ); |
| break; |
| case DRAW_CHARS: |
| g2.drawChars( line.toCharArray(), 0, line.length(), 0, 0 ); |
| break; |
| case DRAW_BYTES: |
| try { |
| byte lineBytes[] = line.getBytes( "ISO-8859-1" ); |
| g2.drawBytes( lineBytes, 0, lineBytes.length, 0, 0 ); |
| } |
| catch ( Exception e ) { |
| e.printStackTrace(); |
| } |
| break; |
| case DRAW_GLYPHV: |
| GlyphVector gv = |
| testFont.createGlyphVector( g2.getFontRenderContext(), line ); |
| g2.drawGlyphVector( gv, (float) 0, (float) 0 ); |
| break; |
| case TL_DRAW: |
| TextLayout tl = new TextLayout( line, testFont, |
| g2.getFontRenderContext() ); |
| tl.draw( g2, (float) 0, (float) 0 ); |
| break; |
| case GV_OUTLINE: |
| GlyphVector gvo = |
| testFont.createGlyphVector( g2.getFontRenderContext(), line ); |
| g2.draw( gvo.getOutline( (float) 0, (float) 0 )); |
| break; |
| case TL_OUTLINE: |
| TextLayout tlo = |
| new TextLayout( line, testFont, |
| g2.getFontRenderContext() ); |
| AffineTransform at = new AffineTransform(); |
| g2.draw( tlo.getOutline( at )); |
| } |
| |
| /// ABP - restore old tform |
| g2.setTransform ( oldTx ); |
| |
| } |
| |
| /// Draws one line of text at given position |
| private void tlDrawLine( Graphics2D g2, TextLayout tl, |
| float baseX, float baseY ) { |
| /// ABP - keep track of old tform, restore it later |
| AffineTransform oldTx = null; |
| oldTx = g2.getTransform(); |
| g2.translate( baseX, baseY ); |
| g2.transform( getAffineTransform( g2Transform ) ); |
| |
| tl.draw( g2, (float) 0, (float) 0 ); |
| |
| /// ABP - restore old tform |
| g2.setTransform ( oldTx ); |
| |
| } |
| |
| |
| /// If textToUse is set to range drawing, then convert |
| /// int to hex string and prepends 0s to make it length 4 |
| /// Otherwise line number was fed; simply return number + 1 converted to String |
| /// (This is because first line is 1, not 0) |
| private String modeSpecificNumStr( int i ) { |
| if ( textToUse == USER_TEXT || textToUse == FILE_TEXT ) |
| return String.valueOf( i + 1 ); |
| |
| StringBuffer s = new StringBuffer( Integer.toHexString( i )); |
| while ( s.length() < 4 ) |
| s.insert( 0, "0" ); |
| return s.toString().toUpperCase(); |
| } |
| |
| /// Resets the scrollbar to display correct range of text currently on screen |
| /// (This scrollbar is not part of a "ScrollPane". It merely simulates its effect by |
| /// indicating the necessary area to be drawn within the panel. |
| /// By doing this, it prevents creating gigantic panel when large text range, |
| /// i.e. CJK Ideographs, is requested) |
| private void resetScrollbar( int oldValue ) { |
| int totalNumRows = 1, numCharToDisplay; |
| if ( textToUse == RANGE_TEXT || textToUse == ALL_GLYPHS ) { |
| if ( textToUse == RANGE_TEXT ) |
| numCharToDisplay = drawRange[1] - drawRange[0]; |
| else /// textToUse == ALL_GLYPHS |
| numCharToDisplay = testFont.getNumGlyphs(); |
| |
| totalNumRows = numCharToDisplay / numCharAcross; |
| if ( numCharToDisplay % numCharAcross != 0 ) |
| totalNumRows++; |
| if ( oldValue / numCharAcross > totalNumRows ) |
| oldValue = 0; |
| |
| verticalBar.setValues( oldValue / numCharAcross, |
| numCharDown, 0, totalNumRows ); |
| } |
| else { |
| if ( textToUse == USER_TEXT ) |
| totalNumRows = userText.length; |
| else /// textToUse == FILE_TEXT; |
| totalNumRows = lineBreakTLs.size(); |
| verticalBar.setValues( oldValue, numCharDown, 0, totalNumRows ); |
| } |
| if ( totalNumRows <= numCharDown && drawStart == 0) { |
| verticalBar.setEnabled( false ); |
| } |
| else { |
| verticalBar.setEnabled( true ); |
| } |
| } |
| |
| /// Calculates the font's metrics that will be used for draw |
| private void calcFontMetrics( Graphics2D g2d, int w, int h ) { |
| FontMetrics fm; |
| Graphics2D g2 = (Graphics2D)g2d.create(); |
| |
| /// ABP |
| if ( g2Transform != NONE && textToUse != FILE_TEXT ) { |
| g2.setFont( g2.getFont().deriveFont( getAffineTransform( g2Transform )) ); |
| fm = g2.getFontMetrics(); |
| } |
| else { |
| fm = g2.getFontMetrics(); |
| } |
| |
| maxAscent = fm.getMaxAscent(); |
| maxDescent = fm.getMaxDescent(); |
| if (maxAscent == 0) maxAscent = 10; |
| if (maxDescent == 0) maxDescent = 5; |
| if ( textToUse == RANGE_TEXT || textToUse == ALL_GLYPHS ) { |
| /// Give slight extra room for each character |
| maxAscent += 3; |
| maxDescent += 3; |
| gridWidth = fm.getMaxAdvance() + 6; |
| gridHeight = maxAscent + maxDescent; |
| if ( force16Cols ) |
| numCharAcross = 16; |
| else |
| numCharAcross = ( w - 10 ) / gridWidth; |
| numCharDown = ( h - 10 ) / gridHeight; |
| |
| canvasInset_X = ( w - numCharAcross * gridWidth ) / 2; |
| canvasInset_Y = ( h - numCharDown * gridHeight ) / 2; |
| if ( numCharDown == 0 || numCharAcross == 0 ) |
| throw new CannotDrawException( isPrinting ? CANT_FIT_PRINT : CANT_FIT_DRAW ); |
| |
| if ( !isPrinting ) |
| resetScrollbar( verticalBar.getValue() * numCharAcross ); |
| } |
| else { |
| maxDescent += fm.getLeading(); |
| canvasInset_X = 5; |
| canvasInset_Y = 5; |
| /// gridWidth and numCharAcross will not be used in this mode... |
| gridHeight = maxAscent + maxDescent; |
| numCharDown = ( h - canvasInset_Y * 2 ) / gridHeight; |
| |
| if ( numCharDown == 0 ) |
| throw new CannotDrawException( isPrinting ? CANT_FIT_PRINT : CANT_FIT_DRAW ); |
| /// If this is text loaded from file, prepares the LineBreak'ed |
| /// text layout at this point |
| if ( textToUse == FILE_TEXT ) { |
| if ( !isPrinting ) |
| f2dt.fireChangeStatus( "LineBreaking Text... Please Wait", false ); |
| lineBreakTLs = new Vector(); |
| for ( int i = 0; i < fileText.length; i++ ) { |
| AttributedString as = |
| new AttributedString( fileText[i], g2.getFont().getAttributes() ); |
| |
| LineBreakMeasurer lbm = |
| new LineBreakMeasurer( as.getIterator(), g2.getFontRenderContext() ); |
| |
| while ( lbm.getPosition() < fileText[i].length() ) |
| lineBreakTLs.add( lbm.nextLayout( (float) w )); |
| |
| } |
| } |
| if ( !isPrinting ) |
| resetScrollbar( verticalBar.getValue() ); |
| } |
| } |
| |
| /// Calculates the amount of text that will be displayed on screen |
| private void calcTextRange() { |
| String displaying = null; |
| |
| if ( textToUse == RANGE_TEXT || textToUse == ALL_GLYPHS ) { |
| if ( isPrinting ) |
| if ( printMode == ONE_PAGE ) |
| drawStart = currentlyShownChar; |
| else /// printMode == CUR_RANGE |
| drawStart = numCharAcross * numCharDown * printPageNumber; |
| else |
| drawStart = verticalBar.getValue() * numCharAcross; |
| if ( textToUse == RANGE_TEXT ) { |
| drawStart += drawRange[0]; |
| drawLimit = drawRange[1]; |
| } |
| else |
| drawLimit = testFont.getNumGlyphs(); |
| drawEnd = drawStart + numCharAcross * numCharDown - 1; |
| |
| if ( drawEnd >= drawLimit ) |
| drawEnd = drawLimit; |
| } |
| else { |
| if ( isPrinting ) |
| if ( printMode == ONE_PAGE ) |
| drawStart = currentlyShownChar; |
| else /// printMode == ALL_TEXT |
| drawStart = numCharDown * printPageNumber; |
| else { |
| drawStart = verticalBar.getValue(); |
| } |
| |
| drawEnd = drawStart + numCharDown - 1; |
| |
| if ( textToUse == USER_TEXT ) |
| drawLimit = userText.length - 1; |
| else |
| drawLimit = lineBreakTLs.size() - 1; |
| |
| if ( drawEnd >= drawLimit ) |
| drawEnd = drawLimit; |
| } |
| |
| // ABP |
| if ( drawStart > drawEnd ) { |
| drawStart = 0; |
| verticalBar.setValue(drawStart); |
| } |
| |
| |
| /// Change the status bar if not printing... |
| if ( !isPrinting ) { |
| backupStatusString = ( "Displaying" + MS_OPENING[textToUse] + |
| modeSpecificNumStr( drawStart ) + " to " + |
| modeSpecificNumStr( drawEnd ) + |
| MS_CLOSING[textToUse] ); |
| f2dt.fireChangeStatus( backupStatusString, false ); |
| } |
| } |
| |
| /// Draws text according to the parameters set by Font2DTest GUI |
| private void drawText( Graphics g, int w, int h ) { |
| Graphics2D g2 = (Graphics2D) g; |
| g2.setColor(Color.white); |
| g2.fillRect(0, 0, w, h); |
| g2.setColor(Color.black); |
| |
| /// sets font, RenderingHints. |
| setParams( g2 ); |
| |
| /// If flag is set, recalculate fontMetrics and reset the scrollbar |
| if ( updateFontMetrics || isPrinting ) { |
| /// NOTE: re-calculates in case G2 transform |
| /// is something other than NONE |
| calcFontMetrics( g2, w, h ); |
| updateFontMetrics = false; |
| } |
| /// Calculate the amount of text that can be drawn... |
| calcTextRange(); |
| |
| /// Draw according to the set "Text to Use" mode |
| if ( textToUse == RANGE_TEXT || textToUse == ALL_GLYPHS ) { |
| int charToDraw = drawStart; |
| if ( showGrid ) |
| drawGrid( g2 ); |
| |
| for ( int i = 0; i < numCharDown && charToDraw <= drawEnd; i++ ) { |
| for ( int j = 0; j < numCharAcross && charToDraw <= drawEnd; j++, charToDraw++ ) { |
| int gridLocX = j * gridWidth + canvasInset_X; |
| int gridLocY = i * gridHeight + canvasInset_Y; |
| |
| modeSpecificDrawChar( g2, charToDraw, |
| gridLocX + gridWidth / 2, |
| gridLocY + maxAscent ); |
| |
| } |
| } |
| } |
| else if ( textToUse == USER_TEXT ) { |
| g2.drawRect( 0, 0, w - 1, h - 1 ); |
| for ( int i = drawStart; i <= drawEnd; i++ ) { |
| int lineStartX = canvasInset_Y; |
| int lineStartY = ( i - drawStart ) * gridHeight + maxAscent; |
| modeSpecificDrawLine( g2, userText[i], lineStartX, lineStartY ); |
| } |
| } |
| else { |
| float xPos, yPos = (float) canvasInset_Y; |
| g2.drawRect( 0, 0, w - 1, h - 1 ); |
| for ( int i = drawStart; i <= drawEnd; i++ ) { |
| TextLayout oneLine = (TextLayout) lineBreakTLs.elementAt( i ); |
| xPos = |
| oneLine.isLeftToRight() ? |
| canvasInset_X : ( (float) w - oneLine.getAdvance() - canvasInset_X ); |
| |
| float fmData[] = {0, oneLine.getAscent(), 0, oneLine.getDescent(), 0, oneLine.getLeading()}; |
| if (g2Transform != NONE) { |
| AffineTransform at = getAffineTransform(g2Transform); |
| at.transform( fmData, 0, fmData, 0, 3); |
| } |
| //yPos += oneLine.getAscent(); |
| yPos += fmData[1]; // ascent |
| //oneLine.draw( g2, xPos, yPos ); |
| tlDrawLine( g2, oneLine, xPos, yPos ); |
| //yPos += oneLine.getDescent() + oneLine.getLeading(); |
| yPos += fmData[3] + fmData[5]; // descent + leading |
| } |
| } |
| g2.dispose(); |
| } |
| |
| /// Component paintComponent function... |
| /// Draws/Refreshes canvas according to flag(s) set by other functions |
| public void paintComponent( Graphics g ) { |
| super.paintComponent(g); |
| |
| Dimension d = this.getSize(); |
| isPrinting = false; |
| try { |
| drawText( g, d.width, d.height ); |
| } |
| catch ( CannotDrawException e ) { |
| super.paintComponent(g); |
| f2dt.fireChangeStatus( ERRORS[ e.id ], true ); |
| return; |
| } |
| |
| showingError = false; |
| } |
| |
| /// Printable interface function |
| /// Component print function... |
| public int print( Graphics g, PageFormat pf, int pageIndex ) { |
| if ( pageIndex == 0 ) { |
| /// Reset the last page index to max... |
| lastPage = Integer.MAX_VALUE; |
| currentlyShownChar = verticalBar.getValue() * numCharAcross; |
| } |
| |
| if ( printMode == ONE_PAGE ) { |
| if ( pageIndex > 0 ) |
| return NO_SUCH_PAGE; |
| } |
| else { |
| if ( pageIndex > lastPage ) |
| return NO_SUCH_PAGE; |
| } |
| |
| int pageWidth = (int) pf.getImageableWidth(); |
| int pageHeight = (int) pf.getImageableHeight(); |
| /// Back up metrics and other drawing info before printing modifies it |
| int backupDrawStart = drawStart, backupDrawEnd = drawEnd; |
| int backupNumCharAcross = numCharAcross, backupNumCharDown = numCharDown; |
| Vector backupLineBreakTLs = null; |
| if ( textToUse == FILE_TEXT ) |
| backupLineBreakTLs = (Vector) lineBreakTLs.clone(); |
| |
| printPageNumber = pageIndex; |
| isPrinting = true; |
| /// Push the actual draw area 60 down to allow info to be printed |
| g.translate( (int) pf.getImageableX(), (int) pf.getImageableY() + 60 ); |
| try { |
| drawText( g, pageWidth, pageHeight - 60 ); |
| } |
| catch ( CannotDrawException e ) { |
| f2dt.fireChangeStatus( ERRORS[ e.id ], true ); |
| return NO_SUCH_PAGE; |
| } |
| |
| /// Draw information about what is being printed |
| String hints = ( " with antialias " + antiAliasType + "and" + |
| " fractional metrics " + fractionalMetricsType + |
| " and lcd contrast = " + lcdContrast); |
| String infoLine1 = ( "Printing" + MS_OPENING[textToUse] + |
| modeSpecificNumStr( drawStart ) + " to " + |
| modeSpecificNumStr( drawEnd ) + MS_CLOSING[textToUse] ); |
| String infoLine2 = ( "With " + fontName + " " + STYLES[fontStyle] + " at " + |
| fontSize + " point size " + TRANSFORMS[fontTransform] ); |
| String infoLine3 = "Using " + METHODS[drawMethod] + hints; |
| String infoLine4 = "Page: " + ( pageIndex + 1 ); |
| g.setFont( new Font( "dialog", Font.PLAIN, 12 )); |
| g.setColor( Color.black ); |
| g.translate( 0, -60 ); |
| g.drawString( infoLine1, 15, 10 ); |
| g.drawString( infoLine2, 15, 22 ); |
| g.drawString( infoLine3, 15, 34 ); |
| g.drawString( infoLine4, 15, 46 ); |
| |
| if ( drawEnd == drawLimit ) |
| /// This indicates that the draw will be completed with this page |
| lastPage = pageIndex; |
| |
| /// Restore the changed values back... |
| /// This is important for JScrollBar settings and LineBreak'ed TLs |
| drawStart = backupDrawStart; |
| drawEnd = backupDrawEnd; |
| numCharAcross = backupNumCharAcross; |
| numCharDown = backupNumCharDown; |
| if ( textToUse == FILE_TEXT ) |
| lineBreakTLs = backupLineBreakTLs; |
| return PAGE_EXISTS; |
| } |
| |
| /// Ouputs the current canvas into a given PNG file |
| public void writePNG( String fileName ) { |
| try { |
| int w = this.getSize().width; |
| int h = this.getSize().height; |
| BufferedImage buffer = (BufferedImage) this.createImage( w, h ); |
| Graphics2D g2 = buffer.createGraphics(); |
| g2.setColor(Color.white); |
| g2.fillRect(0, 0, w, h); |
| g2.setColor(Color.black); |
| updateFontMetrics = true; |
| drawText(g2, w, h); |
| updateFontMetrics = true; |
| ImageIO.write(buffer, "png", new java.io.File(fileName)); |
| } |
| catch ( Exception e ) { |
| f2dt.fireChangeStatus( "ERROR: Failed to Save PNG image; See stack trace", true ); |
| e.printStackTrace(); |
| } |
| } |
| |
| /// Figures out whether a character at the pointer location is valid |
| /// And if so, updates mouse location informations, as well as |
| /// the information on the status bar |
| private boolean checkMouseLoc( MouseEvent e ) { |
| if ( gridWidth != 0 && gridHeight != 0 ) |
| if ( textToUse == RANGE_TEXT || textToUse == ALL_GLYPHS ) { |
| int charLocX = ( e.getX() - canvasInset_X ) / gridWidth; |
| int charLocY = ( e.getY() - canvasInset_Y ) / gridHeight; |
| |
| /// Check to make sure the mouse click location is within drawn area |
| if ( charLocX >= 0 && charLocY >= 0 && |
| charLocX < numCharAcross && charLocY < numCharDown ) { |
| int mouseOverChar = |
| charLocX + ( verticalBar.getValue() + charLocY ) * numCharAcross; |
| if ( textToUse == RANGE_TEXT ) |
| mouseOverChar += drawRange[0]; |
| if ( mouseOverChar > drawEnd ) |
| return false; |
| |
| mouseOverCharX = charLocX; |
| mouseOverCharY = charLocY; |
| currMouseOverChar = mouseOverChar; |
| /// Update status bar |
| f2dt.fireChangeStatus( "Pointing to" + MS_OPENING[textToUse] + |
| modeSpecificNumStr( mouseOverChar ), false ); |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| /// Shows (updates) the character zoom window |
| public void showZoomed() { |
| GlyphVector gv; |
| Font backup = testFont; |
| Point canvasLoc = this.getLocationOnScreen(); |
| |
| /// Calculate the zoom area's location and size... |
| int dialogOffsetX = (int) ( gridWidth * ( ZOOM - 1 ) / 2 ); |
| int dialogOffsetY = (int) ( gridHeight * ( ZOOM - 1 ) / 2 ); |
| int zoomAreaX = |
| mouseOverCharX * gridWidth + canvasInset_X - dialogOffsetX; |
| int zoomAreaY = |
| mouseOverCharY * gridHeight + canvasInset_Y - dialogOffsetY; |
| int zoomAreaWidth = (int) ( gridWidth * ZOOM ); |
| int zoomAreaHeight = (int) ( gridHeight * ZOOM ); |
| |
| /// Position and set size of zoom window as needed |
| zoomWindow.setLocation( canvasLoc.x + zoomAreaX, canvasLoc.y + zoomAreaY ); |
| if ( !nowZooming ) { |
| if ( zoomWindow.getWarningString() != null ) |
| /// If this is not opened as a "secure" window, |
| /// it has a banner below the zoom dialog which makes it look really BAD |
| /// So enlarge it by a bit |
| zoomWindow.setSize( zoomAreaWidth + 1, zoomAreaHeight + 20 ); |
| else |
| zoomWindow.setSize( zoomAreaWidth + 1, zoomAreaHeight + 1 ); |
| } |
| |
| /// Prepare zoomed image |
| zoomImage = |
| (BufferedImage) zoomWindow.createImage( zoomAreaWidth + 1, |
| zoomAreaHeight + 1 ); |
| Graphics2D g2 = (Graphics2D) zoomImage.getGraphics(); |
| testFont = testFont.deriveFont( fontSize * ZOOM ); |
| setParams( g2 ); |
| g2.setColor( Color.white ); |
| g2.fillRect( 0, 0, zoomAreaWidth, zoomAreaHeight ); |
| g2.setColor( Color.black ); |
| g2.drawRect( 0, 0, zoomAreaWidth, zoomAreaHeight ); |
| modeSpecificDrawChar( g2, currMouseOverChar, |
| zoomAreaWidth / 2, (int) ( maxAscent * ZOOM )); |
| g2.dispose(); |
| if ( !nowZooming ) |
| zoomWindow.show(); |
| /// This is sort of redundant... since there is a paint function |
| /// inside zoomWindow definition that does the drawImage. |
| /// (I should be able to call just repaint() here) |
| /// However, for some reason, that paint function fails to respond |
| /// from second time and on; So I have to force the paint here... |
| zoomWindow.getGraphics().drawImage( zoomImage, 0, 0, this ); |
| |
| nowZooming = true; |
| prevZoomChar = currMouseOverChar; |
| testFont = backup; |
| |
| // Windows does not repaint correctly, after |
| // a zoom. Thus, we need to force the canvas |
| // to repaint, but only once. After the first repaint, |
| // everything stabilizes. [ABP] |
| if ( firstTime() ) { |
| refresh(); |
| } |
| } |
| |
| /// Listener Functions |
| |
| /// MouseListener interface function |
| /// Zooms a character when mouse is pressed above it |
| public void mousePressed( MouseEvent e ) { |
| if ( !showingError) { |
| if ( checkMouseLoc( e )) { |
| showZoomed(); |
| this.setCursor( blankCursor ); |
| } |
| } |
| } |
| |
| /// MouseListener interface function |
| /// Redraws the area that was drawn over by zoomed character |
| public void mouseReleased( MouseEvent e ) { |
| if ( textToUse == RANGE_TEXT || textToUse == ALL_GLYPHS ) { |
| if ( nowZooming ) |
| zoomWindow.hide(); |
| nowZooming = false; |
| } |
| this.setCursor( Cursor.getDefaultCursor() ); |
| } |
| |
| /// MouseListener interface function |
| /// Resets the status bar to display range instead of a specific character |
| public void mouseExited( MouseEvent e ) { |
| if ( !showingError && !nowZooming ) |
| f2dt.fireChangeStatus( backupStatusString, false ); |
| } |
| |
| /// MouseMotionListener interface function |
| /// Adjusts the status bar message when mouse moves over a character |
| public void mouseMoved( MouseEvent e ) { |
| if ( !showingError ) { |
| if ( !checkMouseLoc( e )) |
| f2dt.fireChangeStatus( backupStatusString, false ); |
| } |
| } |
| |
| /// MouseMotionListener interface function |
| /// Scrolls the zoomed character when mouse is dragged |
| public void mouseDragged( MouseEvent e ) { |
| if ( !showingError ) |
| if ( nowZooming ) { |
| if ( checkMouseLoc( e ) && currMouseOverChar != prevZoomChar ) |
| showZoomed(); |
| } |
| } |
| |
| /// Empty function to comply with interface requirement |
| public void mouseClicked( MouseEvent e ) {} |
| public void mouseEntered( MouseEvent e ) {} |
| } |
| |
| private final class CannotDrawException extends RuntimeException { |
| /// Error ID |
| public final int id; |
| |
| public CannotDrawException( int i ) { |
| id = i; |
| } |
| } |
| |
| enum FMValues { |
| FMDEFAULT ("DEFAULT", VALUE_FRACTIONALMETRICS_DEFAULT), |
| FMOFF ("OFF", VALUE_FRACTIONALMETRICS_OFF), |
| FMON ("ON", VALUE_FRACTIONALMETRICS_ON); |
| |
| private String name; |
| private Object hint; |
| |
| private static FMValues[] valArray; |
| |
| FMValues(String s, Object o) { |
| name = s; |
| hint = o; |
| } |
| |
| public String toString() { |
| return name; |
| } |
| |
| public Object getHint() { |
| return hint; |
| } |
| public static Object getValue(int ordinal) { |
| if (valArray == null) { |
| valArray = (FMValues[])EnumSet.allOf(FMValues.class).toArray(new FMValues[0]); |
| } |
| for (int i=0;i<valArray.length;i++) { |
| if (valArray[i].ordinal() == ordinal) { |
| return valArray[i]; |
| } |
| } |
| return valArray[0]; |
| } |
| private static FMValues[] getArray() { |
| if (valArray == null) { |
| valArray = (FMValues[])EnumSet.allOf(FMValues.class).toArray(new FMValues[0]); |
| } |
| return valArray; |
| } |
| |
| public static int getHintVal(Object hint) { |
| getArray(); |
| for (int i=0;i<valArray.length;i++) { |
| if (valArray[i].getHint() == hint) { |
| return i; |
| } |
| } |
| return 0; |
| } |
| } |
| |
| enum AAValues { |
| AADEFAULT ("DEFAULT", VALUE_TEXT_ANTIALIAS_DEFAULT), |
| AAOFF ("OFF", VALUE_TEXT_ANTIALIAS_OFF), |
| AAON ("ON", VALUE_TEXT_ANTIALIAS_ON), |
| AAGASP ("GASP", VALUE_TEXT_ANTIALIAS_GASP), |
| AALCDHRGB ("LCD_HRGB", VALUE_TEXT_ANTIALIAS_LCD_HRGB), |
| AALCDHBGR ("LCD_HBGR", VALUE_TEXT_ANTIALIAS_LCD_HBGR), |
| AALCDVRGB ("LCD_VRGB", VALUE_TEXT_ANTIALIAS_LCD_VRGB), |
| AALCDVBGR ("LCD_VBGR", VALUE_TEXT_ANTIALIAS_LCD_VBGR); |
| |
| private String name; |
| private Object hint; |
| |
| private static AAValues[] valArray; |
| |
| AAValues(String s, Object o) { |
| name = s; |
| hint = o; |
| } |
| |
| public String toString() { |
| return name; |
| } |
| |
| public Object getHint() { |
| return hint; |
| } |
| |
| public static boolean isLCDMode(Object o) { |
| return (o instanceof AAValues && |
| ((AAValues)o).ordinal() >= AALCDHRGB.ordinal()); |
| } |
| |
| public static Object getValue(int ordinal) { |
| if (valArray == null) { |
| valArray = (AAValues[])EnumSet.allOf(AAValues.class).toArray(new AAValues[0]); |
| } |
| for (int i=0;i<valArray.length;i++) { |
| if (valArray[i].ordinal() == ordinal) { |
| return valArray[i]; |
| } |
| } |
| return valArray[0]; |
| } |
| |
| private static AAValues[] getArray() { |
| if (valArray == null) { |
| Object [] oa = EnumSet.allOf(AAValues.class).toArray(new AAValues[0]); |
| valArray = (AAValues[])(EnumSet.allOf(AAValues.class).toArray(new AAValues[0])); |
| } |
| return valArray; |
| } |
| |
| public static int getHintVal(Object hint) { |
| getArray(); |
| for (int i=0;i<valArray.length;i++) { |
| if (valArray[i].getHint() == hint) { |
| return i; |
| } |
| } |
| return 0; |
| } |
| |
| } |
| |
| private static Integer defaultContrast; |
| static Integer getDefaultLCDContrast() { |
| if (defaultContrast == null) { |
| GraphicsConfiguration gc = |
| GraphicsEnvironment.getLocalGraphicsEnvironment(). |
| getDefaultScreenDevice().getDefaultConfiguration(); |
| Graphics2D g2d = |
| (Graphics2D)(gc.createCompatibleImage(1,1).getGraphics()); |
| defaultContrast = (Integer) |
| g2d.getRenderingHint(RenderingHints.KEY_TEXT_LCD_CONTRAST); |
| } |
| return defaultContrast; |
| } |
| } |