Created
May 28, 2015 15:55
-
-
Save Palmr/36fe782eba7ee6587e87 to your computer and use it in GitHub Desktop.
Massive text draw function
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//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