下面列出了java.awt.FontMetrics#getMaxAdvance ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
public static void main(String ... args) {
Font font = new Font(Font.DIALOG, Font.PLAIN, FONT_SIZE);
Graphics2D g2d = createGraphics();
FontMetrics ref = null;
RuntimeException failure = null;
for (int a = 0; a < 360; a += 15) {
Graphics2D g = (Graphics2D)g2d.create();
g.rotate(Math.toRadians(a));
FontMetrics m = g.getFontMetrics(font);
g.dispose();
boolean status = true;
if (ref == null) {
ref = m;
} else {
status = ref.getAscent() == m.getAscent() &&
ref.getDescent() == m.getDescent() &&
ref.getLeading() == m.getLeading() &&
ref.getMaxAdvance() == m.getMaxAdvance();
}
System.out.printf("Metrics a%d, d%d, l%d, m%d (%d) %s\n",
m.getAscent(), m.getDescent(), m.getLeading(), m.getMaxAdvance(),
(int)a, status ? "OK" : "FAIL");
if (!status && failure == null) {
failure = new RuntimeException("Font metrics differ for angle " + a);
}
}
if (failure != null) {
throw failure;
}
System.out.println("done");
}
public static void main(String ... args) {
Font font = new Font(Font.DIALOG, Font.PLAIN, FONT_SIZE);
Graphics2D g2d = createGraphics();
FontMetrics ref = null;
RuntimeException failure = null;
for (int a = 0; a < 360; a += 15) {
Graphics2D g = (Graphics2D)g2d.create();
g.rotate(Math.toRadians(a));
FontMetrics m = g.getFontMetrics(font);
g.dispose();
boolean status = true;
if (ref == null) {
ref = m;
} else {
status = ref.getAscent() == m.getAscent() &&
ref.getDescent() == m.getDescent() &&
ref.getLeading() == m.getLeading() &&
ref.getMaxAdvance() == m.getMaxAdvance();
}
System.out.printf("Metrics a%d, d%d, l%d, m%d (%d) %s\n",
m.getAscent(), m.getDescent(), m.getLeading(), m.getMaxAdvance(),
(int)a, status ? "OK" : "FAIL");
if (!status && failure == null) {
failure = new RuntimeException("Font metrics differ for angle " + a);
}
}
if (failure != null) {
throw failure;
}
System.out.println("done");
}
public int getBitmapFontRAMUsage() {
BufferedImage image = new BufferedImage(50, 50, BufferedImage.TYPE_INT_RGB);
Graphics2D g2d = (Graphics2D)image.getGraphics();
g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_COLOR_RENDERING, RenderingHints.VALUE_COLOR_RENDER_QUALITY);
g2d.setRenderingHint(RenderingHints.KEY_STROKE_CONTROL, RenderingHints.VALUE_STROKE_NORMALIZE);
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING, bitmapAntialiasing);
g2d.setFont(java.awt.Font.decode(lookupFont));
FontMetrics metrics = g2d.getFontMetrics();
FontRenderContext context = g2d.getFontRenderContext();
int baseline = (int)Math.ceil(metrics.getMaxAscent());
int[] offsets = new int[bitmapCharset.length()];
int[] widths = new int[offsets.length];
int currentOffset = 0;
for(int iter = 0 ; iter < bitmapCharset.length() ; iter++) {
offsets[iter] = currentOffset;
String currentChar = bitmapCharset.substring(iter, iter + 1);
g2d.drawString(currentChar, currentOffset, baseline);
Rectangle2D rect = g2d.getFont().getStringBounds(currentChar, context);
widths[iter] = (int)Math.ceil(rect.getWidth());
// max advance works but it makes a HUGE image in terms of width which
// occupies more ram
if(g2d.getFont().isItalic()) {
currentOffset += metrics.getMaxAdvance();
} else {
currentOffset += widths[iter] + 1;
}
}
g2d.dispose();
return currentOffset * getHeight() * 4;
}
/**
* Draws the tick marks and labels.
*
* @param g2 the graphics device.
* @param cursor the cursor.
* @param plotArea the plot area.
* @param dataArea the area inside the axes.
* @param edge the side on which the axis is displayed.
*
* @return The axis state.
*/
@Override
protected AxisState drawTickMarksAndLabels(Graphics2D g2, double cursor,
Rectangle2D plotArea, Rectangle2D dataArea, RectangleEdge edge) {
this.internalMarkerWhenTicksOverlap = false;
AxisState ret = super.drawTickMarksAndLabels(g2, cursor, plotArea,
dataArea, edge);
// continue and separate the labels only if necessary
if (!this.internalMarkerWhenTicksOverlap) {
return ret;
}
double ol;
FontMetrics fm = g2.getFontMetrics(getTickLabelFont());
if (isVerticalTickLabels()) {
ol = fm.getMaxAdvance();
}
else {
ol = fm.getHeight();
}
double il = 0;
if (isTickMarksVisible()) {
float xx = (float) valueToJava2D(getRange().getUpperBound(),
dataArea, edge);
Line2D mark = null;
g2.setStroke(getTickMarkStroke());
g2.setPaint(getTickMarkPaint());
if (edge == RectangleEdge.LEFT) {
mark = new Line2D.Double(cursor - ol, xx, cursor + il, xx);
}
else if (edge == RectangleEdge.RIGHT) {
mark = new Line2D.Double(cursor + ol, xx, cursor - il, xx);
}
else if (edge == RectangleEdge.TOP) {
mark = new Line2D.Double(xx, cursor - ol, xx, cursor + il);
}
else if (edge == RectangleEdge.BOTTOM) {
mark = new Line2D.Double(xx, cursor + ol, xx, cursor - il);
}
g2.draw(mark);
}
return ret;
}
/**
* Draws the tick marks and labels.
*
* @param g2 the graphics device.
* @param cursor the cursor.
* @param plotArea the plot area.
* @param dataArea the area inside the axes.
* @param edge the side on which the axis is displayed.
*
* @return The axis state.
*/
@Override
protected AxisState drawTickMarksAndLabels(Graphics2D g2, double cursor,
Rectangle2D plotArea, Rectangle2D dataArea, RectangleEdge edge) {
this.internalMarkerWhenTicksOverlap = false;
AxisState ret = super.drawTickMarksAndLabels(g2, cursor, plotArea,
dataArea, edge);
// continue and separate the labels only if necessary
if (!this.internalMarkerWhenTicksOverlap) {
return ret;
}
double ol;
FontMetrics fm = g2.getFontMetrics(getTickLabelFont());
if (isVerticalTickLabels()) {
ol = fm.getMaxAdvance();
}
else {
ol = fm.getHeight();
}
double il = 0;
if (isTickMarksVisible()) {
float xx = (float) valueToJava2D(getRange().getUpperBound(),
dataArea, edge);
Line2D mark = null;
g2.setStroke(getTickMarkStroke());
g2.setPaint(getTickMarkPaint());
if (edge == RectangleEdge.LEFT) {
mark = new Line2D.Double(cursor - ol, xx, cursor + il, xx);
}
else if (edge == RectangleEdge.RIGHT) {
mark = new Line2D.Double(cursor + ol, xx, cursor - il, xx);
}
else if (edge == RectangleEdge.TOP) {
mark = new Line2D.Double(xx, cursor - ol, xx, cursor + il);
}
else if (edge == RectangleEdge.BOTTOM) {
mark = new Line2D.Double(xx, cursor + ol, xx, cursor - il);
}
g2.draw(mark);
}
return ret;
}
/**
* Draws the tick marks and labels.
*
* @param g2 the graphics device.
* @param cursor the cursor.
* @param plotArea the plot area.
* @param dataArea the area inside the axes.
* @param edge the side on which the axis is displayed.
* @param info the plot rendering info.
*
* @return The axis state.
*/
protected AxisState drawTickMarksAndLabels(Graphics2D g2, double cursor,
Rectangle2D plotArea, Rectangle2D dataArea, RectangleEdge edge,
PlotRenderingInfo info) {
this.internalMarkerWhenTicksOverlap = false;
AxisState ret = super.drawTickMarksAndLabels(g2, cursor, plotArea,
dataArea, edge, info);
// continue and separate the labels only if necessary
if (!this.internalMarkerWhenTicksOverlap) {
return ret;
}
double ol = getTickMarkOutsideLength();
FontMetrics fm = g2.getFontMetrics(getTickLabelFont());
if (isVerticalTickLabels()) {
ol = fm.getMaxAdvance();
}
else {
ol = fm.getHeight();
}
double il = 0;
if (isTickMarksVisible()) {
float xx = (float) valueToJava2D(
getRange().getUpperBound(), dataArea, edge
);
Line2D mark = null;
g2.setStroke(getTickMarkStroke());
g2.setPaint(getTickMarkPaint());
if (edge == RectangleEdge.LEFT) {
mark = new Line2D.Double(cursor - ol, xx, cursor + il, xx);
}
else if (edge == RectangleEdge.RIGHT) {
mark = new Line2D.Double(cursor + ol, xx, cursor - il, xx);
}
else if (edge == RectangleEdge.TOP) {
mark = new Line2D.Double(xx, cursor - ol, xx, cursor + il);
}
else if (edge == RectangleEdge.BOTTOM) {
mark = new Line2D.Double(xx, cursor + ol, xx, cursor - il);
}
g2.draw(mark);
}
return ret;
}
public static void main(String[] args) throws Exception {
GraphicsEnvironment e =
GraphicsEnvironment.getLocalGraphicsEnvironment();
Font[] fonts = e.getAllFonts();
BufferedImage bi = new BufferedImage(500, 500,
BufferedImage.TYPE_INT_RGB);
for (AntialiasHint antialiasHint : antialiasHints) {
for (Font f : fonts) {
for (StyleAndSize styleAndSize : stylesAndSizes) {
f = f.deriveFont(styleAndSize.style, styleAndSize.size);
Graphics2D g2d = bi.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
antialiasHint.getHint());
FontMetrics fm = g2d.getFontMetrics(f);
int[] width;
int maxWidth = -1;
int maxAdvance = fm.getMaxAdvance();
if (debug) {
System.out.println("Testing " + f + " in " +
antialiasHint);
System.out.println("getMaxAdvance: " + maxAdvance);
}
if (maxAdvance != -1) {
String failureMessage = null;
width = fm.getWidths();
for (int j = 0; j < width.length; j++) {
if (width[j] > maxWidth) {
maxWidth = width[j];
}
if (width[j] > maxAdvance) {
failureMessage = "FAILED: getMaxAdvance is " +
"not max for font: " +
f.toString() +
" getMaxAdvance(): " +
maxAdvance +
" getWidths()[" + j + "]: " +
width[j];
throw new Exception(failureMessage);
}
}
}
if (debug) {
System.out.println("Max char width: " + maxWidth);
System.out.println("PASSED");
System.out.println(".........................");
}
}
}
}
System.out.println("TEST PASS - OK");
}
public static void main(String[] args) throws Exception {
GraphicsEnvironment e =
GraphicsEnvironment.getLocalGraphicsEnvironment();
Font[] fonts = e.getAllFonts();
BufferedImage bi = new BufferedImage(500, 500,
BufferedImage.TYPE_INT_RGB);
for (AntialiasHint antialiasHint : antialiasHints) {
for (Font f : fonts) {
for (StyleAndSize styleAndSize : stylesAndSizes) {
f = f.deriveFont(styleAndSize.style, styleAndSize.size);
Graphics2D g2d = bi.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
antialiasHint.getHint());
FontMetrics fm = g2d.getFontMetrics(f);
int[] width;
int maxWidth = -1;
int maxAdvance = fm.getMaxAdvance();
if (debug) {
System.out.println("Testing " + f + " in " +
antialiasHint);
System.out.println("getMaxAdvance: " + maxAdvance);
}
if (maxAdvance != -1) {
String failureMessage = null;
width = fm.getWidths();
for (int j = 0; j < width.length; j++) {
if (width[j] > maxWidth) {
maxWidth = width[j];
}
if (width[j] > maxAdvance) {
failureMessage = "FAILED: getMaxAdvance is " +
"not max for font: " +
f.toString() +
" getMaxAdvance(): " +
maxAdvance +
" getWidths()[" + j + "]: " +
width[j];
throw new Exception(failureMessage);
}
}
}
if (debug) {
System.out.println("Max char width: " + maxWidth);
System.out.println("PASSED");
System.out.println(".........................");
}
}
}
}
System.out.println("TEST PASS - OK");
}
/**
* Draws the tick marks and labels.
*
* @param g2 the graphics device.
* @param cursor the cursor.
* @param plotArea the plot area.
* @param dataArea the area inside the axes.
* @param edge the side on which the axis is displayed.
* @param info the plot rendering info.
*
* @return The axis state.
*/
protected AxisState drawTickMarksAndLabels(Graphics2D g2, double cursor,
Rectangle2D plotArea, Rectangle2D dataArea, RectangleEdge edge,
PlotRenderingInfo info) {
this.internalMarkerWhenTicksOverlap = false;
AxisState ret = super.drawTickMarksAndLabels(g2, cursor, plotArea,
dataArea, edge, info);
// continue and separate the labels only if necessary
if (!this.internalMarkerWhenTicksOverlap) {
return ret;
}
double ol = getTickMarkOutsideLength();
FontMetrics fm = g2.getFontMetrics(getTickLabelFont());
if (isVerticalTickLabels()) {
ol = fm.getMaxAdvance();
}
else {
ol = fm.getHeight();
}
double il = 0;
if (isTickMarksVisible()) {
float xx = (float) valueToJava2D(getRange().getUpperBound(),
dataArea, edge);
Line2D mark = null;
g2.setStroke(getTickMarkStroke());
g2.setPaint(getTickMarkPaint());
if (edge == RectangleEdge.LEFT) {
mark = new Line2D.Double(cursor - ol, xx, cursor + il, xx);
}
else if (edge == RectangleEdge.RIGHT) {
mark = new Line2D.Double(cursor + ol, xx, cursor - il, xx);
}
else if (edge == RectangleEdge.TOP) {
mark = new Line2D.Double(xx, cursor - ol, xx, cursor + il);
}
else if (edge == RectangleEdge.BOTTOM) {
mark = new Line2D.Double(xx, cursor + ol, xx, cursor - il);
}
g2.draw(mark);
}
return ret;
}
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() );
}
}
public static void main(String[] args) throws Exception {
GraphicsEnvironment e =
GraphicsEnvironment.getLocalGraphicsEnvironment();
Font[] fonts = e.getAllFonts();
BufferedImage bi = new BufferedImage(500, 500,
BufferedImage.TYPE_INT_RGB);
for (AntialiasHint antialiasHint : antialiasHints) {
for (Font f : fonts) {
for (StyleAndSize styleAndSize : stylesAndSizes) {
f = f.deriveFont(styleAndSize.style, styleAndSize.size);
Graphics2D g2d = bi.createGraphics();
g2d.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
antialiasHint.getHint());
FontMetrics fm = g2d.getFontMetrics(f);
int[] width;
int maxWidth = -1;
int maxAdvance = fm.getMaxAdvance();
if (debug) {
System.out.println("Testing " + f + " in " +
antialiasHint);
System.out.println("getMaxAdvance: " + maxAdvance);
}
if (maxAdvance != -1) {
String failureMessage = null;
width = fm.getWidths();
for (int j = 0; j < width.length; j++) {
if (width[j] > maxWidth) {
maxWidth = width[j];
}
if (width[j] > maxAdvance) {
failureMessage = "FAILED: getMaxAdvance is " +
"not max for font: " +
f.toString() +
" getMaxAdvance(): " +
maxAdvance +
" getWidths()[" + j + "]: " +
width[j];
throw new Exception(failureMessage);
}
}
}
if (debug) {
System.out.println("Max char width: " + maxWidth);
System.out.println("PASSED");
System.out.println(".........................");
}
}
}
}
System.out.println("TEST PASS - OK");
}
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() );
}
}
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() );
}
}
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() );
}
}
/**
* Draws the tick marks and labels.
*
* @param g2 the graphics device.
* @param cursor the cursor.
* @param plotArea the plot area.
* @param dataArea the area inside the axes.
* @param edge the side on which the axis is displayed.
*
* @return The axis state.
*/
@Override
protected AxisState drawTickMarksAndLabels(Graphics2D g2, double cursor,
Rectangle2D plotArea, Rectangle2D dataArea, RectangleEdge edge) {
this.internalMarkerWhenTicksOverlap = false;
AxisState ret = super.drawTickMarksAndLabels(g2, cursor, plotArea,
dataArea, edge);
// continue and separate the labels only if necessary
if (!this.internalMarkerWhenTicksOverlap) {
return ret;
}
double ol;
FontMetrics fm = g2.getFontMetrics(getTickLabelFont());
if (isVerticalTickLabels()) {
ol = fm.getMaxAdvance();
}
else {
ol = fm.getHeight();
}
double il = 0;
if (isTickMarksVisible()) {
float xx = (float) valueToJava2D(getRange().getUpperBound(),
dataArea, edge);
Line2D mark = null;
g2.setStroke(getTickMarkStroke());
g2.setPaint(getTickMarkPaint());
if (edge == RectangleEdge.LEFT) {
mark = new Line2D.Double(cursor - ol, xx, cursor + il, xx);
}
else if (edge == RectangleEdge.RIGHT) {
mark = new Line2D.Double(cursor + ol, xx, cursor - il, xx);
}
else if (edge == RectangleEdge.TOP) {
mark = new Line2D.Double(xx, cursor - ol, xx, cursor + il);
}
else if (edge == RectangleEdge.BOTTOM) {
mark = new Line2D.Double(xx, cursor + ol, xx, cursor - il);
}
g2.draw(mark);
}
return ret;
}
public static String getCaptcha(HttpServletRequest request, HttpServletResponse response) {
try {
Delegator delegator = (Delegator) request.getAttribute("delegator");
final String captchaSizeConfigName = StringUtils.defaultIfEmpty(request.getParameter("captchaSize"), "default");
final String captchaSizeConfig = EntityUtilProperties.getPropertyValue("captcha", "captcha." + captchaSizeConfigName, delegator);
final String[] captchaSizeConfigs = captchaSizeConfig.split("\\|");
final String captchaCodeId = StringUtils.defaultIfEmpty(request.getParameter("captchaCodeId"), ""); // this is used to uniquely identify in the user session the attribute where the captcha code for the last captcha for the form is stored
final int fontSize = Integer.parseInt(captchaSizeConfigs[0]);
final int height = Integer.parseInt(captchaSizeConfigs[1]);
final int width = Integer.parseInt(captchaSizeConfigs[2]);
final int charsToPrint = UtilProperties.getPropertyAsInteger("captcha", "captcha.code_length", 6);
final char[] availableChars = EntityUtilProperties.getPropertyValue("captcha", "captcha.characters", delegator).toCharArray();
//It is possible to pass the font size, image width and height with the request as well
Color backgroundColor = Color.gray;
Color borderColor = Color.DARK_GRAY;
Color textColor = Color.ORANGE;
Color circleColor = new Color(160, 160, 160);
Font textFont = new Font("Arial", Font.PLAIN, fontSize);
int circlesToDraw = 6;
float horizMargin = 20.0f;
double rotationRange = 0.7; // in radians
BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
Graphics2D g = (Graphics2D) bufferedImage.getGraphics();
g.setColor(backgroundColor);
g.fillRect(0, 0, width, height);
//Generating some circles for background noise
g.setColor(circleColor);
for (int i = 0; i < circlesToDraw; i++) {
int circleRadius = (int) (Math.random() * height / 2.0);
int circleX = (int) (Math.random() * width - circleRadius);
int circleY = (int) (Math.random() * height - circleRadius);
g.drawOval(circleX, circleY, circleRadius * 2, circleRadius * 2);
}
g.setColor(textColor);
g.setFont(textFont);
FontMetrics fontMetrics = g.getFontMetrics();
int maxAdvance = fontMetrics.getMaxAdvance();
int fontHeight = fontMetrics.getHeight();
String captchaCode = RandomStringUtils.random(6, availableChars);
float spaceForLetters = -horizMargin * 2 + width;
float spacePerChar = spaceForLetters / (charsToPrint - 1.0f);
for (int i = 0; i < captchaCode.length(); i++) {
// this is a separate canvas used for the character so that
// we can rotate it independently
int charWidth = fontMetrics.charWidth(captchaCode.charAt(i));
int charDim = Math.max(maxAdvance, fontHeight);
int halfCharDim = (charDim / 2);
BufferedImage charImage = new BufferedImage(charDim, charDim, BufferedImage.TYPE_INT_ARGB);
Graphics2D charGraphics = charImage.createGraphics();
charGraphics.translate(halfCharDim, halfCharDim);
double angle = (Math.random() - 0.5) * rotationRange;
charGraphics.transform(AffineTransform.getRotateInstance(angle));
charGraphics.translate(-halfCharDim, -halfCharDim);
charGraphics.setColor(textColor);
charGraphics.setFont(textFont);
int charX = (int) (0.5 * charDim - 0.5 * charWidth);
charGraphics.drawString("" + captchaCode.charAt(i), charX,
((charDim - fontMetrics.getAscent()) / 2 + fontMetrics.getAscent()));
float x = horizMargin + spacePerChar * (i) - charDim / 2.0f;
int y = ((height - charDim) / 2);
g.drawImage(charImage, (int) x, y, charDim, charDim, null, null);
charGraphics.dispose();
}
// Drawing the image border
g.setColor(borderColor);
g.drawRect(0, 0, width - 1, height - 1);
g.dispose();
response.setContentType("image/jpeg");
ImageIO.write(bufferedImage, "jpg", response.getOutputStream());
HttpSession session = request.getSession();
Map<String, String> captchaCodeMap = UtilGenerics.checkMap(session.getAttribute("_CAPTCHA_CODE_"));
if (captchaCodeMap == null) {
captchaCodeMap = new HashMap<>();
session.setAttribute("_CAPTCHA_CODE_", captchaCodeMap);
}
captchaCodeMap.put(captchaCodeId, captchaCode);
} catch (IOException | IllegalArgumentException | IllegalStateException ioe) {
Debug.logError(ioe.getMessage(), module);
}
return "success";
}
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() );
}
}
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() );
}
}
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() );
}
}
/**
* Draws the tick marks and labels.
*
* @param g2 the graphics device.
* @param cursor the cursor.
* @param plotArea the plot area.
* @param dataArea the area inside the axes.
* @param edge the side on which the axis is displayed.
*
* @return The axis state.
*/
@Override
protected AxisState drawTickMarksAndLabels(Graphics2D g2, double cursor,
Rectangle2D plotArea, Rectangle2D dataArea, RectangleEdge edge) {
this.internalMarkerWhenTicksOverlap = false;
AxisState ret = super.drawTickMarksAndLabels(g2, cursor, plotArea,
dataArea, edge);
// continue and separate the labels only if necessary
if (!this.internalMarkerWhenTicksOverlap) {
return ret;
}
double ol;
FontMetrics fm = g2.getFontMetrics(getTickLabelFont());
if (isVerticalTickLabels()) {
ol = fm.getMaxAdvance();
}
else {
ol = fm.getHeight();
}
double il = 0;
if (isTickMarksVisible()) {
float xx = (float) valueToJava2D(getRange().getUpperBound(),
dataArea, edge);
Line2D mark = null;
g2.setStroke(getTickMarkStroke());
g2.setPaint(getTickMarkPaint());
if (edge == RectangleEdge.LEFT) {
mark = new Line2D.Double(cursor - ol, xx, cursor + il, xx);
}
else if (edge == RectangleEdge.RIGHT) {
mark = new Line2D.Double(cursor + ol, xx, cursor - il, xx);
}
else if (edge == RectangleEdge.TOP) {
mark = new Line2D.Double(xx, cursor - ol, xx, cursor + il);
}
else if (edge == RectangleEdge.BOTTOM) {
mark = new Line2D.Double(xx, cursor + ol, xx, cursor - il);
}
g2.draw(mark);
}
return ret;
}