package com.gebauz.Bauzoid.graphics;
import java.util.Vector;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.Texture;
import com.gebauz.Bauzoid.app.Consts;
import com.gebauz.Bauzoid.file.FileUtil;
import com.gebauz.Bauzoid.graphics.sprite.AtlasSprite;
import com.gebauz.Bauzoid.graphics.sprite.SpriteRegion;
import com.gebauz.Bauzoid.parser.ScanException;
import com.gebauz.Bauzoid.parser.Tokenizer;
public class FontUtil
{
public static final String LOG_TAG = Consts.
LOG_TAG +
":FontUtil";
public static boolean verbose =
true;
private static class CharacterRect
{
public float x
;
public float y
;
public float w
;
public float h
;
public CharacterRect
(float _x,
float _y,
float _w,
float _h
)
{
x = _x
;
y = _y
;
w = _w
;
h = _h
;
}
}
private static class CharacterOffset
{
public float x
;
public float y
;
public CharacterOffset
(float _x,
float _y
)
{
x = _x
;
y = _y
;
}
}
private FontUtil
() {}
public static void log
(String tag,
String msg
)
{
if (verbose
)
Gdx.
app.
log(tag, msg
);
}
public static Font createFontFromFile
(Graphics graphics, FileHandle file
)
{
String fileContents = file.
readString();
Vector<Character> charList =
null;
Vector<Float> widthList =
null;
Vector<CharacterRect
> rectList =
null;
Vector<CharacterOffset
> offsetList =
null;
Font font =
new Font(graphics
);
Texture texture =
null;
try
{
Tokenizer tokenizer =
new Tokenizer
(fileContents
);
tokenizer.
setStringDelimiter(new char[] {'\'',
'"'} );
while (!tokenizer.
checkNoMoreTokens())
{
String identifier = tokenizer.
readIdentifier();
if (identifier.
equalsIgnoreCase("Define"))
{
// Define
String define = tokenizer.
readIdentifier();
if (define.
equalsIgnoreCase("CharList"))
{
charList = parseCharList
(tokenizer
);
}
else if (define.
equalsIgnoreCase("WidthList"))
{
widthList = parseWidthList
(tokenizer
);
}
else if (define.
equalsIgnoreCase("RectList"))
{
rectList = parseRectList
(tokenizer
);
}
else if (define.
equalsIgnoreCase("OffsetList"))
{
offsetList = parseOffsetList
(tokenizer
);
}
tokenizer.
readToken(";");
}
else if (identifier.
equalsIgnoreCase("CreateLayer"))
{
tokenizer.
readIdentifier();
tokenizer.
readToken(";");
}
else if (identifier.
equalsIgnoreCase("LayerSetImage"))
{
tokenizer.
readIdentifier();
// TODO: actually extract path from given file
String filename = FileUtil.
extractPath(file.
path()) +
"/" + tokenizer.
readString() +
".png";
texture =
new Texture
(Gdx.
files.
internal(filename
));
tokenizer.
readToken(";");
}
else if (identifier.
equalsIgnoreCase("LayerSetAscent"))
{
tokenizer.
readIdentifier();
float ascent = tokenizer.
readNumber();
font.
setAscent(ascent
);
tokenizer.
readToken(";");
}
else if (identifier.
equalsIgnoreCase("LayerSetCharWidths"))
{
tokenizer.
readIdentifier();
if (tokenizer.
checkIdentifier())
{
tokenizer.
readIdentifier();
tokenizer.
readIdentifier();
}
else if (tokenizer.
checkToken("("))
{
Vector<Character> charListExtra = parseCharList
(tokenizer
);
Vector<Float> widthListExtra = parseWidthList
(tokenizer
);
charList.
addAll(charListExtra
);
widthList.
addAll(widthListExtra
);
}
tokenizer.
readToken(";");
}
else if (identifier.
equalsIgnoreCase("LayerSetImageMap"))
{
tokenizer.
readIdentifier();
tokenizer.
readIdentifier();
tokenizer.
readIdentifier();
tokenizer.
readToken(";");
}
else if (identifier.
equalsIgnoreCase("LayerSetCharOffsets"))
{
tokenizer.
readIdentifier();
tokenizer.
readIdentifier();
tokenizer.
readIdentifier();
tokenizer.
readToken(";");
}
else if (identifier.
equalsIgnoreCase("LayerSetAscentPadding"))
{
tokenizer.
readIdentifier();
tokenizer.
readNumber();
tokenizer.
readToken(";");
}
else if (identifier.
equalsIgnoreCase("LayerSetLineSpacingOffset"))
{
tokenizer.
readIdentifier();
tokenizer.
readNumber();
tokenizer.
readToken(";");
}
else if (identifier.
equalsIgnoreCase("LayerSetPointSize"))
{
tokenizer.
readIdentifier();
tokenizer.
readNumber();
tokenizer.
readToken(";");
}
else if (identifier.
equalsIgnoreCase("SetDefaultPointSize"))
{
tokenizer.
readNumber();
tokenizer.
readToken(";");
}
}
}
catch (ScanException ex
)
{
ex.
log(LOG_TAG
);
}
// Build font
Font.
CharacterInfo[] characters =
new Font.
CharacterInfo[charList.
size()];
SpriteRegion
[] regions =
new SpriteRegion
[rectList.
size()];
for (int i =
0; i
< characters.
length; i++
)
{
characters
[i
] =
new Font.
CharacterInfo(charList.
elementAt(i
));
characters
[i
].
width = widthList.
elementAt(i
);
if (i
< offsetList.
size())
{
characters
[i
].
offsetX = offsetList.
elementAt(i
).
x;
characters
[i
].
offsetY = offsetList.
elementAt(i
).
y;
}
if (i
< rectList.
size())
{
CharacterRect rect = rectList.
elementAt(i
);
/*characters[i].texX = rectList.elementAt(i).x;
characters[i].texY = rectList.elementAt(i).y;
characters[i].texW = rectList.elementAt(i).w;
characters[i].texH = rectList.elementAt(i).h;*/
regions
[i
] =
new SpriteRegion
(texture, rect.
x, rect.
y, rect.
w, rect.
h);
}
}
AtlasSprite sprite =
new AtlasSprite
(graphics, texture, regions
);
for (int i =
0; i
< regions.
length; i++
)
{
characters
[i
].
setSpriteInstance(sprite.
createSpriteInstance(i
));
}
font.
setCharacters(characters
);
font.
setSprite(sprite
);
return font
;
}
private static Vector<Character> parseCharList
(Tokenizer t
) throws ScanException
{
Vector<Character> charList =
new Vector<Character>();
t.
readToken("(");
while (!t.
checkToken(")"))
{
String character = t.
readString();
if (character.
length() > 1)
throw new ScanException
("Character can only have length 1!", t.
getSurroundings());
charList.
add(character.
charAt(0));
if (t.
checkToken(")"))
break;
t.
readToken(",");
}
t.
readToken(")");
return charList
;
}
private static Vector<Float> parseWidthList
(Tokenizer t
) throws ScanException
{
Vector<Float> widthList =
new Vector<Float>();
t.
readToken("(");
while (!t.
checkToken(")"))
{
float width = t.
readNumber();
widthList.
add(width
);
if (t.
checkToken(")"))
break;
//Gdx.app.log(LOG_TAG, "[" + width + "]");
t.
readToken(",");
}
t.
readToken(")");
return widthList
;
}
private static Vector<CharacterRect
> parseRectList
(Tokenizer t
) throws ScanException
{
Vector<CharacterRect
> rectList =
new Vector<CharacterRect
>();
t.
readToken("(");
while (t.
checkToken("("))
{
t.
readToken("(");
float x = t.
readNumber();
t.
readToken(",");
float y = t.
readNumber();
t.
readToken(",");
float w = t.
readNumber();
t.
readToken(",");
float h = t.
readNumber();
rectList.
add(new CharacterRect
(x, y, w, h
));
t.
readToken(")");
if (!t.
checkToken(","))
break;
t.
readToken(",");
}
if (!t.
checkToken(")"))
throw new ScanException
("Syntax error in RectList!", t.
getSurroundings());
t.
readToken(")");
return rectList
;
}
private static Vector<CharacterOffset
> parseOffsetList
(Tokenizer t
) throws ScanException
{
Vector<CharacterOffset
> offsetList =
new Vector<CharacterOffset
>();
t.
readToken("(");
while (t.
checkToken("("))
{
t.
readToken("(");
float x = t.
readNumber();
t.
readToken(",");
float y = t.
readNumber();
offsetList.
add(new CharacterOffset
(x, y
));
t.
readToken(")");
if (!t.
checkToken(","))
break;
t.
readToken(",");
}
if (!t.
checkToken(")"))
throw new ScanException
("Syntax error in OffsetList!", t.
getSurroundings());
t.
readToken(")");
return offsetList
;
}
}