package loon.action.sprite;
import loon.canvas.LColor;
import loon.font.IFont;
import loon.geom.Affine2f;
import loon.geom.PointI;
import loon.opengl.GLEx;
import loon.utils.StringUtils;
/**
* 单纯图片字体显示用类(而非标准的bmfont)
*/
public class SpriteSheetFont implements IFont {
private SpriteSheet _font;
private int _size = -1;
private float _assent = -1;
private char startingCharacter;
private int charWidth;
private int charHeight;
private int horizontalCount;
private int verticalCount;
private int numChars;
private float fontScaleX = 1f, fontScaleY = 1f;
private PointI _offset = new PointI();
public SpriteSheetFont(String fileName, int tileWidth, int tileHeight) {
this(new SpriteSheet(fileName, tileWidth, tileHeight), ' ');
}
public SpriteSheetFont(String fileName, int tileWidth, int tileHeight, char startingCharacter) {
this(new SpriteSheet(fileName, tileWidth, tileHeight), startingCharacter);
}
public SpriteSheetFont(SpriteSheet font, char startingCharacter) {
this._font = font;
this.startingCharacter = startingCharacter;
this.horizontalCount = font.getHorizontalCount();
this.verticalCount = font.getVerticalCount();
this.charWidth = font.getTileWidth();
this.charHeight = font.getTileHeight();
this.numChars = horizontalCount * verticalCount;
}
public void drawString(String text, float x, float y) {
drawString(text, x, y, LColor.white);
}
public void drawString(String text, float x, float y, LColor col) {
drawString(text, x, y, col, 0, text.length() - 1);
}
public void drawString(String text, float x, float y, LColor col, int startIndex, int endIndex) {
if (StringUtils.isEmpty(text)) {
return;
}
if (StringUtils.isEmpty(text)) {
return;
}
int lines = 0;
float sx = x + _offset.x;
float sy = y + _offset.y;
float widthSize = charWidth * fontScaleX;
float heightSize = charHeight * fontScaleY;
for (int i = 0, size = text.length(); i < size; i++) {
char flag = text.charAt(i);
int index = flag - startingCharacter;
if (index < numChars) {
int xPos = (index % horizontalCount);
int yPos = (index / horizontalCount);
if ('\n' == flag) {
lines += heightSize + 0.5f;
sx = x;
continue;
} else {
sx += widthSize + 0.5f;
}
if ((i >= startIndex) || (i <= endIndex)) {
if (_font.contains(xPos, yPos)) {
if (fontScaleX == 1f && fontScaleY == 1f) {
_font.getSubImage(xPos, yPos).draw(sx, sy + lines, col);
} else {
_font.getSubImage(xPos, yPos).draw(sx, sy + lines, widthSize, heightSize, col);
}
}
}
}
}
}
@Override
public void drawString(GLEx gl, String text, float x, float y) {
drawString(gl, text, x, y, LColor.white);
}
@Override
public void drawString(GLEx gl, String text, float x, float y, LColor col) {
drawString(gl, text, x, y, col, 0, text.length() - 1);
}
public void drawString(GLEx gl, String text, final float x, final float y, LColor col, int startIndex,
int endIndex) {
if (StringUtils.isEmpty(text)) {
return;
}
int lines = 0;
float sx = x + _offset.x;
float sy = y + _offset.y;
float widthSize = charWidth * fontScaleX;
float heightSize = charHeight * fontScaleY;
for (int i = 0, size = text.length(); i < size; i++) {
char flag = text.charAt(i);
int index = flag - startingCharacter;
if (index < numChars) {
int xPos = (index % horizontalCount);
int yPos = (index / horizontalCount);
if ('\n' == flag) {
lines += heightSize + 0.5f;
sx = x;
continue;
} else {
sx += widthSize + 0.5f;
}
if ((i >= startIndex) || (i <= endIndex)) {
if (_font.contains(xPos, yPos)) {
if (fontScaleX == 1f && fontScaleY == 1f) {
gl.draw(_font.getSubImage(xPos, yPos), sx, sy + lines, col);
} else {
gl.draw(_font.getSubImage(xPos, yPos), sx, sy + lines, widthSize, heightSize, col);
}
}
}
}
}
}
@Override
public void drawString(GLEx g, String text, float x, float y, float rotation, LColor c) {
if (StringUtils.isEmpty(text)) {
return;
}
if (rotation == 0) {
drawString(g, text, x, y, c);
return;
}
try {
g.saveTx();
float centerX = x + stringWidth(text) / 2;
float centerY = y + stringHeight(text) / 2;
g.rotate(centerX, centerY, rotation);
drawString(g, text, x, y, c);
} finally {
g.restoreTx();
}
}
@Override
public void drawString(GLEx gl, String text, float x, float y, float sx, float sy, float ax, float ay,
float rotation, LColor c) {
if (StringUtils.isEmpty(text)) {
return;
}
final boolean anchor = ax != 0 || ay != 0;
final boolean scale = sx != 1f || sy != 1f;
final boolean angle = rotation != 0;
final boolean update = scale || angle || anchor;
try {
if (update) {
gl.saveTx();
Affine2f xf = gl.tx();
if (angle) {
float centerX = x + this.stringWidth(text) / 2;
float centerY = y + this.stringHeight(text) / 2;
xf.translate(centerX, centerY);
xf.preRotate(rotation);
xf.translate(-centerX, -centerY);
}
if (scale) {
float centerX = x + this.stringWidth(text) / 2;
float centerY = y + this.stringHeight(text) / 2;
xf.translate(centerX, centerY);
xf.preScale(sx, sy);
xf.translate(-centerX, -centerY);
}
if (anchor) {
xf.translate(ax, ay);
}
}
drawString(gl, text, x, y, c);
} finally {
if (update) {
gl.restoreTx();
}
}
}
public float getFontScaleX() {
return this.fontScaleX;
}
public float getFontScaleY() {
return this.fontScaleX;
}
public void setFontScale(float s) {
this.setFontScale(s, s);
}
public void setFontScale(float sx, float sy) {
this.fontScaleX = sx;
this.fontScaleY = sy;
}
public void setFontScaleX(float x) {
this.fontScaleX = x;
}
public void setFontScaleY(float y) {
this.fontScaleY = y;
}
@Override
public int stringHeight(String text) {
int count = StringUtils.charCount(text, '\n') + 1;
return (int) (charHeight * fontScaleY * count);
}
@Override
public int stringWidth(String text) {
return (int) (charWidth * fontScaleX * text.length());
}
@Override
public int getHeight() {
return (int) (charHeight * fontScaleY);
}
@Override
public float getAscent() {
return _assent == -1 ? (charWidth + charHeight / 2) * this.fontScaleY : _assent;
}
@Override
public String confineLength(String s, int width) {
int length = 0;
for (int i = 0; i < s.length(); i++) {
length += stringWidth(String.valueOf(s.charAt(i)));
if (length >= width) {
int pLength = stringWidth("...");
while (length + pLength >= width && i >= 0) {
length -= stringWidth(String.valueOf(s.charAt(i)));
i--;
}
s = s.substring(0, ++i) + "...";
break;
}
}
return s;
}
public int getHorizontalCount() {
return horizontalCount;
}
public int getVerticalCount() {
return verticalCount;
}
@Override
public int getSize() {
return _size == -1 ? (int) ((charWidth + charHeight / 2) * this.fontScaleY) : _size;
}
@Override
public PointI getOffset() {
return _offset;
}
@Override
public void setOffset(PointI val) {
_offset.set(val);
}
@Override
public void setOffsetX(int x) {
_offset.x = x;
}
@Override
public void setOffsetY(int y) {
_offset.y = y;
}
@Override
public void setAssent(float assent) {
this._assent = assent;
}
@Override
public void setSize(int size) {
this._size = size;
}
@Override
public int charWidth(char c) {
return charWidth;
}
@Override
public void close() {
if (_font != null) {
_font.close();
}
}
}