using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Drawing;
using BauzoidNET.file;
using BauzoidNET.graphics.sprite;
using EndianHandling;
namespace BauzoidNET
.graphics
{
public class FontUtil
{
public static readonly string LOG_TAG
= "FontUtil";
public static bool verbose
= true;
private 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 class CharacterOffset
{
public float x
;
public float y
;
public CharacterOffset
(float _x,
float _y
)
{
x
= _x
;
y
= _y
;
}
}
private class KerningPair
{
public char first
;
public char second
;
public int value
;
public KerningPair
(char a,
char b,
int n
)
{
first
= a
;
second
= b
;
value
= n
;
}
}
private FontUtil
() {}
public static void log
(String msg
)
{
log
(LOG_TAG, msg
);
}
public static void log
(String tag,
String msg
)
{
if (verbose
)
System.Console.WriteLine(tag
+ ": " + msg
);
}
public static Font createFontFromBinaryResource
(Graphics graphics,
byte[] file, Bitmap bmOverride
)
{
MemoryStream stream
= new MemoryStream
(file
);
Font font
= createFontFromBinaryStream
(graphics, stream,
null, bmOverride
);
stream
.Close();
return font
;
}
public static Font createFontFromBinaryFile
(Graphics graphics,
string filename, Stream input, Bitmap bmOverride
= null)
{
FileStream stream
= File
.Open(filename, FileMode
.Open);
Font font
= createFontFromBinaryStream
(graphics, stream, Path
.GetDirectoryName(filename
), bmOverride
);
stream
.Close();
return font
;
}
public static Font createFontFromBinaryStream
(Graphics graphics, Stream input,
string bmDirectory, Bitmap bmOverride
= null)
{
List
<char> charList
= new List
<char>();
List
<float> widthList
= new List
<float>();
List
<CharacterRect
> rectList
= new List
<CharacterRect
>();
List
<CharacterOffset
> offsetList
= new List
<CharacterOffset
>();
List
<KerningPair
> kerningPairs
= new List
<KerningPair
>();
//Font font = new Font(graphics);
//Texture texture = null;
String textureFileFull
= null;
float multiplier
= 1
.0f
;
float ascent
= 10
.0f
;
try
{
//File f = new File(file.read());
EndianBinaryReader reader
= new EndianBinaryReader
(input, Encoding
.Default,
true);
//int version = f.readInt();
int version
= 0;
reader
.ReadInt32(out version
);
if (version
!= 100)
{
//Gdx.app.log(LOG_TAG, "Version mismatch: 100 != " + version);
log
("Version mismatch: 100 != " + version
);
return null;
}
//String textureFile = f.readString();
string textureFile
= FileUtil
.readString(reader
);
//textureFileFull = FileUtil.extractPath(file.path()) + "/" + textureFile;
if (bmDirectory
!= null)
textureFileFull
= bmDirectory
+ "\\" + textureFile
;
else
textureFileFull
= textureFile
;
//ascent = f.readFloat();
//ascent = reader.ReadSingle();
reader
.ReadSingle(out ascent
);
//multiplier = f.readFloat();
//multiplier = reader.ReadSingle();
reader
.ReadSingle(out multiplier
);
// Read character list (char * num)
//int numChars = f.readInt(); // number of characters
int numChars
;
reader
.ReadInt32(out numChars
);
for (int i
= 0; i
< numChars
; i
++)
{
//Character c = f.readChar();
char c
;
reader
.ReadChar(out c
);
charList
.Add(c
);
}
// Read width list (float * num)
//int numWidths = f.readInt(); // number of widths
int numWidths
;
reader
.ReadInt32(out numWidths
);
for (int i
= 0; i
< numWidths
; i
++)
{
//Float width = f.readFloat();
float width
;
reader
.ReadSingle(out width
);
widthList
.Add(width
);
}
// Read rect list (CharRect * num)
//int numRects = f.readInt(); // number of rects
int numRects
;
reader
.ReadInt32(out numRects
);
for (int i
= 0; i
< numRects
; i
++)
{
float x
;
reader
.ReadSingle(out x
);
float y
;
reader
.ReadSingle(out y
);
float w
;
reader
.ReadSingle(out w
);
float h
;
reader
.ReadSingle(out h
);
rectList
.Add(new CharacterRect
(x, y, w, h
));
}
// Read offset list (CharOffset * num)
int numOffsets
;
reader
.ReadInt32(out numOffsets
); // number of offsets
for (int i
= 0; i
< numOffsets
; i
++)
{
float x
;
reader
.ReadSingle(out x
);
float y
;
reader
.ReadSingle(out y
);
offsetList
.Add(new CharacterOffset
(x, y
));
}
// number of kerning pairs
int numKerning
;
reader
.ReadInt32(out numKerning
);
// Read kerning pairs + values
for (int i
= 0; i
< numKerning
; i
++)
{
char a
;
reader
.ReadChar(out a
);
char b
;
reader
.ReadChar(out b
);
int v
;
reader
.ReadInt32(out v
);
kerningPairs
.Add(new KerningPair
(a, b, v
));
}
//f.close();
reader
.Close();
}
catch
{
//Gdx.app.log(LOG_TAG, "Could not read font!");
log
("Could not read font!");
}
Sprite sprite
= null;
if (bmOverride
== null)
{
sprite
= new Sprite
(graphics, textureFileFull
);
}
else
{
sprite
= new Sprite
(graphics, bmOverride
);
}
return buildFont
(graphics, sprite, charList, widthList, rectList, offsetList, multiplier, ascent, kerningPairs
);
}
private static Font buildFont
(Graphics graphics, Sprite sprite, List
<char> charList, List
<float> widthList, List
<CharacterRect
> rectList, List
<CharacterOffset
> offsetList,
float multiplier,
float ascent, List
<KerningPair
> kerningPairs
)
{
// Build font
if (sprite
== null)
{
log
("No sprite specified!");
return null;
}
Font font
= new Font
(graphics
);
Font
.CharacterInfo[] characters
= new Font
.CharacterInfo[charList
.Count];
SpriteRegion
[] regions
= new SpriteRegion
[rectList
.Count];
//Sprite sprite = new Sprite(graphics, textureFile);
sprite
.init();
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
.Count)
{
characters
[i
].offsetX = offsetList
.ElementAt(i
).x;
characters
[i
].offsetY = offsetList
.ElementAt(i
).y;
}
if (i
< rectList
.Count)
{
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
(sprite, i, rect
.x / multiplier, rect
.y / multiplier, rect
.w / multiplier, rect
.h / multiplier,
true);
}
}
sprite
.setRegions(regions
);
//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
);
font
.setAscent(ascent
);
font
.setGlobalMultiplier(multiplier
);
for (int i
= 0; i
< kerningPairs
.Count; i
++)
{
KerningPair pair
= kerningPairs
.ElementAt(i
);
font
.setKerning(pair
.first, pair
.second, pair
.value);
}
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;
}
private static Vector<KerningPair> parseKerningPairs(Tokenizer t) throws ScanException
{
Vector<KerningPair> kerningPairs = new Vector<KerningPair>();
t.readToken("(");
while (!t.checkToken(")"))
{
String pair = t.readString();
kerningPairs.add(new KerningPair(pair.charAt(0), pair.charAt(1), 0));
if (t.checkToken(")"))
break;
//Gdx.app.log(LOG_TAG, "[" + width + "]");
t.readToken(",");
}
t.readToken(")");
return kerningPairs;
}
private static Vector<Integer> parseKerningValues(Tokenizer t) throws ScanException
{
Vector<Integer> kerningValues = new Vector<Integer>();
t.readToken("(");
while (!t.checkToken(")"))
{
int value = (int)t.readNumber();
kerningValues.add(value);
if (t.checkToken(")"))
break;
//Gdx.app.log(LOG_TAG, "[" + width + "]");
t.readToken(",");
}
t.readToken(")");
return kerningValues;
}*/
}
}