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 BauzoidNET.math;
using BauzoidNET.graphics.sprite;
using BauzoidNET.graphics.texture;

namespace BauzoidNET.graphics
{
    public class Font : GraphicsObject
    {
        public static readonly Vector4 DEFAULT_COLOR = new Vector4(1, 1, 1, 1);
       
            public class KerningPair
            {
                    public char first;
                    public char second;
               
                    public KerningPair(char a, char b)
                    {
                            first = a;
                            second = b;
                    }
               
                    public override bool Equals(Object other)
                    {
                        // Not strictly necessary, but often a good optimization
                        if (this == other)
                          return true;
                   
                        if (!(other is KerningPair))
                          return false;
                   
                        KerningPair p = (KerningPair)other;
                   
                        return ((first == p.first) && (second == p.second));
                    }
               
                    public override int GetHashCode()
                    {
                            return (first * 256) + second;                     
                    }
            }
       
            public class CharacterInfo
            {
                    private char mCharacter;
                    public SpriteInstance mSpriteInstance = null;
               
                    public float offsetX = 0;
                    public float offsetY = 0;
               
                    public float width;
       
                    public CharacterInfo(char c)
                    {
                            mCharacter = c;
                    }
               
                    public char getCharacter()
                    {
                            return mCharacter;
                    }
               
                    public void setSpriteInstance(SpriteInstance instance)
                    {
                            mSpriteInstance = instance;
                    }
               
                    public SpriteInstance getSpriteInstance()
                    {
                            return mSpriteInstance;
                    }
               
                    public void render()
                    {
                            if (mSpriteInstance == null)
                                    return;
                       
                            mSpriteInstance.render();
                    }
            }
       
            private CharacterInfo[] mCharacters = null;
            private float mAscent = 0.0f;
            private float mGlobalMultiplier = 2.0f;
            private Sprite mSprite = null;
       
            //private Hashtable<KerningPair, Integer> mKernings = new Hashtable<KerningPair, Integer>();
        private Dictionary<KerningPair, int> mKernings = new Dictionary<KerningPair, int>();
       
            /** The y difference of a line break in multiples of line height. */
            private float mLineBreakFactor = 1.0f;

            public Font(Graphics graphics) :
            base(graphics)
            {
            }
       
            public void dispose()
            {
                    mCharacters = null;        
            }
       
            public void setAscent(float ascent)
            {
                    mAscent = ascent;
            }
       
            public void setCharacters(CharacterInfo[] characters)
            {
                    mCharacters = characters;
            }
       
            public void setSprite(Sprite sprite)
            {
                    mSprite = sprite;
            }
       
            public void setGlobalMultiplier(float multiplier)
            {
                    mGlobalMultiplier = multiplier;
            }
       
            public void drawText(string text, float x, float y, float scale)
            {
                    drawText(text, x, y, DEFAULT_COLOR, scale);
            }
       
            public void drawText(string text, float x, float y)
            {
                    drawText(text, x, y, DEFAULT_COLOR);
            }
       
            public void drawText(string text, float x, float y, Vector4 color)
            {
                    drawText(text, x, y, color, 1.0f);
            }
       
            public void drawTextDirect(string text, float x, float y, Vector4 color, float scale)
            {
                    float posX = x;
                    float posY = y;
               
                    for (int i = 0; i < text.Length; i++)
                    {
                            if (text[i] == '\n')
                            {
                                    posY += mAscent * mLineBreakFactor * scale;
                                    posX = x;
                                    continue;
                            }
                       
                            int n = getCharacterIndexNoCase(text[i]);
                            if (n == -1)
                            {
                                    continue;
                            }
                       
                            CharacterInfo c = mCharacters[n];
                       
                            int kerning = 0;
                            if (i < (text.Length-1))
                            {
                                    // apply kerning if any
                                    char first = c.getCharacter();
                                    char second = text[i+1];
                               
                                    kerning = getKerning(first, second);
                            }
                            if (c.mSpriteInstance != null)
                            {                  
                                    c.mSpriteInstance.transform.x = posX;
                                    c.mSpriteInstance.transform.y = posY;
                                    c.mSpriteInstance.color = color;
                                    c.mSpriteInstance.transform.w = c.mSpriteInstance.getSpriteRegion().getWidth() * scale * mGlobalMultiplier * c.mSpriteInstance.getSprite().getTextureWidth();
                    c.mSpriteInstance.transform.h = c.mSpriteInstance.getSpriteRegion().getHeight() * scale * mGlobalMultiplier * c.mSpriteInstance.getSprite().getTextureHeight();
                                    //c.mSpriteInstance.param.w = mSprite.getRegionWidth(c.mSpriteInstance.getRegionIndex()) * scale * mGlobalMultiplier;
                                    //c.mSpriteInstance.param.h = mSprite.getRegionHeight(c.mSpriteInstance.getRegionIndex()) * scale * mGlobalMultiplier;
                                    c.mSpriteInstance.transform.pivotX = 0;
                                    c.mSpriteInstance.transform.pivotY = 0;
                                    c.mSpriteInstance.render();
                            }
                       
                            posX += c.width * scale + kerning - c.offsetX;
                    }
            }

            public void drawText(string text, float x, float y, Vector4 color, float scale)
            {
                    float posX = x;
                    float posY = y;
               
                    TileBatch batch = getGraphics().getBatch();
               
                    batch.begin();
               
                    for (int i = 0; i < text.Length; i++)
                    {
                            if (text[i] == '\n')
                            {
                                    posY += mAscent * mLineBreakFactor * scale;
                                    posX = x;
                                    continue;
                            }
                       
                            int n = getCharacterIndexNoCase(text[i]);
                            if (n == -1)
                            {
                                    continue;
                            }
                       
                            CharacterInfo c = mCharacters[n];
                       
                            int kerning = 0;
                            if (i < (text.Length-1))
                            {
                                    // apply kerning if any
                                    char first = c.getCharacter();
                                    char second = text[i+1];
                               
                                    kerning = getKerning(first, second);
                            }
                            if (c.mSpriteInstance != null)
                            {                  
                                    c.mSpriteInstance.transform.x = posX;
                                    c.mSpriteInstance.transform.y = posY;
                                    c.mSpriteInstance.color = color;
                    c.mSpriteInstance.transform.w = c.mSpriteInstance.getSpriteRegion().getWidth() * scale * mGlobalMultiplier * c.mSpriteInstance.getSprite().getTextureWidth();
                    c.mSpriteInstance.transform.h = c.mSpriteInstance.getSpriteRegion().getHeight() * scale * mGlobalMultiplier * c.mSpriteInstance.getSprite().getTextureHeight();
                                    //c.mSpriteInstance.param.w = mSprite.getRegionWidth(c.mSpriteInstance.getRegionIndex()) * scale * mGlobalMultiplier;
                                    //c.mSpriteInstance.param.h = mSprite.getRegionHeight(c.mSpriteInstance.getRegionIndex()) * scale * mGlobalMultiplier;
                                    c.mSpriteInstance.transform.pivotX = 0;
                                    c.mSpriteInstance.transform.pivotY = 0;
                       
                                    batch.drawSprite(c.mSpriteInstance);
                            }
                       
                            posX += c.width * scale + kerning - c.offsetX;
                    }
               
                    batch.end();
            }
       
            public float getTextWidth(string text, float scale)
            {
                    float maxWidth = 0;
                    float width = 0;
                    float posX = 0;
               
                    for (int i = 0; i < text.Length; i++)
                    {
                            if (text[i] == '\n')
                            {
                                    posX = 0;
                                    continue;
                            }
                       
                            int n = getCharacterIndexNoCase(text[i]);
                            if (n == -1)
                            {
                                    continue;
                            }
                       
                            CharacterInfo c = mCharacters[n];
                            int kerning = 0;
                            if (i < (text.Length-1))
                            {
                                    // apply kerning if any
                                    char first = c.getCharacter();
                                    char second = text[i+1];
                               
                                    kerning = getKerning(first, second);
                            }
                       
                            width = posX + c.width * scale;
                       
                            if (maxWidth < width)
                            {
                                    maxWidth = width;
                            }
                       
                            posX += c.width * scale + kerning - c.offsetX;
                    }
               
                    return maxWidth;
            }
       
            public float getTextHeight(string text, float scale)
            {
                    float maxHeight = 0;
                    float posY = 0;
               
               
               
                    for (int i = 0; i < text.Length; i++)
                    {
                            if (text[i] == '\n')
                            {
                                    posY += mAscent * mLineBreakFactor * scale;
                                    continue;
                            }
                       
                            int n = getCharacterIndexNoCase(text[i]);
                            if (n == -1)
                            {
                                    continue;
                            }
                       
                            float charHeight = this.mAscent * scale;

                            if ((posY + charHeight) > maxHeight)
                            {
                                    maxHeight = posY + charHeight;
                            }
                    }
               
                    return maxHeight;
            }
       
            public int getCharacterIndex(char c)
            {
                    for (int i = 0; i < mCharacters.Length; i++)
                    {
                            if (mCharacters[i].getCharacter() == c)
                                    return i;
                    }
               
                    return -1;
            }
       
            public int getCharacterIndexNoCase(char c)
            {
                    int n = getCharacterIndex(c);
                    if (n == -1)
                    {
                            n = getCharacterIndex(char.ToLower(c));
                            if (n == -1)
                            {
                                    n = getCharacterIndex(char.ToUpper(c));
                            }
                    }
                    return n;
            }
       
            public CharacterInfo getCharacter(char c)
            {
                    int i = getCharacterIndex(c);
               
                    if (i != -1)
                            return mCharacters[i];
               
                    return null;
            }
       
            public void setKerning(char first, char second, int value)
            {
                    //mKernings.put(new KerningPair(first, second), value);
            mKernings.Add(new KerningPair(first, second), value);
            }
       
            public int getKerning(char first, char second)
            {
                    //int value = mKernings[new KerningPair(first, second)];
            KerningPair key = new KerningPair(first, second);
            if (!mKernings.ContainsKey(key))
                return 0;
               
                    return mKernings[key];
            }
       
            public void setFiltering(bool filter)
            {
                    /*
                    // HACK: should use own texture class
                    if (filter)
                            getGraphics().renderStates.getTextureStage(0).setTextureFilter(mSprite.getTexture(), TextureFilter.Linear, TextureFilter.Linear);
                    else
                            getGraphics().renderStates.getTextureStage(0).setTextureFilter(mSprite.getTexture(), TextureFilter.Nearest, TextureFilter.Nearest);*/

               
                    if (filter)
                mSprite.getTexture().setFilter(Texture.Filter.LINEAR, Texture.Filter.LINEAR);
                    else
                mSprite.getTexture().setFilter(Texture.Filter.NEAREST, Texture.Filter.NEAREST);
            }
       
            public void setLineBreak(float multiple) { mLineBreakFactor = multiple; }
            public float getLineBreak() { return mLineBreakFactor; }
       
    }
}