Fixes tab stops in BitmapText / BitmapFont.

The first explicitely set tab stop was always skipped.
For all non-explicitely set tab stops it inserted a fixed spacing.
This commit changes the behaviour so tabs are aligned to columns.
It also adds handling of tabs to BitmapFont.getLineWidth() which ignored tabs before.
This commit is contained in:
Fennel 2016-12-06 01:12:19 +01:00
parent 92b5d40003
commit e60d67b1bb
4 changed files with 42 additions and 29 deletions

View File

@ -86,6 +86,8 @@ public class BitmapFont implements Savable {
Bottom Bottom
} }
static final float DEFAULT_TAB_WIDTH = 50.0f;
private BitmapCharacterSet charSet; private BitmapCharacterSet charSet;
private Material[] pages; private Material[] pages;
@ -215,6 +217,11 @@ public class BitmapFont implements Savable {
firstCharOfLine = true; firstCharOfLine = true;
continue; continue;
} }
if(theChar == '\t') {
lineWidth = (float)Math.floor(lineWidth / DEFAULT_TAB_WIDTH) * DEFAULT_TAB_WIDTH;
lineWidth += DEFAULT_TAB_WIDTH;
}
BitmapCharacter c = charSet.getCharacter((int) theChar); BitmapCharacter c = charSet.getCharacter((int) theChar);
if (c != null){ if (c != null){
if (theChar == '\\' && i<text.length()-1 && text.charAt(i+1)=='#'){ if (theChar == '\\' && i<text.length()-1 && text.charAt(i+1)=='#'){

View File

@ -369,7 +369,9 @@ public class BitmapText extends Node {
} }
/** /**
* @param tabs tab positions * Sets the positions at where the text continues after a tab character.<br>
* These tab stops need to be sorted from smallest to biggest value.
* @param tabs Sorted tab positions. Use <code>null</code> to reset tab positions.
*/ */
public void setTabPosition(float... tabs) { public void setTabPosition(float... tabs) {
block.setTabPosition(tabs); block.setTabPosition(tabs);
@ -378,7 +380,9 @@ public class BitmapText extends Node {
} }
/** /**
* used for the tabs over the last tab position. * Used for all tabs after the last custom tab position
* (see {@link #setTabPosition(float...) setTabPosition}).<br>
* This value is also used when no custom tab positions are set.
* @param width tab size * @param width tab size
*/ */
public void setTabWidth(float width) { public void setTabWidth(float width) {

View File

@ -306,8 +306,6 @@ class LetterQuad {
} }
void update(StringBlock block) { void update(StringBlock block) {
final float[] tabs = block.getTabPosition();
final float tabWidth = block.getTabWidth();
final Rectangle bound = getBound(block); final Rectangle bound = getBound(block);
sizeScale = block.getSize() / font.getCharSet().getRenderedSize(); sizeScale = block.getSize() / font.getCharSet().getRenderedSize();
lineY = computeLineY(block); lineY = computeLineY(block);
@ -320,16 +318,9 @@ class LetterQuad {
xAdvance = 0; xAdvance = 0;
} else if (isTab()) { } else if (isTab()) {
x0 = previous.getNextX(); x0 = previous.getNextX();
width = tabWidth; width = block.calcNextTabPosition(x0) - x0;
y0 = lineY; y0 = lineY;
height = 0; height = 0;
if (tabs != null && x0 < tabs[tabs.length-1]) {
for (int i = 0; i < tabs.length-1; i++) {
if (x0 > tabs[i] && x0 < tabs[i+1]) {
width = tabs[i+1] - x0;
}
}
}
xAdvance = width; xAdvance = width;
} else if (bitmapChar == null) { } else if (bitmapChar == null) {
x0 = getPrevious().getX1(); x0 = getPrevious().getX1();

View File

@ -53,7 +53,7 @@ class StringBlock implements Cloneable {
private int lineCount; private int lineCount;
private LineWrapMode wrapType = LineWrapMode.Word; private LineWrapMode wrapType = LineWrapMode.Word;
private float[] tabPos; private float[] tabPos;
private float tabWidth = 50; private float tabWidth = BitmapFont.DEFAULT_TAB_WIDTH;
private char ellipsisChar = 0x2026; private char ellipsisChar = 0x2026;
/** /**
@ -91,6 +91,7 @@ class StringBlock implements Cloneable {
clone.color = color.clone(); clone.color = color.clone();
if (textBox != null) if (textBox != null)
clone.textBox = textBox.clone(); clone.textBox = textBox.clone();
// tabPos is read-only and replaced on write.
return clone; return clone;
} catch (CloneNotSupportedException ex) { } catch (CloneNotSupportedException ex) {
throw new AssertionError(); throw new AssertionError();
@ -173,22 +174,6 @@ class StringBlock implements Cloneable {
this.wrapType = wrap; this.wrapType = wrap;
} }
void setTabWidth(float tabWidth) {
this.tabWidth = tabWidth;
}
void setTabPosition(float[] tabs) {
this.tabPos = tabs;
}
float getTabWidth() {
return tabWidth;
}
float[] getTabPosition() {
return tabPos;
}
void setEllipsisChar(char c) { void setEllipsisChar(char c) {
this.ellipsisChar = c; this.ellipsisChar = c;
} }
@ -196,4 +181,30 @@ class StringBlock implements Cloneable {
int getEllipsisChar() { int getEllipsisChar() {
return ellipsisChar; return ellipsisChar;
} }
void setTabWidth(float tabWidth) {
this.tabWidth = tabWidth;
}
void setTabPosition(float[] tabs) {
if(tabs != null && tabs.length > 0) {
this.tabPos = tabs.clone();
} else {
this.tabPos = null;
}
}
float calcNextTabPosition(float posX) {
// If there is an upcoming user-set tab stop, use that one.
if (tabPos != null && posX < tabPos[tabPos.length-1]) {
for (int i = 0; i < tabPos.length; i++) {
if (posX < tabPos[i]) {
return tabPos[i];
}
}
}
// No upcoming tab stops available, use default tab width.
return (float)Math.floor(posX / tabWidth) * tabWidth + tabWidth;
}
} }