/*
* $RCSfile$
* Copyright (C) 2006 Rob Loach (http://www.robloach.net)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Components;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;
using System.IO;
namespace BrickBust
{
///
/// Represents a font which uses an image to display text, generated
/// from LMNOpc Bitmap Font Builder (http://www.lmnopc.com/bitmapfontbuilder).
///
///
/// To use this bitmap font component, just drag an instance of it onto your
/// designer view and then interface with it through code in the Draw method.
///
public class BitmapFont : Microsoft.Xna.Framework.GameComponent
{
#region Fields
// Private Fields
private SpriteBatch m_Sprites;
private byte[] m_Widths;
private Texture2D m_Texture;
private IGraphicsDeviceService m_GraphicsDeviceService;
// Property Associated
private SpriteBlendMode m_BlendMode = SpriteBlendMode.AlphaBlend;
private Color m_Color = Color.White;
private string m_DataFilename = string.Empty;
private string m_ImageFilename = string.Empty;
#endregion Fields
#region Private Functions
///
/// Loads the resources into memory.
///
private void LoadResources()
{
m_Texture = Texture2D.FromFile(m_GraphicsDeviceService.GraphicsDevice, m_ImageFilename);
m_Sprites = new SpriteBatch(m_GraphicsDeviceService.GraphicsDevice);
using(FileStream stream = new FileStream(m_DataFilename, FileMode.Open))
{
m_Widths = new byte[stream.Length];
stream.Read(m_Widths, 0, (int)stream.Length);
stream.Close();
}
}
///
/// Releases the context of the sprite batch, texture and widths.
///
private void ReleaseContent()
{
if (m_Texture != null)
{
m_Texture.Dispose();
m_Texture = null;
}
if (m_Sprites != null)
{
m_Sprites.Dispose();
m_Sprites = null;
}
m_Widths = null;
}
///
/// Prepares the bitmap font for rendering.
///
public override void Start()
{
// TODO: Add your start up code here
m_GraphicsDeviceService = this.Game.GameServices.GetService();
m_GraphicsDeviceService.DeviceReset += new EventHandler(GraphicsDeviceService_DeviceReset);
m_GraphicsDeviceService.DeviceResetting += new EventHandler(GraphicsDeviceService_DeviceResetting);
m_GraphicsDeviceService.DeviceCreated += new EventHandler(GraphicsDeviceService_DeviceCreated);
m_GraphicsDeviceService.DeviceDisposing += new EventHandler(GraphicsDeviceService_DeviceDisposing);
LoadResources();
}
private void GraphicsDeviceService_DeviceDisposing(object sender, EventArgs e)
{
ReleaseContent();
}
private void GraphicsDeviceService_DeviceResetting(object sender, EventArgs e)
{
ReleaseContent();
}
private void GraphicsDeviceService_DeviceCreated(object sender, EventArgs e)
{
LoadResources();
}
private void GraphicsDeviceService_DeviceReset(object sender, EventArgs e)
{
LoadResources();
}
#endregion Private Functions
#region Properties
///
/// Gets and sets the BlendMode for drawing. Defaults for alpha blending.
///
public SpriteBlendMode BlendMode
{
get { return m_BlendMode; }
set { m_BlendMode = value; }
}
///
/// Gets and sets the default color the font should draw in.
///
public Color Color
{
get { return m_Color; }
set { m_Color = value; }
}
///
/// Gets the height of each line.
///
public float LineHeight
{
get
{
if (m_Texture != null)
return m_Texture.Height / 16;
else
return 0;
}
}
///
/// The image file that was generated from LMNOpc Bitmap Font Builder.
///
public string ImageFilename
{
get { return m_ImageFilename; }
set
{
m_ImageFilename = value;
}
}
///
/// The data file generated from LMNOpc Bitmap Font Builder.
///
public string DataFilename
{
get { return m_DataFilename; }
set
{
m_DataFilename = value;
}
}
#endregion Properties
#region Functions
#region TextWidth
///
/// Gets the width of the given text.
///
/// The text to check the width of.
/// The width of the given text.
public float TextWidth(string text)
{
float width = 0f;
CharEnumerator chars = text.GetEnumerator();
while (chars.MoveNext())
width += m_Widths[(int)chars.Current * 2];
return width;
}
#endregion TextWidth
#region Draw
public void Draw(float x, float y, string text, Alignment alignment)
{
if (text == null)
return;
if (text.Length == 0)
return;
switch (alignment)
{
case Alignment.Center:
x -= TextWidth(text) / 2f;
break;
case Alignment.Right:
x -= TextWidth(text);
break;
}
if (m_Sprites != null)
{
m_Sprites.Begin(m_BlendMode);
{
float xLocation = x;
CharEnumerator chars = text.GetEnumerator();
while (chars.MoveNext())
{
byte ascii = (byte)chars.Current;
int charX = (ascii % 16) * m_Texture.Width / 16;
int charY = (ascii / 16) * m_Texture.Height / 16;
m_Sprites.Draw(m_Texture, new Vector2(xLocation, y), new Rectangle(charX, charY, (int)m_Widths[ascii * 2], m_Texture.Width / 16), m_Color);
xLocation += (float)m_Widths[ascii * 2];
}
}
m_Sprites.End();
}
}
public void Draw(float x, float y, string text)
{
Draw(x, y, text, Alignment.Left);
}
public void Draw(Vector2 location, string text)
{
Draw(location.X, location.Y, text, Alignment.Left);
}
public void Draw(Vector2 location, string text, Alignment alignment)
{
Draw(location.X, location.Y, text, alignment);
}
public void Draw(string text)
{
Draw(0f, 0f, text, Alignment.Left);
}
#endregion Draw
#endregion Functions
#region Enumerations
public enum Alignment
{
Left, Center, Right
}
#endregion Enumerations
}
}