Hallo,
ich bin auf der Suche nach einem Algorithmus der mir einen Text automatisch mit
Zeilenumbrüchen formatiert. Wichtig ist dabei das man verschiedene Sachen
"einstellen" kann:
- maximale Anzahl der Pixel pro Zeile (eine Zeile darf z.B. nur max. 500 pixel breit sein, danach automatischer Zeilenumbruch)
- Bestimmung eines oder mehrerer Trennern (z.B. leerzeichen, komma, punkt etc.)
- maximale Anzahl der Zeilen -> evt. verkleinerung der font-size & wenn text immer noch zu lang dann kürzen und mit "..." abschließen
Wenn ihr Algorithmen kennt die davon Teilbereiche lösen, würde mir das auch schon helfen.
Ich habe mich auch selber mal daran versucht, bin aber nicht 100% mit dem Ergebnis zufrieden. Wenn ihr dort Verbesserungen seht, könnt ihr mir die gerne mitteilen
.
ich bin auf der Suche nach einem Algorithmus der mir einen Text automatisch mit
Zeilenumbrüchen formatiert. Wichtig ist dabei das man verschiedene Sachen
"einstellen" kann:
- maximale Anzahl der Pixel pro Zeile (eine Zeile darf z.B. nur max. 500 pixel breit sein, danach automatischer Zeilenumbruch)
- Bestimmung eines oder mehrerer Trennern (z.B. leerzeichen, komma, punkt etc.)
- maximale Anzahl der Zeilen -> evt. verkleinerung der font-size & wenn text immer noch zu lang dann kürzen und mit "..." abschließen
Wenn ihr Algorithmen kennt die davon Teilbereiche lösen, würde mir das auch schon helfen.
Ich habe mich auch selber mal daran versucht, bin aber nicht 100% mit dem Ergebnis zufrieden. Wenn ihr dort Verbesserungen seht, könnt ihr mir die gerne mitteilen
Code:
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.font.TextAttribute;
import java.text.AttributedString;
import sun.font.FontDesignMetrics;
public class MultiLineTextDrawer {
public final static int AL_LEFT = 0;
public final static int AL_CENTER = 1;
public final static int AL_RIGHT = 2;
private Graphics2D graphics;
private int startX = 0;
private int startY = 0;
private int maxLineWidth = 800;
private int maxSubLines = 50;
private int startFontSize = 12;
private int minFontSize = 8;
private int inset = 4;
int alignment = AL_LEFT;
public MultiLineTextDrawer(Graphics2D graphics) {
this.graphics = graphics;
}
public void drawText(String text) {
if(graphics == null)
return;
int aktFontSize = startFontSize;
int aktSubLine = 0;
String[] subLines = new String[1];
subLines[0] = text;
Font font = new Font("Arial", Font.PLAIN, aktFontSize);
// Erstellung von mehrzeiligem Text
int textWidth = FontDesignMetrics.getMetrics(font).stringWidth(text);
if( textWidth > maxLineWidth ) {
int subLinesNeeded = Math.round((((float)textWidth / (float)maxLineWidth) + 0.5f));
if(subLinesNeeded > maxSubLines)
subLinesNeeded = maxSubLines;
// Teile den text in möglichst 'subLinesNeeded' Teile
String[] subStrings = text.split(" ");
// Berechne die Einzelnen Gewichte für jeden subString
float[] subStringWeights = new float[subStrings.length];
for(int i = 0; i < subStrings.length; i++) {
if(i != subStrings.length - 1)
subStrings[i] += " ";
subStringWeights[i] = ((float)subStrings[i].length() / (float)text.length());
}
// Können nur soviele Zeilen existieren wie auch Leerzeichen
if(subStrings.length < subLinesNeeded)
subLinesNeeded = subStrings.length;
// subLines mit "" inialisieren (sonst wird "null" an String gehängt)
subLines = new String[subLinesNeeded];
for( int i = 0; i < subLines.length; i++) {
subLines[i] = "";
}
// subLines werden über die Gewichte mit den subStrings gefüllt
float aktWeight = 0.0f;
for(int i = 0; i < subStrings.length; i++) {
subLines[aktSubLine] += subStrings[i];
aktWeight += subStringWeights[i];
if( i == subStrings.length - 1 )
break;
if( (aktWeight + subStringWeights[i+1]) > (1.0f / subLinesNeeded) ) {
if( aktSubLine < subLines.length - 1 ) {
aktWeight = 0.0f;
aktSubLine++;
}
}
}
}
// Bei immer noch zu große Zeilen muss die Font Größe editiert werden
boolean correctSize = false;
while(!correctSize) {
correctSize = true;
for( int i = 0; i < subLines.length; i++ ) {
font = font.deriveFont((float)aktFontSize);
int subLineWidth = FontDesignMetrics.getMetrics(font).stringWidth(subLines[i]);
if( subLineWidth > maxLineWidth ) {
aktFontSize +=- 1;
correctSize = false;
break;
}
}
}
// Zeichne Strings
graphics.setColor(Color.BLACK);
for( int subCol = 0; subCol < subLines.length; subCol++) {
// hack: sollte schon vorher bereinigt werden -> keine 0 length Strings
if(subLines[subCol].length() == 0)
continue;
AttributedString drawString = new AttributedString(subLines[subCol]);
drawString.addAttribute(TextAttribute.FONT, font);
int y = startY - ((subLines.length - (subCol + 1)) * (aktFontSize + inset));
int x = startX;
textWidth = FontDesignMetrics.getMetrics(font).stringWidth(subLines[subCol]);
int descent = FontDesignMetrics.getMetrics(font).getDescent();
if( alignment == AL_CENTER )
x = ((startX + maxLineWidth) / 2) - (textWidth / 2);
if( alignment == AL_RIGHT )
x = maxLineWidth - textWidth;
graphics.setClip(x, y - aktFontSize, textWidth, (aktFontSize + descent));
graphics.drawString(drawString.getIterator(), x, y);
}
}
public int getInset() {
return inset;
}
public void setInset(int inset) {
this.inset = inset;
}
public int getMaxLineWidth() {
return maxLineWidth;
}
public void setMaxLineWidth(int maxLineWidth) {
this.maxLineWidth = maxLineWidth;
}
public int getMaxSubLines() {
return maxSubLines;
}
public void setMaxSubLines(int maxSubLines) {
this.maxSubLines = maxSubLines;
}
public int getStartFontSize() {
return startFontSize;
}
public void setStartFontSize(int startFontSize) {
this.startFontSize = startFontSize;
}
public int getStartX() {
return startX;
}
public void setStartX(int startX) {
this.startX = startX;
}
public int getStartY() {
return startY;
}
public void setStartY(int startY) {
this.startY = startY;
}
public Graphics2D getGraphics() {
return graphics;
}
public void setGraphics(Graphics2D graphics) {
this.graphics = graphics;
}
public int getAlignment() {
return alignment;
}
public void setAlignment(int alignment) {
this.alignment = alignment;
}
}