|
@@ -33,6 +33,7 @@ package com.jme3.font;
|
|
|
|
|
|
import com.jme3.export.*;
|
|
|
import com.jme3.material.Material;
|
|
|
+
|
|
|
import java.io.IOException;
|
|
|
|
|
|
/**
|
|
@@ -88,6 +89,24 @@ public class BitmapFont implements Savable {
|
|
|
|
|
|
private BitmapCharacterSet charSet;
|
|
|
private Material[] pages;
|
|
|
+ private boolean rightToLeft = false;
|
|
|
+ // For cursive bitmap fonts in which letter shape is determined by the adjacent glyphs.
|
|
|
+ private GlyphParser glyphParser;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @return true, if this is a right-to-left font, otherwise it will return false.
|
|
|
+ */
|
|
|
+ public boolean isRightToLeft() {
|
|
|
+ return rightToLeft;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Specify if this is a right-to-left font. By default it is set to false.
|
|
|
+ * This can be "overwritten" in the BitmapText constructor.
|
|
|
+ */
|
|
|
+ public void setRightToLeft(boolean rightToLeft) {
|
|
|
+ this.rightToLeft = rightToLeft;
|
|
|
+ }
|
|
|
|
|
|
public BitmapFont() {
|
|
|
}
|
|
@@ -123,7 +142,23 @@ public class BitmapFont implements Savable {
|
|
|
public BitmapCharacterSet getCharSet() {
|
|
|
return charSet;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
+ /**
|
|
|
+ * For cursive fonts a GlyphParser needs to be specified which is used
|
|
|
+ * to determine glyph shape by the adjacent glyphs. If nothing is set,
|
|
|
+ * all glyphs will be rendered isolated.
|
|
|
+ */
|
|
|
+ public void setGlyphParser(GlyphParser glyphParser) {
|
|
|
+ this.glyphParser = glyphParser;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @return The GlyphParser set on the font, or null if it has no glyph parser.
|
|
|
+ */
|
|
|
+ public GlyphParser getGlyphParser() {
|
|
|
+ return glyphParser;
|
|
|
+ }
|
|
|
+
|
|
|
/**
|
|
|
* Gets the line height of a StringBlock.
|
|
|
*
|
|
@@ -156,6 +191,8 @@ public class BitmapFont implements Savable {
|
|
|
OutputCapsule oc = ex.getCapsule(this);
|
|
|
oc.write(charSet, "charSet", null);
|
|
|
oc.write(pages, "pages", null);
|
|
|
+ oc.write(rightToLeft, "rightToLeft", false);
|
|
|
+ oc.write(glyphParser, "glyphParser", null);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
@@ -165,6 +202,8 @@ public class BitmapFont implements Savable {
|
|
|
Savable[] pagesSavable = ic.readSavableArray("pages", null);
|
|
|
pages = new Material[pagesSavable.length];
|
|
|
System.arraycopy(pagesSavable, 0, pages, 0, pages.length);
|
|
|
+ rightToLeft = ic.readBoolean("rightToLeft", false);
|
|
|
+ glyphParser = (GlyphParser) ic.readSavable("glyphParser", null);
|
|
|
}
|
|
|
|
|
|
public float getLineWidth(CharSequence text){
|
|
@@ -208,8 +247,10 @@ public class BitmapFont implements Savable {
|
|
|
boolean firstCharOfLine = true;
|
|
|
// float sizeScale = (float) block.getSize() / charSet.getRenderedSize();
|
|
|
float sizeScale = 1f;
|
|
|
- for (int i = 0; i < text.length(); i++){
|
|
|
- char theChar = text.charAt(i);
|
|
|
+ CharSequence characters = glyphParser != null ? glyphParser.parse(text) : text;
|
|
|
+
|
|
|
+ for (int i = 0; i < characters.length(); i++){
|
|
|
+ char theChar = characters.charAt(i);
|
|
|
if (theChar == '\n'){
|
|
|
maxLineWidth = Math.max(maxLineWidth, lineWidth);
|
|
|
lineWidth = 0f;
|
|
@@ -217,38 +258,50 @@ public class BitmapFont implements Savable {
|
|
|
continue;
|
|
|
}
|
|
|
BitmapCharacter c = charSet.getCharacter(theChar);
|
|
|
- if (c != null){
|
|
|
- if (theChar == '\\' && i<text.length()-1 && text.charAt(i+1)=='#'){
|
|
|
- if (i+5<text.length() && text.charAt(i+5)=='#'){
|
|
|
- i+=5;
|
|
|
+ if (c != null) {
|
|
|
+ if (theChar == '\\' && i < characters.length() - 1 && characters.charAt(i + 1) == '#') {
|
|
|
+ if (i + 5 < characters.length() && characters.charAt(i + 5) == '#') {
|
|
|
+ i += 5;
|
|
|
continue;
|
|
|
- }else if (i+8<text.length() && text.charAt(i+8)=='#'){
|
|
|
- i+=8;
|
|
|
+ } else if (i + 8 < characters.length() && characters.charAt(i + 8) == '#') {
|
|
|
+ i += 8;
|
|
|
continue;
|
|
|
}
|
|
|
}
|
|
|
- if (!firstCharOfLine){
|
|
|
- lineWidth += findKerningAmount(lastChar, theChar) * sizeScale;
|
|
|
+ if (!firstCharOfLine) {
|
|
|
+ lineWidth += findKerningAmount(lastChar, theChar) * sizeScale;
|
|
|
} else {
|
|
|
- // The first character needs to add in its xOffset, but it
|
|
|
- // is the only one... and negative offsets = positive width
|
|
|
- // because we're trying to account for the part that hangs
|
|
|
- // over the left. So we subtract.
|
|
|
- lineWidth -= c.getXOffset() * sizeScale;
|
|
|
+ if (rightToLeft) {
|
|
|
+ // Ignore offset, so it will be compatible with BitmapText.getLineWidth().
|
|
|
+ } else {
|
|
|
+ // The first character needs to add in its xOffset but it
|
|
|
+ // is the only one... and negative offsets = positive width
|
|
|
+ // because we're trying to account for the part that hangs
|
|
|
+ // over the left. So we subtract.
|
|
|
+ lineWidth -= c.getXOffset() * sizeScale;
|
|
|
+ }
|
|
|
firstCharOfLine = false;
|
|
|
}
|
|
|
float xAdvance = c.getXAdvance() * sizeScale;
|
|
|
-
|
|
|
- // If this is the last character, then we really should have
|
|
|
- // only added its width. The advance may include extra spacing
|
|
|
+
|
|
|
+ // If this is the last character of a line, then we really should
|
|
|
+ // have only added its width. The advance may include extra spacing
|
|
|
// that we don't care about.
|
|
|
- if (i == text.length() - 1) {
|
|
|
- lineWidth += c.getWidth() * sizeScale;
|
|
|
-
|
|
|
- // Since the width includes the xOffset then we need
|
|
|
- // to take it out again by adding it, ie: offset the width
|
|
|
- // we just added by the appropriate amount.
|
|
|
- lineWidth += c.getXOffset() * sizeScale;
|
|
|
+ if (i == characters.length() - 1 || characters.charAt(i + 1) == '\n') {
|
|
|
+ if (rightToLeft) {
|
|
|
+ // In RTL text we move the letter x0 by it's xAdvance so
|
|
|
+ // we should add it to lineWidth
|
|
|
+ lineWidth += xAdvance;
|
|
|
+ // Then we move letter by it's xOffset.
|
|
|
+ // Negative offsets = positive width.
|
|
|
+ lineWidth -= c.getXOffset() * sizeScale;
|
|
|
+ } else {
|
|
|
+ lineWidth += c.getWidth() * sizeScale;
|
|
|
+ // Since the width includes the xOffset then we need
|
|
|
+ // to take it out again by adding it, ie: offset the width
|
|
|
+ // we just added by the appropriate amount.
|
|
|
+ lineWidth += c.getXOffset() * sizeScale;
|
|
|
+ }
|
|
|
} else {
|
|
|
lineWidth += xAdvance;
|
|
|
}
|