/*
*
* 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
*
* - 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.
*/
/**
*
* @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
/// Drawing Option Constants
{ "plain", "bold", "italic", "bold italic" };
{ "with no transforms", "with scaling", "with Shearing", "with rotation" };
"drawString", "drawChars", "drawBytes", "drawGlyphVector",
"TextLayout.draw", "GlyphVector.getOutline", "TextLayout.getOutline" };
{ " Unicode ", " Glyph Code ", " lines ", " lines " };
{ "", "", " of User Text ", " of LineBreakMeasurer-reformatted Text " };
/// General Graphics Variable
private boolean updateBackBuffer = true;
private boolean updateFontMetrics = true;
private boolean updateFont = true;
private boolean force16Cols = false;
public boolean showingError = false;
/// Printing constants and variables
/// Text drawing variables
private boolean showGrid = true;
/// Parent Font2DTest panel
parent = f;
fc = new FontCanvas();
this.setLayout( new BorderLayout() );
verticalBar.addAdjustmentListener( this );
this.addComponentListener( new ComponentAdapter() {
public void componentResized( ComponentEvent e ) {
updateBackBuffer = true;
updateFontMetrics = true;
}
});
/// Initialize font and its infos
}
}
}
/// Functions called by the main programs to set the various parameters
updateBackBuffer = true;
updateFontMetrics = true;
}
/// convenience fcn to create AffineTransform of appropriate type
/// ABP
switch ( transform )
{
case SCALE:
case ROTATE:
case SHEAR:
case NONE:
break;
default:
//System.err.println( "Illegal G2 Transform Arg: " + transform);
break;
}
return at;
}
}
boolean fontModified = false;
fontModified = true;
/// Recreate the font as specified
}
if ( fontTransform != NONE ) {
}
updateBackBuffer = true;
updateFontMetrics = true;
if ( fontModified ) {
/// Tell main panel to update the font info
}
}
updateBackBuffer = true;
updateFontMetrics = true;
}
public void setDrawMethod( int i ) {
drawMethod = i;
updateBackBuffer = true;
}
textToUse = i;
if ( textToUse == RANGE_TEXT )
else if ( textToUse == ALL_GLYPHS )
}
updateBackBuffer = true;
updateFontMetrics = true;
}
public void setGridDisplay( boolean b ) {
showGrid = b;
updateBackBuffer = true;
}
public void setForce16Columns( boolean b ) {
force16Cols = b;
updateBackBuffer = true;
updateFontMetrics = true;
}
/// Prints out the text display area
public void doPrint( int i ) {
}
printMode = i;
if ( printer.printDialog() ) {
try {
}
catch ( Exception e ) {
}
}
}
/// Displays the page setup dialog and updates PageFormat info
public void doPageSetup() {
}
}
/// Obtains the information about selected font
private void updateFontInfo() {
if ( textToUse == RANGE_TEXT ) {
if ( testFont.canDisplay( i ))
numGlyphs++;
}
else
}
/// Accessor for the font information
return fontInfos;
}
/// Collects the currectly set options and returns them as string
/// 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;
lcdContrast + "\n");
return options;
}
/// Reload all options and refreshes the canvas
int transform, int g2transform,
/// Since repaint call has a low priority, these functions will finish
/// before the actual repainting is done
setGridDisplay( grid );
// previous call to readTextFile has already set the text to draw
}
setDrawMethod( method );
}
/// Writes the current screen to PNG file
}
/// When scrolled using the scroll bar, update the backbuffer
updateBackBuffer = true;
}
// 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]
}
/// Inner class definition...
/// Inner panel that holds the actual drawing area and its routines
/// Number of characters that will fit across and down this canvas
/// FontMetrics variables
/// Here, gridWidth is equivalent to maxAdvance (slightly bigger though)
/// and gridHeight is equivalent to lineHeight
/// Offset from the top left edge of the canvas where the draw will start
/// Offscreen buffer of this canvas
/// LineBreak'ed TextLayout vector
/// Whether the current draw command requested is for printing
private boolean isPrinting = false;
/// Other printing infos
/// Information about zooming (used with range text draw)
private boolean nowZooming = false;
private boolean firstTime = true;
// ABP
/// Status bar message backup
/// Error constants
"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.",
};
/// Other variables
public FontCanvas() {
this.addMouseListener( this );
this.addMouseMotionListener( this );
/// Creates an invisble pointer by giving it bogus image
/// Possibly find a workaround for this...
byte bogus[] = { (byte) 0 };
}
};
zoomWindow.pack();
}
public void refresh() {
firstTime = false;
updateBackBuffer = true;
repaint();
}
/// Sets the font, hints, according to the set parameters
/* 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 explictly 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 &&
} else {
}
}
}
/// Draws one character at time onto the canvas according to
/// the method requested (Used for RANGE_TEXT and ALL_GLYPHS)
/// Create GlyphVector to measure the exact visual advance
/// Using that number, adjust the position of the character drawn
if ( textToUse == ALL_GLYPHS )
else
// 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];
} catch (NoninvertibleTransformException e) {
}
/// ABP - keep track of old tform, restore it later
if ( textToUse == ALL_GLYPHS )
else {
else {
}
switch ( drawMethod ) {
case DRAW_STRING:
break;
case DRAW_CHARS:
break;
case DRAW_BYTES:
if ( charCode > 0xff )
throw new CannotDrawException( DRAW_BYTES_ERROR );
break;
case DRAW_GLYPHV:
break;
case TL_DRAW:
break;
case GV_OUTLINE:
break;
case TL_OUTLINE:
g2.getFontRenderContext() );
}
}
/// ABP - restore old tform
}
/// Draws one line of text at given position
/// ABP - keep track of old tform, restore it later
switch ( drawMethod ) {
case DRAW_STRING:
break;
case DRAW_CHARS:
break;
case DRAW_BYTES:
try {
}
catch ( Exception e ) {
e.printStackTrace();
}
break;
case DRAW_GLYPHV:
break;
case TL_DRAW:
g2.getFontRenderContext() );
break;
case GV_OUTLINE:
break;
case TL_OUTLINE:
g2.getFontRenderContext() );
}
/// ABP - restore old tform
}
/// Draws one line of text at given position
/// ABP - keep track of old tform, restore it later
/// ABP - restore old tform
}
/// 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)
while ( s.length() < 4 )
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)
if ( textToUse == RANGE_TEXT )
else /// textToUse == ALL_GLYPHS
totalNumRows++;
oldValue = 0;
}
else {
else /// textToUse == FILE_TEXT;
}
verticalBar.setEnabled( false );
}
else {
verticalBar.setEnabled( true );
}
}
/// Calculates the font's metrics that will be used for draw
/// ABP
}
else {
}
/// Give slight extra room for each character
maxAscent += 3;
maxDescent += 3;
if ( force16Cols )
numCharAcross = 16;
else
if ( !isPrinting )
}
else {
canvasInset_X = 5;
canvasInset_Y = 5;
/// gridWidth and numCharAcross will not be used in this mode...
if ( numCharDown == 0 )
/// If this is text loaded from file, prepares the LineBreak'ed
/// text layout at this point
if ( !isPrinting )
lineBreakTLs = new Vector();
}
}
if ( !isPrinting )
}
}
/// Calculates the amount of text that will be displayed on screen
private void calcTextRange() {
if ( isPrinting )
else /// printMode == CUR_RANGE
else
if ( textToUse == RANGE_TEXT ) {
}
else
}
else {
if ( isPrinting )
else /// printMode == ALL_TEXT
else {
}
else
}
// ABP
drawStart = 0;
}
/// Change the status bar if not printing...
if ( !isPrinting ) {
MS_CLOSING[textToUse] );
}
}
/// Draws text according to the parameters set by Font2DTest GUI
/// Create back buffer when not printing, and its Graphics2D
/// Then set drawing parameters for that Graphics2D object
if ( isPrinting )
g2 = (Graphics2D) g;
else {
}
/// sets font, RenderingHints.
/// 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...
/// Draw according to the set "Text to Use" mode
int charToDraw = drawStart;
if ( showGrid )
if ( !isPrinting )
//if ( !isPrinting ) {
// g.setClip( gridLocX, gridLocY, gridWidth + 1, gridHeight + 1 );
// g.drawImage( backBuffer, 0, 0, this );
//}
}
}
}
if ( !isPrinting )
int lineStartX = canvasInset_Y;
}
}
else {
if ( !isPrinting )
xPos =
oneLine.isLeftToRight() ?
if (g2Transform != NONE) {
}
//yPos += oneLine.getAscent();
//oneLine.draw( g2, xPos, yPos );
//yPos += oneLine.getDescent() + oneLine.getLeading();
}
}
if ( !isPrinting )
}
/// Component paintComponent function...
if ( updateBackBuffer ) {
isPrinting = false;
try {
}
catch ( CannotDrawException e ) {
super.paintComponent(g);
return;
}
}
else {
/// Screen refresh
}
showingError = false;
updateBackBuffer = false;
}
/// Printable interface function
/// Component print function...
if ( pageIndex == 0 ) {
/// Reset the last page index to max...
}
if ( pageIndex > 0 )
return NO_SUCH_PAGE;
}
else {
return NO_SUCH_PAGE;
}
/// Back up metrics and other drawing info before printing modifies it
isPrinting = true;
/// Push the actual draw area 60 down to allow info to be printed
try {
}
catch ( CannotDrawException e ) {
return NO_SUCH_PAGE;
}
/// Draw information about what is being printed
" fractional metrics " + fractionalMetricsType +
" and lcd contrast = " + lcdContrast);
/// This indicates that the draw will be completed with this page
/// Restore the changed values back...
/// This is important for JScrollBar settings and LineBreak'ed TLs
return PAGE_EXISTS;
}
/// Ouputs the current canvas into a given PNG file
try {
}
catch ( Exception e ) {
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
/// Check to make sure the mouse click location is within drawn area
int mouseOverChar =
if ( textToUse == RANGE_TEXT )
if ( mouseOverChar > drawEnd )
return false;
/// Update status bar
modeSpecificNumStr( mouseOverChar ), false );
return true;
}
}
return false;
}
/// Shows (updates) the character zoom window
public void showZoomed() {
/// Calculate the zoom area's location and size...
int zoomAreaX =
int zoomAreaY =
/// Position and set size of zoom window as needed
if ( !nowZooming ) {
/// 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
else
}
/// Prepare zoomed image
zoomAreaHeight + 1 );
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...
nowZooming = true;
// 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
if ( !showingError) {
if ( checkMouseLoc( e )) {
showZoomed();
this.setCursor( blankCursor );
}
}
}
/// MouseListener interface function
/// Redraws the area that was drawn over by zoomed character
if ( nowZooming )
zoomWindow.hide();
nowZooming = false;
}
}
/// MouseListener interface function
/// Resets the status bar to display range instead of a specific character
if ( !showingError && !nowZooming )
}
/// MouseMotionListener interface function
/// Adjusts the status bar message when mouse moves over a character
if ( !showingError ) {
if ( !checkMouseLoc( e ))
}
}
/// MouseMotionListener interface function
/// Scrolls the zoomed character when mouse is dragged
if ( !showingError )
if ( nowZooming ) {
showZoomed();
}
}
/// Empty function to comply with interface requirement
}
/// Error ID
public final int id;
public CannotDrawException( int i ) {
id = i;
}
}
enum FMValues {
name = s;
hint = o;
}
return name;
}
return hint;
}
}
return valArray[i];
}
}
return valArray[0];
}
}
return valArray;
}
getArray();
return i;
}
}
return 0;
}
}
enum AAValues {
name = s;
hint = o;
}
return name;
}
return hint;
}
return (o instanceof AAValues &&
}
}
return valArray[i];
}
}
return valArray[0];
}
}
return valArray;
}
getArray();
return i;
}
}
return 0;
}
}
if (defaultContrast == null) {
}
return defaultContrast;
}
}