Skip to content

Instantly share code, notes, and snippets.

@jbruchanov
Last active August 29, 2015 14:00
Show Gist options
  • Save jbruchanov/11376943 to your computer and use it in GitHub Desktop.
Save jbruchanov/11376943 to your computer and use it in GitHub Desktop.
TextRenderHelper
GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
g.setFont(new Font("Arial", Font.PLAIN, 24));
FontMetrics fm = g.getFontMetrics();
TextRenderHelper helper = new TextRenderHelper(fm, "Hello World\nHello World Hello World Hello World Hello World", 300, 60);
for (TextRenderHelper.LineRenderContext lrc : helper.prepareForRender(TextRenderHelper.Gravity.CENTER, TextRenderHelper.Gravity.CENTER)) {
g.drawString(lrc.text, lrc.x, lrc.y);
}
private static class TextRenderHelper{
private String mText;
public enum Gravity {
LEFT_TOP, CENTER, RIGHT_BOTTOM
}
private final FontMetrics mFontMetrics;
private int mMaxWidth;
private int mMaxHeight;
private final int mLineHeight;
public TextRenderHelper(FontMetrics metrics, String text, int maxWidth, int maxHeight) {
mFontMetrics = metrics;
mLineHeight = mFontMetrics.getHeight();//mFontMetrics.getMaxAscent() + mFontMetrics.getMaxDescent();
mText = text;
mMaxWidth = maxWidth;
mMaxHeight = maxHeight;
}
public ArrayList<LineRenderContext> prepareForRender(Gravity horizontal, Gravity vertical) {
ArrayList<LineRenderContext> list = createLineContexts(horizontal);
countVerticalPositions(list, vertical);
return list;
}
private ArrayList<LineRenderContext> createLineContexts(Gravity horizontal) {
ArrayList<LineRenderContext> result = new ArrayList<LineRenderContext>();
int width = mFontMetrics.stringWidth(mText);
if (width < mMaxWidth && !mText.contains("\n")) {
//single line
result.add(new LineRenderContext(getX(horizontal, width), mText));
} else {
char[] chars = mText.toCharArray();
String currentLine = String.valueOf(chars[0]);
width = mFontMetrics.stringWidth(currentLine);
for (int i = 1; i < chars.length; i++) {
char c = chars[i];
boolean newLine = '\n' == c;
int newWidth = mFontMetrics.stringWidth(currentLine + c);
if (!newLine && newWidth < mMaxWidth) {//continue till letter will reach max width
currentLine += c;
width = newWidth;
} else {
//add new line
result.add(new LineRenderContext(getX(horizontal, width), currentLine));
currentLine = newLine ? "" : String.valueOf(c);
width = newWidth - width;
}
}
//rest
if (currentLine.trim().length() > 0) {
result.add(new LineRenderContext(getX(horizontal, width), currentLine));
}
}
return result;
}
private void countVerticalPositions(ArrayList<LineRenderContext> contexts, Gravity vertical) {
final int len = contexts.size();
int y = 0;
switch (vertical) {
case LEFT_TOP:
y = mFontMetrics.getMaxAscent();
for (LineRenderContext context1 : contexts) {
context1.y = y;
y += mLineHeight;
}
break;
case CENTER:
y = ((mLineHeight + mMaxHeight) >> 1) - mFontMetrics.getMaxDescent();
final int offset = ((len - 1) * mLineHeight) >> 1;
for (LineRenderContext context : contexts) {
context.y = y - offset;
y += mLineHeight;
}
break;
case RIGHT_BOTTOM:
y = mMaxHeight - mFontMetrics.getMaxDescent();
for (int i = len - 1; i >= 0; i--) {
contexts.get(i).y = y;
y -= mLineHeight;
}
break;
}
}
public int getX(Gravity horizontal, int lineWidth){
int x = 0;
switch (horizontal) {
case LEFT_TOP: x = 0; break;
case CENTER: x = (mMaxWidth - lineWidth) >> 1; break;
case RIGHT_BOTTOM: x = mMaxWidth - lineWidth; break;
}
return x;
}
private static class LineRenderContext {
public int x;
public int y;
public String text;
public LineRenderContext(int x, String text) {
this(x, 0, text);
}
public LineRenderContext(int x, int y, String text) {
this.x = x;
this.y = y;
this.text = text;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment