Skip to content

Instantly share code, notes, and snippets.

@Palmr
Created May 28, 2015 15:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Palmr/36fe782eba7ee6587e87 to your computer and use it in GitHub Desktop.
Save Palmr/36fe782eba7ee6587e87 to your computer and use it in GitHub Desktop.
Massive text draw function
//Draw a wrapped sting
private static boolean isBreakable(char c) {
return (c == ' ' || c == '\t' || c == '-' || c == '\\' || c == '/' || c == '_');
}
private static boolean isNewLine(char c) {
return (c == '\n' || c == '\r');
}
/**
* Draw a string onto a graphics2d object, wrapping words at pWidth pixels wide.
* If a word has to be cut, if less than 75% is cut off it's added back on and the word shrunk, if pShrinkWords == true
*
* @param pString Words to draw
* @param pG Graphics2D object reference used to draw
* @param pX Top left ordinate of where to start drawing down from
* @param pY Top left ordinate of where to start drawing down from
* @param pWidth Width to wrap string at in pixels
* @param pHeight Height to cut off overflow at in pixels
* @param pYOverflow Boolean to allow overflow or not
* @param pShrinkWords Boolean to shrink words that are bigger than the width
* @param pJustification Left/right/centre line justification
* @param pDraw Boolean to switch drawing on or off (handy for just getting bounds before drawing)
* @return Rectangle of the bounding box
*/
public static Rectangle drawString (String pString, Graphics2D pG, int pX, int pY, int pWidth, int pHeight, boolean pYOverflow, boolean pShrinkWords, String pJustification, boolean pDraw) {
FontMetrics lFontMetrics = pG.getFontMetrics();
Font lDrawFont = pG.getFont();
char[] lCharacters = pString.toCharArray();
int lFontHeight = lFontMetrics.getHeight();
int lLeading = 0;//lFontMetrics.getLeading()/2;
int lY = pY;
boolean lFirstLine = true;
boolean lSuppressLastLine = false;
Integer lLastSpace = null;
int lCharsInBuffer = 0;
StringBuffer lLineBuffer = new StringBuffer();
for (int i = 0; i < lCharacters.length; ++i) {
if (lFontMetrics.stringWidth(lLineBuffer.toString() + lCharacters[i]) < pWidth) {
if (!isNewLine(lCharacters[i])) {
lLineBuffer.append(lCharacters[i]);
lCharsInBuffer++;
if (isBreakable(lCharacters[i])) {
lLastSpace = new Integer(i);
}
}
else {
//Find the next Y position for the new line
lY += lFontHeight + (lFirstLine?-lFontMetrics.getDescent():lLeading);
if ((lY + lFontHeight) > pHeight && pYOverflow == false) {
//Break loop if it's hit the Y limit
break;
}
//Draw the line
if (pDraw) {
drawLine(lLineBuffer.toString(), pG, pX, lY, pWidth, pJustification);
}
//Start the new buffer
lLineBuffer.setLength(0);
lLineBuffer.append(lCharacters[i]);
lLastSpace = null;
lCharsInBuffer = 0;
lFirstLine = false;
}
}
else {
//Try and go back to the last space
if (lLastSpace != null) {
//Space found in line, cut down buffer and hop i back a bit
int lNextBreak = 0;
int j;
for (j = i; j < Math.min((i + (int)(lCharsInBuffer * 0.15)), lCharacters.length); ++j) {
if (isBreakable(lCharacters[j])) {
lNextBreak = j;
break;
}
}
if (j == lCharacters.length) {
lNextBreak = lCharacters.length;
}
if (lNextBreak != 0 && pShrinkWords) {
String lNewString = lLineBuffer.toString() + pString.substring(i, j);
int lFontSize;
for (lFontSize = lDrawFont.getSize(); lFontSize > 1; lFontSize--) {
Font lNewSmallerFont = new Font(lDrawFont.getName(), lDrawFont.getStyle(), lFontSize);
pG.setFont(lNewSmallerFont);
if (pG.getFontMetrics().stringWidth(lNewString) < pWidth) {
lY += pG.getFontMetrics().getHeight() + (lFirstLine?-pG.getFontMetrics().getDescent():lLeading);
if (pDraw) {
drawLine(lNewString, pG, pX, lY, pWidth, pJustification);
}
i = j+1;
pG.setFont(lDrawFont);
break;
}
}
if (i >= lCharacters.length) {
lSuppressLastLine = true;
break;
}
pG.setFont(lDrawFont);
lLineBuffer.setLength(0);
lLineBuffer.append(lCharacters[i]);
lLastSpace = null;
lCharsInBuffer = 0;
lFirstLine = false;
continue;
}
else {
lLineBuffer.setLength(lCharsInBuffer - (i - lLastSpace.intValue()) + 1);
i = lLastSpace.intValue() + 1;
}
}
else if (pShrinkWords) {
//Shrink word if It's not too big
int lNextBreak = 0;
int j;
for (j = i; j < Math.min((i + (int)(lCharsInBuffer * 0.50)), lCharacters.length); ++j) {
if (isBreakable(lCharacters[j])) {
lNextBreak = j;
break;
}
}
if (j == lCharacters.length) {
lNextBreak = lCharacters.length;
}
if (lNextBreak != 0) {
String lNewString = lLineBuffer.toString() + pString.substring(i, j);
int lFontSize;
for (lFontSize = lDrawFont.getSize(); lFontSize > 1; lFontSize--) {
Font lNewSmallerFont = new Font(lDrawFont.getName(), lDrawFont.getStyle(), lFontSize);
pG.setFont(lNewSmallerFont);
if (pG.getFontMetrics().stringWidth(lNewString) < pWidth) {
lY += pG.getFontMetrics().getHeight() + (lFirstLine?-pG.getFontMetrics().getDescent():lLeading);
if (pDraw) {
drawLine(lNewString, pG, pX, lY, pWidth, pJustification);
}
i = j+1;
pG.setFont(lDrawFont);
break;
}
}
if (i >= lCharacters.length) {
lSuppressLastLine = true;
break;
}
pG.setFont(lDrawFont);
lLineBuffer.setLength(0);
lLineBuffer.append(lCharacters[i]);
lLastSpace = null;
lCharsInBuffer = 0;
lFirstLine = false;
continue;
}
}
//Find the next Y position for the new line
lY += lFontHeight + (lFirstLine?-lFontMetrics.getDescent():lLeading);
if ((lY + lFontHeight) > pHeight && pYOverflow == false) {
//Break loop if it's hit the Y limit
break;
}
//Draw the line
if (pDraw) {
drawLine(lLineBuffer.toString(), pG, pX, lY, pWidth, pJustification);
}
//Start the new buffer
lLineBuffer.setLength(0);
lLineBuffer.append(lCharacters[i]);
lLastSpace = null;
lCharsInBuffer = 0;
lFirstLine = false;
}
}
if (!lSuppressLastLine) {
//Find the next Y position for the new line
lY = lY + lFontHeight + (lFirstLine?-lFontMetrics.getDescent():lLeading);
//Draw the line
if (pDraw) {
drawLine(lLineBuffer.toString(), pG, pX, lY, pWidth, pJustification);
}
}
//Calculate final bounding box
int lHeight = lY + lFontMetrics.getDescent() - pY;
int lWidth = pWidth;
Rectangle lR = new Rectangle(pX, pY, lWidth, lHeight);
return lR;
} // drawString
/**
* Draw a line of text with justifiction
*
* @param pLine String of text to draw
* @param pG Graphics object to draw on
* @param pX Position to start at
* @param pY Position to start at
* @param pWidth Width of the line, to know where to right align to
* @param pJustification LEFT|RIGHT|CENTRE justification
*/
public static void drawLine (String pLine, Graphics2D pG, int pX, int pY, int pWidth, String pJustification) {
FontMetrics lFontMetrics = pG.getFontMetrics();
if (pLine.trim().length() > 0) {
if ("RIGHT".equals(pJustification.toUpperCase())) {
pG.drawString(pLine.trim(), pX + pWidth - lFontMetrics.stringWidth(pLine.trim()), pY);
}
else if ("CENTRE".equals(pJustification.toUpperCase())) {
pG.drawString(pLine.trim(), pX + (pWidth/2) - (lFontMetrics.stringWidth(pLine.trim())/2), pY);
}
else {
pG.drawString(pLine.trim(), pX, pY);
}
}
} // drawLine
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment