package loon.font;
import loon.HorizontalAlign;
import loon.LRelease;
import loon.LSystem;
import loon.canvas.LColor;
import loon.opengl.GLEx;
import loon.opengl.LSTRDictionary;
import loon.opengl.LSTRFont;
import loon.utils.FloatArray;
import loon.utils.MathUtils;
import loon.utils.StringUtils;
import loon.utils.TArray;
/**
* 一个统一的文字显示用类,用以统一文字的基础显示效果
*/
public class Text implements LRelease {
private boolean _initNativeDraw;
protected IFont _font;
protected float _space = 0;
protected float _lineWidthMaximum;
protected float _lineAlignmentWidth;
protected TextOptions _textOptions;
protected int _charactersToDraw;
protected int _vertexCountToDraw;
protected CharSequence _chars;
protected TArray<CharSequence> _lines = new TArray<CharSequence>(1);
protected FloatArray _lineWidths = new FloatArray(1);
protected float _width = 0, _height = 0;
public Text(final IFont font, final CharSequence chars) {
this(font, chars, new TextOptions());
}
public Text(final IFont font, final CharSequence chars,
final TextOptions opt) {
this._font = font;
this._textOptions = opt;
this.setText(chars);
}
public float getWidth() {
return this._width;
}
public float getHeight() {
return this._height;
}
public IFont getFont() {
return this._font;
}
public CharSequence getText() {
return this._chars;
}
public void setFont(final IFont font) {
this.setText(font, this._chars);
}
public void setText(final IFont font, final CharSequence chars) {
this._font = font;
this.setText(chars);
}
public void setText(final CharSequence chars) {
this._chars = chars != null ? chars : "";
final IFont font = this._font;
this._lines.clear();
this._lineWidths.clear();
if (this._textOptions._autoWrap == AutoWrap.NONE) {
this._lines = FontUtils.splitLines(this._chars, this._lines);
} else {
this._lines = FontUtils.splitLines(this._font, this._chars,
this._lines, this._textOptions._autoWrap,
this._textOptions._autoWrapWidth);
}
final int lineCount = this._lines.size;
float maxLineWidth = 0;
for (int i = 0; i < lineCount; i++) {
final float lineWidth = FontUtils.measureText(font,
this._lines.get(i));
maxLineWidth = MathUtils.max(maxLineWidth, lineWidth);
this._lineWidths.add(lineWidth);
}
this._lineWidthMaximum = maxLineWidth;
if (this._textOptions._autoWrap == AutoWrap.NONE) {
this._lineAlignmentWidth = this._lineWidthMaximum;
} else {
this._lineAlignmentWidth = this._textOptions._autoWrapWidth;
}
this._width = this._lineAlignmentWidth;
if (_width <= 0) {
_width = _lineWidths.get(0)
* StringUtils.countOccurrences(chars, '\n');
}
this._height = lineCount * font.getHeight() + (lineCount - 1)
* this._textOptions._leading;
if (_height <= 0) {
_height = _font.getHeight();
}
this._initNativeDraw = false;
}
public void paintString(GLEx g, float offsetX, float offsetY, LColor color) {
if (!_initNativeDraw) {
if (_font instanceof LFont) {
LSTRDictionary.get().bind((LFont) _font, _lines);
}
if (LSystem.isDesktop()) {
if (_font instanceof LFont) {
LSTRFont strfont = LSTRDictionary.get().STRFont(
(LFont) _font);
if (strfont != null) {
if (_textOptions._autoWrap != AutoWrap.VERTICAL) {
strfont.setUpdateX(0);
} else {
strfont.setUpdateX(1);
}
}
}
}
_initNativeDraw = true;
}
if (_textOptions._autoWrap != AutoWrap.VERTICAL && _lines.size == 1) {
CharSequence c = _lines.get(0);
String mes = null;
if (c instanceof String) {
mes = (String) c;
} else if (c instanceof StringBuffer) {
mes = ((StringBuffer) c).toString();
} else if (c instanceof StringBuilder) {
mes = ((StringBuilder) c).toString();
} else {
mes = new StringBuffer(c).toString();
}
switch (_textOptions._horizontalAlign) {
case CENTER:
_font.drawString(
g,
mes,
(getWidth() / 2 - _font.stringWidth(mes) / 2) + offsetX,
offsetY, color);
break;
case LEFT:
_font.drawString(g, mes, offsetX, offsetY, color);
break;
case RIGHT:
_font.drawString(g, mes, getWidth() - _font.stringWidth(mes)
+ offsetX, offsetY, color);
break;
default:
break;
}
} else if (_textOptions._autoWrap == AutoWrap.VERTICAL) {
float viewX = 0;
int idx = 0;
for (int i = 0, size = _lines.size; i < size; i++) {
CharSequence c = _lines.get(i);
String mes = null;
if (c instanceof String) {
mes = (String) c;
} else if (c instanceof StringBuffer) {
mes = ((StringBuffer) c).toString();
} else if (c instanceof StringBuilder) {
mes = ((StringBuilder) c).toString();
} else {
mes = new StringBuffer(c).toString();
}
if (_textOptions._autoWrap == AutoWrap.VERTICAL) {
char ch = mes.charAt(0);
float viewY = 0;
if (ch != '\n') {
viewY = offsetY
+ idx
* (_font.stringHeight(mes) + _textOptions
.getLeading());
idx++;
} else {
viewX += _font.getSize() + getLeading();
viewY = 0;
idx = 0;
}
switch (_textOptions._horizontalAlign) {
case CENTER:
_font.drawString(
g,
mes,
viewX
+ offsetX
+ (getWidth() / 2 - _font
.stringWidth(mes) / 2), viewY,
color);
break;
case LEFT:
_font.drawString(g, mes, viewX + offsetX, viewY, color);
break;
case RIGHT:
_font.drawString(g, mes, viewX + offsetX + getWidth()
- _font.stringWidth(mes), viewY, color);
break;
default:
break;
}
} else {
switch (_textOptions._horizontalAlign) {
case CENTER:
_font.drawString(
g,
mes,
offsetX
+ (getWidth() / 2 - _font
.stringWidth(mes) / 2),
offsetY
+ i
* (_font.stringHeight(mes) + _textOptions
.getLeading()), color);
break;
case LEFT:
_font.drawString(
g,
mes,
offsetX,
offsetY
+ i
* (_font.stringHeight(mes) + _textOptions
.getLeading()), color);
break;
case RIGHT:
_font.drawString(
g,
mes,
offsetX + getWidth() - _font.stringWidth(mes),
offsetY
+ i
* (_font.stringHeight(mes) + _textOptions
.getLeading()), color);
break;
default:
break;
}
}
}
} else {
for (int i = 0, size = _lines.size; i < size; i++) {
CharSequence c = _lines.get(i);
String mes = null;
if (c instanceof String) {
mes = (String) c;
} else if (c instanceof StringBuffer) {
mes = ((StringBuffer) c).toString();
} else if (c instanceof StringBuilder) {
mes = ((StringBuilder) c).toString();
} else {
mes = new StringBuffer(c).toString();
}
switch (_textOptions._horizontalAlign) {
case CENTER:
_font.drawString(
g,
mes,
offsetX
+ (getWidth() / 2 - _font.stringWidth(mes) / 2),
offsetY
+ i
* (_font.stringHeight(mes) + _textOptions
.getLeading()), color);
break;
case LEFT:
_font.drawString(
g,
mes,
offsetX,
offsetY
+ i
* (_font.stringHeight(mes) + _textOptions
.getLeading()), color);
break;
case RIGHT:
_font.drawString(
g,
mes,
offsetX + getWidth() - _font.stringWidth(mes),
offsetY
+ i
* (_font.stringHeight(mes) + _textOptions
.getLeading()), color);
break;
default:
break;
}
}
}
}
public TArray<CharSequence> getLines() {
return this._lines;
}
public FloatArray getLineWidths() {
return this._lineWidths;
}
public float getLineAlignmentWidth() {
return this._lineAlignmentWidth;
}
public float getLineWidthMaximum() {
return this._lineWidthMaximum;
}
public float getSpace() {
return getLeading();
}
public float getLeading() {
return this._textOptions._leading;
}
public void setLeading(final float leading) {
this._textOptions._leading = leading;
this.initText();
}
public void setSpace(final float space) {
setLeading(space);
}
public HorizontalAlign getHorizontalAlign() {
return this._textOptions._horizontalAlign;
}
public void setHorizontalAlign(final HorizontalAlign horizontalAlign) {
this._textOptions._horizontalAlign = horizontalAlign;
this.initText();
}
public AutoWrap getAutoWrap() {
return this._textOptions._autoWrap;
}
public void setAutoWrap(final AutoWrap autoWrap) {
this._textOptions._autoWrap = autoWrap;
this.initText();
}
public void initText() {
this.setText(this._chars);
}
public float getAutoWrapWidth() {
return this._textOptions._autoWrapWidth;
}
public void setAutoWrapWidth(final float autoWrapWidth) {
this._textOptions._autoWrapWidth = autoWrapWidth;
this.initText();
}
public TextOptions getTextOptions() {
return this._textOptions;
}
public void setTextOptions(final TextOptions opt) {
this._textOptions = opt;
}
@Override
public String toString() {
return new StringBuffer(_chars).toString();
}
public void close() {
if (LSystem.isDesktop()) {
if (_font instanceof LFont) {
LSTRFont font = LSTRDictionary.get().STRFont((LFont) _font);
if (font != null) {
font.setUpdateX(0);
}
}
}
_chars = null;
_lines = null;
_lineWidths = null;
}
}