Subversion Repositories AndroidProjects

Rev

Rev 1456 | Blame | Compare with Previous | Last modification | View Log | RSS feed

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;
            }*/

    }
}