package loon.font;
import loon.LSystem;
import loon.canvas.LColor;
import loon.font.Font.Style;
import loon.geom.PointI;
import loon.geom.Vector2f;
import loon.opengl.GLEx;
import loon.opengl.LSTRDictionary;
import loon.utils.MathUtils;
import loon.utils.ObjectMap;
import loon.utils.StringUtils;
public class LFont implements IFont {
private static LFont defaultFont;
public static LFont newFont() {
return newFont(20);
}
public static LFont newFont(int size) {
return LFont.getFont(LSystem.FONT_NAME, Style.PLAIN, size);
}
/*
* 获得一个默认的LFont.
*
* 比如:
*
* 游戏全局使用默认LFont(除log字体外,log字体需要设置setSystemLogFont)
*
* LSystem.setSystemGameFont(LFont.getDefaultFont());
*
*/
public static LFont getDefaultFont() {
return getDefaultFont(20);
}
public static LFont getDefaultFont(int size) {
if (defaultFont == null || defaultFont.getSize() != size) {
defaultFont = LFont.getFont(LSystem.FONT_NAME, Style.PLAIN, size);
}
return defaultFont;
}
public static void setDefaultFont(LFont font) {
defaultFont = font;
}
private ObjectMap<String, Vector2f> fontSizes = new ObjectMap<String, Vector2f>(50);
private final static String tmp = "H";
private String lastText = tmp;
private PointI _offset = new PointI();
private TextFormat textFormat = null;
private TextLayout textLayout = null;
private int _size = -1;
private float _ascent = -1;
private boolean useCache;
public boolean isUseCache() {
return useCache;
}
public void setUseCache(boolean u) {
this.useCache = u;
}
LFont() {
this(LSystem.FONT_NAME, Style.PLAIN, 20, true);
}
LFont(String name, Style style, int size, boolean antialias) {
this.textFormat = new TextFormat(new Font(name, style, size), antialias);
}
public static LFont getFont(int size) {
return LFont.getFont(LSystem.FONT_NAME, size);
}
public static LFont getFont(String familyName, int size) {
return new LFont(familyName, Style.PLAIN, size, true);
}
public static LFont getFont(String familyName, int styleType, int size) {
Style style = Style.PLAIN;
switch (styleType) {
default:
case 0:
style = Style.PLAIN;
break;
case 1:
style = Style.BOLD;
break;
case 2:
style = Style.ITALIC;
break;
case 3:
style = Style.BOLD_ITALIC;
break;
}
return new LFont(familyName, style, size, true);
}
public static LFont getFont(String familyName, Style style, int size) {
return new LFont(familyName, style, size, true);
}
public static LFont getFont(String familyName, Style style, int size, boolean antialias) {
return new LFont(familyName, style, size, antialias);
}
public TextFormat getFormat() {
return textFormat;
}
public TextLayout getTextLayout() {
return textLayout;
}
@Override
public void drawString(GLEx g, String chars, float tx, float ty) {
drawString(g, chars, tx, ty, LColor.white);
}
@Override
public void drawString(GLEx g, String chars, float tx, float ty, LColor c) {
if (c == null || c.a <= 0.01) {
return;
}
if (StringUtils.isEmpty(chars)) {
return;
}
if (useCache) {
LSTRDictionary.get().drawString(this, chars, _offset.x + tx, _offset.y + ty, 0, c);
} else {
LSTRDictionary.get().drawString(g, this, chars, _offset.x + tx, _offset.y + ty, 0, c);
}
}
@Override
public void drawString(GLEx g, String chars, float tx, float ty, float angle, LColor c) {
if (c == null || c.a <= 0.01) {
return;
}
if (StringUtils.isEmpty(chars)) {
return;
}
if (useCache) {
LSTRDictionary.get().drawString(this, chars, _offset.x + tx, _offset.y + ty, angle, c);
} else {
LSTRDictionary.get().drawString(g, this, chars, _offset.x + tx, _offset.y + ty, angle, c);
}
}
@Override
public void drawString(GLEx g, String chars, float tx, float ty, float sx, float sy, float ax, float ay,
float angle, LColor c) {
if (c == null || c.a <= 0.01) {
return;
}
if (StringUtils.isEmpty(chars)) {
return;
}
if (useCache) {
LSTRDictionary.get().drawString(this, chars, _offset.x + tx, _offset.y + ty, sx, sy, ax, ay, angle, c);
} else {
LSTRDictionary.get().drawString(g, this, chars, _offset.x + tx, _offset.y + ty, sx, sy, ax, ay, angle, c);
}
}
private void initLayout(String text) {
if (text == null || textLayout == null || !text.equals(lastText)) {
textLayout = LSystem.base().graphics().layoutText(tmp, this.textFormat);
}
}
public int charWidth(char ch) {
if (LSystem.base() == null) {
return 0;
}
initLayout(String.valueOf(ch));
return textLayout.bounds.width;
}
public int stringWidth(String message) {
if (LSystem.base() == null || StringUtils.isEmpty(message)) {
return 0;
}
initLayout(message);
if (message.indexOf('\n') == -1) {
return textLayout.stringWidth(message);
} else {
StringBuffer sbr = new StringBuffer();
int width = 0;
for (int i = 0, size = message.length(); i < size; i++) {
char ch = message.charAt(i);
if (ch == '\n') {
width = MathUtils.max(textLayout.stringWidth(sbr.toString()), width);
sbr.delete(0, sbr.length());
} else {
sbr.append(ch);
}
}
return width;
}
}
public int charHeight(char ch) {
if (LSystem.base() == null) {
return 0;
}
initLayout(String.valueOf(ch));
return getHeight();
}
public int stringHeight(String message) {
if (LSystem.base() == null || StringUtils.isEmpty(message)) {
return 0;
}
initLayout(message);
if (message.indexOf('\n') == -1) {
return getHeight();
} else {
String[] list = StringUtils.split(message, '\n');
return list.length * getHeight();
}
}
public boolean isBold() {
return textFormat.font.style == Style.BOLD;
}
public boolean isItalic() {
return textFormat.font.style == Style.ITALIC;
}
public boolean isPlain() {
return textFormat.font.style == Style.PLAIN;
}
public int getSize() {
return this._size == -1 ? (int) textFormat.font.size : this._size;
}
public int getStyle() {
return textFormat.font.style.ordinal();
}
public String getFontName() {
return textFormat.font.name;
}
@Override
public int getHeight() {
initLayout(tmp);
return MathUtils.max(getSize(), textLayout.bounds.height);
}
@Override
public float getAscent() {
initLayout(tmp);
return this._ascent == -1 ? textLayout.ascent() : this._ascent;
}
public float getDescent() {
initLayout(tmp);
return textLayout.descent();
}
public float getLeading() {
initLayout(tmp);
return textLayout.leading();
}
private int hash = 1;
@Override
public int hashCode() {
if (hash == 1) {
hash = LSystem.unite(textFormat.font.name.charAt(0), hash);
hash = LSystem.unite(textFormat.font.name.length(), hash);
hash = LSystem.unite(textFormat.font.name.hashCode(), hash);
hash = LSystem.unite(textFormat.font.style.ordinal(), hash);
hash = LSystem.unite((int) textFormat.font.size, hash);
}
return hash;
}
@Override
public boolean equals(Object o) {
if (o == null) {
return false;
}
if (!(o instanceof LFont)) {
return false;
}
LFont font = (LFont) o;
if (this == font) {
return true;
}
if (hashCode() == font.hashCode()) {
return true;
}
if (font.textFormat == textFormat) {
return true;
}
if (font.textFormat.font.name.equals(textFormat.font.name) && font.textFormat.font.size == textFormat.font.size
&& font.textFormat.font.style.equals(textFormat.font.style)) {
return true;
}
return false;
}
public Vector2f getOrigin(String text) {
Vector2f result = fontSizes.get(text);
if (result == null) {
result = new Vector2f(stringWidth(text) / 2f, getHeight() / 2f);
fontSizes.put(text, result);
}
return result;
}
public TextLayout getLayoutText(String text) {
return LSystem.base().graphics().layoutText(text, this.textFormat);
}
@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;
}
@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._ascent = assent;
}
@Override
public void setSize(int size) {
this._size = size;
}
@Override
public String toString() {
return textFormat.toString();
}
@Override
public void close() {
}
}